1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-01 01:44:22 +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

@ -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