Add QuicSpdySession debug visitor to help with HTTP/3 debugging.
gfe-relnote: debugging only, not protected.
PiperOrigin-RevId: 269599486
Change-Id: Icc3a31fd46a42fa113e87b45d5fd28c78acd4fc0
diff --git a/quic/core/http/quic_receive_control_stream.cc b/quic/core/http/quic_receive_control_stream.cc
index 746efdb..d6794c7 100644
--- a/quic/core/http/quic_receive_control_stream.cc
+++ b/quic/core/http/quic_receive_control_stream.cc
@@ -214,6 +214,9 @@
QUIC_DVLOG(1) << "Control Stream " << id()
<< " received settings frame: " << settings;
QuicSpdySession* spdy_session = static_cast<QuicSpdySession*>(session());
+ if (spdy_session->debug_visitor() != nullptr) {
+ spdy_session->debug_visitor()->OnSettingsFrame(settings);
+ }
for (const auto& setting : settings.values) {
spdy_session->OnSetting(setting.first, setting.second);
}
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index 8980fc2..17c2884 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -306,6 +306,10 @@
QuicHpackDebugVisitor::~QuicHpackDebugVisitor() {}
+Http3DebugVisitor::Http3DebugVisitor() {}
+
+Http3DebugVisitor::~Http3DebugVisitor() {}
+
QuicSpdySession::QuicSpdySession(
QuicConnection* connection,
QuicSession::Visitor* visitor,
@@ -339,7 +343,8 @@
spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
spdy_framer_visitor_(new SpdyFramerVisitor(this)),
max_allowed_push_id_(0),
- destruction_indicator_(123456789) {
+ destruction_indicator_(123456789),
+ debug_visitor_(nullptr) {
h2_deframer_.set_visitor(spdy_framer_visitor_.get());
h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
@@ -913,6 +918,10 @@
ActivateStream(std::move(receive_stream));
receive_control_stream_->SetUnblocked();
QUIC_DVLOG(1) << "Receive Control stream is created";
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnPeerControlStreamCreated(
+ receive_control_stream_->id());
+ }
return true;
}
case kServerPushStream: { // Push Stream.
@@ -931,6 +940,10 @@
ActivateStream(std::move(encoder_receive));
qpack_encoder_receive_stream_->SetUnblocked();
QUIC_DVLOG(1) << "Receive QPACK Encoder stream is created";
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnPeerQpackEncoderStreamCreated(
+ qpack_encoder_receive_stream_->id());
+ }
return true;
}
case kQpackDecoderStream: { // QPACK decoder stream.
@@ -943,7 +956,11 @@
qpack_decoder_receive_stream_ = decoder_receive.get();
ActivateStream(std::move(decoder_receive));
qpack_decoder_receive_stream_->SetUnblocked();
- QUIC_DVLOG(1) << "Receive Qpack Decoder stream is created";
+ QUIC_DVLOG(1) << "Receive QPACK Decoder stream is created";
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnPeerQpackDecoderStreamCreated(
+ qpack_decoder_receive_stream_->id());
+ }
return true;
}
default:
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h
index faba099..40ad070 100644
--- a/quic/core/http/quic_spdy_session.h
+++ b/quic/core/http/quic_spdy_session.h
@@ -52,6 +52,27 @@
virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
};
+class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
+ public:
+ Http3DebugVisitor();
+ Http3DebugVisitor(const Http3DebugVisitor&) = delete;
+ Http3DebugVisitor& operator=(const Http3DebugVisitor&) = delete;
+
+ virtual ~Http3DebugVisitor();
+
+ // Called when peer's control stream type is received.
+ virtual void OnPeerControlStreamCreated(QuicStreamId /*stream_id*/) = 0;
+
+ // Called when peer's QPACK encoder stream type is received.
+ virtual void OnPeerQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
+
+ // Called when peer's QPACK decoder stream type is received.
+ virtual void OnPeerQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
+
+ // Called when SETTINGS frame is received.
+ virtual void OnSettingsFrame(const SettingsFrame& /*frame*/) = 0;
+};
+
// A QUIC session for HTTP.
class QUIC_EXPORT_PRIVATE QuicSpdySession
: public QuicSession,
@@ -209,6 +230,12 @@
int32_t destruction_indicator() const { return destruction_indicator_; }
+ void set_debug_visitor(Http3DebugVisitor* debug_visitor) {
+ debug_visitor_ = debug_visitor;
+ }
+
+ Http3DebugVisitor* debug_visitor() { return debug_visitor_; }
+
protected:
// Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
// CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
@@ -363,6 +390,9 @@
// constructor. As long as it is not the assigned value, that would indicate
// an use-after-free.
int32_t destruction_indicator_;
+
+ // Not owned by the session.
+ Http3DebugVisitor* debug_visitor_;
};
} // namespace quic
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 9311af5..310081c 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -127,6 +127,17 @@
MOCK_METHOD0(OnCanWrite, void());
};
+class MockHttp3DebugVisitor : public Http3DebugVisitor {
+ public:
+ MOCK_METHOD1(OnPeerControlStreamCreated, void(QuicStreamId));
+
+ MOCK_METHOD1(OnPeerQpackEncoderStreamCreated, void(QuicStreamId));
+
+ MOCK_METHOD1(OnPeerQpackDecoderStreamCreated, void(QuicStreamId));
+
+ MOCK_METHOD1(OnSettingsFrame, void(const SettingsFrame&));
+};
+
class TestStream : public QuicSpdyStream {
public:
TestStream(QuicStreamId id, QuicSpdySession* session, StreamType type)
@@ -2177,16 +2188,19 @@
if (!VersionHasStreamType(transport_version())) {
return;
}
+ MockHttp3DebugVisitor debug_visitor;
// Use an arbitrary stream id.
QuicStreamId stream_id =
GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3);
char type[] = {kControlStream};
QuicStreamFrame data1(stream_id, false, 0, QuicStringPiece(type, 1));
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id)).Times(0);
session_.OnStreamFrame(data1);
EXPECT_EQ(stream_id,
QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id());
+ session_.set_debug_visitor(&debug_visitor);
SettingsFrame settings;
settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 512;
settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5;
@@ -2203,6 +2217,7 @@
EXPECT_NE(5u, session_.max_outbound_header_list_size());
EXPECT_NE(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder));
+ EXPECT_CALL(debug_visitor, OnSettingsFrame(settings));
session_.OnStreamFrame(frame);
EXPECT_EQ(512u,
@@ -2379,15 +2394,21 @@
if (!VersionHasStreamType(transport_version())) {
return;
}
+
+ MockHttp3DebugVisitor debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
QuicStreamId id1 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
char type1[] = {kControlStream};
QuicStreamFrame data1(id1, false, 0, QuicStringPiece(type1, 1));
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id1));
session_.OnStreamFrame(data1);
QuicStreamId id2 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
QuicStreamFrame data2(id2, false, 0, QuicStringPiece(type1, 1));
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(id2)).Times(0);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Control stream is received twice.", _));
@@ -2400,11 +2421,13 @@
char type2[]{kQpackEncoderStream};
QuicStreamFrame data3(id3, false, 0, QuicStringPiece(type2, 1));
+ EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id3));
session_.OnStreamFrame(data3);
QuicStreamId id4 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
QuicStreamFrame data4(id4, false, 0, QuicStringPiece(type2, 1));
+ EXPECT_CALL(debug_visitor, OnPeerQpackEncoderStreamCreated(id4)).Times(0);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"QPACK encoder stream is received twice.", _));
@@ -2417,11 +2440,13 @@
char type3[]{kQpackDecoderStream};
QuicStreamFrame data5(id5, false, 0, QuicStringPiece(type3, 1));
+ EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id5));
session_.OnStreamFrame(data5);
QuicStreamId id6 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 5);
QuicStreamFrame data6(id6, false, 0, QuicStringPiece(type3, 1));
+ EXPECT_CALL(debug_visitor, OnPeerQpackDecoderStreamCreated(id6)).Times(0);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"QPACK decoder stream is received twice.", _));