Internal change

PiperOrigin-RevId: 471251804
diff --git a/quiche/quic/core/quic_connection_context.cc b/quiche/quic/core/quic_connection_context.cc
index d8dfbac..01381ed 100644
--- a/quiche/quic/core/quic_connection_context.cc
+++ b/quiche/quic/core/quic_connection_context.cc
@@ -5,12 +5,24 @@
 #include "quiche/quic/core/quic_connection_context.h"
 
 #include "quiche/common/platform/api/quiche_thread_local.h"
+#include "quiche/common/quiche_text_utils.h"
 
 namespace quic {
 namespace {
 DEFINE_QUICHE_THREAD_LOCAL_POINTER(CurrentContext, QuicConnectionContext);
 }  // namespace
 
+std::string QuicConnectionProcessPacketContext::DebugString() const {
+  if (decrypted_payload.empty()) {
+    return "Not processing packet";
+  }
+
+  return absl::StrCat("current_frame_offset: ", current_frame_offset,
+                      ", payload size: ", decrypted_payload.size(),
+                      ", payload hexdump: ",
+                      quiche::QuicheTextUtils::HexDump(decrypted_payload));
+}
+
 // static
 QuicConnectionContext* QuicConnectionContext::Current() {
   return GET_QUICHE_THREAD_LOCAL_POINTER(CurrentContext);
diff --git a/quiche/quic/core/quic_connection_context.h b/quiche/quic/core/quic_connection_context.h
index 192002e..72d6b66 100644
--- a/quiche/quic/core/quic_connection_context.h
+++ b/quiche/quic/core/quic_connection_context.h
@@ -61,6 +61,23 @@
                          absl::string_view bug_message) = 0;
 };
 
+// QuicConnectionProcessPacketContext is a member of QuicConnectionContext that
+// contains information of the packet currently being processed by the owning
+// QuicConnection.
+struct QUIC_EXPORT_PRIVATE QuicConnectionProcessPacketContext final {
+  // If !empty(), the decrypted payload of the packet currently being processed.
+  absl::string_view decrypted_payload;
+
+  // The offset within |decrypted_payload|, if it's non-empty, that marks the
+  // start of the frame currently being processed.
+  // Should not be used when |decrypted_payload| is empty.
+  size_t current_frame_offset = 0;
+
+  // NOTE: This can be very expansive. If used in logs, make sure it is rate
+  // limited via QUIC_BUG etc.
+  std::string DebugString() const;
+};
+
 // QuicConnectionContext is a per-QuicConnection context that includes
 // facilities useable by any part of a QuicConnection. A QuicConnectionContext
 // is owned by a QuicConnection.
@@ -78,6 +95,9 @@
 
   std::unique_ptr<QuicConnectionTracer> tracer;
   std::unique_ptr<QuicBugListener> bug_listener;
+
+  // Information about the packet currently being processed.
+  QuicConnectionProcessPacketContext process_packet_context;
 };
 
 // QuicConnectionContextSwitcher is a RAII object used for maintaining the
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index c67c44e..284dd25 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -23,6 +23,8 @@
 QUIC_FLAG(quic_restart_flag_quic_disable_legacy_version_encapsulation, true)
 // If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.
 QUIC_FLAG(quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
+// If true, QuicConnectionContext will track the decrypted payload and the offset of the current frame, for debugging.
+QUIC_FLAG(quic_reloadable_flag_quic_add_process_packet_context, true)
 // If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.
 QUIC_FLAG(quic_restart_flag_quic_support_release_time_for_gso, false)
 // If true, QuicSpdyStream::OnDataAvailable will check if connection is still connected after HttpDecoder::ProcessInput.
diff --git a/quiche/quic/core/quic_framer.cc b/quiche/quic/core/quic_framer.cc
index 1630a2c..99d9daa 100644
--- a/quiche/quic/core/quic_framer.cc
+++ b/quiche/quic/core/quic_framer.cc
@@ -14,6 +14,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
+#include "absl/cleanup/cleanup.h"
 #include "absl/strings/escaping.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
@@ -30,6 +31,7 @@
 #include "quiche/quic/core/crypto/quic_encrypter.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
+#include "quiche/quic/core/quic_connection_context.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/core/quic_constants.h"
 #include "quiche/quic/core/quic_data_reader.h"
@@ -1894,6 +1896,23 @@
   }
   QuicDataReader reader(decrypted_buffer, decrypted_length);
 
+  // Remember decrypted_payload in the current connection context until the end
+  // of this function.
+  auto* connection_context =
+      add_process_packet_context_ ? QuicConnectionContext::Current() : nullptr;
+  if (connection_context != nullptr) {
+    connection_context->process_packet_context.decrypted_payload =
+        reader.FullPayload();
+    connection_context->process_packet_context.current_frame_offset = 0;
+  }
+  auto clear_decrypted_payload = absl::MakeCleanup([&]() {
+    if (connection_context != nullptr) {
+      QUIC_RELOADABLE_FLAG_COUNT(quic_add_process_packet_context);
+      connection_context->process_packet_context.decrypted_payload =
+          absl::string_view();
+    }
+  });
+
   // Update the largest packet number after we have decrypted the packet
   // so we are confident is not attacker controlled.
   if (supports_multiple_packet_number_spaces_) {
@@ -3159,7 +3178,14 @@
   }
 
   QUIC_DVLOG(2) << ENDPOINT << "Processing IETF packet with header " << header;
+  auto* connection_context =
+      add_process_packet_context_ ? QuicConnectionContext::Current() : nullptr;
   while (!reader->IsDoneReading()) {
+    if (connection_context != nullptr) {
+      connection_context->process_packet_context.current_frame_offset =
+          connection_context->process_packet_context.decrypted_payload.size() -
+          reader->BytesRemaining();
+    }
     uint64_t frame_type;
     // Will be the number of bytes into which frame_type was encoded.
     size_t encoded_bytes = reader->BytesRemaining();
diff --git a/quiche/quic/core/quic_framer.h b/quiche/quic/core/quic_framer.h
index c39ee2b..fbf9fdb 100644
--- a/quiche/quic/core/quic_framer.h
+++ b/quiche/quic/core/quic_framer.h
@@ -1165,6 +1165,9 @@
   // Indicates whether received RETRY packets should be dropped.
   bool drop_incoming_retry_packets_ = false;
 
+  const bool add_process_packet_context_ =
+      GetQuicReloadableFlag(quic_add_process_packet_context);
+
   // The length in bytes of the last packet number written to an IETF-framed
   // packet.
   size_t last_written_packet_number_length_;