Implement PRIORITY_UPDATE frame in HttpEncoder and HttpDecoder.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 289120155
Change-Id: I85525c7fef4cccd7ecef9e1e24a704c656895f75
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index e3ca73e..f8a73f4 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -166,6 +166,9 @@
break;
case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH):
break;
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
+ continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length);
+ break;
default:
continue_processing =
visitor_->OnUnknownFrameStart(current_frame_type_, header_length);
@@ -289,6 +292,12 @@
BufferFramePayload(reader);
break;
}
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
+ // TODO(bnc): Avoid buffering if the entire frame is present, and
+ // instead parse directly out of |reader|.
+ BufferFramePayload(reader);
+ break;
+ }
default: {
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_frame_length_, reader->BytesRemaining());
@@ -406,6 +415,17 @@
continue_processing = visitor_->OnDuplicatePushFrame(frame);
break;
}
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
+ // TODO(bnc): Avoid buffering if the entire frame is present, and
+ // instead parse directly out of |reader|.
+ PriorityUpdateFrame frame;
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
+ if (!ParsePriorityUpdateFrame(&reader, &frame)) {
+ return false;
+ }
+ continue_processing = visitor_->OnPriorityUpdateFrame(frame);
+ break;
+ }
default: {
continue_processing = visitor_->OnUnknownFrameEnd();
break;
@@ -515,6 +535,41 @@
return true;
}
+bool HttpDecoder::ParsePriorityUpdateFrame(QuicDataReader* reader,
+ PriorityUpdateFrame* frame) {
+ uint8_t prioritized_element_type;
+ if (!reader->ReadUInt8(&prioritized_element_type)) {
+ // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
+ RaiseError(QUIC_INVALID_FRAME_DATA,
+ "Unable to read prioritized element type.");
+ return false;
+ }
+
+ if (prioritized_element_type != REQUEST_STREAM &&
+ prioritized_element_type != PUSH_STREAM) {
+ // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
+ RaiseError(QUIC_INVALID_FRAME_DATA, "Invalid prioritized element type.");
+ return false;
+ }
+
+ frame->prioritized_element_type =
+ static_cast<PrioritizedElementType>(prioritized_element_type);
+
+ if (!reader->ReadVarInt62(&frame->prioritized_element_id)) {
+ // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
+ RaiseError(QUIC_INVALID_FRAME_DATA,
+ "Unable to read prioritized element id.");
+ return false;
+ }
+
+ quiche::QuicheStringPiece priority_field_value =
+ reader->ReadRemainingPayload();
+ frame->priority_field_value =
+ std::string(priority_field_value.data(), priority_field_value.size());
+
+ return true;
+}
+
QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
switch (frame_type) {
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
@@ -528,6 +583,9 @@
return sizeof(PushId);
case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH):
return sizeof(PushId);
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
+ // This limit is arbitrary.
+ return 1024 * 1024;
default:
// Other frames require no data buffering, so it's safe to have no limit.
return std::numeric_limits<QuicByteCount>::max();