buffet: Add periodic pings to XMPP connection In order to monitor XMPP connection, we are implementing support for XMPP pings described in XEP-0199 extension to XMPP standard (see: http://xmpp.org/extensions/xep-0199.html#c2s). Now we send ping requests to XMPP server every 60 seconds and if we receive no response, we assume the connection is broken and initiate immediate re-connection. BUG=brillo:1138 TEST=`FEATURES=test emerge-link buffet` Change-Id: Id2c092a0454b360d2c18bef5e30e3461ceeddab8 Reviewed-on: https://chromium-review.googlesource.com/274060 Reviewed-by: Vitaly Buka <vitalybuka@chromium.org> Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org> Tested-by: Alex Vakulenko <avakulenko@chromium.org> Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/notification/xmpp_channel.cc b/buffet/notification/xmpp_channel.cc index ab657d1..9bf9463 100644 --- a/buffet/notification/xmpp_channel.cc +++ b/buffet/notification/xmpp_channel.cc
@@ -75,6 +75,7 @@ const char kDefaultXmppHost[] = "talk.google.com"; const uint16_t kDefaultXmppPort = 5222; +const uint64_t kPingIntervalSeconds = 60; // 1 minute. } // namespace @@ -88,6 +89,7 @@ task_runner_{task_runner}, iq_stanza_handler_{new IqStanzaHandler{this, task_runner}} { read_socket_data_.resize(4096); + ping_timer_.SetTaskRunner(task_runner); } void XmppChannel::OnMessageRead(size_t size) { @@ -417,6 +419,8 @@ delegate_->OnDisconnected(); weak_ptr_factory_.InvalidateWeakPtrs(); + StopPingTimer(); + if (tls_stream_) { tls_stream_->CloseBlocking(nullptr); tls_stream_.reset(); @@ -432,6 +436,7 @@ void XmppChannel::OnConnected() { state_ = XmppState::kStarted; RestartXmppStream(); + StartPingTimer(); } void XmppChannel::RestartXmppStream() { @@ -442,4 +447,34 @@ SendMessage(BuildXmppStartStreamCommand()); } +void XmppChannel::StartPingTimer() { + ping_timer_.Start(FROM_HERE, + base::TimeDelta::FromSeconds(kPingIntervalSeconds), + base::Bind(&XmppChannel::PingServer, + weak_ptr_factory_.GetWeakPtr())); +} + +void XmppChannel::StopPingTimer() { + ping_timer_.Stop(); +} + +void XmppChannel::PingServer() { + // Send an XMPP Ping request as defined in XEP-0199 extension: + // http://xmpp.org/extensions/xep-0199.html + iq_stanza_handler_->SendRequest( + "get", jid_, account_, "<ping xmlns='urn:xmpp:ping'/>", + base::Bind(&XmppChannel::OnPingResponse, weak_ptr_factory_.GetWeakPtr()), + base::Bind(&XmppChannel::OnPingTimeout, weak_ptr_factory_.GetWeakPtr())); +} + +void XmppChannel::OnPingResponse(std::unique_ptr<XmlNode> reply) { + // Ping response received from server. Everything seems to be in order. + // Nothing else to do. +} + +void XmppChannel::OnPingTimeout() { + LOG(WARNING) << "XMPP channel seems to be disconnected - ping timed out"; + Restart(); +} + } // namespace buffet
diff --git a/buffet/notification/xmpp_channel.h b/buffet/notification/xmpp_channel.h index a36a070..bdddd91 100644 --- a/buffet/notification/xmpp_channel.h +++ b/buffet/notification/xmpp_channel.h
@@ -14,6 +14,7 @@ #include <base/macros.h> #include <base/memory/weak_ptr.h> #include <base/single_thread_task_runner.h> +#include <base/timer/timer.h> #include <chromeos/backoff_entry.h> #include <chromeos/streams/stream.h> @@ -73,6 +74,8 @@ // to help provide unit-test-specific functionality. virtual void Connect(const std::string& host, uint16_t port, const base::Closure& callback); + virtual void StartPingTimer(); + virtual void StopPingTimer(); XmppState state_{XmppState::kNotStarted}; @@ -114,6 +117,12 @@ void OnSessionEstablished(std::unique_ptr<XmlNode> reply); void OnSubscribed(std::unique_ptr<XmlNode> reply); + // Sends a ping request to the server to check if the connection is still + // valid. + void PingServer(); + void OnPingResponse(std::unique_ptr<XmlNode> reply); + void OnPingTimeout(); + // Robot account name for the device. std::string account_; @@ -144,6 +153,8 @@ bool write_pending_{false}; std::unique_ptr<IqStanzaHandler> iq_stanza_handler_; + base::Timer ping_timer_{true, true}; + base::WeakPtrFactory<XmppChannel> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(XmppChannel); };
diff --git a/buffet/notification/xmpp_channel_unittest.cc b/buffet/notification/xmpp_channel_unittest.cc index f739ef7..ee6ea75 100644 --- a/buffet/notification/xmpp_channel_unittest.cc +++ b/buffet/notification/xmpp_channel_unittest.cc
@@ -116,6 +116,9 @@ callback.Run(); } + void StartPingTimer() override {} + void StopPingTimer() override {} + chromeos::FakeStream fake_stream_; };