Commit dd708979 authored by Renjie Tang's avatar Renjie Tang Committed by Commit Bot

When QUIC is recently marked broken, the main job should not wait for the alt job to return.

Bug: 1005646
Change-Id: I3cf1a7210a0038b438d38cb375f813f4e8edf891
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1834026Reviewed-by: default avatarZhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Renjie Tang <renjietang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702578}
parent aef4c741
......@@ -872,6 +872,130 @@ TEST_F(HttpStreamFactoryJobControllerTest,
EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
}
TEST_F(HttpStreamFactoryJobControllerTest,
DoNotDelayMainJobIfQuicWasRecentlyBroken) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START);
quic_data_ = std::make_unique<MockQuicData>(
HttpNetworkSession::Params().quic_params.supported_versions.front());
quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
tcp_data_ = std::make_unique<SequencedSocketData>();
tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
HttpRequestInfo request_info;
request_info.method = "GET";
request_info.url = GURL("https://www.google.com");
Initialize(request_info);
url::SchemeHostPort server(request_info.url);
AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session_->http_server_properties()->SetQuicAlternativeService(
server, NetworkIsolationKey(), alternative_service, expiration,
session_->params().quic_params.supported_versions);
// Enable QUIC but mark the alternative service as recently broken.
QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
quic_stream_factory->set_is_quic_known_to_work_on_current_network(true);
session_->http_server_properties()->MarkAlternativeServiceRecentlyBroken(
alternative_service, NetworkIsolationKey());
request_ =
job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
EXPECT_TRUE(job_controller_->main_job());
EXPECT_TRUE(job_controller_->alternative_job());
// The main job shouldn't have any delay since QUIC was recently broken.
EXPECT_FALSE(job_controller_->ShouldWait(
const_cast<net::HttpStreamFactory::Job*>(job_controller_->main_job())));
// Make |alternative_job| succeed.
auto http_stream = std::make_unique<HttpBasicStream>(
std::make_unique<ClientSocketHandle>(), false);
EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, http_stream.get()));
HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
std::move(http_stream));
job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig());
base::RunLoop().RunUntilIdle();
// Check that alternative job is bound while main job is destroyed.
EXPECT_FALSE(job_controller_->main_job());
EXPECT_TRUE(job_controller_->alternative_job());
request_.reset();
VerifyBrokenAlternateProtocolMapping(request_info, false);
EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
}
TEST_F(HttpStreamFactoryJobControllerTest,
DelayMainJobAfterRecentlyBrokenQuicWasConfirmed) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START);
quic_data_ = std::make_unique<MockQuicData>(
HttpNetworkSession::Params().quic_params.supported_versions.front());
quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
tcp_data_ = std::make_unique<SequencedSocketData>();
tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
HttpRequestInfo request_info;
request_info.method = "GET";
request_info.url = GURL("https://www.google.com");
Initialize(request_info);
url::SchemeHostPort server(request_info.url);
AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
session_->http_server_properties()->SetQuicAlternativeService(
server, NetworkIsolationKey(), alternative_service, expiration,
session_->params().quic_params.supported_versions);
// Enable QUIC but mark the alternative service as recently broken.
QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
quic_stream_factory->set_is_quic_known_to_work_on_current_network(true);
session_->http_server_properties()->MarkAlternativeServiceRecentlyBroken(
alternative_service, NetworkIsolationKey());
// Confirm the alt service.
session_->http_server_properties()->ConfirmAlternativeService(
alternative_service, NetworkIsolationKey());
request_ =
job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
EXPECT_TRUE(job_controller_->main_job());
EXPECT_TRUE(job_controller_->alternative_job());
// The main job should wait but it should be unblocked because QUIC job
// doesn't return immediately.
EXPECT_TRUE(job_controller_->ShouldWait(
const_cast<net::HttpStreamFactory::Job*>(job_controller_->main_job())));
EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
// Make |alternative_job| succeed.
auto http_stream = std::make_unique<HttpBasicStream>(
std::make_unique<ClientSocketHandle>(), false);
EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, http_stream.get()));
HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
std::move(http_stream));
job_controller_->OnStreamReady(job_factory_.alternative_job(), SSLConfig());
base::RunLoop().RunUntilIdle();
// Check that alternative job is bound while main job is destroyed.
EXPECT_FALSE(job_controller_->main_job());
EXPECT_TRUE(job_controller_->alternative_job());
request_.reset();
VerifyBrokenAlternateProtocolMapping(request_info, false);
EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
}
void HttpStreamFactoryJobControllerTest::TestOnStreamFailedForBothJobs(
bool alt_job_retried_on_non_default_network) {
quic_data_ = std::make_unique<MockQuicData>(
......
......@@ -1131,8 +1131,7 @@ void QuicStreamRequest::OnConnectionFailedOnDefaultNetwork() {
base::TimeDelta QuicStreamRequest::GetTimeDelayForWaitingJob() const {
if (!factory_)
return base::TimeDelta();
return factory_->GetTimeDelayForWaitingJob(
session_key_.server_id(), session_key_.network_isolation_key());
return factory_->GetTimeDelayForWaitingJob(session_key_);
}
void QuicStreamRequest::SetPriority(RequestPriority priority) {
......@@ -1711,8 +1710,7 @@ void QuicStreamFactory::set_is_quic_known_to_work_on_current_network(
}
base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob(
const quic::QuicServerId& server_id,
const NetworkIsolationKey& network_isolation_key) {
const QuicSessionKey& session_key) {
// If |is_quic_known_to_work_on_current_network_| is false, then one of the
// following is true:
// 1) This is startup and QuicStreamFactory::CreateSession() and
......@@ -1731,8 +1729,14 @@ base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob(
}
}
int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(
server_id, network_isolation_key);
// QUIC was recently broken. Do not delay the main job.
if (WasQuicRecentlyBroken(session_key)) {
return base::TimeDelta();
}
int64_t srtt =
1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(
session_key.server_id(), session_key.network_isolation_key());
// Picked 300ms based on mean time from
// Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram.
const int kDefaultRTT = 300 * quic::kNumMicrosPerMilli;
......
......@@ -477,9 +477,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
bool is_quic_known_to_work_on_current_network);
// It returns the amount of time waiting job should be delayed.
base::TimeDelta GetTimeDelayForWaitingJob(
const quic::QuicServerId& server_id,
const NetworkIsolationKey& network_isolation_key);
base::TimeDelta GetTimeDelayForWaitingJob(const QuicSessionKey& session_key);
QuicChromiumConnectionHelper* helper() { return helper_.get(); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment