shill: simplify PortalDetector start and stop trial
This is a reland of crrev/c/2760640 Change-Id
I4c4b4734324370669bfb0debb32b52e7b592419e. In this new version,
CleanupTrial() is called before invoking |portal_result_callback_| and
the ordering is unchanged.
This patch folds together multiple functions calling into each other
when a portal detection trial is started or stopped. The result is less
code and a logical flow that is easier to follow.
Also, this patch ensures that a metric event is recorded if the http
probe fails to start. Previously no event would be recorded in that
case.
BUG=b:182745554
TEST=unit tests. Checked portal validation on WiFi and Ethernet.
Change-Id: I0caf600eb82dd97544d3b82b1d558b40d12d8a23
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2790193
Tested-by: Hugo Benichi <hugobenichi@google.com>
Commit-Queue: Hugo Benichi <hugobenichi@google.com>
Reviewed-by: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: Eric Caruso <ejcaruso@chromium.org>
diff --git a/shill/portal_detector.cc b/shill/portal_detector.cc
index c5389ec..f6b6dc8 100644
--- a/shill/portal_detector.cc
+++ b/shill/portal_detector.cc
@@ -77,20 +77,6 @@
Stop();
}
-bool PortalDetector::StartAfterDelay(const PortalDetector::Properties& props,
- int delay_seconds) {
- SLOG(connection_.get(), 3) << "In " << __func__;
-
- if (!StartTrial(props, delay_seconds * 1000)) {
- return false;
- }
- // The attempt_start_time_ is calculated based on the current time and
- // |delay_seconds|. This is used to determine if a portal detection attempt
- // is in progress.
- UpdateAttemptTime(delay_seconds);
- return true;
-}
-
const string PortalDetector::PickHttpProbeUrl(const Properties& props) {
if (attempt_count_ == 0 || props.fallback_http_url_strings.empty()) {
return props.http_url_string;
@@ -99,8 +85,8 @@
0, props.fallback_http_url_strings.size() - 1)];
}
-bool PortalDetector::StartTrial(const Properties& props,
- int start_delay_milliseconds) {
+bool PortalDetector::StartAfterDelay(const PortalDetector::Properties& props,
+ int delay_seconds) {
SLOG(connection_.get(), 3) << "In " << __func__;
logging_tag_ = connection_->interface_name() + " " +
@@ -116,6 +102,7 @@
<< props.http_url_string;
return false;
}
+
if (!https_url.ParseFromString(https_url_string_)) {
LOG(ERROR) << "Failed to parse HTTPS probe URL string: "
<< props.https_url_string;
@@ -139,17 +126,15 @@
dispatcher_, LoggingTag() + " HTTPS probe", iface, src_address,
dns_list, allow_non_google_https);
}
- StartTrialAfterDelay(start_delay_milliseconds);
- return true;
-}
-
-void PortalDetector::StartTrialAfterDelay(int start_delay_milliseconds) {
- SLOG(connection_.get(), 4)
- << "In " << __func__ << " delay = " << start_delay_milliseconds << "ms.";
trial_.Reset(
Bind(&PortalDetector::StartTrialTask, weak_ptr_factory_.GetWeakPtr()));
dispatcher_->PostDelayedTask(FROM_HERE, trial_.callback(),
- start_delay_milliseconds);
+ delay_seconds * 1000);
+ // The attempt_start_time_ is calculated based on the current time and
+ // |delay_seconds|. This is used to determine if a portal detection attempt
+ // is in progress.
+ UpdateAttemptTime(delay_seconds);
+ return true;
}
void PortalDetector::StartTrialTask() {
@@ -167,7 +152,8 @@
if (http_result != HttpRequest::kResultInProgress) {
// If the http probe fails to start, complete the trial with a failure
// Result for https.
- LOG(ERROR) << LoggingTag() << ": HTTP probe failed to start";
+ LOG(ERROR) << LoggingTag()
+ << ": HTTP probe failed to start. Aborting trial.";
CompleteTrial(PortalDetector::GetPortalResultForRequestResult(http_result),
Result(Phase::kContent, Status::kFailure));
return;
@@ -187,6 +173,8 @@
https_result_ =
std::make_unique<Result>(GetPortalResultForRequestResult(https_result));
LOG(ERROR) << LoggingTag() << ": HTTPS probe failed to start";
+ // To find the portal sign-in url, wait for the HTTP probe to complete
+ // before completing the trial and calling |portal_result_callback_|.
}
is_active_ = true;
}
@@ -201,7 +189,10 @@
<< ", status=" << http_result.status
<< ". HTTPS probe: phase=" << https_result.phase
<< ", status=" << https_result.status;
- CompleteAttempt(http_result, https_result);
+ http_result.num_attempts = attempt_count_;
+ metrics_->NotifyPortalDetectionMultiProbeResult(http_result, https_result);
+ CleanupTrial();
+ portal_result_callback_.Run(http_result, https_result);
}
void PortalDetector::CleanupTrial() {
@@ -227,14 +218,6 @@
https_request_.reset();
}
-void PortalDetector::CompleteRequest() {
- if (https_result_ && http_result_) {
- metrics_->NotifyPortalDetectionMultiProbeResult(*http_result_,
- *https_result_);
- CompleteTrial(*http_result_.get(), *https_result_.get());
- }
-}
-
void PortalDetector::HttpRequestSuccessCallback(
std::shared_ptr<brillo::http::Response> response) {
// TODO(matthewmwang): check for 0 length data as well
@@ -265,8 +248,8 @@
LOG(INFO) << LoggingTag() << ": HTTP probe response code=" << status_code
<< " status=" << http_result_->status;
http_result_->status_code = status_code;
-
- CompleteRequest();
+ if (https_result_)
+ CompleteTrial(*http_result_, *https_result_);
}
void PortalDetector::HttpsRequestSuccessCallback(
@@ -280,7 +263,8 @@
LOG(INFO) << LoggingTag() << ": HTTPS probe response code=" << status_code
<< " status=" << probe_status;
https_result_ = std::make_unique<Result>(Phase::kContent, probe_status);
- CompleteRequest();
+ if (http_result_)
+ CompleteTrial(*http_result_, *https_result_);
}
void PortalDetector::HttpRequestErrorCallback(HttpRequest::Result result) {
@@ -289,7 +273,8 @@
LOG(INFO) << LoggingTag()
<< ": HTTP probe failed with phase=" << http_result_.get()->phase
<< " status=" << http_result_.get()->status;
- CompleteRequest();
+ if (https_result_)
+ CompleteTrial(*http_result_, *https_result_);
}
void PortalDetector::HttpsRequestErrorCallback(HttpRequest::Result result) {
@@ -298,19 +283,14 @@
LOG(INFO) << LoggingTag()
<< ": HTTPS probe failed with phase=" << https_result_.get()->phase
<< " status=" << https_result_.get()->status;
- CompleteRequest();
+ if (http_result_)
+ CompleteTrial(*http_result_, *https_result_);
}
bool PortalDetector::IsInProgress() {
return is_active_;
}
-void PortalDetector::CompleteAttempt(Result http_result, Result https_result) {
- http_result.num_attempts = attempt_count_;
- CleanupTrial();
- portal_result_callback_.Run(http_result, https_result);
-}
-
void PortalDetector::UpdateAttemptTime(int delay_seconds) {
time_->GetTimeMonotonic(&attempt_start_time_);
struct timeval delay_timeval = {delay_seconds, 0};
diff --git a/shill/portal_detector.h b/shill/portal_detector.h
index 5413d40..6baf972 100644
--- a/shill/portal_detector.h
+++ b/shill/portal_detector.h
@@ -148,6 +148,7 @@
//
// As each attempt completes the callback handed to the constructor will
// be called.
+ // TODO(b/184036481): Change |delay_seconds| type to base::TimeDelay.
virtual bool StartAfterDelay(const Properties& props, int delay_seconds);
// End the current portal detection process if one exists, and do not call
@@ -185,29 +186,10 @@
// to keep attempts spaced by the right duration in the event of a retry.
void UpdateAttemptTime(int delay_seconds);
- // Called after each trial to return |http_result| and |https_result| after
- // attempting to determine connectivity status.
- void CompleteAttempt(Result http_result, Result https_result);
-
- // Start a trial with the supplied delay in ms.
- void StartTrialAfterDelay(int start_delay_milliseconds);
-
- // Start a portal detection test. Returns true if |props.http_url_string| and
- // |props.https_url_string| correctly parse as URLs. Returns false (and does
- // not start) if they fail to parse.
- //
- // After a trial completes, the callback supplied in the constructor is
- // called.
- bool StartTrial(const Properties& props, int start_delay_milliseconds);
-
// Internal method used to start the actual connectivity trial, called after
// the start delay completes.
void StartTrialTask();
- // Called after a request finishes. Will call CompleteTrial once all probes
- // are done.
- void CompleteRequest();
-
// Callback used to return data read from the HTTP HttpRequest.
void HttpRequestSuccessCallback(
std::shared_ptr<brillo::http::Response> response);
@@ -222,7 +204,8 @@
// Callback used to return the error from the HTTPS HttpRequest.
void HttpsRequestErrorCallback(HttpRequest::Result result);
- // Internal method used to clean up state and call CompleteAttempt.
+ // Called after each trial to return |http_result| and |https_result| after
+ // attempting to determine connectivity status.
void CompleteTrial(Result http_result, Result https_result);
// Internal method used to cancel the timeout timer and stop an active
diff --git a/shill/portal_detector_test.cc b/shill/portal_detector_test.cc
index 11c2f54..542ca1d 100644
--- a/shill/portal_detector_test.cc
+++ b/shill/portal_detector_test.cc
@@ -389,7 +389,7 @@
HttpRequest::kResultDNSFailure);
PortalDetector::Result https_result = PortalDetector::Result(
PortalDetector::Phase::kContent, PortalDetector::Status::kFailure);
- portal_detector()->CompleteAttempt(r, https_result);
+ portal_detector()->CompleteTrial(r, https_result);
init_delay *= 2;
}
portal_detector()->Stop();