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_;