host_status_sender.cc revision f2477e01787aa58f445919b809d89e252beef54f
17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// found in the LICENSE file.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/host/host_status_sender.h"
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_number_conversions.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/stringize_macros.h"
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/time/time.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/base/constants.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "remoting/base/logging.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/host/server_log_entry.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/jingle_glue/iq_sender.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "remoting/jingle_glue/signal_strategy.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "third_party/libjingle/source/talk/xmpp/constants.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing buzz::QName;
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing buzz::XmlElement;
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace remoting {
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace {
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kHostStatusTag[] = "host-status";
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kHostIdAttr[] = "hostid";
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kExitCodeAttr[] = "exit-code";
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kHostVersionTag[] = "host-version";
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kSignatureTag[] = "signature";
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kStatusAttr[] = "status";
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kSignatureTimeAttr[] = "time";
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char* const HostStatusSender::host_status_strings_[] =
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch{"OFFLINE", "ONLINE"};
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochHostStatusSender::HostStatusSender(
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& host_id,
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SignalStrategy* signal_strategy,
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_refptr<RsaKeyPair> key_pair,
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& directory_bot_jid)
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : host_id_(host_id),
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      signal_strategy_(signal_strategy),
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      key_pair_(key_pair),
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      directory_bot_jid_(directory_bot_jid) {
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(signal_strategy_);
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(key_pair_.get());
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signal_strategy_->AddListener(this);
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochHostStatusSender::~HostStatusSender() {
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signal_strategy_->RemoveListener(this);
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::OnSignalStrategyStateChange(
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SignalStrategy::State state) {
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state == SignalStrategy::CONNECTED)
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    iq_sender_.reset(new IqSender(signal_strategy_));
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else if (state == SignalStrategy::DISCONNECTED)
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    iq_sender_.reset();
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool HostStatusSender::OnSignalStrategyIncomingStanza(
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const XmlElement* stanza) {
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::SendOfflineStatus(HostExitCodes exit_code) {
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SendHostStatus(OFFLINE, exit_code);
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::SendOnlineStatus() {
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SendHostStatus(ONLINE, kSuccessExitCode);
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::SendHostStatus(HostStatus status,
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                      HostExitCodes exit_code) {
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SignalStrategy::State state = signal_strategy_->GetState();
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state == SignalStrategy::CONNECTED) {
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HOST_LOG << "Sending host status '"
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << HostStatusToString(status)
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << "' to "
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << directory_bot_jid_;
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    iq_sender_->SendIq(buzz::STR_SET,
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       directory_bot_jid_,
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       CreateHostStatusMessage(status, exit_code),
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       IqSender::ReplyCallback());
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HOST_LOG << "Cannot send host status to '"
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << directory_bot_jid_
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << " ' because the state of the SignalStrategy is "
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << state;
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<XmlElement> HostStatusSender::CreateHostStatusMessage(
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HostStatus status, HostExitCodes exit_code) {
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create host status stanza.
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> host_status(new XmlElement(
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kHostStatusTag)));
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddAttr(
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kHostIdAttr), host_id_);
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddAttr(
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kStatusAttr), HostStatusToString(status));
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status == OFFLINE) {
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    host_status->AddAttr(
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        QName(kChromotingXmlNamespace, kExitCodeAttr),
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ExitCodeToString(exit_code));
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddElement(CreateSignature(status, exit_code).release());
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Append host version.
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> version_tag(new XmlElement(
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kHostVersionTag)));
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  version_tag->AddText(STRINGIZE(VERSION));
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddElement(version_tag.release());
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Append log message (which isn't signed).
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza());
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<ServerLogEntry> log_entry(
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ServerLogEntry::MakeForHostStatus(status, exit_code));
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  log_entry->AddHostFields();
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  log->AddElement(log_entry->ToStanza().release());
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddElement(log.release());
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return host_status.Pass();
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<XmlElement> HostStatusSender::CreateSignature(
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HostStatus status, HostExitCodes exit_code) {
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> signature_tag(new XmlElement(
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kSignatureTag)));
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Number of seconds since epoch (Jan 1, 1970).
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int64 time = static_cast<int64>(base::Time::Now().ToDoubleT());
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string time_str(base::Int64ToString(time));
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signature_tag->AddAttr(
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str);
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Add a time stamp to the signature to prevent replay attacks.
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string message =
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      signal_strategy_->GetLocalJid() +
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      " " +
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      time_str +
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      " " +
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      HostStatusToString(status);
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status == OFFLINE)
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    message += std::string(" ") + ExitCodeToString(exit_code);
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string signature(key_pair_->SignMessage(message));
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signature_tag->AddText(signature);
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return signature_tag.Pass();
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace remoting
163