Update MoQT SUBSCRIBE_ANNOUNCES to draft-11.

PiperOrigin-RevId: 781206674
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc
index 803ab62..769c51c 100644
--- a/quiche/quic/moqt/moqt_framer.cc
+++ b/quiche/quic/moqt/moqt_framer.cc
@@ -648,6 +648,7 @@
     return quiche::QuicheBuffer();
   }
   return SerializeControlMessage(MoqtMessageType::kSubscribeAnnounces,
+                                 WireVarInt62(message.request_id),
                                  WireTrackNamespace(message.track_namespace),
                                  WireKeyValuePairList(parameters));
 }
@@ -655,16 +656,15 @@
 quiche::QuicheBuffer MoqtFramer::SerializeSubscribeAnnouncesOk(
     const MoqtSubscribeAnnouncesOk& message) {
   return SerializeControlMessage(MoqtMessageType::kSubscribeAnnouncesOk,
-                                 WireTrackNamespace(message.track_namespace));
+                                 WireVarInt62(message.request_id));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeSubscribeAnnouncesError(
     const MoqtSubscribeAnnouncesError& message) {
   return SerializeControlMessage(
       MoqtMessageType::kSubscribeAnnouncesError,
-      WireTrackNamespace(message.track_namespace),
-      WireVarInt62(message.error_code),
-      WireStringWithVarInt62Length(message.reason_phrase));
+      WireVarInt62(message.request_id), WireVarInt62(message.error_code),
+      WireStringWithVarInt62Length(message.error_reason));
 }
 
 quiche::QuicheBuffer MoqtFramer::SerializeUnsubscribeAnnounces(
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h
index 455ad9b..2e6960d 100644
--- a/quiche/quic/moqt/moqt_messages.h
+++ b/quiche/quic/moqt/moqt_messages.h
@@ -686,18 +686,19 @@
 };
 
 struct QUICHE_EXPORT MoqtSubscribeAnnounces {
+  uint64_t request_id;
   TrackNamespace track_namespace;
   VersionSpecificParameters parameters;
 };
 
 struct QUICHE_EXPORT MoqtSubscribeAnnouncesOk {
-  TrackNamespace track_namespace;
+  uint64_t request_id;
 };
 
 struct QUICHE_EXPORT MoqtSubscribeAnnouncesError {
-  TrackNamespace track_namespace;
+  uint64_t request_id;
   RequestErrorCode error_code;
-  std::string reason_phrase;
+  std::string error_reason;
 };
 
 struct QUICHE_EXPORT MoqtUnsubscribeAnnounces {
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index d8d96b6..968a9e5 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -720,7 +720,8 @@
 size_t MoqtControlParser::ProcessSubscribeAnnounces(
     quic::QuicDataReader& reader) {
   MoqtSubscribeAnnounces subscribe_announces;
-  if (!ReadTrackNamespace(reader, subscribe_announces.track_namespace)) {
+  if (!reader.ReadVarInt62(&subscribe_announces.request_id) ||
+      !ReadTrackNamespace(reader, subscribe_announces.track_namespace)) {
     return 0;
   }
   KeyValuePairList parameters;
@@ -743,7 +744,7 @@
 size_t MoqtControlParser::ProcessSubscribeAnnouncesOk(
     quic::QuicDataReader& reader) {
   MoqtSubscribeAnnouncesOk subscribe_namespace_ok;
-  if (!ReadTrackNamespace(reader, subscribe_namespace_ok.track_namespace)) {
+  if (!reader.ReadVarInt62(&subscribe_namespace_ok.request_id)) {
     return 0;
   }
   visitor_.OnSubscribeAnnouncesOkMessage(subscribe_namespace_ok);
@@ -754,9 +755,9 @@
     quic::QuicDataReader& reader) {
   MoqtSubscribeAnnouncesError subscribe_namespace_error;
   uint64_t error_code;
-  if (!ReadTrackNamespace(reader, subscribe_namespace_error.track_namespace) ||
+  if (!reader.ReadVarInt62(&subscribe_namespace_error.request_id) ||
       !reader.ReadVarInt62(&error_code) ||
-      !reader.ReadStringVarInt62(subscribe_namespace_error.reason_phrase)) {
+      !reader.ReadStringVarInt62(subscribe_namespace_error.error_reason)) {
     return 0;
   }
   subscribe_namespace_error.error_code =
diff --git a/quiche/quic/moqt/moqt_session.cc b/quiche/quic/moqt/moqt_session.cc
index e58a988..2a202ed 100644
--- a/quiche/quic/moqt/moqt_session.cc
+++ b/quiche/quic/moqt/moqt_session.cc
@@ -264,13 +264,37 @@
                     << "Tried to send SUBSCRIBE_ANNOUNCES after GOAWAY";
     return false;
   }
+  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 SUBSCRIBE_ANNOUNCES with ID "
+                    << next_request_id_
+                    << " which is greater than the maximum ID "
+                    << peer_max_request_id_;
+    return false;
+  }
+  if (outgoing_subscribe_announces_.contains(track_namespace)) {
+    std::move(callback)(
+        track_namespace, RequestErrorCode::kInternalError,
+        "SUBSCRIBE_ANNOUNCES already outstanding for namespace");
+    return false;
+  }
   MoqtSubscribeAnnounces message;
+  message.request_id = next_request_id_;
+  next_request_id_ += 2;
   message.track_namespace = track_namespace;
   message.parameters = parameters;
   SendControlMessage(framer_.SerializeSubscribeAnnounces(message));
   QUIC_DLOG(INFO) << ENDPOINT << "Sent SUBSCRIBE_ANNOUNCES message for "
                   << message.track_namespace;
-  outgoing_subscribe_announces_[track_namespace] = std::move(callback);
+  pending_outgoing_subscribe_announces_[message.request_id] =
+      PendingSubscribeAnnouncesData{track_namespace, std::move(callback)};
+  outgoing_subscribe_announces_.emplace(track_namespace);
   return true;
 }
 
@@ -1322,14 +1346,17 @@
 
 void MoqtSession::ControlStream::OnSubscribeAnnouncesMessage(
     const MoqtSubscribeAnnounces& message) {
+  if (!session_->ValidateRequestId(message.request_id)) {
+    return;
+  }
   // TODO(martinduke): Handle authentication.
   if (session_->sent_goaway_) {
     QUIC_DLOG(INFO) << ENDPOINT
                     << "Received a SUBSCRIBE_ANNOUNCES after GOAWAY";
     MoqtSubscribeAnnouncesError error;
-    error.track_namespace = message.track_namespace;
+    error.request_id = message.request_id;
     error.error_code = RequestErrorCode::kUnauthorized;
-    error.reason_phrase = "SUBSCRIBE_ANNOUNCES after GOAWAY";
+    error.error_reason = "SUBSCRIBE_ANNOUNCES after GOAWAY";
     SendOrBufferMessage(
         session_->framer_.SerializeSubscribeAnnouncesError(error));
     return;
@@ -1339,49 +1366,45 @@
           message.track_namespace, message.parameters);
   if (result.has_value()) {
     MoqtSubscribeAnnouncesError error;
-    error.track_namespace = message.track_namespace;
+    error.request_id = message.request_id;
     error.error_code = result->error_code;
-    error.reason_phrase = result->reason_phrase;
+    error.error_reason = result->reason_phrase;
     SendOrBufferMessage(
         session_->framer_.SerializeSubscribeAnnouncesError(error));
     return;
   }
   MoqtSubscribeAnnouncesOk ok;
-  ok.track_namespace = message.track_namespace;
+  ok.request_id = message.request_id;
   SendOrBufferMessage(session_->framer_.SerializeSubscribeAnnouncesOk(ok));
 }
 
 void MoqtSession::ControlStream::OnSubscribeAnnouncesOkMessage(
     const MoqtSubscribeAnnouncesOk& message) {
   auto it =
-      session_->outgoing_subscribe_announces_.find(message.track_namespace);
-  if (it == session_->outgoing_subscribe_announces_.end()) {
+      session_->pending_outgoing_subscribe_announces_.find(message.request_id);
+  if (it == session_->pending_outgoing_subscribe_announces_.end()) {
+    session_->Error(MoqtError::kProtocolViolation,
+                    "Received SUBSCRIBE_ANNOUNCES_OK for unknown request_id");
     return;  // UNSUBSCRIBE_ANNOUNCES may already have deleted the entry.
   }
-  if (it->second == nullptr) {
-    session_->Error(MoqtError::kProtocolViolation,
-                    "Two responses to SUBSCRIBE_ANNOUNCES");
-    return;
-  }
-  std::move(it->second)(message.track_namespace, std::nullopt, "");
-  it->second = nullptr;
+  std::move(it->second.callback)(it->second.track_namespace, std::nullopt, "");
+  session_->pending_outgoing_subscribe_announces_.erase(it);
 }
 
 void MoqtSession::ControlStream::OnSubscribeAnnouncesErrorMessage(
     const MoqtSubscribeAnnouncesError& message) {
   auto it =
-      session_->outgoing_subscribe_announces_.find(message.track_namespace);
-  if (it == session_->outgoing_subscribe_announces_.end()) {
+      session_->pending_outgoing_subscribe_announces_.find(message.request_id);
+  if (it == session_->pending_outgoing_subscribe_announces_.end()) {
+    session_->Error(
+        MoqtError::kProtocolViolation,
+        "Received SUBSCRIBE_ANNOUNCES_ERROR for unknown request_id");
     return;  // UNSUBSCRIBE_ANNOUNCES may already have deleted the entry.
   }
-  if (it->second == nullptr) {
-    session_->Error(MoqtError::kProtocolViolation,
-                    "Two responses to SUBSCRIBE_ANNOUNCES");
-    return;
-  }
-  std::move(it->second)(message.track_namespace, message.error_code,
-                        absl::string_view(message.reason_phrase));
-  session_->outgoing_subscribe_announces_.erase(it);
+  std::move(it->second.callback)(it->second.track_namespace, message.error_code,
+                                 absl::string_view(message.error_reason));
+  session_->outgoing_subscribe_announces_.erase(it->second.track_namespace);
+  session_->pending_outgoing_subscribe_announces_.erase(it);
 }
 
 void MoqtSession::ControlStream::OnUnsubscribeAnnouncesMessage(
diff --git a/quiche/quic/moqt/moqt_session.h b/quiche/quic/moqt/moqt_session.h
index d88742a..924674f 100644
--- a/quiche/quic/moqt/moqt_session.h
+++ b/quiche/quic/moqt/moqt_session.h
@@ -829,8 +829,13 @@
   // when sending UNSUBSCRIBE_ANNOUNCES, to make sure the application doesn't
   // unsubscribe from something that it isn't subscribed to. ANNOUNCEs that
   // result from this subscription use incoming_announce_callback.
-  absl::flat_hash_map<TrackNamespace, MoqtOutgoingSubscribeAnnouncesCallback>
-      outgoing_subscribe_announces_;
+  struct PendingSubscribeAnnouncesData {
+    TrackNamespace track_namespace;
+    MoqtOutgoingSubscribeAnnouncesCallback callback;
+  };
+  absl::flat_hash_map<uint64_t, PendingSubscribeAnnouncesData>
+      pending_outgoing_subscribe_announces_;
+  absl::flat_hash_set<TrackNamespace> outgoing_subscribe_announces_;
 
   // The minimum request ID the peer can use that is monotonically increasing.
   uint64_t next_incoming_request_id_ = 0;
diff --git a/quiche/quic/moqt/moqt_session_test.cc b/quiche/quic/moqt/moqt_session_test.cc
index 03cb3ae..32400fc 100644
--- a/quiche/quic/moqt/moqt_session_test.cc
+++ b/quiche/quic/moqt/moqt_session_test.cc
@@ -55,12 +55,14 @@
 
 constexpr webtransport::StreamId kIncomingUniStreamId = 15;
 constexpr webtransport::StreamId kOutgoingUniStreamId = 14;
+constexpr uint64_t kDefaultLocalRequestId = 0;
+constexpr uint64_t kDefaultPeerRequestId = 1;
 
 FullTrackName kDefaultTrackName() { return FullTrackName("foo", "bar"); }
 
-MoqtSubscribe DefaultSubscribe() {
+MoqtSubscribe DefaultSubscribe(uint64_t request_id) {
   MoqtSubscribe subscribe = {
-      /*request_id=*/1,
+      request_id,
       /*track_alias=*/2,
       kDefaultTrackName(),
       /*subscriber_priority=*/0x80,
@@ -74,13 +76,24 @@
   return subscribe;
 }
 
+// The usual test case is that a SUBSCRIBE is coming in.
+MoqtSubscribe DefaultSubscribe() {
+  return DefaultSubscribe(kDefaultPeerRequestId);
+}
+
+// Used when a test sets up a remote track.
+MoqtSubscribe DefaultLocalSubscribe() {
+  return DefaultSubscribe(kDefaultLocalRequestId);
+}
+
 MoqtFetch DefaultFetch() {
   MoqtFetch fetch = {
-      /*request_id=*/1,
+      kDefaultPeerRequestId,
       /*subscriber_priority=*/0x80,
       /*group_order=*/std::nullopt,
       /*fetch=*/
-      StandaloneFetch(kDefaultTrackName(), Location(0, 0), 1, std::nullopt),
+      StandaloneFetch(kDefaultTrackName(), Location(0, 0),
+                      kDefaultPeerRequestId, std::nullopt),
       /*parameters=*/VersionSpecificParameters(),
   };
   return fetch;
@@ -471,7 +484,8 @@
   EXPECT_CALL(mock_stream_,
               Writev(ControlMessageOfType(MoqtMessageType::kSubscribeOk), _));
   listener->OnSubscribeAccepted();
-  EXPECT_NE(MoqtSessionPeer::GetSubscription(&session_, 1), nullptr);
+  EXPECT_NE(MoqtSessionPeer::GetSubscription(&session_, kDefaultPeerRequestId),
+            nullptr);
 }
 
 TEST_F(MoqtSessionTest, AsynchronousSubscribeReturnsError) {
@@ -490,7 +504,8 @@
   listener->OnSubscribeRejected(
       MoqtSubscribeErrorReason(RequestErrorCode::kInternalError, "Test error"),
       request.track_alias);
-  EXPECT_EQ(MoqtSessionPeer::GetSubscription(&session_, 1), nullptr);
+  EXPECT_EQ(MoqtSessionPeer::GetSubscription(&session_, kDefaultPeerRequestId),
+            nullptr);
 }
 
 TEST_F(MoqtSessionTest, SubscribeForPast) {
@@ -579,7 +594,7 @@
 
   // Peer unsubscribes.
   MoqtUnsubscribe unsubscribe = {
-      /*request_id=*/1,
+      kDefaultPeerRequestId,
   };
   stream_input->OnUnsubscribeMessage(unsubscribe);
   EXPECT_EQ(MoqtSessionPeer::GetSubscription(&session_, 1), nullptr);
@@ -893,15 +908,17 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtAnnounce announce = {
-      /*request_id=*/1,
+      kDefaultPeerRequestId,
       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{1}), _));
+  EXPECT_CALL(
+      mock_stream_,
+      Writev(SerializedControlMessage(MoqtAnnounceOk{kDefaultPeerRequestId}),
+             _));
   stream_input->OnAnnounceMessage(announce);
   MoqtUnannounce unannounce = {
       track_namespace,
@@ -920,15 +937,17 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtAnnounce announce = {
-      /*request_id=*/1,
+      kDefaultPeerRequestId,
       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{1}), _));
+  EXPECT_CALL(
+      mock_stream_,
+      Writev(SerializedControlMessage(MoqtAnnounceOk{kDefaultPeerRequestId}),
+             _));
   stream_input->OnAnnounceMessage(announce);
   EXPECT_CALL(mock_stream_,
               Writev(SerializedControlMessage(MoqtAnnounceCancel{
@@ -947,7 +966,7 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtAnnounce announce = {
-      /*request_id=*/1,
+      kDefaultPeerRequestId,
       track_namespace,
       *parameters,
   };
@@ -958,10 +977,11 @@
   EXPECT_CALL(session_callbacks_.incoming_announce_callback,
               Call(track_namespace, parameters))
       .WillOnce(Return(error));
-  EXPECT_CALL(mock_stream_,
-              Writev(SerializedControlMessage(MoqtAnnounceError{
-                         1, error.error_code, error.reason_phrase}),
-                     _));
+  EXPECT_CALL(
+      mock_stream_,
+      Writev(SerializedControlMessage(MoqtAnnounceError{
+                 kDefaultPeerRequestId, error.error_code, error.reason_phrase}),
+             _));
   stream_input->OnAnnounceMessage(announce);
 }
 
@@ -984,7 +1004,7 @@
       },
       VersionSpecificParameters());
   MoqtSubscribeAnnouncesOk ok = {
-      /*track_namespace=*/track_namespace,
+      kDefaultLocalRequestId,
   };
   stream_input->OnSubscribeAnnouncesOkMessage(ok);
   EXPECT_TRUE(got_callback);
@@ -1015,7 +1035,7 @@
       },
       VersionSpecificParameters());
   MoqtSubscribeAnnouncesError error = {
-      track_namespace,
+      kDefaultLocalRequestId,
       RequestErrorCode::kInvalidRange,
       /*reason_phrase=*/"deadbeef",
   };
@@ -1111,7 +1131,8 @@
   MockSubscribeRemoteTrackVisitor visitor_;
   FullTrackName ftn("foo", "bar");
   std::string payload = "deadbeef";
-  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultSubscribe(), &visitor_);
+  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultLocalSubscribe(),
+                                     &visitor_);
   MoqtObject object = {
       /*track_alias=*/2,
       /*group_sequence=*/0,
@@ -1140,7 +1161,7 @@
 
   // SUBSCRIBE_OK arrives
   MoqtSubscribeOk ok = {
-      /*request_id=*/1,
+      kDefaultLocalRequestId,
       /*expires=*/quic::QuicTimeDelta::FromMilliseconds(0),
       /*group_order=*/MoqtDeliveryOrder::kAscending,
       /*largest_location=*/std::nullopt,
@@ -1156,7 +1177,8 @@
   MockSubscribeRemoteTrackVisitor visitor;
   FullTrackName ftn("foo", "bar");
   std::string payload = "deadbeef";
-  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultSubscribe(), &visitor);
+  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultLocalSubscribe(),
+                                     &visitor);
   MoqtObject object = {
       /*track_alias=*/2,
       /*group_sequence=*/0,
@@ -1185,7 +1207,7 @@
 
   // SUBSCRIBE_ERROR arrives
   MoqtSubscribeError subscribe_error = {
-      /*request_id=*/1,
+      kDefaultLocalRequestId,
       /*error_code=*/RequestErrorCode::kRetryTrackAlias,
       /*reason_phrase=*/"foo",
       /*track_alias =*/3,
@@ -1203,11 +1225,12 @@
 
 TEST_F(MoqtSessionTest, SubscribeErrorWithTrackAlias) {
   MockSubscribeRemoteTrackVisitor visitor;
-  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultSubscribe(), &visitor);
+  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultLocalSubscribe(),
+                                     &visitor);
 
   // SUBSCRIBE_ERROR arrives
   MoqtSubscribeError subscribe_error = {
-      /*request_id=*/1,
+      kDefaultLocalRequestId,
       /*error_code=*/RequestErrorCode::kRetryTrackAlias,
       /*reason_phrase=*/"foo",
       /*track_alias =*/3,
@@ -1223,11 +1246,12 @@
 
 TEST_F(MoqtSessionTest, SubscribeErrorWithBadTrackAlias) {
   MockSubscribeRemoteTrackVisitor visitor;
-  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultSubscribe(), &visitor);
+  MoqtSessionPeer::CreateRemoteTrack(&session_, DefaultLocalSubscribe(),
+                                     &visitor);
 
   // SUBSCRIBE_ERROR arrives
   MoqtSubscribeError subscribe_error = {
-      /*request_id=*/1,
+      kDefaultLocalRequestId,
       /*error_code=*/RequestErrorCode::kRetryTrackAlias,
       /*reason_phrase=*/"foo",
       /*track_alias =*/2,
@@ -2572,6 +2596,7 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtSubscribeAnnounces announces = {
+      /*request_id=*/1,
       track_namespace,
       *parameters,
   };
@@ -2599,6 +2624,7 @@
   auto parameters = std::make_optional<VersionSpecificParameters>(
       AuthTokenType::kOutOfBand, "foo");
   MoqtSubscribeAnnounces announces = {
+      /*request_id=*/1,
       track_namespace,
       *parameters,
   };
@@ -3206,8 +3232,7 @@
       mock_stream_,
       Writev(ControlMessageOfType(MoqtMessageType::kSubscribeAnnouncesError),
              _));
-  stream_input->OnSubscribeAnnouncesMessage(
-      MoqtSubscribeAnnounces(TrackNamespace("foo")));
+  stream_input->OnSubscribeAnnouncesMessage(MoqtSubscribeAnnounces(7));
   // Block all outgoing SUBSCRIBE, ANNOUNCE, GOAWAY,etc.
   EXPECT_CALL(mock_stream_, Writev).Times(0);
   MockSubscribeRemoteTrackVisitor remote_track_visitor;
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h
index cee1e60..1039053 100644
--- a/quiche/quic/moqt/test_tools/moqt_test_message.h
+++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -1133,6 +1133,10 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtSubscribeAnnounces>(values);
+    if (cast.request_id != subscribe_namespace_.request_id) {
+      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE request_id mismatch";
+      return false;
+    }
     if (cast.track_namespace != subscribe_namespace_.track_namespace) {
       QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE track namespace mismatch";
       return false;
@@ -1144,20 +1148,22 @@
     return true;
   }
 
-  void ExpandVarints() override { ExpandVarintsImpl("vv---vvv-----"); }
+  void ExpandVarints() override { ExpandVarintsImpl("vvv---vvv-----"); }
 
   MessageStructuredData structured_data() const override {
     return TestMessageBase::MessageStructuredData(subscribe_namespace_);
   }
 
  private:
-  uint8_t raw_packet_[16] = {
-      0x11, 0x00, 0x0d, 0x01, 0x03, 0x66, 0x6f, 0x6f,  // namespace = "foo"
-      0x01,                                            // 1 parameter
+  uint8_t raw_packet_[17] = {
+      0x11, 0x00, 0x0e, 0x01,                    // request_id = 1
+      0x01, 0x03, 0x66, 0x6f, 0x6f,              // namespace = "foo"
+      0x01,                                      // 1 parameter
       0x01, 0x05, 0x03, 0x00, 0x62, 0x61, 0x72,  // authorization_tag = "bar"
   };
 
   MoqtSubscribeAnnounces subscribe_namespace_ = {
+      /*request_id=*/1,
       TrackNamespace("foo"),
       VersionSpecificParameters(AuthTokenType::kOutOfBand, "bar"),
   };
@@ -1171,26 +1177,26 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtSubscribeAnnouncesOk>(values);
-    if (cast.track_namespace != subscribe_namespace_ok_.track_namespace) {
-      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_OK track namespace mismatch";
+    if (cast.request_id != subscribe_namespace_ok_.request_id) {
+      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_OK 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(subscribe_namespace_ok_);
   }
 
  private:
-  uint8_t raw_packet_[8] = {
-      0x12, 0x00, 0x05, 0x01, 0x03, 0x66, 0x6f, 0x6f,  // namespace = "foo"
+  uint8_t raw_packet_[4] = {
+      0x12, 0x00, 0x01, 0x01,  // request_id = 1
   };
 
   MoqtSubscribeAnnouncesOk subscribe_namespace_ok_ = {
-      TrackNamespace("foo"),
+      /*request_id=*/1,
   };
 };
 
@@ -1202,39 +1208,38 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtSubscribeAnnouncesError>(values);
-    if (cast.track_namespace != subscribe_namespace_error_.track_namespace) {
-      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR track namespace mismatch";
+    if (cast.request_id != subscribe_namespace_error_.request_id) {
+      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR request_id mismatch";
       return false;
     }
     if (cast.error_code != subscribe_namespace_error_.error_code) {
       QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR error code mismatch";
       return false;
     }
-    if (cast.reason_phrase != subscribe_namespace_error_.reason_phrase) {
-      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_ERROR reason phrase mismatch";
+    if (cast.error_reason != subscribe_namespace_error_.error_reason) {
+      QUIC_LOG(INFO) << "SUBSCRIBE_NAMESPACE_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(subscribe_namespace_error_);
   }
 
  private:
-  uint8_t raw_packet_[13] = {
-      0x13, 0x00, 0x0a, 0x01,
-      0x03, 0x66, 0x6f, 0x6f,  // track_namespace = "foo"
+  uint8_t raw_packet_[9] = {
+      0x13, 0x00, 0x06, 0x01,  // request_id = 1
       0x01,                    // error_code = 1
-      0x03, 0x62, 0x61, 0x72,  // reason_phrase = "bar"
+      0x03, 0x62, 0x61, 0x72,  // error_reason = "bar"
   };
 
   MoqtSubscribeAnnouncesError subscribe_namespace_error_ = {
-      TrackNamespace("foo"),
+      /*request_id=*/1,
       /*error_code=*/RequestErrorCode::kUnauthorized,
-      /*reason_phrase=*/"bar",
+      /*error_reason=*/"bar",
   };
 };