| 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
|
|
|