Add a callback that notifies the QuicTransportClientSession visitor when the session is ready. Also add a bit of extra defense in depth for ALPN checks. gfe-relnote: n/a (not used in production) PiperOrigin-RevId: 284658419 Change-Id: Ic665263a024821e529c564e7c8b86d362f9991a8
diff --git a/quic/quic_transport/quic_transport_client_session.cc b/quic/quic_transport/quic_transport_client_session.cc index e9487ec..f316813 100644 --- a/quic/quic_transport/quic_transport_client_session.cc +++ b/quic/quic_transport/quic_transport_client_session.cc
@@ -67,6 +67,19 @@ proof_handler); } +void QuicTransportClientSession::OnAlpnSelected(QuicStringPiece alpn) { + // Defense in-depth: ensure the ALPN selected is the desired one. + if (alpn != QuicTransportAlpn()) { + QUIC_BUG << "QuicTransport negotiated non-QuicTransport ALPN: " << alpn; + connection()->CloseConnection( + QUIC_INTERNAL_ERROR, "QuicTransport negotiated non-QuicTransport ALPN", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return; + } + + alpn_received_ = true; +} + QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) { QUIC_DVLOG(1) << "Creating incoming QuicTransport stream " << id; QuicTransportStream* stream = CreateStream(id); @@ -222,12 +235,24 @@ /*fin=*/true, nullptr); client_indication_sent_ = true; + // Defense in depth: never set the ready bit unless ALPN has been confirmed. + if (!alpn_received_) { + QUIC_BUG << "ALPN confirmation missing after handshake complete"; + connection()->CloseConnection( + QUIC_INTERNAL_ERROR, + "ALPN confirmation missing after handshake complete", + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + return; + } + // Don't set the ready bit if we closed the connection due to any error // beforehand. if (!connection()->connected()) { return; } + ready_ = true; + visitor_->OnSessionReady(); } } // namespace quic
diff --git a/quic/quic_transport/quic_transport_client_session.h b/quic/quic_transport/quic_transport_client_session.h index b3d8f17..c09b076 100644 --- a/quic/quic_transport/quic_transport_client_session.h +++ b/quic/quic_transport/quic_transport_client_session.h
@@ -37,6 +37,10 @@ public: virtual ~ClientVisitor() {} + // Notifies the visitor when the client indication has been sent and the + // connection is ready to exchange application data. + virtual void OnSessionReady() = 0; + // Notifies the visitor when a new stream has been received. The stream in // question can be retrieved using AcceptIncomingBidirectionalStream() or // AcceptIncomingUnidirectionalStream(). @@ -56,6 +60,8 @@ std::vector<std::string> GetAlpnsToOffer() const override { return std::vector<std::string>({QuicTransportAlpn()}); } + void OnAlpnSelected(QuicStringPiece alpn) override; + bool alpn_received() const { return alpn_received_; } void CryptoConnect() { crypto_stream_->CryptoConnect(); } @@ -121,6 +127,7 @@ url::Origin origin_; ClientVisitor* visitor_; // not owned bool client_indication_sent_ = false; + bool alpn_received_ = false; bool ready_ = false; // Contains all of the streams that has been received by the session but have
diff --git a/quic/quic_transport/quic_transport_client_session_test.cc b/quic/quic_transport/quic_transport_client_session_test.cc index 51a0eb8..1225352 100644 --- a/quic/quic_transport/quic_transport_client_session_test.cc +++ b/quic/quic_transport/quic_transport_client_session_test.cc
@@ -103,6 +103,7 @@ "\0\x01" // length "/"; // value + EXPECT_CALL(visitor_, OnSessionReady()); Connect(); EXPECT_TRUE(session_->IsSessionReady());
diff --git a/quic/quic_transport/quic_transport_integration_test.cc b/quic/quic_transport/quic_transport_integration_test.cc index 1695a19..f5c804d 100644 --- a/quic/quic_transport/quic_transport_integration_test.cc +++ b/quic/quic_transport/quic_transport_integration_test.cc
@@ -205,6 +205,7 @@ TEST_F(QuicTransportIntegrationTest, SuccessfulHandshake) { CreateDefaultEndpoints("/discard"); WireUpEndpoints(); + EXPECT_CALL(*client_->visitor(), OnSessionReady()); RunHandshake(); EXPECT_TRUE(client_->session()->IsSessionReady()); EXPECT_TRUE(server_->session()->IsSessionReady());
diff --git a/quic/test_tools/quic_transport_test_tools.h b/quic/test_tools/quic_transport_test_tools.h index 9632d4c..9c5cef4 100644 --- a/quic/test_tools/quic_transport_test_tools.h +++ b/quic/test_tools/quic_transport_test_tools.h
@@ -14,6 +14,7 @@ class MockClientVisitor : public QuicTransportClientSession::ClientVisitor { public: + MOCK_METHOD0(OnSessionReady, void()); MOCK_METHOD0(OnIncomingBidirectionalStreamAvailable, void()); MOCK_METHOD0(OnIncomingUnidirectionalStreamAvailable, void()); };