Commit a6b68d11 authored by Zhongyi Shi's avatar Zhongyi Shi Committed by Commit Bot

Change the HttpStreamFactory::JobController to mark alternative service broken...

Change the HttpStreamFactory::JobController to mark alternative service broken until default network changes.

Change the HttpStreamFactory::JobController to mark alternative service broken until default network changes iff TCP succeeds, QUIC fails on the defaut network but succeeds on the alternate network. The HttpServerProperties will clear the brokenness until default network changes.

Bug: 790547
Change-Id: Ib33def42b474898879bf9e39567632ed273c5ca2
Reviewed-on: https://chromium-review.googlesource.com/1212142
Commit-Queue: Zhongyi Shi <zhongyi@chromium.org>
Reviewed-by: default avatarRyan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593486}
parent 36a634af
...@@ -649,6 +649,7 @@ int HttpProxyClientSocketWrapper::DoQuicProxyCreateSession() { ...@@ -649,6 +649,7 @@ int HttpProxyClientSocketWrapper::DoQuicProxyCreateSession() {
initial_socket_tag_, ssl_params_->ssl_config().GetCertVerifyFlags(), initial_socket_tag_, ssl_params_->ssl_config().GetCertVerifyFlags(),
GURL("https://" + proxy_server.ToString()), net_log_, GURL("https://" + proxy_server.ToString()), net_log_,
&quic_net_error_details_, &quic_net_error_details_,
/*failed_on_default_network_callback=*/CompletionOnceCallback(),
base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete, base::Bind(&HttpProxyClientSocketWrapper::OnIOComplete,
base::Unretained(this))); base::Unretained(this)));
} }
......
...@@ -901,7 +901,10 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { ...@@ -901,7 +901,10 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() {
int rv = quic_request_.Request( int rv = quic_request_.Request(
destination, quic_version_, request_info_.privacy_mode, priority_, destination, quic_version_, request_info_.privacy_mode, priority_,
request_info_.socket_tag, ssl_config->GetCertVerifyFlags(), url, request_info_.socket_tag, ssl_config->GetCertVerifyFlags(), url,
net_log_, &net_error_details_, io_callback_); net_log_, &net_error_details_,
base::BindOnce(&Job::OnFailedOnDefaultNetwork,
ptr_factory_.GetWeakPtr()),
io_callback_);
if (rv == OK) { if (rv == OK) {
using_existing_quic_session_ = true; using_existing_quic_session_ = true;
} else if (rv == ERR_IO_PENDING) { } else if (rv == ERR_IO_PENDING) {
...@@ -999,6 +1002,12 @@ void HttpStreamFactory::Job::OnQuicHostResolution(int result) { ...@@ -999,6 +1002,12 @@ void HttpStreamFactory::Job::OnQuicHostResolution(int result) {
delegate_->OnConnectionInitialized(this, result); delegate_->OnConnectionInitialized(this, result);
} }
void HttpStreamFactory::Job::OnFailedOnDefaultNetwork(int result) {
DCHECK_EQ(job_type_, ALTERNATIVE);
DCHECK(using_quic_);
delegate_->OnFailedOnDefaultNetwork(this);
}
int HttpStreamFactory::Job::DoInitConnectionComplete(int result) { int HttpStreamFactory::Job::DoInitConnectionComplete(int result) {
net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_INIT_CONNECTION); net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_INIT_CONNECTION);
if (job_type_ == PRECONNECT) { if (job_type_ == PRECONNECT) {
......
...@@ -83,6 +83,9 @@ class HttpStreamFactory::Job { ...@@ -83,6 +83,9 @@ class HttpStreamFactory::Job {
int status, int status,
const SSLConfig& used_ssl_config) = 0; const SSLConfig& used_ssl_config) = 0;
// Invoked when |job| fails on the default network.
virtual void OnFailedOnDefaultNetwork(Job* job) = 0;
// Invoked when |job| has a certificate error for the HttpStreamRequest. // Invoked when |job| has a certificate error for the HttpStreamRequest.
virtual void OnCertificateError(Job* job, virtual void OnCertificateError(Job* job,
int status, int status,
...@@ -316,6 +319,9 @@ class HttpStreamFactory::Job { ...@@ -316,6 +319,9 @@ class HttpStreamFactory::Job {
// resolution, not the result of host resolution itself. // resolution, not the result of host resolution itself.
void OnQuicHostResolution(int result); void OnQuicHostResolution(int result);
// Invoked when the underlying connection fails on the default network.
void OnFailedOnDefaultNetwork(int result);
// Each of these methods corresponds to a State value. Those with an input // Each of these methods corresponds to a State value. Those with an input
// argument receive the result from the previous state. If a method returns // argument receive the result from the previous state. If a method returns
// ERR_IO_PENDING, then the result from OnIOComplete will be passed to the // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the
......
...@@ -78,7 +78,9 @@ HttpStreamFactory::JobController::JobController( ...@@ -78,7 +78,9 @@ HttpStreamFactory::JobController::JobController(
is_websocket_(is_websocket), is_websocket_(is_websocket),
enable_ip_based_pooling_(enable_ip_based_pooling), enable_ip_based_pooling_(enable_ip_based_pooling),
enable_alternative_services_(enable_alternative_services), enable_alternative_services_(enable_alternative_services),
main_job_net_error_(OK),
alternative_job_net_error_(OK), alternative_job_net_error_(OK),
alternative_job_failed_on_default_network_(false),
job_bound_(false), job_bound_(false),
main_job_is_blocked_(false), main_job_is_blocked_(false),
main_job_is_resumed_(false), main_job_is_resumed_(false),
...@@ -209,6 +211,7 @@ void HttpStreamFactory::JobController::OnStreamReadyOnPooledConnection( ...@@ -209,6 +211,7 @@ void HttpStreamFactory::JobController::OnStreamReadyOnPooledConnection(
main_job_.reset(); main_job_.reset();
alternative_job_.reset(); alternative_job_.reset();
ResetErrorStatusForJobs();
factory_->OnStreamReady(proxy_info, request_info_.privacy_mode); factory_->OnStreamReady(proxy_info, request_info_.privacy_mode);
...@@ -226,6 +229,7 @@ void HttpStreamFactory::JobController:: ...@@ -226,6 +229,7 @@ void HttpStreamFactory::JobController::
main_job_.reset(); main_job_.reset();
alternative_job_.reset(); alternative_job_.reset();
ResetErrorStatusForJobs();
delegate_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info, delegate_->OnBidirectionalStreamImplReady(used_ssl_config, used_proxy_info,
std::move(stream)); std::move(stream));
...@@ -322,6 +326,9 @@ void HttpStreamFactory::JobController::OnStreamFailed( ...@@ -322,6 +326,9 @@ void HttpStreamFactory::JobController::OnStreamFailed(
} else { } else {
OnAlternativeServiceJobFailed(status); OnAlternativeServiceJobFailed(status);
} }
} else {
DCHECK_EQ(main_job_.get(), job);
main_job_net_error_ = status;
} }
MaybeResumeMainJob(job, base::TimeDelta()); MaybeResumeMainJob(job, base::TimeDelta());
...@@ -365,6 +372,11 @@ void HttpStreamFactory::JobController::OnStreamFailed( ...@@ -365,6 +372,11 @@ void HttpStreamFactory::JobController::OnStreamFailed(
delegate_->OnStreamFailed(status, *job->net_error_details(), used_ssl_config); delegate_->OnStreamFailed(status, *job->net_error_details(), used_ssl_config);
} }
void HttpStreamFactory::JobController::OnFailedOnDefaultNetwork(Job* job) {
DCHECK_EQ(job->job_type(), ALTERNATIVE);
alternative_job_failed_on_default_network_ = true;
}
void HttpStreamFactory::JobController::OnCertificateError( void HttpStreamFactory::JobController::OnCertificateError(
Job* job, Job* job,
int status, int status,
...@@ -482,8 +494,6 @@ void HttpStreamFactory::JobController::OnNewSpdySessionReady( ...@@ -482,8 +494,6 @@ void HttpStreamFactory::JobController::OnNewSpdySessionReady(
// Notify |request_|. // Notify |request_|.
if (!is_preconnect_ && !is_job_orphaned) { if (!is_preconnect_ && !is_job_orphaned) {
if (job->job_type() == MAIN && alternative_job_net_error_ != OK)
ReportBrokenAlternativeService();
DCHECK(request_); DCHECK(request_);
...@@ -528,6 +538,7 @@ void HttpStreamFactory::JobController::OnNewSpdySessionReady( ...@@ -528,6 +538,7 @@ void HttpStreamFactory::JobController::OnNewSpdySessionReady(
void HttpStreamFactory::JobController::OnPreconnectsComplete(Job* job) { void HttpStreamFactory::JobController::OnPreconnectsComplete(Job* job) {
DCHECK_EQ(main_job_.get(), job); DCHECK_EQ(main_job_.get(), job);
main_job_.reset(); main_job_.reset();
ResetErrorStatusForJobs();
factory_->OnPreconnectsCompleteInternal(); factory_->OnPreconnectsCompleteInternal();
MaybeNotifyFactoryOfCompletion(); MaybeNotifyFactoryOfCompletion();
} }
...@@ -579,6 +590,12 @@ void HttpStreamFactory::JobController::ResumeMainJob() { ...@@ -579,6 +590,12 @@ void HttpStreamFactory::JobController::ResumeMainJob() {
main_job_wait_time_ = base::TimeDelta(); main_job_wait_time_ = base::TimeDelta();
} }
void HttpStreamFactory::JobController::ResetErrorStatusForJobs() {
main_job_net_error_ = OK;
alternative_job_net_error_ = OK;
alternative_job_failed_on_default_network_ = false;
}
void HttpStreamFactory::JobController::MaybeResumeMainJob( void HttpStreamFactory::JobController::MaybeResumeMainJob(
Job* job, Job* job,
const base::TimeDelta& delay) { const base::TimeDelta& delay) {
...@@ -919,11 +936,17 @@ void HttpStreamFactory::JobController::OrphanUnboundJob() { ...@@ -919,11 +936,17 @@ void HttpStreamFactory::JobController::OrphanUnboundJob() {
return; return;
} }
if (bound_job_->job_type() == ALTERNATIVE && main_job_) { if (bound_job_->job_type() == ALTERNATIVE && main_job_ &&
// |request_| is bound to the alternative job. This means that the main job !alternative_job_failed_on_default_network_) {
// |request_| is bound to the alternative job and the alternative job
// succeeds on the default network. This means that the main job
// is no longer needed, so cancel it now. Pending ConnectJobs will return // is no longer needed, so cancel it now. Pending ConnectJobs will return
// established sockets to socket pools if applicable. // established sockets to socket pools if applicable.
// https://crbug.com/757548. // https://crbug.com/757548.
// The main job still needs to run if the alternative job succeeds on the
// alternate network in order to figure out whether QUIC should be marked as
// broken until the default network changes.
DCHECK_EQ(OK, alternative_job_net_error_);
main_job_.reset(); main_job_.reset();
} }
} }
...@@ -931,9 +954,6 @@ void HttpStreamFactory::JobController::OrphanUnboundJob() { ...@@ -931,9 +954,6 @@ void HttpStreamFactory::JobController::OrphanUnboundJob() {
void HttpStreamFactory::JobController::OnJobSucceeded(Job* job) { void HttpStreamFactory::JobController::OnJobSucceeded(Job* job) {
DCHECK(job); DCHECK(job);
if (job->job_type() == MAIN && alternative_job_net_error_ != OK)
ReportBrokenAlternativeService();
if (!bound_job_) { if (!bound_job_) {
if (main_job_ && alternative_job_) if (main_job_ && alternative_job_)
ReportAlternateProtocolUsage(job); ReportAlternateProtocolUsage(job);
...@@ -958,14 +978,6 @@ void HttpStreamFactory::JobController::OnAlternativeServiceJobFailed( ...@@ -958,14 +978,6 @@ void HttpStreamFactory::JobController::OnAlternativeServiceJobFailed(
DCHECK_NE(kProtoUnknown, alternative_service_info_.protocol()); DCHECK_NE(kProtoUnknown, alternative_service_info_.protocol());
alternative_job_net_error_ = net_error; alternative_job_net_error_ = net_error;
if (IsJobOrphaned(alternative_job_.get())) {
// If |request_| is gone, then it must have been successfully served by
// |main_job_|.
// If |request_| is bound to a different job, then it is being
// successfully served by the main job.
ReportBrokenAlternativeService();
}
} }
void HttpStreamFactory::JobController::OnAlternativeProxyJobFailed( void HttpStreamFactory::JobController::OnAlternativeProxyJobFailed(
...@@ -988,17 +1000,41 @@ void HttpStreamFactory::JobController::OnAlternativeProxyJobFailed( ...@@ -988,17 +1000,41 @@ void HttpStreamFactory::JobController::OnAlternativeProxyJobFailed(
} }
} }
void HttpStreamFactory::JobController::ReportBrokenAlternativeService() { void HttpStreamFactory::JobController::MaybeReportBrokenAlternativeService() {
// If alternative job succeeds on the default network, no brokenness to
// report.
if (alternative_job_net_error_ == OK &&
!alternative_job_failed_on_default_network_)
return;
// No brokenness to report if the main job fails.
if (main_job_net_error_ != OK)
return;
DCHECK(alternative_service_info_.protocol() != kProtoUnknown); DCHECK(alternative_service_info_.protocol() != kProtoUnknown);
DCHECK_NE(OK, alternative_job_net_error_);
int error_to_report = alternative_job_net_error_; if (alternative_job_failed_on_default_network_ &&
alternative_job_net_error_ = OK; alternative_job_net_error_ == OK) {
base::UmaHistogramSparse("Net.AlternateServiceFailed", -error_to_report); // Alternative job failed on the default network but succeeds on the
// non-default network, mark alternative service broken until the default
// network changes.
session_->http_server_properties()
->MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
alternative_service_info_.alternative_service());
// Reset error status for Jobs after reporting brokenness.
ResetErrorStatusForJobs();
return;
}
// Report brokenness if alternative job failed.
base::UmaHistogramSparse("Net.AlternateServiceFailed",
-alternative_job_net_error_);
if (error_to_report == ERR_NETWORK_CHANGED || if (alternative_job_net_error_ == ERR_NETWORK_CHANGED ||
error_to_report == ERR_INTERNET_DISCONNECTED) { alternative_job_net_error_ == ERR_INTERNET_DISCONNECTED) {
// No need to mark alternative service as broken. // No need to mark alternative service as broken.
// Reset error status for Jobs.
ResetErrorStatusForJobs();
return; return;
} }
...@@ -1006,9 +1042,17 @@ void HttpStreamFactory::JobController::ReportBrokenAlternativeService() { ...@@ -1006,9 +1042,17 @@ void HttpStreamFactory::JobController::ReportBrokenAlternativeService() {
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_ALT); BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_ALT);
session_->http_server_properties()->MarkAlternativeServiceBroken( session_->http_server_properties()->MarkAlternativeServiceBroken(
alternative_service_info_.alternative_service()); alternative_service_info_.alternative_service());
// Reset error status for Jobs after reporting brokenness.
ResetErrorStatusForJobs();
} }
void HttpStreamFactory::JobController::MaybeNotifyFactoryOfCompletion() { void HttpStreamFactory::JobController::MaybeNotifyFactoryOfCompletion() {
if (!main_job_ && !alternative_job_) {
// Both jobs are gone, report brokenness if apply. Error status for Jobs
// will be reset after reporting to avoid redundant reporting.
MaybeReportBrokenAlternativeService();
}
if (!request_ && !main_job_ && !alternative_job_) { if (!request_ && !main_job_ && !alternative_job_) {
DCHECK(!bound_job_); DCHECK(!bound_job_);
factory_->OnJobControllerComplete(this); factory_->OnJobControllerComplete(this);
...@@ -1306,6 +1350,7 @@ int HttpStreamFactory::JobController::ReconsiderProxyAfterError(Job* job, ...@@ -1306,6 +1350,7 @@ int HttpStreamFactory::JobController::ReconsiderProxyAfterError(Job* job,
bound_job_ = nullptr; bound_job_ = nullptr;
alternative_job_.reset(); alternative_job_.reset();
main_job_.reset(); main_job_.reset();
ResetErrorStatusForJobs();
// Also resets states that related to the old main job. In particular, // Also resets states that related to the old main job. In particular,
// cancels |resume_main_job_callback_| so there won't be any delayed // cancels |resume_main_job_callback_| so there won't be any delayed
// ResumeMainJob() left in the task queue. // ResumeMainJob() left in the task queue.
......
...@@ -111,6 +111,9 @@ class HttpStreamFactory::JobController ...@@ -111,6 +111,9 @@ class HttpStreamFactory::JobController
int status, int status,
const SSLConfig& used_ssl_config) override; const SSLConfig& used_ssl_config) override;
// Invoked when |job| fails on the default network.
void OnFailedOnDefaultNetwork(Job* job) override;
// Invoked when |job| has a certificate error for the Request. // Invoked when |job| has a certificate error for the Request.
void OnCertificateError(Job* job, void OnCertificateError(Job* job,
int status, int status,
...@@ -244,9 +247,14 @@ class HttpStreamFactory::JobController ...@@ -244,9 +247,14 @@ class HttpStreamFactory::JobController
// net error of the failed alternative proxy job. // net error of the failed alternative proxy job.
void OnAlternativeProxyJobFailed(int net_error); void OnAlternativeProxyJobFailed(int net_error);
// Called to report to http_server_properties to mark alternative service // Called when all Jobs complete. Reports alternative service brokenness to
// broken. // HttpServerProperties if apply and resets net errors afterwards:
void ReportBrokenAlternativeService(); // - report broken if the main job has no error and the alternative job has an
// error;
// - report broken until default network change if the main job has no error,
// the alternative job has no error, but the alternative job failed on the
// default network.
void MaybeReportBrokenAlternativeService();
void MaybeNotifyFactoryOfCompletion(); void MaybeNotifyFactoryOfCompletion();
...@@ -262,6 +270,11 @@ class HttpStreamFactory::JobController ...@@ -262,6 +270,11 @@ class HttpStreamFactory::JobController
// Resumes the main job immediately. // Resumes the main job immediately.
void ResumeMainJob(); void ResumeMainJob();
// Reset error status to default value for Jobs:
// - reset |main_job_net_error_| and |alternative_job_net_error_| to OK;
// - reset |alternative_job_failed_on_default_network_| to false.
void ResetErrorStatusForJobs();
AlternativeServiceInfo GetAlternativeServiceInfoFor( AlternativeServiceInfo GetAlternativeServiceInfoFor(
const HttpRequestInfo& request_info, const HttpRequestInfo& request_info,
HttpStreamRequest::Delegate* delegate, HttpStreamRequest::Delegate* delegate,
...@@ -344,8 +357,13 @@ class HttpStreamFactory::JobController ...@@ -344,8 +357,13 @@ class HttpStreamFactory::JobController
// (or by |main_job_| if |is_preconnect_|.) // (or by |main_job_| if |is_preconnect_|.)
AlternativeServiceInfo alternative_service_info_; AlternativeServiceInfo alternative_service_info_;
// Net error code of the failed alternative job. Set to OK by default. // Error status used for alternative service brokenness reporting.
// Net error code of the main job. Set to OK by default.
int main_job_net_error_;
// Net error code of the alternative job. Set to OK by default.
int alternative_job_net_error_; int alternative_job_net_error_;
// Set to true if the alternative job failed on the default network.
bool alternative_job_failed_on_default_network_;
// True if a Job has ever been bound to the |request_|. // True if a Job has ever been bound to the |request_|.
bool job_bound_; bool job_bound_;
......
...@@ -623,6 +623,10 @@ int QuicStreamFactory::Job::DoConfirmConnection(int rv) { ...@@ -623,6 +623,10 @@ int QuicStreamFactory::Job::DoConfirmConnection(int rv) {
net_log_.AddEvent( net_log_.AddEvent(
NetLogEventType:: NetLogEventType::
QUIC_STREAM_FACTORY_JOB_RETRY_ON_ALTERNATE_NETWORK); QUIC_STREAM_FACTORY_JOB_RETRY_ON_ALTERNATE_NETWORK);
// Notify requests that connection on the default network failed.
for (auto* request : stream_requests_) {
request->OnConnectionFailedOnDefaultNetwork();
}
DVLOG(1) << "Retry connection on alternate network"; DVLOG(1) << "Retry connection on alternate network";
session_ = nullptr; session_ = nullptr;
io_state_ = STATE_CONNECT; io_state_ = STATE_CONNECT;
...@@ -661,16 +665,18 @@ QuicStreamRequest::~QuicStreamRequest() { ...@@ -661,16 +665,18 @@ QuicStreamRequest::~QuicStreamRequest() {
factory_->CancelRequest(this); factory_->CancelRequest(this);
} }
int QuicStreamRequest::Request(const HostPortPair& destination, int QuicStreamRequest::Request(
quic::QuicTransportVersion quic_version, const HostPortPair& destination,
PrivacyMode privacy_mode, quic::QuicTransportVersion quic_version,
RequestPriority priority, PrivacyMode privacy_mode,
const SocketTag& socket_tag, RequestPriority priority,
int cert_verify_flags, const SocketTag& socket_tag,
const GURL& url, int cert_verify_flags,
const NetLogWithSource& net_log, const GURL& url,
NetErrorDetails* net_error_details, const NetLogWithSource& net_log,
CompletionOnceCallback callback) { NetErrorDetails* net_error_details,
CompletionOnceCallback failed_on_default_network_callback,
CompletionOnceCallback callback) {
DCHECK_NE(quic_version, quic::QUIC_VERSION_UNSUPPORTED); DCHECK_NE(quic_version, quic::QUIC_VERSION_UNSUPPORTED);
DCHECK(net_error_details); DCHECK(net_error_details);
DCHECK(callback_.is_null()); DCHECK(callback_.is_null());
...@@ -678,6 +684,8 @@ int QuicStreamRequest::Request(const HostPortPair& destination, ...@@ -678,6 +684,8 @@ int QuicStreamRequest::Request(const HostPortPair& destination,
DCHECK(factory_); DCHECK(factory_);
net_error_details_ = net_error_details; net_error_details_ = net_error_details;
failed_on_default_network_callback_ =
std::move(failed_on_default_network_callback);
session_key_ = session_key_ =
QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, socket_tag); QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, socket_tag);
...@@ -709,6 +717,11 @@ void QuicStreamRequest::SetSession( ...@@ -709,6 +717,11 @@ void QuicStreamRequest::SetSession(
session_ = move(session); session_ = move(session);
} }
void QuicStreamRequest::OnConnectionFailedOnDefaultNetwork() {
if (!failed_on_default_network_callback_.is_null())
base::ResetAndReturn(&failed_on_default_network_callback_).Run(OK);
}
void QuicStreamRequest::OnRequestComplete(int rv) { void QuicStreamRequest::OnRequestComplete(int rv) {
factory_ = nullptr; factory_ = nullptr;
base::ResetAndReturn(&callback_).Run(rv); base::ResetAndReturn(&callback_).Run(rv);
...@@ -1324,6 +1337,14 @@ void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) { ...@@ -1324,6 +1337,14 @@ void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) {
if (!migrate_sessions_on_network_change_v2_) if (!migrate_sessions_on_network_change_v2_)
return; return;
// Clear alternative services that were marked as broken until default network
// changes.
if (retry_on_alternate_network_before_handshake_ &&
default_network_ != NetworkChangeNotifier::kInvalidNetworkHandle &&
network != default_network_) {
http_server_properties_->OnDefaultNetworkChanged();
}
DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network); DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network);
default_network_ = network; default_network_ = network;
ScopedConnectionMigrationEventLog scoped_event_log(net_log_, ScopedConnectionMigrationEventLog scoped_event_log(net_log_,
......
...@@ -123,6 +123,7 @@ class NET_EXPORT_PRIVATE QuicStreamRequest { ...@@ -123,6 +123,7 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
const GURL& url, const GURL& url,
const NetLogWithSource& net_log, const NetLogWithSource& net_log,
NetErrorDetails* net_error_details, NetErrorDetails* net_error_details,
CompletionOnceCallback failed_on_default_network_callback,
CompletionOnceCallback callback); CompletionOnceCallback callback);
// This function must be called after Request() returns ERR_IO_PENDING. // This function must be called after Request() returns ERR_IO_PENDING.
...@@ -144,6 +145,11 @@ class NET_EXPORT_PRIVATE QuicStreamRequest { ...@@ -144,6 +145,11 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
void OnRequestComplete(int rv); void OnRequestComplete(int rv);
// Called when the original connection created on the default network for
// |this| fails and a new connection has been created on the alternate
// network.
void OnConnectionFailedOnDefaultNetwork();
// Helper method that calls |factory_|'s GetTimeDelayForWaitingJob(). It // Helper method that calls |factory_|'s GetTimeDelayForWaitingJob(). It
// returns the amount of time waiting job should be delayed. // returns the amount of time waiting job should be delayed.
base::TimeDelta GetTimeDelayForWaitingJob() const; base::TimeDelta GetTimeDelayForWaitingJob() const;
...@@ -165,6 +171,7 @@ class NET_EXPORT_PRIVATE QuicStreamRequest { ...@@ -165,6 +171,7 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
QuicSessionKey session_key_; QuicSessionKey session_key_;
NetLogWithSource net_log_; NetLogWithSource net_log_;
CompletionOnceCallback callback_; CompletionOnceCallback callback_;
CompletionOnceCallback failed_on_default_network_callback_;
NetErrorDetails* net_error_details_; // Unowned. NetErrorDetails* net_error_details_; // Unowned.
std::unique_ptr<QuicChromiumClientSession::Handle> session_; std::unique_ptr<QuicChromiumClientSession::Handle> session_;
......
...@@ -159,7 +159,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -159,7 +159,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
env->host_port_pair, env->host_port_pair,
data_provider.PickValueInArray(quic::kSupportedTransportVersions), data_provider.PickValueInArray(quic::kSupportedTransportVersions),
PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), kCertVerifyFlags, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY, SocketTag(), kCertVerifyFlags,
GURL(kUrl), env->net_log, &net_error_details, callback.callback()); GURL(kUrl), env->net_log, &net_error_details,
/*failed_on_default_network_callback=*/CompletionOnceCallback(),
callback.callback());
callback.WaitForResult(); callback.WaitForResult();
std::unique_ptr<QuicChromiumClientSession::Handle> session = std::unique_ptr<QuicChromiumClientSession::Handle> session =
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -50,6 +50,15 @@ const std::vector<PostedTask>& TestTaskRunner::GetPostedTasks() const { ...@@ -50,6 +50,15 @@ const std::vector<PostedTask>& TestTaskRunner::GetPostedTasks() const {
return tasks_; return tasks_;
} }
quic::QuicTime::Delta TestTaskRunner::NextPendingTaskDelay() {
if (tasks_.empty())
return quic::QuicTime::Delta::Infinite();
auto next = FindNextTask();
return quic::QuicTime::Delta::FromMicroseconds(
(next->GetTimeToRun() - NowInTicks(*clock_)).InMicroseconds());
}
void TestTaskRunner::RunNextTask() { void TestTaskRunner::RunNextTask() {
std::vector<PostedTask>::iterator next = FindNextTask(); std::vector<PostedTask>::iterator next = FindNextTask();
DCHECK(next != tasks_.end()); DCHECK(next != tasks_.end());
...@@ -60,6 +69,24 @@ void TestTaskRunner::RunNextTask() { ...@@ -60,6 +69,24 @@ void TestTaskRunner::RunNextTask() {
std::move(task.task).Run(); std::move(task.task).Run();
} }
void TestTaskRunner::FastForwardBy(quic::QuicTime::Delta delta) {
DCHECK_GE(delta, quic::QuicTime::Delta::Zero());
quic::QuicTime end_timestamp = clock_->Now() + delta;
while (NextPendingTaskDelay() <= end_timestamp - clock_->Now()) {
RunNextTask();
}
if (clock_->Now() != end_timestamp)
clock_->AdvanceTime(end_timestamp - clock_->Now());
while (NextPendingTaskDelay() <= quic::QuicTime::Delta::Zero()) {
RunNextTask();
}
return;
}
void TestTaskRunner::RunUntilIdle() { void TestTaskRunner::RunUntilIdle() {
while (!tasks_.empty()) while (!tasks_.empty())
RunNextTask(); RunNextTask();
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "base/test/test_pending_task.h" #include "base/test/test_pending_task.h"
#include "net/third_party/quic/core/quic_time.h"
namespace quic { namespace quic {
class MockClock; class MockClock;
...@@ -40,10 +41,19 @@ class TestTaskRunner : public base::SequencedTaskRunner { ...@@ -40,10 +41,19 @@ class TestTaskRunner : public base::SequencedTaskRunner {
const std::vector<PostedTask>& GetPostedTasks() const; const std::vector<PostedTask>& GetPostedTasks() const;
// Returns the delay for next task to run. If there is no pending task,
// return QuicTime::Delta::Infinite().
quic::QuicTime::Delta NextPendingTaskDelay();
// Finds the next task to run, advances the time to the correct time // Finds the next task to run, advances the time to the correct time
// and then runs the task. // and then runs the task.
void RunNextTask(); void RunNextTask();
// Fast forwards virtual time by |delta|, causing all tasks with a remaining
// delay less than or equal to |delta| to be executed. |delta| must be
// non-negative.
void FastForwardBy(quic::QuicTime::Delta delta);
// While there are posted tasks, finds the next task to run, advances the // While there are posted tasks, finds the next task to run, advances the
// time to the correct time and then runs the task. // time to the correct time and then runs the task.
void RunUntilIdle(); void RunUntilIdle();
......
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