Index: remoting/host/heartbeat_sender.cc |
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc |
index fa234e35ae6039ec63c644b4667de1bb9e7de54c..7f6803891fab50e9c8ff9392470ae36f06723ce5 100644 |
--- a/remoting/host/heartbeat_sender.cc |
+++ b/remoting/host/heartbeat_sender.cc |
@@ -6,70 +6,103 @@ |
#include "base/logging.h" |
#include "base/message_loop.h" |
+#include "base/string_util.h" |
+#include "base/time.h" |
#include "remoting/base/constants.h" |
#include "remoting/host/host_config.h" |
#include "remoting/jingle_glue/iq_request.h" |
#include "remoting/jingle_glue/jingle_client.h" |
#include "remoting/jingle_glue/jingle_thread.h" |
-#include "talk/xmpp/constants.h" |
-#include "talk/xmllite/xmlelement.h" |
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
+#include "third_party/libjingle/source/talk/xmpp/constants.h" |
namespace remoting { |
namespace { |
-const char * const kChromotingNamespace = "google:remoting"; |
-const buzz::QName kHeartbeatQuery(true, kChromotingNamespace, "heartbeat"); |
-const buzz::QName kHostIdAttr(true, kChromotingNamespace, "hostid"); |
+const char kHeartbeatQueryTag[] = "heartbeat"; |
+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. |
} |
HeartbeatSender::HeartbeatSender() |
- : started_(false) { |
+ : state_(CREATED) { |
} |
-void HeartbeatSender::Start(MutableHostConfig* config, JingleClient* jingle_client) { |
- DCHECK(jingle_client); |
- DCHECK(!started_); |
+HeartbeatSender::~HeartbeatSender() { |
+ DCHECK(state_ == CREATED || state_ == INITIALIZED || state_ == STOPPED); |
+} |
- started_ = true; |
+bool HeartbeatSender::Init(MutableHostConfig* config, |
+ JingleClient* jingle_client) { |
+ DCHECK(jingle_client); |
+ DCHECK(state_ == CREATED); |
jingle_client_ = jingle_client; |
config_ = config; |
if (!config_->GetString(kHostIdConfigPath, &host_id_)) { |
LOG(ERROR) << "host_id is not defined in the config."; |
- return; |
+ return false; |
} |
- jingle_client_->message_loop()->PostTask( |
- FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoStart)); |
+ if (!key_pair_.Load(config)) { |
+ return false; |
+ } |
+ |
+ state_ = INITIALIZED; |
+ |
+ return true; |
} |
-void HeartbeatSender::DoStart() { |
- DCHECK(MessageLoop::current() == jingle_client_->message_loop()); |
+void HeartbeatSender::Start() { |
+ if (MessageLoop::current() != jingle_client_->message_loop()) { |
+ jingle_client_->message_loop()->PostTask( |
+ FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::Start)); |
+ return; |
+ } |
+ |
+ DCHECK(state_ == INITIALIZED); |
+ state_ = STARTED; |
- request_.reset(new IqRequest(jingle_client_)); |
+ request_.reset(jingle_client_->CreateIqRequest()); |
request_->set_callback(NewCallback(this, &HeartbeatSender::ProcessResponse)); |
jingle_client_->message_loop()->PostTask( |
FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza)); |
} |
+void HeartbeatSender::Stop() { |
+ if (MessageLoop::current() != jingle_client_->message_loop()) { |
+ jingle_client_->message_loop()->PostTask( |
+ FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::Stop)); |
+ return; |
+ } |
+ |
+ DCHECK(state_ == STARTED); |
+ state_ = STOPPED; |
+ request_.reset(NULL); |
+} |
+ |
void HeartbeatSender::DoSendStanza() { |
- DCHECK(MessageLoop::current() == jingle_client_->message_loop()); |
+ if (state_ == STARTED) { |
+ // |jingle_client_| may be already destroyed if |state_| is set to |
+ // |STOPPED|, so don't touch it here unless we are in |STARTED| state. |
+ DCHECK(MessageLoop::current() == jingle_client_->message_loop()); |
- LOG(INFO) << "Sending heartbeat stanza to " << kChromotingBotJid; |
+ LOG(INFO) << "Sending heartbeat stanza to " << kChromotingBotJid; |
- buzz::XmlElement* stanza = new buzz::XmlElement(kHeartbeatQuery); |
- stanza->AddAttr(kHostIdAttr, host_id_); |
- request_->SendIq(buzz::STR_SET, kChromotingBotJid, stanza); |
+ request_->SendIq(buzz::STR_SET, kChromotingBotJid, |
+ CreateHeartbeatMessage()); |
- // Schedule next heartbeat. |
- jingle_client_->message_loop()->PostDelayedTask( |
- FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza), |
- kHeartbeatPeriodMs); |
+ // Schedule next heartbeat. |
+ jingle_client_->message_loop()->PostDelayedTask( |
+ FROM_HERE, NewRunnableMethod(this, &HeartbeatSender::DoSendStanza), |
+ kHeartbeatPeriodMs); |
+ } |
} |
void HeartbeatSender::ProcessResponse(const buzz::XmlElement* response) { |
@@ -79,4 +112,28 @@ void HeartbeatSender::ProcessResponse(const buzz::XmlElement* response) { |
} |
} |
+buzz::XmlElement* HeartbeatSender::CreateHeartbeatMessage() { |
+ buzz::XmlElement* query = new buzz::XmlElement( |
+ buzz::QName(kChromotingXmlNamespace, kHeartbeatQueryTag)); |
+ query->AddAttr(buzz::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)); |
+ |
+ int64 time = static_cast<int64>(base::Time::Now().ToDoubleT()); |
+ std::string time_str(Int64ToString(time)); |
+ signature_tag->AddAttr( |
+ buzz::QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str); |
+ |
+ std::string message = jingle_client_->GetFullJid() + ' ' + time_str; |
+ std::string signature(key_pair_.GetSignature(message)); |
+ signature_tag->AddText(signature); |
+ |
+ return signature_tag; |
+} |
+ |
} // namespace remoting |