Internal QUICHE change

PiperOrigin-RevId: 331651056
Change-Id: Ic1b3d126e19f4294358b99d5a7099699a892cabd
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 7eb0202..6b694a0 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -2879,7 +2879,8 @@
     packet_send_time = packet_send_time + result.send_time_offset;
   }
 
-  if (debug_visitor_ != nullptr) {
+  if (!sent_packet_manager_.give_sent_packet_to_debug_visitor_after_sent() &&
+      debug_visitor_ != nullptr) {
     // Pass the write result to the visitor.
     debug_visitor_->OnPacketSent(*packet, packet->transmission_type,
                                  packet_send_time);
@@ -2927,6 +2928,24 @@
       << ENDPOINT
       << "Trying to start blackhole detection without no bytes in flight";
 
+  if (sent_packet_manager_.give_sent_packet_to_debug_visitor_after_sent() &&
+      debug_visitor_ != nullptr) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(
+        quic_give_sent_packet_to_debug_visitor_after_sent, 1, 2);
+    if (sent_packet_manager_.unacked_packets().empty()) {
+      QUIC_BUG << "Unacked map is empty right after packet is sent";
+    } else {
+      debug_visitor_->OnPacketSent(
+          packet->packet_number, packet->encrypted_length,
+          packet->has_crypto_handshake, packet->transmission_type,
+          packet->encryption_level,
+          sent_packet_manager_.unacked_packets()
+              .rbegin()
+              ->retransmittable_frames,
+          packet->nonretransmittable_frames, packet_send_time);
+    }
+  }
+
   if (in_flight || !retransmission_alarm_->IsSet()) {
     SetRetransmissionAlarm();
   }
@@ -4026,7 +4045,8 @@
     return false;
   }
 
-  if (debug_visitor_ != nullptr) {
+  if (!sent_packet_manager_.give_sent_packet_to_debug_visitor_after_sent() &&
+      debug_visitor_ != nullptr) {
     debug_visitor_->OnPacketSent(
         *probing_packet, probing_packet->transmission_type, packet_send_time);
   }
@@ -4036,6 +4056,24 @@
       probing_packet.get(), packet_send_time, probing_packet->transmission_type,
       NO_RETRANSMITTABLE_DATA, /*measure_rtt=*/true);
 
+  if (sent_packet_manager_.give_sent_packet_to_debug_visitor_after_sent() &&
+      debug_visitor_ != nullptr) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(
+        quic_give_sent_packet_to_debug_visitor_after_sent, 2, 2);
+    if (sent_packet_manager_.unacked_packets().empty()) {
+      QUIC_BUG << "Unacked map is empty right after packet is sent";
+    } else {
+      debug_visitor_->OnPacketSent(
+          probing_packet->packet_number, probing_packet->encrypted_length,
+          probing_packet->has_crypto_handshake,
+          probing_packet->transmission_type, probing_packet->encryption_level,
+          sent_packet_manager_.unacked_packets()
+              .rbegin()
+              ->retransmittable_frames,
+          probing_packet->nonretransmittable_frames, packet_send_time);
+    }
+  }
+
   if (IsWriteBlockedStatus(result.status)) {
     if (probing_writer == writer_) {
       // Visitor should not be write blocked if the probing writer is not the
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 4e2c507..9b62a98 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -202,10 +202,21 @@
   ~QuicConnectionDebugVisitor() override {}
 
   // Called when a packet has been sent.
+  // TODO(wub): Delete when deprecating
+  // --quic_give_sent_packet_to_debug_visitor_after_sent.
   virtual void OnPacketSent(const SerializedPacket& /*serialized_packet*/,
                             TransmissionType /*transmission_type*/,
                             QuicTime /*sent_time*/) {}
 
+  virtual void OnPacketSent(QuicPacketNumber /*packet_number*/,
+                            QuicPacketLength /*packet_length*/,
+                            bool /*has_crypto_handshake*/,
+                            TransmissionType /*transmission_type*/,
+                            EncryptionLevel /*encryption_level*/,
+                            const QuicFrames& /*retransmittable_frames*/,
+                            const QuicFrames& /*nonretransmittable_frames*/,
+                            QuicTime /*sent_time*/) {}
+
   // Called when a coalesced packet has been sent.
   virtual void OnCoalescedPacketSent(
       const QuicCoalescedPacket& /*coalesced_packet*/,
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 1070c77..7b9ece2 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -7170,10 +7170,20 @@
   MockQuicConnectionDebugVisitor debug_visitor;
   connection_.set_debug_visitor(&debug_visitor);
 
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  }
   connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
 
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  }
   connection_.SendConnectivityProbingPacket(writer_.get(),
                                             connection_.peer_address());
 }
@@ -7300,7 +7310,12 @@
   CongestionBlockWrites();
   connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  }
   EXPECT_CALL(debug_visitor, OnPingSent()).Times(1);
   connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
   EXPECT_FALSE(connection_.HasQueuedData());
@@ -7312,7 +7327,12 @@
 
   connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  }
   EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
   connection_.SendControlFrame(QuicFrame(new QuicBlockedFrame(1, 3)));
   EXPECT_EQ(1u, connection_.GetStats().blocked_frames_sent);
@@ -7328,7 +7348,12 @@
   QuicBlockedFrame blocked(1, 3);
 
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(0);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(0);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(0);
+  }
   EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
   connection_.SendControlFrame(QuicFrame(&blocked));
   EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
@@ -8051,21 +8076,45 @@
   }
   // Expect them retransmitted in cyclic order (foo, bar, test, foo, bar...).
   QuicPacketCount sent_count = 0;
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _))
-      .WillRepeatedly(Invoke([this, &sent_count](const SerializedPacket&,
-                                                 TransmissionType, QuicTime) {
-        ASSERT_EQ(1u, writer_->stream_frames().size());
-        if (connection_.version().CanSendCoalescedPackets()) {
-          // There is a delay of sending coalesced packet, so (6, 0, 3, 6,
-          // 0...).
-          EXPECT_EQ(3 * ((sent_count + 2) % 3),
-                    writer_->stream_frames()[0]->offset);
-        } else {
-          // Identify the frames by stream offset (0, 3, 6, 0, 3...).
-          EXPECT_EQ(3 * (sent_count % 3), writer_->stream_frames()[0]->offset);
-        }
-        sent_count++;
-      }));
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _))
+        .WillRepeatedly(
+            Invoke([this, &sent_count](QuicPacketNumber, QuicPacketLength, bool,
+                                       TransmissionType, EncryptionLevel,
+                                       const QuicFrames&, const QuicFrames&,
+                                       QuicTime) {
+              ASSERT_EQ(1u, writer_->stream_frames().size());
+              if (connection_.version().CanSendCoalescedPackets()) {
+                // There is a delay of sending coalesced packet, so (6, 0, 3, 6,
+                // 0...).
+                EXPECT_EQ(3 * ((sent_count + 2) % 3),
+                          writer_->stream_frames()[0]->offset);
+              } else {
+                // Identify the frames by stream offset (0, 3, 6, 0, 3...).
+                EXPECT_EQ(3 * (sent_count % 3),
+                          writer_->stream_frames()[0]->offset);
+              }
+              sent_count++;
+            }));
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _))
+        .WillRepeatedly(Invoke([this, &sent_count](const SerializedPacket&,
+                                                   TransmissionType, QuicTime) {
+          ASSERT_EQ(1u, writer_->stream_frames().size());
+          if (connection_.version().CanSendCoalescedPackets()) {
+            // There is a delay of sending coalesced packet, so (6, 0, 3, 6,
+            // 0...).
+            EXPECT_EQ(3 * ((sent_count + 2) % 3),
+                      writer_->stream_frames()[0]->offset);
+          } else {
+            // Identify the frames by stream offset (0, 3, 6, 0, 3...).
+            EXPECT_EQ(3 * (sent_count % 3),
+                      writer_->stream_frames()[0]->offset);
+          }
+          sent_count++;
+        }));
+  }
   EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
       .WillRepeatedly(Return(true));
   EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] {
@@ -8089,7 +8138,12 @@
 
   MockQuicConnectionDebugVisitor debug_visitor;
   connection_.set_debug_visitor(&debug_visitor);
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(0);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(0);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(0);
+  }
   EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
       .WillRepeatedly(Return(true));
   EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] {
@@ -9975,7 +10029,12 @@
   }
   MockQuicConnectionDebugVisitor debug_visitor;
   connection_.set_debug_visitor(&debug_visitor);
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(3);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(3);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(3);
+  }
   EXPECT_CALL(debug_visitor, OnCoalescedPacketSent(_, _)).Times(1);
   EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(1);
   {
@@ -10017,7 +10076,12 @@
 
   MockQuicConnectionDebugVisitor debug_visitor;
   connection_.set_debug_visitor(&debug_visitor);
-  EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  if (connection_.sent_packet_manager()
+          .give_sent_packet_to_debug_visitor_after_sent()) {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _, _, _, _, _)).Times(1);
+  } else {
+    EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
+  }
 
   // Our TestPacketWriter normally parses the sent packet using the version
   // from the connection, so here we need to tell it to use the encapsulation
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index 678ce04..6719a94 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -438,6 +438,10 @@
 
   void OnUserAgentIdKnown() { loss_algorithm_->OnUserAgentIdKnown(); }
 
+  bool give_sent_packet_to_debug_visitor_after_sent() const {
+    return give_sent_packet_to_debug_visitor_after_sent_;
+  }
+
  private:
   friend class test::QuicConnectionPeer;
   friend class test::QuicSentPacketManagerPeer;
@@ -694,6 +698,9 @@
   // The multiplier for caculating PTO timeout before any RTT sample is
   // available.
   float pto_multiplier_without_rtt_samples_;
+
+  const bool give_sent_packet_to_debug_visitor_after_sent_ =
+      GetQuicReloadableFlag(quic_give_sent_packet_to_debug_visitor_after_sent);
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_trace_visitor.cc b/quic/core/quic_trace_visitor.cc
index eeaf297..bf352f3 100644
--- a/quic/core/quic_trace_visitor.cc
+++ b/quic/core/quic_trace_visitor.cc
@@ -108,6 +108,75 @@
   }
 }
 
+void QuicTraceVisitor::OnPacketSent(
+    QuicPacketNumber packet_number,
+    QuicPacketLength packet_length,
+    bool /*has_crypto_handshake*/,
+    TransmissionType /*transmission_type*/,
+    EncryptionLevel encryption_level,
+    const QuicFrames& retransmittable_frames,
+    const QuicFrames& /*nonretransmittable_frames*/,
+    QuicTime sent_time) {
+  quic_trace::Event* event = trace_.add_events();
+  event->set_event_type(quic_trace::PACKET_SENT);
+  event->set_time_us(ConvertTimestampToRecordedFormat(sent_time));
+  event->set_packet_number(packet_number.ToUint64());
+  event->set_packet_size(packet_length);
+  event->set_encryption_level(EncryptionLevelToProto(encryption_level));
+
+  for (const QuicFrame& frame : retransmittable_frames) {
+    switch (frame.type) {
+      case STREAM_FRAME:
+      case RST_STREAM_FRAME:
+      case CONNECTION_CLOSE_FRAME:
+      case WINDOW_UPDATE_FRAME:
+      case BLOCKED_FRAME:
+      case PING_FRAME:
+      case HANDSHAKE_DONE_FRAME:
+      case ACK_FREQUENCY_FRAME:
+        PopulateFrameInfo(frame, event->add_frames());
+        break;
+
+      case PADDING_FRAME:
+      case MTU_DISCOVERY_FRAME:
+      case STOP_WAITING_FRAME:
+      case ACK_FRAME:
+        QUIC_BUG
+            << "Frames of type are not retransmittable and are not supposed "
+               "to be in retransmittable_frames";
+        break;
+
+      // New IETF frames, not used in current gQUIC version.
+      case NEW_CONNECTION_ID_FRAME:
+      case RETIRE_CONNECTION_ID_FRAME:
+      case MAX_STREAMS_FRAME:
+      case STREAMS_BLOCKED_FRAME:
+      case PATH_RESPONSE_FRAME:
+      case PATH_CHALLENGE_FRAME:
+      case STOP_SENDING_FRAME:
+      case MESSAGE_FRAME:
+      case CRYPTO_FRAME:
+      case NEW_TOKEN_FRAME:
+        break;
+
+      // Ignore gQUIC-specific frames.
+      case GOAWAY_FRAME:
+        break;
+
+      case NUM_FRAME_TYPES:
+        QUIC_BUG << "Unknown frame type encountered";
+        break;
+    }
+  }
+
+  // Output PCC DebugState on packet sent for analysis.
+  if (connection_->sent_packet_manager()
+          .GetSendAlgorithm()
+          ->GetCongestionControlType() == kPCC) {
+    PopulateTransportState(event->mutable_transport_state());
+  }
+}
+
 void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame,
                                          quic_trace::Frame* frame_record) {
   switch (frame.type) {
diff --git a/quic/core/quic_trace_visitor.h b/quic/core/quic_trace_visitor.h
index c9732cf..889d90a 100644
--- a/quic/core/quic_trace_visitor.h
+++ b/quic/core/quic_trace_visitor.h
@@ -18,10 +18,21 @@
  public:
   explicit QuicTraceVisitor(const QuicConnection* connection);
 
+  // TODO(wub): Delete when deprecating
+  // --quic_give_sent_packet_to_debug_visitor_after_sent.
   void OnPacketSent(const SerializedPacket& serialized_packet,
                     TransmissionType transmission_type,
                     QuicTime sent_time) override;
 
+  void OnPacketSent(QuicPacketNumber packet_number,
+                    QuicPacketLength packet_length,
+                    bool has_crypto_handshake,
+                    TransmissionType transmission_type,
+                    EncryptionLevel encryption_level,
+                    const QuicFrames& retransmittable_frames,
+                    const QuicFrames& nonretransmittable_frames,
+                    QuicTime sent_time) override;
+
   void OnIncomingAck(QuicPacketNumber ack_packet_number,
                      EncryptionLevel ack_decrypted_level,
                      const QuicAckFrame& ack_frame,
diff --git a/quic/core/quic_unacked_packet_map.h b/quic/core/quic_unacked_packet_map.h
index 601daeb..595f435 100644
--- a/quic/core/quic_unacked_packet_map.h
+++ b/quic/core/quic_unacked_packet_map.h
@@ -115,10 +115,13 @@
   typedef std::deque<QuicTransmissionInfo> UnackedPacketMap;
 
   typedef UnackedPacketMap::const_iterator const_iterator;
+  typedef UnackedPacketMap::const_reverse_iterator const_reverse_iterator;
   typedef UnackedPacketMap::iterator iterator;
 
   const_iterator begin() const { return unacked_packets_.begin(); }
   const_iterator end() const { return unacked_packets_.end(); }
+  const_reverse_iterator rbegin() const { return unacked_packets_.rbegin(); }
+  const_reverse_iterator rend() const { return unacked_packets_.rend(); }
   iterator begin() { return unacked_packets_.begin(); }
   iterator end() { return unacked_packets_.end(); }
 
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index cf9969f..86f2003 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -1366,12 +1366,26 @@
   MockQuicConnectionDebugVisitor();
   ~MockQuicConnectionDebugVisitor() override;
 
+  // TODO(wub): Delete when deprecating
+  // --quic_give_sent_packet_to_debug_visitor_after_sent.
   MOCK_METHOD(void,
               OnPacketSent,
               (const SerializedPacket&, TransmissionType, QuicTime),
               (override));
 
   MOCK_METHOD(void,
+              OnPacketSent,
+              (QuicPacketNumber,
+               QuicPacketLength,
+               bool,
+               TransmissionType,
+               EncryptionLevel,
+               const QuicFrames&,
+               const QuicFrames&,
+               QuicTime),
+              (override));
+
+  MOCK_METHOD(void,
               OnCoalescedPacketSent,
               (const QuicCoalescedPacket&, size_t),
               (override));