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.", _));