buffet: Fix failed XMPP authorization issue
Right now, if XMPP notification channel is created early enough before
buffet was able to refresh the access token, XMPP might have invalid
or outdated credentials and XMPP SASL handshake would fail with
"not authorized" problem. Current code just retries the connection
attempt, but, sadly, using the same invalid credentials, which goes
into infinte loop of failed attempts.
Fixed the problem by making sure that XMPP authorization error causes
access token refresh and if authorization error occurrs, XMPP connection
will not be re-established until we get a new access token.
BUG=brillo:1174
TEST=`FEATURES=test emerge-link buffet`
Change-Id: Ieebfff26f4d06524819b2a5819f468e179cd2d6f
Reviewed-on: https://chromium-review.googlesource.com/273979
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index bd99917..3dd5864 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -280,10 +280,23 @@
LOG(INFO) << "Access token is refreshed for additional " << expires_in
<< " seconds.";
+ if (primary_notification_channel_ &&
+ !primary_notification_channel_->IsConnected()) {
+ // If we have disconnected channel, it is due to failed credentials.
+ // Now that we have a new access token, retry the connection.
+ StartNotificationChannel();
+ }
return true;
}
+void DeviceRegistrationInfo::RunRefreshAccessToken() {
+ RefreshAccessToken(nullptr);
+}
+
void DeviceRegistrationInfo::StartNotificationChannel() {
+ if (notification_channel_starting_)
+ return;
+
// If no MessageLoop assume we're in unittests.
if (!base::MessageLoop::current()) {
LOG(INFO) << "No MessageLoop, not starting notification channel";
@@ -318,6 +331,7 @@
return;
}
+ notification_channel_starting_ = true;
primary_notification_channel_.reset(
new XmppChannel{config_->robot_account(), access_token_, task_runner});
primary_notification_channel_->Start(this);
@@ -953,6 +967,7 @@
LOG(INFO) << "Notification channel successfully established over "
<< channel_name;
CHECK_EQ(primary_notification_channel_->GetName(), channel_name);
+ notification_channel_starting_ = false;
pull_channel_->UpdatePullInterval(
base::TimeDelta::FromMilliseconds(config_->backup_polling_period_ms()));
current_notification_channel_ = primary_notification_channel_.get();
@@ -971,6 +986,11 @@
void DeviceRegistrationInfo::OnPermanentFailure() {
LOG(ERROR) << "Failed to establish notification channel.";
+ notification_channel_starting_ = false;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceRegistrationInfo::RunRefreshAccessToken,
+ weak_factory_.GetWeakPtr()));
}
void DeviceRegistrationInfo::OnCommandCreated(