quic/dsr/frontend/PacketBuilder.h (74 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <quic/codec/PacketNumber.h>
#include <quic/codec/QuicConnectionId.h>
#include <quic/codec/Types.h>
#include <quic/dsr/Types.h>
namespace quic {
struct DSRPacketBuilderBase {
virtual ~DSRPacketBuilderBase() = default;
virtual size_t remainingSpace() const noexcept = 0;
virtual void addSendInstruction(SendInstruction&&, uint32_t) = 0;
};
/**
* This is likely a bad name. The point of having a "Packet Builder" is to
* create the OutstandingPacket when we send out send instructions.
*
* I do think from perf perspective we can do better than this in the future.
*/
class DSRPacketBuilder : public DSRPacketBuilderBase {
public:
explicit DSRPacketBuilder(
size_t packetSize,
ShortHeader header,
PacketNum largestAckedPacketNum)
: packetSize_(packetSize), packet_(std::move(header)) {
updatePacketSizeWithHeader(largestAckedPacketNum);
}
void addSendInstruction(
SendInstruction&& sendInstruction,
uint32_t streamEncodedSize) override {
CHECK(
sendInstructions_.empty() ||
sendInstructions_.back().streamId == sendInstruction.streamId);
WriteStreamFrame frame = sendInstructionToWriteStreamFrame(sendInstruction);
packet_.frames.push_back(frame);
sendInstructions_.push_back(std::move(sendInstruction));
packetSize_ -= streamEncodedSize;
encodedSize_ += streamEncodedSize;
}
struct Packet {
RegularQuicWritePacket packet;
std::vector<SendInstruction> sendInstructions;
uint32_t encodedSize;
Packet(
RegularQuicWritePacket pkt,
std::vector<SendInstruction> instructions,
uint32_t size)
: packet(std::move(pkt)),
sendInstructions(std::move(instructions)),
encodedSize(size) {}
};
Packet buildPacket() && {
CHECK(!sendInstructions_.empty());
CHECK_EQ(sendInstructions_.size(), packet_.frames.size());
return Packet(packet_, std::move(sendInstructions_), encodedSize_);
}
size_t remainingSpace() const noexcept override {
return packetSize_;
}
private:
void updatePacketSizeWithHeader(PacketNum largestAckedPacketNum) {
auto shortHeader = packet_.header.asShort();
CHECK(shortHeader);
auto packetNumEncoding = encodePacketNumber(
shortHeader->getPacketSequenceNum(), largestAckedPacketNum);
auto connIdLen = shortHeader->getConnectionId().size();
if (packetNumEncoding.length + connIdLen + 1 > packetSize_) {
packetSize_ = 0;
return;
}
auto headerSize = packetNumEncoding.length + connIdLen + 1;
encodedSize_ += headerSize;
packetSize_ -= headerSize;
}
private:
size_t packetSize_;
RegularQuicWritePacket packet_;
std::vector<SendInstruction> sendInstructions_;
uint32_t encodedSize_{0};
};
} // namespace quic