Implement draft-05 SUBSCRIBE/SUBSCRIBE_UPDATE PiperOrigin-RevId: 654109878
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc index 8439ebf..aff5753 100644 --- a/quiche/quic/moqt/moqt_framer.cc +++ b/quiche/quic/moqt/moqt_framer.cc
@@ -303,7 +303,9 @@ WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), WireStringWithVarInt62Length(message.track_namespace), WireStringWithVarInt62Length(message.track_name), - WireVarInt62(filter_type), WireVarInt62(string_params.size()), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(filter_type), + WireVarInt62(string_params.size()), WireSpan<WireStringParameter>(string_params)); case MoqtFilterType::kAbsoluteStart: return Serialize( @@ -311,7 +313,9 @@ WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), WireStringWithVarInt62Length(message.track_namespace), WireStringWithVarInt62Length(message.track_name), - WireVarInt62(filter_type), WireVarInt62(*message.start_group), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(filter_type), + WireVarInt62(*message.start_group), WireVarInt62(*message.start_object), WireVarInt62(string_params.size()), WireSpan<WireStringParameter>(string_params)); @@ -321,7 +325,9 @@ WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), WireStringWithVarInt62Length(message.track_namespace), WireStringWithVarInt62Length(message.track_name), - WireVarInt62(filter_type), WireVarInt62(*message.start_group), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(filter_type), + WireVarInt62(*message.start_group), WireVarInt62(*message.start_object), WireVarInt62(*message.end_group), WireVarInt62(message.end_object.has_value() ? *message.end_object + 1 : 0), @@ -400,7 +406,8 @@ WireVarInt62(MoqtMessageType::kSubscribeUpdate), WireVarInt62(message.subscribe_id), WireVarInt62(message.start_group), WireVarInt62(message.start_object), WireVarInt62(end_group), - WireVarInt62(end_object), WireSpan<WireStringParameter>(string_params)); + WireVarInt62(end_object), WireUint8(message.subscriber_priority), + WireSpan<WireStringParameter>(string_params)); } quiche::QuicheBuffer MoqtFramer::SerializeAnnounce(
diff --git a/quiche/quic/moqt/moqt_framer_test.cc b/quiche/quic/moqt/moqt_framer_test.cc index 6be927d..2a9ef38 100644 --- a/quiche/quic/moqt/moqt_framer_test.cc +++ b/quiche/quic/moqt/moqt_framer_test.cc
@@ -294,6 +294,8 @@ /*track_alias=*/4, /*track_namespace=*/"foo", /*track_name=*/"abcd", + /*subscriber_priority=*/0x20, + /*group_order=*/std::nullopt, start_group, start_object, end_group, @@ -324,7 +326,7 @@ } buffer = framer_.SerializeSubscribe(subscribe); // Go to the filter type. - const uint8_t* read = BufferAtOffset(buffer, 12); + const uint8_t* read = BufferAtOffset(buffer, 14); EXPECT_EQ(static_cast<MoqtFilterType>(*read), expected_filter_type); EXPECT_GT(buffer.size(), 0); if (expected_filter_type == MoqtFilterType::kAbsoluteRange && @@ -344,6 +346,8 @@ /*track_alias=*/4, /*track_namespace=*/"foo", /*track_name=*/"abcd", + /*subscriber_priority=*/0x20, + /*group_order=*/std::nullopt, /*start_group=*/std::optional<uint64_t>(4), /*start_object=*/std::optional<uint64_t>(3), /*end_group=*/std::optional<uint64_t>(3), @@ -367,6 +371,8 @@ /*track_alias=*/4, /*track_namespace=*/"foo", /*track_name=*/"abcd", + /*subscriber_priority=*/0x20, + /*group_order=*/std::nullopt, /*start_group=*/std::nullopt, /*start_object=*/std::optional<uint64_t>(3), /*end_group=*/std::nullopt, @@ -386,6 +392,7 @@ /*start_object=*/3, /*end_group=*/4, /*end_object=*/std::nullopt, + /*subscriber_priority=*/0xaa, /*authorization_info=*/"bar", }; quiche::QuicheBuffer buffer; @@ -404,6 +411,7 @@ /*start_object=*/3, /*end_group=*/4, /*end_object=*/6, + /*subscriber_priority=*/0xaa, /*authorization_info=*/"bar", }; quiche::QuicheBuffer buffer; @@ -422,6 +430,7 @@ /*start_object=*/3, /*end_group=*/std::nullopt, /*end_object=*/6, + /*subscriber_priority=*/0xaa, /*authorization_info=*/"bar", }; quiche::QuicheBuffer buffer;
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h index 584fcf9..1d9f312 100644 --- a/quiche/quic/moqt/moqt_messages.h +++ b/quiche/quic/moqt/moqt_messages.h
@@ -243,6 +243,8 @@ uint64_t track_alias; std::string track_namespace; std::string track_name; + MoqtPriority subscriber_priority; + std::optional<MoqtDeliveryOrder> group_order; // The combinations of these that have values indicate the filter type. // SG: Start Group; SO: Start Object; EG: End Group; EO: End Object; // (none): KLatestObject @@ -312,6 +314,7 @@ uint64_t start_object; std::optional<uint64_t> end_group; std::optional<uint64_t> end_object; + MoqtPriority subscriber_priority; std::optional<std::string> authorization_info; };
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc index c5a51d7..c9f2ed0 100644 --- a/quiche/quic/moqt/moqt_parser.cc +++ b/quiche/quic/moqt/moqt_parser.cc
@@ -21,6 +21,27 @@ namespace moqt { +namespace { + +bool ParseDeliveryOrder(uint8_t raw_value, + std::optional<MoqtDeliveryOrder>& output) { + switch (raw_value) { + case 0x00: + output = std::nullopt; + return true; + case 0x01: + output = MoqtDeliveryOrder::kAscending; + return true; + case 0x02: + output = MoqtDeliveryOrder::kDescending; + return true; + default: + return false; + } +} + +} // namespace + // The buffering philosophy is complicated, to minimize copying. Here is an // overview: // If the entire message body is present (except for OBJECT payload), it is @@ -402,11 +423,17 @@ size_t MoqtParser::ProcessSubscribe(quic::QuicDataReader& reader) { MoqtSubscribe subscribe_request; uint64_t filter, group, object; + uint8_t group_order; if (!reader.ReadVarInt62(&subscribe_request.subscribe_id) || !reader.ReadVarInt62(&subscribe_request.track_alias) || !reader.ReadStringVarInt62(subscribe_request.track_namespace) || !reader.ReadStringVarInt62(subscribe_request.track_name) || - !reader.ReadVarInt62(&filter)) { + !reader.ReadUInt8(&subscribe_request.subscriber_priority) || + !reader.ReadUInt8(&group_order) || !reader.ReadVarInt62(&filter)) { + return 0; + } + if (!ParseDeliveryOrder(group_order, subscribe_request.group_order)) { + ParseError("Invalid group order value in SUBSCRIBE message"); return 0; } MoqtFilterType filter_type = static_cast<MoqtFilterType>(filter); @@ -566,6 +593,7 @@ !reader.ReadVarInt62(&subscribe_update.start_group) || !reader.ReadVarInt62(&subscribe_update.start_object) || !reader.ReadVarInt62(&end_group) || !reader.ReadVarInt62(&end_object) || + !reader.ReadUInt8(&subscribe_update.subscriber_priority) || !reader.ReadVarInt62(&num_params)) { return 0; }
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc index 3cf061a..cf6b2e3 100644 --- a/quiche/quic/moqt/moqt_parser_test.cc +++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -23,6 +23,9 @@ namespace { +using ::testing::HasSubstr; +using ::testing::Optional; + inline bool IsObjectMessage(MoqtMessageType type) { return (type == MoqtMessageType::kObjectStream || type == MoqtMessageType::kObjectDatagram || @@ -625,6 +628,7 @@ char subscribe[] = { 0x03, 0x01, 0x02, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x02, // filter_type = kLatestObject 0x02, // two params 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" @@ -632,8 +636,7 @@ }; parser.ProcessData(absl::string_view(subscribe, sizeof(subscribe)), false); EXPECT_EQ(visitor_.messages_received_, 0); - EXPECT_TRUE(visitor_.parsing_error_.has_value()); - EXPECT_EQ(*visitor_.parsing_error_, + EXPECT_EQ(visitor_.parsing_error_, "AUTHORIZATION_INFO parameter appears twice in SUBSCRIBE"); EXPECT_EQ(visitor_.parsing_error_code_, MoqtError::kProtocolViolation); } @@ -642,6 +645,7 @@ MoqtParser parser(kWebTrans, visitor_); char subscribe_update[] = { 0x02, 0x02, 0x03, 0x01, 0x05, 0x06, // start and end sequences + 0xaa, // priority = 0xaa 0x02, // 2 parameters 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" @@ -649,8 +653,7 @@ parser.ProcessData( absl::string_view(subscribe_update, sizeof(subscribe_update)), false); EXPECT_EQ(visitor_.messages_received_, 0); - EXPECT_TRUE(visitor_.parsing_error_.has_value()); - EXPECT_EQ(*visitor_.parsing_error_, + EXPECT_EQ(visitor_.parsing_error_, "AUTHORIZATION_INFO parameter appears twice in SUBSCRIBE_UPDATE"); EXPECT_EQ(visitor_.parsing_error_code_, MoqtError::kProtocolViolation); } @@ -769,13 +772,14 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x01, // filter_type = kLatestGroup 0x01, // 1 parameter 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" }; parser.ProcessData(absl::string_view(subscribe, sizeof(subscribe)), false); EXPECT_EQ(visitor_.messages_received_, 1); - EXPECT_TRUE(visitor_.last_message_.has_value()); + ASSERT_TRUE(visitor_.last_message_.has_value()); MoqtSubscribe message = std::get<MoqtSubscribe>(visitor_.last_message_.value()); EXPECT_FALSE(message.start_group.has_value()); @@ -790,6 +794,7 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x02, // filter_type = kLatestObject 0x01, // 1 parameter 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" @@ -805,12 +810,29 @@ EXPECT_FALSE(message.end_object.has_value()); } +TEST_F(MoqtMessageSpecificTest, InvalidDeliveryOrder) { + MoqtParser parser(kRawQuic, visitor_); + char subscribe[] = { + 0x03, 0x01, 0x02, // id and alias + 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x08, // priority = 0x20 ??? + 0x01, // filter_type = kLatestGroup + 0x01, // 1 parameter + 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" + }; + parser.ProcessData(absl::string_view(subscribe, sizeof(subscribe)), false); + EXPECT_EQ(visitor_.messages_received_, 0); + EXPECT_THAT(visitor_.parsing_error_, Optional(HasSubstr("group order"))); +} + TEST_F(MoqtMessageSpecificTest, AbsoluteStart) { MoqtParser parser(kRawQuic, visitor_); char subscribe[] = { 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x03, // filter_type = kAbsoluteStart 0x04, // start_group = 4 0x01, // start_object = 1 @@ -834,6 +856,7 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x04, // filter_type = kAbsoluteStart 0x04, // start_group = 4 0x01, // start_object = 1 @@ -859,6 +882,7 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x04, // filter_type = kAbsoluteRange 0x04, // start_group = 4 0x01, // start_object = 1 @@ -884,6 +908,7 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x04, // filter_type = kAbsoluteRange 0x04, // start_group = 4 0x01, // start_object = 1 @@ -904,6 +929,7 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x04, // filter_type = kAbsoluteRange 0x04, // start_group = 4 0x01, // start_object = 1 @@ -919,6 +945,7 @@ MoqtParser parser(kRawQuic, visitor_); char subscribe_update[] = { 0x02, 0x02, 0x03, 0x01, 0x04, 0x07, // start and end sequences + 0x20, // priority 0x00, // No parameters }; parser.ProcessData( @@ -930,6 +957,7 @@ MoqtParser parser(kRawQuic, visitor_); char subscribe_update[] = { 0x02, 0x02, 0x03, 0x01, 0x03, 0x06, // start and end sequences + 0x20, // priority 0x01, // 1 parameter 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" }; @@ -946,6 +974,7 @@ 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, 0x02, // priority = 0x20 descending 0x04, // filter_type = kAbsoluteRange 0x04, // start_group = 4 0x01, // start_object = 1 @@ -978,6 +1007,7 @@ MoqtParser parser(kRawQuic, visitor_); char subscribe_update[] = { 0x02, 0x02, 0x03, 0x02, 0x00, 0x01, // start and end sequences + 0x20, // priority 0x01, // 1 parameter 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" };
diff --git a/quiche/quic/moqt/moqt_session.cc b/quiche/quic/moqt/moqt_session.cc index 58ff443..bde0055 100644 --- a/quiche/quic/moqt/moqt_session.cc +++ b/quiche/quic/moqt/moqt_session.cc
@@ -48,6 +48,8 @@ using ::quic::Perspective; +constexpr MoqtPriority kDefaultSubscriberPriority = 0x80; + bool PublisherHasData(const MoqtTrackPublisher& publisher) { absl::StatusOr<MoqtTrackStatusCode> status = publisher.GetTrackStatus(); return status.ok() && DoesTrackStatusImplyHavingData(*status); @@ -246,6 +248,8 @@ MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; message.start_group = start_group; message.start_object = start_object; message.end_group = std::nullopt; @@ -269,6 +273,8 @@ MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; message.start_group = start_group; message.start_object = start_object; message.end_group = end_group; @@ -296,6 +302,8 @@ MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; message.start_group = start_group; message.start_object = start_object; message.end_group = end_group; @@ -313,6 +321,8 @@ MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; message.start_group = std::nullopt; message.start_object = std::nullopt; message.end_group = std::nullopt; @@ -330,6 +340,8 @@ MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; // First object of current group. message.start_group = std::nullopt; message.start_object = 0; @@ -716,7 +728,7 @@ ? *message.end_object : UINT64_MAX); } - it->second->Update(start, end); + it->second->Update(start, end, message.subscriber_priority); } void MoqtSession::ControlStream::OnAnnounceMessage( @@ -850,7 +862,9 @@ session_(session), track_publisher_(track_publisher), track_alias_(subscribe.track_alias), - window_(SubscribeMessageToWindow(subscribe, *track_publisher)) { + window_(SubscribeMessageToWindow(subscribe, *track_publisher)), + subscriber_priority_(subscribe.subscriber_priority), + subscriber_delivery_order_(subscribe.group_order) { track_publisher->AddObjectListener(this); QUIC_DLOG(INFO) << ENDPOINT << "Created subscription for " << subscribe.track_namespace << ":" << subscribe.track_name; @@ -874,8 +888,10 @@ } void MoqtSession::PublishedSubscription::Update( - FullSequence start, std::optional<FullSequence> end) { + FullSequence start, std::optional<FullSequence> end, + MoqtPriority subscriber_priority) { window_.UpdateStartEnd(start, end); + subscriber_priority_ = subscriber_priority; // TODO: reset streams that are no longer in-window. // TODO: send SUBSCRIBE_DONE if required. // TODO: send an error for invalid updates now that it's a part of draft-05.
diff --git a/quiche/quic/moqt/moqt_session.h b/quiche/quic/moqt/moqt_session.h index 52af69d..4e6d172 100644 --- a/quiche/quic/moqt/moqt_session.h +++ b/quiche/quic/moqt/moqt_session.h
@@ -19,6 +19,7 @@ #include "quiche/quic/moqt/moqt_framer.h" #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/quic/moqt/moqt_parser.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/quic/moqt/moqt_subscribe_windows.h" #include "quiche/quic/moqt/moqt_track.h" @@ -301,8 +302,9 @@ // conceptually simpler, as backpressure is less of a concern. void Backfill(); - // Updates the window of the subscription in question. - void Update(FullSequence start, std::optional<FullSequence> end); + // Updates the window and other properties of the subscription in question. + void Update(FullSequence start, std::optional<FullSequence> end, + MoqtPriority subscriber_priority); // Checks if the specified sequence is within the window of this // subscription. bool InWindow(FullSequence sequence) { return window_.InWindow(sequence); } @@ -328,6 +330,8 @@ std::shared_ptr<MoqtTrackPublisher> track_publisher_; uint64_t track_alias_; SubscribeWindow window_; + MoqtPriority subscriber_priority_; + std::optional<MoqtDeliveryOrder> subscriber_delivery_order_; // Largest sequence number ever sent via this subscription. std::optional<FullSequence> largest_sent_; // Should be almost always accessed via `stream_map()`.
diff --git a/quiche/quic/moqt/moqt_session_test.cc b/quiche/quic/moqt/moqt_session_test.cc index 9a1bf9c..22ab0d0 100644 --- a/quiche/quic/moqt/moqt_session_test.cc +++ b/quiche/quic/moqt/moqt_session_test.cc
@@ -304,6 +304,8 @@ /*track_alias=*/2, /*track_namespace=*/"foo", /*track_name=*/"bar", + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt, @@ -438,6 +440,8 @@ /*track_alias=*/2, /*track_namespace=*/"foo", /*track_name=*/"bar", + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt, @@ -641,6 +645,8 @@ /*track_alias=*/2, /*track_namespace=*/ftn.track_namespace, /*track_name=*/ftn.track_name, + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt, @@ -698,6 +704,8 @@ /*track_alias=*/2, /*track_namespace=*/ftn.track_namespace, /*track_name=*/ftn.track_name, + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt, @@ -758,6 +766,8 @@ /*track_alias=*/2, /*track_namespace=*/ftn.track_namespace, /*track_name=*/ftn.track_name, + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt, @@ -809,6 +819,8 @@ /*track_alias=*/2, /*track_namespace=*/ftn.track_namespace, /*track_name=*/ftn.track_name, + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt, @@ -1220,6 +1232,8 @@ /*track_alias=*/2, /*track_namespace=*/"foo", /*track_name=*/"bar", + /*subscriber_priority=*/0x80, + /*group_order=*/std::nullopt, /*start_group=*/0, /*start_object=*/0, /*end_group=*/std::nullopt,
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h index 44a6405..91219f6 100644 --- a/quiche/quic/moqt/test_tools/moqt_test_message.h +++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -422,6 +422,14 @@ QUIC_LOG(INFO) << "SUBSCRIBE track name mismatch"; return false; } + if (cast.subscriber_priority != subscribe_.subscriber_priority) { + QUIC_LOG(INFO) << "SUBSCRIBE subscriber priority mismatch"; + return false; + } + if (cast.group_order != subscribe_.group_order) { + QUIC_LOG(INFO) << "SUBSCRIBE group order mismatch"; + return false; + } if (cast.start_group != subscribe_.start_group) { QUIC_LOG(INFO) << "SUBSCRIBE start group mismatch"; return false; @@ -445,20 +453,24 @@ return true; } - void ExpandVarints() override { ExpandVarintsImpl("vvvv---v----vvvvvv---"); } + void ExpandVarints() override { + ExpandVarintsImpl("vvvv---v------vvvvvv---"); + } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_); } private: - uint8_t raw_packet_[21] = { + uint8_t raw_packet_[23] = { 0x03, 0x01, 0x02, // id and alias 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x20, // subscriber priority = 0x20 + 0x02, // group order = descending 0x03, // Filter type: Absolute Start 0x04, // start_group = 4 (relative previous) 0x01, // start_object = 1 (absolute) @@ -473,6 +485,8 @@ /*track_alias=*/2, /*track_namespace=*/"foo", /*track_name=*/"abcd", + /*subscriber_priority=*/0x20, + /*group_order=*/MoqtDeliveryOrder::kDescending, /*start_group=*/4, /*start_object=*/1, /*end_group=*/std::nullopt, @@ -701,6 +715,10 @@ QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE end group mismatch"; return false; } + if (cast.subscriber_priority != subscribe_update_.subscriber_priority) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE subscriber priority mismatch"; + return false; + } if (cast.authorization_info != subscribe_update_.authorization_info) { QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE authorization info mismatch"; return false; @@ -708,15 +726,16 @@ return true; } - void ExpandVarints() override { ExpandVarintsImpl("vvvvvvvvv---"); } + void ExpandVarints() override { ExpandVarintsImpl("vvvvvv-vvv---"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_update_); } private: - uint8_t raw_packet_[12] = { + uint8_t raw_packet_[13] = { 0x02, 0x02, 0x03, 0x01, 0x05, 0x06, // start and end sequences + 0xaa, // subscriber_priority 0x01, // 1 parameter 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" }; @@ -727,6 +746,7 @@ /*start_object=*/1, /*end_group=*/4, /*end_object=*/5, + /*subscriber_priority=*/0xaa, /*authorization_info=*/"bar", }; };