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());
};