Update MoQT ANNOUNCE-related messages to draft-11.

PiperOrigin-RevId: 781194184
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc
index 1d5225c..803ab62 100644
--- a/quiche/quic/moqt/moqt_framer.cc
+++ b/quiche/quic/moqt/moqt_framer.cc
@@ -563,6 +563,7 @@
     return quiche::QuicheBuffer();
   }
   return SerializeControlMessage(MoqtMessageType::kAnnounce,
+                                 WireVarInt62(message.request_id),
                                  WireTrackNamespace(message.track_namespace),
                                  WireKeyValuePairList(parameters));
 }
@@ -570,16 +571,21 @@
 quiche::QuicheBuffer MoqtFramer::SerializeAnnounceOk(
     const MoqtAnnounceOk& message) {
   return SerializeControlMessage(MoqtMessageType::kAnnounceOk,
-                                 WireTrackNamespace(message.track_namespace));
+                                 WireVarInt62(message.request_id));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeAnnounceError(
     const MoqtAnnounceError& message) {
   return SerializeControlMessage(
-      MoqtMessageType::kAnnounceError,
-      WireTrackNamespace(message.track_namespace),
+      MoqtMessageType::kAnnounceError, WireVarInt62(message.request_id),
       WireVarInt62(message.error_code),
-      WireStringWithVarInt62Length(message.reason_phrase));
+      WireStringWithVarInt62Length(message.error_reason));
+}
+
+quiche::QuicheBuffer MoqtFramer::SerializeUnannounce(
+    const MoqtUnannounce& message) {
+  return SerializeControlMessage(MoqtMessageType::kUnannounce,
+                                 WireTrackNamespace(message.track_namespace));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeAnnounceCancel(
@@ -588,7 +594,7 @@
       MoqtMessageType::kAnnounceCancel,
       WireTrackNamespace(message.track_namespace),
       WireVarInt62(message.error_code),
-      WireStringWithVarInt62Length(message.reason_phrase));
+      WireStringWithVarInt62Length(message.error_reason));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeTrackStatusRequest(
@@ -607,12 +613,6 @@
                                  WireKeyValuePairList(parameters));
 }
 
-quiche::QuicheBuffer MoqtFramer::SerializeUnannounce(
-    const MoqtUnannounce& message) {
-  return SerializeControlMessage(MoqtMessageType::kUnannounce,
-                                 WireTrackNamespace(message.track_namespace));
-}
-
 quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus(
     const MoqtTrackStatus& message) {
   KeyValuePairList parameters;
diff --git a/quiche/quic/moqt/moqt_framer.h b/quiche/quic/moqt/moqt_framer.h
index d001464..a573ca4 100644
--- a/quiche/quic/moqt/moqt_framer.h
+++ b/quiche/quic/moqt/moqt_framer.h
@@ -49,11 +49,11 @@
   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 SerializeAnnounceCancel(
       const MoqtAnnounceCancel& message);
   quiche::QuicheBuffer SerializeTrackStatusRequest(
       const MoqtTrackStatusRequest& message);
-  quiche::QuicheBuffer SerializeUnannounce(const MoqtUnannounce& message);
   quiche::QuicheBuffer SerializeTrackStatus(const MoqtTrackStatus& message);
   quiche::QuicheBuffer SerializeGoAway(const MoqtGoAway& message);
   quiche::QuicheBuffer SerializeSubscribeAnnounces(
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h
index cd008cb..455ad9b 100644
--- a/quiche/quic/moqt/moqt_messages.h
+++ b/quiche/quic/moqt/moqt_messages.h
@@ -622,24 +622,31 @@
 };
 
 struct QUICHE_EXPORT MoqtAnnounce {
+  uint64_t request_id;
   TrackNamespace track_namespace;
   VersionSpecificParameters parameters;
 };
 
 struct QUICHE_EXPORT MoqtAnnounceOk {
-  TrackNamespace track_namespace;
+  uint64_t request_id;
 };
 
 struct QUICHE_EXPORT MoqtAnnounceError {
-  TrackNamespace track_namespace;
+  uint64_t request_id;
   RequestErrorCode error_code;
-  std::string reason_phrase;
+  std::string error_reason;
 };
 
 struct QUICHE_EXPORT MoqtUnannounce {
   TrackNamespace track_namespace;
 };
 
+struct QUICHE_EXPORT MoqtAnnounceCancel {
+  TrackNamespace track_namespace;
+  RequestErrorCode error_code;
+  std::string error_reason;
+};
+
 enum class QUICHE_EXPORT MoqtTrackStatusCode : uint64_t {
   kInProgress = 0x0,
   kDoesNotExist = 0x1,
@@ -674,12 +681,6 @@
   VersionSpecificParameters parameters;
 };
 
-struct QUICHE_EXPORT MoqtAnnounceCancel {
-  TrackNamespace track_namespace;
-  RequestErrorCode error_code;
-  std::string reason_phrase;
-};
-
 struct QUICHE_EXPORT MoqtGoAway {
   std::string new_session_uri;
 };
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index 9e1a0b0..d8d96b6 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -588,7 +588,8 @@
 
 size_t MoqtControlParser::ProcessAnnounce(quic::QuicDataReader& reader) {
   MoqtAnnounce announce;
-  if (!ReadTrackNamespace(reader, announce.track_namespace)) {
+  if (!reader.ReadVarInt62(&announce.request_id) ||
+      !ReadTrackNamespace(reader, announce.track_namespace)) {
     return 0;
   }
   KeyValuePairList parameters;
@@ -610,7 +611,7 @@
 
 size_t MoqtControlParser::ProcessAnnounceOk(quic::QuicDataReader& reader) {
   MoqtAnnounceOk announce_ok;
-  if (!ReadTrackNamespace(reader, announce_ok.track_namespace)) {
+  if (!reader.ReadVarInt62(&announce_ok.request_id)) {
     return 0;
   }
   visitor_.OnAnnounceOkMessage(announce_ok);
@@ -619,12 +620,10 @@
 
 size_t MoqtControlParser::ProcessAnnounceError(quic::QuicDataReader& reader) {
   MoqtAnnounceError announce_error;
-  if (!ReadTrackNamespace(reader, announce_error.track_namespace)) {
-    return 0;
-  }
   uint64_t error_code;
-  if (!reader.ReadVarInt62(&error_code) ||
-      !reader.ReadStringVarInt62(announce_error.reason_phrase)) {
+  if (!reader.ReadVarInt62(&announce_error.request_id) ||
+      !reader.ReadVarInt62(&error_code) ||
+      !reader.ReadStringVarInt62(announce_error.error_reason)) {
     return 0;
   }
   announce_error.error_code = static_cast<RequestErrorCode>(error_code);
@@ -639,7 +638,7 @@
   }
   uint64_t error_code;
   if (!reader.ReadVarInt62(&error_code) ||
-      !reader.ReadStringVarInt62(announce_cancel.reason_phrase)) {
+      !reader.ReadStringVarInt62(announce_cancel.error_reason)) {
     return 0;
   }
   announce_cancel.error_code = static_cast<RequestErrorCode>(error_code);
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc
index b527d59..3624c7d 100644
--- a/quiche/quic/moqt/moqt_parser_test.cc
+++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -807,8 +807,8 @@
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtControlParser parser(kWebTrans, &stream, visitor_);
   char announce[] = {
-      0x06, 0x00, 0x14, 0x01, 0x03, 0x66, 0x6f,
-      0x6f,                                      // track_namespace = "foo"
+      0x06, 0x00, 0x15, 0x02, 0x01, 0x03, 0x66,
+      0x6f, 0x6f,                                // track_namespace = "foo"
       0x02,                                      // 2 params
       0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72,  // authorization = "bar"
       0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72,  // authorization = "bar"
@@ -822,8 +822,8 @@
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtControlParser parser(kWebTrans, &stream, visitor_);
   char announce[] = {
-      0x06, 0x00, 0x10, 0x01, 0x03, 0x66, 0x6f,
-      0x6f,                                      // track_namespace = "foo"
+      0x06, 0x00, 0x11, 0x02, 0x01, 0x03, 0x66,
+      0x6f, 0x6f,                                // track_namespace = "foo"
       0x02,                                      // 2 params
       0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72,  // authorization_info = "bar"
       0x02, 0x67, 0x10,                          // delivery_timeout = 10000
@@ -1268,22 +1268,22 @@
 }
 
 // All messages with TrackNamespace use ReadTrackNamespace too check this. Use
-// ANNOUNCE_OK for the test because it's small.
+// ANNOUNCE.
 TEST_F(MoqtMessageSpecificTest, NamespaceTooSmall) {
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtControlParser parser(kRawQuic, &stream, visitor_);
-  char announce_ok[] = {
-      0x07, 0x00, 0x03,  // type, length
-      0x01, 0x01, 'a',   // 1 namespace element
+  char announce[7] = {
+      0x06, 0x00, 0x04, 0x02,  // request_id = 2
+      0x01, 0x00,              // one empty namespace element
+      0x00,                    // no parameters
   };
-  stream.Receive(absl::string_view(announce_ok, sizeof(announce_ok)), false);
+  stream.Receive(absl::string_view(announce, sizeof(announce)), false);
   parser.ReadAndDispatchMessages();
   EXPECT_EQ(visitor_.messages_received_, 1);
   EXPECT_EQ(visitor_.parsing_error_, std::nullopt);
-  announce_ok[2] -= 2;  // Remove one element.
-  announce_ok[3] = 0x00;
-  stream.Receive(absl::string_view(announce_ok, sizeof(announce_ok) - 2),
-                 false);
+  --announce[2];  // Remove one element.
+  --announce[4];
+  stream.Receive(absl::string_view(announce, sizeof(announce) - 1), false);
   parser.ReadAndDispatchMessages();
   EXPECT_EQ(visitor_.messages_received_, 1);
   EXPECT_EQ(visitor_.parsing_error_, "Invalid number of namespace elements");
@@ -1292,22 +1292,18 @@
 TEST_F(MoqtMessageSpecificTest, NamespaceTooLarge) {
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtControlParser parser(kRawQuic, &stream, visitor_);
-  char announce_ok[70] = {
-      0x07, 0x00, 0x41,  // type, length = 65
-      0x20,              // 32 namespace elements. This is the maximum.
+  char announce[39] = {
+      0x06, 0x00, 0x23, 0x02,  // type, length = 35, request_id = 2
+      0x20,                    // 32 namespace elements. This is the maximum.
   };
-  for (size_t i = 4; i < sizeof(announce_ok); i = i + 2) {
-    announce_ok[i] = 0x01;
-    announce_ok[i + 1] = 'a' + i;
-  }
-  stream.Receive(absl::string_view(announce_ok, sizeof(announce_ok) - 2),
-                 false);
+  // 32 empty namespace elements + no parameters.
+  stream.Receive(absl::string_view(announce, sizeof(announce) - 1), false);
   parser.ReadAndDispatchMessages();
   EXPECT_EQ(visitor_.messages_received_, 1);
   EXPECT_EQ(visitor_.parsing_error_, std::nullopt);
-  announce_ok[2] += 2;  // Add one element.
-  ++announce_ok[3];
-  stream.Receive(absl::string_view(announce_ok, sizeof(announce_ok)), false);
+  ++announce[2];  // Add one element.
+  ++announce[4];
+  stream.Receive(absl::string_view(announce, sizeof(announce)), false);
   parser.ReadAndDispatchMessages();
   EXPECT_EQ(visitor_.messages_received_, 1);
   EXPECT_EQ(visitor_.parsing_error_, "Invalid number of namespace elements");
diff --git a/quiche/quic/moqt/moqt_session.cc b/quiche/quic/moqt/moqt_session.cc
index 6a31483..e58a988 100644
--- a/quiche/quic/moqt/moqt_session.cc
+++ b/quiche/quic/moqt/moqt_session.cc
@@ -295,9 +295,22 @@
   if (outgoing_announces_.contains(track_namespace)) {
     std::move(announce_callback)(
         track_namespace,
-        MoqtAnnounceErrorReason{
-            RequestErrorCode::kInternalError,
-            "ANNOUNCE message already outstanding for namespace"});
+        MoqtAnnounceErrorReason{RequestErrorCode::kInternalError,
+                                "ANNOUNCE already outstanding for namespace"});
+    return;
+  }
+  if (next_request_id_ >= peer_max_request_id_) {
+    if (!last_requests_blocked_sent_.has_value() ||
+        peer_max_request_id_ > *last_requests_blocked_sent_) {
+      MoqtRequestsBlocked requests_blocked;
+      requests_blocked.max_request_id = peer_max_request_id_;
+      SendControlMessage(framer_.SerializeRequestsBlocked(requests_blocked));
+      last_requests_blocked_sent_ = peer_max_request_id_;
+    }
+    QUIC_DLOG(INFO) << ENDPOINT << "Tried to send ANNOUNCE with ID "
+                    << next_request_id_
+                    << " which is greater than the maximum ID "
+                    << peer_max_request_id_;
     return;
   }
   if (received_goaway_ || sent_goaway_) {
@@ -305,11 +318,14 @@
     return;
   }
   MoqtAnnounce message;
+  message.request_id = next_request_id_;
+  next_request_id_ += 2;
   message.track_namespace = track_namespace;
   message.parameters = parameters;
   SendControlMessage(framer_.SerializeAnnounce(message));
   QUIC_DLOG(INFO) << ENDPOINT << "Sent ANNOUNCE message for "
                   << message.track_namespace;
+  pending_outgoing_announces_[message.request_id] = track_namespace;
   outgoing_announces_[track_namespace] = std::move(announce_callback);
 }
 
@@ -1165,12 +1181,15 @@
 
 void MoqtSession::ControlStream::OnAnnounceMessage(
     const MoqtAnnounce& message) {
+  if (!session_->ValidateRequestId(message.request_id)) {
+    return;
+  }
   if (session_->sent_goaway_) {
     QUIC_DLOG(INFO) << ENDPOINT << "Received an ANNOUNCE after GOAWAY";
     MoqtAnnounceError error;
-    error.track_namespace = message.track_namespace;
+    error.request_id = message.request_id;
     error.error_code = RequestErrorCode::kUnauthorized;
-    error.reason_phrase = "ANNOUNCE after GOAWAY";
+    error.error_reason = "ANNOUNCE after GOAWAY";
     SendOrBufferMessage(session_->framer_.SerializeAnnounceError(error));
     return;
   }
@@ -1179,14 +1198,14 @@
                                                       message.parameters);
   if (error.has_value()) {
     MoqtAnnounceError reply;
-    reply.track_namespace = message.track_namespace;
+    reply.request_id = message.request_id;
     reply.error_code = error->error_code;
-    reply.reason_phrase = error->reason_phrase;
+    reply.error_reason = error->reason_phrase;
     SendOrBufferMessage(session_->framer_.SerializeAnnounceError(reply));
     return;
   }
   MoqtAnnounceOk ok;
-  ok.track_namespace = message.track_namespace;
+  ok.request_id = message.request_id;
   SendOrBufferMessage(session_->framer_.SerializeAnnounceOk(ok));
 }
 
@@ -1194,24 +1213,41 @@
 // ERROR, we immediately destroy the state.
 void MoqtSession::ControlStream::OnAnnounceOkMessage(
     const MoqtAnnounceOk& message) {
-  auto it = session_->outgoing_announces_.find(message.track_namespace);
-  if (it == session_->outgoing_announces_.end()) {
-    return;  // State might have been destroyed due to UNANNOUNCE.
+  auto it = session_->pending_outgoing_announces_.find(message.request_id);
+  if (it == session_->pending_outgoing_announces_.end()) {
+    session_->Error(MoqtError::kProtocolViolation,
+                    "Received ANNOUNCE_OK for unknown request_id");
+    return;
   }
-  std::move(it->second)(message.track_namespace, std::nullopt);
+  TrackNamespace track_namespace = it->second;
+  session_->pending_outgoing_announces_.erase(it);
+  auto callback_it = session_->outgoing_announces_.find(track_namespace);
+  if (callback_it == session_->outgoing_announces_.end()) {
+    // It might have already been destroyed due to UNANNOUNCE.
+    return;
+  }
+  std::move(callback_it->second)(track_namespace, std::nullopt);
 }
 
 void MoqtSession::ControlStream::OnAnnounceErrorMessage(
     const MoqtAnnounceError& message) {
-  auto it = session_->outgoing_announces_.find(message.track_namespace);
-  if (it == session_->outgoing_announces_.end()) {
+  auto it = session_->pending_outgoing_announces_.find(message.request_id);
+  if (it == session_->pending_outgoing_announces_.end()) {
+    session_->Error(MoqtError::kProtocolViolation,
+                    "Received ANNOUNCE_ERROR for unknown request_id");
+    return;
+  }
+  TrackNamespace track_namespace = it->second;
+  session_->pending_outgoing_announces_.erase(it);
+  auto it2 = session_->outgoing_announces_.find(track_namespace);
+  if (it2 == session_->outgoing_announces_.end()) {
     return;  // State might have been destroyed due to UNANNOUNCE.
   }
-  std::move(it->second)(
-      message.track_namespace,
+  std::move(it2->second)(
+      track_namespace,
       MoqtAnnounceErrorReason{message.error_code,
-                              std::string(message.reason_phrase)});
-  session_->outgoing_announces_.erase(it);
+                              std::string(message.error_reason)});
+  session_->outgoing_announces_.erase(it2);
 }
 
 void MoqtSession::ControlStream::OnAnnounceCancelMessage(
@@ -1227,7 +1263,7 @@
   std::move(it->second)(
       message.track_namespace,
       MoqtAnnounceErrorReason{message.error_code,
-                              std::string(message.reason_phrase)});
+                              std::string(message.error_reason)});
   session_->outgoing_announces_.erase(it);
 }
 
diff --git a/quiche/quic/moqt/moqt_session.h b/quiche/quic/moqt/moqt_session.h
index 775ed5e..d88742a 100644
--- a/quiche/quic/moqt/moqt_session.h
+++ b/quiche/quic/moqt/moqt_session.h
@@ -819,11 +819,12 @@
   absl::flat_hash_map<FullTrackName, MoqtPublishingMonitorInterface*>
       monitoring_interfaces_for_published_tracks_;
 
-  // Indexed by track namespace. If the value is not nullptr, no OK or ERROR
-  // has been received. The entry is deleted after sending UNANNOUNCE or
-  // receiving ANNOUNCE_CANCEL.
+  // Outgoing ANNOUNCE for which no OK or ERROR has been received.
+  absl::flat_hash_map<uint64_t, TrackNamespace> pending_outgoing_announces_;
+  // All outgoing ANNOUNCE.
   absl::flat_hash_map<TrackNamespace, MoqtOutgoingAnnounceCallback>
       outgoing_announces_;
+
   // The value is nullptr after OK or ERROR is received. The entry is deleted
   // when sending UNSUBSCRIBE_ANNOUNCES, to make sure the application doesn't
   // unsubscribe from something that it isn't subscribed to. ANNOUNCEs that
diff --git a/quiche/quic/moqt/moqt_session_test.cc b/quiche/quic/moqt/moqt_session_test.cc
index a89bf05..03cb3ae 100644
--- a/quiche/quic/moqt/moqt_session_test.cc
+++ b/quiche/quic/moqt/moqt_session_test.cc
@@ -364,7 +364,7 @@
                     VersionSpecificParameters());
 
   MoqtAnnounceOk ok = {
-      TrackNamespace("foo"),
+      /*request_id=*/0,
   };
   EXPECT_CALL(announce_resolved_callback, Call(_, _))
       .WillOnce([&](TrackNamespace track_namespace,
@@ -377,7 +377,7 @@
   MoqtAnnounceCancel cancel = {
       TrackNamespace("foo"),
       RequestErrorCode::kInternalError,
-      /*reason_phrase=*/"Test error",
+      /*error_reason=*/"Test error",
   };
   EXPECT_CALL(announce_resolved_callback, Call(_, _))
       .WillOnce([&](TrackNamespace track_namespace,
@@ -407,7 +407,7 @@
                     VersionSpecificParameters());
 
   MoqtAnnounceOk ok = {
-      TrackNamespace{"foo"},
+      /*request_id=*/0,
   };
   EXPECT_CALL(announce_resolved_callback, Call(_, _))
       .WillOnce([&](TrackNamespace track_namespace,
@@ -440,7 +440,7 @@
                     VersionSpecificParameters());
 
   MoqtAnnounceError error = {
-      /*track_namespace=*/TrackNamespace{"foo"},
+      /*request_id=*/0,
       /*error_code=*/RequestErrorCode::kInternalError,
       /*reason_phrase=*/"Test error",
   };
@@ -893,15 +893,15 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtAnnounce announce = {
+      /*request_id=*/1,
       track_namespace,
       *parameters,
   };
   EXPECT_CALL(session_callbacks_.incoming_announce_callback,
               Call(track_namespace, parameters))
       .WillOnce(Return(std::nullopt));
-  EXPECT_CALL(
-      mock_stream_,
-      Writev(SerializedControlMessage(MoqtAnnounceOk{track_namespace}), _));
+  EXPECT_CALL(mock_stream_,
+              Writev(SerializedControlMessage(MoqtAnnounceOk{1}), _));
   stream_input->OnAnnounceMessage(announce);
   MoqtUnannounce unannounce = {
       track_namespace,
@@ -920,15 +920,15 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtAnnounce announce = {
+      /*request_id=*/1,
       track_namespace,
       *parameters,
   };
   EXPECT_CALL(session_callbacks_.incoming_announce_callback,
               Call(track_namespace, parameters))
       .WillOnce(Return(std::nullopt));
-  EXPECT_CALL(
-      mock_stream_,
-      Writev(SerializedControlMessage(MoqtAnnounceOk{track_namespace}), _));
+  EXPECT_CALL(mock_stream_,
+              Writev(SerializedControlMessage(MoqtAnnounceOk{1}), _));
   stream_input->OnAnnounceMessage(announce);
   EXPECT_CALL(mock_stream_,
               Writev(SerializedControlMessage(MoqtAnnounceCancel{
@@ -947,6 +947,7 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtAnnounce announce = {
+      /*request_id=*/1,
       track_namespace,
       *parameters,
   };
@@ -957,11 +958,10 @@
   EXPECT_CALL(session_callbacks_.incoming_announce_callback,
               Call(track_namespace, parameters))
       .WillOnce(Return(error));
-  EXPECT_CALL(
-      mock_stream_,
-      Writev(SerializedControlMessage(MoqtAnnounceError{
-                 track_namespace, error.error_code, error.reason_phrase}),
-             _));
+  EXPECT_CALL(mock_stream_,
+              Writev(SerializedControlMessage(MoqtAnnounceError{
+                         1, error.error_code, error.reason_phrase}),
+                     _));
   stream_input->OnAnnounceMessage(announce);
 }
 
@@ -3196,11 +3196,11 @@
   EXPECT_CALL(mock_stream_,
               Writev(ControlMessageOfType(MoqtMessageType::kAnnounceError), _));
   stream_input->OnAnnounceMessage(
-      MoqtAnnounce(TrackNamespace("foo"), VersionSpecificParameters()));
+      MoqtAnnounce(3, TrackNamespace("foo"), VersionSpecificParameters()));
   EXPECT_CALL(mock_stream_,
               Writev(ControlMessageOfType(MoqtMessageType::kFetchError), _));
   MoqtFetch fetch = DefaultFetch();
-  fetch.request_id = 3;
+  fetch.request_id = 5;
   stream_input->OnFetchMessage(fetch);
   EXPECT_CALL(
       mock_stream_,
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h
index fcfbce5..cee1e60 100644
--- a/quiche/quic/moqt/test_tools/moqt_test_message.h
+++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -813,32 +813,37 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtAnnounce>(values);
+    if (cast.request_id != announce_.request_id) {
+      QUIC_LOG(INFO) << "ANNOUNCE request ID mismatch";
+      return false;
+    }
     if (cast.track_namespace != announce_.track_namespace) {
-      QUIC_LOG(INFO) << "ANNOUNCE MESSAGE track namespace mismatch";
+      QUIC_LOG(INFO) << "ANNOUNCE track namespace mismatch";
       return false;
     }
     if (cast.parameters != announce_.parameters) {
-      QUIC_LOG(INFO) << "ANNOUNCE MESSAGE parameter mismatch";
+      QUIC_LOG(INFO) << "ANNOUNCE parameter mismatch";
       return false;
     }
     return true;
   }
 
-  void ExpandVarints() override { ExpandVarintsImpl("vv---vvv-----"); }
+  void ExpandVarints() override { ExpandVarintsImpl("vvv---vvv-----"); }
 
   MessageStructuredData structured_data() const override {
     return TestMessageBase::MessageStructuredData(announce_);
   }
 
  private:
-  uint8_t raw_packet_[16] = {
-      0x06, 0x00, 0x0d, 0x01, 0x03, 0x66, 0x6f,
-      0x6f,                                      // track_namespace = "foo"
+  uint8_t raw_packet_[17] = {
+      0x06, 0x00, 0x0e, 0x02,                    // request_id = 2
+      0x01, 0x03, 0x66, 0x6f, 0x6f,              // track_namespace = "foo"
       0x01,                                      // 1 parameter
       0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72,  // authorization_tag = "bar"
   };
 
   MoqtAnnounce announce_ = {
+      /*request_id=*/2,
       TrackNamespace{"foo"},
       VersionSpecificParameters(AuthTokenType::kOutOfBand, "bar"),
   };
@@ -852,27 +857,26 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtAnnounceOk>(values);
-    if (cast.track_namespace != announce_ok_.track_namespace) {
-      QUIC_LOG(INFO) << "ANNOUNCE OK MESSAGE track namespace mismatch";
+    if (cast.request_id != announce_ok_.request_id) {
+      QUIC_LOG(INFO) << "ANNOUNCE OK MESSAGE request ID mismatch";
       return false;
     }
     return true;
   }
 
-  void ExpandVarints() override { ExpandVarintsImpl("vv---"); }
+  void ExpandVarints() override { ExpandVarintsImpl("v"); }
 
   MessageStructuredData structured_data() const override {
     return TestMessageBase::MessageStructuredData(announce_ok_);
   }
 
  private:
-  uint8_t raw_packet_[8] = {
-      0x07, 0x00, 0x05, 0x01,
-      0x03, 0x66, 0x6f, 0x6f,  // track_namespace = "foo"
+  uint8_t raw_packet_[4] = {
+      0x07, 0x00, 0x01, 0x01,  // request_id = 1
   };
 
   MoqtAnnounceOk announce_ok_ = {
-      TrackNamespace("foo"),
+      /*request_id=*/1,
   };
 };
 
@@ -884,37 +888,36 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtAnnounceError>(values);
-    if (cast.track_namespace != announce_error_.track_namespace) {
-      QUIC_LOG(INFO) << "ANNOUNCE ERROR track namespace mismatch";
+    if (cast.request_id != announce_error_.request_id) {
+      QUIC_LOG(INFO) << "ANNOUNCE_ERROR request ID mismatch";
       return false;
     }
     if (cast.error_code != announce_error_.error_code) {
-      QUIC_LOG(INFO) << "ANNOUNCE ERROR error code mismatch";
+      QUIC_LOG(INFO) << "ANNOUNCE_ERROR error code mismatch";
       return false;
     }
-    if (cast.reason_phrase != announce_error_.reason_phrase) {
-      QUIC_LOG(INFO) << "ANNOUNCE ERROR reason phrase mismatch";
+    if (cast.error_reason != announce_error_.error_reason) {
+      QUIC_LOG(INFO) << "ANNOUNCE_ERROR error reason mismatch";
       return false;
     }
     return true;
   }
 
-  void ExpandVarints() override { ExpandVarintsImpl("vv---vv---"); }
+  void ExpandVarints() override { ExpandVarintsImpl("vvv---"); }
 
   MessageStructuredData structured_data() const override {
     return TestMessageBase::MessageStructuredData(announce_error_);
   }
 
  private:
-  uint8_t raw_packet_[13] = {
-      0x08, 0x00, 0x0a, 0x01,
-      0x03, 0x66, 0x6f, 0x6f,  // track_namespace = "foo"
+  uint8_t raw_packet_[9] = {
+      0x08, 0x00, 0x06, 0x01,  // request_id = 1
       0x03,                    // error_code = 3
       0x03, 0x62, 0x61, 0x72,  // reason_phrase = "bar"
   };
 
   MoqtAnnounceError announce_error_ = {
-      TrackNamespace("foo"),
+      /*request_id=*/1,
       RequestErrorCode::kNotSupported,
       /*reason_phrase=*/"bar",
   };
@@ -936,7 +939,7 @@
       QUIC_LOG(INFO) << "ANNOUNCE CANCEL error code mismatch";
       return false;
     }
-    if (cast.reason_phrase != announce_cancel_.reason_phrase) {
+    if (cast.error_reason != announce_cancel_.error_reason) {
       QUIC_LOG(INFO) << "ANNOUNCE CANCEL reason phrase mismatch";
       return false;
     }
@@ -954,13 +957,13 @@
       0x0c, 0x00, 0x0a, 0x01,
       0x03, 0x66, 0x6f, 0x6f,  // track_namespace = "foo"
       0x03,                    // error_code = 3
-      0x03, 0x62, 0x61, 0x72,  // reason_phrase = "bar"
+      0x03, 0x62, 0x61, 0x72,  // error_reason = "bar"
   };
 
   MoqtAnnounceCancel announce_cancel_ = {
       TrackNamespace("foo"),
       RequestErrorCode::kNotSupported,
-      /*reason_phrase=*/"bar",
+      /*error_reason=*/"bar",
   };
 };