Handles expires param = 0 as infinite.

Bug from MOQT interop

PiperOrigin-RevId: 868889896
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index d32baf9..7d43a77 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -358,6 +358,9 @@
             expires = quic::QuicTimeDelta::TryFromMilliseconds(
                           std::get<uint64_t>(value))
                           .value_or(quic::QuicTimeDelta::Infinite());
+            if (expires->IsZero()) {
+              expires = quic::QuicTimeDelta::Infinite();
+            }
             break;
           case MessageParameter::kLargestObject:
             if (largest_object.has_value()) {
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc
index 0fed64d..7c34e0c 100644
--- a/quiche/quic/moqt/moqt_parser_test.cc
+++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -1291,6 +1291,22 @@
   EXPECT_EQ(visitor_.parsing_error_, "Invalid SUBSCRIBE_OK track extensions");
 }
 
+TEST_F(MoqtMessageSpecificTest, SubscribeOkExpirationIsZero) {
+  webtransport::test::InMemoryStream stream(/*stream_id=*/0);
+  MoqtControlParser parser(kRawQuic, &stream, visitor_);
+  char subscribe_ok[] = {
+      0x04, 0x00, 0x05, 0x02, 0x01,  // request_id = 2, track_alias = 1
+      0x01, 0x08, 0x00               // expires = 0
+  };
+  stream.Receive(absl::string_view(subscribe_ok, sizeof(subscribe_ok)), false);
+  parser.ReadAndDispatchMessages();
+  EXPECT_EQ(visitor_.parsing_error_, std::nullopt);
+  ASSERT_EQ(visitor_.messages_received_, 1);
+  MoqtSubscribeOk message =
+      std::get<MoqtSubscribeOk>(visitor_.last_message_.value());
+  EXPECT_EQ(message.parameters.expires, quic::QuicTimeDelta::Infinite());
+}
+
 TEST_F(MoqtMessageSpecificTest, FetchWholeGroup) {
   webtransport::test::InMemoryStream stream(/*stream_id=*/0);
   MoqtControlParser parser(kRawQuic, &stream, visitor_);