Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / remoting / host / host_status_sender.cc
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/strings/string_number_conversions.h"
8 #include "base/strings/stringize_macros.h"
9 #include "base/time/time.h"
10 #include "remoting/base/constants.h"
11 #include "remoting/base/logging.h"
12 #include "remoting/host/server_log_entry_host.h"
13 #include "remoting/signaling/iq_sender.h"
14 #include "remoting/signaling/server_log_entry.h"
15 #include "remoting/signaling/signal_strategy.h"
16 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
17 #include "third_party/webrtc/libjingle/xmpp/constants.h"
18
19 using buzz::QName;
20 using buzz::XmlElement;
21
22 namespace remoting {
23
24 namespace {
25
26 const char kHostStatusTag[] = "host-status";
27 const char kHostIdAttr[] = "hostid";
28 const char kExitCodeAttr[] = "exit-code";
29 const char kHostVersionTag[] = "host-version";
30 const char kSignatureTag[] = "signature";
31 const char kStatusAttr[] = "status";
32 const char kSignatureTimeAttr[] = "time";
33
34 }  // namespace
35
36 const char* const HostStatusSender::host_status_strings_[] =
37 {"OFFLINE", "ONLINE"};
38
39 HostStatusSender::HostStatusSender(
40     const std::string& host_id,
41     SignalStrategy* signal_strategy,
42     scoped_refptr<RsaKeyPair> key_pair,
43     const std::string& directory_bot_jid)
44     : host_id_(host_id),
45       signal_strategy_(signal_strategy),
46       key_pair_(key_pair),
47       directory_bot_jid_(directory_bot_jid) {
48   DCHECK(signal_strategy_);
49   DCHECK(key_pair_.get());
50
51   signal_strategy_->AddListener(this);
52 }
53
54 HostStatusSender::~HostStatusSender() {
55   signal_strategy_->RemoveListener(this);
56 }
57
58 void HostStatusSender::OnSignalStrategyStateChange(
59     SignalStrategy::State state) {
60   if (state == SignalStrategy::CONNECTED)
61     iq_sender_.reset(new IqSender(signal_strategy_));
62   else if (state == SignalStrategy::DISCONNECTED)
63     iq_sender_.reset();
64 }
65
66 bool HostStatusSender::OnSignalStrategyIncomingStanza(
67     const XmlElement* stanza) {
68   return false;
69 }
70
71 void HostStatusSender::SendOfflineStatus(HostExitCodes exit_code) {
72   SendHostStatus(OFFLINE, exit_code);
73 }
74
75 void HostStatusSender::SendOnlineStatus() {
76   SendHostStatus(ONLINE, kSuccessExitCode);
77 }
78
79 void HostStatusSender::SendHostStatus(HostStatus status,
80                                       HostExitCodes exit_code) {
81   SignalStrategy::State state = signal_strategy_->GetState();
82   if (state == SignalStrategy::CONNECTED) {
83     HOST_LOG << "Sending host status '"
84               << HostStatusToString(status)
85               << "' to "
86               << directory_bot_jid_;
87
88     iq_sender_->SendIq(buzz::STR_SET,
89                        directory_bot_jid_,
90                        CreateHostStatusMessage(status, exit_code),
91                        IqSender::ReplyCallback());
92   } else {
93     HOST_LOG << "Cannot send host status to '"
94               << directory_bot_jid_
95               << " ' because the state of the SignalStrategy is "
96               << state;
97   }
98 }
99
100 scoped_ptr<XmlElement> HostStatusSender::CreateHostStatusMessage(
101     HostStatus status, HostExitCodes exit_code) {
102   // Create host status stanza.
103   scoped_ptr<XmlElement> host_status(new XmlElement(
104       QName(kChromotingXmlNamespace, kHostStatusTag)));
105   host_status->AddAttr(
106       QName(kChromotingXmlNamespace, kHostIdAttr), host_id_);
107   host_status->AddAttr(
108       QName(kChromotingXmlNamespace, kStatusAttr), HostStatusToString(status));
109
110   if (status == OFFLINE) {
111     host_status->AddAttr(
112         QName(kChromotingXmlNamespace, kExitCodeAttr),
113         ExitCodeToString(exit_code));
114   }
115
116   host_status->AddElement(CreateSignature(status, exit_code).release());
117
118   // Append host version.
119   scoped_ptr<XmlElement> version_tag(new XmlElement(
120       QName(kChromotingXmlNamespace, kHostVersionTag)));
121   version_tag->AddText(STRINGIZE(VERSION));
122   host_status->AddElement(version_tag.release());
123
124   // Append log message (which isn't signed).
125   scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza());
126   scoped_ptr<ServerLogEntry> log_entry(
127       MakeLogEntryForHostStatus(status, exit_code));
128   AddHostFieldsToLogEntry(log_entry.get());
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, HostExitCodes 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 += std::string(" ") + 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