// Copyright (c) 2012 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_event_logger.h"
#include <windows.h>
#include <string>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/ip_endpoint.h"
#include "remoting/host/host_status_monitor.h"
#include "remoting/host/host_status_observer.h"
#include "remoting/protocol/transport.h"
#include "remoting_host_messages.h"
namespace remoting {
namespace {
class HostEventLoggerWin : public HostEventLogger, public HostStatusObserver {
public:
HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor,
const std::string& application_name);
virtual ~HostEventLoggerWin();
// HostStatusObserver implementation. These methods will be called from the
// network thread.
virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE;
virtual void OnClientDisconnected(const std::string& jid) OVERRIDE;
virtual void OnAccessDenied(const std::string& jid) OVERRIDE;
virtual void OnClientRouteChange(
const std::string& jid,
const std::string& channel_name,
const protocol::TransportRoute& route) OVERRIDE;
virtual void OnStart(const std::string& xmpp_login) OVERRIDE;
virtual void OnShutdown() OVERRIDE;
private:
void LogString(WORD type, DWORD event_id, const std::string& string);
void Log(WORD type, DWORD event_id, const std::vector<std::string>& strings);
base::WeakPtr<HostStatusMonitor> monitor_;
// The handle of the application event log.
HANDLE event_log_;
DISALLOW_COPY_AND_ASSIGN(HostEventLoggerWin);
};
} //namespace
HostEventLoggerWin::HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor,
const std::string& application_name)
: monitor_(monitor),
event_log_(NULL) {
event_log_ = RegisterEventSourceW(
NULL, base::UTF8ToUTF16(application_name).c_str());
if (event_log_ != NULL) {
monitor_->AddStatusObserver(this);
} else {
PLOG(ERROR) << "Failed to register the event source: " << application_name;
}
}
HostEventLoggerWin::~HostEventLoggerWin() {
if (event_log_ != NULL) {
if (monitor_)
monitor_->RemoveStatusObserver(this);
DeregisterEventSource(event_log_);
}
}
void HostEventLoggerWin::OnClientAuthenticated(const std::string& jid) {
LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_CONNECTED, jid);
}
void HostEventLoggerWin::OnClientDisconnected(const std::string& jid) {
LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_DISCONNECTED, jid);
}
void HostEventLoggerWin::OnAccessDenied(const std::string& jid) {
LogString(EVENTLOG_ERROR_TYPE, MSG_HOST_CLIENT_ACCESS_DENIED, jid);
}
void HostEventLoggerWin::OnClientRouteChange(
const std::string& jid,
const std::string& channel_name,
const protocol::TransportRoute& route) {
std::vector<std::string> strings(5);
strings[0] = jid;
strings[1] = route.remote_address.ToString();
strings[2] = route.local_address.ToString();
strings[3] = channel_name;
strings[4] = protocol::TransportRoute::GetTypeString(route.type);
Log(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_ROUTING_CHANGED, strings);
}
void HostEventLoggerWin::OnShutdown() {
// TODO(rmsousa): Fix host shutdown to actually call this, and add a log line.
}
void HostEventLoggerWin::OnStart(const std::string& xmpp_login) {
LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_STARTED, xmpp_login);
}
void HostEventLoggerWin::Log(WORD type,
DWORD event_id,
const std::vector<std::string>& strings) {
if (event_log_ == NULL)
return;
// ReportEventW() takes an array of raw string pointers. They should stay
// valid for the duration of the call.
std::vector<const WCHAR*> raw_strings(strings.size());
std::vector<base::string16> utf16_strings(strings.size());
for (size_t i = 0; i < strings.size(); ++i) {
utf16_strings[i] = base::UTF8ToUTF16(strings[i]);
raw_strings[i] = utf16_strings[i].c_str();
}
if (!ReportEventW(event_log_,
type,
HOST_CATEGORY,
event_id,
NULL,
static_cast<WORD>(raw_strings.size()),
0,
&raw_strings[0],
NULL)) {
PLOG(ERROR) << "Failed to write an event to the event log";
}
}
void HostEventLoggerWin::LogString(WORD type,
DWORD event_id,
const std::string& string) {
std::vector<std::string> strings;
strings.push_back(string);
Log(type, event_id, strings);
}
// static
scoped_ptr<HostEventLogger> HostEventLogger::Create(
base::WeakPtr<HostStatusMonitor> monitor,
const std::string& application_name) {
return scoped_ptr<HostEventLogger>(
new HostEventLoggerWin(monitor, application_name));
}
} // namespace remoting