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 {