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"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "remoting/host/server_log_entry_host.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/signaling/iq_sender.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/signaling/server_log_entry.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/signaling/signal_strategy.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "third_party/libjingle/source/talk/xmpp/constants.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing buzz::QName;
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing buzz::XmlElement;
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace remoting {
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace {
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kHostStatusTag[] = "host-status";
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kHostIdAttr[] = "hostid";
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kExitCodeAttr[] = "exit-code";
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kHostVersionTag[] = "host-version";
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kSignatureTag[] = "signature";
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kStatusAttr[] = "status";
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kSignatureTimeAttr[] = "time";
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char* const HostStatusSender::host_status_strings_[] =
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch{"OFFLINE", "ONLINE"};
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochHostStatusSender::HostStatusSender(
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& host_id,
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SignalStrategy* signal_strategy,
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_refptr<RsaKeyPair> key_pair,
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& directory_bot_jid)
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : host_id_(host_id),
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      signal_strategy_(signal_strategy),
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      key_pair_(key_pair),
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      directory_bot_jid_(directory_bot_jid) {
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(signal_strategy_);
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(key_pair_.get());
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signal_strategy_->AddListener(this);
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochHostStatusSender::~HostStatusSender() {
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signal_strategy_->RemoveListener(this);
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::OnSignalStrategyStateChange(
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SignalStrategy::State state) {
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state == SignalStrategy::CONNECTED)
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    iq_sender_.reset(new IqSender(signal_strategy_));
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else if (state == SignalStrategy::DISCONNECTED)
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    iq_sender_.reset();
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool HostStatusSender::OnSignalStrategyIncomingStanza(
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const XmlElement* stanza) {
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return false;
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::SendOfflineStatus(HostExitCodes exit_code) {
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SendHostStatus(OFFLINE, exit_code);
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::SendOnlineStatus() {
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SendHostStatus(ONLINE, kSuccessExitCode);
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostStatusSender::SendHostStatus(HostStatus status,
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                      HostExitCodes exit_code) {
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SignalStrategy::State state = signal_strategy_->GetState();
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (state == SignalStrategy::CONNECTED) {
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HOST_LOG << "Sending host status '"
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << HostStatusToString(status)
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << "' to "
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << directory_bot_jid_;
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    iq_sender_->SendIq(buzz::STR_SET,
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       directory_bot_jid_,
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       CreateHostStatusMessage(status, exit_code),
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       IqSender::ReplyCallback());
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HOST_LOG << "Cannot send host status to '"
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << directory_bot_jid_
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << " ' because the state of the SignalStrategy is "
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << state;
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<XmlElement> HostStatusSender::CreateHostStatusMessage(
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HostStatus status, HostExitCodes exit_code) {
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create host status stanza.
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> host_status(new XmlElement(
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kHostStatusTag)));
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddAttr(
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kHostIdAttr), host_id_);
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddAttr(
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kStatusAttr), HostStatusToString(status));
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status == OFFLINE) {
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    host_status->AddAttr(
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        QName(kChromotingXmlNamespace, kExitCodeAttr),
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        ExitCodeToString(exit_code));
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddElement(CreateSignature(status, exit_code).release());
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Append host version.
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> version_tag(new XmlElement(
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kHostVersionTag)));
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  version_tag->AddText(STRINGIZE(VERSION));
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddElement(version_tag.release());
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Append log message (which isn't signed).
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza());
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<ServerLogEntry> log_entry(
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      MakeLogEntryForHostStatus(status, exit_code));
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AddHostFieldsToLogEntry(log_entry.get());
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  log->AddElement(log_entry->ToStanza().release());
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  host_status->AddElement(log.release());
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return host_status.Pass();
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<XmlElement> HostStatusSender::CreateSignature(
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HostStatus status, HostExitCodes exit_code) {
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<XmlElement> signature_tag(new XmlElement(
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kSignatureTag)));
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Number of seconds since epoch (Jan 1, 1970).
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int64 time = static_cast<int64>(base::Time::Now().ToDoubleT());
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string time_str(base::Int64ToString(time));
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signature_tag->AddAttr(
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str);
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Add a time stamp to the signature to prevent replay attacks.
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string message =
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      signal_strategy_->GetLocalJid() +
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      " " +
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      time_str +
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      " " +
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      HostStatusToString(status);
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status == OFFLINE)
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    message += std::string(" ") + ExitCodeToString(exit_code);
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string signature(key_pair_->SignMessage(message));
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  signature_tag->AddText(signature);
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return signature_tag.Pass();
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace remoting
164