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);
|
conn.qLogger->addPacket(packet, encodedSize);
|
||||||
}
|
}
|
||||||
for (const auto& frame : packet.frames) {
|
for (const auto& frame : packet.frames) {
|
||||||
folly::variant_match(
|
switch (frame.type()) {
|
||||||
frame,
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
[&](const WriteStreamFrame& writeStreamFrame) {
|
const WriteStreamFrame& writeStreamFrame = *frame.asWriteStreamFrame();
|
||||||
retransmittable = true;
|
retransmittable = true;
|
||||||
auto stream = CHECK_NOTNULL(
|
auto stream = CHECK_NOTNULL(
|
||||||
conn.streamManager->getStream(writeStreamFrame.streamId));
|
conn.streamManager->getStream(writeStreamFrame.streamId));
|
||||||
@@ -223,8 +223,10 @@ void updateConnection(
|
|||||||
conn.streamManager->updateWritableStreams(*stream);
|
conn.streamManager->updateWritableStreams(*stream);
|
||||||
}
|
}
|
||||||
conn.streamManager->updateLossStreams(*stream);
|
conn.streamManager->updateLossStreams(*stream);
|
||||||
},
|
break;
|
||||||
[&](const WriteCryptoFrame& writeCryptoFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
|
const WriteCryptoFrame& writeCryptoFrame = *frame.asWriteCryptoFrame();
|
||||||
retransmittable = true;
|
retransmittable = true;
|
||||||
auto protectionType = packet.header.getProtectionType();
|
auto protectionType = packet.header.getProtectionType();
|
||||||
// NewSessionTicket is sent in crypto frame encrypted with 1-rtt key,
|
// NewSessionTicket is sent in crypto frame encrypted with 1-rtt key,
|
||||||
@@ -232,8 +234,7 @@ void updateConnection(
|
|||||||
isHandshake =
|
isHandshake =
|
||||||
(protectionType == ProtectionType::Initial ||
|
(protectionType == ProtectionType::Initial ||
|
||||||
protectionType == ProtectionType::Handshake);
|
protectionType == ProtectionType::Handshake);
|
||||||
auto encryptionLevel =
|
auto encryptionLevel = protectionTypeToEncryptionLevel(protectionType);
|
||||||
protectionTypeToEncryptionLevel(protectionType);
|
|
||||||
handleStreamWritten(
|
handleStreamWritten(
|
||||||
conn,
|
conn,
|
||||||
*getCryptoStream(*conn.cryptoState, encryptionLevel),
|
*getCryptoStream(*conn.cryptoState, encryptionLevel),
|
||||||
@@ -242,8 +243,10 @@ void updateConnection(
|
|||||||
false,
|
false,
|
||||||
packetNum,
|
packetNum,
|
||||||
packetNumberSpace);
|
packetNumberSpace);
|
||||||
},
|
break;
|
||||||
[&](const WriteAckFrame& writeAckFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteAckFrame_E: {
|
||||||
|
const WriteAckFrame& writeAckFrame = *frame.asWriteAckFrame();
|
||||||
DCHECK(!ackFrameCounter++)
|
DCHECK(!ackFrameCounter++)
|
||||||
<< "Send more than one WriteAckFrame " << conn;
|
<< "Send more than one WriteAckFrame " << conn;
|
||||||
auto largestAckedPacketWritten = writeAckFrame.ackBlocks.back().end;
|
auto largestAckedPacketWritten = writeAckFrame.ackBlocks.back().end;
|
||||||
@@ -255,8 +258,10 @@ void updateConnection(
|
|||||||
conn,
|
conn,
|
||||||
getAckState(conn, packetNumberSpace),
|
getAckState(conn, packetNumberSpace),
|
||||||
largestAckedPacketWritten);
|
largestAckedPacketWritten);
|
||||||
},
|
break;
|
||||||
[&](const RstStreamFrame& rstStreamFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::RstStreamFrame_E: {
|
||||||
|
const RstStreamFrame& rstStreamFrame = *frame.asRstStreamFrame();
|
||||||
retransmittable = true;
|
retransmittable = true;
|
||||||
VLOG(10) << nodeToString(conn.nodeType)
|
VLOG(10) << nodeToString(conn.nodeType)
|
||||||
<< " sent reset streams in packetNum=" << packetNum << " "
|
<< " sent reset streams in packetNum=" << packetNum << " "
|
||||||
@@ -271,8 +276,10 @@ void updateConnection(
|
|||||||
DCHECK(packetEvent.hasValue())
|
DCHECK(packetEvent.hasValue())
|
||||||
<< " reset missing from pendingEvents for non-clone packet";
|
<< " reset missing from pendingEvents for non-clone packet";
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
[&](const MaxDataFrame& maxDataFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxDataFrame_E: {
|
||||||
|
const MaxDataFrame& maxDataFrame = *frame.asMaxDataFrame();
|
||||||
CHECK(!connWindowUpdateSent++)
|
CHECK(!connWindowUpdateSent++)
|
||||||
<< "Send more than one connection window update " << conn;
|
<< "Send more than one connection window update " << conn;
|
||||||
VLOG(10) << nodeToString(conn.nodeType)
|
VLOG(10) << nodeToString(conn.nodeType)
|
||||||
@@ -280,12 +287,15 @@ void updateConnection(
|
|||||||
<< conn;
|
<< conn;
|
||||||
retransmittable = true;
|
retransmittable = true;
|
||||||
VLOG(10) << nodeToString(conn.nodeType)
|
VLOG(10) << nodeToString(conn.nodeType)
|
||||||
<< " sent conn window update in packetNum=" << packetNum
|
<< " sent conn window update in packetNum=" << packetNum << " "
|
||||||
<< " " << conn;
|
<< conn;
|
||||||
onConnWindowUpdateSent(
|
onConnWindowUpdateSent(
|
||||||
conn, packetNum, maxDataFrame.maximumData, sentTime);
|
conn, packetNum, maxDataFrame.maximumData, sentTime);
|
||||||
},
|
break;
|
||||||
[&](const MaxStreamDataFrame& maxStreamDataFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
|
const MaxStreamDataFrame& maxStreamDataFrame =
|
||||||
|
*frame.asMaxStreamDataFrame();
|
||||||
auto stream = CHECK_NOTNULL(
|
auto stream = CHECK_NOTNULL(
|
||||||
conn.streamManager->getStream(maxStreamDataFrame.streamId));
|
conn.streamManager->getStream(maxStreamDataFrame.streamId));
|
||||||
retransmittable = true;
|
retransmittable = true;
|
||||||
@@ -294,15 +304,28 @@ void updateConnection(
|
|||||||
<< " stream=" << maxStreamDataFrame.streamId << " " << conn;
|
<< " stream=" << maxStreamDataFrame.streamId << " " << conn;
|
||||||
onStreamWindowUpdateSent(
|
onStreamWindowUpdateSent(
|
||||||
*stream, packetNum, maxStreamDataFrame.maximumData, sentTime);
|
*stream, packetNum, maxStreamDataFrame.maximumData, sentTime);
|
||||||
},
|
break;
|
||||||
[&](const StreamDataBlockedFrame& streamBlockedFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
|
||||||
|
const StreamDataBlockedFrame& streamBlockedFrame =
|
||||||
|
*frame.asStreamDataBlockedFrame();
|
||||||
VLOG(10) << nodeToString(conn.nodeType)
|
VLOG(10) << nodeToString(conn.nodeType)
|
||||||
<< " sent blocked stream frame packetNum=" << packetNum
|
<< " sent blocked stream frame packetNum=" << packetNum << " "
|
||||||
<< " " << conn;
|
<< conn;
|
||||||
retransmittable = true;
|
retransmittable = true;
|
||||||
conn.streamManager->removeBlocked(streamBlockedFrame.streamId);
|
conn.streamManager->removeBlocked(streamBlockedFrame.streamId);
|
||||||
},
|
break;
|
||||||
[&](const PaddingFrame&) {
|
}
|
||||||
|
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
|
// do not mark padding as retransmittable. There are several reasons
|
||||||
// for this:
|
// for this:
|
||||||
// 1. We might need to pad ACK packets to make it so that we can
|
// 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
|
// count towards congestion window, so the padding frames in those
|
||||||
// ack packets should not count towards the window either
|
// ack packets should not count towards the window either
|
||||||
// 2. Of course we do not want to retransmit the ACK frames.
|
// 2. Of course we do not want to retransmit the ACK frames.
|
||||||
},
|
break;
|
||||||
[&](const QuicSimpleFrame& simpleFrame) {
|
}
|
||||||
retransmittable = true;
|
default:
|
||||||
// We don't want this triggered for cloned frames.
|
retransmittable = true;
|
||||||
if (!packetEvent.hasValue()) {
|
|
||||||
updateSimpleFrameOnPacketSent(conn, simpleFrame);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
[&](const auto&) { retransmittable = true; });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Now pureAck is equivalent to non retransmittable packet. This might
|
// 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
|
// Write those framses with a regular builder
|
||||||
writeFrame(connCloseFrame, regularBuilder);
|
writeFrame(connCloseFrame, regularBuilder);
|
||||||
writeFrame(maxStreamFrame, regularBuilder);
|
writeFrame(QuicSimpleFrame(maxStreamFrame), regularBuilder);
|
||||||
writeFrame(pingFrame, regularBuilder);
|
writeFrame(pingFrame, regularBuilder);
|
||||||
writeAckFrame(ackMeta, regularBuilder);
|
writeAckFrame(ackMeta, regularBuilder);
|
||||||
|
|
||||||
@@ -386,15 +386,15 @@ TEST_F(QuicPacketSchedulerTest, WriteOnlyOutstandingPacketsTest) {
|
|||||||
// Test that the only frame that's written is maxdataframe
|
// Test that the only frame that's written is maxdataframe
|
||||||
EXPECT_GE(writtenPacket.packet.frames.size(), 1);
|
EXPECT_GE(writtenPacket.packet.frames.size(), 1);
|
||||||
auto& writtenFrame = writtenPacket.packet.frames.at(0);
|
auto& writtenFrame = writtenPacket.packet.frames.at(0);
|
||||||
auto maxDataFrame = boost::get<MaxDataFrame>(&writtenFrame);
|
auto maxDataFrame = writtenFrame.asMaxDataFrame();
|
||||||
CHECK(maxDataFrame);
|
CHECK(maxDataFrame);
|
||||||
for (auto& frame : writtenPacket.packet.frames) {
|
for (auto& frame : writtenPacket.packet.frames) {
|
||||||
bool present = false;
|
bool present = false;
|
||||||
/* the next four frames should not be written */
|
/* the next four frames should not be written */
|
||||||
present |= boost::get<ConnectionCloseFrame>(&frame) ? true : false;
|
present |= frame.asConnectionCloseFrame() ? true : false;
|
||||||
present |= boost::get<QuicSimpleFrame>(&frame) ? true : false;
|
present |= frame.asQuicSimpleFrame() ? true : false;
|
||||||
present |= boost::get<PingFrame>(&frame) ? true : false;
|
present |= frame.asPingFrame() ? true : false;
|
||||||
present |= boost::get<WriteAckFrame>(&frame) ? true : false;
|
present |= frame.asWriteAckFrame() ? true : false;
|
||||||
ASSERT_FALSE(present);
|
ASSERT_FALSE(present);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -535,12 +535,10 @@ TEST_F(QuicPacketSchedulerTest, CloneSchedulerUseNormalSchedulerFirst) {
|
|||||||
conn.ackStates.appDataAckState.nextPacketNum,
|
conn.ackStates.appDataAckState.nextPacketNum,
|
||||||
shortHeader.getPacketSequenceNum());
|
shortHeader.getPacketSequenceNum());
|
||||||
EXPECT_EQ(1, result.second->packet.frames.size());
|
EXPECT_EQ(1, result.second->packet.frames.size());
|
||||||
folly::variant_match(
|
MaxDataFrame* maxDataFrame =
|
||||||
result.second->packet.frames.front(),
|
result.second->packet.frames.front().asMaxDataFrame();
|
||||||
[&](const MaxDataFrame& frame) { EXPECT_EQ(2832, frame.maximumData); },
|
ASSERT_NE(maxDataFrame, nullptr);
|
||||||
[&](const auto&) {
|
EXPECT_EQ(2832, maxDataFrame->maximumData);
|
||||||
ASSERT_FALSE(true); // should not happen
|
|
||||||
});
|
|
||||||
EXPECT_TRUE(folly::IOBufEqualTo{}(
|
EXPECT_TRUE(folly::IOBufEqualTo{}(
|
||||||
*folly::IOBuf::copyBuffer("if you are the dealer"),
|
*folly::IOBuf::copyBuffer("if you are the dealer"),
|
||||||
*result.second->header));
|
*result.second->header));
|
||||||
@@ -580,18 +578,25 @@ TEST_F(QuicPacketSchedulerTest, CloneWillGenerateNewWindowUpdate) {
|
|||||||
EXPECT_EQ(expectedPacketEvent, *packetResult.first);
|
EXPECT_EQ(expectedPacketEvent, *packetResult.first);
|
||||||
int32_t verifyConnWindowUpdate = 1, verifyStreamWindowUpdate = 1;
|
int32_t verifyConnWindowUpdate = 1, verifyStreamWindowUpdate = 1;
|
||||||
for (const auto& frame : packetResult.second->packet.frames) {
|
for (const auto& frame : packetResult.second->packet.frames) {
|
||||||
folly::variant_match(
|
switch (frame.type()) {
|
||||||
frame,
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
[&](const MaxStreamDataFrame& maxStreamDataFrame) {
|
const MaxStreamDataFrame& maxStreamDataFrame =
|
||||||
|
*frame.asMaxStreamDataFrame();
|
||||||
EXPECT_EQ(stream->id, maxStreamDataFrame.streamId);
|
EXPECT_EQ(stream->id, maxStreamDataFrame.streamId);
|
||||||
verifyStreamWindowUpdate--;
|
verifyStreamWindowUpdate--;
|
||||||
},
|
break;
|
||||||
[&](const MaxDataFrame&) { verifyConnWindowUpdate--; },
|
}
|
||||||
[&](const PaddingFrame&) {},
|
case QuicWriteFrame::Type::MaxDataFrame_E: {
|
||||||
[&](const auto&) {
|
verifyConnWindowUpdate--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QuicWriteFrame::Type::PaddingFrame_E: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
// should never happen
|
// should never happen
|
||||||
EXPECT_TRUE(false);
|
EXPECT_TRUE(false);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(0, verifyStreamWindowUpdate);
|
EXPECT_EQ(0, verifyStreamWindowUpdate);
|
||||||
EXPECT_EQ(0, verifyConnWindowUpdate);
|
EXPECT_EQ(0, verifyConnWindowUpdate);
|
||||||
@@ -600,15 +605,21 @@ TEST_F(QuicPacketSchedulerTest, CloneWillGenerateNewWindowUpdate) {
|
|||||||
EXPECT_GE(packetResult.second->packet.frames.size(), 2);
|
EXPECT_GE(packetResult.second->packet.frames.size(), 2);
|
||||||
uint32_t streamWindowUpdateCounter = 0;
|
uint32_t streamWindowUpdateCounter = 0;
|
||||||
uint32_t connWindowUpdateCounter = 0;
|
uint32_t connWindowUpdateCounter = 0;
|
||||||
for (auto& streamFlowControl :
|
for (auto& frame : packetResult.second->packet.frames) {
|
||||||
all_frames<MaxStreamDataFrame>(packetResult.second->packet.frames)) {
|
auto streamFlowControl = frame.asMaxStreamDataFrame();
|
||||||
streamWindowUpdateCounter++;
|
if (!streamFlowControl) {
|
||||||
EXPECT_EQ(1700, streamFlowControl.maximumData);
|
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++;
|
connWindowUpdateCounter++;
|
||||||
EXPECT_EQ(3300, connFlowControl.maximumData);
|
EXPECT_EQ(3300, connFlowControl->maximumData);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(1, connWindowUpdateCounter);
|
EXPECT_EQ(1, connWindowUpdateCounter);
|
||||||
EXPECT_EQ(1, streamWindowUpdateCounter);
|
EXPECT_EQ(1, streamWindowUpdateCounter);
|
||||||
|
@@ -1223,14 +1223,13 @@ TEST_F(QuicTransportFunctionsTest, NothingWritten) {
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class FrameType>
|
const QuicWriteFrame& getFirstFrameInOutstandingPackets(
|
||||||
const FrameType& getFirstFrameInOutstandingPackets(
|
const std::deque<OutstandingPacket>& outstandingPackets,
|
||||||
const std::deque<OutstandingPacket>& outstandingPackets) {
|
QuicWriteFrame::Type frameType) {
|
||||||
for (const auto& packet : outstandingPackets) {
|
for (const auto& packet : outstandingPackets) {
|
||||||
for (const auto& frame : packet.packet.frames) {
|
for (const auto& frame : packet.packet.frames) {
|
||||||
auto decodedFrame = boost::get<FrameType>(&frame);
|
if (frame.type() == frameType) {
|
||||||
if (decodedFrame) {
|
return frame;
|
||||||
return *decodedFrame;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1272,8 +1271,10 @@ TEST_F(QuicTransportFunctionsTest, WriteBlockedFrameWhenBlocked) {
|
|||||||
EXPECT_LT(sentBytes, 200);
|
EXPECT_LT(sentBytes, 200);
|
||||||
|
|
||||||
EXPECT_GT(conn->ackStates.appDataAckState.nextPacketNum, originalNextSeq);
|
EXPECT_GT(conn->ackStates.appDataAckState.nextPacketNum, originalNextSeq);
|
||||||
auto blocked = getFirstFrameInOutstandingPackets<StreamDataBlockedFrame>(
|
auto blocked = *getFirstFrameInOutstandingPackets(
|
||||||
conn->outstandingPackets);
|
conn->outstandingPackets,
|
||||||
|
QuicWriteFrame::Type::StreamDataBlockedFrame_E)
|
||||||
|
.asStreamDataBlockedFrame();
|
||||||
EXPECT_EQ(blocked.streamId, stream1->id);
|
EXPECT_EQ(blocked.streamId, stream1->id);
|
||||||
|
|
||||||
// Since everything is blocked, we shouldn't write a blocked again, so we
|
// Since everything is blocked, we shouldn't write a blocked again, so we
|
||||||
@@ -1758,7 +1759,7 @@ TEST_F(QuicTransportFunctionsTest, UpdateConnectionCloneCounter) {
|
|||||||
auto connWindowUpdate =
|
auto connWindowUpdate =
|
||||||
MaxDataFrame(conn->flowControlState.advertisedMaxOffset);
|
MaxDataFrame(conn->flowControlState.advertisedMaxOffset);
|
||||||
conn->pendingEvents.connWindowUpdate = true;
|
conn->pendingEvents.connWindowUpdate = true;
|
||||||
packet.packet.frames.push_back(connWindowUpdate);
|
packet.packet.frames.emplace_back(connWindowUpdate);
|
||||||
PacketEvent packetEvent = 100;
|
PacketEvent packetEvent = 100;
|
||||||
conn->outstandingPacketEvents.insert(packetEvent);
|
conn->outstandingPacketEvents.insert(packetEvent);
|
||||||
updateConnection(*conn, packetEvent, packet.packet, TimePoint(), 123);
|
updateConnection(*conn, packetEvent, packet.packet, TimePoint(), 123);
|
||||||
@@ -1788,7 +1789,7 @@ TEST_F(QuicTransportFunctionsTest, ClonedBlocked) {
|
|||||||
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
|
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
|
||||||
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
auto stream = conn->streamManager->createNextBidirectionalStream().value();
|
||||||
StreamDataBlockedFrame blockedFrame(stream->id, 1000);
|
StreamDataBlockedFrame blockedFrame(stream->id, 1000);
|
||||||
packet.packet.frames.push_back(blockedFrame);
|
packet.packet.frames.emplace_back(blockedFrame);
|
||||||
conn->outstandingPacketEvents.insert(packetEvent);
|
conn->outstandingPacketEvents.insert(packetEvent);
|
||||||
// This shall not crash
|
// This shall not crash
|
||||||
updateConnection(
|
updateConnection(
|
||||||
@@ -1805,8 +1806,8 @@ TEST_F(QuicTransportFunctionsTest, TwoConnWindowUpdateWillCrash) {
|
|||||||
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
|
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
|
||||||
MaxDataFrame connWindowUpdate(
|
MaxDataFrame connWindowUpdate(
|
||||||
1000 + conn->flowControlState.advertisedMaxOffset);
|
1000 + conn->flowControlState.advertisedMaxOffset);
|
||||||
packet.packet.frames.push_back(connWindowUpdate);
|
packet.packet.frames.emplace_back(connWindowUpdate);
|
||||||
packet.packet.frames.push_back(connWindowUpdate);
|
packet.packet.frames.emplace_back(connWindowUpdate);
|
||||||
conn->pendingEvents.connWindowUpdate = true;
|
conn->pendingEvents.connWindowUpdate = true;
|
||||||
EXPECT_DEATH(
|
EXPECT_DEATH(
|
||||||
updateConnection(
|
updateConnection(
|
||||||
@@ -1859,7 +1860,7 @@ TEST_F(QuicTransportFunctionsTest, ClonedRst) {
|
|||||||
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
|
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
|
||||||
RstStreamFrame rstStreamFrame(
|
RstStreamFrame rstStreamFrame(
|
||||||
stream->id, GenericApplicationErrorCode::UNKNOWN, 0);
|
stream->id, GenericApplicationErrorCode::UNKNOWN, 0);
|
||||||
packet.packet.frames.push_back(rstStreamFrame);
|
packet.packet.frames.emplace_back(std::move(rstStreamFrame));
|
||||||
conn->outstandingPacketEvents.insert(packetEvent);
|
conn->outstandingPacketEvents.insert(packetEvent);
|
||||||
// This shall not crash
|
// This shall not crash
|
||||||
updateConnection(
|
updateConnection(
|
||||||
|
@@ -235,8 +235,7 @@ size_t bufLength(
|
|||||||
void dropPackets(QuicServerConnectionState& conn) {
|
void dropPackets(QuicServerConnectionState& conn) {
|
||||||
for (const auto& packet : conn.outstandingPackets) {
|
for (const auto& packet : conn.outstandingPackets) {
|
||||||
for (const auto& frame : packet.packet.frames) {
|
for (const auto& frame : packet.packet.frames) {
|
||||||
const WriteStreamFrame* streamFrame =
|
const WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
|
||||||
boost::get<WriteStreamFrame>(&frame);
|
|
||||||
if (!streamFrame) {
|
if (!streamFrame) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -285,15 +284,18 @@ void verifyCorrectness(
|
|||||||
bool finSet = false;
|
bool finSet = false;
|
||||||
std::vector<uint64_t> offsets;
|
std::vector<uint64_t> offsets;
|
||||||
for (const auto& packet : conn.outstandingPackets) {
|
for (const auto& packet : conn.outstandingPackets) {
|
||||||
for (const auto& streamFrame :
|
for (const auto& frame : packet.packet.frames) {
|
||||||
all_frames<WriteStreamFrame>(packet.packet.frames)) {
|
auto streamFrame = frame.asWriteStreamFrame();
|
||||||
if (streamFrame.streamId != id) {
|
if (!streamFrame) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
offsets.push_back(streamFrame.offset);
|
if (streamFrame->streamId != id) {
|
||||||
endOffset = std::max(endOffset, streamFrame.offset + streamFrame.len);
|
continue;
|
||||||
totalLen += streamFrame.len;
|
}
|
||||||
finSet |= streamFrame.fin;
|
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);
|
auto stream = conn.streamManager->findStream(id);
|
||||||
@@ -592,8 +594,12 @@ TEST_F(QuicTransportTest, WriteFlowControl) {
|
|||||||
auto& packet =
|
auto& packet =
|
||||||
getFirstOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
getFirstOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
||||||
bool blockedFound = false;
|
bool blockedFound = false;
|
||||||
for (auto& blocked : all_frames<StreamDataBlockedFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(blocked.streamId, streamId);
|
auto blocked = frame.asStreamDataBlockedFrame();
|
||||||
|
if (!blocked) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(blocked->streamId, streamId);
|
||||||
blockedFound = true;
|
blockedFound = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(blockedFound);
|
EXPECT_TRUE(blockedFound);
|
||||||
@@ -782,10 +788,14 @@ TEST_F(QuicTransportTest, WriteImmediateAcks) {
|
|||||||
EXPECT_GE(packet.frames.size(), 1);
|
EXPECT_GE(packet.frames.size(), 1);
|
||||||
|
|
||||||
bool ackFound = false;
|
bool ackFound = false;
|
||||||
for (auto& ackFrame : all_frames<WriteAckFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
auto ackFrame = frame.asWriteAckFrame();
|
||||||
EXPECT_EQ(start, ackFrame.ackBlocks.front().start);
|
if (!ackFrame) {
|
||||||
EXPECT_EQ(end, ackFrame.ackBlocks.front().end);
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(ackFrame->ackBlocks.size(), 1);
|
||||||
|
EXPECT_EQ(start, ackFrame->ackBlocks.front().start);
|
||||||
|
EXPECT_EQ(end, ackFrame->ackBlocks.front().end);
|
||||||
ackFound = true;
|
ackFound = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(ackFound);
|
EXPECT_TRUE(ackFound);
|
||||||
@@ -835,10 +845,14 @@ TEST_F(QuicTransportTest, WritePendingAckIfHavingData) {
|
|||||||
EXPECT_GE(packet.frames.size(), 2);
|
EXPECT_GE(packet.frames.size(), 2);
|
||||||
|
|
||||||
bool ackFound = false;
|
bool ackFound = false;
|
||||||
for (auto& ackFrame : all_frames<WriteAckFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
auto ackFrame = frame.asWriteAckFrame();
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().start, start);
|
if (!ackFrame) {
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().end, end);
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(ackFrame->ackBlocks.size(), 1);
|
||||||
|
EXPECT_EQ(ackFrame->ackBlocks.front().start, start);
|
||||||
|
EXPECT_EQ(ackFrame->ackBlocks.front().end, end);
|
||||||
ackFound = true;
|
ackFound = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(ackFound);
|
EXPECT_TRUE(ackFound);
|
||||||
@@ -864,10 +878,14 @@ TEST_F(QuicTransportTest, RstStream) {
|
|||||||
->packet;
|
->packet;
|
||||||
EXPECT_GE(packet.frames.size(), 1);
|
EXPECT_GE(packet.frames.size(), 1);
|
||||||
bool rstFound = false;
|
bool rstFound = false;
|
||||||
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(streamId, frame.streamId);
|
auto rstFrame = frame.asRstStreamFrame();
|
||||||
EXPECT_EQ(0, frame.offset);
|
if (!rstFrame) {
|
||||||
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(streamId, rstFrame->streamId);
|
||||||
|
EXPECT_EQ(0, rstFrame->offset);
|
||||||
|
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstFrame->errorCode);
|
||||||
rstFound = true;
|
rstFound = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(rstFound);
|
EXPECT_TRUE(rstFound);
|
||||||
@@ -896,15 +914,20 @@ TEST_F(QuicTransportTest, StopSending) {
|
|||||||
->packet;
|
->packet;
|
||||||
EXPECT_EQ(14, packet.frames.size());
|
EXPECT_EQ(14, packet.frames.size());
|
||||||
bool foundStopSending = false;
|
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(
|
folly::variant_match(
|
||||||
simpleFrame,
|
*simpleFrame,
|
||||||
[&](const StopSendingFrame& frame) {
|
[&](const StopSendingFrame& frame) {
|
||||||
EXPECT_EQ(streamId, frame.streamId);
|
EXPECT_EQ(streamId, frame.streamId);
|
||||||
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
||||||
foundStopSending = true;
|
foundStopSending = true;
|
||||||
},
|
},
|
||||||
[&](auto&) {});
|
[&](auto&) {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(foundStopSending);
|
EXPECT_TRUE(foundStopSending);
|
||||||
}
|
}
|
||||||
@@ -932,9 +955,13 @@ TEST_F(QuicTransportTest, SendPathChallenge) {
|
|||||||
transport_->getConnectionState(), PacketNumberSpace::AppData)
|
transport_->getConnectionState(), PacketNumberSpace::AppData)
|
||||||
->packet;
|
->packet;
|
||||||
bool foundPathChallenge = false;
|
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(
|
folly::variant_match(
|
||||||
simpleFrame,
|
*simpleFrame,
|
||||||
[&](const PathChallengeFrame& frame) {
|
[&](const PathChallengeFrame& frame) {
|
||||||
EXPECT_EQ(frame, pathChallenge);
|
EXPECT_EQ(frame, pathChallenge);
|
||||||
foundPathChallenge = true;
|
foundPathChallenge = true;
|
||||||
@@ -1133,9 +1160,13 @@ TEST_F(QuicTransportTest, SendPathResponse) {
|
|||||||
auto packet =
|
auto packet =
|
||||||
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
||||||
bool foundPathResponse = false;
|
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(
|
folly::variant_match(
|
||||||
simpleFrame,
|
*simpleFrame,
|
||||||
[&](const PathResponseFrame& frame) {
|
[&](const PathResponseFrame& frame) {
|
||||||
EXPECT_EQ(frame, pathResponse);
|
EXPECT_EQ(frame, pathResponse);
|
||||||
foundPathResponse = true;
|
foundPathResponse = true;
|
||||||
@@ -1244,9 +1275,13 @@ TEST_F(QuicTransportTest, SendNewConnectionIdFrame) {
|
|||||||
transport_->getConnectionState(), PacketNumberSpace::AppData)
|
transport_->getConnectionState(), PacketNumberSpace::AppData)
|
||||||
->packet;
|
->packet;
|
||||||
bool foundNewConnectionId = false;
|
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(
|
folly::variant_match(
|
||||||
simpleFrame,
|
*simpleFrame,
|
||||||
[&](const NewConnectionIdFrame& frame) {
|
[&](const NewConnectionIdFrame& frame) {
|
||||||
EXPECT_EQ(frame, newConnId);
|
EXPECT_EQ(frame, newConnId);
|
||||||
foundNewConnectionId = true;
|
foundNewConnectionId = true;
|
||||||
@@ -1379,9 +1414,13 @@ TEST_F(QuicTransportTest, SendRetireConnectionIdFrame) {
|
|||||||
transport_->getConnectionState(), PacketNumberSpace::AppData)
|
transport_->getConnectionState(), PacketNumberSpace::AppData)
|
||||||
->packet;
|
->packet;
|
||||||
bool foundRetireConnectionId = false;
|
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(
|
folly::variant_match(
|
||||||
simpleFrame,
|
*simpleFrame,
|
||||||
[&](const RetireConnectionIdFrame& frame) {
|
[&](const RetireConnectionIdFrame& frame) {
|
||||||
EXPECT_EQ(frame, retireConnId);
|
EXPECT_EQ(frame, retireConnId);
|
||||||
foundRetireConnectionId = true;
|
foundRetireConnectionId = true;
|
||||||
@@ -1500,10 +1539,14 @@ TEST_F(QuicTransportTest, RstWrittenStream) {
|
|||||||
EXPECT_GE(packet.frames.size(), 1);
|
EXPECT_GE(packet.frames.size(), 1);
|
||||||
|
|
||||||
bool foundReset = false;
|
bool foundReset = false;
|
||||||
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(streamId, frame.streamId);
|
auto rstStream = frame.asRstStreamFrame();
|
||||||
EXPECT_EQ(currentWriteOffset, frame.offset);
|
if (!rstStream) {
|
||||||
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(streamId, rstStream->streamId);
|
||||||
|
EXPECT_EQ(currentWriteOffset, rstStream->offset);
|
||||||
|
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstStream->errorCode);
|
||||||
foundReset = true;
|
foundReset = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(foundReset);
|
EXPECT_TRUE(foundReset);
|
||||||
@@ -1530,9 +1573,13 @@ TEST_F(QuicTransportTest, RstStreamUDPWriteFailNonFatal) {
|
|||||||
EXPECT_GE(packet.frames.size(), 1);
|
EXPECT_GE(packet.frames.size(), 1);
|
||||||
|
|
||||||
bool foundReset = false;
|
bool foundReset = false;
|
||||||
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(streamId, frame.streamId);
|
auto rstStream = frame.asRstStreamFrame();
|
||||||
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
if (!rstStream) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(streamId, rstStream->streamId);
|
||||||
|
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstStream->errorCode);
|
||||||
foundReset = true;
|
foundReset = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(foundReset);
|
EXPECT_TRUE(foundReset);
|
||||||
@@ -1596,10 +1643,14 @@ TEST_F(QuicTransportTest, WriteAfterSendRst) {
|
|||||||
EXPECT_GE(packet.frames.size(), 1);
|
EXPECT_GE(packet.frames.size(), 1);
|
||||||
|
|
||||||
bool foundReset = false;
|
bool foundReset = false;
|
||||||
for (auto& frame : all_frames<RstStreamFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(streamId, frame.streamId);
|
auto rstFrame = frame.asRstStreamFrame();
|
||||||
EXPECT_EQ(currentWriteOffset, frame.offset);
|
if (!rstFrame) {
|
||||||
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(streamId, rstFrame->streamId);
|
||||||
|
EXPECT_EQ(currentWriteOffset, rstFrame->offset);
|
||||||
|
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, rstFrame->errorCode);
|
||||||
foundReset = true;
|
foundReset = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(foundReset);
|
EXPECT_TRUE(foundReset);
|
||||||
@@ -1671,8 +1722,12 @@ TEST_F(QuicTransportTest, WriteWindowUpdate) {
|
|||||||
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
||||||
EXPECT_GE(packet.frames.size(), 1);
|
EXPECT_GE(packet.frames.size(), 1);
|
||||||
bool connWindowFound = false;
|
bool connWindowFound = false;
|
||||||
for (auto& connWindowUpdate : all_frames<MaxDataFrame>(packet.frames)) {
|
for (auto& frame : packet.frames) {
|
||||||
EXPECT_EQ(100, connWindowUpdate.maximumData);
|
auto connWindowUpdate = frame.asMaxDataFrame();
|
||||||
|
if (!connWindowUpdate) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(100, connWindowUpdate->maximumData);
|
||||||
connWindowFound = true;
|
connWindowFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1702,7 +1757,7 @@ TEST_F(QuicTransportTest, WriteWindowUpdate) {
|
|||||||
auto packet1 =
|
auto packet1 =
|
||||||
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
|
||||||
const MaxStreamDataFrame* streamWindowUpdate =
|
const MaxStreamDataFrame* streamWindowUpdate =
|
||||||
boost::get<MaxStreamDataFrame>(&packet1.frames.front());
|
packet1.frames.front().asMaxStreamDataFrame();
|
||||||
EXPECT_TRUE(streamWindowUpdate);
|
EXPECT_TRUE(streamWindowUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2278,7 +2333,7 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
|
|||||||
auto& packet = *getFirstOutstandingPacket(conn, PacketNumberSpace::AppData);
|
auto& packet = *getFirstOutstandingPacket(conn, PacketNumberSpace::AppData);
|
||||||
EXPECT_EQ(1, packet.packet.frames.size());
|
EXPECT_EQ(1, packet.packet.frames.size());
|
||||||
auto& frame = packet.packet.frames.front();
|
auto& frame = packet.packet.frames.front();
|
||||||
const WriteStreamFrame* streamFrame = boost::get<WriteStreamFrame>(&frame);
|
const WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
|
||||||
EXPECT_TRUE(streamFrame);
|
EXPECT_TRUE(streamFrame);
|
||||||
EXPECT_EQ(streamFrame->streamId, s1);
|
EXPECT_EQ(streamFrame->streamId, s1);
|
||||||
conn.outstandingPackets.clear();
|
conn.outstandingPackets.clear();
|
||||||
@@ -2301,7 +2356,7 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
|
|||||||
auto& packet2 = *getFirstOutstandingPacket(conn, PacketNumberSpace::AppData);
|
auto& packet2 = *getFirstOutstandingPacket(conn, PacketNumberSpace::AppData);
|
||||||
EXPECT_EQ(1, packet2.packet.frames.size());
|
EXPECT_EQ(1, packet2.packet.frames.size());
|
||||||
auto& frame2 = packet2.packet.frames.front();
|
auto& frame2 = packet2.packet.frames.front();
|
||||||
const WriteStreamFrame* streamFrame2 = boost::get<WriteStreamFrame>(&frame2);
|
const WriteStreamFrame* streamFrame2 = frame2.asWriteStreamFrame();
|
||||||
EXPECT_TRUE(streamFrame2);
|
EXPECT_TRUE(streamFrame2);
|
||||||
EXPECT_EQ(streamFrame2->streamId, s2);
|
EXPECT_EQ(streamFrame2->streamId, s2);
|
||||||
conn.outstandingPackets.clear();
|
conn.outstandingPackets.clear();
|
||||||
@@ -2324,10 +2379,10 @@ TEST_F(QuicTransportTest, WriteStreamFromMiddleOfMap) {
|
|||||||
EXPECT_EQ(2, packet3.packet.frames.size());
|
EXPECT_EQ(2, packet3.packet.frames.size());
|
||||||
auto& frame3 = packet3.packet.frames.front();
|
auto& frame3 = packet3.packet.frames.front();
|
||||||
auto& frame4 = packet3.packet.frames.back();
|
auto& frame4 = packet3.packet.frames.back();
|
||||||
const WriteStreamFrame* streamFrame3 = boost::get<WriteStreamFrame>(&frame3);
|
const WriteStreamFrame* streamFrame3 = frame3.asWriteStreamFrame();
|
||||||
EXPECT_TRUE(streamFrame3);
|
EXPECT_TRUE(streamFrame3);
|
||||||
EXPECT_EQ(streamFrame3->streamId, s2);
|
EXPECT_EQ(streamFrame3->streamId, s2);
|
||||||
const WriteStreamFrame* streamFrame4 = boost::get<WriteStreamFrame>(&frame4);
|
const WriteStreamFrame* streamFrame4 = frame4.asWriteStreamFrame();
|
||||||
EXPECT_TRUE(streamFrame4);
|
EXPECT_TRUE(streamFrame4);
|
||||||
EXPECT_EQ(streamFrame4->streamId, s1);
|
EXPECT_EQ(streamFrame4->streamId, s1);
|
||||||
transport_->close(folly::none);
|
transport_->close(folly::none);
|
||||||
|
@@ -295,31 +295,36 @@ void QuicClientTransport::processPacketData(
|
|||||||
// TODO: replace this with a better solution later.
|
// TODO: replace this with a better solution later.
|
||||||
cancelHandshakeCryptoStreamRetransmissions(*conn_->cryptoState);
|
cancelHandshakeCryptoStreamRetransmissions(*conn_->cryptoState);
|
||||||
}
|
}
|
||||||
folly::variant_match(
|
switch (packetFrame.type()) {
|
||||||
packetFrame,
|
case QuicWriteFrame::Type::WriteAckFrame_E: {
|
||||||
[&](const WriteAckFrame& frame) {
|
const WriteAckFrame& frame = *packetFrame.asWriteAckFrame();
|
||||||
DCHECK(!frame.ackBlocks.empty());
|
DCHECK(!frame.ackBlocks.empty());
|
||||||
VLOG(4) << "Client received ack for largestAcked="
|
VLOG(4) << "Client received ack for largestAcked="
|
||||||
<< frame.ackBlocks.back().end << " " << *this;
|
<< frame.ackBlocks.back().end << " " << *this;
|
||||||
commonAckVisitorForAckFrame(ackState, frame);
|
commonAckVisitorForAckFrame(ackState, frame);
|
||||||
},
|
break;
|
||||||
[&](const RstStreamFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::RstStreamFrame_E: {
|
||||||
|
const RstStreamFrame& frame = *packetFrame.asRstStreamFrame();
|
||||||
VLOG(4) << "Client received ack for reset frame stream="
|
VLOG(4) << "Client received ack for reset frame stream="
|
||||||
<< frame.streamId << " " << *this;
|
<< frame.streamId << " " << *this;
|
||||||
|
|
||||||
auto stream =
|
auto stream = conn_->streamManager->getStream(frame.streamId);
|
||||||
conn_->streamManager->getStream(frame.streamId);
|
|
||||||
if (stream) {
|
if (stream) {
|
||||||
invokeStreamSendStateMachine(
|
invokeStreamSendStateMachine(
|
||||||
*conn_, *stream, StreamEvents::RstAck(frame));
|
*conn_, *stream, StreamEvents::RstAck(frame));
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
[&](const WriteStreamFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
|
const WriteStreamFrame& frame =
|
||||||
|
*packetFrame.asWriteStreamFrame();
|
||||||
|
|
||||||
auto ackedStream =
|
auto ackedStream =
|
||||||
conn_->streamManager->getStream(frame.streamId);
|
conn_->streamManager->getStream(frame.streamId);
|
||||||
VLOG(4) << "Client got ack for stream=" << frame.streamId
|
VLOG(4) << "Client got ack for stream=" << frame.streamId
|
||||||
<< " offset=" << frame.offset
|
<< " offset=" << frame.offset << " fin=" << frame.fin
|
||||||
<< " fin=" << frame.fin << " data=" << frame.len
|
<< " data=" << frame.len
|
||||||
<< " closed=" << (ackedStream == nullptr) << " "
|
<< " closed=" << (ackedStream == nullptr) << " "
|
||||||
<< *this;
|
<< *this;
|
||||||
if (ackedStream) {
|
if (ackedStream) {
|
||||||
@@ -328,18 +333,23 @@ void QuicClientTransport::processPacketData(
|
|||||||
*ackedStream,
|
*ackedStream,
|
||||||
StreamEvents::AckStreamFrame(frame));
|
StreamEvents::AckStreamFrame(frame));
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
[&](const WriteCryptoFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
|
const WriteCryptoFrame& frame =
|
||||||
|
*packetFrame.asWriteCryptoFrame();
|
||||||
auto cryptoStream = getCryptoStream(
|
auto cryptoStream = getCryptoStream(
|
||||||
*conn_->cryptoState,
|
*conn_->cryptoState,
|
||||||
protectionTypeToEncryptionLevel(
|
protectionTypeToEncryptionLevel(
|
||||||
outstandingProtectionType));
|
outstandingProtectionType));
|
||||||
processCryptoStreamAck(
|
processCryptoStreamAck(
|
||||||
*cryptoStream, frame.offset, frame.len);
|
*cryptoStream, frame.offset, frame.len);
|
||||||
},
|
break;
|
||||||
[&](const auto& /* frame */) {
|
}
|
||||||
// Ignore other frames.
|
default:
|
||||||
});
|
// ignore other frames.
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
markPacketLoss,
|
markPacketLoss,
|
||||||
receiveTimePoint);
|
receiveTimePoint);
|
||||||
|
@@ -167,6 +167,11 @@ class QuicClientTransport
|
|||||||
|
|
||||||
void happyEyeballsConnAttemptDelayTimeoutExpired() noexcept;
|
void happyEyeballsConnAttemptDelayTimeoutExpired() noexcept;
|
||||||
|
|
||||||
|
void handleAckFrame(
|
||||||
|
const OutstandingPacket& outstandingPacket,
|
||||||
|
const QuicWriteFrame& packetFrame,
|
||||||
|
const ReadAckFrame&);
|
||||||
|
|
||||||
// From ClientHandshake::HandshakeCallback
|
// From ClientHandshake::HandshakeCallback
|
||||||
void onNewCachedPsk(
|
void onNewCachedPsk(
|
||||||
fizz::client::NewCachedPsk& newCachedPsk) noexcept override;
|
fizz::client::NewCachedPsk& newCachedPsk) noexcept override;
|
||||||
|
@@ -3934,12 +3934,11 @@ RegularQuicWritePacket* findPacketWithStream(
|
|||||||
StreamId streamId) {
|
StreamId streamId) {
|
||||||
auto op = findOutstandingPacket(conn, [=](OutstandingPacket& packet) {
|
auto op = findOutstandingPacket(conn, [=](OutstandingPacket& packet) {
|
||||||
for (auto& frame : packet.packet.frames) {
|
for (auto& frame : packet.packet.frames) {
|
||||||
bool tryPacket = folly::variant_match(
|
bool tryPacket = false;
|
||||||
frame,
|
WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
|
||||||
[streamId](WriteStreamFrame& streamFrame) {
|
if (streamFrame) {
|
||||||
return streamFrame.streamId == streamId;
|
tryPacket = streamFrame->streamId == streamId;
|
||||||
},
|
}
|
||||||
[](auto&) { return false; });
|
|
||||||
if (tryPacket) {
|
if (tryPacket) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -53,9 +53,9 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
|
|||||||
iter != packet.packet.frames.cend();
|
iter != packet.packet.frames.cend();
|
||||||
iter++) {
|
iter++) {
|
||||||
const QuicWriteFrame& frame = *iter;
|
const QuicWriteFrame& frame = *iter;
|
||||||
writeSuccess = folly::variant_match(
|
switch (frame.type()) {
|
||||||
frame,
|
case QuicWriteFrame::Type::WriteAckFrame_E: {
|
||||||
[&](const WriteAckFrame& ackFrame) {
|
const WriteAckFrame& ackFrame = *frame.asWriteAckFrame();
|
||||||
auto& packetHeader = builder_.getPacketHeader();
|
auto& packetHeader = builder_.getPacketHeader();
|
||||||
uint64_t ackDelayExponent =
|
uint64_t ackDelayExponent =
|
||||||
(packetHeader.getHeaderForm() == HeaderForm::Long)
|
(packetHeader.getHeaderForm() == HeaderForm::Long)
|
||||||
@@ -64,9 +64,11 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
|
|||||||
AckFrameMetaData meta(
|
AckFrameMetaData meta(
|
||||||
ackFrame.ackBlocks, ackFrame.ackDelay, ackDelayExponent);
|
ackFrame.ackBlocks, ackFrame.ackDelay, ackDelayExponent);
|
||||||
auto ackWriteResult = writeAckFrame(meta, builder_);
|
auto ackWriteResult = writeAckFrame(meta, builder_);
|
||||||
return ackWriteResult.hasValue();
|
writeSuccess = ackWriteResult.hasValue();
|
||||||
},
|
break;
|
||||||
[&](const WriteStreamFrame& streamFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
|
const WriteStreamFrame& streamFrame = *frame.asWriteStreamFrame();
|
||||||
auto stream = conn_.streamManager->getStream(streamFrame.streamId);
|
auto stream = conn_.streamManager->getStream(streamFrame.streamId);
|
||||||
if (stream && retransmittable(*stream)) {
|
if (stream && retransmittable(*stream)) {
|
||||||
auto streamData = cloneRetransmissionBuffer(streamFrame, stream);
|
auto streamData = cloneRetransmissionBuffer(streamFrame, stream);
|
||||||
@@ -83,17 +85,21 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
writeStreamFrameData(builder_, std::move(streamData), *dataLen);
|
writeStreamFrameData(builder_, std::move(streamData), *dataLen);
|
||||||
notPureAck = true;
|
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
|
// 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
|
// 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
|
// move on to the next packet? I'm gonna err on the aggressive side
|
||||||
// for now and call it success.
|
// for now and call it success.
|
||||||
return true;
|
writeSuccess = true;
|
||||||
},
|
break;
|
||||||
[&](const WriteCryptoFrame& cryptoFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
|
const WriteCryptoFrame& cryptoFrame = *frame.asWriteCryptoFrame();
|
||||||
// initialStream and handshakeStream can only be in handshake packet,
|
// initialStream and handshakeStream can only be in handshake packet,
|
||||||
// so they are not clonable
|
// so they are not clonable
|
||||||
CHECK(!packet.isHandshake);
|
CHECK(!packet.isHandshake);
|
||||||
@@ -106,7 +112,8 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
|
|||||||
|
|
||||||
// No crypto data found to be cloned, just skip
|
// No crypto data found to be cloned, just skip
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
return true;
|
writeSuccess = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
auto cryptoWriteResult =
|
auto cryptoWriteResult =
|
||||||
writeCryptoFrame(cryptoFrame.offset, std::move(buf), builder_);
|
writeCryptoFrame(cryptoFrame.offset, std::move(buf), builder_);
|
||||||
@@ -114,47 +121,60 @@ folly::Optional<PacketEvent> PacketRebuilder::rebuildFromPacket(
|
|||||||
cryptoWriteResult->offset == cryptoFrame.offset &&
|
cryptoWriteResult->offset == cryptoFrame.offset &&
|
||||||
cryptoWriteResult->len == cryptoFrame.len;
|
cryptoWriteResult->len == cryptoFrame.len;
|
||||||
notPureAck |= ret;
|
notPureAck |= ret;
|
||||||
return ret;
|
writeSuccess = ret;
|
||||||
},
|
break;
|
||||||
[&](const MaxDataFrame&) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxDataFrame_E: {
|
||||||
shouldWriteWindowUpdate = true;
|
shouldWriteWindowUpdate = true;
|
||||||
auto ret = 0 != writeFrame(generateMaxDataFrame(conn_), builder_);
|
auto ret = 0 != writeFrame(generateMaxDataFrame(conn_), builder_);
|
||||||
windowUpdateWritten |= ret;
|
windowUpdateWritten |= ret;
|
||||||
notPureAck |= ret;
|
notPureAck |= ret;
|
||||||
return true;
|
writeSuccess = true;
|
||||||
},
|
break;
|
||||||
[&](const MaxStreamDataFrame& maxStreamDataFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
|
const MaxStreamDataFrame& maxStreamDataFrame =
|
||||||
|
*frame.asMaxStreamDataFrame();
|
||||||
auto stream =
|
auto stream =
|
||||||
conn_.streamManager->getStream(maxStreamDataFrame.streamId);
|
conn_.streamManager->getStream(maxStreamDataFrame.streamId);
|
||||||
if (!stream || !stream->shouldSendFlowControl()) {
|
if (!stream || !stream->shouldSendFlowControl()) {
|
||||||
return true;
|
writeSuccess = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
shouldWriteWindowUpdate = true;
|
shouldWriteWindowUpdate = true;
|
||||||
auto ret =
|
auto ret =
|
||||||
0 != writeFrame(generateMaxStreamDataFrame(*stream), builder_);
|
0 != writeFrame(generateMaxStreamDataFrame(*stream), builder_);
|
||||||
windowUpdateWritten |= ret;
|
windowUpdateWritten |= ret;
|
||||||
notPureAck |= ret;
|
notPureAck |= ret;
|
||||||
return true;
|
writeSuccess = true;
|
||||||
},
|
break;
|
||||||
[&](const PaddingFrame& paddingFrame) {
|
}
|
||||||
return writeFrame(paddingFrame, builder_) != 0;
|
case QuicWriteFrame::Type::PaddingFrame_E: {
|
||||||
},
|
const PaddingFrame& paddingFrame = *frame.asPaddingFrame();
|
||||||
[&](const QuicSimpleFrame& simpleFrame) {
|
writeSuccess = writeFrame(paddingFrame, builder_) != 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
|
||||||
|
const QuicSimpleFrame& simpleFrame = *frame.asQuicSimpleFrame();
|
||||||
auto updatedSimpleFrame =
|
auto updatedSimpleFrame =
|
||||||
updateSimpleFrameOnPacketClone(conn_, simpleFrame);
|
updateSimpleFrameOnPacketClone(conn_, simpleFrame);
|
||||||
if (!updatedSimpleFrame) {
|
if (!updatedSimpleFrame) {
|
||||||
return true;
|
writeSuccess = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
bool ret =
|
bool ret =
|
||||||
writeSimpleFrame(std::move(*updatedSimpleFrame), builder_) != 0;
|
writeSimpleFrame(std::move(*updatedSimpleFrame), builder_) != 0;
|
||||||
notPureAck |= ret;
|
notPureAck |= ret;
|
||||||
return ret;
|
writeSuccess = ret;
|
||||||
},
|
break;
|
||||||
[&](const auto& otherFrame) {
|
}
|
||||||
bool ret = writeFrame(otherFrame, builder_) != 0;
|
default: {
|
||||||
|
bool ret = writeFrame(QuicWriteFrame(frame), builder_) != 0;
|
||||||
notPureAck |= ret;
|
notPureAck |= ret;
|
||||||
return ret;
|
writeSuccess = ret;
|
||||||
});
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!writeSuccess) {
|
if (!writeSuccess) {
|
||||||
return folly::none;
|
return folly::none;
|
||||||
}
|
}
|
||||||
|
@@ -339,7 +339,7 @@ size_t writeSimpleFrame(
|
|||||||
} else {
|
} else {
|
||||||
builder.write(errorCode);
|
builder.write(errorCode);
|
||||||
}
|
}
|
||||||
builder.appendFrame(std::move(stopSendingFrame));
|
builder.appendFrame(QuicSimpleFrame(std::move(stopSendingFrame)));
|
||||||
return stopSendingFrameSize;
|
return stopSendingFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -358,7 +358,7 @@ size_t writeSimpleFrame(
|
|||||||
builder.write(streamId);
|
builder.write(streamId);
|
||||||
builder.write(maximumData);
|
builder.write(maximumData);
|
||||||
builder.write(minimumStreamOffset);
|
builder.write(minimumStreamOffset);
|
||||||
builder.appendFrame(std::move(minStreamDataFrame));
|
builder.appendFrame(QuicSimpleFrame(std::move(minStreamDataFrame)));
|
||||||
return minStreamDataFrameSize;
|
return minStreamDataFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -376,7 +376,8 @@ size_t writeSimpleFrame(
|
|||||||
builder.write(frameType);
|
builder.write(frameType);
|
||||||
builder.write(streamId);
|
builder.write(streamId);
|
||||||
builder.write(minimumStreamOffset);
|
builder.write(minimumStreamOffset);
|
||||||
builder.appendFrame(std::move(expiredStreamDataFrame));
|
builder.appendFrame(
|
||||||
|
QuicSimpleFrame(std::move(expiredStreamDataFrame)));
|
||||||
return expiredStreamDataFrameSize;
|
return expiredStreamDataFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -389,7 +390,7 @@ size_t writeSimpleFrame(
|
|||||||
if (packetSpaceCheck(spaceLeft, pathChallengeFrameSize)) {
|
if (packetSpaceCheck(spaceLeft, pathChallengeFrameSize)) {
|
||||||
builder.write(frameType);
|
builder.write(frameType);
|
||||||
builder.writeBE(pathChallengeFrame.pathData);
|
builder.writeBE(pathChallengeFrame.pathData);
|
||||||
builder.appendFrame(std::move(pathChallengeFrame));
|
builder.appendFrame(QuicSimpleFrame(std::move(pathChallengeFrame)));
|
||||||
return pathChallengeFrameSize;
|
return pathChallengeFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -402,7 +403,7 @@ size_t writeSimpleFrame(
|
|||||||
if (packetSpaceCheck(spaceLeft, pathResponseFrameSize)) {
|
if (packetSpaceCheck(spaceLeft, pathResponseFrameSize)) {
|
||||||
builder.write(frameType);
|
builder.write(frameType);
|
||||||
builder.writeBE(pathResponseFrame.pathData);
|
builder.writeBE(pathResponseFrame.pathData);
|
||||||
builder.appendFrame(std::move(pathResponseFrame));
|
builder.appendFrame(QuicSimpleFrame(std::move(pathResponseFrame)));
|
||||||
return pathResponseFrameSize;
|
return pathResponseFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -429,7 +430,7 @@ size_t writeSimpleFrame(
|
|||||||
builder.push(
|
builder.push(
|
||||||
newConnectionIdFrame.token.data(),
|
newConnectionIdFrame.token.data(),
|
||||||
newConnectionIdFrame.token.size());
|
newConnectionIdFrame.token.size());
|
||||||
builder.appendFrame(std::move(newConnectionIdFrame));
|
builder.appendFrame(QuicSimpleFrame(std::move(newConnectionIdFrame)));
|
||||||
return newConnectionIdFrameSize;
|
return newConnectionIdFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -446,7 +447,7 @@ size_t writeSimpleFrame(
|
|||||||
if (packetSpaceCheck(spaceLeft, maxStreamsFrameSize)) {
|
if (packetSpaceCheck(spaceLeft, maxStreamsFrameSize)) {
|
||||||
builder.write(intFrameType);
|
builder.write(intFrameType);
|
||||||
builder.write(streamCount);
|
builder.write(streamCount);
|
||||||
builder.appendFrame(maxStreamsFrame);
|
builder.appendFrame(QuicSimpleFrame(maxStreamsFrame));
|
||||||
return maxStreamsFrameSize;
|
return maxStreamsFrameSize;
|
||||||
}
|
}
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
@@ -460,7 +461,7 @@ size_t writeSimpleFrame(
|
|||||||
if (packetSpaceCheck(spaceLeft, retireConnectionIdFrameSize)) {
|
if (packetSpaceCheck(spaceLeft, retireConnectionIdFrameSize)) {
|
||||||
builder.write(frameType);
|
builder.write(frameType);
|
||||||
builder.write(sequence);
|
builder.write(sequence);
|
||||||
builder.appendFrame(retireConnectionIdFrame);
|
builder.appendFrame(QuicSimpleFrame(retireConnectionIdFrame));
|
||||||
return retireConnectionIdFrameSize;
|
return retireConnectionIdFrameSize;
|
||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
@@ -473,9 +474,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
|
|
||||||
uint64_t spaceLeft = builder.remainingSpaceInPkt();
|
uint64_t spaceLeft = builder.remainingSpaceInPkt();
|
||||||
|
|
||||||
return folly::variant_match(
|
switch (frame.type()) {
|
||||||
frame,
|
case QuicWriteFrame::Type::PaddingFrame_E: {
|
||||||
[&](PaddingFrame& paddingFrame) {
|
PaddingFrame& paddingFrame = *frame.asPaddingFrame();
|
||||||
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::PADDING));
|
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::PADDING));
|
||||||
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
|
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
|
||||||
builder.write(intFrameType);
|
builder.write(intFrameType);
|
||||||
@@ -483,8 +484,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
return intFrameType.getSize();
|
return intFrameType.getSize();
|
||||||
}
|
}
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](PingFrame& pingFrame) {
|
case QuicWriteFrame::Type::PingFrame_E: {
|
||||||
|
PingFrame& pingFrame = *frame.asPingFrame();
|
||||||
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::PING));
|
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::PING));
|
||||||
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
|
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
|
||||||
builder.write(intFrameType);
|
builder.write(intFrameType);
|
||||||
@@ -493,8 +495,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
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 intFrameType(static_cast<uint8_t>(FrameType::RST_STREAM));
|
||||||
QuicInteger streamId(rstStreamFrame.streamId);
|
QuicInteger streamId(rstStreamFrame.streamId);
|
||||||
QuicInteger offset(rstStreamFrame.offset);
|
QuicInteger offset(rstStreamFrame.offset);
|
||||||
@@ -520,8 +523,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
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 intFrameType(static_cast<uint8_t>(FrameType::MAX_DATA));
|
||||||
QuicInteger maximumData(maxDataFrame.maximumData);
|
QuicInteger maximumData(maxDataFrame.maximumData);
|
||||||
auto frameSize = intFrameType.getSize() + maximumData.getSize();
|
auto frameSize = intFrameType.getSize() + maximumData.getSize();
|
||||||
@@ -533,8 +537,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](MaxStreamDataFrame& maxStreamDataFrame) {
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
|
MaxStreamDataFrame& maxStreamDataFrame = *frame.asMaxStreamDataFrame();
|
||||||
QuicInteger intFrameType(
|
QuicInteger intFrameType(
|
||||||
static_cast<uint8_t>(FrameType::MAX_STREAM_DATA));
|
static_cast<uint8_t>(FrameType::MAX_STREAM_DATA));
|
||||||
QuicInteger streamId(maxStreamDataFrame.streamId);
|
QuicInteger streamId(maxStreamDataFrame.streamId);
|
||||||
@@ -550,8 +555,9 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
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 intFrameType(static_cast<uint8_t>(FrameType::DATA_BLOCKED));
|
||||||
QuicInteger dataLimit(blockedFrame.dataLimit);
|
QuicInteger dataLimit(blockedFrame.dataLimit);
|
||||||
auto blockedFrameSize = intFrameType.getSize() + dataLimit.getSize();
|
auto blockedFrameSize = intFrameType.getSize() + dataLimit.getSize();
|
||||||
@@ -563,8 +569,10 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](StreamDataBlockedFrame& streamBlockedFrame) {
|
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
|
||||||
|
StreamDataBlockedFrame& streamBlockedFrame =
|
||||||
|
*frame.asStreamDataBlockedFrame();
|
||||||
QuicInteger intFrameType(
|
QuicInteger intFrameType(
|
||||||
static_cast<uint8_t>(FrameType::STREAM_DATA_BLOCKED));
|
static_cast<uint8_t>(FrameType::STREAM_DATA_BLOCKED));
|
||||||
QuicInteger streamId(streamBlockedFrame.streamId);
|
QuicInteger streamId(streamBlockedFrame.streamId);
|
||||||
@@ -580,15 +588,15 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](StreamsBlockedFrame& streamsBlockedFrame) {
|
case QuicWriteFrame::Type::StreamsBlockedFrame_E: {
|
||||||
|
StreamsBlockedFrame& streamsBlockedFrame = *frame.asStreamsBlockedFrame();
|
||||||
auto frameType = streamsBlockedFrame.isForBidirectionalStream()
|
auto frameType = streamsBlockedFrame.isForBidirectionalStream()
|
||||||
? FrameType::STREAMS_BLOCKED_BIDI
|
? FrameType::STREAMS_BLOCKED_BIDI
|
||||||
: FrameType::STREAMS_BLOCKED_UNI;
|
: FrameType::STREAMS_BLOCKED_UNI;
|
||||||
QuicInteger intFrameType(static_cast<FrameTypeType>(frameType));
|
QuicInteger intFrameType(static_cast<FrameTypeType>(frameType));
|
||||||
QuicInteger streamId(streamsBlockedFrame.streamLimit);
|
QuicInteger streamId(streamsBlockedFrame.streamLimit);
|
||||||
auto streamBlockedFrameSize =
|
auto streamBlockedFrameSize = intFrameType.getSize() + streamId.getSize();
|
||||||
intFrameType.getSize() + streamId.getSize();
|
|
||||||
if (packetSpaceCheck(spaceLeft, streamBlockedFrameSize)) {
|
if (packetSpaceCheck(spaceLeft, streamBlockedFrameSize)) {
|
||||||
builder.write(intFrameType);
|
builder.write(intFrameType);
|
||||||
builder.write(streamId);
|
builder.write(streamId);
|
||||||
@@ -597,8 +605,10 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](ConnectionCloseFrame& connectionCloseFrame) {
|
case QuicWriteFrame::Type::ConnectionCloseFrame_E: {
|
||||||
|
ConnectionCloseFrame& connectionCloseFrame =
|
||||||
|
*frame.asConnectionCloseFrame();
|
||||||
QuicInteger intFrameType(
|
QuicInteger intFrameType(
|
||||||
static_cast<uint8_t>(FrameType::CONNECTION_CLOSE));
|
static_cast<uint8_t>(FrameType::CONNECTION_CLOSE));
|
||||||
QuicInteger reasonLength(connectionCloseFrame.reasonPhrase.size());
|
QuicInteger reasonLength(connectionCloseFrame.reasonPhrase.size());
|
||||||
@@ -632,8 +642,10 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](ApplicationCloseFrame& applicationCloseFrame) {
|
case QuicWriteFrame::Type::ApplicationCloseFrame_E: {
|
||||||
|
ApplicationCloseFrame& applicationCloseFrame =
|
||||||
|
*frame.asApplicationCloseFrame();
|
||||||
QuicInteger intFrameType(
|
QuicInteger intFrameType(
|
||||||
static_cast<uint8_t>(FrameType::APPLICATION_CLOSE));
|
static_cast<uint8_t>(FrameType::APPLICATION_CLOSE));
|
||||||
QuicInteger reasonLength(applicationCloseFrame.reasonPhrase.size());
|
QuicInteger reasonLength(applicationCloseFrame.reasonPhrase.size());
|
||||||
@@ -662,17 +674,18 @@ size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder) {
|
|||||||
}
|
}
|
||||||
// no space left in packet
|
// no space left in packet
|
||||||
return size_t(0);
|
return size_t(0);
|
||||||
},
|
}
|
||||||
[&](QuicSimpleFrame& simpleFrame) {
|
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
|
||||||
return writeSimpleFrame(std::move(simpleFrame), builder);
|
return writeSimpleFrame(std::move(*frame.asQuicSimpleFrame()), builder);
|
||||||
},
|
}
|
||||||
[&](auto&) -> size_t {
|
default: {
|
||||||
// TODO add support for: RETIRE_CONNECTION_ID and NEW_TOKEN frames
|
// TODO add support for: RETIRE_CONNECTION_ID and NEW_TOKEN frames
|
||||||
auto errorStr = folly::to<std::string>(
|
auto errorStr = folly::to<std::string>(
|
||||||
"Unknown / unsupported frame type received at ", __func__);
|
"Unknown / unsupported frame type received at ", __func__);
|
||||||
VLOG(2) << errorStr;
|
VLOG(2) << errorStr;
|
||||||
throw QuicTransportException(
|
throw QuicTransportException(
|
||||||
errorStr, TransportErrorCode::FRAME_ENCODING_ERROR);
|
errorStr, TransportErrorCode::FRAME_ENCODING_ERROR);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
@@ -592,22 +592,25 @@ using QuicSimpleFrame = boost::variant<
|
|||||||
|
|
||||||
DECLARE_VARIANT_TYPE(QuicFrame, QUIC_FRAME)
|
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.
|
// Types of frames which are written.
|
||||||
using QuicWriteFrame = boost::variant<
|
DECLARE_VARIANT_TYPE(QuicWriteFrame, QUIC_WRITE_FRAME)
|
||||||
PaddingFrame,
|
|
||||||
RstStreamFrame,
|
|
||||||
ConnectionCloseFrame,
|
|
||||||
ApplicationCloseFrame,
|
|
||||||
MaxDataFrame,
|
|
||||||
MaxStreamDataFrame,
|
|
||||||
PingFrame,
|
|
||||||
DataBlockedFrame,
|
|
||||||
StreamDataBlockedFrame,
|
|
||||||
StreamsBlockedFrame,
|
|
||||||
WriteAckFrame,
|
|
||||||
WriteStreamFrame,
|
|
||||||
WriteCryptoFrame,
|
|
||||||
QuicSimpleFrame>;
|
|
||||||
|
|
||||||
enum class HeaderForm : bool {
|
enum class HeaderForm : bool {
|
||||||
Long = 1,
|
Long = 1,
|
||||||
|
@@ -80,7 +80,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
|
|||||||
|
|
||||||
// Write them with a regular builder
|
// Write them with a regular builder
|
||||||
writeFrame(connCloseFrame, regularBuilder1);
|
writeFrame(connCloseFrame, regularBuilder1);
|
||||||
writeFrame(maxStreamsFrame, regularBuilder1);
|
writeFrame(QuicSimpleFrame(maxStreamsFrame), regularBuilder1);
|
||||||
writeFrame(pingFrame, regularBuilder1);
|
writeFrame(pingFrame, regularBuilder1);
|
||||||
writeAckFrame(ackMeta, regularBuilder1);
|
writeAckFrame(ackMeta, regularBuilder1);
|
||||||
writeStreamFrameHeader(
|
writeStreamFrameHeader(
|
||||||
@@ -123,44 +123,61 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
|
|||||||
stream->currentReadOffset + stream->flowControlState.windowSize,
|
stream->currentReadOffset + stream->flowControlState.windowSize,
|
||||||
stream->flowControlState.advertisedMaxOffset);
|
stream->flowControlState.advertisedMaxOffset);
|
||||||
for (const auto& frame : packet2.packet.frames) {
|
for (const auto& frame : packet2.packet.frames) {
|
||||||
folly::variant_match(
|
switch (frame.type()) {
|
||||||
frame,
|
case QuicWriteFrame::Type::ConnectionCloseFrame_E: {
|
||||||
[](const ConnectionCloseFrame& closeFrame) {
|
const ConnectionCloseFrame& closeFrame =
|
||||||
|
*frame.asConnectionCloseFrame();
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
TransportErrorCode::FRAME_ENCODING_ERROR, closeFrame.errorCode);
|
TransportErrorCode::FRAME_ENCODING_ERROR, closeFrame.errorCode);
|
||||||
EXPECT_EQ("The sun is in the sky.", closeFrame.reasonPhrase);
|
EXPECT_EQ("The sun is in the sky.", closeFrame.reasonPhrase);
|
||||||
EXPECT_EQ(FrameType::ACK, closeFrame.closingFrameType);
|
EXPECT_EQ(FrameType::ACK, closeFrame.closingFrameType);
|
||||||
},
|
break;
|
||||||
[](const QuicSimpleFrame& simpleFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
|
||||||
|
const QuicSimpleFrame& simpleFrame = *frame.asQuicSimpleFrame();
|
||||||
auto maxStreamFrame = boost::get<MaxStreamsFrame>(simpleFrame);
|
auto maxStreamFrame = boost::get<MaxStreamsFrame>(simpleFrame);
|
||||||
EXPECT_EQ(4321, maxStreamFrame.maxStreams);
|
EXPECT_EQ(4321, maxStreamFrame.maxStreams);
|
||||||
},
|
break;
|
||||||
[](const PingFrame& ping) { EXPECT_EQ(PingFrame(), ping); },
|
}
|
||||||
[](const WriteAckFrame& ack) {
|
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>(10, 100), ack.ackBlocks.front());
|
||||||
EXPECT_EQ(Interval<PacketNum>(200, 1000), ack.ackBlocks.back());
|
EXPECT_EQ(Interval<PacketNum>(200, 1000), ack.ackBlocks.back());
|
||||||
},
|
break;
|
||||||
[&buf, &streamId](const WriteStreamFrame& streamFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
|
const WriteStreamFrame& streamFrame = *frame.asWriteStreamFrame();
|
||||||
EXPECT_EQ(streamId, streamFrame.streamId);
|
EXPECT_EQ(streamId, streamFrame.streamId);
|
||||||
EXPECT_EQ(0, streamFrame.offset);
|
EXPECT_EQ(0, streamFrame.offset);
|
||||||
EXPECT_EQ(buf->computeChainDataLength(), streamFrame.len);
|
EXPECT_EQ(buf->computeChainDataLength(), streamFrame.len);
|
||||||
EXPECT_EQ(true, streamFrame.fin);
|
EXPECT_EQ(true, streamFrame.fin);
|
||||||
},
|
break;
|
||||||
[&cryptoOffset, &cryptoBuf](const WriteCryptoFrame& frame) {
|
}
|
||||||
EXPECT_EQ(frame.offset, cryptoOffset);
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
EXPECT_EQ(frame.len, cryptoBuf->computeChainDataLength());
|
const WriteCryptoFrame& cryptoFrame = *frame.asWriteCryptoFrame();
|
||||||
},
|
EXPECT_EQ(cryptoFrame.offset, cryptoOffset);
|
||||||
[&expectedConnFlowControlValue](const MaxDataFrame& maxData) {
|
EXPECT_EQ(cryptoFrame.len, cryptoBuf->computeChainDataLength());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxDataFrame_E: {
|
||||||
|
const MaxDataFrame& maxData = *frame.asMaxDataFrame();
|
||||||
EXPECT_EQ(expectedConnFlowControlValue, maxData.maximumData);
|
EXPECT_EQ(expectedConnFlowControlValue, maxData.maximumData);
|
||||||
},
|
break;
|
||||||
[&streamId, &expectedStreamFlowControlValue](
|
}
|
||||||
const MaxStreamDataFrame& maxStreamData) {
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
|
const MaxStreamDataFrame& maxStreamData = *frame.asMaxStreamDataFrame();
|
||||||
EXPECT_EQ(streamId, maxStreamData.streamId);
|
EXPECT_EQ(streamId, maxStreamData.streamId);
|
||||||
EXPECT_EQ(expectedStreamFlowControlValue, maxStreamData.maximumData);
|
EXPECT_EQ(expectedStreamFlowControlValue, maxStreamData.maximumData);
|
||||||
},
|
break;
|
||||||
[](const auto&) {
|
}
|
||||||
|
default:
|
||||||
EXPECT_TRUE(false); /* should never happen*/
|
EXPECT_TRUE(false); /* should never happen*/
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(folly::IOBufEqualTo()(*packet1.header, *packet2.header));
|
EXPECT_TRUE(folly::IOBufEqualTo()(*packet1.header, *packet2.header));
|
||||||
// TODO: I don't have a good way to verify body without decode them
|
// 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
|
// rebuilder writes frames to regularBuilder2
|
||||||
EXPECT_EQ(packet1.packet.frames.size(), packet2.packet.frames.size() + 1);
|
EXPECT_EQ(packet1.packet.frames.size(), packet2.packet.frames.size() + 1);
|
||||||
for (const auto& frame : packet2.packet.frames) {
|
for (const auto& frame : packet2.packet.frames) {
|
||||||
folly::variant_match(
|
const WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
|
||||||
frame,
|
if (!streamFrame) {
|
||||||
[&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&) {
|
|
||||||
EXPECT_TRUE(false); /* should never happen*/
|
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));
|
EXPECT_TRUE(folly::IOBufEqualTo()(*packet1.header, *packet2.header));
|
||||||
}
|
}
|
||||||
|
@@ -127,7 +127,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameToEmptyPacket) {
|
|||||||
auto regularPacket = std::move(builtOut.first);
|
auto regularPacket = std::move(builtOut.first);
|
||||||
|
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
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.streamId, streamId);
|
||||||
EXPECT_EQ(resultFrame.offset, offset);
|
EXPECT_EQ(resultFrame.offset, offset);
|
||||||
EXPECT_EQ(resultFrame.len, 10);
|
EXPECT_EQ(resultFrame.len, 10);
|
||||||
@@ -174,7 +174,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameToPartialPacket) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = std::move(builtOut.first);
|
auto regularPacket = std::move(builtOut.first);
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
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.streamId, streamId);
|
||||||
EXPECT_EQ(resultFrame.offset, offset);
|
EXPECT_EQ(resultFrame.offset, offset);
|
||||||
EXPECT_EQ(resultFrame.len, 20);
|
EXPECT_EQ(resultFrame.len, 20);
|
||||||
@@ -241,14 +241,14 @@ TEST_F(QuicWriteCodecTest, WriteTwoStreamFrames) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = std::move(builtOut.first);
|
auto regularPacket = std::move(builtOut.first);
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 2);
|
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.streamId, streamId1);
|
||||||
EXPECT_EQ(resultFrame.offset, offset1);
|
EXPECT_EQ(resultFrame.offset, offset1);
|
||||||
EXPECT_EQ(resultFrame.len, 30);
|
EXPECT_EQ(resultFrame.len, 30);
|
||||||
outputBuf->trimStart(8);
|
outputBuf->trimStart(8);
|
||||||
EXPECT_TRUE(folly::IOBufEqualTo()(inputBuf, outputBuf));
|
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.streamId, streamId2);
|
||||||
EXPECT_EQ(resultFrame2.offset, offset2);
|
EXPECT_EQ(resultFrame2.offset, offset2);
|
||||||
EXPECT_EQ(resultFrame2.len, remainingSpace - 7);
|
EXPECT_EQ(resultFrame2.len, remainingSpace - 7);
|
||||||
@@ -307,7 +307,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamFramePartialData) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
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.streamId, streamId);
|
||||||
EXPECT_EQ(resultFrame.offset, offset);
|
EXPECT_EQ(resultFrame.offset, offset);
|
||||||
EXPECT_EQ(resultFrame.len, 33);
|
EXPECT_EQ(resultFrame.len, 33);
|
||||||
@@ -385,7 +385,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamSpaceForOneByte) {
|
|||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
|
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
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.streamId, streamId);
|
||||||
EXPECT_EQ(resultFrame.offset, offset);
|
EXPECT_EQ(resultFrame.offset, offset);
|
||||||
EXPECT_EQ(resultFrame.len, 1);
|
EXPECT_EQ(resultFrame.len, 1);
|
||||||
@@ -430,7 +430,7 @@ TEST_F(QuicWriteCodecTest, WriteFinToEmptyPacket) {
|
|||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
|
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
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.streamId, streamId);
|
||||||
EXPECT_EQ(resultFrame.offset, offset);
|
EXPECT_EQ(resultFrame.offset, offset);
|
||||||
EXPECT_EQ(inputBuf->computeChainDataLength(), resultFrame.len);
|
EXPECT_EQ(inputBuf->computeChainDataLength(), resultFrame.len);
|
||||||
@@ -592,8 +592,7 @@ TEST_F(QuicWriteCodecTest, AckFrameVeryLargeAckRange) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
EXPECT_EQ(regularPacket.frames.size(), 1);
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(regularPacket.frames.back());
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
||||||
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1);
|
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1);
|
||||||
@@ -640,8 +639,7 @@ TEST_F(QuicWriteCodecTest, WriteSimpleAckFrame) {
|
|||||||
EXPECT_EQ(kDefaultUDPSendPacketLen - 11, pktBuilder.remainingSpaceInPkt());
|
EXPECT_EQ(kDefaultUDPSendPacketLen - 11, pktBuilder.remainingSpaceInPkt());
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(regularPacket.frames.back());
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 2);
|
EXPECT_EQ(ackFrame.ackBlocks.size(), 2);
|
||||||
auto iter = ackFrame.ackBlocks.cbegin();
|
auto iter = ackFrame.ackBlocks.cbegin();
|
||||||
EXPECT_EQ(iter->start, 101);
|
EXPECT_EQ(iter->start, 101);
|
||||||
@@ -675,8 +673,7 @@ TEST_F(QuicWriteCodecTest, WriteAckFrameWillSaveAckDelay) {
|
|||||||
writeAckFrame(meta, pktBuilder);
|
writeAckFrame(meta, pktBuilder);
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(regularPacket.frames.back());
|
|
||||||
EXPECT_EQ(ackDelay, ackFrame.ackDelay);
|
EXPECT_EQ(ackDelay, ackFrame.ackDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,8 +711,7 @@ TEST_F(QuicWriteCodecTest, VerifyNumAckBlocksSizeAccounted) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
EXPECT_EQ(regularPacket.frames.size(), 1);
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(regularPacket.frames.back());
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 64);
|
EXPECT_EQ(ackFrame.ackBlocks.size(), 64);
|
||||||
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().start, 746);
|
EXPECT_EQ(ackFrame.ackBlocks.front().start, 746);
|
||||||
@@ -787,8 +783,7 @@ TEST_F(QuicWriteCodecTest, OnlyAckLargestPacket) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
EXPECT_EQ(regularPacket.frames.size(), 1);
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(regularPacket.frames.back());
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1000);
|
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1000);
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().end, 1000);
|
EXPECT_EQ(ackFrame.ackBlocks.front().end, 1000);
|
||||||
@@ -838,8 +833,7 @@ TEST_F(QuicWriteCodecTest, WriteSomeAckBlocks) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(regularPacket.frames.size(), 1);
|
EXPECT_EQ(regularPacket.frames.size(), 1);
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(regularPacket.frames.back());
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 14);
|
EXPECT_EQ(ackFrame.ackBlocks.size(), 14);
|
||||||
|
|
||||||
// Verify the on wire bytes via decoder:
|
// Verify the on wire bytes via decoder:
|
||||||
@@ -886,8 +880,7 @@ TEST_F(QuicWriteCodecTest, OnlyHasSpaceForFirstAckBlock) {
|
|||||||
EXPECT_EQ(ackFrameWriteResult.bytesWritten, 7);
|
EXPECT_EQ(ackFrameWriteResult.bytesWritten, 7);
|
||||||
EXPECT_EQ(pktBuilder.remainingSpaceInPkt(), 3);
|
EXPECT_EQ(pktBuilder.remainingSpaceInPkt(), 3);
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
WriteAckFrame ackFrame =
|
WriteAckFrame& ackFrame = *builtOut.first.frames.back().asWriteAckFrame();
|
||||||
boost::get<WriteAckFrame>(builtOut.first.frames.back());
|
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
EXPECT_EQ(ackFrame.ackBlocks.size(), 1);
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1000);
|
EXPECT_EQ(ackFrame.ackBlocks.front().start, 1000);
|
||||||
EXPECT_EQ(ackFrame.ackBlocks.front().end, 1000);
|
EXPECT_EQ(ackFrame.ackBlocks.front().end, 1000);
|
||||||
@@ -917,7 +910,7 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamData) {
|
|||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 3);
|
EXPECT_EQ(bytesWritten, 3);
|
||||||
auto& resultMaxStreamDataFrame =
|
auto& resultMaxStreamDataFrame =
|
||||||
boost::get<MaxStreamDataFrame>(regularPacket.frames[0]);
|
*regularPacket.frames[0].asMaxStreamDataFrame();
|
||||||
EXPECT_EQ(id, resultMaxStreamDataFrame.streamId);
|
EXPECT_EQ(id, resultMaxStreamDataFrame.streamId);
|
||||||
EXPECT_EQ(offset, resultMaxStreamDataFrame.maximumData);
|
EXPECT_EQ(offset, resultMaxStreamDataFrame.maximumData);
|
||||||
|
|
||||||
@@ -949,7 +942,7 @@ TEST_F(QuicWriteCodecTest, WriteMaxData) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 3);
|
EXPECT_EQ(bytesWritten, 3);
|
||||||
auto& resultMaxDataFrame = boost::get<MaxDataFrame>(regularPacket.frames[0]);
|
auto& resultMaxDataFrame = *regularPacket.frames[0].asMaxDataFrame();
|
||||||
EXPECT_EQ(1000, resultMaxDataFrame.maximumData);
|
EXPECT_EQ(1000, resultMaxDataFrame.maximumData);
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
@@ -975,7 +968,8 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamId) {
|
|||||||
uint64_t maxStream = i;
|
uint64_t maxStream = i;
|
||||||
bool isBidirectional = true;
|
bool isBidirectional = true;
|
||||||
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
|
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
|
||||||
auto bytesWritten = writeFrame(maxStreamsFrame, pktBuilder);
|
auto bytesWritten =
|
||||||
|
writeFrame(QuicSimpleFrame(maxStreamsFrame), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
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.
|
// 1 byte for the type and up to 2 bytes for the stream count.
|
||||||
EXPECT_EQ(1 + streamCountSize, bytesWritten);
|
EXPECT_EQ(1 + streamCountSize, bytesWritten);
|
||||||
auto& resultMaxStreamIdFrame = boost::get<MaxStreamsFrame>(
|
auto& resultMaxStreamIdFrame = boost::get<MaxStreamsFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(i, resultMaxStreamIdFrame.maxStreams);
|
EXPECT_EQ(i, resultMaxStreamIdFrame.maxStreams);
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
@@ -1003,7 +997,8 @@ TEST_F(QuicWriteCodecTest, WriteUniMaxStreamId) {
|
|||||||
uint64_t maxStream = i;
|
uint64_t maxStream = i;
|
||||||
bool isBidirectional = false;
|
bool isBidirectional = false;
|
||||||
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
|
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
|
||||||
auto bytesWritten = writeFrame(maxStreamsFrame, pktBuilder);
|
auto bytesWritten =
|
||||||
|
writeFrame(QuicSimpleFrame(maxStreamsFrame), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
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.
|
// 1 byte for the type and up to 2 bytes for the stream count.
|
||||||
EXPECT_EQ(1 + streamCountSize, bytesWritten);
|
EXPECT_EQ(1 + streamCountSize, bytesWritten);
|
||||||
auto& resultMaxStreamIdFrame = boost::get<MaxStreamsFrame>(
|
auto& resultMaxStreamIdFrame = boost::get<MaxStreamsFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(i, resultMaxStreamIdFrame.maxStreams);
|
EXPECT_EQ(i, resultMaxStreamIdFrame.maxStreams);
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
@@ -1030,7 +1025,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceForMaxStreamId) {
|
|||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
StreamId maxStream = 0x1234;
|
StreamId maxStream = 0x1234;
|
||||||
MaxStreamsFrame maxStreamIdFrame(maxStream, true);
|
MaxStreamsFrame maxStreamIdFrame(maxStream, true);
|
||||||
EXPECT_EQ(0, writeFrame(maxStreamIdFrame, pktBuilder));
|
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(maxStreamIdFrame), pktBuilder));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicWriteCodecTest, WriteConnClose) {
|
TEST_F(QuicWriteCodecTest, WriteConnClose) {
|
||||||
@@ -1039,14 +1034,15 @@ TEST_F(QuicWriteCodecTest, WriteConnClose) {
|
|||||||
std::string reasonPhrase("You are fired");
|
std::string reasonPhrase("You are fired");
|
||||||
ConnectionCloseFrame connectionCloseFrame(
|
ConnectionCloseFrame connectionCloseFrame(
|
||||||
TransportErrorCode::PROTOCOL_VIOLATION, reasonPhrase);
|
TransportErrorCode::PROTOCOL_VIOLATION, reasonPhrase);
|
||||||
auto connCloseBytesWritten = writeFrame(connectionCloseFrame, pktBuilder);
|
auto connCloseBytesWritten =
|
||||||
|
writeFrame(std::move(connectionCloseFrame), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
// 6 == ErrorCode(2) + FrameType(1) + reasonPhrase-len(2)
|
// 6 == ErrorCode(2) + FrameType(1) + reasonPhrase-len(2)
|
||||||
EXPECT_EQ(4 + reasonPhrase.size(), connCloseBytesWritten);
|
EXPECT_EQ(4 + reasonPhrase.size(), connCloseBytesWritten);
|
||||||
auto& resultConnCloseFrame =
|
auto& resultConnCloseFrame =
|
||||||
boost::get<ConnectionCloseFrame>(regularPacket.frames[0]);
|
*regularPacket.frames[0].asConnectionCloseFrame();
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
TransportErrorCode::PROTOCOL_VIOLATION, resultConnCloseFrame.errorCode);
|
TransportErrorCode::PROTOCOL_VIOLATION, resultConnCloseFrame.errorCode);
|
||||||
EXPECT_EQ("You are fired", resultConnCloseFrame.reasonPhrase);
|
EXPECT_EQ("You are fired", resultConnCloseFrame.reasonPhrase);
|
||||||
@@ -1074,7 +1070,7 @@ TEST_F(QuicWriteCodecTest, DecodeConnCloseLarge) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
auto& resultConnCloseFrame =
|
auto& resultConnCloseFrame =
|
||||||
boost::get<ConnectionCloseFrame>(regularPacket.frames[0]);
|
*regularPacket.frames[0].asConnectionCloseFrame();
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
TransportErrorCode::PROTOCOL_VIOLATION, resultConnCloseFrame.errorCode);
|
TransportErrorCode::PROTOCOL_VIOLATION, resultConnCloseFrame.errorCode);
|
||||||
EXPECT_EQ(resultConnCloseFrame.reasonPhrase, reasonPhrase);
|
EXPECT_EQ(resultConnCloseFrame.reasonPhrase, reasonPhrase);
|
||||||
@@ -1091,7 +1087,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceConnClose) {
|
|||||||
std::string reasonPhrase("You are all fired");
|
std::string reasonPhrase("You are all fired");
|
||||||
ConnectionCloseFrame connCloseFrame(
|
ConnectionCloseFrame connCloseFrame(
|
||||||
TransportErrorCode::PROTOCOL_VIOLATION, reasonPhrase);
|
TransportErrorCode::PROTOCOL_VIOLATION, reasonPhrase);
|
||||||
EXPECT_EQ(0, writeFrame(connCloseFrame, pktBuilder));
|
EXPECT_EQ(0, writeFrame(std::move(connCloseFrame), pktBuilder));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
|
TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
|
||||||
@@ -1101,12 +1097,12 @@ TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
|
|||||||
reasonPhrase.resize(kMaxReasonPhraseLength + 10);
|
reasonPhrase.resize(kMaxReasonPhraseLength + 10);
|
||||||
ApplicationCloseFrame applicationCloseFrame(
|
ApplicationCloseFrame applicationCloseFrame(
|
||||||
GenericApplicationErrorCode::UNKNOWN, reasonPhrase);
|
GenericApplicationErrorCode::UNKNOWN, reasonPhrase);
|
||||||
writeFrame(applicationCloseFrame, pktBuilder);
|
writeFrame(std::move(applicationCloseFrame), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
auto& resultAppCloseFrame =
|
auto& resultAppCloseFrame =
|
||||||
boost::get<ApplicationCloseFrame>(regularPacket.frames[0]);
|
*regularPacket.frames[0].asApplicationCloseFrame();
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
GenericApplicationErrorCode::UNKNOWN, resultAppCloseFrame.errorCode);
|
GenericApplicationErrorCode::UNKNOWN, resultAppCloseFrame.errorCode);
|
||||||
EXPECT_EQ(resultAppCloseFrame.reasonPhrase, reasonPhrase);
|
EXPECT_EQ(resultAppCloseFrame.reasonPhrase, reasonPhrase);
|
||||||
@@ -1119,13 +1115,12 @@ TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
|
|||||||
TEST_F(QuicWriteCodecTest, WritePing) {
|
TEST_F(QuicWriteCodecTest, WritePing) {
|
||||||
MockQuicPacketBuilder pktBuilder;
|
MockQuicPacketBuilder pktBuilder;
|
||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
PingFrame pingFrame;
|
auto pingBytesWritten = writeFrame(PingFrame(), pktBuilder);
|
||||||
auto pingBytesWritten = writeFrame(pingFrame, pktBuilder);
|
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(1, pingBytesWritten);
|
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);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
folly::io::Cursor cursor(wireBuf.get());
|
folly::io::Cursor cursor(wireBuf.get());
|
||||||
@@ -1140,20 +1135,18 @@ TEST_F(QuicWriteCodecTest, NoSpaceForPing) {
|
|||||||
MockQuicPacketBuilder pktBuilder;
|
MockQuicPacketBuilder pktBuilder;
|
||||||
pktBuilder.remaining_ = 0;
|
pktBuilder.remaining_ = 0;
|
||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
PingFrame pingFrame;
|
EXPECT_EQ(0, writeFrame(PingFrame(), pktBuilder));
|
||||||
EXPECT_EQ(0, writeFrame(pingFrame, pktBuilder));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicWriteCodecTest, WritePadding) {
|
TEST_F(QuicWriteCodecTest, WritePadding) {
|
||||||
MockQuicPacketBuilder pktBuilder;
|
MockQuicPacketBuilder pktBuilder;
|
||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
PaddingFrame paddingFrame;
|
auto paddingBytesWritten = writeFrame(PaddingFrame(), pktBuilder);
|
||||||
auto paddingBytesWritten = writeFrame(paddingFrame, pktBuilder);
|
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(1, paddingBytesWritten);
|
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);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
folly::io::Cursor cursor(wireBuf.get());
|
folly::io::Cursor cursor(wireBuf.get());
|
||||||
@@ -1183,7 +1176,7 @@ TEST_F(QuicWriteCodecTest, WriteStreamBlocked) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(blockedBytesWritten, 7);
|
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);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
folly::io::Cursor cursor(wireBuf.get());
|
folly::io::Cursor cursor(wireBuf.get());
|
||||||
@@ -1217,8 +1210,7 @@ TEST_F(QuicWriteCodecTest, WriteRstStream) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(13, rstStreamBytesWritten);
|
EXPECT_EQ(13, rstStreamBytesWritten);
|
||||||
auto& resultRstStreamFrame =
|
auto& resultRstStreamFrame = *regularPacket.frames[0].asRstStreamFrame();
|
||||||
boost::get<RstStreamFrame>(regularPacket.frames[0]);
|
|
||||||
EXPECT_EQ(errorCode, resultRstStreamFrame.errorCode);
|
EXPECT_EQ(errorCode, resultRstStreamFrame.errorCode);
|
||||||
EXPECT_EQ(id, resultRstStreamFrame.streamId);
|
EXPECT_EQ(id, resultRstStreamFrame.streamId);
|
||||||
EXPECT_EQ(offset, resultRstStreamFrame.offset);
|
EXPECT_EQ(offset, resultRstStreamFrame.offset);
|
||||||
@@ -1255,7 +1247,7 @@ TEST_F(QuicWriteCodecTest, WriteBlockedFrame) {
|
|||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 5);
|
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);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
folly::io::Cursor cursor(wireBuf.get());
|
folly::io::Cursor cursor(wireBuf.get());
|
||||||
@@ -1279,13 +1271,13 @@ TEST_F(QuicWriteCodecTest, WriteStreamIdNeeded) {
|
|||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
StreamId blockedStreamId = 0x211;
|
StreamId blockedStreamId = 0x211;
|
||||||
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
|
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
|
||||||
auto bytesWritten = writeFrame(streamIdNeeded, pktBuilder);
|
auto bytesWritten = writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 3);
|
EXPECT_EQ(bytesWritten, 3);
|
||||||
EXPECT_NO_THROW(boost::get<MaxStreamsFrame>(
|
EXPECT_NO_THROW(boost::get<MaxStreamsFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0])));
|
*regularPacket.frames[0].asQuicSimpleFrame()));
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
folly::io::Cursor cursor(wireBuf.get());
|
folly::io::Cursor cursor(wireBuf.get());
|
||||||
@@ -1302,7 +1294,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceForStreamIdNeeded) {
|
|||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
StreamId blockedStreamId = 0x211;
|
StreamId blockedStreamId = 0x211;
|
||||||
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
|
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
|
||||||
EXPECT_EQ(0, writeFrame(streamIdNeeded, pktBuilder));
|
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicWriteCodecTest, WriteNewConnId) {
|
TEST_F(QuicWriteCodecTest, WriteNewConnId) {
|
||||||
@@ -1311,13 +1303,13 @@ TEST_F(QuicWriteCodecTest, WriteNewConnId) {
|
|||||||
StatelessResetToken token;
|
StatelessResetToken token;
|
||||||
memset(token.data(), 'a', token.size());
|
memset(token.data(), 'a', token.size());
|
||||||
NewConnectionIdFrame newConnId(1, 0, getTestConnectionId(), token);
|
NewConnectionIdFrame newConnId(1, 0, getTestConnectionId(), token);
|
||||||
auto bytesWritten = writeFrame(newConnId, pktBuilder);
|
auto bytesWritten = writeFrame(QuicSimpleFrame(newConnId), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 28);
|
EXPECT_EQ(bytesWritten, 28);
|
||||||
auto& resultNewConnIdFrame = boost::get<NewConnectionIdFrame>(
|
auto& resultNewConnIdFrame = boost::get<NewConnectionIdFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(resultNewConnIdFrame.sequenceNumber, 1);
|
EXPECT_EQ(resultNewConnIdFrame.sequenceNumber, 1);
|
||||||
EXPECT_EQ(resultNewConnIdFrame.retirePriorTo, 0);
|
EXPECT_EQ(resultNewConnIdFrame.retirePriorTo, 0);
|
||||||
EXPECT_EQ(resultNewConnIdFrame.connectionId, getTestConnectionId());
|
EXPECT_EQ(resultNewConnIdFrame.connectionId, getTestConnectionId());
|
||||||
@@ -1338,13 +1330,13 @@ TEST_F(QuicWriteCodecTest, WriteRetireConnId) {
|
|||||||
MockQuicPacketBuilder pktBuilder;
|
MockQuicPacketBuilder pktBuilder;
|
||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
RetireConnectionIdFrame retireConnId(3);
|
RetireConnectionIdFrame retireConnId(3);
|
||||||
auto bytesWritten = writeFrame(retireConnId, pktBuilder);
|
auto bytesWritten = writeFrame(QuicSimpleFrame(retireConnId), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 2);
|
EXPECT_EQ(bytesWritten, 2);
|
||||||
auto resultRetireConnIdFrame = boost::get<RetireConnectionIdFrame>(
|
auto resultRetireConnIdFrame = boost::get<RetireConnectionIdFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(resultRetireConnIdFrame.sequenceNumber, 3);
|
EXPECT_EQ(resultRetireConnIdFrame.sequenceNumber, 3);
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
@@ -1385,7 +1377,7 @@ TEST_F(QuicWriteCodecTest, NoSpaceForNewConnId) {
|
|||||||
setupCommonExpects(pktBuilder);
|
setupCommonExpects(pktBuilder);
|
||||||
NewConnectionIdFrame newConnId(
|
NewConnectionIdFrame newConnId(
|
||||||
1, 0, getTestConnectionId(), StatelessResetToken());
|
1, 0, getTestConnectionId(), StatelessResetToken());
|
||||||
EXPECT_EQ(0, writeFrame(newConnId, pktBuilder));
|
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(newConnId), pktBuilder));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicWriteCodecTest, WriteExpiredStreamDataFrame) {
|
TEST_F(QuicWriteCodecTest, WriteExpiredStreamDataFrame) {
|
||||||
@@ -1394,13 +1386,14 @@ TEST_F(QuicWriteCodecTest, WriteExpiredStreamDataFrame) {
|
|||||||
StreamId id = 10;
|
StreamId id = 10;
|
||||||
uint64_t offset = 0x08;
|
uint64_t offset = 0x08;
|
||||||
ExpiredStreamDataFrame expiredStreamDataFrame(id, offset);
|
ExpiredStreamDataFrame expiredStreamDataFrame(id, offset);
|
||||||
auto bytesWritten = writeFrame(expiredStreamDataFrame, pktBuilder);
|
auto bytesWritten =
|
||||||
|
writeFrame(QuicSimpleFrame(expiredStreamDataFrame), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 4);
|
EXPECT_EQ(bytesWritten, 4);
|
||||||
auto result = boost::get<ExpiredStreamDataFrame>(
|
auto result = boost::get<ExpiredStreamDataFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(id, result.streamId);
|
EXPECT_EQ(id, result.streamId);
|
||||||
EXPECT_EQ(offset, result.minimumStreamOffset);
|
EXPECT_EQ(offset, result.minimumStreamOffset);
|
||||||
|
|
||||||
@@ -1424,13 +1417,14 @@ TEST_F(QuicWriteCodecTest, WriteMinStreamDataFrame) {
|
|||||||
uint64_t maximumData = 0x64;
|
uint64_t maximumData = 0x64;
|
||||||
uint64_t offset = 0x08;
|
uint64_t offset = 0x08;
|
||||||
MinStreamDataFrame minStreamDataFrame(id, maximumData, offset);
|
MinStreamDataFrame minStreamDataFrame(id, maximumData, offset);
|
||||||
auto bytesWritten = writeFrame(minStreamDataFrame, pktBuilder);
|
auto bytesWritten =
|
||||||
|
writeFrame(QuicSimpleFrame(minStreamDataFrame), pktBuilder);
|
||||||
|
|
||||||
auto builtOut = std::move(pktBuilder).buildPacket();
|
auto builtOut = std::move(pktBuilder).buildPacket();
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
EXPECT_EQ(bytesWritten, 6);
|
EXPECT_EQ(bytesWritten, 6);
|
||||||
auto result = boost::get<MinStreamDataFrame>(
|
auto result = boost::get<MinStreamDataFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(id, result.streamId);
|
EXPECT_EQ(id, result.streamId);
|
||||||
EXPECT_EQ(maximumData, result.maximumData);
|
EXPECT_EQ(maximumData, result.maximumData);
|
||||||
EXPECT_EQ(offset, result.minimumStreamOffset);
|
EXPECT_EQ(offset, result.minimumStreamOffset);
|
||||||
@@ -1461,7 +1455,7 @@ TEST_F(QuicWriteCodecTest, WritePathChallenge) {
|
|||||||
|
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
auto result = boost::get<PathChallengeFrame>(
|
auto result = boost::get<PathChallengeFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(result.pathData, pathData);
|
EXPECT_EQ(result.pathData, pathData);
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
@@ -1486,7 +1480,7 @@ TEST_F(QuicWriteCodecTest, WritePathResponse) {
|
|||||||
|
|
||||||
auto regularPacket = builtOut.first;
|
auto regularPacket = builtOut.first;
|
||||||
auto result = boost::get<PathResponseFrame>(
|
auto result = boost::get<PathResponseFrame>(
|
||||||
boost::get<QuicSimpleFrame>(regularPacket.frames[0]));
|
*regularPacket.frames[0].asQuicSimpleFrame());
|
||||||
EXPECT_EQ(result.pathData, pathData);
|
EXPECT_EQ(result.pathData, pathData);
|
||||||
|
|
||||||
auto wireBuf = std::move(builtOut.second);
|
auto wireBuf = std::move(builtOut.second);
|
||||||
|
@@ -35,6 +35,11 @@ namespace quic {
|
|||||||
new (&X##_) X(std::move(x)); \
|
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) \
|
#define UNION_MOVE_CASES(X, other) \
|
||||||
case Type::X##_E: \
|
case Type::X##_E: \
|
||||||
new (&X##_) X(std::move(other.X##_)); \
|
new (&X##_) X(std::move(other.X##_)); \
|
||||||
@@ -56,6 +61,8 @@ namespace quic {
|
|||||||
\
|
\
|
||||||
X(UNION_CTORS, NAME) \
|
X(UNION_CTORS, NAME) \
|
||||||
\
|
\
|
||||||
|
X(UNION_COPY_CTORS, NAME) \
|
||||||
|
\
|
||||||
NAME(NAME&& other) { \
|
NAME(NAME&& other) { \
|
||||||
switch (other.type_) { X(UNION_MOVE_CASES, other) } \
|
switch (other.type_) { X(UNION_MOVE_CASES, other) } \
|
||||||
type_ = other.type_; \
|
type_ = other.type_; \
|
||||||
|
@@ -70,8 +70,12 @@ PacketNum rstStreamAndSendPacket(
|
|||||||
conn.transportSettings.writeConnectionDataPacketsLimit);
|
conn.transportSettings.writeConnectionDataPacketsLimit);
|
||||||
|
|
||||||
for (const auto& packet : conn.outstandingPackets) {
|
for (const auto& packet : conn.outstandingPackets) {
|
||||||
for (const auto& frame : all_frames<RstStreamFrame>(packet.packet.frames)) {
|
for (const auto& frame : packet.packet.frames) {
|
||||||
if (frame.streamId == stream.id) {
|
auto rstFrame = frame.asRstStreamFrame();
|
||||||
|
if (!rstFrame) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (rstFrame->streamId == stream.id) {
|
||||||
return packet.packet.header.getPacketSequenceNum();
|
return packet.packet.header.getPacketSequenceNum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -276,15 +276,14 @@ auto findFrameInPacketFunc() {
|
|||||||
return [&](auto& p) {
|
return [&](auto& p) {
|
||||||
return std::find_if(
|
return std::find_if(
|
||||||
p.packet.frames.begin(), p.packet.frames.end(), [&](auto& f) {
|
p.packet.frames.begin(), p.packet.frames.end(), [&](auto& f) {
|
||||||
|
QuicSimpleFrame* simpleFrame = f.asQuicSimpleFrame();
|
||||||
|
if (!simpleFrame) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return folly::variant_match(
|
return folly::variant_match(
|
||||||
f,
|
*simpleFrame,
|
||||||
[&](QuicSimpleFrame& s) {
|
|
||||||
return folly::variant_match(
|
|
||||||
s,
|
|
||||||
[&](FrameType&) { return true; },
|
[&](FrameType&) { return true; },
|
||||||
[&](auto&) { return false; });
|
[&](auto&) { return false; });
|
||||||
},
|
|
||||||
[&](auto&) { return false; });
|
|
||||||
}) != p.packet.frames.end();
|
}) != p.packet.frames.end();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -195,62 +195,88 @@ std::unique_ptr<QLogPacketEvent> QLogger::createPacketEvent(
|
|||||||
uint64_t numPaddingFrames = 0;
|
uint64_t numPaddingFrames = 0;
|
||||||
// looping through the packet to store logs created from frames in the packet
|
// looping through the packet to store logs created from frames in the packet
|
||||||
for (const auto& quicFrame : writePacket.frames) {
|
for (const auto& quicFrame : writePacket.frames) {
|
||||||
folly::variant_match(
|
switch (quicFrame.type()) {
|
||||||
quicFrame,
|
case QuicWriteFrame::Type::PaddingFrame_E:
|
||||||
[&](const PaddingFrame& /* unused */) { ++numPaddingFrames; },
|
++numPaddingFrames;
|
||||||
[&](const RstStreamFrame& frame) {
|
break;
|
||||||
|
case QuicWriteFrame::Type::RstStreamFrame_E: {
|
||||||
|
const RstStreamFrame& frame = *quicFrame.asRstStreamFrame();
|
||||||
event->frames.push_back(std::make_unique<RstStreamFrameLog>(
|
event->frames.push_back(std::make_unique<RstStreamFrameLog>(
|
||||||
frame.streamId, frame.errorCode, frame.offset));
|
frame.streamId, frame.errorCode, frame.offset));
|
||||||
},
|
break;
|
||||||
[&](const ConnectionCloseFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::ConnectionCloseFrame_E: {
|
||||||
|
const ConnectionCloseFrame& frame = *quicFrame.asConnectionCloseFrame();
|
||||||
event->frames.push_back(std::make_unique<ConnectionCloseFrameLog>(
|
event->frames.push_back(std::make_unique<ConnectionCloseFrameLog>(
|
||||||
frame.errorCode, frame.reasonPhrase, frame.closingFrameType));
|
frame.errorCode, frame.reasonPhrase, frame.closingFrameType));
|
||||||
},
|
break;
|
||||||
[&](const ApplicationCloseFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::ApplicationCloseFrame_E: {
|
||||||
|
const ApplicationCloseFrame& frame =
|
||||||
|
*quicFrame.asApplicationCloseFrame();
|
||||||
event->frames.push_back(std::make_unique<ApplicationCloseFrameLog>(
|
event->frames.push_back(std::make_unique<ApplicationCloseFrameLog>(
|
||||||
frame.errorCode, frame.reasonPhrase));
|
frame.errorCode, frame.reasonPhrase));
|
||||||
},
|
break;
|
||||||
[&](const MaxDataFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxDataFrame_E: {
|
||||||
|
const MaxDataFrame& frame = *quicFrame.asMaxDataFrame();
|
||||||
event->frames.push_back(
|
event->frames.push_back(
|
||||||
std::make_unique<MaxDataFrameLog>(frame.maximumData));
|
std::make_unique<MaxDataFrameLog>(frame.maximumData));
|
||||||
},
|
break;
|
||||||
[&](const MaxStreamDataFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
|
const MaxStreamDataFrame& frame = *quicFrame.asMaxStreamDataFrame();
|
||||||
event->frames.push_back(std::make_unique<MaxStreamDataFrameLog>(
|
event->frames.push_back(std::make_unique<MaxStreamDataFrameLog>(
|
||||||
frame.streamId, frame.maximumData));
|
frame.streamId, frame.maximumData));
|
||||||
},
|
break;
|
||||||
[&](const StreamsBlockedFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::StreamsBlockedFrame_E: {
|
||||||
|
const StreamsBlockedFrame& frame = *quicFrame.asStreamsBlockedFrame();
|
||||||
event->frames.push_back(std::make_unique<StreamsBlockedFrameLog>(
|
event->frames.push_back(std::make_unique<StreamsBlockedFrameLog>(
|
||||||
frame.streamLimit, frame.isForBidirectional));
|
frame.streamLimit, frame.isForBidirectional));
|
||||||
},
|
break;
|
||||||
[&](const PingFrame& /* unused */) {
|
}
|
||||||
|
case QuicWriteFrame::Type::PingFrame_E:
|
||||||
event->frames.push_back(std::make_unique<PingFrameLog>());
|
event->frames.push_back(std::make_unique<PingFrameLog>());
|
||||||
},
|
break;
|
||||||
[&](const DataBlockedFrame& frame) {
|
case QuicWriteFrame::Type::DataBlockedFrame_E: {
|
||||||
|
const DataBlockedFrame& frame = *quicFrame.asDataBlockedFrame();
|
||||||
event->frames.push_back(
|
event->frames.push_back(
|
||||||
std::make_unique<DataBlockedFrameLog>(frame.dataLimit));
|
std::make_unique<DataBlockedFrameLog>(frame.dataLimit));
|
||||||
},
|
break;
|
||||||
[&](const StreamDataBlockedFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
|
||||||
|
const StreamDataBlockedFrame& frame = *quicFrame.asStreamDataBlockedFrame();
|
||||||
event->frames.push_back(std::make_unique<StreamDataBlockedFrameLog>(
|
event->frames.push_back(std::make_unique<StreamDataBlockedFrameLog>(
|
||||||
frame.streamId, frame.dataLimit));
|
frame.streamId, frame.dataLimit));
|
||||||
},
|
break;
|
||||||
[&](const WriteAckFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteAckFrame_E: {
|
||||||
|
const WriteAckFrame& frame = *quicFrame.asWriteAckFrame();
|
||||||
event->frames.push_back(std::make_unique<WriteAckFrameLog>(
|
event->frames.push_back(std::make_unique<WriteAckFrameLog>(
|
||||||
frame.ackBlocks, frame.ackDelay));
|
frame.ackBlocks, frame.ackDelay));
|
||||||
},
|
break;
|
||||||
[&](const WriteStreamFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
|
const WriteStreamFrame& frame = *quicFrame.asWriteStreamFrame();
|
||||||
event->frames.push_back(std::make_unique<StreamFrameLog>(
|
event->frames.push_back(std::make_unique<StreamFrameLog>(
|
||||||
frame.streamId, frame.offset, frame.len, frame.fin));
|
frame.streamId, frame.offset, frame.len, frame.fin));
|
||||||
},
|
break;
|
||||||
[&](const WriteCryptoFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
|
const WriteCryptoFrame& frame = *quicFrame.asWriteCryptoFrame();
|
||||||
event->frames.push_back(
|
event->frames.push_back(
|
||||||
std::make_unique<CryptoFrameLog>(frame.offset, frame.len));
|
std::make_unique<CryptoFrameLog>(frame.offset, frame.len));
|
||||||
},
|
break;
|
||||||
[&](const QuicSimpleFrame& simpleFrame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
|
||||||
|
const QuicSimpleFrame& simpleFrame = *quicFrame.asQuicSimpleFrame();
|
||||||
addQuicSimpleFrameToEvent(event.get(), simpleFrame);
|
addQuicSimpleFrameToEvent(event.get(), simpleFrame);
|
||||||
},
|
break;
|
||||||
[&](const auto& /* unused */) {
|
}
|
||||||
// Ignore other frames.
|
default:
|
||||||
});
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (numPaddingFrames > 0) {
|
if (numPaddingFrames > 0) {
|
||||||
event->frames.push_back(
|
event->frames.push_back(
|
||||||
|
@@ -57,9 +57,9 @@ void markPacketLoss(
|
|||||||
bool processed,
|
bool processed,
|
||||||
PacketNum currentPacketNum) {
|
PacketNum currentPacketNum) {
|
||||||
for (auto& packetFrame : packet.frames) {
|
for (auto& packetFrame : packet.frames) {
|
||||||
folly::variant_match(
|
switch (packetFrame.type()) {
|
||||||
packetFrame,
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E: {
|
||||||
[&](MaxStreamDataFrame& frame) {
|
MaxStreamDataFrame& frame = *packetFrame.asMaxStreamDataFrame();
|
||||||
// For all other frames, we process it if it's not from a clone
|
// 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.
|
// packet, or if the clone and its siblings have never been processed.
|
||||||
// But for both MaxData and MaxStreamData, clone and its siblings may
|
// 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.
|
// since newer value is already sent in later packets.
|
||||||
auto stream = conn.streamManager->getStream(frame.streamId);
|
auto stream = conn.streamManager->getStream(frame.streamId);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
// TODO: check for the stream is in Open or HalfClosedLocal state, the
|
// TODO: check for the stream is in Open or HalfClosedLocal state, the
|
||||||
// peer doesn't need a flow control update in these cases.
|
// peer doesn't need a flow control update in these cases.
|
||||||
if (stream->latestMaxStreamDataPacket == currentPacketNum) {
|
if (stream->latestMaxStreamDataPacket == currentPacketNum) {
|
||||||
onStreamWindowUpdateLost(*stream);
|
onStreamWindowUpdateLost(*stream);
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
[&](MaxDataFrame&) {
|
}
|
||||||
|
case QuicWriteFrame::Type::MaxDataFrame_E: {
|
||||||
if (conn.latestMaxDataPacket == currentPacketNum) {
|
if (conn.latestMaxDataPacket == currentPacketNum) {
|
||||||
onConnWindowUpdateLost(conn);
|
onConnWindowUpdateLost(conn);
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
|
}
|
||||||
// For other frame types, we only process them if the packet is not a
|
// For other frame types, we only process them if the packet is not a
|
||||||
// processed clone.
|
// processed clone.
|
||||||
[&](WriteStreamFrame& frame) {
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
|
WriteStreamFrame frame = *packetFrame.asWriteStreamFrame();
|
||||||
if (processed) {
|
if (processed) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
auto stream = conn.streamManager->getStream(frame.streamId);
|
auto stream = conn.streamManager->getStream(frame.streamId);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
auto bufferItr = std::lower_bound(
|
auto bufferItr = std::lower_bound(
|
||||||
stream->retransmissionBuffer.begin(),
|
stream->retransmissionBuffer.begin(),
|
||||||
@@ -103,12 +106,12 @@ void markPacketLoss(
|
|||||||
// It's possible that the stream was reset or data on the stream was
|
// 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
|
// skipped while we discovered that its packet was lost so we might
|
||||||
// not have the offset.
|
// not have the offset.
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
// The original rxmt offset might have been bumped up after it was
|
// The original rxmt offset might have been bumped up after it was
|
||||||
// shrunk due to egress partially reliable skip.
|
// shrunk due to egress partially reliable skip.
|
||||||
if (!ackFrameMatchesRetransmitBuffer(*stream, frame, *bufferItr)) {
|
if (!ackFrameMatchesRetransmitBuffer(*stream, frame, *bufferItr)) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
stream->lossBuffer.insert(
|
stream->lossBuffer.insert(
|
||||||
std::upper_bound(
|
std::upper_bound(
|
||||||
@@ -121,16 +124,16 @@ void markPacketLoss(
|
|||||||
std::move(*bufferItr));
|
std::move(*bufferItr));
|
||||||
stream->retransmissionBuffer.erase(bufferItr);
|
stream->retransmissionBuffer.erase(bufferItr);
|
||||||
conn.streamManager->updateLossStreams(*stream);
|
conn.streamManager->updateLossStreams(*stream);
|
||||||
},
|
break;
|
||||||
[&](WriteCryptoFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
|
WriteCryptoFrame& frame = *packetFrame.asWriteCryptoFrame();
|
||||||
if (processed) {
|
if (processed) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
auto protectionType = packet.header.getProtectionType();
|
auto protectionType = packet.header.getProtectionType();
|
||||||
auto encryptionLevel =
|
auto encryptionLevel = protectionTypeToEncryptionLevel(protectionType);
|
||||||
protectionTypeToEncryptionLevel(protectionType);
|
auto cryptoStream = getCryptoStream(*conn.cryptoState, encryptionLevel);
|
||||||
auto cryptoStream =
|
|
||||||
getCryptoStream(*conn.cryptoState, encryptionLevel);
|
|
||||||
|
|
||||||
auto bufferItr = std::lower_bound(
|
auto bufferItr = std::lower_bound(
|
||||||
cryptoStream->retransmissionBuffer.begin(),
|
cryptoStream->retransmissionBuffer.begin(),
|
||||||
@@ -142,7 +145,7 @@ void markPacketLoss(
|
|||||||
if (bufferItr == cryptoStream->retransmissionBuffer.end()) {
|
if (bufferItr == cryptoStream->retransmissionBuffer.end()) {
|
||||||
// It's possible that the stream was reset while we discovered that
|
// It's possible that the stream was reset while we discovered that
|
||||||
// it's packet was lost so we might not have the offset.
|
// it's packet was lost so we might not have the offset.
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
DCHECK_EQ(bufferItr->offset, frame.offset);
|
DCHECK_EQ(bufferItr->offset, frame.offset);
|
||||||
cryptoStream->lossBuffer.insert(
|
cryptoStream->lossBuffer.insert(
|
||||||
@@ -155,40 +158,48 @@ void markPacketLoss(
|
|||||||
}),
|
}),
|
||||||
std::move(*bufferItr));
|
std::move(*bufferItr));
|
||||||
cryptoStream->retransmissionBuffer.erase(bufferItr);
|
cryptoStream->retransmissionBuffer.erase(bufferItr);
|
||||||
},
|
break;
|
||||||
[&](RstStreamFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::RstStreamFrame_E: {
|
||||||
|
RstStreamFrame& frame = *packetFrame.asRstStreamFrame();
|
||||||
if (processed) {
|
if (processed) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
auto stream = conn.streamManager->getStream(frame.streamId);
|
auto stream = conn.streamManager->getStream(frame.streamId);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
// If the stream is dead, ignore the retransmissions of the rst
|
// If the stream is dead, ignore the retransmissions of the rst
|
||||||
// stream.
|
// stream.
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
// Add the lost RstStreamFrame back to pendingEvents:
|
// Add the lost RstStreamFrame back to pendingEvents:
|
||||||
conn.pendingEvents.resets.insert({frame.streamId, frame});
|
conn.pendingEvents.resets.insert({frame.streamId, frame});
|
||||||
},
|
break;
|
||||||
[&](StreamDataBlockedFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
|
||||||
|
StreamDataBlockedFrame& frame = *packetFrame.asStreamDataBlockedFrame();
|
||||||
if (processed) {
|
if (processed) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
auto stream = conn.streamManager->getStream(frame.streamId);
|
auto stream = conn.streamManager->getStream(frame.streamId);
|
||||||
// TODO: check for retransmittable
|
// TODO: check for retransmittable
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
onBlockedLost(*stream);
|
onBlockedLost(*stream);
|
||||||
},
|
break;
|
||||||
[&](QuicSimpleFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::QuicSimpleFrame_E: {
|
||||||
|
QuicSimpleFrame& frame = *packetFrame.asQuicSimpleFrame();
|
||||||
if (processed) {
|
if (processed) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
updateSimpleFrameOnPacketLoss(conn, frame);
|
updateSimpleFrameOnPacketLoss(conn, frame);
|
||||||
},
|
break;
|
||||||
[&](auto&) {
|
}
|
||||||
|
default:
|
||||||
// ignore the rest of the frames.
|
// ignore the rest of the frames.
|
||||||
});
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
@@ -696,10 +696,14 @@ TEST_F(QuicLossFunctionsTest, TestMarkRstLoss) {
|
|||||||
auto& packet2 =
|
auto& packet2 =
|
||||||
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
|
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
|
||||||
bool rstFound = false;
|
bool rstFound = false;
|
||||||
for (auto& frame : all_frames<RstStreamFrame>(packet2.frames)) {
|
for (auto& frame : packet2.frames) {
|
||||||
EXPECT_EQ(stream->id, frame.streamId);
|
auto resetFrame = frame.asRstStreamFrame();
|
||||||
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, frame.errorCode);
|
if (!resetFrame) {
|
||||||
EXPECT_EQ(currentOffset, frame.offset);
|
continue;
|
||||||
|
}
|
||||||
|
EXPECT_EQ(stream->id, resetFrame->streamId);
|
||||||
|
EXPECT_EQ(GenericApplicationErrorCode::UNKNOWN, resetFrame->errorCode);
|
||||||
|
EXPECT_EQ(currentOffset, resetFrame->offset);
|
||||||
rstFound = true;
|
rstFound = true;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(rstFound);
|
EXPECT_TRUE(rstFound);
|
||||||
@@ -1235,12 +1239,19 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
|
|||||||
for (const auto& frame :
|
for (const auto& frame :
|
||||||
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
||||||
->packet.frames) {
|
->packet.frames) {
|
||||||
folly::variant_match(
|
switch (frame.type()) {
|
||||||
frame,
|
case QuicWriteFrame::Type::WriteStreamFrame_E:
|
||||||
[&](const WriteStreamFrame&) { streamDataCounter++; },
|
streamDataCounter++;
|
||||||
[&](const MaxStreamDataFrame&) { streamWindowUpdateCounter++; },
|
break;
|
||||||
[&](const MaxDataFrame&) { connWindowUpdateCounter++; },
|
case QuicWriteFrame::Type::MaxStreamDataFrame_E:
|
||||||
[](const auto&) { ASSERT_TRUE(false); });
|
streamWindowUpdateCounter++;
|
||||||
|
break;
|
||||||
|
case QuicWriteFrame::Type::MaxDataFrame_E:
|
||||||
|
connWindowUpdateCounter++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CHECK(false) << "unexpected frame=" << (int)frame.type();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(1, streamDataCounter);
|
EXPECT_EQ(1, streamDataCounter);
|
||||||
EXPECT_EQ(1, streamWindowUpdateCounter);
|
EXPECT_EQ(1, streamWindowUpdateCounter);
|
||||||
|
@@ -756,9 +756,10 @@ void onServerReadDataFromOpen(
|
|||||||
[&](const OutstandingPacket&,
|
[&](const OutstandingPacket&,
|
||||||
const QuicWriteFrame& packetFrame,
|
const QuicWriteFrame& packetFrame,
|
||||||
const ReadAckFrame&) {
|
const ReadAckFrame&) {
|
||||||
folly::variant_match(
|
switch (packetFrame.type()) {
|
||||||
packetFrame,
|
case QuicWriteFrame::Type::WriteStreamFrame_E: {
|
||||||
[&](const WriteStreamFrame& frame) {
|
const WriteStreamFrame& frame =
|
||||||
|
*packetFrame.asWriteStreamFrame();
|
||||||
VLOG(4)
|
VLOG(4)
|
||||||
<< "Server received ack for stream=" << frame.streamId
|
<< "Server received ack for stream=" << frame.streamId
|
||||||
<< " offset=" << frame.offset << " fin=" << frame.fin
|
<< " offset=" << frame.offset << " fin=" << frame.fin
|
||||||
@@ -771,32 +772,40 @@ void onServerReadDataFromOpen(
|
|||||||
*ackedStream,
|
*ackedStream,
|
||||||
StreamEvents::AckStreamFrame(frame));
|
StreamEvents::AckStreamFrame(frame));
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
[&](const WriteCryptoFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteCryptoFrame_E: {
|
||||||
|
const WriteCryptoFrame& frame =
|
||||||
|
*packetFrame.asWriteCryptoFrame();
|
||||||
auto cryptoStream =
|
auto cryptoStream =
|
||||||
getCryptoStream(*conn.cryptoState, encryptionLevel);
|
getCryptoStream(*conn.cryptoState, encryptionLevel);
|
||||||
processCryptoStreamAck(
|
processCryptoStreamAck(
|
||||||
*cryptoStream, frame.offset, frame.len);
|
*cryptoStream, frame.offset, frame.len);
|
||||||
},
|
break;
|
||||||
[&](const RstStreamFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::RstStreamFrame_E: {
|
||||||
|
const RstStreamFrame& frame = *packetFrame.asRstStreamFrame();
|
||||||
VLOG(4) << "Server received ack for reset stream="
|
VLOG(4) << "Server received ack for reset stream="
|
||||||
<< frame.streamId << " " << conn;
|
<< frame.streamId << " " << conn;
|
||||||
auto stream =
|
auto stream = conn.streamManager->getStream(frame.streamId);
|
||||||
conn.streamManager->getStream(frame.streamId);
|
|
||||||
if (stream) {
|
if (stream) {
|
||||||
invokeStreamSendStateMachine(
|
invokeStreamSendStateMachine(
|
||||||
conn, *stream, StreamEvents::RstAck(frame));
|
conn, *stream, StreamEvents::RstAck(frame));
|
||||||
}
|
}
|
||||||
},
|
break;
|
||||||
[&](const WriteAckFrame& frame) {
|
}
|
||||||
|
case QuicWriteFrame::Type::WriteAckFrame_E: {
|
||||||
|
const WriteAckFrame& frame = *packetFrame.asWriteAckFrame();
|
||||||
DCHECK(!frame.ackBlocks.empty());
|
DCHECK(!frame.ackBlocks.empty());
|
||||||
VLOG(4) << "Server received ack for largestAcked="
|
VLOG(4) << "Server received ack for largestAcked="
|
||||||
<< frame.ackBlocks.back().end << " " << conn;
|
<< frame.ackBlocks.back().end << " " << conn;
|
||||||
commonAckVisitorForAckFrame(ackState, frame);
|
commonAckVisitorForAckFrame(ackState, frame);
|
||||||
},
|
break;
|
||||||
[&](const auto& /*frame*/) {
|
}
|
||||||
// Ignore other frames.
|
default: {
|
||||||
});
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
markPacketLoss,
|
markPacketLoss,
|
||||||
readData.networkData.receiveTimePoint);
|
readData.networkData.receiveTimePoint);
|
||||||
|
@@ -1116,7 +1116,7 @@ TEST_F(QuicServerTransportTest, TestOpenAckStreamFrame) {
|
|||||||
PacketNum currentPacket = packet.packet.header.getPacketSequenceNum();
|
PacketNum currentPacket = packet.packet.header.getPacketSequenceNum();
|
||||||
ASSERT_FALSE(packet.packet.frames.empty());
|
ASSERT_FALSE(packet.packet.frames.empty());
|
||||||
for (auto& quicFrame : packet.packet.frames) {
|
for (auto& quicFrame : packet.packet.frames) {
|
||||||
auto frame = boost::get<WriteStreamFrame>(&quicFrame);
|
auto frame = quicFrame.asWriteStreamFrame();
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1374,7 +1374,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrame) {
|
|||||||
StopSendingFrame stopSendingFrame(
|
StopSendingFrame stopSendingFrame(
|
||||||
streamId, GenericApplicationErrorCode::UNKNOWN);
|
streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||||
ASSERT_TRUE(builder.canBuildPacket());
|
ASSERT_TRUE(builder.canBuildPacket());
|
||||||
writeFrame(std::move(stopSendingFrame), builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
connCallback,
|
connCallback,
|
||||||
@@ -1416,7 +1416,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterCloseStream) {
|
|||||||
StopSendingFrame stopSendingFrame(
|
StopSendingFrame stopSendingFrame(
|
||||||
streamId, GenericApplicationErrorCode::UNKNOWN);
|
streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||||
ASSERT_TRUE(builder.canBuildPacket());
|
ASSERT_TRUE(builder.canBuildPacket());
|
||||||
writeFrame(std::move(stopSendingFrame), builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
server->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
server->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||||
EXPECT_CALL(connCallback, onStopSending(_, _)).Times(0);
|
EXPECT_CALL(connCallback, onStopSending(_, _)).Times(0);
|
||||||
@@ -1499,7 +1499,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterHalfCloseRemote) {
|
|||||||
builder, 0x00, stream->currentReadOffset, 0, 10, true);
|
builder, 0x00, stream->currentReadOffset, 0, 10, true);
|
||||||
ASSERT_TRUE(dataLen.hasValue());
|
ASSERT_TRUE(dataLen.hasValue());
|
||||||
ASSERT_EQ(*dataLen, 0);
|
ASSERT_EQ(*dataLen, 0);
|
||||||
writeFrame(std::move(stopSendingFrame), builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
connCallback,
|
connCallback,
|
||||||
@@ -1523,7 +1523,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingBeforeStream) {
|
|||||||
StopSendingFrame stopSendingFrame(
|
StopSendingFrame stopSendingFrame(
|
||||||
streamId, GenericApplicationErrorCode::UNKNOWN);
|
streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||||
ASSERT_TRUE(builder.canBuildPacket());
|
ASSERT_TRUE(builder.canBuildPacket());
|
||||||
writeFrame(std::move(stopSendingFrame), builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
EXPECT_CALL(connCallback, onNewBidirectionalStream(streamId));
|
EXPECT_CALL(connCallback, onNewBidirectionalStream(streamId));
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
@@ -1578,8 +1578,8 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterReset) {
|
|||||||
StopSendingFrame stopSendingFrame2(
|
StopSendingFrame stopSendingFrame2(
|
||||||
streamId2, GenericApplicationErrorCode::UNKNOWN);
|
streamId2, GenericApplicationErrorCode::UNKNOWN);
|
||||||
ASSERT_TRUE(builder.canBuildPacket());
|
ASSERT_TRUE(builder.canBuildPacket());
|
||||||
writeFrame(std::move(stopSendingFrame1), builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame1), builder);
|
||||||
writeFrame(std::move(stopSendingFrame2), builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame2), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
connCallback, onStopSending(_, GenericApplicationErrorCode::UNKNOWN))
|
connCallback, onStopSending(_, GenericApplicationErrorCode::UNKNOWN))
|
||||||
@@ -1605,7 +1605,7 @@ TEST_F(QuicServerTransportTest, StopSendingLoss) {
|
|||||||
StopSendingFrame stopSendingFrame(
|
StopSendingFrame stopSendingFrame(
|
||||||
streamId, GenericApplicationErrorCode::UNKNOWN);
|
streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||||
ASSERT_TRUE(builder.canBuildPacket());
|
ASSERT_TRUE(builder.canBuildPacket());
|
||||||
writeFrame(stopSendingFrame, builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
markPacketLoss(
|
markPacketLoss(
|
||||||
server->getNonConstConn(),
|
server->getNonConstConn(),
|
||||||
@@ -1635,7 +1635,7 @@ TEST_F(QuicServerTransportTest, StopSendingLossAfterStreamClosed) {
|
|||||||
StopSendingFrame stopSendingFrame(
|
StopSendingFrame stopSendingFrame(
|
||||||
streamId, GenericApplicationErrorCode::UNKNOWN);
|
streamId, GenericApplicationErrorCode::UNKNOWN);
|
||||||
ASSERT_TRUE(builder.canBuildPacket());
|
ASSERT_TRUE(builder.canBuildPacket());
|
||||||
writeFrame(stopSendingFrame, builder);
|
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
|
||||||
auto packet = std::move(builder).buildPacket();
|
auto packet = std::move(builder).buildPacket();
|
||||||
|
|
||||||
// clear out all the streams, this is not a great way to simulate closed
|
// 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(stream->retransmissionBuffer.size(), 1);
|
||||||
EXPECT_EQ(1, conn->outstandingPackets.size());
|
EXPECT_EQ(1, conn->outstandingPackets.size());
|
||||||
|
|
||||||
auto& streamFrame = boost::get<WriteStreamFrame>(
|
auto& streamFrame =
|
||||||
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
||||||
->packet.frames.front());
|
->packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
|
|
||||||
StreamEvents::AckStreamFrame ack(streamFrame);
|
StreamEvents::AckStreamFrame ack(streamFrame);
|
||||||
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
|
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
|
||||||
@@ -256,8 +257,9 @@ TEST_F(QuicOpenStateTest, RetxBufferSortedAfterAck) {
|
|||||||
EXPECT_EQ(3, stream->retransmissionBuffer.size());
|
EXPECT_EQ(3, stream->retransmissionBuffer.size());
|
||||||
EXPECT_EQ(3, conn->outstandingPackets.size());
|
EXPECT_EQ(3, conn->outstandingPackets.size());
|
||||||
auto packet = conn->outstandingPackets[folly::Random::rand32() % 3];
|
auto packet = conn->outstandingPackets[folly::Random::rand32() % 3];
|
||||||
auto streamFrame = boost::get<WriteStreamFrame>(
|
auto streamFrame = *conn->outstandingPackets[std::rand() % 3]
|
||||||
conn->outstandingPackets[std::rand() % 3].packet.frames.front());
|
.packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
StreamEvents::AckStreamFrame ack(streamFrame);
|
StreamEvents::AckStreamFrame ack(streamFrame);
|
||||||
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
|
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
|
||||||
EXPECT_EQ(2, stream->retransmissionBuffer.size());
|
EXPECT_EQ(2, stream->retransmissionBuffer.size());
|
||||||
@@ -289,9 +291,10 @@ TEST_F(QuicOpenStateTest, AckStreamAfterSkip) {
|
|||||||
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
||||||
EXPECT_EQ(1, conn->outstandingPackets.size());
|
EXPECT_EQ(1, conn->outstandingPackets.size());
|
||||||
|
|
||||||
auto& streamFrame = boost::get<WriteStreamFrame>(
|
auto& streamFrame =
|
||||||
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
||||||
->packet.frames.front());
|
->packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
|
|
||||||
PacketNum packetNum(1);
|
PacketNum packetNum(1);
|
||||||
MinStreamDataFrame minDataFrame(stream->id, 1000, 100);
|
MinStreamDataFrame minDataFrame(stream->id, 1000, 100);
|
||||||
@@ -333,9 +336,10 @@ TEST_F(QuicOpenStateTest, AckStreamAfterSkipHalfBuf) {
|
|||||||
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
||||||
EXPECT_EQ(1, conn->outstandingPackets.size());
|
EXPECT_EQ(1, conn->outstandingPackets.size());
|
||||||
|
|
||||||
auto& streamFrame = boost::get<WriteStreamFrame>(
|
auto& streamFrame =
|
||||||
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
||||||
->packet.frames.front());
|
->packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
|
|
||||||
PacketNum packetNum(1);
|
PacketNum packetNum(1);
|
||||||
// Skip ~0.5 buffers.
|
// Skip ~0.5 buffers.
|
||||||
@@ -387,11 +391,11 @@ TEST_F(QuicOpenStateTest, AckStreamAfterSkipOneAndAHalfBuf) {
|
|||||||
auto streamFrameIt =
|
auto streamFrameIt =
|
||||||
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData);
|
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData);
|
||||||
auto& streamFrame1 =
|
auto& streamFrame1 =
|
||||||
boost::get<WriteStreamFrame>(streamFrameIt->packet.frames.front());
|
*streamFrameIt->packet.frames.front().asWriteStreamFrame();
|
||||||
auto& streamFrame2 = boost::get<WriteStreamFrame>(
|
auto& streamFrame2 = *getNextOutstandingPacket(
|
||||||
getNextOutstandingPacket(
|
|
||||||
*conn, PacketNumberSpace::AppData, ++streamFrameIt)
|
*conn, PacketNumberSpace::AppData, ++streamFrameIt)
|
||||||
->packet.frames.front());
|
->packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
|
|
||||||
PacketNum packetNum(1);
|
PacketNum packetNum(1);
|
||||||
// Skip ~1.5 buffers.
|
// Skip ~1.5 buffers.
|
||||||
@@ -502,9 +506,10 @@ TEST_F(QuicHalfClosedRemoteStateTest, AckStream) {
|
|||||||
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
||||||
EXPECT_EQ(1, conn->outstandingPackets.size());
|
EXPECT_EQ(1, conn->outstandingPackets.size());
|
||||||
|
|
||||||
auto& streamFrame = boost::get<WriteStreamFrame>(
|
auto& streamFrame =
|
||||||
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
||||||
->packet.frames.front());
|
->packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
|
|
||||||
StreamEvents::AckStreamFrame ack(streamFrame);
|
StreamEvents::AckStreamFrame ack(streamFrame);
|
||||||
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
|
invokeHandler<StreamSendStateMachine>(stream->send, ack, *stream);
|
||||||
@@ -541,9 +546,10 @@ TEST_F(QuicHalfClosedRemoteStateTest, AckStreamAfterSkip) {
|
|||||||
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
EXPECT_EQ(stream->retransmissionBuffer.size(), 1);
|
||||||
EXPECT_EQ(1, conn->outstandingPackets.size());
|
EXPECT_EQ(1, conn->outstandingPackets.size());
|
||||||
|
|
||||||
auto& streamFrame = boost::get<WriteStreamFrame>(
|
auto& streamFrame =
|
||||||
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
*getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
|
||||||
->packet.frames.front());
|
->packet.frames.front()
|
||||||
|
.asWriteStreamFrame();
|
||||||
|
|
||||||
PacketNum packetNum(1);
|
PacketNum packetNum(1);
|
||||||
MinStreamDataFrame minDataFrame(stream->id, 1000, 100);
|
MinStreamDataFrame minDataFrame(stream->id, 1000, 100);
|
||||||
|
@@ -81,7 +81,7 @@ TEST_P(AckHandlersTest, TestAckMultipleSequentialBlocks) {
|
|||||||
GetParam(),
|
GetParam(),
|
||||||
ackFrame,
|
ackFrame,
|
||||||
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
||||||
auto& stream = boost::get<WriteStreamFrame>(packetFrame);
|
auto& stream = *packetFrame.asWriteStreamFrame();
|
||||||
streams.emplace_back(stream);
|
streams.emplace_back(stream);
|
||||||
},
|
},
|
||||||
testLossHandler(lostPackets),
|
testLossHandler(lostPackets),
|
||||||
@@ -152,7 +152,7 @@ TEST_P(AckHandlersTest, TestAckBlocksWithGaps) {
|
|||||||
GetParam(),
|
GetParam(),
|
||||||
ackFrame,
|
ackFrame,
|
||||||
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
||||||
auto& stream = boost::get<WriteStreamFrame>(packetFrame);
|
auto& stream = *packetFrame.asWriteStreamFrame();
|
||||||
streams.emplace_back(stream);
|
streams.emplace_back(stream);
|
||||||
},
|
},
|
||||||
testLossHandler(lostPackets),
|
testLossHandler(lostPackets),
|
||||||
@@ -259,7 +259,7 @@ TEST_P(AckHandlersTest, TestNonSequentialPacketNumbers) {
|
|||||||
GetParam(),
|
GetParam(),
|
||||||
ackFrame,
|
ackFrame,
|
||||||
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
||||||
auto& stream = boost::get<WriteStreamFrame>(packetFrame);
|
auto& stream = *packetFrame.asWriteStreamFrame();
|
||||||
streams.emplace_back(stream);
|
streams.emplace_back(stream);
|
||||||
},
|
},
|
||||||
testLossHandler(lostPackets),
|
testLossHandler(lostPackets),
|
||||||
@@ -337,15 +337,10 @@ TEST_P(AckHandlersTest, AckVisitorForAckTest) {
|
|||||||
auto ackedPacketNum =
|
auto ackedPacketNum =
|
||||||
outstandingPacket.packet.header.getPacketSequenceNum();
|
outstandingPacket.packet.header.getPacketSequenceNum();
|
||||||
EXPECT_EQ(ackedPacketNum, firstReceivedAck.largestAcked);
|
EXPECT_EQ(ackedPacketNum, firstReceivedAck.largestAcked);
|
||||||
folly::variant_match(
|
const WriteAckFrame* frame = packetFrame.asWriteAckFrame();
|
||||||
packetFrame,
|
if (frame) {
|
||||||
[&](const WriteAckFrame& frame) {
|
commonAckVisitorForAckFrame(conn.ackStates.appDataAckState, *frame);
|
||||||
commonAckVisitorForAckFrame(
|
}
|
||||||
conn.ackStates.appDataAckState, frame);
|
|
||||||
},
|
|
||||||
[&](const auto& /* frame */) {
|
|
||||||
// Ignore other frames.
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[](auto& /* conn */,
|
[](auto& /* conn */,
|
||||||
auto& /* packet */,
|
auto& /* packet */,
|
||||||
@@ -368,15 +363,10 @@ TEST_P(AckHandlersTest, AckVisitorForAckTest) {
|
|||||||
GetParam(),
|
GetParam(),
|
||||||
secondReceivedAck,
|
secondReceivedAck,
|
||||||
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
[&](const auto&, const auto& packetFrame, const ReadAckFrame&) {
|
||||||
folly::variant_match(
|
const WriteAckFrame* frame = packetFrame.asWriteAckFrame();
|
||||||
packetFrame,
|
if (frame) {
|
||||||
[&](const WriteAckFrame& frame) {
|
commonAckVisitorForAckFrame(conn.ackStates.appDataAckState, *frame);
|
||||||
commonAckVisitorForAckFrame(
|
}
|
||||||
conn.ackStates.appDataAckState, frame);
|
|
||||||
},
|
|
||||||
[&](const auto& /* frame */) {
|
|
||||||
// Ignore other frames.
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[](auto& /* conn */,
|
[](auto& /* conn */,
|
||||||
auto& /* packet */,
|
auto& /* packet */,
|
||||||
|
Reference in New Issue
Block a user