OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "remoting/host/host_status_sender.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/stringize_macros.h" |
| 10 #include "remoting/base/constants.h" |
| 11 #include "remoting/host/host_exit_codes.h" |
| 12 #include "remoting/host/server_log_entry.h" |
| 13 #include "remoting/jingle_glue/iq_sender.h" |
| 14 #include "remoting/jingle_glue/signal_strategy.h" |
| 15 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
| 16 #include "third_party/libjingle/source/talk/xmpp/constants.h" |
| 17 |
| 18 using buzz::QName; |
| 19 using buzz::XmlElement; |
| 20 |
| 21 namespace remoting { |
| 22 |
| 23 namespace { |
| 24 |
| 25 const char kHostStatusTag[] = "host-status"; |
| 26 const char kHostIdAttr[] = "hostid"; |
| 27 const char kExitCodeAttr[] = "exit-code"; |
| 28 const char kHostVersionTag[] = "host-version"; |
| 29 const char kSignatureTag[] = "signature"; |
| 30 const char kStatusAttr[] = "status"; |
| 31 const char kSignatureTimeAttr[] = "time"; |
| 32 |
| 33 } // namespace |
| 34 |
| 35 std::string HostStatusSender::host_status_strings_[] = |
| 36 {"OFFLINE", "ONLINE"}; |
| 37 |
| 38 HostStatusSender::HostStatusSender( |
| 39 const std::string& host_id, |
| 40 SignalStrategy* signal_strategy, |
| 41 scoped_refptr<RsaKeyPair> key_pair, |
| 42 const std::string& directory_bot_jid) |
| 43 : host_id_(host_id), |
| 44 signal_strategy_(signal_strategy), |
| 45 key_pair_(key_pair), |
| 46 directory_bot_jid_(directory_bot_jid) { |
| 47 DCHECK(signal_strategy_); |
| 48 DCHECK(key_pair_.get()); |
| 49 |
| 50 signal_strategy_->AddListener(this); |
| 51 } |
| 52 |
| 53 HostStatusSender::~HostStatusSender() { |
| 54 signal_strategy_->RemoveListener(this); |
| 55 } |
| 56 |
| 57 void HostStatusSender::OnSignalStrategyStateChange( |
| 58 SignalStrategy::State state) { |
| 59 if (state == SignalStrategy::CONNECTED) |
| 60 iq_sender_.reset(new IqSender(signal_strategy_)); |
| 61 else if (state == SignalStrategy::DISCONNECTED) |
| 62 iq_sender_.reset(); |
| 63 } |
| 64 |
| 65 bool HostStatusSender::OnSignalStrategyIncomingStanza( |
| 66 const XmlElement* stanza) { |
| 67 return false; |
| 68 } |
| 69 |
| 70 void HostStatusSender::SendOfflineStatus(int exit_code) { |
| 71 SendHostStatus(OFFLINE, exit_code); |
| 72 } |
| 73 |
| 74 void HostStatusSender::SendOnlineStatus() { |
| 75 SendHostStatus(ONLINE, 0); |
| 76 } |
| 77 |
| 78 void HostStatusSender::SendHostStatus(HostStatus status, int exit_code) { |
| 79 SignalStrategy::State state = signal_strategy_->GetState(); |
| 80 if (state == SignalStrategy::CONNECTED) { |
| 81 LOG(INFO) << "Sending host status '" |
| 82 << HostStatusToString(status) |
| 83 << "' to " |
| 84 << directory_bot_jid_; |
| 85 |
| 86 iq_sender_->SendIq(buzz::STR_SET, |
| 87 directory_bot_jid_, |
| 88 CreateHostStatusMessage(status, exit_code), |
| 89 IqSender::ReplyCallback()); |
| 90 } else { |
| 91 LOG(INFO) << "Cannot send host status to '" |
| 92 << directory_bot_jid_ |
| 93 << " ' because the state of the SignalStrategy is " |
| 94 << state; |
| 95 } |
| 96 } |
| 97 |
| 98 scoped_ptr<XmlElement> HostStatusSender::CreateHostStatusMessage( |
| 99 HostStatus status, int exit_code) { |
| 100 // Create host status stanza. |
| 101 scoped_ptr<XmlElement> host_status(new XmlElement( |
| 102 QName(kChromotingXmlNamespace, kHostStatusTag))); |
| 103 host_status->AddAttr( |
| 104 QName(kChromotingXmlNamespace, kHostIdAttr), host_id_); |
| 105 host_status->AddAttr( |
| 106 QName(kChromotingXmlNamespace, kStatusAttr), HostStatusToString(status)); |
| 107 |
| 108 if (status == OFFLINE) { |
| 109 host_status->AddAttr( |
| 110 QName(kChromotingXmlNamespace, kExitCodeAttr), |
| 111 ExitCodeToString(exit_code)); |
| 112 } |
| 113 |
| 114 host_status->AddElement(CreateSignature(status, exit_code).release()); |
| 115 |
| 116 // Append host version. |
| 117 scoped_ptr<XmlElement> version_tag(new XmlElement( |
| 118 QName(kChromotingXmlNamespace, kHostVersionTag))); |
| 119 version_tag->AddText(STRINGIZE(VERSION)); |
| 120 host_status->AddElement(version_tag.release()); |
| 121 |
| 122 // Append log message (which isn't signed). |
| 123 scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza()); |
| 124 scoped_ptr<ServerLogEntry> log_entry(ServerLogEntry::MakeForHostStatus()); |
| 125 log_entry->AddHostFields(); |
| 126 log_entry->AddCustomField(kStatusAttr, HostStatusToString(status)); |
| 127 if (status == OFFLINE) |
| 128 log_entry->AddCustomField(kExitCodeAttr, ExitCodeToString(exit_code)); |
| 129 log->AddElement(log_entry->ToStanza().release()); |
| 130 host_status->AddElement(log.release()); |
| 131 return host_status.Pass(); |
| 132 } |
| 133 |
| 134 scoped_ptr<XmlElement> HostStatusSender::CreateSignature( |
| 135 HostStatus status, int exit_code) { |
| 136 scoped_ptr<XmlElement> signature_tag(new XmlElement( |
| 137 QName(kChromotingXmlNamespace, kSignatureTag))); |
| 138 |
| 139 // Number of seconds since epoch (Jan 1, 1970). |
| 140 int64 time = static_cast<int64>(base::Time::Now().ToDoubleT()); |
| 141 std::string time_str(base::Int64ToString(time)); |
| 142 |
| 143 signature_tag->AddAttr( |
| 144 QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str); |
| 145 |
| 146 // Add a time stamp to the signature to prevent replay attacks. |
| 147 std::string message = |
| 148 signal_strategy_->GetLocalJid() + |
| 149 " " + |
| 150 time_str + |
| 151 " " + |
| 152 HostStatusToString(status); |
| 153 |
| 154 if (status == OFFLINE) |
| 155 message += " " + ExitCodeToString(exit_code); |
| 156 |
| 157 std::string signature(key_pair_->SignMessage(message)); |
| 158 signature_tag->AddText(signature); |
| 159 |
| 160 return signature_tag.Pass(); |
| 161 } |
| 162 |
| 163 } // namespace remoting |
OLD | NEW |