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