Skip to content

Commit 0b73764

Browse files
Aman Sharmameta-codesync[bot]
authored andcommitted
Extract frame header and frame length parsing into separate helpers
Summary: The `MoQControlCodec::onIngress()` state machine had the logic for two of its three parse states (`FRAME_HEADER_TYPE` and `FRAME_LENGTH`) inlined directly in the `switch` body, making the function lengthy and harder to follow. This diff extracts those two cases into the private helpers that were already declared in the header: parseFrameHeaderType and parseFrameLength. Reviewed By: afrind Differential Revision: D96370652 fbshipit-source-id: 28b5d852cab8a77576e5230b387c0cef4e5ea73f
1 parent 8aff6c9 commit 0b73764

2 files changed

Lines changed: 85 additions & 60 deletions

File tree

moxygen/MoQCodec.cpp

Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,76 @@ void MoQCodec::onIngressStart(std::unique_ptr<folly::IOBuf> data) {
1616
ingress_.append(std::move(data));
1717
}
1818

19+
folly::Expected<folly::Unit, ErrorCode> MoQControlCodec::parseFrameHeaderType(
20+
folly::io::Cursor& cursor,
21+
size_t& remainingLength) {
22+
auto type = quic::follyutils::decodeQuicInteger(cursor);
23+
if (!type) {
24+
XLOG(DBG6) << __func__ << " underflow";
25+
return folly::makeUnexpected(ErrorCode::PARSE_UNDERFLOW);
26+
}
27+
curFrameType_ = FrameType(type->first);
28+
remainingLength -= type->second;
29+
if (!checkFrameAllowed(curFrameType_)) {
30+
XLOG(DBG4) << "Frame not allowed: 0x" << std::setfill('0')
31+
<< std::setw(sizeof(uint64_t) * 2) << std::hex
32+
<< (uint64_t)curFrameType_ << " on streamID=" << streamId_;
33+
return folly::makeUnexpected(ErrorCode::PROTOCOL_VIOLATION);
34+
}
35+
if (callback_) {
36+
callback_->onFrame(curFrameType_);
37+
}
38+
parseState_ = ParseState::FRAME_LENGTH;
39+
return folly::unit;
40+
}
41+
42+
folly::Expected<folly::Unit, ErrorCode> MoQControlCodec::parseFrameLength(
43+
folly::io::Cursor& cursor,
44+
size_t& remainingLength) {
45+
uint64_t length = 0;
46+
size_t bytesParsed = 0;
47+
48+
bool parseFrameLengthAs16bit = false;
49+
if (curFrameType_ == FrameType::CLIENT_SETUP ||
50+
curFrameType_ == FrameType::SERVER_SETUP) {
51+
parseFrameLengthAs16bit = true;
52+
} else if (
53+
curFrameType_ == FrameType::LEGACY_CLIENT_SETUP ||
54+
curFrameType_ == FrameType::LEGACY_SERVER_SETUP) {
55+
parseFrameLengthAs16bit = false;
56+
} else if (!moqFrameParser_.getVersion().has_value()) {
57+
XLOG(DBG4)
58+
<< "Received a non-setup frame before knowing the negotiated version";
59+
return folly::makeUnexpected(ErrorCode::PROTOCOL_VIOLATION);
60+
} else {
61+
parseFrameLengthAs16bit =
62+
(getDraftMajorVersion(*moqFrameParser_.getVersion()) >= 11);
63+
}
64+
65+
if (parseFrameLengthAs16bit) {
66+
if (remainingLength < 2) {
67+
XLOG(DBG6) << __func__ << " underflow";
68+
return folly::makeUnexpected(ErrorCode::PARSE_UNDERFLOW);
69+
}
70+
// Parse the length as a 16 bit integer
71+
length = cursor.readBE<uint16_t>();
72+
bytesParsed = 2;
73+
} else {
74+
// Parse the length as a varint
75+
auto decodeResult = quic::follyutils::decodeQuicInteger(cursor);
76+
if (!decodeResult) {
77+
XLOG(DBG6) << __func__ << " underflow";
78+
return folly::makeUnexpected(ErrorCode::PARSE_UNDERFLOW);
79+
}
80+
length = decodeResult->first;
81+
bytesParsed = decodeResult->second;
82+
}
83+
curFrameLength_ = length;
84+
remainingLength -= bytesParsed;
85+
parseState_ = ParseState::FRAME_PAYLOAD;
86+
return folly::unit;
87+
}
88+
1989
MoQCodec::ParseResult MoQControlCodec::onIngress(
2090
std::unique_ptr<folly::IOBuf> data,
2191
bool eom) {
@@ -25,73 +95,19 @@ MoQCodec::ParseResult MoQControlCodec::onIngress(
2595
while (!connError_ && remainingLength > 0) {
2696
switch (parseState_) {
2797
case ParseState::FRAME_HEADER_TYPE: {
28-
auto type = quic::follyutils::decodeQuicInteger(cursor);
29-
if (!type) {
30-
XLOG(DBG6) << __func__ << " underflow";
31-
connError_ = ErrorCode::PARSE_UNDERFLOW;
32-
break;
33-
}
34-
curFrameType_ = FrameType(type->first);
35-
remainingLength -= type->second;
36-
auto res = checkFrameAllowed(curFrameType_);
37-
if (!res) {
38-
XLOG(DBG4) << "Frame not allowed: 0x" << std::setfill('0')
39-
<< std::setw(sizeof(uint64_t) * 2) << std::hex
40-
<< (uint64_t)curFrameType_ << " on streamID=" << streamId_;
41-
connError_.emplace(ErrorCode::PROTOCOL_VIOLATION);
98+
auto res = parseFrameHeaderType(cursor, remainingLength);
99+
if (res.hasError()) {
100+
connError_ = res.error();
42101
break;
43102
}
44-
if (callback_) {
45-
callback_->onFrame(curFrameType_);
46-
}
47-
parseState_ = ParseState::FRAME_LENGTH;
48103
[[fallthrough]];
49104
}
50105
case ParseState::FRAME_LENGTH: {
51-
uint64_t length = 0;
52-
size_t bytesParsed = 0;
53-
54-
bool parseFrameLengthAs16bit = false;
55-
if (curFrameType_ == FrameType::CLIENT_SETUP ||
56-
curFrameType_ == FrameType::SERVER_SETUP) {
57-
parseFrameLengthAs16bit = true;
58-
} else if (
59-
curFrameType_ == FrameType::LEGACY_CLIENT_SETUP ||
60-
curFrameType_ == FrameType::LEGACY_SERVER_SETUP) {
61-
parseFrameLengthAs16bit = false;
62-
} else if (!moqFrameParser_.getVersion().has_value()) {
63-
XLOG(DBG4)
64-
<< "Received a non-setup frame before knowing the negotiated version";
65-
connError_.emplace(ErrorCode::PROTOCOL_VIOLATION);
106+
auto res = parseFrameLength(cursor, remainingLength);
107+
if (res.hasError()) {
108+
connError_ = res.error();
66109
break;
67-
} else {
68-
parseFrameLengthAs16bit =
69-
(getDraftMajorVersion(*moqFrameParser_.getVersion()) >= 11);
70-
}
71-
72-
if (parseFrameLengthAs16bit) {
73-
if (remainingLength < 2) {
74-
XLOG(DBG6) << __func__ << " underflow";
75-
connError_ = ErrorCode::PARSE_UNDERFLOW;
76-
break;
77-
}
78-
// Parse the length as a 16 bit integer
79-
length = cursor.readBE<uint16_t>();
80-
bytesParsed = 2;
81-
} else {
82-
// Parse the length as a varint
83-
auto decodeResult = quic::follyutils::decodeQuicInteger(cursor);
84-
if (!decodeResult) {
85-
XLOG(DBG6) << __func__ << " underflow";
86-
connError_ = ErrorCode::PARSE_UNDERFLOW;
87-
break;
88-
}
89-
length = decodeResult->first;
90-
bytesParsed = decodeResult->second;
91110
}
92-
curFrameLength_ = length;
93-
remainingLength -= bytesParsed;
94-
parseState_ = ParseState::FRAME_PAYLOAD;
95111
[[fallthrough]];
96112
}
97113
case ParseState::FRAME_PAYLOAD: {

moxygen/MoQCodec.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,15 @@ class MoQControlCodec : public MoQCodec {
170170
};
171171
ParseState parseState_{ParseState::FRAME_HEADER_TYPE};
172172
bool seenSetup_{false};
173+
174+
private:
175+
// State-machine helpers called from onIngress().
176+
folly::Expected<folly::Unit, ErrorCode> parseFrameHeaderType(
177+
folly::io::Cursor& cursor,
178+
size_t& remainingLength);
179+
folly::Expected<folly::Unit, ErrorCode> parseFrameLength(
180+
folly::io::Cursor& cursor,
181+
size_t& remainingLength);
173182
};
174183

175184
class MoQSubNsReceiverCodec : public MoQControlCodec {

0 commit comments

Comments
 (0)