Update parser and framer to draft-01.

PiperOrigin-RevId: 569892337
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc
index 986e1ae..5806b7d 100644
--- a/quiche/quic/moqt/moqt_framer.cc
+++ b/quiche/quic/moqt/moqt_framer.cc
@@ -220,6 +220,22 @@
   return buffer;
 }
 
+quiche::QuicheBuffer MoqtFramer::SerializeUnsubscribe(
+    const MoqtUnsubscribe& message) {
+  size_t message_len = NeededVarIntLen(message.full_track_name.length()) +
+                       message.full_track_name.length();
+  size_t buffer_size =
+      message_len +
+      NeededVarIntLen(static_cast<uint64_t>(MoqtMessageType::kUnsubscribe)) +
+      NeededVarIntLen(message_len);
+  quiche::QuicheBuffer buffer(allocator_, buffer_size);
+  quic::QuicDataWriter writer(buffer.size(), buffer.data());
+  writer.WriteVarInt62(static_cast<uint64_t>(MoqtMessageType::kUnsubscribe));
+  writer.WriteVarInt62(message_len);
+  writer.WriteStringPieceVarInt62(message.full_track_name);
+  return buffer;
+}
+
 quiche::QuicheBuffer MoqtFramer::SerializeAnnounce(
     const MoqtAnnounce& message) {
   size_t message_len = NeededVarIntLen(message.track_namespace.length()) +
@@ -249,7 +265,8 @@
 
 quiche::QuicheBuffer MoqtFramer::SerializeAnnounceOk(
     const MoqtAnnounceOk& message) {
-  size_t message_len = message.track_namespace.length();
+  size_t message_len = NeededVarIntLen(message.track_namespace.length()) +
+                       message.track_namespace.length();
   size_t buffer_size =
       message_len +
       NeededVarIntLen(static_cast<uint64_t>(MoqtMessageType::kAnnounceOk)) +
@@ -258,7 +275,7 @@
   quic::QuicDataWriter writer(buffer.size(), buffer.data());
   writer.WriteVarInt62(static_cast<uint64_t>(MoqtMessageType::kAnnounceOk));
   writer.WriteVarInt62(message_len);
-  writer.WriteStringPiece(message.track_namespace);
+  writer.WriteStringPieceVarInt62(message.track_namespace);
   return buffer;
 }
 
@@ -283,6 +300,22 @@
   return buffer;
 }
 
+quiche::QuicheBuffer MoqtFramer::SerializeUnannounce(
+    const MoqtUnannounce& message) {
+  size_t message_len = NeededVarIntLen(message.track_namespace.length()) +
+                       message.track_namespace.length();
+  size_t buffer_size =
+      message_len +
+      NeededVarIntLen(static_cast<uint64_t>(MoqtMessageType::kUnannounce)) +
+      NeededVarIntLen(message_len);
+  quiche::QuicheBuffer buffer(allocator_, buffer_size);
+  quic::QuicDataWriter writer(buffer.size(), buffer.data());
+  writer.WriteVarInt62(static_cast<uint64_t>(MoqtMessageType::kUnannounce));
+  writer.WriteVarInt62(message_len);
+  writer.WriteStringPieceVarInt62(message.track_namespace);
+  return buffer;
+}
+
 quiche::QuicheBuffer MoqtFramer::SerializeGoAway() {
   size_t buffer_size =
       NeededVarIntLen(static_cast<uint64_t>(MoqtMessageType::kGoAway)) +
diff --git a/quiche/quic/moqt/moqt_framer.h b/quiche/quic/moqt/moqt_framer.h
index ba194a6..d88ecfb 100644
--- a/quiche/quic/moqt/moqt_framer.h
+++ b/quiche/quic/moqt/moqt_framer.h
@@ -49,9 +49,11 @@
   quiche::QuicheBuffer SerializeSubscribeOk(const MoqtSubscribeOk& message);
   quiche::QuicheBuffer SerializeSubscribeError(
       const MoqtSubscribeError& message);
+  quiche::QuicheBuffer SerializeUnsubscribe(const MoqtUnsubscribe& message);
   quiche::QuicheBuffer SerializeAnnounce(const MoqtAnnounce& message);
   quiche::QuicheBuffer SerializeAnnounceOk(const MoqtAnnounceOk& message);
   quiche::QuicheBuffer SerializeAnnounceError(const MoqtAnnounceError& message);
+  quiche::QuicheBuffer SerializeUnannounce(const MoqtUnannounce& message);
   quiche::QuicheBuffer SerializeGoAway();
 
  private:
diff --git a/quiche/quic/moqt/moqt_framer_test.cc b/quiche/quic/moqt/moqt_framer_test.cc
index dd3cad4..abfac63 100644
--- a/quiche/quic/moqt/moqt_framer_test.cc
+++ b/quiche/quic/moqt/moqt_framer_test.cc
@@ -130,6 +130,10 @@
         auto data = std::get<MoqtSubscribeError>(structured_data);
         return framer_.SerializeSubscribeError(data);
       }
+      case MoqtMessageType::kUnsubscribe: {
+        auto data = std::get<MoqtUnsubscribe>(structured_data);
+        return framer_.SerializeUnsubscribe(data);
+      }
       case MoqtMessageType::kAnnounce: {
         auto data = std::get<MoqtAnnounce>(structured_data);
         return framer_.SerializeAnnounce(data);
@@ -142,6 +146,10 @@
         auto data = std::get<MoqtAnnounceError>(structured_data);
         return framer_.SerializeAnnounceError(data);
       }
+      case MoqtMessageType::kUnannounce: {
+        auto data = std::get<MoqtUnannounce>(structured_data);
+        return framer_.SerializeUnannounce(data);
+      }
       case moqt::MoqtMessageType::kGoAway: {
         return framer_.SerializeGoAway();
       }
diff --git a/quiche/quic/moqt/moqt_messages.cc b/quiche/quic/moqt/moqt_messages.cc
index 9b37dc7..93a4b95 100644
--- a/quiche/quic/moqt/moqt_messages.cc
+++ b/quiche/quic/moqt/moqt_messages.cc
@@ -20,12 +20,16 @@
       return "SUBSCRIBE_OK";
     case MoqtMessageType::kSubscribeError:
       return "SUBSCRIBE_ERROR";
+    case MoqtMessageType::kUnsubscribe:
+      return "UNSUBSCRIBE";
     case MoqtMessageType::kAnnounce:
       return "ANNOUNCE";
     case MoqtMessageType::kAnnounceOk:
       return "ANNOUNCE_OK";
     case MoqtMessageType::kAnnounceError:
       return "ANNOUNCE_ERROR";
+    case MoqtMessageType::kUnannounce:
+      return "UNANNOUNCE";
     case MoqtMessageType::kGoAway:
       return "GOAWAY";
   }
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h
index 30c1d97..a88f284 100644
--- a/quiche/quic/moqt/moqt_messages.h
+++ b/quiche/quic/moqt/moqt_messages.h
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Structured data for message types in draft-ietf-moq-transport-00.
+// Structured data for message types in draft-ietf-moq-transport-01.
 
 #ifndef QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_
 #define QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_
@@ -33,6 +33,8 @@
   kAnnounce = 0x06,
   kAnnounceOk = 0x7,
   kAnnounceError = 0x08,
+  kUnannounce = 0x09,
+  kUnsubscribe = 0x0a,
   kGoAway = 0x10,
 };
 
@@ -88,6 +90,10 @@
   absl::string_view reason_phrase;
 };
 
+struct QUICHE_EXPORT MoqtUnsubscribe {
+  absl::string_view full_track_name;
+};
+
 struct QUICHE_EXPORT MoqtAnnounce {
   absl::string_view track_namespace;
   absl::optional<absl::string_view> authorization_info;
@@ -103,6 +109,10 @@
   absl::string_view reason_phrase;
 };
 
+struct QUICHE_EXPORT MoqtUnannounce {
+  absl::string_view track_namespace;
+};
+
 struct QUICHE_EXPORT MoqtGoAway {};
 
 std::string MoqtMessageTypeToString(MoqtMessageType message_type);
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index d90af04..3de44cf 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -284,12 +284,16 @@
       return ProcessSubscribeOk(data);
     case MoqtMessageType::kSubscribeError:
       return ProcessSubscribeError(data);
+    case MoqtMessageType::kUnsubscribe:
+      return ProcessUnsubscribe(data);
     case MoqtMessageType::kAnnounce:
       return ProcessAnnounce(data);
     case MoqtMessageType::kAnnounceOk:
       return ProcessAnnounceOk(data);
     case MoqtMessageType::kAnnounceError:
       return ProcessAnnounceError(data);
+    case MoqtMessageType::kUnannounce:
+      return ProcessUnannounce(data);
     case MoqtMessageType::kGoAway:
       return ProcessGoAway(data);
     default:
@@ -520,6 +524,18 @@
   return reader.PreviouslyReadPayload().length();
 }
 
+absl::optional<size_t> MoqtParser::ProcessUnsubscribe(absl::string_view data) {
+  MoqtUnsubscribe unsubscribe;
+  quic::QuicDataReader reader(data);
+  if (!reader.ReadStringPieceVarInt62(&unsubscribe.full_track_name)) {
+    return absl::nullopt;
+  }
+  if (reader.IsDoneReading()) {
+    visitor_.OnUnsubscribeMessage(unsubscribe);
+  }
+  return reader.PreviouslyReadPayload().length();
+}
+
 absl::optional<size_t> MoqtParser::ProcessAnnounce(absl::string_view data) {
   MoqtAnnounce announce;
   quic::QuicDataReader reader(data);
@@ -585,7 +601,7 @@
 absl::optional<size_t> MoqtParser::ProcessAnnounceOk(absl::string_view data) {
   MoqtAnnounceOk announce_ok;
   quic::QuicDataReader reader(data);
-  if (!reader.ReadStringPiece(&announce_ok.track_namespace, data.length())) {
+  if (!reader.ReadStringPieceVarInt62(&announce_ok.track_namespace)) {
     return absl::nullopt;
   }
   if (reader.IsDoneReading()) {
@@ -613,6 +629,18 @@
   return reader.PreviouslyReadPayload().length();
 }
 
+absl::optional<size_t> MoqtParser::ProcessUnannounce(absl::string_view data) {
+  MoqtUnannounce unannounce;
+  quic::QuicDataReader reader(data);
+  if (!reader.ReadStringPieceVarInt62(&unannounce.track_namespace)) {
+    return absl::nullopt;
+  }
+  if (reader.IsDoneReading()) {
+    visitor_.OnUnannounceMessage(unannounce);
+  }
+  return reader.PreviouslyReadPayload().length();
+}
+
 absl::optional<size_t> MoqtParser::ProcessGoAway(absl::string_view data) {
   if (!data.empty()) {
     // GOAWAY can only be followed by end_of_stream. Anything else is an error.
diff --git a/quiche/quic/moqt/moqt_parser.h b/quiche/quic/moqt/moqt_parser.h
index d931922..bb23546 100644
--- a/quiche/quic/moqt/moqt_parser.h
+++ b/quiche/quic/moqt/moqt_parser.h
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// A parser for draft-ietf-moq-transport-00.
+// A parser for draft-ietf-moq-transport-01.
 
 #ifndef QUICHE_QUIC_MOQT_MOQT_PARSER_H_
 #define QUICHE_QUIC_MOQT_MOQT_PARSER_H_
@@ -40,9 +40,11 @@
       const MoqtSubscribeRequest& message) = 0;
   virtual void OnSubscribeOkMessage(const MoqtSubscribeOk& message) = 0;
   virtual void OnSubscribeErrorMessage(const MoqtSubscribeError& message) = 0;
+  virtual void OnUnsubscribeMessage(const MoqtUnsubscribe& message) = 0;
   virtual void OnAnnounceMessage(const MoqtAnnounce& message) = 0;
   virtual void OnAnnounceOkMessage(const MoqtAnnounceOk& message) = 0;
   virtual void OnAnnounceErrorMessage(const MoqtAnnounceError& message) = 0;
+  virtual void OnUnannounceMessage(const MoqtUnannounce& message) = 0;
   // In an exception to the above, the parser calls this when it gets two bytes,
   // whether or not it includes stream FIN. When a zero-length message has
   // special meaning, a message with an actual length of zero is tricky!
@@ -93,9 +95,11 @@
   absl::optional<size_t> ProcessSubscribeRequest(absl::string_view data);
   absl::optional<size_t> ProcessSubscribeOk(absl::string_view data);
   absl::optional<size_t> ProcessSubscribeError(absl::string_view data);
+  absl::optional<size_t> ProcessUnsubscribe(absl::string_view data);
   absl::optional<size_t> ProcessAnnounce(absl::string_view data);
   absl::optional<size_t> ProcessAnnounceOk(absl::string_view data);
   absl::optional<size_t> ProcessAnnounceError(absl::string_view data);
+  absl::optional<size_t> ProcessUnannounce(absl::string_view data);
   absl::optional<size_t> ProcessGoAway(absl::string_view data);
 
   // If the message length field is zero, it runs to the end of the stream.
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc
index 357be26..3af0767 100644
--- a/quiche/quic/moqt/moqt_parser_test.cc
+++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -125,6 +125,14 @@
     subscribe_error.reason_phrase = absl::string_view(string1_);
     last_message_ = TestMessageBase::MessageStructuredData(subscribe_error);
   }
+  void OnUnsubscribeMessage(const MoqtUnsubscribe& message) override {
+    end_of_message_ = true;
+    messages_received_++;
+    MoqtUnsubscribe unsubscribe = message;
+    string0_ = std::string(unsubscribe.full_track_name);
+    unsubscribe.full_track_name = absl::string_view(string0_);
+    last_message_ = TestMessageBase::MessageStructuredData(unsubscribe);
+  }
   void OnAnnounceMessage(const MoqtAnnounce& message) override {
     end_of_message_ = true;
     messages_received_++;
@@ -155,6 +163,14 @@
     announce_error.reason_phrase = absl::string_view(string1_);
     last_message_ = TestMessageBase::MessageStructuredData(announce_error);
   }
+  void OnUnannounceMessage(const MoqtUnannounce& message) override {
+    end_of_message_ = true;
+    messages_received_++;
+    MoqtUnannounce unannounce = message;
+    string0_ = std::string(unannounce.track_namespace);
+    unannounce.track_namespace = absl::string_view(string0_);
+    last_message_ = TestMessageBase::MessageStructuredData(unannounce);
+  }
   void OnGoAwayMessage() override {
     got_goaway_ = true;
     end_of_message_ = true;
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h
index 5d1ac90..876a619 100644
--- a/quiche/quic/moqt/test_tools/moqt_test_message.h
+++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -35,8 +35,9 @@
   MoqtMessageType message_type() const { return message_type_; }
 
   typedef absl::variant<MoqtSetup, MoqtObject, MoqtSubscribeRequest,
-                        MoqtSubscribeOk, MoqtSubscribeError, MoqtAnnounce,
-                        MoqtAnnounceOk, MoqtAnnounceError, MoqtGoAway>
+                        MoqtSubscribeOk, MoqtSubscribeError, MoqtUnsubscribe,
+                        MoqtAnnounce, MoqtAnnounceOk, MoqtAnnounceError,
+                        MoqtUnannounce, MoqtGoAway>
       MessageStructuredData;
 
   // The total actual size of the message.
@@ -429,6 +430,37 @@
   };
 };
 
+class QUICHE_NO_EXPORT UnsubscribeMessage : public TestMessageBase {
+ public:
+  UnsubscribeMessage() : TestMessageBase(MoqtMessageType::kUnsubscribe) {
+    SetWireImage(raw_packet_, sizeof(raw_packet_));
+  }
+
+  bool EqualFieldValues(MessageStructuredData& values) const override {
+    auto cast = std::get<MoqtUnsubscribe>(values);
+    if (cast.full_track_name != unsubscribe_.full_track_name) {
+      QUIC_LOG(INFO) << "UNSUBSCRIBE full track name mismatch";
+      return false;
+    }
+    return true;
+  }
+
+  void ExpandVarints() override { ExpandVarintsImpl("vvv---"); }
+
+  MessageStructuredData structured_data() const override {
+    return TestMessageBase::MessageStructuredData(unsubscribe_);
+  }
+
+ private:
+  uint8_t raw_packet_[6] = {
+      0x0a, 0x04, 0x03, 0x66, 0x6f, 0x6f,  // track_name = "foo"
+  };
+
+  MoqtUnsubscribe unsubscribe_ = {
+      /*full_track_name=*/"foo",
+  };
+};
+
 class QUICHE_NO_EXPORT AnnounceMessage : public TestMessageBase {
  public:
   AnnounceMessage() : TestMessageBase(MoqtMessageType::kAnnounce) {
@@ -481,15 +513,15 @@
     return true;
   }
 
-  void ExpandVarints() override { ExpandVarintsImpl("vv---"); }
+  void ExpandVarints() override { ExpandVarintsImpl("vvv---"); }
 
   MessageStructuredData structured_data() const override {
     return TestMessageBase::MessageStructuredData(announce_ok_);
   }
 
  private:
-  uint8_t raw_packet_[5] = {
-      0x07, 0x03, 0x66, 0x6f, 0x6f,  // track_namespace = "foo"
+  uint8_t raw_packet_[6] = {
+      0x07, 0x04, 0x03, 0x66, 0x6f, 0x6f,  // track_namespace = "foo"
   };
 
   MoqtAnnounceOk announce_ok_ = {
@@ -540,6 +572,37 @@
   };
 };
 
+class QUICHE_NO_EXPORT UnannounceMessage : public TestMessageBase {
+ public:
+  UnannounceMessage() : TestMessageBase(MoqtMessageType::kUnannounce) {
+    SetWireImage(raw_packet_, sizeof(raw_packet_));
+  }
+
+  bool EqualFieldValues(MessageStructuredData& values) const override {
+    auto cast = std::get<MoqtUnannounce>(values);
+    if (cast.track_namespace != unannounce_.track_namespace) {
+      QUIC_LOG(INFO) << "UNSUBSCRIBE full track name mismatch";
+      return false;
+    }
+    return true;
+  }
+
+  void ExpandVarints() override { ExpandVarintsImpl("vvv---"); }
+
+  MessageStructuredData structured_data() const override {
+    return TestMessageBase::MessageStructuredData(unannounce_);
+  }
+
+ private:
+  uint8_t raw_packet_[6] = {
+      0x09, 0x04, 0x03, 0x66, 0x6f, 0x6f,  // track_namespace
+  };
+
+  MoqtUnannounce unannounce_ = {
+      /*track_namespace=*/"foo",
+  };
+};
+
 class QUICHE_NO_EXPORT GoAwayMessage : public TestMessageBase {
  public:
   GoAwayMessage() : TestMessageBase(MoqtMessageType::kGoAway) {