Framer/Parser for MOQT PUBLISH_SKIPPED. This is named PUBLISH_BLOCKED in draft-18 but will be renamed. We do not yet support SUBSCRIBE_TRACKS, so there is no use for this message yet. PiperOrigin-RevId: 994719010
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc index d52ac07..e02f090 100644 --- a/quiche/quic/moqt/moqt_framer.cc +++ b/quiche/quic/moqt/moqt_framer.cc
@@ -586,6 +586,12 @@ WireTrackNamespace(message.track_namespace_suffix)); } +quiche::QuicheBuffer MoqtFramer::SerializePublishSkipped( + const MoqtPublishSkipped& message) { + return SerializeControlMessage(MoqtMessageType::kPublishSkipped, + WireFullTrackName(message.name)); +} + quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus( const MoqtTrackStatus& message) { return SerializeSubscribe(message, MoqtMessageType::kTrackStatus);
diff --git a/quiche/quic/moqt/moqt_framer.h b/quiche/quic/moqt/moqt_framer.h index 282104d..c5a1ac4 100644 --- a/quiche/quic/moqt/moqt_framer.h +++ b/quiche/quic/moqt/moqt_framer.h
@@ -60,6 +60,8 @@ const MoqtPublishNamespace& message); quiche::QuicheBuffer SerializeNamespace(const MoqtNamespace& message); quiche::QuicheBuffer SerializeNamespaceDone(const MoqtNamespaceDone& message); + quiche::QuicheBuffer SerializePublishSkipped( + const MoqtPublishSkipped& message); quiche::QuicheBuffer SerializeTrackStatus(const MoqtTrackStatus& message); quiche::QuicheBuffer SerializeGoAway(const MoqtGoAway& message); quiche::QuicheBuffer SerializeSubscribeNamespace(
diff --git a/quiche/quic/moqt/moqt_framer_test.cc b/quiche/quic/moqt/moqt_framer_test.cc index 09f355c..941c286 100644 --- a/quiche/quic/moqt/moqt_framer_test.cc +++ b/quiche/quic/moqt/moqt_framer_test.cc
@@ -43,23 +43,15 @@ std::vector<MoqtFramerTestParams> GetMoqtFramerTestParams() { std::vector<MoqtFramerTestParams> params; std::vector<MoqtMessageType> message_types = { - MoqtMessageType::kRequestOk, - MoqtMessageType::kRequestError, - MoqtMessageType::kSubscribe, - MoqtMessageType::kSubscribeOk, - MoqtMessageType::kPublishDone, - MoqtMessageType::kPublishNamespace, - MoqtMessageType::kNamespace, - MoqtMessageType::kNamespaceDone, - MoqtMessageType::kTrackStatus, - MoqtMessageType::kGoAway, - MoqtMessageType::kSubscribeNamespace, - MoqtMessageType::kSubscribeTracks, - MoqtMessageType::kFetch, - MoqtMessageType::kFetchOk, - MoqtMessageType::kPublish, - MoqtMessageType::kObjectAck, - MoqtMessageType::kSetup, + MoqtMessageType::kRequestOk, MoqtMessageType::kRequestError, + MoqtMessageType::kSubscribe, MoqtMessageType::kSubscribeOk, + MoqtMessageType::kPublishDone, MoqtMessageType::kPublishNamespace, + MoqtMessageType::kNamespace, MoqtMessageType::kNamespaceDone, + MoqtMessageType::kPublishSkipped, MoqtMessageType::kTrackStatus, + MoqtMessageType::kGoAway, MoqtMessageType::kSubscribeNamespace, + MoqtMessageType::kSubscribeTracks, MoqtMessageType::kFetch, + MoqtMessageType::kFetchOk, MoqtMessageType::kPublish, + MoqtMessageType::kObjectAck, MoqtMessageType::kSetup, }; for (const MoqtMessageType message_type : message_types) { if (message_type == MoqtMessageType::kSetup) { @@ -169,6 +161,10 @@ auto data = std::get<MoqtNamespaceDone>(structured_data); return framer_.SerializeNamespaceDone(data); } + case MoqtMessageType::kPublishSkipped: { + auto data = std::get<MoqtPublishSkipped>(structured_data); + return framer_.SerializePublishSkipped(data); + } case moqt::MoqtMessageType::kTrackStatus: { auto data = std::get<MoqtTrackStatus>(structured_data); return framer_.SerializeTrackStatus(data);
diff --git a/quiche/quic/moqt/moqt_messages.cc b/quiche/quic/moqt/moqt_messages.cc index 6aeb9c5..f2f7652 100644 --- a/quiche/quic/moqt/moqt_messages.cc +++ b/quiche/quic/moqt/moqt_messages.cc
@@ -91,6 +91,8 @@ return "NAMESPACE"; case MoqtMessageType::kNamespaceDone: return "NAMESPACE_DONE"; + case MoqtMessageType::kPublishSkipped: + return "PUBLISH_SKIPPED"; case MoqtMessageType::kRequestOk: return "REQUEST_OK"; case MoqtMessageType::kGoAway:
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h index 149fa69..8488fdb 100644 --- a/quiche/quic/moqt/moqt_messages.h +++ b/quiche/quic/moqt/moqt_messages.h
@@ -213,6 +213,7 @@ kPublishDone = 0x0b, kTrackStatus = 0x0d, kNamespaceDone = 0x0e, + kPublishSkipped = 0x0f, kGoAway = 0x10, kFetch = 0x16, kFetchOk = 0x18, @@ -431,6 +432,10 @@ TrackNamespace track_namespace_suffix; }; +struct QUICHE_EXPORT MoqtPublishSkipped { + FullTrackName name; +}; + enum class QUICHE_EXPORT FetchType : uint64_t { kStandalone = 0x1, kRelativeJoining = 0x2,
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc index d57ef11..7a17db0 100644 --- a/quiche/quic/moqt/moqt_parser.cc +++ b/quiche/quic/moqt/moqt_parser.cc
@@ -778,6 +778,15 @@ return namespace_done; } +absl::StatusOr<MoqtPublishSkipped> +MoqtControlMessageParser::ProcessPublishSkipped(absl::string_view data) const { + quic::QuicDataReader reader(data); + MoqtPublishSkipped publish_skipped; + QUICHE_RETURN_IF_ERROR(ReadFullTrackName(reader, publish_skipped.name)); + QUICHE_RETURN_IF_ERROR(CheckForTrailingData(reader)); + return publish_skipped; +} + absl::StatusOr<MoqtRequestOk> MoqtControlMessageParser::ProcessRequestOk( absl::string_view data) const { quic::QuicDataReader reader(data);
diff --git a/quiche/quic/moqt/moqt_parser.h b/quiche/quic/moqt/moqt_parser.h index a9c4ce5..cda423a 100644 --- a/quiche/quic/moqt/moqt_parser.h +++ b/quiche/quic/moqt/moqt_parser.h
@@ -164,6 +164,8 @@ absl::StatusOr<MoqtNamespace> ProcessNamespace(absl::string_view data) const; absl::StatusOr<MoqtNamespaceDone> ProcessNamespaceDone( absl::string_view data) const; + absl::StatusOr<MoqtPublishSkipped> ProcessPublishSkipped( + absl::string_view data) const; absl::StatusOr<MoqtTrackStatus> ProcessTrackStatus( absl::string_view data) const; absl::StatusOr<MoqtGoAway> ProcessGoAway(absl::string_view data) const; @@ -212,6 +214,8 @@ return parse(&MoqtControlMessageParser::ProcessNamespace); case MoqtMessageType::kNamespaceDone: return parse(&MoqtControlMessageParser::ProcessNamespaceDone); + case MoqtMessageType::kPublishSkipped: + return parse(&MoqtControlMessageParser::ProcessPublishSkipped); case MoqtMessageType::kTrackStatus: return parse(&MoqtControlMessageParser::ProcessTrackStatus); case MoqtMessageType::kGoAway:
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc index bb16687..78e7252 100644 --- a/quiche/quic/moqt/moqt_parser_test.cc +++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -57,6 +57,7 @@ MoqtMessageType::kPublishNamespace, MoqtMessageType::kNamespace, MoqtMessageType::kNamespaceDone, + MoqtMessageType::kPublishSkipped, MoqtMessageType::kGoAway, MoqtMessageType::kSubscribeNamespace, MoqtMessageType::kSubscribeTracks,
diff --git a/quiche/quic/moqt/test_tools/moqt_framer_utils.cc b/quiche/quic/moqt/test_tools/moqt_framer_utils.cc index 1b11bfd..f301c3c 100644 --- a/quiche/quic/moqt/test_tools/moqt_framer_utils.cc +++ b/quiche/quic/moqt/test_tools/moqt_framer_utils.cc
@@ -52,6 +52,9 @@ quiche::QuicheBuffer operator()(const MoqtNamespaceDone& message) { return framer.SerializeNamespaceDone(message); } + quiche::QuicheBuffer operator()(const MoqtPublishSkipped& message) { + return framer.SerializePublishSkipped(message); + } quiche::QuicheBuffer operator()(const MoqtTrackStatus& message) { return framer.SerializeTrackStatus(message); }
diff --git a/quiche/quic/moqt/test_tools/moqt_framer_utils.h b/quiche/quic/moqt/test_tools/moqt_framer_utils.h index 7fd5a9d..4a53a64 100644 --- a/quiche/quic/moqt/test_tools/moqt_framer_utils.h +++ b/quiche/quic/moqt/test_tools/moqt_framer_utils.h
@@ -20,11 +20,13 @@ namespace moqt::test { -using AnyMoqtControlMessage = std::variant< - MoqtSetup, MoqtRequestOk, MoqtRequestError, MoqtSubscribe, MoqtSubscribeOk, - MoqtPublishDone, MoqtRequestUpdate, MoqtPublishNamespace, MoqtTrackStatus, - MoqtGoAway, MoqtSubscribeNamespace, MoqtSubscribeTracks, MoqtFetch, - MoqtFetchOk, MoqtPublish, MoqtNamespace, MoqtNamespaceDone, MoqtObjectAck>; +using AnyMoqtControlMessage = + std::variant<MoqtSetup, MoqtRequestOk, MoqtRequestError, MoqtSubscribe, + MoqtSubscribeOk, MoqtPublishDone, MoqtRequestUpdate, + MoqtPublishNamespace, MoqtTrackStatus, MoqtGoAway, + MoqtSubscribeNamespace, MoqtSubscribeTracks, MoqtFetch, + MoqtFetchOk, MoqtPublish, MoqtNamespace, MoqtNamespaceDone, + MoqtPublishSkipped, MoqtObjectAck>; std::string SerializeGenericMessage(const AnyMoqtControlMessage& frame, bool use_webtrans = false);
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h index 6c023c7..5325c92 100644 --- a/quiche/quic/moqt/test_tools/moqt_test_message.h +++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -119,7 +119,7 @@ MoqtRequestUpdate, MoqtPublishNamespace, MoqtTrackStatus, MoqtGoAway, MoqtSubscribeNamespace, MoqtSubscribeTracks, MoqtFetch, MoqtFetchOk, MoqtPublish, MoqtNamespace, - MoqtNamespaceDone, MoqtObjectAck>; + MoqtNamespaceDone, MoqtPublishSkipped, MoqtObjectAck>; // The total actual size of the message. size_t total_message_size() const { return wire_image_size_; } @@ -1068,6 +1068,39 @@ }; }; +class QUICHE_NO_EXPORT PublishSkippedMessage : public TestMessageBase { + public: + PublishSkippedMessage() : TestMessageBase() { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + bool EqualFieldValues(const MessageStructuredData& values) const override { + auto cast = std::get<MoqtPublishSkipped>(values); + if (cast.name != publish_skipped_.name) { + QUIC_LOG(INFO) << "PUBLISH_SKIPPED name mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vv---v---"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(publish_skipped_); + } + + private: + uint8_t raw_packet_[12] = { + 0x0f, 0x00, 0x09, 0x01, + 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + 0x03, 0x62, 0x61, 0x72, // track_name = "bar" + }; + + MoqtPublishSkipped publish_skipped_ = { + FullTrackName("foo", "bar"), + }; +}; + class QUICHE_NO_EXPORT RequestOkMessage : public TestMessageBase { public: RequestOkMessage() : TestMessageBase() { @@ -1662,6 +1695,8 @@ return std::make_unique<NamespaceMessage>(); case MoqtMessageType::kNamespaceDone: return std::make_unique<NamespaceDoneMessage>(); + case MoqtMessageType::kPublishSkipped: + return std::make_unique<PublishSkippedMessage>(); case MoqtMessageType::kTrackStatus: return std::make_unique<TrackStatusMessage>(); case MoqtMessageType::kGoAway: