Make `last_timestamp` a local variable.

There is no reason to carry the timestamp values across the parser calls.  The current code is also structured so that if the first ACK timestamp block is empty, and the second one is not, the second one gets the `last_timestamp` value from previous parse, which can be anything.

Also fix the bug where we never check return value of `OnAckTimestamp` (it returns true, but we still shouldn't ignore it).

PiperOrigin-RevId: 994024141
diff --git a/quiche/quic/core/quic_framer.cc b/quiche/quic/core/quic_framer.cc
index 4ff9171..ed5a691 100644
--- a/quiche/quic/core/quic_framer.cc
+++ b/quiche/quic/core/quic_framer.cc
@@ -441,7 +441,6 @@
       local_receive_timestamps_exponent_(0),
       process_reset_stream_at_(false),
       creation_time_(creation_time),
-      last_timestamp_(QuicTime::Delta::Zero()),
       support_key_update_for_connection_(false),
       current_key_phase_bit_(false),
       potential_peer_key_update_attempt_count_(0),
@@ -3856,6 +3855,7 @@
   }
 
   uint64_t total_timestamp_count = 0;
+  std::optional<QuicTime::Delta> last_timestamp;
 
   // Iterate through all timestamp ranges, each of which represents a block of
   // contiguous packets for which receive timestamps are being reported. Each
@@ -3911,17 +3911,22 @@
         return false;
       }
       timestamp_delta = timestamp_delta << local_receive_timestamps_exponent_;
-      if (i == 0 && j == 0) {
-        last_timestamp_ = QuicTime::Delta::FromMicroseconds(timestamp_delta);
+      if (!last_timestamp.has_value()) {
+        last_timestamp = QuicTime::Delta::FromMicroseconds(timestamp_delta);
       } else {
-        last_timestamp_ = last_timestamp_ -
-                          QuicTime::Delta::FromMicroseconds(timestamp_delta);
-        if (last_timestamp_ < QuicTime::Delta::Zero()) {
+        last_timestamp = *last_timestamp -
+                         QuicTime::Delta::FromMicroseconds(timestamp_delta);
+        if (*last_timestamp < QuicTime::Delta::Zero()) {
           set_detailed_error("Receive timestamp delta too high.");
           return false;
         }
       }
-      visitor_->OnAckTimestamp(packet_number, creation_time_ + last_timestamp_);
+      if (!visitor_->OnAckTimestamp(packet_number,
+                                    creation_time_ + *last_timestamp)) {
+        set_detailed_error(
+            "Visitor suppresses further processing of ACK frame.");
+        return false;
+      }
       packet_number--;
     }
   }
diff --git a/quiche/quic/core/quic_framer.h b/quiche/quic/core/quic_framer.h
index 26671f8..6ad31c9 100644
--- a/quiche/quic/core/quic_framer.h
+++ b/quiche/quic/core/quic_framer.h
@@ -1157,8 +1157,6 @@
   bool process_reset_stream_at_;
   // The creation time of the connection, used to calculate timestamps.
   QuicTime creation_time_;
-  // The last timestamp received if local_max_receive_timestamps_per_ack_ > 0.
-  QuicTime::Delta last_timestamp_;
 
   // Whether IETF QUIC Key Update is supported on this connection.
   bool support_key_update_for_connection_;
diff --git a/quiche/quic/core/quic_framer_test.cc b/quiche/quic/core/quic_framer_test.cc
index 6e08dbc..8a4e557 100644
--- a/quiche/quic/core/quic_framer_test.cc
+++ b/quiche/quic/core/quic_framer_test.cc
@@ -4167,6 +4167,75 @@
                                "Receive timestamp delta too high."));
 }
 
+TEST_P(QuicFramerTest, AckFrameEmptyFirstReceiveTimestampRange) {
+  if (!VersionIsIetfQuic(framer_.transport_version())) {
+    return;
+  }
+  SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
+  // clang-format off
+  PacketFragments packet_ietf = {
+      // type (short header, 4 byte packet number)
+      {"",
+       { 0x43 }},
+      // connection_id
+      {"",
+       { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
+      // packet number
+      {"",
+       { 0x12, 0x34, 0x56, 0x78 }},
+
+      // frame type (IETF_ACK_RECEIVE_TIMESTAMPS frame)
+      {"",
+       { 0x83, 0x17, 0x83, 0x07 }},
+       // largest acked
+       {"Unable to read largest acked.",
+        { kVarInt62TwoBytes + 0x12, 0x34 }},   // = 4660
+       // Zero delta time.
+       {"Unable to read ack delay time.",
+        { kVarInt62OneByte + 0x00 }},
+       // number of additional ack blocks
+       {"Unable to read ack block count.",
+        { kVarInt62OneByte + 0x00 }},
+       // first ack block length.
+       {"Unable to read first ack block length.",
+        { kVarInt62OneByte + 0x00 }},  // 1st block length = 1
+
+       // Receive Timestamps (2 ranges; first range has 0 timestamps).
+       { "Unable to read receive timestamp range count.",
+         { kVarInt62OneByte + 0x02 }},
+       // Timestamp range 1 (empty).
+       { "Unable to read receive timestamp delta largest acked.",
+         { kVarInt62OneByte + 0x00 }},
+       { "Unable to read receive timestamp count.",
+         { kVarInt62OneByte + 0x00 }},
+       // Timestamp range 2 (two packets).
+       { "Unable to read receive timestamp delta largest acked.",
+         { kVarInt62OneByte + 0x02 }},
+       { "Unable to read receive timestamp count.",
+         { kVarInt62OneByte + 0x02 }},
+       { "Unable to read receive timestamp delta.",
+         { kVarInt62OneByte + 0x20 }},
+       { "Unable to read receive timestamp delta.",
+         { kVarInt62OneByte + 0x05 }},
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicEncryptedPacket> encrypted(
+      AssemblePacketFromFragments(packet_ietf));
+
+  framer_.set_local_max_receive_timestamps_per_ack(1000);
+  EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+  EXPECT_THAT(framer_.error(), IsQuicNoError());
+  ASSERT_TRUE(visitor_.header_.get());
+  const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+
+  EXPECT_THAT(frame.received_packet_times,
+              ContainerEq(PacketTimeVector{
+                  {LargestAcked(frame) - 2, CreationTimePlus(0x20)},
+                  {LargestAcked(frame) - 3, CreationTimePlus(0x1b)},
+              }));
+}
+
 TEST_P(QuicFramerTest, AckFrameTimeStampDeltaTooHigh) {
   SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
   // clang-format off