summaryrefslogtreecommitdiffstats
path: root/remoting/host
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-14 03:05:40 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-14 03:05:40 +0000
commit0e097f90d5bba038b5826ebac2870aadde28d2ca (patch)
tree47e141ab9ffcdd2baf1b4729ab1a9d8f384d55c2 /remoting/host
parentbb5c09478725b63241bd0d8d04bff0f70acc5d8f (diff)
downloadchromium_src-0e097f90d5bba038b5826ebac2870aadde28d2ca.zip
chromium_src-0e097f90d5bba038b5826ebac2870aadde28d2ca.tar.gz
chromium_src-0e097f90d5bba038b5826ebac2870aadde28d2ca.tar.bz2
Use heartbeat interval received from the bot.
BUG=None TEST=Unittests Review URL: http://codereview.chromium.org/5510006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69096 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host')
-rw-r--r--remoting/host/heartbeat_sender.cc57
-rw-r--r--remoting/host/heartbeat_sender.h18
-rw-r--r--remoting/host/heartbeat_sender_unittest.cc47
3 files changed, 96 insertions, 26 deletions
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc
index b4caf57f..74c08c3 100644
--- a/remoting/host/heartbeat_sender.cc
+++ b/remoting/host/heartbeat_sender.cc
@@ -16,6 +16,9 @@
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
#include "third_party/libjingle/source/talk/xmpp/constants.h"
+using buzz::QName;
+using buzz::XmlElement;
+
namespace remoting {
namespace {
@@ -24,12 +27,15 @@ const char kHostIdAttr[] = "hostid";
const char kHeartbeatSignatureTag[] = "signature";
const char kSignatureTimeAttr[] = "time";
-// TODO(sergeyu): Make this configurable by the cloud.
-const int64 kHeartbeatPeriodMs = 5 * 60 * 1000; // 5 minutes.
+const char kHeartbeatResultTag[] = "heartbeat-result";
+const char kSetIntervalTag[] = "set-interval";
+
+const int64 kDefaultHeartbeatIntervalMs = 5 * 60 * 1000; // 5 minutes.
}
HeartbeatSender::HeartbeatSender()
- : state_(CREATED) {
+ : state_(CREATED),
+ interval_ms_(kDefaultHeartbeatIntervalMs) {
}
HeartbeatSender::~HeartbeatSender() {
@@ -103,33 +109,56 @@ void HeartbeatSender::DoSendStanza() {
// Schedule next heartbeat.
jingle_client_->message_loop()->PostDelayedTask(
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza),
- kHeartbeatPeriodMs);
+ interval_ms_);
}
}
-void HeartbeatSender::ProcessResponse(const buzz::XmlElement* response) {
- if (response->Attr(buzz::QN_TYPE) == buzz::STR_ERROR) {
+void HeartbeatSender::ProcessResponse(const XmlElement* response) {
+ std::string type = response->Attr(buzz::QN_TYPE);
+ if (type == buzz::STR_ERROR) {
LOG(ERROR) << "Received error in response to heartbeat: "
<< response->Str();
+ return;
+ }
+
+ // This method must only be called for error or result stanzas.
+ DCHECK_EQ(buzz::STR_RESULT, type);
+
+ const XmlElement* result_element =
+ response->FirstNamed(QName(kChromotingXmlNamespace, kHeartbeatResultTag));
+ if (result_element) {
+ const XmlElement* set_interval_element =
+ result_element->FirstNamed(QName(kChromotingXmlNamespace,
+ kSetIntervalTag));
+ if (set_interval_element) {
+ const std::string& interval_str = set_interval_element->BodyText();
+ int interval;
+ if (!base::StringToInt(interval_str, &interval) || interval <= 0) {
+ LOG(ERROR) << "Received invalid set-interval: "
+ << set_interval_element->Str();
+ } else {
+ interval_ms_ = interval * base::Time::kMillisecondsPerSecond;
+ }
+ }
}
}
-buzz::XmlElement* HeartbeatSender::CreateHeartbeatMessage() {
- buzz::XmlElement* query = new buzz::XmlElement(
- buzz::QName(kChromotingXmlNamespace, kHeartbeatQueryTag));
- query->AddAttr(buzz::QName(kChromotingXmlNamespace, kHostIdAttr), host_id_);
+XmlElement* HeartbeatSender::CreateHeartbeatMessage() {
+ XmlElement* query = new XmlElement(
+ QName(kChromotingXmlNamespace, kHeartbeatQueryTag));
+ query->AddAttr(QName(kChromotingXmlNamespace, kHostIdAttr), host_id_);
query->AddElement(CreateSignature());
return query;
}
-buzz::XmlElement* HeartbeatSender::CreateSignature() {
- buzz::XmlElement* signature_tag = new buzz::XmlElement(
- buzz::QName(kChromotingXmlNamespace, kHeartbeatSignatureTag));
+XmlElement* HeartbeatSender::CreateSignature() {
+ XmlElement* signature_tag = new XmlElement(
+ QName(kChromotingXmlNamespace, kHeartbeatSignatureTag));
int64 time = static_cast<int64>(base::Time::Now().ToDoubleT());
std::string time_str(base::Int64ToString(time));
signature_tag->AddAttr(
- buzz::QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str);
+ QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str);
std::string message = jingle_client_->GetFullJid() + ' ' + time_str;
std::string signature(key_pair_.GetSignature(message));
diff --git a/remoting/host/heartbeat_sender.h b/remoting/host/heartbeat_sender.h
index e2befa9..ef310b4 100644
--- a/remoting/host/heartbeat_sender.h
+++ b/remoting/host/heartbeat_sender.h
@@ -37,6 +37,22 @@ class MutableHostConfig;
// being signed is the full Jid concatenated with the time value, separated by
// space. For example, for the heartbeat stanza above the message that is being
// signed is "user@gmail.com/chromoting123123 1279061748".
+//
+// Bot sends the following result stanza in response to each heartbeat:
+//
+// <iq type="set" from="remoting@bot.talk.google.com"
+// to="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
+// <rem:heartbeat-result xmlns:rem="google:remoting">
+// <rem:set-interval>300</rem:set-interval>
+// </rem:heartbeat>
+// </iq>
+//
+// The set-interval tag is used to specify desired heartbeat interval
+// in seconds. The heartbeat-result and the set-interval tags are
+// optional. Host uses default heartbeat interval if it doesn't find
+// set-interval tag in the result Iq stanza it receives from the
+// server.
+//
// TODO(sergeyu): Is it enough to sign JID and nothing else?
class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
public:
@@ -61,6 +77,7 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
private:
FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, DoSendStanza);
FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, CreateHeartbeatMessage);
+ FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, ProcessResponse);
enum State {
CREATED,
@@ -84,6 +101,7 @@ class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
scoped_ptr<IqRequest> request_;
std::string host_id_;
HostKeyPair key_pair_;
+ int interval_ms_;
DISALLOW_COPY_AND_ASSIGN(HeartbeatSender);
};
diff --git a/remoting/host/heartbeat_sender_unittest.cc b/remoting/host/heartbeat_sender_unittest.cc
index c5f03a8..9b3edfc 100644
--- a/remoting/host/heartbeat_sender_unittest.cc
+++ b/remoting/host/heartbeat_sender_unittest.cc
@@ -19,6 +19,9 @@
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
#include "third_party/libjingle/source/talk/xmpp/constants.h"
+using buzz::QName;
+using buzz::XmlElement;
+
using testing::_;
using testing::DeleteArg;
using testing::DoAll;
@@ -46,7 +49,7 @@ class MockIqRequest : public IqRequest {
}
MOCK_METHOD3(SendIq, void(const std::string& type,
const std::string& addressee,
- buzz::XmlElement* iq_body));
+ XmlElement* iq_body));
};
class HeartbeatSenderTest : public testing::Test {
@@ -79,10 +82,9 @@ class HeartbeatSenderTest : public testing::Test {
scoped_refptr<InMemoryHostConfig> config_;
};
+// Call Start() followed by Stop(), and makes sure an Iq stanza is
+// being send.
TEST_F(HeartbeatSenderTest, DoSendStanza) {
- // This test calls Start() followed by Stop(), and makes sure an Iq
- // stanza is being send.
-
// |iq_request| is freed by HeartbeatSender.
MockIqRequest* iq_request = new MockIqRequest(jingle_client_);
@@ -102,30 +104,29 @@ TEST_F(HeartbeatSenderTest, DoSendStanza) {
message_loop_.RunAllPending();
}
+// Validate format of the heartbeat stanza.
TEST_F(HeartbeatSenderTest, CreateHeartbeatMessage) {
- // This test validates format of the heartbeat stanza.
-
scoped_refptr<HeartbeatSender> heartbeat_sender(new HeartbeatSender());
ASSERT_TRUE(heartbeat_sender->Init(config_, jingle_client_));
int64 start_time = static_cast<int64>(base::Time::Now().ToDoubleT());
- scoped_ptr<buzz::XmlElement> stanza(
+ scoped_ptr<XmlElement> stanza(
heartbeat_sender->CreateHeartbeatMessage());
ASSERT_TRUE(stanza.get() != NULL);
- EXPECT_TRUE(buzz::QName(kChromotingXmlNamespace, "heartbeat") ==
+ EXPECT_TRUE(QName(kChromotingXmlNamespace, "heartbeat") ==
stanza->Name());
EXPECT_EQ(std::string(kHostId),
- stanza->Attr(buzz::QName(kChromotingXmlNamespace, "hostid")));
+ stanza->Attr(QName(kChromotingXmlNamespace, "hostid")));
- buzz::QName signature_tag(kChromotingXmlNamespace, "signature");
- buzz::XmlElement* signature = stanza->FirstNamed(signature_tag);
+ QName signature_tag(kChromotingXmlNamespace, "signature");
+ XmlElement* signature = stanza->FirstNamed(signature_tag);
ASSERT_TRUE(signature != NULL);
EXPECT_TRUE(stanza->NextNamed(signature_tag) == NULL);
std::string time_str =
- signature->Attr(buzz::QName(kChromotingXmlNamespace, "time"));
+ signature->Attr(QName(kChromotingXmlNamespace, "time"));
int64 time;
EXPECT_TRUE(base::StringToInt64(time_str, &time));
int64 now = static_cast<int64>(base::Time::Now().ToDoubleT());
@@ -139,4 +140,26 @@ TEST_F(HeartbeatSenderTest, CreateHeartbeatMessage) {
EXPECT_EQ(expected_signature, signature->BodyText());
}
+// Verify that ProcessResponse parses set-interval result.
+TEST_F(HeartbeatSenderTest, ProcessResponse) {
+ XmlElement* response = new XmlElement(QName("", "iq"));
+ response->AddAttr(QName("", "type"), "result");
+
+ XmlElement* result = new XmlElement(
+ QName(kChromotingXmlNamespace, "heartbeat-result"));
+ response->AddElement(result);
+
+ XmlElement* set_interval = new XmlElement(
+ QName(kChromotingXmlNamespace, "set-interval"));
+ result->AddElement(set_interval);
+
+ const int kTestInterval = 123;
+ set_interval->AddText(base::IntToString(kTestInterval));
+
+ scoped_refptr<HeartbeatSender> heartbeat_sender(new HeartbeatSender());
+ heartbeat_sender->ProcessResponse(response);
+
+ EXPECT_EQ(kTestInterval * 1000, heartbeat_sender->interval_ms_);
+}
+
} // namespace remoting