1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-04-18 17:24:03 +03:00

Remove exception throwing from QuicInteger

Summary: Continuing the theme, removing it from QuicInteger which ends up being in a lot of the write paths.

Reviewed By: kvtsoy

Differential Revision: D72757026

fbshipit-source-id: 99a6ab2caea8fb495b1cb466172611002968e527
This commit is contained in:
Matt Joras 2025-04-10 18:14:11 -07:00 committed by Facebook GitHub Bot
parent 7dbd219831
commit b81c086d09
38 changed files with 1502 additions and 724 deletions

View File

@ -33,7 +33,7 @@ AckScheduler::AckScheduler(
const AckState& ackState)
: conn_(conn), ackState_(ackState) {}
Optional<PacketNum> AckScheduler::writeNextAcks(
folly::Expected<Optional<PacketNum>, QuicError> AckScheduler::writeNextAcks(
PacketBuilderInterface& builder) {
// Use default ack delay for long headers. Usually long headers are sent
// before crypto negotiation, so the peer might not know about the ack delay
@ -61,49 +61,56 @@ Optional<PacketNum> AckScheduler::writeNextAcks(
conn_.connectionTime, /* connect timestamp */
};
Optional<WriteAckFrameResult> ackWriteResult;
auto ackWriteResult =
[&]() -> folly::Expected<Optional<WriteAckFrameResult>, QuicError> {
uint64_t peerRequestedTimestampsCount =
conn_.maybePeerAckReceiveTimestampsConfig.has_value()
? conn_.maybePeerAckReceiveTimestampsConfig.value()
.maxReceiveTimestampsPerAck
: 0;
uint64_t peerRequestedTimestampsCount =
conn_.maybePeerAckReceiveTimestampsConfig.has_value()
? conn_.maybePeerAckReceiveTimestampsConfig.value()
.maxReceiveTimestampsPerAck
: 0;
if (conn_.negotiatedExtendedAckFeatures > 0) {
// The peer supports extended ACKs and we have them enabled.
return writeAckFrame(
meta,
builder,
FrameType::ACK_EXTENDED,
conn_.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer
.value_or(AckReceiveTimestampsConfig()),
peerRequestedTimestampsCount,
conn_.negotiatedExtendedAckFeatures);
} else if (
conn_.transportSettings.readEcnOnIngress &&
(meta.ackState.ecnECT0CountReceived ||
meta.ackState.ecnECT1CountReceived ||
meta.ackState.ecnCECountReceived)) {
// We have to report ECN counts, but we can't use the extended ACK
// frame. In this case, we give ACK_ECN precedence over
// ACK_RECEIVE_TIMESTAMPS.
return writeAckFrame(meta, builder, FrameType::ACK_ECN);
} else if (conn_.negotiatedAckReceiveTimestampSupport) {
// Use ACK_RECEIVE_TIMESTAMPS if its enabled on both endpoints AND the
// peer requests at least 1 timestamp
return writeAckFrame(
meta,
builder,
FrameType::ACK_RECEIVE_TIMESTAMPS,
conn_.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer
.value(),
peerRequestedTimestampsCount);
} else {
return writeAckFrame(meta, builder, FrameType::ACK);
}
}();
if (conn_.negotiatedExtendedAckFeatures > 0) {
// The peer supports extended ACKs and we have them enabled.
ackWriteResult = writeAckFrame(
meta,
builder,
FrameType::ACK_EXTENDED,
conn_.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer
.value_or(AckReceiveTimestampsConfig()),
peerRequestedTimestampsCount,
conn_.negotiatedExtendedAckFeatures);
} else if (
conn_.transportSettings.readEcnOnIngress &&
(meta.ackState.ecnECT0CountReceived ||
meta.ackState.ecnECT1CountReceived ||
meta.ackState.ecnCECountReceived)) {
// We have to report ECN counts, but we can't use the extended ACK
// frame. In this case, we give ACK_ECN precedence over
// ACK_RECEIVE_TIMESTAMPS.
ackWriteResult = writeAckFrame(meta, builder, FrameType::ACK_ECN);
} else if (conn_.negotiatedAckReceiveTimestampSupport) {
// Use ACK_RECEIVE_TIMESTAMPS if its enabled on both endpoints AND the
// peer requests at least 1 timestamp
ackWriteResult = writeAckFrame(
meta,
builder,
FrameType::ACK_RECEIVE_TIMESTAMPS,
conn_.transportSettings.maybeAckReceiveTimestampsConfigSentToPeer
.value(),
peerRequestedTimestampsCount);
} else {
ackWriteResult = writeAckFrame(meta, builder, FrameType::ACK);
if (ackWriteResult.hasError()) {
return folly::makeUnexpected(ackWriteResult.error());
}
if (!ackWriteResult) {
if (!ackWriteResult.value()) {
return none;
}
return largestAckedPacketNum;
}

View File

@ -16,7 +16,8 @@ class AckScheduler {
public:
AckScheduler(const QuicConnectionStateBase& conn, const AckState& ackState);
Optional<PacketNum> writeNextAcks(PacketBuilderInterface& builder);
[[nodiscard]] folly::Expected<Optional<PacketNum>, QuicError> writeNextAcks(
PacketBuilderInterface& builder);
[[nodiscard]] bool hasPendingAcks() const;

View File

@ -227,12 +227,18 @@ FrameScheduler::scheduleFramesForPacket(
const LongHeader* longHeader = builder.getPacketHeader().asLong();
bool initialPacket =
longHeader && longHeader->getHeaderType() == LongHeader::Types::Initial;
builder.encodePacketHeader();
auto encodeRes = builder.encodePacketHeader();
if (encodeRes.hasError()) {
return folly::makeUnexpected(encodeRes.error());
}
// Add fixed padding at start of short header packets if configured
if (shortHeader && conn_.transportSettings.fixedShortHeaderPadding > 0) {
for (size_t i = 0; i < conn_.transportSettings.fixedShortHeaderPadding;
i++) {
writeFrame(PaddingFrame(), builder);
auto writeRes = writeFrame(PaddingFrame(), builder);
if (writeRes.hasError()) {
return folly::makeUnexpected(writeRes.error());
}
}
shortHeaderPadding = conn_.transportSettings.fixedShortHeaderPadding;
}
@ -246,7 +252,11 @@ FrameScheduler::scheduleFramesForPacket(
bool cryptoDataWritten = false;
bool rstWritten = false;
if (cryptoStreamScheduler_ && cryptoStreamScheduler_->hasData()) {
cryptoDataWritten = cryptoStreamScheduler_->writeCryptoData(wrapper);
auto cryptoDataRes = cryptoStreamScheduler_->writeCryptoData(wrapper);
if (cryptoDataRes.hasError()) {
return folly::makeUnexpected(cryptoDataRes.error());
}
cryptoDataWritten = cryptoDataRes.value();
}
if (rstScheduler_ && rstScheduler_->hasPendingRsts()) {
rstWritten = rstScheduler_->writeRsts(wrapper);
@ -256,14 +266,20 @@ FrameScheduler::scheduleFramesForPacket(
if (cryptoDataWritten || rstWritten) {
// If packet has non ack data, it is subject to congestion control. We
// need to use the wrapper/
ackScheduler_->writeNextAcks(wrapper);
auto writeAcksRes = ackScheduler_->writeNextAcks(wrapper);
if (writeAcksRes.hasError()) {
return folly::makeUnexpected(writeAcksRes.error());
}
} else {
// If we start with writing acks, we will let the ack scheduler write
// up to the full packet space. If the ack bytes exceeds the writable
// bytes, this will be a pure ack packet and it will skip congestion
// controller. Otherwise, we will give other schedulers an opportunity to
// write up to writable bytes.
ackScheduler_->writeNextAcks(builder);
auto writeAcksRes = ackScheduler_->writeNextAcks(builder);
if (writeAcksRes.hasError()) {
return folly::makeUnexpected(writeAcksRes.error());
}
}
}
// Immediate ACK frames are subject to congestion control but should be sent
@ -297,14 +313,20 @@ FrameScheduler::scheduleFramesForPacket(
}
if (datagramFrameScheduler_ &&
datagramFrameScheduler_->hasPendingDatagramFrames()) {
datagramFrameScheduler_->writeDatagramFrames(wrapper);
auto datagramRes = datagramFrameScheduler_->writeDatagramFrames(wrapper);
if (datagramRes.hasError()) {
return folly::makeUnexpected(datagramRes.error());
}
}
if (builder.hasFramesPending()) {
if (initialPacket) {
// This is the initial packet, we need to fill er up.
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
auto writeRes = writeFrame(PaddingFrame(), builder);
if (writeRes.hasError()) {
return folly::makeUnexpected(writeRes.error());
}
}
}
if (shortHeader) {
@ -312,7 +334,10 @@ FrameScheduler::scheduleFramesForPacket(
if (paddingModulo > 0) {
size_t paddingIncrement = wrapper.remainingSpaceInPkt() % paddingModulo;
for (size_t i = 0; i < paddingIncrement; i++) {
writeFrame(PaddingFrame(), builder);
auto writeRes = writeFrame(PaddingFrame(), builder);
if (writeRes.hasError()) {
return folly::makeUnexpected(writeRes.error());
}
}
shortHeaderPadding += paddingIncrement;
}
@ -627,7 +652,10 @@ bool PingFrameScheduler::hasPingFrame() const {
}
bool PingFrameScheduler::writePing(PacketBuilderInterface& builder) {
return 0 != writeFrame(PingFrame(), builder);
auto writeFrameResult = writeFrame(PingFrame(), builder);
// We shouldn't ever error on a PING.
CHECK(!writeFrameResult.hasError());
return writeFrameResult.value() != 0;
}
DatagramFrameScheduler::DatagramFrameScheduler(QuicConnectionStateBase& conn)
@ -637,7 +665,7 @@ bool DatagramFrameScheduler::hasPendingDatagramFrames() const {
return !conn_.datagramState.writeBuffer.empty();
}
bool DatagramFrameScheduler::writeDatagramFrames(
folly::Expected<bool, QuicError> DatagramFrameScheduler::writeDatagramFrames(
PacketBuilderInterface& builder) {
bool sent = false;
for (size_t i = 0; i <= conn_.datagramState.writeBuffer.size(); ++i) {
@ -645,15 +673,26 @@ bool DatagramFrameScheduler::writeDatagramFrames(
auto len = payload.chainLength();
uint64_t spaceLeft = builder.remainingSpaceInPkt();
QuicInteger frameTypeQuicInt(static_cast<uint8_t>(FrameType::DATAGRAM_LEN));
auto frameTypeSize = frameTypeQuicInt.getSize();
if (frameTypeSize.hasError()) {
return folly::makeUnexpected(frameTypeSize.error());
}
QuicInteger datagramLenInt(len);
auto datagramLenSize = datagramLenInt.getSize();
if (datagramLenSize.hasError()) {
return folly::makeUnexpected(datagramLenSize.error());
}
auto datagramFrameLength =
frameTypeQuicInt.getSize() + len + datagramLenInt.getSize();
frameTypeSize.value() + len + datagramLenSize.value();
if (folly::to<uint64_t>(datagramFrameLength) <= spaceLeft) {
auto datagramFrame = DatagramFrame(len, payload.move());
auto res = writeFrame(datagramFrame, builder);
if (res.hasError()) {
return folly::makeUnexpected(res.error());
}
// Must always succeed since we have already checked that there is enough
// space to write the frame
CHECK_GT(res, 0);
CHECK_GT(res.value(), 0);
QUIC_STATS(conn_.statsCallback, onDatagramWrite, len);
conn_.datagramState.writeBuffer.pop_front();
sent = true;
@ -734,7 +773,8 @@ CryptoStreamScheduler::CryptoStreamScheduler(
const QuicCryptoStream& cryptoStream)
: conn_(conn), cryptoStream_(cryptoStream) {}
bool CryptoStreamScheduler::writeCryptoData(PacketBuilderInterface& builder) {
folly::Expected<bool, QuicError> CryptoStreamScheduler::writeCryptoData(
PacketBuilderInterface& builder) {
bool cryptoDataWritten = false;
uint64_t writableData =
folly::to<uint64_t>(cryptoStream_.pendingWrites.chainLength());
@ -743,21 +783,27 @@ bool CryptoStreamScheduler::writeCryptoData(PacketBuilderInterface& builder) {
// will always take precedence over the crypto data.
for (const auto& buffer : cryptoStream_.lossBuffer) {
auto res = writeCryptoFrame(buffer.offset, buffer.data, builder);
if (!res) {
if (res.hasError()) {
return folly::makeUnexpected(res.error());
}
if (!res.value()) {
return cryptoDataWritten;
}
VLOG(4) << "Wrote retransmitted crypto" << " offset=" << buffer.offset
<< " bytes=" << res->len << " " << conn_;
<< " bytes=" << res.value()->len << " " << conn_;
cryptoDataWritten = true;
}
if (writableData != 0) {
auto res = writeCryptoFrame(
cryptoStream_.currentWriteOffset, cryptoStream_.pendingWrites, builder);
if (res) {
if (res.hasError()) {
return folly::makeUnexpected(res.error());
}
if (res.value()) {
VLOG(4) << "Wrote crypto frame"
<< " offset=" << cryptoStream_.currentWriteOffset
<< " bytesWritten=" << res->len << " " << conn_;
<< " bytesWritten=" << res.value()->len << " " << conn_;
cryptoDataWritten = true;
}
}
@ -779,7 +825,10 @@ bool ImmediateAckFrameScheduler::hasPendingImmediateAckFrame() const {
bool ImmediateAckFrameScheduler::writeImmediateAckFrame(
PacketBuilderInterface& builder) {
return 0 != writeFrame(ImmediateAckFrame(), builder);
auto result = writeFrame(ImmediateAckFrame(), builder);
// We shouldn't ever error on an IMMEDIATE_ACK.
CHECK(!result.hasError());
return result.value() != 0;
}
CloningScheduler::CloningScheduler(
@ -891,7 +940,10 @@ CloningScheduler::scheduleFramesForPacket(
}
internalBuilder->accountForCipherOverhead(cipherOverhead_);
internalBuilder->encodePacketHeader();
auto encodeRes = internalBuilder->encodePacketHeader();
if (encodeRes.hasError()) {
return folly::makeUnexpected(encodeRes.error());
}
PacketRebuilder rebuilder(*internalBuilder, conn_);
// TODO: It's possible we write out a packet that's larger than the

View File

@ -174,7 +174,8 @@ class DatagramFrameScheduler {
[[nodiscard]] bool hasPendingDatagramFrames() const;
bool writeDatagramFrames(PacketBuilderInterface& builder);
[[nodiscard]] folly::Expected<bool, QuicError> writeDatagramFrames(
PacketBuilderInterface& builder);
private:
QuicConnectionStateBase& conn_;
@ -213,7 +214,8 @@ class CryptoStreamScheduler {
/**
* Returns whether or we could write data to the stream.
*/
bool writeCryptoData(PacketBuilderInterface& builder);
[[nodiscard]] folly::Expected<bool, QuicError> writeCryptoData(
PacketBuilderInterface& builder);
bool hasData() const;

View File

@ -1313,47 +1313,80 @@ void writeCloseCommon(
connection.udpSendPacketLen,
header,
getAckState(connection, pnSpace).largestAckedByPeer.value_or(0));
packetBuilder.encodePacketHeader();
auto encodeResult = packetBuilder.encodePacketHeader();
if (encodeResult.hasError()) {
LOG(ERROR) << "Error encoding packet header: "
<< encodeResult.error().message;
return;
}
packetBuilder.accountForCipherOverhead(aead.getCipherOverhead());
size_t written = 0;
if (!closeDetails) {
written = writeFrame(
auto writeResult = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(TransportErrorCode::NO_ERROR),
std::string("No error")),
packetBuilder);
if (writeResult.hasError()) {
LOG(ERROR) << "Error writing frame: " << writeResult.error().message;
return;
}
written = *writeResult;
} else {
switch (closeDetails->code.type()) {
case QuicErrorCode::Type::ApplicationErrorCode:
written = writeFrame(
case QuicErrorCode::Type::ApplicationErrorCode: {
auto writeResult = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(*closeDetails->code.asApplicationErrorCode()),
closeDetails->message,
quic::FrameType::CONNECTION_CLOSE_APP_ERR),
packetBuilder);
if (writeResult.hasError()) {
LOG(ERROR) << "Error writing frame: " << writeResult.error().message;
return;
}
written = *writeResult;
break;
case QuicErrorCode::Type::TransportErrorCode:
written = writeFrame(
}
case QuicErrorCode::Type::TransportErrorCode: {
auto writeResult = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(*closeDetails->code.asTransportErrorCode()),
closeDetails->message,
quic::FrameType::CONNECTION_CLOSE),
packetBuilder);
if (writeResult.hasError()) {
LOG(ERROR) << "Error writing frame: " << writeResult.error().message;
return;
}
written = *writeResult;
break;
case QuicErrorCode::Type::LocalErrorCode:
written = writeFrame(
}
case QuicErrorCode::Type::LocalErrorCode: {
auto writeResult = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
std::string("Internal error"),
quic::FrameType::CONNECTION_CLOSE),
packetBuilder);
if (writeResult.hasError()) {
LOG(ERROR) << "Error writing frame: " << writeResult.error().message;
return;
}
written = *writeResult;
break;
}
}
}
if (pnSpace == PacketNumberSpace::Initial &&
connection.nodeType == QuicNodeType::Client) {
while (packetBuilder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), packetBuilder);
auto paddingResult = writeFrame(PaddingFrame(), packetBuilder);
if (paddingResult.hasError()) {
LOG(ERROR) << "Error writing padding frame: "
<< paddingResult.error().message;
return;
}
}
}
if (written == 0) {

View File

@ -139,7 +139,7 @@ RegularQuicPacketBuilder createPacketBuilder(QuicClientConnectionState& conn) {
conn.udpSendPacketLen,
std::move(shortHeader),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
return builder;
}
@ -486,7 +486,7 @@ TEST_F(QuicPacketSchedulerTest, CryptoSchedulerOnlySingleLossFits) {
conn.udpSendPacketLen,
std::move(longHeader),
conn.ackStates.handshakeAckState->largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
PacketBuilderWrapper builderWrapper(builder, 13);
CryptoStreamScheduler scheduler(
conn, *getCryptoStream(*conn.cryptoState, EncryptionLevel::Handshake));
@ -557,7 +557,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerExists) {
conn.udpSendPacketLen,
std::move(shortHeader),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
auto originalSpace = builder.remainingSpaceInPkt();
conn.streamManager->queueWindowUpdate(stream->id);
scheduler.writeWindowUpdates(builder);
@ -581,7 +581,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameNoSpace) {
conn.udpSendPacketLen,
std::move(shortHeader),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
PacketBuilderWrapper builderWrapper(builder, 2);
auto originalSpace = builder.remainingSpaceInPkt();
conn.streamManager->queueWindowUpdate(stream->id);
@ -604,7 +604,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerStreamNotExists) {
conn.udpSendPacketLen,
std::move(shortHeader),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
auto originalSpace = builder.remainingSpaceInPkt();
conn.streamManager->queueWindowUpdate(nonExistentStream);
scheduler.writeWindowUpdates(builder);
@ -707,10 +707,11 @@ TEST_F(QuicPacketSchedulerTest, WriteOnlyOutstandingPacketsTest) {
.ackDelayExponent = static_cast<uint8_t>(kDefaultAckDelayExponent)};
// Write those framses with a regular builder
writeFrame(connCloseFrame, regularBuilder);
writeFrame(QuicSimpleFrame(maxStreamFrame), regularBuilder);
writeFrame(pingFrame, regularBuilder);
writeAckFrame(ackMeta, regularBuilder);
ASSERT_FALSE(writeFrame(connCloseFrame, regularBuilder).hasError());
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(maxStreamFrame), regularBuilder).hasError());
ASSERT_FALSE(writeFrame(pingFrame, regularBuilder).hasError());
ASSERT_FALSE(writeAckFrame(ackMeta, regularBuilder).hasError());
auto result = cloningScheduler.scheduleFramesForPacket(
std::move(regularBuilder), kDefaultUDPSendPacketLen);
@ -1919,7 +1920,7 @@ TEST_F(QuicPacketSchedulerTest, WriteLossWithoutFlowControl) {
conn.udpSendPacketLen,
std::move(shortHeader1),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder1.encodePacketHeader();
ASSERT_FALSE(builder1.encodePacketHeader().hasError());
scheduler.writeStreams(builder1);
auto packet1 = std::move(builder1).buildPacket().packet;
ASSERT_FALSE(
@ -1949,7 +1950,7 @@ TEST_F(QuicPacketSchedulerTest, WriteLossWithoutFlowControl) {
conn.udpSendPacketLen,
std::move(shortHeader2),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder2.encodePacketHeader();
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
scheduler.writeStreams(builder2);
auto packet2 = std::move(builder2).buildPacket().packet;
ASSERT_FALSE(
@ -1997,7 +1998,7 @@ TEST_F(QuicPacketSchedulerTest, WriteLossWithoutFlowControlIgnoreDSR) {
conn.udpSendPacketLen,
std::move(shortHeader1),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder1.encodePacketHeader();
ASSERT_FALSE(builder1.encodePacketHeader().hasError());
scheduler.writeStreams(builder1);
auto packet1 = std::move(builder1).buildPacket().packet;
ASSERT_FALSE(
@ -2042,7 +2043,7 @@ TEST_F(QuicPacketSchedulerTest, WriteLossWithoutFlowControlSequential) {
conn.udpSendPacketLen,
std::move(shortHeader1),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder1.encodePacketHeader();
ASSERT_FALSE(builder1.encodePacketHeader().hasError());
scheduler.writeStreams(builder1);
auto packet1 = std::move(builder1).buildPacket().packet;
ASSERT_FALSE(
@ -2072,7 +2073,7 @@ TEST_F(QuicPacketSchedulerTest, WriteLossWithoutFlowControlSequential) {
conn.udpSendPacketLen,
std::move(shortHeader2),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder2.encodePacketHeader();
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
scheduler.writeStreams(builder2);
auto packet2 = std::move(builder2).buildPacket().packet;
ASSERT_FALSE(
@ -2121,7 +2122,7 @@ TEST_F(QuicPacketSchedulerTest, RunOutFlowControlDuringStreamWrite) {
conn.udpSendPacketLen,
std::move(shortHeader1),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder1.encodePacketHeader();
ASSERT_FALSE(builder1.encodePacketHeader().hasError());
scheduler.writeStreams(builder1);
auto packet1 = std::move(builder1).buildPacket().packet;
ASSERT_FALSE(
@ -2175,7 +2176,7 @@ TEST_F(QuicPacketSchedulerTest, WritingFINFromBufWithBufMetaFirst) {
conn.udpSendPacketLen,
std::move(header),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StreamFrameScheduler scheduler(conn);
scheduler.writeStreams(builder);
auto packet = std::move(builder).buildPacket().packet;
@ -2213,7 +2214,7 @@ TEST_F(QuicPacketSchedulerTest, NoFINWriteWhenBufMetaWrittenFIN) {
conn.udpSendPacketLen,
std::move(header),
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StreamFrameScheduler scheduler(conn);
scheduler.writeStreams(builder);
auto packet = std::move(builder).buildPacket().packet;
@ -2258,7 +2259,7 @@ TEST_F(QuicPacketSchedulerTest, DatagramFrameSchedulerMultipleFramesPerPacket) {
.WillRepeatedly(Invoke([](uint64_t bytes) { EXPECT_GT(bytes, 0); }));
// Call scheduler
auto& frames = builder.frames_;
scheduler.writeDatagramFrames(builder);
ASSERT_FALSE(scheduler.writeDatagramFrames(builder).hasError());
ASSERT_EQ(frames.size(), 2);
}
@ -2286,12 +2287,12 @@ TEST_F(QuicPacketSchedulerTest, DatagramFrameSchedulerOneFramePerPacket) {
EXPECT_CALL(quicStats, onDatagramWrite(_))
.Times(1)
.WillRepeatedly(Invoke([](uint64_t bytes) { EXPECT_GT(bytes, 0); }));
scheduler.writeDatagramFrames(builder);
ASSERT_FALSE(scheduler.writeDatagramFrames(builder).hasError());
ASSERT_EQ(frames.size(), 1);
EXPECT_CALL(quicStats, onDatagramWrite(_))
.Times(1)
.WillRepeatedly(Invoke([](uint64_t bytes) { EXPECT_GT(bytes, 0); }));
scheduler.writeDatagramFrames(builder);
ASSERT_FALSE(scheduler.writeDatagramFrames(builder).hasError());
ASSERT_EQ(frames.size(), 2);
}
@ -2315,14 +2316,14 @@ TEST_F(QuicPacketSchedulerTest, DatagramFrameWriteWhenRoomAvailable) {
conn.statsCallback = &quicStats;
// Call scheduler
auto& frames = builder.frames_;
scheduler.writeDatagramFrames(builder);
ASSERT_FALSE(scheduler.writeDatagramFrames(builder).hasError());
ASSERT_EQ(frames.size(), 0);
EXPECT_CALL(builder, remainingSpaceInPkt())
.WillRepeatedly(Return(conn.udpSendPacketLen / 2));
EXPECT_CALL(quicStats, onDatagramWrite(_))
.Times(1)
.WillRepeatedly(Invoke([](uint64_t bytes) { EXPECT_GT(bytes, 0); }));
scheduler.writeDatagramFrames(builder);
ASSERT_FALSE(scheduler.writeDatagramFrames(builder).hasError());
ASSERT_EQ(frames.size(), 1);
}
@ -2365,8 +2366,8 @@ TEST_F(QuicPacketSchedulerTest, ShortHeaderPaddingWithSpaceForPadding) {
DatagramFrame frame1(inputDataLength1, std::move(inputData1));
DatagramFrame frame2(inputDataLength2, std::move(inputData2));
writeFrame(frame1, builder1);
writeFrame(frame2, builder2);
ASSERT_FALSE(writeFrame(frame1, builder1).hasError());
ASSERT_FALSE(writeFrame(frame2, builder2).hasError());
NiceMock<MockQuicStats> quicStats;
conn.statsCallback = &quicStats;
@ -2479,7 +2480,7 @@ TEST_F(QuicPacketSchedulerTest, ShortHeaderPaddingNearMaxPacketLength) {
conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0));
DatagramFrame frame(inputDataLength, std::move(inputData));
writeFrame(frame, builder);
ASSERT_FALSE(writeFrame(frame, builder).hasError());
NiceMock<MockQuicStats> quicStats;
conn.statsCallback = &quicStats;
@ -2534,7 +2535,7 @@ TEST_F(QuicPacketSchedulerTest, ShortHeaderPaddingMaxPacketLength) {
// create enough input data to fully fill packet
while (builder.remainingSpaceInPkt() >
connectionIdSize + packetNumberEncoding.length + 1) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
NiceMock<MockQuicStats> quicStats;
@ -2872,7 +2873,9 @@ TEST_F(QuicAckSchedulerTest, DefaultAckFrame) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -2897,7 +2900,9 @@ TEST_F(QuicAckSchedulerTest, WriteAckEcnWhenReadingEcnOnEgress) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -2927,7 +2932,9 @@ TEST_F(QuicAckSchedulerTest, WriteAckReceiveTimestampsWhenEnabled) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -2957,7 +2964,9 @@ TEST_F(QuicAckSchedulerTest, AckEcnTakesPrecedenceOverReceiveTimestamps) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -2987,7 +2996,9 @@ TEST_F(QuicAckSchedulerTest, AckExtendedNotSentIfNotSupported) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -3016,7 +3027,9 @@ TEST_F(QuicAckSchedulerTest, AckExtendedNotSentIfNotEnabled) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -3053,7 +3066,9 @@ TEST_F(
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -3088,7 +3103,9 @@ TEST_F(QuicAckSchedulerTest, AckExtendedNotSentIfECNFeatureNotSupported) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -3127,7 +3144,9 @@ TEST_F(QuicAckSchedulerTest, AckExtendedWithAllFeatures) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -3166,7 +3185,9 @@ TEST_F(QuicAckSchedulerTest, AckExtendedTakesPrecedenceOverECN) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();
@ -3205,7 +3226,9 @@ TEST_F(QuicAckSchedulerTest, AckExtendedTakesPrecedenceOverReceiveTimestamps) {
AckScheduler ackScheduler(*conn_, ackState_);
ASSERT_TRUE(ackScheduler.hasPendingAcks());
ASSERT_TRUE(ackScheduler.writeNextAcks(*builder_) != none);
auto writeResult = ackScheduler.writeNextAcks(*builder_);
ASSERT_FALSE(writeResult.hasError());
ASSERT_TRUE(writeResult.value() != none);
ASSERT_EQ(builder_->frames_.size(), 1);
auto ackFrame = builder_->frames_[0].asWriteAckFrame();

View File

@ -141,7 +141,7 @@ auto buildEmptyPacket(
conn.udpSendPacketLen,
std::move(*header),
getAckState(conn, pnSpace).largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
DCHECK(builder.canBuildPacket());
return std::move(builder).buildPacket();
}

View File

@ -285,12 +285,12 @@ class QuicTypedTransportTestBase : protected QuicTransportTestClass {
peerPacketNumStore.nextAppDataPacketNum++);
RegularQuicPacketBuilder builder(
getConn().udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
CHECK(builder.canBuildPacket());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
writeSimpleFrame(stopSendingFrame, builder);
CHECK(!writeSimpleFrame(stopSendingFrame, builder).hasError());
auto buf = quic::test::packetToBuf(std::move(builder).buildPacket());
buf->coalesce();
@ -309,12 +309,12 @@ class QuicTypedTransportTestBase : protected QuicTransportTestClass {
peerPacketNumStore.nextAppDataPacketNum++);
RegularQuicPacketBuilder builder(
getConn().udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
CHECK(builder.canBuildPacket());
RstStreamFrame rstStreamFrame(
streamId, GenericApplicationErrorCode::UNKNOWN, offset);
writeFrame(rstStreamFrame, builder);
CHECK(!writeFrame(rstStreamFrame, builder).hasError());
auto buf = quic::test::packetToBuf(std::move(builder).buildPacket());
buf->coalesce();

View File

@ -11,7 +11,7 @@
namespace quic {
folly::Expected<size_t, TransportErrorCode> getQuicIntegerSize(uint64_t value) {
folly::Expected<size_t, QuicError> getQuicIntegerSize(uint64_t value) {
if (value <= kOneByteLimit) {
return 1;
} else if (value <= kTwoByteLimit) {
@ -21,22 +21,8 @@ folly::Expected<size_t, TransportErrorCode> getQuicIntegerSize(uint64_t value) {
} else if (value <= kEightByteLimit) {
return 8;
}
return folly::makeUnexpected(TransportErrorCode::INTERNAL_ERROR);
}
size_t getQuicIntegerSizeThrows(uint64_t value) {
if (value <= kOneByteLimit) {
return 1;
} else if (value <= kTwoByteLimit) {
return 2;
} else if (value <= kFourByteLimit) {
return 4;
} else if (value <= kEightByteLimit) {
return 8;
}
throw QuicTransportException(
folly::to<std::string>("Value too large: ", value),
TransportErrorCode::INTERNAL_ERROR);
return folly::makeUnexpected(
QuicError(TransportErrorCode::INTERNAL_ERROR, "Cannot encode value"));
}
uint8_t decodeQuicIntegerLength(uint8_t firstByte) {
@ -84,12 +70,14 @@ Optional<std::pair<uint64_t, size_t>> decodeQuicInteger(
QuicInteger::QuicInteger(uint64_t value) : value_(value) {}
size_t QuicInteger::getSize() const {
folly::Expected<size_t, QuicError> QuicInteger::getSize() const {
auto size = getQuicIntegerSize(value_);
if (size.hasError()) {
LOG(ERROR) << "Value too large value=" << value_;
throw QuicTransportException(
folly::to<std::string>("Value too large ", value_), size.error());
std::string errorMsg = "Value too large ";
errorMsg += std::to_string(value_);
return folly::makeUnexpected(
QuicError(TransportErrorCode::INTERNAL_ERROR, std::move(errorMsg)));
}
return size.value();
}

View File

@ -114,14 +114,8 @@ uint8_t decodeQuicIntegerLength(uint8_t firstByte);
* if value is too large to be represented with the variable
* length encoding
*/
folly::Expected<size_t, TransportErrorCode> getQuicIntegerSize(uint64_t value);
/**
* Returns number of bytes needed to encode value as a QUIC integer, or throws
* an exception if value is too large to be represented with the variable
* length encoding
*/
size_t getQuicIntegerSizeThrows(uint64_t value);
[[nodiscard]] folly::Expected<size_t, QuicError> getQuicIntegerSize(
uint64_t value);
/**
* A better API for dealing with QUIC integers for encoding.
@ -151,7 +145,7 @@ class QuicInteger {
* Returns the number of bytes needed to represent the QUIC integer in
* its encoded form.
**/
size_t getSize() const;
[[nodiscard]] folly::Expected<size_t, QuicError> getSize() const;
/**
* Returns the real value of the QUIC integer that it was instantiated with.

View File

@ -13,9 +13,9 @@
#include <quic/codec/PacketNumber.h>
namespace quic {
template <typename BufOp = BufAppender>
PacketNumEncodingResult encodeLongHeaderHelper(
[[nodiscard]] folly::Expected<PacketNumEncodingResult, QuicError>
encodeLongHeaderHelper(
const LongHeader& longHeader,
BufOp& bufop,
uint32_t& spaceCounter,
@ -43,8 +43,11 @@ PacketNumEncodingResult encodeLongHeaderHelper(
if (isInitial) {
// For initial packets, we write both the token length and the token itself.
uint64_t tokenLength = token.size();
QuicInteger tokenLengthInt(tokenLength);
tokenHeaderLength = tokenLengthInt.getSize() + tokenLength;
auto tokenLengthInt = QuicInteger(tokenLength).getSize();
if (tokenLengthInt.hasError()) {
return folly::makeUnexpected(tokenLengthInt.error());
}
tokenHeaderLength = tokenLengthInt.value() + tokenLength;
} else if (isRetry) {
// For retry packets, we write only the token.
tokenHeaderLength = token.size();
@ -280,11 +283,17 @@ RegularQuicPacketBuilder::Packet RegularQuicPacketBuilder::buildPacket() && {
return Packet(std::move(packet_), std::move(header_), std::move(body_));
}
void RegularQuicPacketBuilder::encodeLongHeader(
folly::Expected<folly::Unit, QuicError>
RegularQuicPacketBuilder::encodeLongHeader(
const LongHeader& longHeader,
PacketNum largestAckedPacketNum) {
packetNumberEncoding_ = encodeLongHeaderHelper(
auto encodingResult = encodeLongHeaderHelper(
longHeader, headerAppender_, remainingBytes_, largestAckedPacketNum);
if (encodingResult.hasError()) {
return folly::makeUnexpected(encodingResult.error());
}
packetNumberEncoding_ = std::move(encodingResult.value());
return folly::unit;
}
void RegularQuicPacketBuilder::encodeShortHeader(
@ -578,7 +587,7 @@ RetryPacketBuilder::RetryPacketBuilder(
writeRetryPacket();
}
void RetryPacketBuilder::writeRetryPacket() {
folly::Expected<folly::Unit, QuicError> RetryPacketBuilder::writeRetryPacket() {
packetBuf_ = folly::IOBuf::create(kAppenderGrowthSize);
// Encode the portion of the retry packet that comes before the
@ -591,7 +600,11 @@ void RetryPacketBuilder::writeRetryPacket() {
0 /* packet number, can be arbitrary for retry packets */,
quicVersion_,
retryToken_);
encodeLongHeaderHelper(header, appender, remainingBytes_, 0);
auto encodeResult =
encodeLongHeaderHelper(header, appender, remainingBytes_, 0);
if (encodeResult.hasError()) {
return folly::makeUnexpected(encodeResult.error());
}
packetBuf_->coalesce();
// Encode the integrity tag.
@ -603,6 +616,7 @@ void RetryPacketBuilder::writeRetryPacket() {
BufAppender appender2(packetBuf_.get(), kRetryIntegrityTagLen);
appender2.push(integrityTag_.data(), integrityTag_.size());
}
return folly::unit;
}
bool RetryPacketBuilder::canBuildPacket() const noexcept {
@ -828,23 +842,33 @@ InplaceQuicPacketBuilder::~InplaceQuicPacketBuilder() {
releaseOutputBufferInternal();
}
void RegularQuicPacketBuilder::encodePacketHeader() {
folly::Expected<folly::Unit, QuicError>
RegularQuicPacketBuilder::encodePacketHeader() {
CHECK(!packetNumberEncoding_.hasValue());
if (packet_.header.getHeaderForm() == HeaderForm::Long) {
LongHeader& longHeader = *packet_.header.asLong();
encodeLongHeader(longHeader, largestAckedPacketNum_);
auto result = encodeLongHeader(longHeader, largestAckedPacketNum_);
if (result.hasError()) {
return folly::makeUnexpected(result.error());
}
} else {
ShortHeader& shortHeader = *packet_.header.asShort();
encodeShortHeader(shortHeader, largestAckedPacketNum_);
}
return folly::unit;
}
void InplaceQuicPacketBuilder::encodePacketHeader() {
folly::Expected<folly::Unit, QuicError>
InplaceQuicPacketBuilder::encodePacketHeader() {
CHECK(!packetNumberEncoding_.hasValue());
if (packet_.header.getHeaderForm() == HeaderForm::Long) {
LongHeader& longHeader = *packet_.header.asLong();
packetNumberEncoding_ = encodeLongHeaderHelper(
auto encodingResult = encodeLongHeaderHelper(
longHeader, bufWriter_, remainingBytes_, largestAckedPacketNum_);
if (encodingResult.hasError()) {
return folly::makeUnexpected(encodingResult.error());
}
packetNumberEncoding_ = std::move(encodingResult.value());
if (longHeader.getHeaderType() != LongHeader::Types::Retry) {
// Remember the position to write packet number and packet length.
packetLenOffset_ = bufWriter_.getBytesWritten();
@ -867,6 +891,7 @@ void InplaceQuicPacketBuilder::encodePacketHeader() {
}
}
bodyStart_ = bufWriter_.tail();
return folly::unit;
}
} // namespace quic

View File

@ -61,7 +61,8 @@ class PacketBuilderInterface {
[[nodiscard]] virtual uint32_t remainingSpaceInPkt() const = 0;
virtual void encodePacketHeader() = 0;
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError>
encodePacketHeader() = 0;
// Functions to write bytes to the packet
virtual void writeBE(uint8_t data) = 0;
@ -132,7 +133,8 @@ class InplaceQuicPacketBuilder final : public PacketBuilderInterface {
// PacketBuilderInterface
[[nodiscard]] uint32_t remainingSpaceInPkt() const override;
void encodePacketHeader() override;
[[nodiscard]] folly::Expected<folly::Unit, QuicError> encodePacketHeader()
override;
void writeBE(uint8_t data) override;
void writeBE(uint16_t data) override;
@ -210,7 +212,8 @@ class RegularQuicPacketBuilder final : public PacketBuilderInterface {
[[nodiscard]] uint32_t getHeaderBytes() const override;
void encodePacketHeader() override;
[[nodiscard]] folly::Expected<folly::Unit, QuicError> encodePacketHeader()
override;
// PacketBuilderInterface
[[nodiscard]] uint32_t remainingSpaceInPkt() const override;
@ -253,7 +256,7 @@ class RegularQuicPacketBuilder final : public PacketBuilderInterface {
void releaseOutputBuffer() && override;
private:
void encodeLongHeader(
[[nodiscard]] folly::Expected<folly::Unit, QuicError> encodeLongHeader(
const LongHeader& longHeader,
PacketNum largestAckedPacketNum);
void encodeShortHeader(
@ -432,7 +435,7 @@ class RetryPacketBuilder {
[[nodiscard]] bool canBuildPacket() const noexcept;
private:
void writeRetryPacket();
folly::Expected<folly::Unit, QuicError> writeRetryPacket();
Buf packetBuf_;
@ -481,7 +484,8 @@ class PacketBuilderWrapper : public PacketBuilderInterface {
: 0;
}
void encodePacketHeader() override {
[[nodiscard]] folly::Expected<folly::Unit, QuicError> encodePacketHeader()
override {
CHECK(false)
<< "We only support wrapping builder that has already encoded header";
}

View File

@ -153,17 +153,23 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
}
auto cryptoWriteResult =
writeCryptoFrame(cryptoFrame.offset, *buf, builder_);
bool ret = cryptoWriteResult.has_value() &&
if (cryptoWriteResult.hasError()) {
return folly::makeUnexpected(cryptoWriteResult.error());
}
cryptoWriteResult->offset == cryptoFrame.offset &&
cryptoWriteResult->len == cryptoFrame.len;
bool ret = cryptoWriteResult.value()->offset == cryptoFrame.offset &&
cryptoWriteResult.value()->len == cryptoFrame.len;
notPureAck |= ret;
writeSuccess = ret;
break;
}
case QuicWriteFrame::Type::MaxDataFrame: {
shouldWriteWindowUpdate = true;
auto ret = 0 != writeFrame(generateMaxDataFrame(conn_), builder_);
auto writeResult = writeFrame(generateMaxDataFrame(conn_), builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
bool ret = writeResult.value() != 0;
windowUpdateWritten |= ret;
notPureAck |= ret;
writeSuccess = true;
@ -187,8 +193,12 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
break;
}
shouldWriteWindowUpdate = true;
bool ret =
0 != writeFrame(generateMaxStreamDataFrame(*stream), builder_);
auto writeResult =
writeFrame(generateMaxStreamDataFrame(*stream), builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
bool ret = writeResult.value() != 0;
windowUpdateWritten |= ret;
notPureAck |= ret;
writeSuccess = true;
@ -196,12 +206,20 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
}
case QuicWriteFrame::Type::PaddingFrame: {
const PaddingFrame& paddingFrame = *frame.asPaddingFrame();
writeSuccess = writeFrame(paddingFrame, builder_) != 0;
auto writeResult = writeFrame(paddingFrame, builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
writeSuccess = writeResult.value() != 0;
break;
}
case QuicWriteFrame::Type::PingFrame: {
const PingFrame& pingFrame = *frame.asPingFrame();
writeSuccess = writeFrame(pingFrame, builder_) != 0;
auto writeResult = writeFrame(pingFrame, builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
writeSuccess = writeResult.value() != 0;
notPureAck |= writeSuccess;
break;
}
@ -213,8 +231,12 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
writeSuccess = true;
break;
}
bool ret =
writeSimpleFrame(std::move(*updatedSimpleFrame), builder_) != 0;
auto writeResult =
writeSimpleFrame(std::move(*updatedSimpleFrame), builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
bool ret = writeResult.value() != 0;
notPureAck |= ret;
writeSuccess = ret;
break;
@ -224,7 +246,11 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
writeSuccess = true;
break;
default: {
bool ret = writeFrame(QuicWriteFrame(frame), builder_) != 0;
auto writeResult = writeFrame(QuicWriteFrame(frame), builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
bool ret = writeResult.value() != 0;
notPureAck |= ret;
writeSuccess = ret;
break;
@ -245,7 +271,10 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
conn_,
protectionTypeToPacketNumberSpace(packetHeader.getProtectionType()));
AckScheduler ackScheduler(conn_, ackState);
ackScheduler.writeNextAcks(builder_);
auto writeResult = ackScheduler.writeNextAcks(builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
}
// We shouldn't clone if:
@ -259,7 +288,10 @@ PacketRebuilder::rebuildFromPacket(OutstandingPacketWrapper& packet) {
if (encryptionLevel == EncryptionLevel::Initial) {
// Pad anything else that's left.
while (builder_.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder_);
auto writeResult = writeFrame(PaddingFrame(), builder_);
if (writeResult.hasError()) {
return folly::makeUnexpected(writeResult.error());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,6 @@
#include <quic/common/IntervalSet.h>
#include <quic/state/TransportSettings.h>
#include <sys/types.h>
#include <chrono>
#include <cstdint>
namespace quic {
@ -25,7 +24,7 @@ namespace quic {
* The input parameter is the frame to be written to the output appender.
*
*/
size_t writeSimpleFrame(
[[nodiscard]] folly::Expected<size_t, QuicError> writeSimpleFrame(
QuicSimpleFrame&& frame,
PacketBuilderInterface& builder);
@ -35,7 +34,9 @@ size_t writeSimpleFrame(
* The input parameter is the frame to be written to the output appender.
*
*/
size_t writeFrame(QuicWriteFrame&& frame, PacketBuilderInterface& builder);
[[nodiscard]] folly::Expected<size_t, QuicError> writeFrame(
QuicWriteFrame&& frame,
PacketBuilderInterface& builder);
/**
* Write a complete stream frame header into builder
@ -76,7 +77,8 @@ void writeStreamFrameData(
* written. The caller should check the structure to confirm how many bytes were
* written.
*/
Optional<WriteCryptoFrame> writeCryptoFrame(
[[nodiscard]] folly::Expected<Optional<WriteCryptoFrame>, QuicError>
writeCryptoFrame(
uint64_t offsetIn,
const ChainedByteRangeHead& data,
PacketBuilderInterface& builder);
@ -97,7 +99,8 @@ Optional<WriteCryptoFrame> writeCryptoFrame(
* written to the appender. Returns an empty optional if an ack block could not
* be written.
*/
Optional<WriteAckFrameResult> writeAckFrame(
[[nodiscard]] folly::Expected<Optional<WriteAckFrameResult>, QuicError>
writeAckFrame(
const WriteAckFrameMetaData& ackFrameMetaData,
PacketBuilderInterface& builder,
FrameType frameType = FrameType::ACK,
@ -109,7 +112,8 @@ Optional<WriteAckFrameResult> writeAckFrame(
/**
* Helper functions to write the fields for ACK_RECEIVE_TIMESTAMPS frame
*/
size_t computeSizeUsedByRecvdTimestamps(quic::WriteAckFrame& writeAckFrame);
[[nodiscard]] folly::Expected<size_t, QuicError>
computeSizeUsedByRecvdTimestamps(quic::WriteAckFrame& writeAckFrame);
} // namespace quic

View File

@ -96,7 +96,10 @@ class MockQuicPacketBuilder : public PacketBuilderInterface {
MOCK_METHOD(uint32_t, getHeaderBytes, (), (const));
MOCK_METHOD(bool, hasFramesPending, (), (const));
MOCK_METHOD(void, releaseOutputBufferMock, ());
MOCK_METHOD(void, encodePacketHeader, ());
MOCK_METHOD(
(folly::Expected<folly::Unit, QuicError>),
encodePacketHeader,
());
void releaseOutputBuffer() && override {
releaseOutputBufferMock();

View File

@ -49,7 +49,7 @@ TEST_F(QuicHeaderCodecTest, ShortHeaderTest) {
ShortHeader(
ProtectionType::KeyPhaseZero, getTestConnectionId(), packetNum),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
auto packet = std::move(builder).buildPacket();
auto result = parseHeader(packet.header);
auto& header = result->parsedHeader;

View File

@ -94,7 +94,10 @@ TEST_P(QuicIntegerEncodeTest, GetSize) {
auto size = getQuicIntegerSize(GetParam().decoded);
if (GetParam().error) {
EXPECT_TRUE(size.hasError());
EXPECT_EQ(size.error(), TransportErrorCode::INTERNAL_ERROR);
ASSERT_NE(size.error().code.asTransportErrorCode(), nullptr);
EXPECT_EQ(
*size.error().code.asTransportErrorCode(),
TransportErrorCode::INTERNAL_ERROR);
return;
}
EXPECT_EQ(*size, GetParam().hexEncoded.size() / 2);

View File

@ -246,10 +246,12 @@ TEST_P(QuicPacketBuilderTest, ShortHeaderRegularPacket) {
ShortHeader(ProtectionType::KeyPhaseZero, connId, pktNum),
largestAckedPacketNum,
2000);
builder->encodePacketHeader();
auto encodeResult = builder->encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
// write out at least one frame
writeFrame(PaddingFrame(), *builder);
auto writeFrameResult = writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrameResult.hasError());
EXPECT_TRUE(builder->canBuildPacket());
auto builtOut = std::move(*builder).buildPacket();
auto resultRegularPacket = builtOut.packet;
@ -305,10 +307,12 @@ TEST_P(QuicPacketBuilderTest, EnforcePacketSizeWithCipherOverhead) {
largestAckedPacketNum,
2000);
builder->accountForCipherOverhead(cipherOverhead);
builder->encodePacketHeader();
auto encodeResult = builder->encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
// write out at least one frame
writeFrame(PaddingFrame(), *builder);
auto writeFrameResult = writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrameResult.hasError());
EXPECT_TRUE(builder->canBuildPacket());
auto builtOut = std::move(*builder).buildPacket();
@ -351,7 +355,8 @@ TEST_P(QuicPacketBuilderTest, ShortHeaderWithNoFrames) {
ShortHeader(ProtectionType::KeyPhaseZero, connId, pktNum),
0 /*largestAckedPacketNum*/,
kDefaultUDPSendPacketLen);
builder->encodePacketHeader();
auto encodeResult = builder->encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
EXPECT_TRUE(builder->canBuildPacket());
auto builtOut = std::move(*builder).buildPacket();
@ -383,10 +388,12 @@ TEST_P(QuicPacketBuilderTest, TestPaddingAccountsForCipherOverhead) {
ShortHeader(ProtectionType::KeyPhaseZero, connId, pktNum),
largestAckedPacketNum,
kDefaultUDPSendPacketLen);
builder->encodePacketHeader();
auto encodeResult = builder->encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
builder->accountForCipherOverhead(cipherOverhead);
EXPECT_TRUE(builder->canBuildPacket());
writeFrame(PaddingFrame(), *builder);
auto writeFrameResult = writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrameResult.hasError());
auto builtOut = std::move(*builder).buildPacket();
auto resultRegularPacket = builtOut.packet;
// We should have padded the remaining bytes with Padding frames.
@ -410,9 +417,11 @@ TEST_P(QuicPacketBuilderTest, TestPaddingRespectsRemainingBytes) {
ShortHeader(ProtectionType::KeyPhaseZero, connId, pktNum),
largestAckedPacketNum,
2000);
builder->encodePacketHeader();
auto encodeResult = builder->encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
EXPECT_TRUE(builder->canBuildPacket());
writeFrame(PaddingFrame(), *builder);
auto writeFrameResult = writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrameResult.hasError());
auto builtOut = std::move(*builder).buildPacket();
auto resultRegularPacket = builtOut.packet;
@ -451,14 +460,14 @@ TEST_P(QuicPacketBuilderTest, LongHeaderBytesCounting) {
std::move(header),
largestAcked,
kDefaultUDPSendPacketLen);
builder->encodePacketHeader();
ASSERT_FALSE(builder->encodePacketHeader().hasError());
auto expectedWrittenHeaderFieldLen = sizeof(uint8_t) +
sizeof(QuicVersionType) + sizeof(uint8_t) + clientCid.size() +
sizeof(uint8_t) + serverCid.size();
auto estimatedHeaderBytes = builder->getHeaderBytes();
EXPECT_GT(
estimatedHeaderBytes, expectedWrittenHeaderFieldLen + kMaxPacketLenSize);
writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), *builder).hasError());
EXPECT_LE(
std::move(*builder).buildPacket().header.computeChainDataLength(),
estimatedHeaderBytes);
@ -474,9 +483,9 @@ TEST_P(QuicPacketBuilderTest, ShortHeaderBytesCounting) {
ShortHeader(ProtectionType::KeyPhaseZero, cid, pktNum),
largestAcked,
2000);
builder->encodePacketHeader();
ASSERT_FALSE(builder->encodePacketHeader().hasError());
auto headerBytes = builder->getHeaderBytes();
writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), *builder).hasError());
EXPECT_EQ(
std::move(*builder).buildPacket().header.computeChainDataLength(),
headerBytes);
@ -503,9 +512,9 @@ TEST_P(QuicPacketBuilderTest, InplaceBuilderReleaseBufferInBuild) {
1000,
ShortHeader(ProtectionType::KeyPhaseZero, getTestConnectionId(), 0),
0);
builder->encodePacketHeader();
ASSERT_FALSE(builder->encodePacketHeader().hasError());
EXPECT_FALSE(bufAccessor.ownsBuffer());
writeFrame(PaddingFrame(), *builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), *builder).hasError());
std::move(*builder).buildPacket();
EXPECT_TRUE(bufAccessor.ownsBuffer());
}
@ -518,10 +527,10 @@ TEST_F(QuicPacketBuilderTest, BuildTwoInplaces) {
1000,
ShortHeader(ProtectionType::KeyPhaseZero, getTestConnectionId(), 0),
0);
builder1->encodePacketHeader();
ASSERT_FALSE(builder1->encodePacketHeader().hasError());
auto headerBytes = builder1->getHeaderBytes();
for (size_t i = 0; i < 20; i++) {
writeFrame(PaddingFrame(), *builder1);
ASSERT_FALSE(writeFrame(PaddingFrame(), *builder1).hasError());
}
EXPECT_EQ(headerBytes, builder1->getHeaderBytes());
auto builtOut1 = std::move(*builder1).buildPacket();
@ -534,10 +543,10 @@ TEST_F(QuicPacketBuilderTest, BuildTwoInplaces) {
1000,
ShortHeader(ProtectionType::KeyPhaseZero, getTestConnectionId(), 0),
0);
builder2->encodePacketHeader();
ASSERT_FALSE(builder2->encodePacketHeader().hasError());
EXPECT_EQ(headerBytes, builder2->getHeaderBytes());
for (size_t i = 0; i < 40; i++) {
writeFrame(PaddingFrame(), *builder2);
ASSERT_FALSE(writeFrame(PaddingFrame(), *builder2).hasError());
}
auto builtOut2 = std::move(*builder2).buildPacket();
EXPECT_EQ(1, builtOut2.packet.frames.size());
@ -558,7 +567,7 @@ TEST_F(QuicPacketBuilderTest, InplaceBuilderShorterHeaderBytes) {
ShortHeader(ProtectionType::KeyPhaseZero, connId, packetNum),
largestAckedPacketNum,
kDefaultUDPSendPacketLen);
inplaceBuilder->encodePacketHeader();
ASSERT_FALSE(inplaceBuilder->encodePacketHeader().hasError());
EXPECT_EQ(2 + connId.size(), inplaceBuilder->getHeaderBytes());
}
@ -578,7 +587,7 @@ TEST_F(QuicPacketBuilderTest, InplaceBuilderLongHeaderBytes) {
QuicVersion::MVFST),
largestAckedPacketNum,
kDefaultUDPSendPacketLen);
inplaceBuilder->encodePacketHeader();
ASSERT_FALSE(inplaceBuilder->encodePacketHeader().hasError());
EXPECT_EQ(
9 /* initial + version + cid + cid + token length */ + srcConnId.size() +
destConnId.size() + kMaxPacketLenSize,
@ -761,8 +770,8 @@ TEST_P(QuicPacketBuilderTest, PadUpLongHeaderPacket) {
QuicVersion::MVFST),
largestAcked,
kDefaultUDPSendPacketLen);
builder->encodePacketHeader();
writeFrame(PingFrame(), *builder);
ASSERT_FALSE(builder->encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(PingFrame(), *builder).hasError());
EXPECT_TRUE(builder->canBuildPacket());
auto builtOut = std::move(*builder).buildPacket();
auto resultPacket = builtOut.packet;
@ -794,10 +803,10 @@ TEST_P(QuicPacketBuilderTest, TestCipherOverhead) {
QuicVersion::MVFST),
largestAcked,
kDefaultUDPSendPacketLen);
builder->encodePacketHeader();
ASSERT_FALSE(builder->encodePacketHeader().hasError());
builder->accountForCipherOverhead(cipherOverhead);
while (builder->canBuildPacket()) {
writeFrame(PingFrame(), *builder);
ASSERT_FALSE(writeFrame(PingFrame(), *builder).hasError());
}
auto builtOut = std::move(*builder).buildPacket();
auto resultRegularPacket = builtOut.packet;

View File

@ -44,7 +44,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildEmpty) {
kDefaultUDPSendPacketLen,
ShortHeader(ProtectionType::KeyPhaseZero, getTestConnectionId(), 0),
0 /* largestAcked */);
regularBuilder.encodePacketHeader();
ASSERT_FALSE(regularBuilder.encodePacketHeader().hasError());
QuicConnectionStateBase conn(QuicNodeType::Client);
PacketRebuilder rebuilder(regularBuilder, conn);
auto packet = std::move(regularBuilder).buildPacket();
@ -69,10 +69,11 @@ TEST_F(QuicPacketRebuilderTest, RebuildSmallInitial) {
kDefaultUDPSendPacketLen, std::move(initialHeader2), 0);
PingFrame pingFrame{};
writeFrame(pingFrame, regularBuilder1);
ASSERT_FALSE(writeFrame(pingFrame, regularBuilder1).hasError());
MaxStreamsFrame maxStreamsFrame(4321, true);
writeFrame(QuicSimpleFrame(maxStreamsFrame), regularBuilder1);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(maxStreamsFrame), regularBuilder1).hasError());
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
QuicConnectionStateBase conn(QuicNodeType::Client);
PacketRebuilder rebuilder(regularBuilder2, conn);
auto packet = std::move(regularBuilder1).buildPacket();
@ -80,7 +81,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildSmallInitial) {
EXPECT_FALSE(packet.header.empty());
ASSERT_EQ(packet.packet.frames.size(), 2);
EXPECT_FALSE(packet.body.empty());
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
ASSERT_FALSE(rebuildResult.hasError());
ASSERT_TRUE(rebuildResult.value().hasValue());
@ -99,7 +100,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder1(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
// Get a bunch frames
ConnectionCloseFrame connCloseFrame(
QuicErrorCode(TransportErrorCode::FRAME_ENCODING_ERROR),
@ -131,10 +132,11 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
PingFrame pingFrame{};
// Write them with a regular builder
// Write the ACK frame first since it has special rebuilder handling.
writeAckFrame(ackMeta, regularBuilder1);
writeFrame(connCloseFrame, regularBuilder1);
writeFrame(QuicSimpleFrame(maxStreamsFrame), regularBuilder1);
writeFrame(pingFrame, regularBuilder1);
ASSERT_FALSE(writeAckFrame(ackMeta, regularBuilder1).hasError());
ASSERT_FALSE(writeFrame(connCloseFrame, regularBuilder1).hasError());
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(maxStreamsFrame), regularBuilder1).hasError());
ASSERT_FALSE(writeFrame(pingFrame, regularBuilder1).hasError());
writeStreamFrameHeader(
regularBuilder1,
streamId,
@ -145,10 +147,12 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
none /* skipLenHint */);
writeStreamFrameData(
regularBuilder1, buf->clone(), buf->computeChainDataLength());
writeFrame(maxDataFrame, regularBuilder1);
writeFrame(maxStreamDataFrame, regularBuilder1);
writeCryptoFrame(
cryptoOffset, ChainedByteRangeHead(cryptoBuf), regularBuilder1);
ASSERT_FALSE(writeFrame(maxDataFrame, regularBuilder1).hasError());
ASSERT_FALSE(writeFrame(maxStreamDataFrame, regularBuilder1).hasError());
ASSERT_FALSE(
writeCryptoFrame(
cryptoOffset, ChainedByteRangeHead(cryptoBuf), regularBuilder1)
.hasError());
auto packet1 = std::move(regularBuilder1).buildPacket();
ASSERT_EQ(8, packet1.packet.frames.size());
stream->retransmissionBuffer.emplace(
@ -171,7 +175,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildPacket) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto outstanding = makeDummyOutstandingPacket(packet1.packet, 1000);
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
@ -261,7 +265,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildAfterResetStream) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder1(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ASSERT_FALSE(
@ -289,7 +293,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildAfterResetStream) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto outstanding = makeDummyOutstandingPacket(packet1.packet, 1000);
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
@ -302,7 +306,7 @@ TEST_F(QuicPacketRebuilderTest, FinOnlyStreamRebuild) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder1(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
ASSERT_FALSE(
@ -325,7 +329,7 @@ TEST_F(QuicPacketRebuilderTest, FinOnlyStreamRebuild) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto outstanding = makeDummyOutstandingPacket(packet1.packet, 2000);
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
@ -350,7 +354,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildDataStreamAndEmptyCryptoStream) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder1(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
// Get a bunch frames
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
@ -374,8 +378,10 @@ TEST_F(QuicPacketRebuilderTest, RebuildDataStreamAndEmptyCryptoStream) {
none /* skipLenHint */);
writeStreamFrameData(
regularBuilder1, buf->clone(), buf->computeChainDataLength());
writeCryptoFrame(
cryptoOffset, ChainedByteRangeHead(cryptoBuf), regularBuilder1);
ASSERT_FALSE(
writeCryptoFrame(
cryptoOffset, ChainedByteRangeHead(cryptoBuf), regularBuilder1)
.hasError());
auto packet1 = std::move(regularBuilder1).buildPacket();
ASSERT_EQ(2, packet1.packet.frames.size());
stream->retransmissionBuffer.emplace(
@ -391,7 +397,7 @@ TEST_F(QuicPacketRebuilderTest, RebuildDataStreamAndEmptyCryptoStream) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto outstanding = makeDummyOutstandingPacket(packet1.packet, 1000);
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
@ -418,7 +424,7 @@ TEST_F(QuicPacketRebuilderTest, CannotRebuildEmptyCryptoStream) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder1(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
// Get a bunch frames
QuicServerConnectionState conn(
FizzServerQuicHandshakeContext::Builder().build());
@ -426,8 +432,10 @@ TEST_F(QuicPacketRebuilderTest, CannotRebuildEmptyCryptoStream) {
auto cryptoBuf = folly::IOBuf::copyBuffer("NewSessionTicket");
// Write them with a regular builder
writeCryptoFrame(
cryptoOffset, ChainedByteRangeHead(cryptoBuf), regularBuilder1);
ASSERT_FALSE(
writeCryptoFrame(
cryptoOffset, ChainedByteRangeHead(cryptoBuf), regularBuilder1)
.hasError());
auto packet1 = std::move(regularBuilder1).buildPacket();
ASSERT_EQ(1, packet1.packet.frames.size());
// Do not add the buf to crypto stream's retransmission buffer,
@ -438,7 +446,7 @@ TEST_F(QuicPacketRebuilderTest, CannotRebuildEmptyCryptoStream) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto outstanding = makeDummyOutstandingPacket(packet1.packet, 1000);
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
@ -451,7 +459,7 @@ TEST_F(QuicPacketRebuilderTest, CannotRebuild) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder1(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder1.encodePacketHeader();
ASSERT_FALSE(regularBuilder1.encodePacketHeader().hasError());
// Get a bunch frames
ConnectionCloseFrame connCloseFrame(
QuicErrorCode(TransportErrorCode::FRAME_ENCODING_ERROR),
@ -476,10 +484,10 @@ TEST_F(QuicPacketRebuilderTest, CannotRebuild) {
folly::IOBuf::copyBuffer("You can't deny you are looking for the sunset");
PingFrame pingFrame;
// Write them with a regular builder
writeFrame(connCloseFrame, regularBuilder1);
writeFrame(maxStreamIdFrame, regularBuilder1);
writeFrame(pingFrame, regularBuilder1);
writeAckFrame(ackMeta, regularBuilder1);
ASSERT_FALSE(writeFrame(connCloseFrame, regularBuilder1).hasError());
ASSERT_FALSE(writeFrame(maxStreamIdFrame, regularBuilder1).hasError());
ASSERT_FALSE(writeFrame(pingFrame, regularBuilder1).hasError());
ASSERT_FALSE(writeAckFrame(ackMeta, regularBuilder1).hasError());
writeStreamFrameHeader(
regularBuilder1,
streamId,
@ -507,7 +515,7 @@ TEST_F(QuicPacketRebuilderTest, CannotRebuild) {
2,
std::move(shortHeader2),
0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto outstanding = makeDummyOutstandingPacket(packet1.packet, 1000);
auto rebuildResult = rebuilder.rebuildFromPacket(outstanding);
@ -520,9 +528,9 @@ TEST_F(QuicPacketRebuilderTest, CloneCounter) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0 /* largestAcked */);
regularBuilder.encodePacketHeader();
ASSERT_FALSE(regularBuilder.encodePacketHeader().hasError());
MaxDataFrame maxDataFrame(31415926);
writeFrame(maxDataFrame, regularBuilder);
ASSERT_FALSE(writeFrame(maxDataFrame, regularBuilder).hasError());
auto packet = std::move(regularBuilder).buildPacket();
auto outstandingPacket = makeDummyOutstandingPacket(packet.packet, 1000);
QuicServerConnectionState conn(
@ -531,7 +539,7 @@ TEST_F(QuicPacketRebuilderTest, CloneCounter) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0 /* largestAcked */);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
ASSERT_FALSE(rebuilder.rebuildFromPacket(outstandingPacket).hasError());
EXPECT_TRUE(outstandingPacket.maybeClonedPacketIdentifier.has_value());
@ -543,9 +551,9 @@ TEST_F(QuicPacketRebuilderTest, PurePingWillRebuild) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder(
kDefaultUDPSendPacketLen, std::move(shortHeader1), 0);
regularBuilder.encodePacketHeader();
ASSERT_FALSE(regularBuilder.encodePacketHeader().hasError());
PingFrame pingFrame;
writeFrame(pingFrame, regularBuilder);
ASSERT_FALSE(writeFrame(pingFrame, regularBuilder).hasError());
auto packet = std::move(regularBuilder).buildPacket();
auto outstandingPacket = makeDummyOutstandingPacket(packet.packet, 50);
EXPECT_EQ(1, outstandingPacket.packet.frames.size());
@ -555,7 +563,7 @@ TEST_F(QuicPacketRebuilderTest, PurePingWillRebuild) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder2(
kDefaultUDPSendPacketLen, std::move(shortHeader2), 0);
regularBuilder2.encodePacketHeader();
ASSERT_FALSE(regularBuilder2.encodePacketHeader().hasError());
PacketRebuilder rebuilder(regularBuilder2, conn);
auto rebuildResult = rebuilder.rebuildFromPacket(outstandingPacket);
ASSERT_FALSE(rebuildResult.hasError());
@ -579,7 +587,7 @@ TEST_F(QuicPacketRebuilderTest, LastStreamFrameSkipLen) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder(
kDefaultUDPSendPacketLen, std::move(shortHeader), 0);
regularBuilder.encodePacketHeader();
ASSERT_FALSE(regularBuilder.encodePacketHeader().hasError());
writeStreamFrameHeader(
regularBuilder,
streamId,
@ -633,7 +641,9 @@ TEST_F(QuicPacketRebuilderTest, LastStreamFrameSkipLen) {
EXPECT_CALL(mockBuilder, write(_))
.Times(4)
.WillRepeatedly(Invoke([&](const QuicInteger& quicInt) {
packetLimit -= quicInt.getSize();
auto sizeResult = quicInt.getSize();
ASSERT_FALSE(sizeResult.hasError());
packetLimit -= sizeResult.value();
}));
PacketRebuilder rebuilder(mockBuilder, conn);
@ -656,7 +666,7 @@ TEST_F(QuicPacketRebuilderTest, LastStreamFrameFinOnlySkipLen) {
ProtectionType::KeyPhaseZero, getTestConnectionId(), 0);
RegularQuicPacketBuilder regularBuilder(
kDefaultUDPSendPacketLen, std::move(shortHeader), 0);
regularBuilder.encodePacketHeader();
ASSERT_FALSE(regularBuilder.encodePacketHeader().hasError());
writeStreamFrameHeader(
regularBuilder,
streamId,
@ -710,7 +720,9 @@ TEST_F(QuicPacketRebuilderTest, LastStreamFrameFinOnlySkipLen) {
EXPECT_CALL(mockBuilder, write(_))
.Times(5)
.WillRepeatedly(Invoke([&](const QuicInteger& quicInt) {
packetLimit -= quicInt.getSize();
auto sizeResult = quicInt.getSize();
ASSERT_FALSE(sizeResult.hasError());
packetLimit -= sizeResult.value();
}));
PacketRebuilder rebuilder(mockBuilder, conn);

View File

@ -199,10 +199,13 @@ TEST_F(QuicReadCodecTest, LongHeaderPacketLenMismatch) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(headerIn), 0 /* largestAcked */);
builder.encodePacketHeader();
auto encodeResult = builder.encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
builder.accountForCipherOverhead(0);
auto cryptoFrameBuf = folly::IOBuf::copyBuffer("CHLO");
writeCryptoFrame(0, ChainedByteRangeHead(cryptoFrameBuf), builder);
auto writeResult =
writeCryptoFrame(0, ChainedByteRangeHead(cryptoFrameBuf), builder);
ASSERT_FALSE(writeResult.hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
auto packetQueue = bufToQueue(std::move(packet));
@ -280,7 +283,8 @@ TEST_F(QuicReadCodecTest, StreamWithShortHeaderOnlyHeader) {
ShortHeader header(ProtectionType::KeyPhaseZero, connId, packetNum);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
auto encodeResult = builder.encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
auto packetBuf = packetToBuf(std::move(builder).buildPacket());
auto aead = std::make_unique<MockAead>();

View File

@ -158,12 +158,13 @@ void setupCommonExpects(MockQuicPacketBuilder& pktBuilder) {
pktBuilder.appender_.push(data, len);
pktBuilder.remaining_ -= len;
})));
EXPECT_CALL(pktBuilder, write(_))
.WillRepeatedly(Invoke([&](const QuicInteger& quicInteger) {
auto size = quicInteger.getSize();
ASSERT_FALSE(size.hasError());
quicInteger.encode(
[&](auto val) { pktBuilder.appender_.writeBE(val); });
pktBuilder.remaining_ -= quicInteger.getSize();
pktBuilder.remaining_ -= *size;
}));
}
@ -224,8 +225,10 @@ size_t computeBytesForOptionalAckFields(
if (frameType == FrameType::ACK_EXTENDED) {
// Account for the extended ack header if it is included into the ack.
sizeConsumed += getQuicIntegerSizeThrows(
ackFrameWriteResult.extendedAckFeaturesEnabled);
auto sizeResult =
getQuicIntegerSize(ackFrameWriteResult.extendedAckFeaturesEnabled);
CHECK(!sizeResult.hasError());
sizeConsumed += sizeResult.value();
}
if (frameType == FrameType::ACK_RECEIVE_TIMESTAMPS ||
@ -250,27 +253,41 @@ size_t computeBytesForOptionalAckFields(
// 1. last received packet's timestamp delta,
// 2. last received packet's number,
// 3. count of timestamp ranges
sizeConsumed +=
getQuicIntegerSizeThrows(
lastTimeStampDelta
.count()) + // latest received packet timestamp delta
getQuicIntegerSizeThrows(lastPktNum) + // latest received packet number
getQuicIntegerSizeThrows(
numRanges); // count of ack_receive_timestamp ranges
auto lastTimeDeltaSizeResult =
getQuicIntegerSize(lastTimeStampDelta.count());
CHECK(!lastTimeDeltaSizeResult.hasError());
auto lastPktNumSizeResult = getQuicIntegerSize(lastPktNum);
CHECK(!lastPktNumSizeResult.hasError());
auto numRangesSizeResult = getQuicIntegerSize(numRanges);
CHECK(!numRangesSizeResult.hasError());
sizeConsumed += lastTimeDeltaSizeResult
.value() + // latest received packet timestamp delta
lastPktNumSizeResult.value() + // latest received packet number
numRangesSizeResult.value(); // count of ack_receive_timestamp ranges
if (numRanges > 0) {
sizeConsumed +=
auto sizeUsedResult =
computeSizeUsedByRecvdTimestamps(ackFrameWriteResult.writeAckFrame);
CHECK(!sizeUsedResult.hasError());
sizeConsumed += sizeUsedResult.value();
};
}
if (shouldHaveECN) {
// Account for ECN count fields if they are included into the ack.
sizeConsumed += getQuicIntegerSizeThrows(
ackFrameMetadata.ackState.ecnECT0CountReceived) +
getQuicIntegerSizeThrows(
ackFrameMetadata.ackState.ecnECT1CountReceived) +
getQuicIntegerSizeThrows(ackFrameMetadata.ackState.ecnCECountReceived);
auto ect0SizeResult =
getQuicIntegerSize(ackFrameMetadata.ackState.ecnECT0CountReceived);
CHECK(!ect0SizeResult.hasError());
auto ect1SizeResult =
getQuicIntegerSize(ackFrameMetadata.ackState.ecnECT1CountReceived);
CHECK(!ect1SizeResult.hasError());
auto ceSizeResult =
getQuicIntegerSize(ackFrameMetadata.ackState.ecnCECountReceived);
CHECK(!ceSizeResult.hasError());
sizeConsumed +=
ect0SizeResult.value() + ect1SizeResult.value() + ceSizeResult.value();
}
return sizeConsumed;
}
@ -383,13 +400,16 @@ TEST_P(QuicWriteCodecExtendedAckTest, WriteWithFeatures) {
// There is 1 gap => each represented by 2 bytes => 2 bytes
// 2 byte for first ack block length, then 2 bytes for the next len => 4 bytes
// total 11 bytes for base ACK. Extended frame size is added below.
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored,
extendedAckSupport);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
EXPECT_EQ(11 + addlBytesConsumed, ackFrameWriteResult.bytesWritten);
@ -1020,7 +1040,9 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameHeadeSkipLen) {
EXPECT_CALL(pktBuilder, write(_))
.Times(2)
.WillRepeatedly(Invoke([&](const QuicInteger& quicInt) {
packetLimit -= quicInt.getSize();
auto size = quicInt.getSize();
ASSERT_FALSE(size.hasError());
packetLimit -= size.value();
}));
StreamId streamId = 0;
uint64_t offset = 10;
@ -1047,7 +1069,8 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameHeadeNotSkipLen) {
EXPECT_CALL(pktBuilder, write(_))
.Times(3)
.WillRepeatedly(Invoke([&](const QuicInteger& quicInt) {
packetLimit -= quicInt.getSize();
ASSERT_FALSE(quicInt.getSize().hasError());
packetLimit -= quicInt.getSize().value();
}));
StreamId streamId = 0;
uint64_t offset = 10;
@ -1074,7 +1097,8 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameHeadeLengthHintTrue) {
EXPECT_CALL(pktBuilder, write(_))
.Times(2)
.WillRepeatedly(Invoke([&](const QuicInteger& quicInt) {
packetLimit -= quicInt.getSize();
ASSERT_FALSE(quicInt.getSize().hasError());
packetLimit -= quicInt.getSize().value();
}));
StreamId streamId = 0;
uint64_t offset = 10;
@ -1101,7 +1125,8 @@ TEST_F(QuicWriteCodecTest, WriteStreamFrameHeadeLengthHintFalse) {
EXPECT_CALL(pktBuilder, write(_))
.Times(3)
.WillRepeatedly(Invoke([&](const QuicInteger& quicInt) {
packetLimit -= quicInt.getSize();
ASSERT_FALSE(quicInt.getSize().hasError());
packetLimit -= quicInt.getSize().value();
}));
StreamId streamId = 0;
uint64_t offset = 10;
@ -1132,14 +1157,14 @@ TEST_P(QuicWriteCodecTest, AckFrameGapExceedsRepresentation) {
.connTime = connTime,
};
EXPECT_THROW(
writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
0),
QuicTransportException);
auto result = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
0);
ASSERT_TRUE(result.hasError());
ASSERT_NE(result.error().code.asTransportErrorCode(), nullptr);
}
TEST_P(QuicWriteCodecTest, AckFrameVeryLargeAckRange) {
@ -1193,12 +1218,15 @@ TEST_P(QuicWriteCodecTest, AckFrameVeryLargeAckRange) {
.ackDelayExponent = static_cast<uint8_t>(kDefaultAckDelayExponent),
.connTime = connTime,
};
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
@ -1227,7 +1255,6 @@ TEST_P(QuicWriteCodecTest, AckFrameVeryLargeAckRange) {
assertsOnDecodedReceiveTimestamps(
ackFrameMetaData,
ackFrameWriteResult.writeAckFrame,
decodedAckFrame,
1 /* timestamp ranges count */,
kMaxReceivedPktsTimestampsStored /* timestamps count */,
@ -1264,7 +1291,8 @@ TEST_P(QuicWriteCodecTest, AckFrameNotEnoughForAnything) {
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
EXPECT_FALSE(result.has_value());
EXPECT_FALSE(result.hasError());
EXPECT_FALSE(result.value().has_value());
EXPECT_EQ(pktBuilder.remainingSpaceInPkt(), 4);
}
@ -1294,13 +1322,16 @@ TEST_P(QuicWriteCodecTest, WriteSimpleAckFrame) {
// There is 1 gap => each represented by 2 bytes => 2 bytes
// 2 byte for first ack block length, then 2 bytes for the next len => 4 bytes
// total 11 bytes
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored,
extendedAckSupport);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
EXPECT_EQ(11 + addlBytesConsumed, ackFrameWriteResult.bytesWritten);
@ -1369,12 +1400,14 @@ TEST_P(QuicWriteCodecTest, WriteAckFrameWillSaveAckDelay) {
.connTime = connTime,
};
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResult = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
ASSERT_FALSE(ackFrameWriteResult.hasError());
ASSERT_TRUE(ackFrameWriteResult.value().has_value());
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
WriteAckFrame& ackFrame = *regularPacket.frames.back().asWriteAckFrame();
@ -1422,12 +1455,15 @@ TEST_P(QuicWriteCodecTest, VerifyNumAckBlocksSizeAccounted) {
// There is 1 gap => each represented by 2 bytes => 2 bytes
// 2 byte for first ack block length, then 2 bytes for the next len => 4 bytes
// total 11 bytes
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
auto builtOut = std::move(pktBuilder).buildTestPacket();
@ -1585,12 +1621,15 @@ TEST_P(QuicWriteCodecTest, OnlyAckLargestPacket) {
.connTime = connTime,
};
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
@ -1628,7 +1667,6 @@ TEST_P(QuicWriteCodecTest, OnlyAckLargestPacket) {
assertsOnDecodedReceiveTimestamps(
ackFrameMetaData,
ackFrameWriteResult.writeAckFrame,
decodedAckFrame,
1 /* timestamp ranges count */,
1 /* timestamps count */,
@ -1686,13 +1724,16 @@ TEST_P(QuicWriteCodecTest, WriteSomeAckBlocks) {
.connTime = connTime,
};
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored,
extendedAckSupport);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
@ -1730,7 +1771,6 @@ TEST_P(QuicWriteCodecTest, WriteSomeAckBlocks) {
assertsOnDecodedReceiveTimestamps(
ackFrameMetaData,
ackFrameWriteResult.writeAckFrame,
decodedAckFrame,
0 /* timestamp ranges count */,
0 /* timestamps count */,
@ -1765,7 +1805,8 @@ TEST_P(QuicWriteCodecTest, NoSpaceForAckBlockSection) {
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
EXPECT_FALSE(ackFrameWriteResult.has_value());
ASSERT_FALSE(ackFrameWriteResult.hasError());
EXPECT_FALSE(ackFrameWriteResult.value().hasValue());
}
TEST_P(QuicWriteCodecTest, OnlyHasSpaceForFirstAckBlock) {
@ -1802,12 +1843,15 @@ TEST_P(QuicWriteCodecTest, OnlyHasSpaceForFirstAckBlock) {
.connTime = connTime,
};
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
kMaxReceivedPktsTimestampsStored);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().hasValue());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
@ -1875,13 +1919,16 @@ TEST_P(QuicWriteCodecTest, WriteAckFrameWithMultipleTimestampRanges) {
.connTime = connTime,
};
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
50, /*maxRecvTimestampsToSend*/
extendedAckSupport);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().hasValue());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
@ -1969,13 +2016,16 @@ TEST_P(
// - 3 bytes for the ECN counts (all 0 in this test)
pktBuilder.remaining_ = 84;
}
auto ackFrameWriteResult = *writeAckFrame(
auto ackFrameWriteResultExpected = writeAckFrame(
ackFrameMetaData,
pktBuilder,
frameType,
defaultAckReceiveTimestmpsConfig,
100,
extendedAckSupport);
ASSERT_FALSE(ackFrameWriteResultExpected.hasError());
ASSERT_TRUE(ackFrameWriteResultExpected.value().has_value());
auto& ackFrameWriteResult = ackFrameWriteResultExpected.value().value();
auto addlBytesConsumed = computeBytesForOptionalAckFields(
ackFrameMetaData, ackFrameWriteResult, frameType);
@ -2045,7 +2095,9 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamData) {
StreamId id = 1;
uint64_t offset = 0x08;
MaxStreamDataFrame maxStreamDataFrame(id, offset);
auto bytesWritten = writeFrame(maxStreamDataFrame, pktBuilder);
auto bytesWrittenExpected = writeFrame(maxStreamDataFrame, pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2072,14 +2124,17 @@ TEST_F(QuicWriteCodecTest, NoSpaceForMaxStreamData) {
pktBuilder.remaining_ = 1;
setupCommonExpects(pktBuilder);
MaxStreamDataFrame maxStreamDataFrame(1, 0x08);
EXPECT_EQ(0, writeFrame(maxStreamDataFrame, pktBuilder));
ASSERT_FALSE(writeFrame(maxStreamDataFrame, pktBuilder).hasError());
EXPECT_EQ(0, writeFrame(maxStreamDataFrame, pktBuilder).value());
}
TEST_F(QuicWriteCodecTest, WriteMaxData) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
MaxDataFrame maxDataFrame(1000);
auto bytesWritten = writeFrame(maxDataFrame, pktBuilder);
auto bytesWrittenExpected = writeFrame(maxDataFrame, pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2101,7 +2156,8 @@ TEST_F(QuicWriteCodecTest, NoSpaceForMaxData) {
pktBuilder.remaining_ = 0;
setupCommonExpects(pktBuilder);
MaxDataFrame maxDataFrame(1000);
EXPECT_EQ(0, writeFrame(maxDataFrame, pktBuilder));
ASSERT_FALSE(writeFrame(maxDataFrame, pktBuilder).hasError());
EXPECT_EQ(0, writeFrame(maxDataFrame, pktBuilder).value());
}
TEST_F(QuicWriteCodecTest, WriteMaxStreamId) {
@ -2111,8 +2167,10 @@ TEST_F(QuicWriteCodecTest, WriteMaxStreamId) {
uint64_t maxStream = i;
bool isBidirectional = true;
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
auto bytesWritten =
auto bytesWrittenExpected =
writeFrame(QuicSimpleFrame(maxStreamsFrame), pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2142,8 +2200,10 @@ TEST_F(QuicWriteCodecTest, WriteUniMaxStreamId) {
uint64_t maxStream = i;
bool isBidirectional = false;
MaxStreamsFrame maxStreamsFrame(maxStream, isBidirectional);
auto bytesWritten =
auto bytesWrittenExpected =
writeFrame(QuicSimpleFrame(maxStreamsFrame), pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2170,18 +2230,22 @@ TEST_F(QuicWriteCodecTest, NoSpaceForMaxStreamId) {
pktBuilder.remaining_ = 0;
setupCommonExpects(pktBuilder);
StreamId maxStream = 0x1234;
MaxStreamsFrame maxStreamIdFrame(maxStream, true);
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(maxStreamIdFrame), pktBuilder));
auto result =
writeFrame(QuicSimpleFrame(MaxStreamsFrame(maxStream, true)), pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WriteConnClose) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
std::string reasonPhrase("You are fired");
ConnectionCloseFrame connectionCloseFrame(
QuicErrorCode(TransportErrorCode::PROTOCOL_VIOLATION), reasonPhrase);
auto connCloseBytesWritten =
writeFrame(std::move(connectionCloseFrame), pktBuilder);
auto connCloseBytesWrittenExpected = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(TransportErrorCode::PROTOCOL_VIOLATION), reasonPhrase),
pktBuilder);
ASSERT_FALSE(connCloseBytesWrittenExpected.hasError());
auto connCloseBytesWritten = connCloseBytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2213,9 +2277,11 @@ TEST_F(QuicWriteCodecTest, DecodeConnCloseLarge) {
setupCommonExpects(pktBuilder);
std::string reasonPhrase;
reasonPhrase.resize(kMaxReasonPhraseLength + 10);
ConnectionCloseFrame connectionCloseFrame(
QuicErrorCode(TransportErrorCode::PROTOCOL_VIOLATION), reasonPhrase);
writeFrame(connectionCloseFrame, pktBuilder);
auto result = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(TransportErrorCode::PROTOCOL_VIOLATION), reasonPhrase),
pktBuilder);
ASSERT_FALSE(result.hasError());
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
auto& resultConnCloseFrame =
@ -2236,9 +2302,12 @@ TEST_F(QuicWriteCodecTest, NoSpaceConnClose) {
pktBuilder.remaining_ = 2;
setupCommonExpects(pktBuilder);
std::string reasonPhrase("You are all fired");
ConnectionCloseFrame connCloseFrame(
QuicErrorCode(TransportErrorCode::PROTOCOL_VIOLATION), reasonPhrase);
EXPECT_EQ(0, writeFrame(std::move(connCloseFrame), pktBuilder));
auto result = writeFrame(
ConnectionCloseFrame(
QuicErrorCode(TransportErrorCode::PROTOCOL_VIOLATION), reasonPhrase),
pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
@ -2250,7 +2319,8 @@ TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
QuicErrorCode(GenericApplicationErrorCode::UNKNOWN),
reasonPhrase,
quic::FrameType::CONNECTION_CLOSE_APP_ERR);
writeFrame(std::move(applicationCloseFrame), pktBuilder);
auto result = writeFrame(std::move(applicationCloseFrame), pktBuilder);
ASSERT_FALSE(result.hasError());
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2269,7 +2339,9 @@ TEST_F(QuicWriteCodecTest, DecodeAppCloseLarge) {
TEST_F(QuicWriteCodecTest, WritePing) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
auto pingBytesWritten = writeFrame(PingFrame(), pktBuilder);
auto pingBytesWrittenExpected = writeFrame(PingFrame(), pktBuilder);
ASSERT_FALSE(pingBytesWrittenExpected.hasError());
auto pingBytesWritten = pingBytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2292,13 +2364,17 @@ TEST_F(QuicWriteCodecTest, NoSpaceForPing) {
MockQuicPacketBuilder pktBuilder;
pktBuilder.remaining_ = 0;
setupCommonExpects(pktBuilder);
EXPECT_EQ(0, writeFrame(PingFrame(), pktBuilder));
auto result = writeFrame(PingFrame(), pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WritePadding) {
MockQuicPacketBuilder pktBuilder;
setupCommonExpects(pktBuilder);
auto paddingBytesWritten = writeFrame(PaddingFrame(), pktBuilder);
auto paddingBytesWrittenExpected = writeFrame(PaddingFrame(), pktBuilder);
ASSERT_FALSE(paddingBytesWrittenExpected.hasError());
auto paddingBytesWritten = paddingBytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2320,7 +2396,9 @@ TEST_F(QuicWriteCodecTest, NoSpaceForPadding) {
pktBuilder.remaining_ = 0;
setupCommonExpects(pktBuilder);
PaddingFrame paddingFrame;
EXPECT_EQ(0, writeFrame(paddingFrame, pktBuilder));
auto result = writeFrame(paddingFrame, pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WriteStreamBlocked) {
@ -2329,7 +2407,9 @@ TEST_F(QuicWriteCodecTest, WriteStreamBlocked) {
StreamId blockedId = 0xF00D;
uint64_t blockedOffset = 0x1111;
StreamDataBlockedFrame blockedFrame(blockedId, blockedOffset);
auto blockedBytesWritten = writeFrame(blockedFrame, pktBuilder);
auto blockedBytesWrittenExpected = writeFrame(blockedFrame, pktBuilder);
ASSERT_FALSE(blockedBytesWrittenExpected.hasError());
auto blockedBytesWritten = blockedBytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2354,7 +2434,9 @@ TEST_F(QuicWriteCodecTest, NoSpaceForBlockedStream) {
StreamId blockedStream = 0x01;
uint64_t blockedOffset = 0x1111;
StreamDataBlockedFrame blockedFrame(blockedStream, blockedOffset);
EXPECT_EQ(0, writeFrame(blockedFrame, pktBuilder));
auto result = writeFrame(blockedFrame, pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WriteRstStream) {
@ -2364,7 +2446,9 @@ TEST_F(QuicWriteCodecTest, WriteRstStream) {
ApplicationErrorCode errorCode = GenericApplicationErrorCode::UNKNOWN;
uint64_t offset = 0xF00D;
RstStreamFrame rstStreamFrame(id, errorCode, offset);
auto rstStreamBytesWritten = writeFrame(rstStreamFrame, pktBuilder);
auto rstStreamBytesWrittenExpected = writeFrame(rstStreamFrame, pktBuilder);
ASSERT_FALSE(rstStreamBytesWrittenExpected.hasError());
auto rstStreamBytesWritten = rstStreamBytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2394,7 +2478,9 @@ TEST_F(QuicWriteCodecTest, NoSpaceForRst) {
ApplicationErrorCode errorCode = GenericApplicationErrorCode::UNKNOWN;
uint64_t offset = 0xF00D;
RstStreamFrame rstStreamFrame(id, errorCode, offset);
EXPECT_EQ(0, writeFrame(rstStreamFrame, pktBuilder));
auto result = writeFrame(rstStreamFrame, pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WriteRstStreamAt) {
@ -2405,7 +2491,9 @@ TEST_F(QuicWriteCodecTest, WriteRstStreamAt) {
uint64_t finalSize = 0xF00D;
uint64_t reliableSize = 0xF00C;
RstStreamFrame rstStreamFrame(id, errorCode, finalSize, reliableSize);
auto rstStreamBytesWritten = writeFrame(rstStreamFrame, pktBuilder);
auto rstStreamBytesWrittenExpected = writeFrame(rstStreamFrame, pktBuilder);
ASSERT_FALSE(rstStreamBytesWrittenExpected.hasError());
auto rstStreamBytesWritten = rstStreamBytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2434,7 +2522,9 @@ TEST_F(QuicWriteCodecTest, WriteBlockedFrame) {
setupCommonExpects(pktBuilder);
uint64_t blockedOffset = 0x11111;
DataBlockedFrame blockedFrame(blockedOffset);
auto bytesWritten = writeFrame(blockedFrame, pktBuilder);
auto bytesWrittenExpected = writeFrame(blockedFrame, pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2456,7 +2546,9 @@ TEST_F(QuicWriteCodecTest, NoSpaceForBlocked) {
setupCommonExpects(pktBuilder);
uint64_t blockedOffset = 0x11111;
DataBlockedFrame blockedFrame(blockedOffset);
EXPECT_EQ(0, writeFrame(blockedFrame, pktBuilder));
auto result = writeFrame(blockedFrame, pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WriteStreamIdNeeded) {
@ -2464,7 +2556,10 @@ TEST_F(QuicWriteCodecTest, WriteStreamIdNeeded) {
setupCommonExpects(pktBuilder);
StreamId blockedStreamId = 0x211;
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
auto bytesWritten = writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder);
auto bytesWrittenExpected =
writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2489,7 +2584,9 @@ TEST_F(QuicWriteCodecTest, NoSpaceForStreamIdNeeded) {
setupCommonExpects(pktBuilder);
StreamId blockedStreamId = 0x211;
MaxStreamsFrame streamIdNeeded(blockedStreamId, true);
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder));
auto result = writeFrame(QuicSimpleFrame(streamIdNeeded), pktBuilder);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(QuicWriteCodecTest, WriteNewConnId) {
@ -2498,7 +2595,10 @@ TEST_F(QuicWriteCodecTest, WriteNewConnId) {
StatelessResetToken token;
memset(token.data(), 'a', token.size());
NewConnectionIdFrame newConnId(1, 0, getTestConnectionId(), token);
auto bytesWritten = writeFrame(QuicSimpleFrame(newConnId), pktBuilder);
auto bytesWrittenExpected =
writeFrame(QuicSimpleFrame(newConnId), pktBuilder);
ASSERT_FALSE(bytesWrittenExpected.hasError());
auto bytesWritten = bytesWrittenExpected.value();
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
@ -2528,10 +2628,11 @@ TEST_F(QuicWriteCodecTest, WriteRetireConnId) {
setupCommonExpects(pktBuilder);
RetireConnectionIdFrame retireConnId(3);
auto bytesWritten = writeFrame(QuicSimpleFrame(retireConnId), pktBuilder);
ASSERT_FALSE(bytesWritten.hasError());
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 2);
EXPECT_EQ(bytesWritten.value(), 2);
RetireConnectionIdFrame resultRetireConnIdFrame =
*regularPacket.frames[0].asQuicSimpleFrame()->asRetireConnectionIdFrame();
EXPECT_EQ(resultRetireConnIdFrame.sequenceNumber, 3);
@ -2555,10 +2656,11 @@ TEST_F(QuicWriteCodecTest, WriteStopSending) {
StopSendingFrame stopSending(streamId, errorCode);
auto bytesWritten = writeSimpleFrame(stopSending, pktBuilder);
ASSERT_FALSE(bytesWritten.hasError());
auto builtOut = std::move(pktBuilder).buildTestPacket();
auto regularPacket = builtOut.first;
EXPECT_EQ(bytesWritten, 10);
EXPECT_EQ(bytesWritten.value(), 10);
auto wireBuf = std::move(builtOut.second);
BufQueue queue;
@ -2577,7 +2679,8 @@ TEST_F(QuicWriteCodecTest, NoSpaceForNewConnId) {
setupCommonExpects(pktBuilder);
NewConnectionIdFrame newConnId(
1, 0, getTestConnectionId(), StatelessResetToken());
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(newConnId), pktBuilder));
ASSERT_FALSE(writeFrame(QuicSimpleFrame(newConnId), pktBuilder).hasError());
EXPECT_EQ(0, writeFrame(QuicSimpleFrame(newConnId), pktBuilder).value());
}
TEST_F(QuicWriteCodecTest, WritePathChallenge) {
@ -2587,7 +2690,8 @@ TEST_F(QuicWriteCodecTest, WritePathChallenge) {
uint64_t pathData = 0x64;
PathChallengeFrame pathChallenge(pathData);
auto bytesWritten = writeSimpleFrame(pathChallenge, pktBuilder);
EXPECT_EQ(bytesWritten, 9);
ASSERT_FALSE(bytesWritten.hasError());
EXPECT_EQ(bytesWritten.value(), 9);
auto builtOut = std::move(pktBuilder).buildTestPacket();
@ -2614,7 +2718,8 @@ TEST_F(QuicWriteCodecTest, WritePathResponse) {
uint64_t pathData = 0x64;
PathResponseFrame pathResponse(pathData);
auto bytesWritten = writeSimpleFrame(pathResponse, pktBuilder);
EXPECT_EQ(bytesWritten, 9);
ASSERT_FALSE(bytesWritten.hasError());
EXPECT_EQ(bytesWritten.value(), 9);
auto builtOut = std::move(pktBuilder).buildTestPacket();
@ -2700,7 +2805,10 @@ TEST_F(QuicWriteCodecTest, WriteAckFrequencyFrame) {
frame.reorderThreshold = 50; // Length: 1
auto dataLen = writeSimpleFrame(frame, pktBuilder);
ASSERT_EQ(dataLen, 10); // Based upon the values passed above + 2 (frame-type)
ASSERT_FALSE(dataLen.hasError());
ASSERT_EQ(
dataLen.value(),
10); // Based upon the values passed above + 2 (frame-type)
auto outputBuf = pktBuilder.data_->clone();
EXPECT_EQ(outputBuf->computeChainDataLength(), 10);

View File

@ -21,7 +21,7 @@ std::pair<uint8_t, Buf> encodeShortHeader(const ShortHeader& header) {
ShortHeader headerCopy = header;
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(headerCopy), 0 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
auto packet = std::move(builder).buildPacket();
Buf out;
folly::io::Cursor cursor(&packet.header);
@ -61,7 +61,7 @@ folly::Expected<ParsedLongHeaderResult, TransportErrorCode> makeLongHeader(
packetType == LongHeader::Types::Retry ? std::move(headerRetry)
: std::move(headerRegular),
0 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
folly::io::Cursor cursor(packet.get());
uint8_t initialByte = cursor.readBE<uint8_t>();

View File

@ -132,7 +132,7 @@ RegularQuicPacketBuilder::Packet AckPacketBuilder::build() && {
std::move(*header),
getAckState(*CHECK_NOTNULL(dstConn), ackPnSpace)
.largestAckScheduled.value_or(0));
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
if (maybeAead) {
builder.accountForCipherOverhead(maybeAead.value()->getCipherOverhead());
}
@ -145,7 +145,7 @@ RegularQuicPacketBuilder::Packet AckPacketBuilder::build() && {
static_cast<uint8_t>(
CHECK_NOTNULL(dstConn)->transportSettings.ackDelayExponent),
TimePoint()};
writeAckFrame(ackData, builder);
CHECK(!writeAckFrame(ackData, builder).hasError());
return std::move(builder).buildPacket();
}

View File

@ -305,7 +305,7 @@ RegularQuicPacketBuilder::Packet createStreamPacket(
builder.reset(new RegularQuicPacketBuilder(
packetSizeLimit, std::move(header), largestAcked));
}
builder->encodePacketHeader();
CHECK(!builder->encodePacketHeader().hasError());
builder->accountForCipherOverhead(cipherOverhead);
auto res = *writeStreamFrameHeader(
*builder,
@ -353,7 +353,7 @@ RegularQuicPacketBuilder::Packet createInitialCryptoPacket(
if (!builder) {
builder = &fallbackBuilder;
}
builder->encodePacketHeader();
CHECK(!builder->encodePacketHeader().hasError());
builder->accountForCipherOverhead(aead.getCipherOverhead());
auto res = writeCryptoFrame(offset, data, *builder);
CHECK(res.hasValue()) << "failed to write crypto frame";
@ -396,7 +396,7 @@ RegularQuicPacketBuilder::Packet createCryptoPacket(
}
RegularQuicPacketBuilder builder(
packetSizeLimit, std::move(*header), largestAcked);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(aead.getCipherOverhead());
auto res = writeCryptoFrame(offset, data, builder);
CHECK(res.hasValue()) << "failed to write crypto frame";

View File

@ -38,7 +38,7 @@ bool PacketGroupWriter::writeSingleQuicPacket(
std::move(shortHeader),
largestAckedByPeer,
0);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(aead.getCipherOverhead());
// frontend has already limited the length to flow control, thus
// flowControlLen == length

View File

@ -54,8 +54,8 @@ DSRStreamFrameScheduler::enrichAndAddSendInstruction(
* same backend. Thus one SendInstruction can only have one stream. So this API
* only write a single stream.
*/
DSRStreamFrameScheduler::SchedulingResult DSRStreamFrameScheduler::writeStream(
DSRPacketBuilderBase& builder) {
folly::Expected<DSRStreamFrameScheduler::SchedulingResult, QuicError>
DSRStreamFrameScheduler::writeStream(DSRPacketBuilderBase& builder) {
SchedulingResult result;
auto& writeQueue = conn_.streamManager->writeQueue();
const auto& levelIter = std::find_if(
@ -78,7 +78,7 @@ DSRStreamFrameScheduler::SchedulingResult DSRStreamFrameScheduler::writeStream(
CHECK(stream->hasSchedulableDsr());
if (hasLossBufMeta) {
SendInstruction::Builder instructionBuilder(conn_, streamId);
auto encodedSize = writeDSRStreamFrame(
auto encodedSizeExpected = writeDSRStreamFrame(
builder,
instructionBuilder,
streamId,
@ -88,6 +88,12 @@ DSRStreamFrameScheduler::SchedulingResult DSRStreamFrameScheduler::writeStream(
.length, // flowControlLen shouldn't be used to limit loss write
stream->lossBufMetas.front().eof,
stream->currentWriteOffset + stream->pendingWrites.chainLength());
if (encodedSizeExpected.hasError()) {
return folly::makeUnexpected(encodedSizeExpected.error());
}
auto encodedSize = encodedSizeExpected.value();
if (encodedSize > 0) {
if (builder.remainingSpace() < encodedSize) {
return result;
@ -123,7 +129,7 @@ DSRStreamFrameScheduler::SchedulingResult DSRStreamFrameScheduler::writeStream(
bool canWriteFin = stream->finalWriteOffset.has_value() &&
stream->writeBufMeta.length <= flowControlLen;
SendInstruction::Builder instructionBuilder(conn_, streamId);
auto encodedSize = writeDSRStreamFrame(
auto encodedSizeExpected = writeDSRStreamFrame(
builder,
instructionBuilder,
streamId,
@ -132,6 +138,12 @@ DSRStreamFrameScheduler::SchedulingResult DSRStreamFrameScheduler::writeStream(
flowControlLen,
canWriteFin,
stream->currentWriteOffset + stream->pendingWrites.chainLength());
if (encodedSizeExpected.hasError()) {
return folly::makeUnexpected(encodedSizeExpected.error());
}
auto encodedSize = encodedSizeExpected.value();
if (encodedSize > 0) {
if (builder.remainingSpace() < encodedSize) {
return result;

View File

@ -31,7 +31,8 @@ class DSRStreamFrameScheduler {
};
// Write a single stream's data into builder.
SchedulingResult writeStream(DSRPacketBuilderBase& builder);
[[nodiscard]] folly::Expected<SchedulingResult, QuicError> writeStream(
DSRPacketBuilderBase& builder);
private:
void enrichInstruction(

View File

@ -9,7 +9,8 @@
#include <quic/dsr/frontend/WriteCodec.h>
namespace quic {
uint32_t writeDSRStreamFrame(
folly::Expected<uint32_t, QuicError> writeDSRStreamFrame(
DSRPacketBuilderBase& packetBuilder,
SendInstruction::Builder& instructionBuilder,
StreamId id,
@ -22,13 +23,17 @@ uint32_t writeDSRStreamFrame(
return 0;
}
if (writeBufferLen == 0 && !fin) {
throw QuicInternalException(
"No data or fin supplied when writing stream.",
LocalErrorCode::INTERNAL_ERROR);
return folly::makeUnexpected(QuicError(
TransportErrorCode::INTERNAL_ERROR,
"No data or fin supplied when writing stream."));
}
QuicInteger idInt(id);
uint64_t headerSize = sizeof(uint8_t) + idInt.getSize();
auto idIntSize = idInt.getSize();
if (idIntSize.hasError()) {
return folly::makeUnexpected(idIntSize.error());
}
uint64_t headerSize = sizeof(uint8_t) + idIntSize.value();
if (packetBuilder.remainingSpace() < headerSize) {
VLOG(4) << "No space in packet for stream header. stream=" << id
<< " limit=" << packetBuilder.remainingSpace();
@ -37,7 +42,11 @@ uint32_t writeDSRStreamFrame(
QuicInteger offsetInt(offset);
if (offset != 0) {
headerSize += offsetInt.getSize();
auto offsetIntSize = offsetInt.getSize();
if (offsetIntSize.hasError()) {
return folly::makeUnexpected(offsetIntSize.error());
}
headerSize += offsetIntSize.value();
}
instructionBuilder.setStreamOffset(offset);

View File

@ -11,7 +11,7 @@
#include <quic/dsr/frontend/PacketBuilder.h>
namespace quic {
uint32_t writeDSRStreamFrame(
[[nodiscard]] folly::Expected<uint32_t, QuicError> writeDSRStreamFrame(
DSRPacketBuilderBase& packetBuilder,
SendInstruction::Builder& instructionBuilder,
StreamId id,

View File

@ -50,7 +50,10 @@ folly::Expected<uint64_t, QuicError> writePacketizationRequest(
getAckState(connection, PacketNumberSpace::AppData)
.largestAckedByPeer.value_or(0));
auto schedulerResult = scheduler.writeStream(packetBuilder);
if (!schedulerResult.writeSuccess) {
if (schedulerResult.hasError()) {
return folly::makeUnexpected(schedulerResult.error());
}
if (!schedulerResult->writeSuccess) {
/**
* Scheduling can fail when we:
* (1) run out of flow control
@ -61,19 +64,19 @@ folly::Expected<uint64_t, QuicError> writePacketizationRequest(
*
* At least for (1) and (3), we should flush the sender.
*/
if (schedulerResult.sender) {
senders.insert(schedulerResult.sender);
if (schedulerResult->sender) {
senders.insert(schedulerResult->sender);
}
return packetCounter;
}
CHECK(schedulerResult.sender);
CHECK(schedulerResult->sender);
auto packet = std::move(packetBuilder).buildPacket();
// The contract is that if scheduler can schedule, builder has to be able to
// build.
CHECK_GT(packet.encodedSize, 0u);
bool instructionAddError = false;
for (const auto& instruction : packet.sendInstructions) {
if (!schedulerResult.sender->addSendInstruction(instruction)) {
if (!schedulerResult->sender->addSendInstruction(instruction)) {
instructionAddError = true;
break;
}
@ -101,12 +104,13 @@ folly::Expected<uint64_t, QuicError> writePacketizationRequest(
if (instructionAddError) {
// TODO: Support empty write loop detection
senders.insert(schedulerResult.sender);
senders.insert(schedulerResult->sender);
return packetCounter;
}
++packetCounter;
senders.insert(schedulerResult.sender);
senders.insert(schedulerResult->sender);
}
return packetCounter;
}
} // namespace quic

View File

@ -52,7 +52,9 @@ TEST_F(SchedulerTest, ScheduleStream) {
writtenLength = instruction.len;
EXPECT_FALSE(instruction.fin);
}));
EXPECT_TRUE(scheduler.writeStream(builder_).writeSuccess);
auto result = scheduler.writeStream(builder_);
ASSERT_FALSE(result.hasError());
EXPECT_TRUE(result.value().writeSuccess);
auto writtenMeta = stream->writeBufMeta.split(writtenLength);
auto nextExpectedOffset = stream->writeBufMeta.offset;
@ -79,7 +81,9 @@ TEST_F(SchedulerTest, ScheduleStream) {
writtenLength = instruction.len;
EXPECT_TRUE(instruction.fin);
}));
EXPECT_TRUE(scheduler.writeStream(builder_).writeSuccess);
result = scheduler.writeStream(builder_);
ASSERT_FALSE(result.hasError());
EXPECT_TRUE(result.value().writeSuccess);
auto nextWrittenMeta = stream->writeBufMeta.split(writtenLength);
EXPECT_EQ(stream->writeBufMeta.length, 0);

View File

@ -41,19 +41,19 @@ class WriteCodecTest : public DSRCommonTestFixture {
TEST_F(WriteCodecTest, NoPacketSize) {
packetSize_ = 0;
auto instructionBuilder = createBuilder();
EXPECT_EQ(
0,
writeDSRStreamFrame(
builder_, instructionBuilder, 0, 0, 100, 100, true, 3));
auto result = writeDSRStreamFrame(
builder_, instructionBuilder, 0, 0, 100, 100, true, 3);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(WriteCodecTest, TooSmallPacketSize) {
packetSize_ = 1;
auto instructionBuilder = createBuilder();
EXPECT_EQ(
0,
writeDSRStreamFrame(
builder_, instructionBuilder, 0, 0, 100, 100, true, 1));
auto result = writeDSRStreamFrame(
builder_, instructionBuilder, 0, 0, 100, 100, true, 1);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(WriteCodecTest, RegularWrite) {
@ -73,8 +73,9 @@ TEST_F(WriteCodecTest, RegularWrite) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_EQ(dataLen, sendInstruction.len);
@ -99,8 +100,9 @@ TEST_F(WriteCodecTest, PacketSizeLimit) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_GT(dataLen, sendInstruction.len);
@ -125,8 +127,9 @@ TEST_F(WriteCodecTest, FlowControlLimit) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_EQ(flowControlLen, sendInstruction.len);
@ -152,7 +155,8 @@ TEST_F(WriteCodecTest, NoSpaceForData) {
flowControlLen,
fin,
bufMetaStartingOffset);
EXPECT_EQ(0, result);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(WriteCodecTest, CanHaveOneByteData) {
@ -173,8 +177,9 @@ TEST_F(WriteCodecTest, CanHaveOneByteData) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_EQ(1, sendInstruction.len);
@ -191,17 +196,17 @@ TEST_F(WriteCodecTest, PacketSpaceEqStreamHeaderSize) {
uint64_t bufMetaStartingOffset = 333;
auto instructionBuilder = createBuilder();
packetSize_ = 2;
EXPECT_EQ(
0,
writeDSRStreamFrame(
builder_,
instructionBuilder,
stream,
offset,
dataLen,
flowControlLen,
fin,
bufMetaStartingOffset));
auto result = writeDSRStreamFrame(
builder_,
instructionBuilder,
stream,
offset,
dataLen,
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
EXPECT_EQ(0, result.value());
}
TEST_F(WriteCodecTest, PacketSpaceEqStreamHeaderSizeWithFIN) {
@ -222,8 +227,9 @@ TEST_F(WriteCodecTest, PacketSpaceEqStreamHeaderSizeWithFIN) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_EQ(0, sendInstruction.len);
@ -248,8 +254,9 @@ TEST_F(WriteCodecTest, WriteFIN) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_EQ(10, sendInstruction.len);
@ -274,8 +281,9 @@ TEST_F(WriteCodecTest, FINWithoutData) {
flowControlLen,
fin,
bufMetaStartingOffset);
ASSERT_FALSE(result.hasError());
auto sendInstruction = instructionBuilder.build();
EXPECT_GT(result, 0);
EXPECT_GT(result.value(), 0);
EXPECT_EQ(stream, sendInstruction.streamId);
EXPECT_EQ(offset, sendInstruction.streamOffset);
EXPECT_EQ(0, sendInstruction.len);
@ -291,16 +299,15 @@ TEST_F(WriteCodecTest, NoFINNoData) {
uint64_t flowControlLen = 10;
uint64_t bufMetaStartingOffset = 333;
auto instructionBuilder = createBuilder();
EXPECT_THROW(
writeDSRStreamFrame(
builder_,
instructionBuilder,
stream,
offset,
dataLen,
flowControlLen,
fin,
bufMetaStartingOffset),
QuicInternalException);
EXPECT_TRUE(writeDSRStreamFrame(
builder_,
instructionBuilder,
stream,
offset,
dataLen,
flowControlLen,
fin,
bufMetaStartingOffset)
.hasError());
}
} // namespace quic::test

View File

@ -2629,12 +2629,13 @@ TEST_F(QuicClientTransportAfterStartTest, RecvNewConnectionIdValid) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
auto token = StatelessResetToken{1, 9, 2, 0};
NewConnectionIdFrame newConnId(1, 0, ConnectionId({2, 4, 2, 3}), token);
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2669,7 +2670,7 @@ TEST_F(QuicClientTransportAfterStartTest, ShortHeaderPacketWithNoFrames) {
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
Buf buf = packetToBuf(std::move(builder).buildPacket());
buf->coalesce();
@ -2695,11 +2696,12 @@ TEST_F(
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(
1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2716,11 +2718,12 @@ TEST_F(QuicClientTransportAfterStartTest, RecvNewConnectionIdInvalidRetire) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(
1, 3, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2740,11 +2743,12 @@ TEST_F(QuicClientTransportAfterStartTest, RecvNewConnectionIdUsing0LenCid) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(
1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2771,10 +2775,11 @@ TEST_F(
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(1, 0, connId2, StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2796,10 +2801,11 @@ TEST_F(
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(2, 0, connId2, StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2925,10 +2931,11 @@ TEST_F(QuicClientTransportAfterStartTest, RecvPathChallengeNoAvailablePeerIds) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
PathChallengeFrame pathChallenge(123);
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -2952,10 +2959,11 @@ TEST_F(QuicClientTransportAfterStartTest, RecvPathChallengeAvailablePeerId) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
PathChallengeFrame pathChallenge(123);
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto data = packetToBuf(packet);
@ -3614,9 +3622,9 @@ TEST_F(
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(rstFrame, builder);
ASSERT_FALSE(writeFrame(rstFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
EXPECT_THROW(deliverData(packet->coalesce()), std::runtime_error);
}
@ -3632,9 +3640,9 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveReliableRst) {
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(rstFrame, builder);
ASSERT_FALSE(writeFrame(rstFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
deliverDataWithoutErrorCheck(packet->coalesce());
EXPECT_EQ(
@ -3656,8 +3664,8 @@ TEST_F(
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
writeFrame(rstFrame, builder);
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(rstFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
deliverData(packet->coalesce());
@ -3670,8 +3678,8 @@ TEST_F(
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder2.encodePacketHeader();
writeFrame(rstFrame, builder2);
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(rstFrame, builder2).hasError());
auto data = folly::IOBuf::copyBuffer("hello");
writeStreamFrameHeader(
@ -3724,9 +3732,9 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveRstStreamAfterEom) {
ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
RegularQuicPacketBuilder builder(
client->getConn().udpSendPacketLen, std::move(header), 0);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(rstFrame, builder);
ASSERT_FALSE(writeFrame(rstFrame, builder).hasError());
auto packet2 = packetToBuf(std::move(builder).buildPacket());
deliverData(packet2->coalesce());
@ -4171,15 +4179,14 @@ TEST_F(QuicClientTransportVersionAndRetryTest, UnencryptedAckData) {
version);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
DCHECK(builder.canBuildPacket());
// WriteAckFrameMetaData ackData(acks, 0us, 0);
WriteAckFrameState writeAckState = {.acks = acks};
WriteAckFrameMetaData ackData = {
.ackState = writeAckState,
.ackDelay = 0us,
.ackDelayExponent = static_cast<uint8_t>(kDefaultAckDelayExponent)};
writeAckFrame(ackData, builder);
ASSERT_FALSE(writeAckFrame(ackData, builder).hasError());
auto packet = packetToBufCleartext(
std::move(builder).buildPacket(),
getInitialCipher(),
@ -4198,9 +4205,9 @@ TEST_F(QuicClientTransportVersionAndRetryTest, UnencryptedPing) {
version);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
DCHECK(builder.canBuildPacket());
writeFrame(PingFrame(), builder);
ASSERT_FALSE(writeFrame(PingFrame(), builder).hasError());
auto packet = packetToBufCleartext(
std::move(builder).buildPacket(),
getInitialCipher(),
@ -4226,9 +4233,9 @@ Buf getHandshakePacketWithFrame(
kDefaultUDPSendPacketLen,
std::move(header),
packetNum / 2 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(serverWriteCipher.getCipherOverhead());
writeFrame(std::move(frame), builder);
CHECK(!writeFrame(std::move(frame), builder).hasError());
return packetToBufCleartext(
std::move(builder).buildPacket(),
serverWriteCipher,
@ -4548,11 +4555,11 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveConnectionClose) {
ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
RegularQuicPacketBuilder builder(
client->getConn().udpSendPacketLen, std::move(header), 0);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ConnectionCloseFrame connClose(
QuicErrorCode(TransportErrorCode::NO_ERROR),
"Stand clear of the closing doors, please");
writeFrame(std::move(connClose), builder);
ASSERT_FALSE(writeFrame(std::move(connClose), builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
EXPECT_CALL(clientConnCallback, onConnectionEnd());
deliverDataWithoutErrorCheck(packet->coalesce());
@ -4575,11 +4582,11 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveApplicationClose) {
ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
RegularQuicPacketBuilder builder(
client->getConn().udpSendPacketLen, std::move(header), 0);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ConnectionCloseFrame appClose(
QuicErrorCode(GenericApplicationErrorCode::UNKNOWN),
"Stand clear of the closing doors, please");
writeFrame(std::move(appClose), builder);
ASSERT_FALSE(writeFrame(std::move(appClose), builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
EXPECT_FALSE(client->isClosed());
socketWrites.clear();
@ -4614,10 +4621,10 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveApplicationCloseNoError) {
ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
RegularQuicPacketBuilder builder(
client->getConn().udpSendPacketLen, std::move(header), 0);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ConnectionCloseFrame appClose(
QuicErrorCode(GenericApplicationErrorCode::NO_ERROR), "No Error");
writeFrame(std::move(appClose), builder);
ASSERT_FALSE(writeFrame(std::move(appClose), builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
EXPECT_FALSE(client->isClosed());
socketWrites.clear();
@ -4799,8 +4806,8 @@ TEST_F(QuicClientTransportAfterStartTest, PingIsTreatedAsRetransmittable) {
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
writeFrame(pingFrame, builder);
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(pingFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
deliverData(packet->coalesce());
EXPECT_TRUE(client->getConn().pendingEvents.scheduleAckTimeout);
@ -4814,13 +4821,13 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveDatagramFrameAndDiscard) {
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
EXPECT_CALL(*quicStats_, onDatagramDroppedOnRead()).Times(1);
StringPiece datagramPayload = "do not rely on me. I am unreliable";
DatagramFrame datagramFrame(
datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
writeFrame(datagramFrame, builder);
ASSERT_FALSE(writeFrame(datagramFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
deliverData(packet->coalesce());
ASSERT_EQ(client->getConn().datagramState.readBuffer.size(), 0);
@ -4844,12 +4851,12 @@ TEST_F(QuicClientTransportAfterStartTest, ReceiveDatagramFrameAndStore) {
client->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StringPiece datagramPayload = "do not rely on me. I am unreliable";
DatagramFrame datagramFrame(
datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
writeFrame(datagramFrame, builder);
ASSERT_FALSE(writeFrame(datagramFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
deliverData(packet->coalesce());
if (i < conn.datagramState.maxReadBufferSize) {
@ -4877,11 +4884,11 @@ TEST_F(
client->getConn().udpSendPacketLen,
std::move(header1),
0 /* largestAcked */);
builder1.encodePacketHeader();
ASSERT_FALSE(builder1.encodePacketHeader().hasError());
StringPiece datagramPayload1 = "first";
DatagramFrame datagramFrame1(
datagramPayload1.size(), IOBuf::copyBuffer(datagramPayload1));
writeFrame(datagramFrame1, builder1);
ASSERT_FALSE(writeFrame(datagramFrame1, builder1).hasError());
auto packet1 = packetToBuf(std::move(builder1).buildPacket());
EXPECT_CALL(*quicStats_, onDatagramRead(_))
.Times(1)
@ -4897,11 +4904,11 @@ TEST_F(
client->getConn().udpSendPacketLen,
std::move(header2),
0 /* largestAcked */);
builder2.encodePacketHeader();
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
StringPiece datagramPayload2 = "second";
DatagramFrame datagramFrame2(
datagramPayload2.size(), IOBuf::copyBuffer(datagramPayload2));
writeFrame(datagramFrame2, builder2);
ASSERT_FALSE(writeFrame(datagramFrame2, builder2).hasError());
auto packet2 = packetToBuf(std::move(builder2).buildPacket());
EXPECT_CALL(*quicStats_, onDatagramDroppedOnRead()).Times(1);
EXPECT_CALL(*quicStats_, onDatagramRead(_))

View File

@ -241,7 +241,7 @@ PacketNum QuicLossFunctionsTest::sendPacket(
conn.udpSendPacketLen,
std::move(*header),
getAckState(conn, packetNumberSpace).largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
EXPECT_TRUE(builder.canBuildPacket());
auto packet = std::move(builder).buildPacket();
if (forcedSize) {

View File

@ -984,9 +984,9 @@ TEST_F(QuicServerWorkerTest, BlockedSourcePort) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
auto packet = packetToReceivedUdpPacket(std::move(builder).buildPacket());
worker_->handleNetworkData(blockedSrcPort, packet);
@ -1003,9 +1003,9 @@ TEST_F(QuicServerWorkerTest, ZeroLengthConnectionId) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
auto packet = packetToReceivedUdpPacket(std::move(builder).buildPacket());
worker_->handleNetworkData(kClientAddr, packet);
@ -1021,7 +1021,7 @@ TEST_F(QuicServerWorkerTest, ClientInitialCounting) {
LongHeader::Types::Initial, srcConnId, destConnId, num, version);
RegularQuicPacketBuilder initialBuilder(
kDefaultUDPSendPacketLen, std::move(initialHeader), 0);
initialBuilder.encodePacketHeader();
ASSERT_FALSE(initialBuilder.encodePacketHeader().hasError());
auto initialPacket =
packetToReceivedUdpPacket((std::move(initialBuilder).buildPacket()));
EXPECT_CALL(*quicStats_, onClientInitialReceived(QuicVersion::MVFST))
@ -1035,7 +1035,7 @@ TEST_F(QuicServerWorkerTest, ClientInitialCounting) {
LongHeader::Types::Initial, srcConnId, destConnId, bignum, version);
RegularQuicPacketBuilder initialBuilderBigNum(
kDefaultUDPSendPacketLen, std::move(initialHeaderBigNum), 0);
initialBuilderBigNum.encodePacketHeader();
ASSERT_FALSE(initialBuilderBigNum.encodePacketHeader().hasError());
auto initialPacketBigNum = packetToReceivedUdpPacket(
(std::move(initialBuilderBigNum).buildPacket()));
EXPECT_CALL(*quicStats_, onClientInitialReceived(QuicVersion::MVFST))
@ -1047,7 +1047,7 @@ TEST_F(QuicServerWorkerTest, ClientInitialCounting) {
LongHeader::Types::Handshake, srcConnId, destConnId, num, version);
RegularQuicPacketBuilder handshakeBuilder(
kDefaultUDPSendPacketLen, std::move(handshakeHeader), 0);
handshakeBuilder.encodePacketHeader();
ASSERT_FALSE(handshakeBuilder.encodePacketHeader().hasError());
auto handshakePacket =
packetToReceivedUdpPacket((std::move(handshakeBuilder).buildPacket()));
EXPECT_CALL(*quicStats_, onClientInitialReceived(_)).Times(0);
@ -1068,9 +1068,9 @@ TEST_F(QuicServerWorkerTest, ConnectionIdTooShort) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
auto packet = packetToReceivedUdpPacket((std::move(builder).buildPacket()));
worker_->handleNetworkData(kClientAddr, packet);
@ -1091,9 +1091,9 @@ TEST_F(QuicServerWorkerTest, FailToParseConnectionId) {
LongHeader::Types::Initial, srcConnId, dstConnId, num, version);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
auto packet = packetToBuf(std::move(builder).buildPacket());
// To force dropping path, set initial to false
@ -1130,9 +1130,9 @@ TEST_F(QuicServerWorkerTest, ConnectionIdTooShortDispatch) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
auto packet = packetToBuf(std::move(builder).buildPacket());
RoutingData routingData(HeaderForm::Long, true, false, dstConnId, srcConnId);
@ -1158,9 +1158,9 @@ TEST_F(QuicServerWorkerTest, ConnectionIdTooLargeDispatch) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
while (builder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), builder);
ASSERT_FALSE(writeFrame(PaddingFrame(), builder).hasError());
}
auto packet = packetToBuf(std::move(builder).buildPacket());
RoutingData routingData(HeaderForm::Long, true, false, dstConnId, srcConnId);
@ -1201,7 +1201,7 @@ TEST_F(QuicServerWorkerTest, PacketAfterShutdown) {
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
auto packet = packetToReceivedUdpPacket((std::move(builder).buildPacket()));
worker_->handleNetworkData(kClientAddr, packet);
eventbase_.terminateLoopSoon();
@ -1459,7 +1459,7 @@ auto createInitialStream(
pktHeaderType == LongHeader::Types::Retry ? std::move(headerRetry)
: std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
auto streamData = data.clone();
auto res = writeStreamFrameHeader(
builder,
@ -1540,9 +1540,9 @@ class QuicServerWorkerRetryTest : public QuicServerWorkerTest {
RegularQuicPacketBuilder initialBuilder(
kDefaultUDPSendPacketLen, std::move(initialHeader), 0);
initialBuilder.encodePacketHeader();
CHECK(!initialBuilder.encodePacketHeader().hasError());
while (initialBuilder.remainingSpaceInPkt() > 0) {
writeFrame(PaddingFrame(), initialBuilder);
CHECK(!writeFrame(PaddingFrame(), initialBuilder).hasError());
}
auto initialPacket = packetToBuf(std::move(initialBuilder).buildPacket());
RoutingData routingData(

View File

@ -81,7 +81,8 @@ TEST_F(QuicServerTransportTest, TestReadMultipleStreams) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
auto encodeResult = builder.encodePacketHeader();
ASSERT_FALSE(encodeResult.hasError());
ASSERT_TRUE(builder.canBuildPacket());
auto buf1 = IOBuf::copyBuffer("Aloha");
@ -437,13 +438,13 @@ TEST_F(QuicServerTransportTest, ReceivePacketAfterLocalError) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
// Deliver a reset to non existent stream to trigger a local conn error
StreamId streamId = 0x01;
RstStreamFrame rstFrame(streamId, GenericApplicationErrorCode::UNKNOWN, 0);
writeFrame(std::move(rstFrame), builder);
ASSERT_FALSE(writeFrame(std::move(rstFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverDataWithoutErrorCheck(packetToBuf(packet));
EXPECT_TRUE(verifyFramePresent(
@ -460,9 +461,9 @@ TEST_F(QuicServerTransportTest, ReceivePacketAfterLocalError) {
server->getConn().udpSendPacketLen,
std::move(header2),
0 /* largestAcked */);
builder2.encodePacketHeader();
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
RstStreamFrame rstFrame2(streamId, GenericApplicationErrorCode::UNKNOWN, 0);
writeFrame(std::move(rstFrame2), builder2);
ASSERT_FALSE(writeFrame(std::move(rstFrame2), builder2).hasError());
auto packet2 = std::move(builder2).buildPacket();
deliverDataWithoutErrorCheck(packetToBuf(packet2));
EXPECT_TRUE(hasNotReceivedNewPacketsSinceLastCloseSent(server->getConn()));
@ -484,13 +485,13 @@ TEST_F(QuicServerTransportTest, ReceiveCloseAfterLocalError) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
// Deliver a reset to non existent stream to trigger a local conn error
StreamId streamId = 0x01;
RstStreamFrame rstFrame(streamId, GenericApplicationErrorCode::UNKNOWN, 0);
writeFrame(std::move(rstFrame), builder);
ASSERT_FALSE(writeFrame(std::move(rstFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverDataWithoutErrorCheck(packetToBuf(packet));
EXPECT_TRUE(verifyFramePresent(
@ -511,11 +512,11 @@ TEST_F(QuicServerTransportTest, ReceiveCloseAfterLocalError) {
server->getConn().udpSendPacketLen,
std::move(header2),
0 /* largestAcked */);
builder2.encodePacketHeader();
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
std::string errMsg = "Mind the gap";
ConnectionCloseFrame connClose(
QuicErrorCode(TransportErrorCode::NO_ERROR), errMsg);
writeFrame(std::move(connClose), builder2);
ASSERT_FALSE(writeFrame(std::move(connClose), builder2).hasError());
auto packet2 = std::move(builder2).buildPacket();
deliverDataWithoutErrorCheck(packetToBuf(packet2));
@ -552,23 +553,24 @@ TEST_F(QuicServerTransportTest, NoDataExceptCloseProcessedAfterClosing) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
auto buf = folly::IOBuf::copyBuffer("hello");
writeStreamFrameHeader(
builder,
4,
0,
buf->computeChainDataLength(),
buf->computeChainDataLength(),
true,
none /* skipLenHint */);
ASSERT_FALSE(writeStreamFrameHeader(
builder,
4,
0,
buf->computeChainDataLength(),
buf->computeChainDataLength(),
true,
none /* skipLenHint */)
.hasError());
writeStreamFrameData(builder, buf->clone(), buf->computeChainDataLength());
std::string errMsg = "Mind the gap";
ConnectionCloseFrame connClose(
QuicErrorCode(TransportErrorCode::NO_ERROR), errMsg);
writeFrame(std::move(connClose), builder);
ASSERT_FALSE(writeFrame(std::move(connClose), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -725,11 +727,11 @@ TEST_F(QuicServerTransportTest, RecvRstStreamFrameNonexistClientStream) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
RstStreamFrame rstFrame(streamId, GenericApplicationErrorCode::UNKNOWN, 0);
writeFrame(std::move(rstFrame), builder);
ASSERT_FALSE(writeFrame(std::move(rstFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet));
@ -754,8 +756,8 @@ TEST_F(QuicServerTransportTest, ReceiveRstStreamNonExistentAndOtherFrame) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
writeFrame(rstFrame, builder);
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(rstFrame, builder).hasError());
auto packet = packetToBuf(std::move(builder).buildPacket());
deliverData(std::move(packet));
@ -770,18 +772,19 @@ TEST_F(QuicServerTransportTest, ReceiveRstStreamNonExistentAndOtherFrame) {
server->getConn().udpSendPacketLen,
std::move(header2),
0 /* largestAcked */);
builder2.encodePacketHeader();
writeFrame(rstFrame, builder2);
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(rstFrame, builder2).hasError());
auto data = folly::IOBuf::copyBuffer("hello");
writeStreamFrameHeader(
builder2,
streamId,
0,
data->computeChainDataLength(),
data->computeChainDataLength(),
false,
none /* skipLenHint */);
ASSERT_FALSE(writeStreamFrameHeader(
builder2,
streamId,
0,
data->computeChainDataLength(),
data->computeChainDataLength(),
false,
none /* skipLenHint */)
.hasError());
writeStreamFrameData(builder2, data->clone(), data->computeChainDataLength());
auto packetObject = std::move(builder2).buildPacket();
auto packet2 = packetToBuf(std::move(packetObject));
@ -802,12 +805,12 @@ TEST_F(QuicServerTransportTest, RecvRstStreamFrameNonexistServerStream) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
StreamId streamId = 0x01;
RstStreamFrame rstFrame(streamId, GenericApplicationErrorCode::UNKNOWN, 0);
writeFrame(std::move(rstFrame), builder);
ASSERT_FALSE(writeFrame(std::move(rstFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_THROW(deliverData(packetToBuf(packet)), std::runtime_error);
}
@ -851,14 +854,14 @@ TEST_F(QuicServerTransportTest, RecvRstStreamFrame) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
RstStreamFrame rstFrame(
streamId,
GenericApplicationErrorCode::UNKNOWN,
words.at(0).length() + words.at(1).length());
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(rstFrame), builder);
ASSERT_FALSE(writeFrame(std::move(rstFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet));
@ -892,11 +895,11 @@ TEST_F(QuicServerTransportTest, RecvReliableRstStreamFrame) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
RstStreamFrame rstFrame(streamId, GenericApplicationErrorCode::UNKNOWN, 5, 5);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(rstFrame), builder);
ASSERT_FALSE(writeFrame(std::move(rstFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverDataWithoutErrorCheck(packetToBuf(packet));
EXPECT_EQ(
@ -940,11 +943,12 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrame) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
connCallback,
@ -989,12 +993,13 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterCloseStream) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
server->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
EXPECT_CALL(connCallback, onStopSending(_, _)).Times(0);
@ -1038,11 +1043,11 @@ TEST_F(QuicServerTransportTest, RecvInvalidMaxStreamData) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
MaxStreamDataFrame maxStreamDataFrame(streamId, 100);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(std::move(maxStreamDataFrame), builder);
ASSERT_FALSE(writeFrame(std::move(maxStreamDataFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_THROW(deliverData(packetToBuf(packet)), std::runtime_error);
}
@ -1083,7 +1088,7 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterHalfCloseRemote) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
@ -1100,7 +1105,8 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterHalfCloseRemote) {
auto dataLen = *res;
ASSERT_TRUE(dataLen.has_value());
ASSERT_EQ(*dataLen, 0);
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
connCallback,
@ -1119,12 +1125,13 @@ TEST_F(QuicServerTransportTest, RecvStopSendingBeforeStream) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(connCallback, onNewBidirectionalStream(streamId));
EXPECT_CALL(
@ -1185,15 +1192,17 @@ TEST_F(QuicServerTransportTest, RecvStopSendingFrameAfterReset) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame1(
streamId1, GenericApplicationErrorCode::UNKNOWN);
StopSendingFrame stopSendingFrame2(
streamId2, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame1), builder);
writeFrame(QuicSimpleFrame(stopSendingFrame2), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame1), builder).hasError());
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame2), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
connCallback, onStopSending(_, GenericApplicationErrorCode::UNKNOWN))
@ -1218,11 +1227,12 @@ TEST_F(QuicServerTransportTest, StopSendingLoss) {
std::move(header),
server->getConn().ackStates.appDataAckState.largestAckedByPeer.value_or(
0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
ASSERT_FALSE(markPacketLoss(server->getNonConstConn(), packet.packet, false)
.hasError());
@ -1249,11 +1259,12 @@ TEST_F(QuicServerTransportTest, StopSendingLossAfterStreamClosed) {
std::move(header),
server->getConn().ackStates.appDataAckState.largestAckedByPeer.value_or(
0));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StopSendingFrame stopSendingFrame(
streamId, GenericApplicationErrorCode::UNKNOWN);
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
ASSERT_FALSE(
writeFrame(QuicSimpleFrame(stopSendingFrame), builder).hasError());
auto packet = std::move(builder).buildPacket();
// clear out all the streams, this is not a great way to simulate closed
@ -1338,10 +1349,11 @@ TEST_F(QuicServerTransportTest, RecvPathChallenge) {
ProtectionType::KeyPhaseZero, *conn.serverConnectionId, 10);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
PathChallengeFrame pathChallenge(123);
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -1393,11 +1405,11 @@ TEST_F(QuicServerTransportTest, ReceiveConnectionClose) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
std::string errMsg = "Stand clear of the closing doors, please";
ConnectionCloseFrame connClose(
QuicErrorCode(TransportErrorCode::NO_ERROR), errMsg);
writeFrame(std::move(connClose), builder);
ASSERT_FALSE(writeFrame(std::move(connClose), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(connCallback, onConnectionEnd());
deliverDataWithoutErrorCheck(packetToBuf(packet));
@ -1438,11 +1450,11 @@ TEST_F(QuicServerTransportTest, ReceiveConnectionCloseBeforeDatagram) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StringPiece datagramPayload = "do not rely on me. I am unreliable";
DatagramFrame datagramFrame(
datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
writeFrame(datagramFrame, builder);
ASSERT_FALSE(writeFrame(datagramFrame, builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(*quicStats_, onDatagramRead(_)).Times(1);
@ -1467,11 +1479,11 @@ TEST_F(QuicServerTransportTest, ReceiveConnectionCloseBeforeDatagram) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
std::string errMsg = "Stand clear of the closing doors, please";
ConnectionCloseFrame connClose(
QuicErrorCode(TransportErrorCode::NO_ERROR), errMsg);
writeFrame(std::move(connClose), builder);
ASSERT_FALSE(writeFrame(std::move(connClose), builder).hasError());
auto packet = std::move(builder).buildPacket();
// Build late datagram.
@ -1483,11 +1495,11 @@ TEST_F(QuicServerTransportTest, ReceiveConnectionCloseBeforeDatagram) {
server->getConn().udpSendPacketLen,
std::move(header2),
0 /* largestAcked */);
builder2.encodePacketHeader();
ASSERT_FALSE(builder2.encodePacketHeader().hasError());
StringPiece datagramPayload = "do not rely on me. I am unreliable";
DatagramFrame datagramFrame(
datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
writeFrame(datagramFrame, builder2);
ASSERT_FALSE(writeFrame(datagramFrame, builder2).hasError());
auto packet2 = std::move(builder2).buildPacket();
// Deliver conn close followed by late datagram.
@ -1528,12 +1540,12 @@ TEST_F(QuicServerTransportTest, ReceiveApplicationClose) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
std::string errMsg = "Stand clear of the closing doors, please";
ConnectionCloseFrame appClose(
QuicErrorCode(GenericApplicationErrorCode::UNKNOWN), errMsg);
writeFrame(std::move(appClose), builder);
ASSERT_FALSE(writeFrame(std::move(appClose), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(
@ -1569,11 +1581,11 @@ TEST_F(QuicServerTransportTest, ReceiveConnectionCloseTwice) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
std::string errMsg = "Mind the gap";
ConnectionCloseFrame connClose(
QuicErrorCode(TransportErrorCode::NO_ERROR), errMsg);
writeFrame(std::move(connClose), builder);
ASSERT_FALSE(writeFrame(std::move(connClose), builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(connCallback, onConnectionEnd());
deliverDataWithoutErrorCheck(packetToBuf(packet));
@ -1832,7 +1844,7 @@ TEST_F(QuicServerTransportTest, ShortHeaderPacketWithNoFrames) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
Buf buf = packetToBuf(std::move(builder).buildPacket());
@ -1883,7 +1895,7 @@ TEST_F(QuicServerTransportTest, ShortHeaderPacketWithNoFramesAfterClose) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
Buf buf = packetToBuf(std::move(builder).buildPacket());
buf->coalesce();
@ -1949,10 +1961,10 @@ TEST_P(
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(PathChallengeFrame(123), builder);
ASSERT_FALSE(writeSimpleFrame(PathChallengeFrame(123), builder).hasError());
auto packet = std::move(builder).buildPacket();
auto packetData = packetToBuf(packet);
folly::SocketAddress newPeer("100.101.102.103", 23456);
@ -2084,12 +2096,14 @@ TEST_P(QuicServerTransportAllowMigrationTest, MigrateToUnvalidatedPeer) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(
PathResponseFrame(server->getConn().outstandingPathValidation->pathData),
builder);
ASSERT_FALSE(writeSimpleFrame(
PathResponseFrame(
server->getConn().outstandingPathValidation->pathData),
builder)
.hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet), false, &newPeer);
EXPECT_FALSE(server->getConn().outstandingPathValidation);
@ -2167,12 +2181,14 @@ TEST_P(QuicServerTransportAllowMigrationTest, ResetPathRttPathResponse) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(
PathResponseFrame(server->getConn().outstandingPathValidation->pathData),
builder);
ASSERT_FALSE(writeSimpleFrame(
PathResponseFrame(
server->getConn().outstandingPathValidation->pathData),
builder)
.hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet), false, &newPeer);
EXPECT_FALSE(server->getConn().outstandingPathValidation);
@ -2235,13 +2251,15 @@ TEST_P(QuicServerTransportAllowMigrationTest, IgnoreInvalidPathResponse) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(
PathResponseFrame(
server->getConn().outstandingPathValidation->pathData ^ 1),
builder);
ASSERT_FALSE(
writeSimpleFrame(
PathResponseFrame(
server->getConn().outstandingPathValidation->pathData ^ 1),
builder)
.hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet), false, &newPeer);
EXPECT_TRUE(server->getConn().outstandingPathValidation);
@ -2293,11 +2311,13 @@ TEST_P(
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
writeSimpleFrame(
PathResponseFrame(server->getConn().outstandingPathValidation->pathData),
builder);
ASSERT_FALSE(writeSimpleFrame(
PathResponseFrame(
server->getConn().outstandingPathValidation->pathData),
builder)
.hasError());
auto packet = std::move(builder).buildPacket();
folly::SocketAddress newPeer2("200.101.102.103", 23456);
try {
@ -2387,12 +2407,13 @@ TEST_P(QuicServerTransportAllowMigrationTest, RetiringConnIdIssuesNewIds) {
ProtectionType::KeyPhaseZero, nextConnId, clientNextAppDataPacketNum++);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
// build packet containing a frame retiring the initial server conn id
ASSERT_TRUE(builder.canBuildPacket());
RetireConnectionIdFrame retireConnIdFrame(initialServerConnId.sequenceNumber);
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder).hasError());
auto retireConnIdPacket = std::move(builder).buildPacket();
/**
@ -2426,12 +2447,13 @@ TEST_P(QuicServerTransportAllowMigrationTest, RetiringInvalidConnId) {
clientNextAppDataPacketNum++);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
// build packet containing a frame retiring an invalid conn id / seq no
ASSERT_TRUE(builder.canBuildPacket());
RetireConnectionIdFrame retireConnIdFrame(conn.nextSelfConnectionIdSequence);
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder).hasError());
auto retireConnIdPacket = std::move(builder).buildPacket();
// retiring invalid conn id should not invoke onConnectionIdRetired()
@ -2468,12 +2490,13 @@ TEST_P(QuicServerTransportAllowMigrationTest, RetireConnIdOfContainingPacket) {
clientNextAppDataPacketNum++);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
// build packet containing a frame retiring conn id of containing packet
ASSERT_TRUE(builder.canBuildPacket());
RetireConnectionIdFrame retireConnIdFrame(0);
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder).hasError());
auto retireConnIdPacket = std::move(builder).buildPacket();
// parsing packet should throw an error
@ -2503,12 +2526,13 @@ TEST_P(
clientNextAppDataPacketNum++);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
// build packet containing a RETIRE_CONNECTION_ID frame
ASSERT_TRUE(builder.canBuildPacket());
RetireConnectionIdFrame retireConnIdFrame(0);
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder).hasError());
auto retireConnIdPacket = std::move(builder).buildPacket();
// parsing packet should throw an error
@ -3127,8 +3151,8 @@ TEST_F(QuicServerTransportTest, PingIsTreatedAsRetransmittable) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
writeFrame(pingFrame, builder);
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(pingFrame, builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet));
EXPECT_TRUE(server->getConn().pendingEvents.scheduleAckTimeout);
@ -3150,8 +3174,8 @@ TEST_F(QuicServerTransportTest, ImmediateAckValid) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
writeFrame(immediateAckFrame, builder);
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(immediateAckFrame, builder).hasError());
auto packet = std::move(builder).buildPacket();
ASSERT_NO_THROW(deliverData(packetToBuf(packet)));
// An ACK has been scheduled for AppData number space.
@ -3179,8 +3203,8 @@ TEST_F(QuicServerTransportTest, ImmediateAckProtocolViolation) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
writeFrame(immediateAckFrame, builder);
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_FALSE(writeFrame(immediateAckFrame, builder).hasError());
auto packet = std::move(builder).buildPacket();
// This should throw a protocol violation error
ASSERT_THROW(deliverData(packetToBuf(packet)), std::runtime_error);
@ -3202,11 +3226,11 @@ TEST_F(QuicServerTransportTest, ReceiveDatagramFrameAndDiscard) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StringPiece datagramPayload = "do not rely on me. I am unreliable";
DatagramFrame datagramFrame(
datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
writeFrame(datagramFrame, builder);
ASSERT_FALSE(writeFrame(datagramFrame, builder).hasError());
auto packet = std::move(builder).buildPacket();
EXPECT_CALL(*quicStats_, onDatagramDroppedOnRead()).Times(1);
deliverData(packetToBuf(packet));
@ -3232,11 +3256,11 @@ TEST_F(QuicServerTransportTest, ReceiveDatagramFrameAndStore) {
server->getConn().udpSendPacketLen,
std::move(header),
0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
StringPiece datagramPayload = "do not rely on me. I am unreliable";
DatagramFrame datagramFrame(
datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
writeFrame(datagramFrame, builder);
ASSERT_FALSE(writeFrame(datagramFrame, builder).hasError());
auto packet = std::move(builder).buildPacket();
deliverData(packetToBuf(packet));
if (i < conn.datagramState.maxReadBufferSize) {
@ -3255,11 +3279,12 @@ TEST_F(QuicServerTransportTest, RecvNewConnectionIdValid) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(
1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken{9, 8, 7, 6});
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -3278,11 +3303,12 @@ TEST_F(QuicServerTransportTest, RecvNewConnectionIdTooManyReceivedIds) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(
1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -3298,11 +3324,12 @@ TEST_F(QuicServerTransportTest, RecvNewConnectionIdInvalidRetire) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(
1, 3, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -3320,10 +3347,11 @@ TEST_F(QuicServerTransportTest, RecvNewConnectionIdNoopValidDuplicate) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(1, 0, connId2, StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -3341,10 +3369,11 @@ TEST_F(QuicServerTransportTest, RecvNewConnectionIdExceptionInvalidDuplicate) {
ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
RegularQuicPacketBuilder builder(
conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
ASSERT_TRUE(builder.canBuildPacket());
NewConnectionIdFrame newConnId(2, 0, connId2, StatelessResetToken());
writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(newConnId), builder).hasError());
auto packet = std::move(builder).buildPacket();
@ -3625,14 +3654,14 @@ TEST_F(QuicUnencryptedServerTransportTest, TestUnencryptedAck) {
QuicVersion::MVFST);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
DCHECK(builder.canBuildPacket());
WriteAckFrameState writeAckState = {.acks = acks};
WriteAckFrameMetaData ackData = {
.ackState = writeAckState,
.ackDelay = 0us,
.ackDelayExponent = static_cast<uint8_t>(kDefaultAckDelayExponent)};
writeAckFrame(ackData, builder);
ASSERT_FALSE(writeAckFrame(ackData, builder).hasError());
auto packet = packetToBufCleartext(
std::move(builder).buildPacket(),
*getInitialCipher(),
@ -3837,7 +3866,8 @@ TEST_F(
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), /*largestAckedPacketNum=*/0);
RetireConnectionIdFrame retireConnIdFrame(0);
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder);
ASSERT_FALSE(
writeSimpleFrame(QuicSimpleFrame(retireConnIdFrame), builder).hasError());
// add some data
auto data = IOBuf::copyBuffer("hello!");
@ -3856,7 +3886,7 @@ TEST_F(
data->clone(),
std::min(folly::to<size_t>(dataLen), data->computeChainDataLength()));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(0);
auto packet = std::move(builder).buildPacket();
@ -3880,7 +3910,8 @@ TEST_F(
server->getConn().supportedVersions[0]);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), /*largestAcked=*/0);
writeSimpleFrame(PathResponseFrame(0xaabbccddeeff), builder);
ASSERT_FALSE(
writeSimpleFrame(PathResponseFrame(0xaabbccddeeff), builder).hasError());
// add some data
auto data = IOBuf::copyBuffer("hello!");
@ -3899,7 +3930,7 @@ TEST_F(
data->clone(),
std::min(folly::to<size_t>(dataLen), data->computeChainDataLength()));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(0);
auto packet = std::move(builder).buildPacket();
@ -3923,7 +3954,9 @@ TEST_F(
server->getConn().supportedVersions[0]);
RegularQuicPacketBuilder builder(
kDefaultUDPSendPacketLen, std::move(header), /*largestAcked=*/0);
writeSimpleFrame(NewTokenFrame(IOBuf::copyBuffer("token!")), builder);
ASSERT_FALSE(
writeSimpleFrame(NewTokenFrame(IOBuf::copyBuffer("token!")), builder)
.hasError());
// add some data
auto data = IOBuf::copyBuffer("hello!");
@ -3942,7 +3975,7 @@ TEST_F(
data->clone(),
std::min(folly::to<size_t>(dataLen), data->computeChainDataLength()));
builder.encodePacketHeader();
ASSERT_FALSE(builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(0);
auto packet = std::move(builder).buildPacket();
@ -4652,9 +4685,9 @@ Buf getHandshakePacketWithFrame(
kDefaultUDPSendPacketLen,
std::move(header),
clientPacketNum / 2 /* largestAcked */);
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
builder.accountForCipherOverhead(clientWriteCipher.getCipherOverhead());
writeFrame(std::move(frame), builder);
CHECK(!writeFrame(std::move(frame), builder).hasError());
return packetToBufCleartext(
std::move(builder).buildPacket(),
clientWriteCipher,

View File

@ -4525,7 +4525,7 @@ class AckEventForAppDataTest : public Test {
conn_->udpSendPacketLen,
std::move(*header),
getAckState(*conn_, pnSpace).largestAckedByPeer.value_or(0));
builder.encodePacketHeader();
CHECK(!builder.encodePacketHeader().hasError());
DCHECK(builder.canBuildPacket());
return std::move(builder).buildPacket();
}