in quic/codec/QuicWriteCodec.cpp [320:512]
size_t writeSimpleFrame(
QuicSimpleFrame&& frame,
PacketBuilderInterface& builder) {
using FrameTypeType = std::underlying_type<FrameType>::type;
uint64_t spaceLeft = builder.remainingSpaceInPkt();
switch (frame.type()) {
case QuicSimpleFrame::Type::StopSendingFrame: {
const StopSendingFrame& stopSendingFrame = *frame.asStopSendingFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::STOP_SENDING));
QuicInteger streamId(stopSendingFrame.streamId);
QuicInteger errorCode(static_cast<uint64_t>(stopSendingFrame.errorCode));
size_t errorSize = errorCode.getSize();
auto stopSendingFrameSize =
intFrameType.getSize() + streamId.getSize() + errorSize;
if (packetSpaceCheck(spaceLeft, stopSendingFrameSize)) {
builder.write(intFrameType);
builder.write(streamId);
builder.write(errorCode);
builder.appendFrame(QuicSimpleFrame(std::move(stopSendingFrame)));
return stopSendingFrameSize;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::PathChallengeFrame: {
const PathChallengeFrame& pathChallengeFrame =
*frame.asPathChallengeFrame();
QuicInteger frameType(static_cast<uint8_t>(FrameType::PATH_CHALLENGE));
auto pathChallengeFrameSize =
frameType.getSize() + sizeof(pathChallengeFrame.pathData);
if (packetSpaceCheck(spaceLeft, pathChallengeFrameSize)) {
builder.write(frameType);
builder.writeBE(pathChallengeFrame.pathData);
builder.appendFrame(QuicSimpleFrame(std::move(pathChallengeFrame)));
return pathChallengeFrameSize;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::PathResponseFrame: {
const PathResponseFrame& pathResponseFrame = *frame.asPathResponseFrame();
QuicInteger frameType(static_cast<uint8_t>(FrameType::PATH_RESPONSE));
auto pathResponseFrameSize =
frameType.getSize() + sizeof(pathResponseFrame.pathData);
if (packetSpaceCheck(spaceLeft, pathResponseFrameSize)) {
builder.write(frameType);
builder.writeBE(pathResponseFrame.pathData);
builder.appendFrame(QuicSimpleFrame(std::move(pathResponseFrame)));
return pathResponseFrameSize;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::NewConnectionIdFrame: {
const NewConnectionIdFrame& newConnectionIdFrame =
*frame.asNewConnectionIdFrame();
QuicInteger frameType(static_cast<uint8_t>(FrameType::NEW_CONNECTION_ID));
QuicInteger sequenceNumber(newConnectionIdFrame.sequenceNumber);
QuicInteger retirePriorTo(newConnectionIdFrame.retirePriorTo);
// Include an 8-bit unsigned integer containing the length of the connId
auto newConnectionIdFrameSize = frameType.getSize() +
sequenceNumber.getSize() + retirePriorTo.getSize() + sizeof(uint8_t) +
newConnectionIdFrame.connectionId.size() +
newConnectionIdFrame.token.size();
if (packetSpaceCheck(spaceLeft, newConnectionIdFrameSize)) {
builder.write(frameType);
builder.write(sequenceNumber);
builder.write(retirePriorTo);
builder.writeBE(newConnectionIdFrame.connectionId.size());
builder.push(
newConnectionIdFrame.connectionId.data(),
newConnectionIdFrame.connectionId.size());
builder.push(
newConnectionIdFrame.token.data(),
newConnectionIdFrame.token.size());
builder.appendFrame(QuicSimpleFrame(std::move(newConnectionIdFrame)));
return newConnectionIdFrameSize;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::MaxStreamsFrame: {
const MaxStreamsFrame& maxStreamsFrame = *frame.asMaxStreamsFrame();
auto frameType = maxStreamsFrame.isForBidirectionalStream()
? FrameType::MAX_STREAMS_BIDI
: FrameType::MAX_STREAMS_UNI;
QuicInteger intFrameType(static_cast<FrameTypeType>(frameType));
QuicInteger streamCount(maxStreamsFrame.maxStreams);
auto maxStreamsFrameSize = intFrameType.getSize() + streamCount.getSize();
if (packetSpaceCheck(spaceLeft, maxStreamsFrameSize)) {
builder.write(intFrameType);
builder.write(streamCount);
builder.appendFrame(QuicSimpleFrame(maxStreamsFrame));
return maxStreamsFrameSize;
}
return size_t(0);
}
case QuicSimpleFrame::Type::RetireConnectionIdFrame: {
const RetireConnectionIdFrame& retireConnectionIdFrame =
*frame.asRetireConnectionIdFrame();
QuicInteger frameType(
static_cast<uint8_t>(FrameType::RETIRE_CONNECTION_ID));
QuicInteger sequence(retireConnectionIdFrame.sequenceNumber);
auto retireConnectionIdFrameSize =
frameType.getSize() + sequence.getSize();
if (packetSpaceCheck(spaceLeft, retireConnectionIdFrameSize)) {
builder.write(frameType);
builder.write(sequence);
builder.appendFrame(QuicSimpleFrame(retireConnectionIdFrame));
return retireConnectionIdFrameSize;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::HandshakeDoneFrame: {
const HandshakeDoneFrame& handshakeDoneFrame =
*frame.asHandshakeDoneFrame();
CHECK(builder.getPacketHeader().asShort());
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::HANDSHAKE_DONE));
if (packetSpaceCheck(spaceLeft, intFrameType.getSize())) {
builder.write(intFrameType);
builder.appendFrame(QuicSimpleFrame(handshakeDoneFrame));
return intFrameType.getSize();
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::KnobFrame: {
const KnobFrame& knobFrame = *frame.asKnobFrame();
QuicInteger intFrameType(static_cast<uint64_t>(FrameType::KNOB));
QuicInteger intKnobSpace(knobFrame.knobSpace);
QuicInteger intKnobId(knobFrame.id);
QuicInteger intKnobLen(knobFrame.len);
size_t knobFrameLen = intFrameType.getSize() + intKnobSpace.getSize() +
intKnobId.getSize() + intKnobLen.getSize() + intKnobLen.getValue();
if (packetSpaceCheck(spaceLeft, knobFrameLen)) {
builder.write(intFrameType);
builder.write(intKnobSpace);
builder.write(intKnobId);
builder.write(intKnobLen);
builder.insert(knobFrame.blob->clone());
builder.appendFrame(QuicSimpleFrame(knobFrame));
return knobFrameLen;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::AckFrequencyFrame: {
const auto ackFrequencyFrame = frame.asAckFrequencyFrame();
QuicInteger intFrameType(static_cast<uint64_t>(FrameType::ACK_FREQUENCY));
QuicInteger intSequenceNumber(ackFrequencyFrame->sequenceNumber);
QuicInteger intPacketTolerance(ackFrequencyFrame->packetTolerance);
QuicInteger intUpdateMaxAckDelay(ackFrequencyFrame->updateMaxAckDelay);
size_t ackFrequencyFrameLen = intFrameType.getSize() +
intSequenceNumber.getSize() + intPacketTolerance.getSize() +
intUpdateMaxAckDelay.getSize() + 1 /* ignoreOrder */;
if (packetSpaceCheck(spaceLeft, ackFrequencyFrameLen)) {
builder.write(intFrameType);
builder.write(intSequenceNumber);
builder.write(intPacketTolerance);
builder.write(intUpdateMaxAckDelay);
builder.writeBE(ackFrequencyFrame->ignoreOrder);
builder.appendFrame(QuicSimpleFrame(*ackFrequencyFrame));
return ackFrequencyFrameLen;
}
// no space left in packet
return size_t(0);
}
case QuicSimpleFrame::Type::NewTokenFrame: {
const auto newTokenFrame = frame.asNewTokenFrame();
QuicInteger intFrameType(static_cast<uint8_t>(FrameType::NEW_TOKEN));
auto& token = newTokenFrame->token;
QuicInteger tokenLength(token.size());
auto newTokenFrameLength = intFrameType.getSize() +
/*encoding token length*/ tokenLength.getSize() +
tokenLength.getValue();
if (packetSpaceCheck(spaceLeft, newTokenFrameLength)) {
builder.write(intFrameType);
builder.write(tokenLength);
builder.push((uint8_t*)token.data(), tokenLength.getValue());
builder.appendFrame(QuicSimpleFrame(*newTokenFrame));
return newTokenFrameLength;
}
// no space left in packet
return size_t(0);
}
}
folly::assume_unreachable();
}