Notify QuicTransportClientSession users when creating new streams is possible. gfe-relnote: n/a (not used in production) PiperOrigin-RevId: 288543454 Change-Id: I581abdcc7dcdb11285c47f4d1ef6f8ce34454c63
diff --git a/quic/quic_transport/quic_transport_client_session.cc b/quic/quic_transport/quic_transport_client_session.cc index d1f6e4c..6db1e4d 100644 --- a/quic/quic_transport/quic_transport_client_session.cc +++ b/quic/quic_transport/quic_transport_client_session.cc
@@ -284,4 +284,13 @@ return datagram; } +void QuicTransportClientSession::OnCanCreateNewOutgoingStream( + bool unidirectional) { + if (unidirectional) { + visitor_->OnCanCreateNewOutgoingUnidirectionalStream(); + } else { + visitor_->OnCanCreateNewOutgoingBidirectionalStream(); + } +} + } // namespace quic
diff --git a/quic/quic_transport/quic_transport_client_session.h b/quic/quic_transport/quic_transport_client_session.h index 7566964..b5f0ca0 100644 --- a/quic/quic_transport/quic_transport_client_session.h +++ b/quic/quic_transport/quic_transport_client_session.h
@@ -50,6 +50,10 @@ // Notifies the visitor when a new datagram has been received. virtual void OnIncomingDatagramAvailable() = 0; + + // Notifies the visitor that a new outgoing stream can now be created. + virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0; + virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0; }; QuicTransportClientSession(QuicConnection* connection, @@ -130,6 +134,8 @@ // Creates the client indication stream and sends the client indication on it. void SendClientIndication(); + void OnCanCreateNewOutgoingStream(bool unidirectional) override; + std::unique_ptr<QuicCryptoClientStream> crypto_stream_; GURL url_; url::Origin origin_;
diff --git a/quic/quic_transport/quic_transport_integration_test.cc b/quic/quic_transport/quic_transport_integration_test.cc index e0a1193..f4effe2 100644 --- a/quic/quic_transport/quic_transport_integration_test.cc +++ b/quic/quic_transport/quic_transport_integration_test.cc
@@ -70,6 +70,7 @@ QuicTransportClientEndpoint(Simulator* simulator, const std::string& name, const std::string& peer_name, + const QuicConfig& config, url::Origin origin, const std::string& path) : QuicTransportEndpointBase(simulator, @@ -79,7 +80,7 @@ crypto_config_(crypto_test_utils::ProofVerifierForTesting()), session_(connection_.get(), nullptr, - DefaultQuicConfig(), + config, GetVersions(), GURL("quic-transport://test.example.com:50000" + path), &crypto_config_, @@ -102,6 +103,7 @@ QuicTransportServerEndpoint(Simulator* simulator, const std::string& name, const std::string& peer_name, + const QuicConfig& config, std::vector<url::Origin> accepted_origins) : QuicTransportEndpointBase(simulator, name, @@ -116,7 +118,7 @@ session_(connection_.get(), /*owns_connection=*/false, nullptr, - DefaultQuicConfig(), + config, GetVersions(), &crypto_config_, &compressed_certs_cache_, @@ -162,9 +164,9 @@ void CreateDefaultEndpoints(const std::string& path) { client_ = std::make_unique<QuicTransportClientEndpoint>( - &simulator_, "Client", "Server", GetTestOrigin(), path); + &simulator_, "Client", "Server", client_config_, GetTestOrigin(), path); server_ = std::make_unique<QuicTransportServerEndpoint>( - &simulator_, "Server", "Client", accepted_origins_); + &simulator_, "Server", "Client", server_config_, accepted_origins_); } void WireUpEndpoints() { @@ -193,6 +195,9 @@ return session->IsSessionReady() || session->error() != QUIC_NO_ERROR; } + QuicConfig client_config_ = DefaultQuicConfig(); + QuicConfig server_config_ = DefaultQuicConfig(); + Simulator simulator_; simulator::Switch switch_; std::unique_ptr<simulator::SymmetricLink> client_link_; @@ -378,6 +383,34 @@ EXPECT_LT(received, 1000u); } +TEST_F(QuicTransportIntegrationTest, OutgoingStreamFlowControlBlocked) { + server_config_.SetMaxUnidirectionalStreamsToSend(4); + CreateDefaultEndpoints("/discard"); + WireUpEndpoints(); + RunHandshake(); + + QuicTransportStream* stream; + // Note that since we've already used one stream for client indication, we can + // only send three streams at once. + for (int i = 0; i < 3; i++) { + ASSERT_TRUE(client_->session()->CanOpenNextOutgoingUnidirectionalStream()); + stream = client_->session()->OpenOutgoingUnidirectionalStream(); + ASSERT_TRUE(stream != nullptr); + ASSERT_TRUE(stream->SendFin()); + } + EXPECT_FALSE(client_->session()->CanOpenNextOutgoingUnidirectionalStream()); + + // Receiving FINs for the streams we've just opened will cause the server to + // let us open more streams. + bool can_create_new_stream = false; + EXPECT_CALL(*client_->visitor(), OnCanCreateNewOutgoingUnidirectionalStream()) + .WillOnce(Assign(&can_create_new_stream, true)); + ASSERT_TRUE(simulator_.RunUntilOrTimeout( + [&can_create_new_stream]() { return can_create_new_stream; }, + kDefaultTimeout)); + EXPECT_TRUE(client_->session()->CanOpenNextOutgoingUnidirectionalStream()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_transport_test_tools.h b/quic/test_tools/quic_transport_test_tools.h index 3d521ef..b15e699 100644 --- a/quic/test_tools/quic_transport_test_tools.h +++ b/quic/test_tools/quic_transport_test_tools.h
@@ -18,6 +18,8 @@ MOCK_METHOD0(OnIncomingBidirectionalStreamAvailable, void()); MOCK_METHOD0(OnIncomingUnidirectionalStreamAvailable, void()); MOCK_METHOD0(OnIncomingDatagramAvailable, void()); + MOCK_METHOD0(OnCanCreateNewOutgoingBidirectionalStream, void()); + MOCK_METHOD0(OnCanCreateNewOutgoingUnidirectionalStream, void()); }; class MockServerVisitor : public QuicTransportServerSession::ServerVisitor {