Chromium Code Reviews| Index: remoting/host/host_status_sender.cc |
| diff --git a/remoting/host/host_status_sender.cc b/remoting/host/host_status_sender.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8497adff0eda5dc518ab01ce024fa9410f5d4143 |
| --- /dev/null |
| +++ b/remoting/host/host_status_sender.cc |
| @@ -0,0 +1,156 @@ |
| +// Copyright 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "remoting/host/host_status_sender.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/strings/stringize_macros.h" |
| +#include "remoting/base/constants.h" |
| +#include "remoting/host/server_log_entry.h" |
| +#include "remoting/jingle_glue/iq_sender.h" |
| +#include "remoting/jingle_glue/signal_strategy.h" |
| +#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 { |
| + |
| +const char kHostStatusTag[] = "host-status"; |
| +const char kHostIdAttr[] = "hostid"; |
| +const char kExitCodeAttr[] = "exit-code"; |
| +const char kHostVersionTag[] = "host-version"; |
| +const char kSignatureTag[] = "signature"; |
| +const char kStatusAttr[] = "status"; |
| +const char kSignatureTimeAttr[] = "time"; |
| + |
| +} // namespace |
| + |
| +HostStatusSender::HostStatusSender( |
| + const std::string& host_id, |
| + SignalStrategy* signal_strategy, |
| + scoped_refptr<RsaKeyPair> key_pair, |
| + const std::string& directory_bot_jid) |
| + : host_id_(host_id), |
| + signal_strategy_(signal_strategy), |
| + key_pair_(key_pair), |
| + directory_bot_jid_(directory_bot_jid) { |
| + DCHECK(signal_strategy_); |
| + DCHECK(key_pair_.get()); |
| + |
| + signal_strategy_->AddListener(this); |
| +} |
| + |
| +HostStatusSender::~HostStatusSender() { |
| + signal_strategy_->RemoveListener(this); |
| +} |
| + |
| +void HostStatusSender::OnSignalStrategyStateChange( |
| + SignalStrategy::State state) { |
| + if (state == SignalStrategy::CONNECTED) |
| + iq_sender_.reset(new IqSender(signal_strategy_)); |
| + else if (state == SignalStrategy::DISCONNECTED) |
| + iq_sender_.reset(); |
| +} |
| + |
| +bool HostStatusSender::OnSignalStrategyIncomingStanza( |
| + const XmlElement* stanza) { |
| + return false; |
| +} |
| + |
| +void HostStatusSender::SendOfflineStatus(int exit_code) { |
| + SendHostStatus(OFFLINE, exit_code); |
| +} |
| + |
| +void HostStatusSender::SendOnlineStatus() { |
| + SendHostStatus(ONLINE, 0); |
| +} |
| + |
| +void HostStatusSender::SendHostStatus(HostStatus status, int exit_code) { |
| + SignalStrategy::State state = signal_strategy_->GetState(); |
| + if (state == SignalStrategy::CONNECTED) { |
| + LOG(INFO) << "Sending host status '" |
| + << status |
| + << "' to " |
| + << directory_bot_jid_; |
| + |
| + iq_sender_->SendIq(buzz::STR_SET, |
| + directory_bot_jid_, |
| + CreateHostStatusMessage(status, exit_code), |
| + IqSender::ReplyCallback()); |
| + } else { |
| + LOG(INFO) << "Cannot send host status to '" |
| + << directory_bot_jid_ |
| + << " ' because the state of the SignalStrategy is " |
| + << state; |
| + } |
| +} |
| + |
| +scoped_ptr<XmlElement> HostStatusSender::CreateHostStatusMessage( |
| + HostStatus status, int exit_code) { |
| + // Create host status stanza. |
| + scoped_ptr<XmlElement> host_status(new XmlElement( |
| + QName(kChromotingXmlNamespace, kHostStatusTag))); |
| + host_status->AddAttr( |
| + QName(kChromotingXmlNamespace, kHostIdAttr), host_id_); |
| + host_status->AddAttr( |
| + QName(kChromotingXmlNamespace, kStatusAttr), base::IntToString(status)); |
|
rmsousa
2013/07/04 01:20:14
we typically don't send/receive enums as raw numbe
weitao
2013/07/09 00:37:40
Done.
|
| + |
| + if (status == OFFLINE) { |
| + host_status->AddAttr( |
| + QName(kChromotingXmlNamespace, kExitCodeAttr), |
|
rmsousa
2013/07/04 01:20:14
For this one, I'm inclined to say that we should a
weitao
2013/07/09 00:37:40
Done.
|
| + base::IntToString(exit_code)); |
| + } |
| + |
| + host_status->AddElement(CreateSignature(status, exit_code).release()); |
| + |
| + // Append host version. |
| + scoped_ptr<XmlElement> version_tag(new XmlElement( |
| + QName(kChromotingXmlNamespace, kHostVersionTag))); |
| + version_tag->AddText(STRINGIZE(VERSION)); |
| + host_status->AddElement(version_tag.release()); |
| + |
| + // Append log message (which isn't signed). |
| + scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza()); |
| + scoped_ptr<ServerLogEntry> log_entry(ServerLogEntry::MakeForHostStatus()); |
| + log_entry->AddHostFields(); |
| + log->AddElement(log_entry->ToStanza().release()); |
|
rmsousa
2013/07/04 01:20:14
this log message should include the status and exi
weitao
2013/07/09 00:37:40
Done.
|
| + host_status->AddElement(log.release()); |
| + return host_status.Pass(); |
| +} |
| + |
| +scoped_ptr<XmlElement> HostStatusSender::CreateSignature( |
| + HostStatus status, int exit_code) { |
| + scoped_ptr<XmlElement> signature_tag(new XmlElement( |
| + QName(kChromotingXmlNamespace, kSignatureTag))); |
| + |
| + // Number of seconds since epoch (Jan 1, 1970). |
| + int64 time = static_cast<int64>(base::Time::Now().ToDoubleT()); |
| + std::string time_str(base::Int64ToString(time)); |
| + |
| + signature_tag->AddAttr( |
| + QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str); |
| + |
| + // Add a time stamp to the signature to prevent replay attacks. |
| + std::string message = |
| + signal_strategy_->GetLocalJid() + |
| + " " + |
| + time_str + |
| + " " + |
| + base::IntToString(status); |
| + |
| + if (status == OFFLINE) |
| + message += " " + base::IntToString(exit_code); |
| + |
| + std::string signature(key_pair_->SignMessage(message)); |
| + signature_tag->AddText(signature); |
| + |
| + return signature_tag.Pass(); |
| +} |
| + |
| +} // namespace remoting |