in proxygen/lib/http/codec/HQControlCodec.cpp [34:78]
ParseResult HQControlCodec::checkFrameAllowed(FrameType type) {
switch (type) {
case hq::FrameType::DATA:
case hq::FrameType::HEADERS:
case hq::FrameType::PUSH_PROMISE:
return HTTP3::ErrorCode::HTTP_FRAME_UNEXPECTED;
default:
break;
}
if (getStreamType() == hq::UnidirectionalStreamType::CONTROL) {
// SETTINGS MUST be the first frame on an HQ Control Stream
if (!receivedSettings_ && type != hq::FrameType::SETTINGS) {
return HTTP3::ErrorCode::HTTP_MISSING_SETTINGS;
}
// multiple SETTINGS frames are not allowed
if (receivedSettings_ && type == hq::FrameType::SETTINGS) {
return HTTP3::ErrorCode::HTTP_FRAME_UNEXPECTED;
}
// A client MUST treat the receipt of a MAX_PUSH_ID frame as a connection
// error of type HTTP_FRAME_UNEXPECTED
if (transportDirection_ == TransportDirection::UPSTREAM &&
type == hq::FrameType::MAX_PUSH_ID) {
return HTTP3::ErrorCode::HTTP_FRAME_UNEXPECTED;
}
// PRIORITY_UPDATE is downstream control codec only
if (transportDirection_ == TransportDirection::UPSTREAM &&
(type == hq::FrameType::PRIORITY_UPDATE ||
type == hq::FrameType::PUSH_PRIORITY_UPDATE ||
type == hq::FrameType::FB_PUSH_PRIORITY_UPDATE ||
type == hq::FrameType::FB_PRIORITY_UPDATE)) {
return HTTP3::ErrorCode::HTTP_FRAME_UNEXPECTED;
}
}
// Only GOAWAY from Server to Client are allowed in H1Q
if (getStreamType() == hq::UnidirectionalStreamType::H1Q_CONTROL &&
(transportDirection_ == TransportDirection::DOWNSTREAM ||
type != hq::FrameType::GOAWAY)) {
return HTTP3::ErrorCode::HTTP_FRAME_UNEXPECTED;
}
return folly::none;
}