diff options
author | weitaosu@chromium.org <weitaosu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-10 03:57:06 +0000 |
---|---|---|
committer | weitaosu@chromium.org <weitaosu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-10 03:57:06 +0000 |
commit | 929fb4e415bec4565b9eea7254f5ac019c7648b5 (patch) | |
tree | 6eaf066b57413f021ebc2fdaaf35abf494721a8b /remoting/host | |
parent | 47b37a6c0e164891bfa3993687cd3cc3edd113c6 (diff) | |
download | chromium_src-929fb4e415bec4565b9eea7254f5ac019c7648b5.zip chromium_src-929fb4e415bec4565b9eea7254f5ac019c7648b5.tar.gz chromium_src-929fb4e415bec4565b9eea7254f5ac019c7648b5.tar.bz2 |
Host offline status reporting.
This is change #1 of the Host offline status reporting work:
1. Define the structure of the offline status message.
2. The host sends the offline status message if the underlying XMPP connection is live.
BUG=247245
Review URL: https://chromiumcodereview.appspot.com/18075003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210731 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host')
-rw-r--r-- | remoting/host/host_exit_codes.cc | 28 | ||||
-rw-r--r-- | remoting/host/host_exit_codes.h | 1 | ||||
-rw-r--r-- | remoting/host/host_status_sender.cc | 161 | ||||
-rw-r--r-- | remoting/host/host_status_sender.h | 105 | ||||
-rw-r--r-- | remoting/host/host_status_sender_unittest.cc | 199 | ||||
-rw-r--r-- | remoting/host/remoting_me2me_host.cc | 25 | ||||
-rw-r--r-- | remoting/host/server_log_entry.cc | 16 | ||||
-rw-r--r-- | remoting/host/server_log_entry.h | 6 |
8 files changed, 538 insertions, 3 deletions
diff --git a/remoting/host/host_exit_codes.cc b/remoting/host/host_exit_codes.cc new file mode 100644 index 0000000..4e206a5 --- /dev/null +++ b/remoting/host/host_exit_codes.cc @@ -0,0 +1,28 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/host_exit_codes.h" + +#include "remoting/protocol/name_value_map.h" + +using remoting::protocol::NameMapElement; + +namespace remoting { + +const NameMapElement<HostExitCodes> kHostExitCodeStrings[] = { + { kSuccessExitCode, "SUCCESS_EXIT" }, + { kInitializationFailed, "INITIALIZATION_FAILED" }, + { kInvalidHostConfigurationExitCode, "INVALID_HOST_CONFIGURATION" }, + { kInvalidHostIdExitCode, "INVALID_HOST_ID" }, + { kInvalidOauthCredentialsExitCode, "INVALID_OAUTH_CREDENTIALS" }, + { kInvalidHostDomainExitCode, "INVALID_HOST_DOMAIN" }, + { kLoginScreenNotSupportedExitCode, "LOGIN_SCREEN_NOT_SUPPORTED" }, + { kUsernameMismatchExitCode, "USERNAME_MISMATCH" }, +}; + +const char* ExitCodeToString(HostExitCodes exit_code) { + return ValueToName(kHostExitCodeStrings, exit_code); +} + +} // namespace remoting diff --git a/remoting/host/host_exit_codes.h b/remoting/host/host_exit_codes.h index b325d1f..c45459b 100644 --- a/remoting/host/host_exit_codes.h +++ b/remoting/host/host_exit_codes.h @@ -33,6 +33,7 @@ enum HostExitCodes { kMaxPermanentErrorExitCode = kUsernameMismatchExitCode }; +const char* ExitCodeToString(HostExitCodes exit_code); } // namespace remoting #endif // REMOTING_HOST_HOST_EXIT_CODES_H_ diff --git a/remoting/host/host_status_sender.cc b/remoting/host/host_status_sender.cc new file mode 100644 index 0000000..75154cc --- /dev/null +++ b/remoting/host/host_status_sender.cc @@ -0,0 +1,161 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/host_status_sender.h" + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringize_macros.h" +#include "remoting/base/constants.h" +#include "remoting/host/server_log_entry.h" +#include "remoting/jingle_glue/iq_sender.h" +#include "remoting/jingle_glue/signal_strategy.h" +#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" +#include "third_party/libjingle/source/talk/xmpp/constants.h" + +using buzz::QName; +using buzz::XmlElement; + +namespace remoting { + +namespace { + +const char kHostStatusTag[] = "host-status"; +const char kHostIdAttr[] = "hostid"; +const char kExitCodeAttr[] = "exit-code"; +const char kHostVersionTag[] = "host-version"; +const char kSignatureTag[] = "signature"; +const char kStatusAttr[] = "status"; +const char kSignatureTimeAttr[] = "time"; + +} // namespace + +const char* const HostStatusSender::host_status_strings_[] = +{"OFFLINE", "ONLINE"}; + +HostStatusSender::HostStatusSender( + const std::string& host_id, + SignalStrategy* signal_strategy, + scoped_refptr<RsaKeyPair> key_pair, + const std::string& directory_bot_jid) + : host_id_(host_id), + signal_strategy_(signal_strategy), + key_pair_(key_pair), + directory_bot_jid_(directory_bot_jid) { + DCHECK(signal_strategy_); + DCHECK(key_pair_.get()); + + signal_strategy_->AddListener(this); +} + +HostStatusSender::~HostStatusSender() { + signal_strategy_->RemoveListener(this); +} + +void HostStatusSender::OnSignalStrategyStateChange( + SignalStrategy::State state) { + if (state == SignalStrategy::CONNECTED) + iq_sender_.reset(new IqSender(signal_strategy_)); + else if (state == SignalStrategy::DISCONNECTED) + iq_sender_.reset(); +} + +bool HostStatusSender::OnSignalStrategyIncomingStanza( + const XmlElement* stanza) { + return false; +} + +void HostStatusSender::SendOfflineStatus(HostExitCodes exit_code) { + SendHostStatus(OFFLINE, exit_code); +} + +void HostStatusSender::SendOnlineStatus() { + SendHostStatus(ONLINE, kSuccessExitCode); +} + +void HostStatusSender::SendHostStatus(HostStatus status, + HostExitCodes exit_code) { + SignalStrategy::State state = signal_strategy_->GetState(); + if (state == SignalStrategy::CONNECTED) { + LOG(INFO) << "Sending host status '" + << HostStatusToString(status) + << "' to " + << directory_bot_jid_; + + iq_sender_->SendIq(buzz::STR_SET, + directory_bot_jid_, + CreateHostStatusMessage(status, exit_code), + IqSender::ReplyCallback()); + } else { + LOG(INFO) << "Cannot send host status to '" + << directory_bot_jid_ + << " ' because the state of the SignalStrategy is " + << state; + } +} + +scoped_ptr<XmlElement> HostStatusSender::CreateHostStatusMessage( + HostStatus status, HostExitCodes exit_code) { + // Create host status stanza. + scoped_ptr<XmlElement> host_status(new XmlElement( + QName(kChromotingXmlNamespace, kHostStatusTag))); + host_status->AddAttr( + QName(kChromotingXmlNamespace, kHostIdAttr), host_id_); + host_status->AddAttr( + QName(kChromotingXmlNamespace, kStatusAttr), HostStatusToString(status)); + + if (status == OFFLINE) { + host_status->AddAttr( + QName(kChromotingXmlNamespace, kExitCodeAttr), + ExitCodeToString(exit_code)); + } + + host_status->AddElement(CreateSignature(status, exit_code).release()); + + // Append host version. + scoped_ptr<XmlElement> version_tag(new XmlElement( + QName(kChromotingXmlNamespace, kHostVersionTag))); + version_tag->AddText(STRINGIZE(VERSION)); + host_status->AddElement(version_tag.release()); + + // Append log message (which isn't signed). + scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza()); + scoped_ptr<ServerLogEntry> log_entry( + ServerLogEntry::MakeForHostStatus(status, exit_code)); + log_entry->AddHostFields(); + log->AddElement(log_entry->ToStanza().release()); + host_status->AddElement(log.release()); + return host_status.Pass(); +} + +scoped_ptr<XmlElement> HostStatusSender::CreateSignature( + HostStatus status, HostExitCodes exit_code) { + scoped_ptr<XmlElement> signature_tag(new XmlElement( + QName(kChromotingXmlNamespace, kSignatureTag))); + + // Number of seconds since epoch (Jan 1, 1970). + int64 time = static_cast<int64>(base::Time::Now().ToDoubleT()); + std::string time_str(base::Int64ToString(time)); + + signature_tag->AddAttr( + QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str); + + // Add a time stamp to the signature to prevent replay attacks. + std::string message = + signal_strategy_->GetLocalJid() + + " " + + time_str + + " " + + HostStatusToString(status); + + if (status == OFFLINE) + message += std::string(" ") + ExitCodeToString(exit_code); + + std::string signature(key_pair_->SignMessage(message)); + signature_tag->AddText(signature); + + return signature_tag.Pass(); +} + +} // namespace remoting diff --git a/remoting/host/host_status_sender.h b/remoting/host/host_status_sender.h new file mode 100644 index 0000000..3fa86b5 --- /dev/null +++ b/remoting/host/host_status_sender.h @@ -0,0 +1,105 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_HOST_STATUS_SENDER_H_ +#define REMOTING_HOST_STATUS_SENDER_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "remoting/base/rsa_key_pair.h" +#include "remoting/host/host_exit_codes.h" +#include "remoting/jingle_glue/signal_strategy.h" + +namespace base { +class MessageLoopProxy; +} // namespace base + +namespace buzz { +class XmlElement; +} // namespace buzz + +namespace remoting { + +class RsaKeyPair; +class IqSender; + +// HostStatusSender sends the host status to the Chromoting Bot. +// Each host status stanza looks as follows: +// +// <cli:iq type="set" to="user@gmail.com/chromoting123123" +// id="123" xmlns:cli="jabber:client"> +// <rem:host-status rem:hostid="0" +// rem:status="OFFLINE" rem:exit-code="INVALID_HOST_CONFIGURATION" +// xmlns:rem="google:remoting"> +// <rem:signature rem:time="1372878097">.signature.</rem:signature> +// <rem:host-version>30.0.1554.0</rem:host-version> +// <rem:log><rem:entry cpu="x86_64" event-name="host-status" +// host-version="30.0.1560.0" os-name="Linux" role="host"/> +// </rem:log> +// </rem:host-status> +// </cli:iq> +// +// The signature is a base-64 encoded SHA-1 hash, signed with the host's +// private RSA key. The message being signed contains the full Jid (e.g. +// "user@gmail.com/chromoting123123"), the timestamp, the host status, +// and the exit code. +class HostStatusSender : SignalStrategy::Listener { + public: + + enum HostStatus { + OFFLINE = 0, + ONLINE = 1 + }; + + HostStatusSender(const std::string& host_id, + SignalStrategy* signal_strategy, + scoped_refptr<RsaKeyPair> key_pair, + const std::string& directory_bot_jid); + virtual ~HostStatusSender(); + + // SignalStrategy::Listener interface. + virtual void OnSignalStrategyStateChange( + SignalStrategy::State state) OVERRIDE; + virtual bool OnSignalStrategyIncomingStanza( + const buzz::XmlElement* stanza) OVERRIDE; + + // APIs for sending host status XMPP messages to the chromoting bot. + // status: the reason (exit code) why the host is offline. + void SendOnlineStatus(); + void SendOfflineStatus(HostExitCodes exit_code); + + inline static const char* HostStatusToString(HostStatus host_status) { + return host_status_strings_[host_status]; + } + + private: + // Helper method for sending either an online or an offline status message. + void SendHostStatus(HostStatus status, HostExitCodes exit_code); + + // Helper method to compose host status stanzas. + scoped_ptr<buzz::XmlElement> CreateHostStatusMessage( + HostStatus status, HostExitCodes exit_code); + + // Helper method to create the signature blob used in the host status stanza. + scoped_ptr<buzz::XmlElement> CreateSignature( + HostStatus status, HostExitCodes exit_code); + + std::string host_id_; + SignalStrategy* signal_strategy_; + scoped_refptr<RsaKeyPair> key_pair_; + std::string directory_bot_jid_; + scoped_ptr<IqSender> iq_sender_; + + // The string representation of the HostStatus values. + static const char* const host_status_strings_[2]; + + DISALLOW_COPY_AND_ASSIGN(HostStatusSender); +}; + +} // namespace remoting + +#endif // REMOTING_HOST_STATUS_SENDER_H_ diff --git a/remoting/host/host_status_sender_unittest.cc b/remoting/host/host_status_sender_unittest.cc new file mode 100644 index 0000000..4e55e73 --- /dev/null +++ b/remoting/host/host_status_sender_unittest.cc @@ -0,0 +1,199 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/host_status_sender.h" + +#include "base/strings/string_number_conversions.h" +#include "remoting/base/constants.h" +#include "remoting/base/rsa_key_pair.h" +#include "remoting/base/test_rsa_key_pair.h" +#include "remoting/host/host_exit_codes.h" +#include "remoting/jingle_glue/mock_objects.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" + +using buzz::QName; +using buzz::XmlElement; + +using testing::DoAll; +using testing::NotNull; +using testing::Return; +using testing::SaveArg; + +namespace remoting { + +namespace { + +const char kTestBotJid[] = "remotingunittest@bot.talk.google.com"; +const char kHostId[] = "0"; +const char kTestJid[] = "user@gmail.com/chromoting123"; +const char kStanzaId[] = "123"; + +const HostExitCodes kTestExitCode = kInvalidHostConfigurationExitCode; +const char kTestExitCodeString[] = "INVALID_HOST_CONFIGURATION"; + +} // namespace + +class HostStatusSenderTest + : public testing::Test { + protected: + virtual void SetUp() OVERRIDE { + key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair); + ASSERT_TRUE(key_pair_.get()); + + host_status_sender_.reset(new HostStatusSender( + kHostId, &signal_strategy_, key_pair_, kTestBotJid)); + } + + virtual void TearDown() OVERRIDE { + host_status_sender_.reset(); + } + + void ValidateHostStatusStanza(XmlElement* stanza, + HostStatusSender::HostStatus status); + + void ValidateSignature( + XmlElement* signature, HostStatusSender::HostStatus status); + + MockSignalStrategy signal_strategy_; + scoped_refptr<RsaKeyPair> key_pair_; + scoped_ptr<HostStatusSender> host_status_sender_; +}; + +TEST_F(HostStatusSenderTest, SendOnlineStatus) { + XmlElement* sent_iq = NULL; + EXPECT_CALL(signal_strategy_, GetState()) + .WillOnce(Return(SignalStrategy::DISCONNECTED)) + .WillRepeatedly(Return(SignalStrategy::CONNECTED)); + EXPECT_CALL(signal_strategy_, GetLocalJid()) + .WillRepeatedly(Return(kTestJid)); + EXPECT_CALL(signal_strategy_, GetNextId()) + .WillOnce(Return(kStanzaId)); + EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) + .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true))); + + // Call SendOnlineStatus twice. The first call should be a + // no-op because |signal_strategy_| is diconnected. + // So we expect SendStanza to be called only once. + host_status_sender_->SendOnlineStatus(); + + host_status_sender_->OnSignalStrategyStateChange( + SignalStrategy::CONNECTED); + host_status_sender_->SendOnlineStatus(); + + scoped_ptr<XmlElement> stanza(sent_iq); + + ASSERT_TRUE(stanza != NULL); + LOG(INFO) << stanza->Str(); + + ValidateHostStatusStanza(stanza.get(), HostStatusSender::ONLINE); +} + +TEST_F(HostStatusSenderTest, SendOfflineStatus) { + XmlElement* sent_iq = NULL; + EXPECT_CALL(signal_strategy_, GetState()) + .WillOnce(Return(SignalStrategy::DISCONNECTED)) + .WillRepeatedly(Return(SignalStrategy::CONNECTED)); + EXPECT_CALL(signal_strategy_, GetLocalJid()) + .WillRepeatedly(Return(kTestJid)); + EXPECT_CALL(signal_strategy_, GetNextId()) + .WillOnce(Return(kStanzaId)); + EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull())) + .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true))); + + // Call SendOfflineStatus twice. The first call should be a + // no-op because |signal_strategy_| is diconnected. + // So we expect SendStanza to be called only once. + host_status_sender_->SendOfflineStatus(kTestExitCode); + + host_status_sender_->OnSignalStrategyStateChange( + SignalStrategy::CONNECTED); + host_status_sender_->SendOfflineStatus(kTestExitCode); + + scoped_ptr<XmlElement> stanza(sent_iq); + + ASSERT_TRUE(stanza != NULL); + LOG(INFO) << stanza->Str(); + + ValidateHostStatusStanza(stanza.get(), HostStatusSender::OFFLINE); +} + +// Validate a host status stanza. +void HostStatusSenderTest::ValidateHostStatusStanza( + XmlElement* stanza, HostStatusSender::HostStatus status) { + EXPECT_EQ(stanza->Attr(QName(std::string(), "to")), + std::string(kTestBotJid)); + EXPECT_EQ(stanza->Attr(QName(std::string(), "type")), "set"); + + XmlElement* host_status_stanza = + stanza->FirstNamed(QName(kChromotingXmlNamespace, "host-status")); + ASSERT_TRUE(host_status_stanza != NULL); + + if (status == HostStatusSender::ONLINE) { + EXPECT_EQ("ONLINE", + host_status_stanza->Attr( + QName(kChromotingXmlNamespace, "status"))); + EXPECT_FALSE(host_status_stanza->HasAttr( + QName(kChromotingXmlNamespace, "exit-code"))); + } else { + EXPECT_EQ("OFFLINE", + host_status_stanza->Attr( + QName(kChromotingXmlNamespace, "status"))); + EXPECT_EQ(kTestExitCodeString, + host_status_stanza->Attr( + QName(kChromotingXmlNamespace, "exit-code"))); + } + + EXPECT_EQ(std::string(kHostId), + host_status_stanza->Attr( + QName(kChromotingXmlNamespace, "hostid"))); + + QName signature_tag(kChromotingXmlNamespace, "signature"); + XmlElement* signature = host_status_stanza->FirstNamed(signature_tag); + ASSERT_TRUE(signature != NULL); + EXPECT_TRUE(host_status_stanza->NextNamed(signature_tag) == NULL); + + ValidateSignature(signature, status); +} + +// Validate the signature. +void HostStatusSenderTest::ValidateSignature( + XmlElement* signature, HostStatusSender::HostStatus status) { + + EXPECT_TRUE(signature->HasAttr( + QName(kChromotingXmlNamespace, "time"))); + + std::string time_str = + signature->Attr(QName(kChromotingXmlNamespace, "time")); + + int64 time; + ASSERT_TRUE(base::StringToInt64(time_str, &time)); + + std::string message; + message += kTestJid; + message += " "; + message += time_str; + message += " "; + + if (status == HostStatusSender::OFFLINE) { + message += "OFFLINE"; + message += " "; + message += kTestExitCodeString; + } else { + message += "ONLINE"; + } + + scoped_refptr<RsaKeyPair> key_pair = RsaKeyPair::FromString(kTestRsaKeyPair); + ASSERT_TRUE(key_pair.get()); + + std::string expected_signature = + key_pair->SignMessage(message); + EXPECT_EQ(expected_signature, signature->BodyText()); + + int64 now = static_cast<int64>(base::Time::Now().ToDoubleT()); + LOG(INFO) << "SendHostStatus took " << now - time << " seconds."; +} + +} // namespace remoting diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 25a4ef1..91b4606 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -50,6 +50,7 @@ #include "remoting/host/host_event_logger.h" #include "remoting/host/host_exit_codes.h" #include "remoting/host/host_main.h" +#include "remoting/host/host_status_sender.h" #include "remoting/host/ipc_constants.h" #include "remoting/host/ipc_desktop_environment.h" #include "remoting/host/ipc_host_event_logger.h" @@ -221,7 +222,9 @@ class HostProcess void RestartHost(); // Stops the host and shuts down the process with the specified |exit_code|. - void ShutdownHost(int exit_code); + void ShutdownHost(HostExitCodes exit_code); + + void ScheduleHostShutdown(); void ShutdownOnNetworkThread(); @@ -272,6 +275,7 @@ class HostProcess scoped_ptr<XmppSignalStrategy> signal_strategy_; scoped_ptr<SignalingConnector> signaling_connector_; scoped_ptr<HeartbeatSender> heartbeat_sender_; + scoped_ptr<HostStatusSender> host_status_sender_; scoped_ptr<HostChangeNotificationListener> host_change_notification_listener_; scoped_ptr<LogToServer> log_to_server_; scoped_ptr<HostEventLogger> host_event_logger_; @@ -956,6 +960,9 @@ void HostProcess::StartHost() { this, host_id_, signal_strategy_.get(), key_pair_, directory_bot_jid_)); + host_status_sender_.reset(new HostStatusSender( + host_id_, signal_strategy_.get(), key_pair_, directory_bot_jid_)); + host_change_notification_listener_.reset(new HostChangeNotificationListener( this, host_id_, signal_strategy_.get(), directory_bot_jid_)); @@ -990,7 +997,7 @@ void HostProcess::RestartHost() { ShutdownOnNetworkThread(); } -void HostProcess::ShutdownHost(int exit_code) { +void HostProcess::ShutdownHost(HostExitCodes exit_code) { DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); *exit_code_out_ = exit_code; @@ -999,7 +1006,8 @@ void HostProcess::ShutdownHost(int exit_code) { case HOST_INITIALIZING: case HOST_STARTED: state_ = HOST_STOPPING; - ShutdownOnNetworkThread(); + host_status_sender_->SendOfflineStatus(exit_code); + ScheduleHostShutdown(); break; case HOST_STOPPING_TO_RESTART: @@ -1013,6 +1021,16 @@ void HostProcess::ShutdownHost(int exit_code) { } } +// TODO(weitaosu): shut down the host once we get an ACK for the offline status +// XMPP message. +void HostProcess::ScheduleHostShutdown() { + // Delay the shutdown by 2 second to allow SendOfflineStatus to complete. + context_->network_task_runner()->PostDelayedTask( + FROM_HERE, + base::Bind(&HostProcess::ShutdownOnNetworkThread, base::Unretained(this)), + base::TimeDelta::FromSeconds(2)); +} + void HostProcess::ShutdownOnNetworkThread() { DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); @@ -1020,6 +1038,7 @@ void HostProcess::ShutdownOnNetworkThread() { host_event_logger_.reset(); log_to_server_.reset(); heartbeat_sender_.reset(); + host_status_sender_.reset(); host_change_notification_listener_.reset(); signaling_connector_.reset(); signal_strategy_.reset(); diff --git a/remoting/host/server_log_entry.cc b/remoting/host/server_log_entry.cc index f18b2378..b13f6c6 100644 --- a/remoting/host/server_log_entry.cc +++ b/remoting/host/server_log_entry.cc @@ -26,6 +26,7 @@ const char kLogEntry[] = "entry"; const char kKeyEventName[] = "event-name"; const char kValueEventNameSessionState[] = "session-state"; const char kValueEventNameHeartbeat[] = "heartbeat"; +const char kValueEventNameHostStatus[] = "host-status"; const char kKeyRole[] = "role"; const char kValueRoleHost[] = "host"; @@ -38,6 +39,9 @@ const char kKeySessionState[] = "session-state"; const char kValueSessionStateConnected[] = "connected"; const char kValueSessionStateClosed[] = "closed"; +const char kStatusName[] = "status"; +const char kExitCodeName[] = "exit-code"; + const char kKeyOsName[] = "os-name"; const char kValueOsNameWindows[] = "Windows"; const char kValueOsNameLinux[] = "Linux"; @@ -84,6 +88,18 @@ scoped_ptr<ServerLogEntry> ServerLogEntry::MakeForHeartbeat() { return entry.Pass(); } +// static +scoped_ptr<ServerLogEntry> ServerLogEntry::MakeForHostStatus( + HostStatusSender::HostStatus host_status, HostExitCodes exit_code) { + scoped_ptr<ServerLogEntry> entry(new ServerLogEntry()); + entry->Set(kKeyRole, kValueRoleHost); + entry->Set(kKeyEventName, kValueEventNameHostStatus); + entry->Set(kStatusName, HostStatusSender::HostStatusToString(host_status)); + if (host_status == HostStatusSender::OFFLINE) + entry->Set(kExitCodeName, ExitCodeToString(exit_code)); + return entry.Pass(); +} + void ServerLogEntry::AddHostFields() { #if defined(OS_WIN) Set(kKeyOsName, kValueOsNameWindows); diff --git a/remoting/host/server_log_entry.h b/remoting/host/server_log_entry.h index 3e8e68b..ccaa850 100644 --- a/remoting/host/server_log_entry.h +++ b/remoting/host/server_log_entry.h @@ -9,6 +9,8 @@ #include <string> #include "base/memory/scoped_ptr.h" +#include "remoting/host/host_exit_codes.h" +#include "remoting/host/host_status_sender.h" #include "remoting/protocol/transport.h" namespace buzz { @@ -37,6 +39,10 @@ class ServerLogEntry { // Constructs a log entry for a heartbeat. static scoped_ptr<ServerLogEntry> MakeForHeartbeat(); + // Constructs a log entry for a host status message. + static scoped_ptr<ServerLogEntry> MakeForHostStatus( + HostStatusSender::HostStatus host_status, HostExitCodes exit_code); + ~ServerLogEntry(); // Adds fields describing the host to this log entry. |