diff options
author | maksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-07 06:01:27 +0000 |
---|---|---|
committer | maksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-07 06:01:27 +0000 |
commit | 98fae91a816298249923d30172e55f434687e1f9 (patch) | |
tree | a898ac7360d0f90fc938ad88b4ed388044724bc9 /cloud_print/gcp20 | |
parent | 06fb2c0371b9cfb5980351d45665d41fdcfae3b5 (diff) | |
download | chromium_src-98fae91a816298249923d30172e55f434687e1f9.zip chromium_src-98fae91a816298249923d30172e55f434687e1f9.tar.gz chromium_src-98fae91a816298249923d30172e55f434687e1f9.tar.bz2 |
GCP2.0 Device: XMPP pings.
BUG=
Review URL: https://chromiumcodereview.appspot.com/21916003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216107 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print/gcp20')
-rw-r--r-- | cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc | 90 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h | 42 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/printer.cc | 7 |
3 files changed, 125 insertions, 14 deletions
diff --git a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc index bcf7dcc..6ad90230 100644 --- a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc +++ b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc @@ -4,7 +4,10 @@ #include "cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h" +#include "base/bind.h" #include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/rand_util.h" #include "base/single_thread_task_runner.h" #include "cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h" #include "jingle/notifier/base/notifier_options.h" @@ -12,6 +15,10 @@ namespace { +const int kUrgentPingInterval = 60; // in seconds +const int kPingTimeout = 30; // in seconds +const double kRandomDelayPercentage = 0.2; + const char kCloudPrintPushNotificationsSource[] = "cloudprint.google.com"; // Splits message into two parts (e.g. '<device_id>/delete' will be splitted @@ -32,21 +39,29 @@ void TokenizeXmppMessage(const std::string& message, std::string* device_id, CloudPrintXmppListener::CloudPrintXmppListener( const std::string& robot_email, + int standard_ping_interval, scoped_refptr<base::SingleThreadTaskRunner> task_runner, Delegate* delegate) : robot_email_(robot_email), + standard_ping_interval_(standard_ping_interval), + ping_timeouts_posted_(0), + ping_responses_pending_(0), + ping_scheduled_(false), context_getter_(new CloudPrintURLRequestContextGetter(task_runner)), delegate_(delegate) { } CloudPrintXmppListener::~CloudPrintXmppListener() { - push_client_->RemoveObserver(this); - push_client_.reset(); + if (push_client_) { + push_client_->RemoveObserver(this); + push_client_.reset(); + } } void CloudPrintXmppListener::Connect(const std::string& access_token) { - push_client_.reset(); access_token_ = access_token; + ping_responses_pending_ = 0; + ping_scheduled_ = 0; notifier::NotifierOptions options; options.request_context_getter = context_getter_; @@ -66,8 +81,13 @@ void CloudPrintXmppListener::Connect(const std::string& access_token) { push_client_->UpdateCredentials(robot_email_, access_token_); } +void CloudPrintXmppListener::set_standard_ping_interval(int interval) { + standard_ping_interval_ = interval; +} + void CloudPrintXmppListener::OnNotificationsEnabled() { delegate_->OnXmppConnected(); + SchedulePing(); } void CloudPrintXmppListener::OnNotificationsDisabled( @@ -77,7 +97,7 @@ void CloudPrintXmppListener::OnNotificationsDisabled( delegate_->OnXmppAuthError(); break; case notifier::TRANSIENT_NOTIFICATION_ERROR: - delegate_->OnXmppNetworkError(); + Disconnect(); break; default: NOTREACHED() << "XMPP failed with unexpected reason code: " << reason; @@ -102,7 +122,65 @@ void CloudPrintXmppListener::OnIncomingNotification( } void CloudPrintXmppListener::OnPingResponse() { - // TODO(maksymb): Implement pings - NOTIMPLEMENTED(); + ping_responses_pending_ = 0; + SchedulePing(); +} + +void CloudPrintXmppListener::Disconnect() { + push_client_.reset(); + delegate_->OnXmppNetworkError(); +} + +void CloudPrintXmppListener::SchedulePing() { + if (ping_scheduled_) + return; + + DCHECK_LE(kPingTimeout, kUrgentPingInterval); + int delay = (ping_responses_pending_ > 0) + ? kUrgentPingInterval - kPingTimeout + : standard_ping_interval_; + + delay += base::RandInt(0, delay*kRandomDelayPercentage); + + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&CloudPrintXmppListener::SendPing, AsWeakPtr()), + base::TimeDelta::FromSeconds(delay)); + + ping_scheduled_ = true; +} + +void CloudPrintXmppListener::SendPing() { + ping_scheduled_ = false; + + DCHECK(push_client_); + push_client_->SendPing(); + ++ping_responses_pending_; + + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&CloudPrintXmppListener::OnPingTimeoutReached, AsWeakPtr()), + base::TimeDelta::FromSeconds(kPingTimeout)); + ++ping_timeouts_posted_; +} + +void CloudPrintXmppListener::OnPingTimeoutReached() { + DCHECK_GT(ping_timeouts_posted_, 0); + --ping_timeouts_posted_; + if (ping_timeouts_posted_ > 0) + return; // Fake (old) timeout. + + switch (ping_responses_pending_) { + case 0: + break; + case 1: + SchedulePing(); + break; + case 2: + Disconnect(); + break; + default: + NOTREACHED(); + } } diff --git a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h index 843ba89..7c612fe 100644 --- a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h +++ b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h @@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "jingle/notifier/listener/push_client_observer.h" namespace base { @@ -31,7 +32,9 @@ class PushClient; } // namespace notifier -class CloudPrintXmppListener: public notifier::PushClientObserver { +class CloudPrintXmppListener + : public base::SupportsWeakPtr<CloudPrintXmppListener>, + public notifier::PushClientObserver { public: class Delegate { public: @@ -52,12 +55,13 @@ class CloudPrintXmppListener: public notifier::PushClientObserver { // Invoked when local settings was updated. virtual void OnXmppNewLocalSettings(const std::string& device_id) = 0; - // Invoked when printer was deleted from server. + // Invoked when printer was deleted from the server. virtual void OnXmppDeleteNotification(const std::string& device_id) = 0; }; CloudPrintXmppListener( const std::string& robot_email, + int standard_ping_interval, scoped_refptr<base::SingleThreadTaskRunner> task_runner, Delegate* delegate); @@ -66,6 +70,9 @@ class CloudPrintXmppListener: public notifier::PushClientObserver { // Connects to the server. void Connect(const std::string& access_token); + // Update ping interval when new local_settings was received. + void set_standard_ping_interval(int interval); + private: // notifier::PushClientObserver methods: virtual void OnNotificationsEnabled() OVERRIDE; @@ -75,18 +82,41 @@ class CloudPrintXmppListener: public notifier::PushClientObserver { const notifier::Notification& notification) OVERRIDE; virtual void OnPingResponse() OVERRIDE; - // Is used for reconnection when number of retries is now exhausted. - void ReconnectInternal(); + // Stops listening and sending pings. + void Disconnect(); + + // Schedules ping (unless it was already scheduled). + void SchedulePing(); + + // Sends ping. + void SendPing(); + + // Checks if ping was received. + void OnPingTimeoutReached(); // Credentials: std::string robot_email_; std::string access_token_; - scoped_refptr<net::URLRequestContextGetter> context_getter_; - // Internal listener. scoped_ptr<notifier::PushClient> push_client_; + // Interval between pings in regular workflow. + int standard_ping_interval_; + + // Number of timeouts posted to MessageLoop. Is used for controlling "fake" + // timeout calls. + int ping_timeouts_posted_; + + // Number of responses awaiting from XMPP server. Is used for controlling + // number of failed pings. + int ping_responses_pending_; + + // Is used for preventing multiple pings at the moment. + bool ping_scheduled_; + + scoped_refptr<net::URLRequestContextGetter> context_getter_; + Delegate* delegate_; DISALLOW_COPY_AND_ASSIGN(CloudPrintXmppListener); diff --git a/cloud_print/gcp20/prototype/printer.cc b/cloud_print/gcp20/prototype/printer.cc index a161edd..4583aa7 100644 --- a/cloud_print/gcp20/prototype/printer.cc +++ b/cloud_print/gcp20/prototype/printer.cc @@ -27,7 +27,8 @@ const char kPrinterStatePathDefault[] = "printer_state.json"; namespace { const uint16 kHttpPortDefault = 10101; -const uint32 kTtlDefault = 60*60; +const uint32 kTtlDefault = 60*60; // in seconds +const int kXmppPingIntervalDefault = 5*60; // in seconds const char kServiceType[] = "_privet._tcp.local"; const char kServiceNamePrefixDefault[] = "first_gcp20_device"; @@ -182,6 +183,7 @@ void Printer::Stop() { } void Printer::OnAuthError() { + LOG(ERROR) << "Auth error occurred"; access_token_update_ = base::Time::Now(); ChangeState(OFFLINE); // TODO(maksymb): Implement *instant* updating of access_token. @@ -476,7 +478,8 @@ void Printer::TryConnect() { void Printer::ConnectXmpp() { xmpp_listener_.reset( - new CloudPrintXmppListener(reg_info_.xmpp_jid, GetTaskRunner(), this)); + new CloudPrintXmppListener(reg_info_.xmpp_jid, kXmppPingIntervalDefault, + GetTaskRunner(), this)); xmpp_listener_->Connect(access_token_); } |