diff --git a/source/common/quic/envoy_quic_client_connection.cc b/source/common/quic/envoy_quic_client_connection.cc index 411cfcece015..4527f3cc1cd0 100644 --- a/source/common/quic/envoy_quic_client_connection.cc +++ b/source/common/quic/envoy_quic_client_connection.cc @@ -9,6 +9,9 @@ #include "source/common/quic/envoy_quic_utils.h" #include "source/common/runtime/runtime_features.h" +ABSL_FLAG(bool, envoy_reloadable_features_quic_client_3ms_poll, false, ""); +ABSL_FLAG(bool, envoy_reloadable_features_quic_client_5ms_poll, false, ""); + namespace Envoy { namespace Quic { @@ -131,6 +134,24 @@ void EnvoyQuicClientConnection::setUpConnectionSocket(Network::ConnectionSocket& if (!connection_socket.isOpen()) { CloseConnection(quic::QUIC_CONNECTION_CANCELLED, "Fail to set up connection socket.", quic::ConnectionCloseBehavior::SILENT_CLOSE); + } else { + int poll_time = 0; + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.quic_client_3ms_poll")) { + poll_time = 3; + } else if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.quic_client_5ms_poll")) { + poll_time = 5; + } + if (poll_time) { + if (!poll_timer_) { + poll_timer_ = dispatcher_.createTimer([this, poll_time]() { + if (connected() && connectionSocket()) { + connectionSocket()->ioHandle().activateFileEvents(Event::FileReadyType::Read); + poll_timer_->enableTimer(std::chrono::milliseconds(poll_time)); + } + }); + } + poll_timer_->enableTimer(std::chrono::milliseconds(poll_time)); + } } } diff --git a/source/common/quic/envoy_quic_client_connection.h b/source/common/quic/envoy_quic_client_connection.h index 8530386f6483..31dec116e186 100644 --- a/source/common/quic/envoy_quic_client_connection.h +++ b/source/common/quic/envoy_quic_client_connection.h @@ -144,6 +144,7 @@ class EnvoyQuicClientConnection : public quic::QuicConnection, void probeWithNewPort(const quic::QuicSocketAddress& peer_address, quic::PathValidationReason reason); + Event::TimerPtr poll_timer_; OptRef delegate_; uint32_t packets_dropped_{0}; Event::Dispatcher& dispatcher_; diff --git a/test/integration/protocol_integration_test.cc b/test/integration/protocol_integration_test.cc index 261ddd3c430e..c85231d1960b 100644 --- a/test/integration/protocol_integration_test.cc +++ b/test/integration/protocol_integration_test.cc @@ -1463,6 +1463,36 @@ TEST_P(DownstreamProtocolIntegrationTest, HittingDecoderFilterLimitNoEndStream) } } +TEST_P(ProtocolIntegrationTest, TestLargeResposneBody) { + config_helper_.addRuntimeOverride("envoy.reloadable_features.quic_client_3ms_poll", "true"); + initialize(); + + codec_client_ = makeHttpConnection(lookupPort("http")); + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + + waitForNextUpstreamRequest(); + upstream_request_->encodeHeaders(default_response_headers_, false); + upstream_request_->encodeData(1024 * 200, true); + + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_TRUE(response->complete()); +} + +TEST_P(ProtocolIntegrationTest, TestLargeResposneBodyFive) { + config_helper_.addRuntimeOverride("envoy.reloadable_features.quic_client_5ms_poll", "true"); + initialize(); + + codec_client_ = makeHttpConnection(lookupPort("http")); + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + + waitForNextUpstreamRequest(); + upstream_request_->encodeHeaders(default_response_headers_, false); + upstream_request_->encodeData(1024 * 200, true); + + ASSERT_TRUE(response->waitForEndStream()); + EXPECT_TRUE(response->complete()); +} + // Test hitting the encoder buffer filter with too many response bytes to buffer. Given the request // headers are sent on early, the stream/connection will be reset. TEST_P(ProtocolIntegrationTest, HittingEncoderFilterLimit) {