-
Notifications
You must be signed in to change notification settings - Fork 7
/
daemon.cc
179 lines (143 loc) · 5.88 KB
/
daemon.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2018 The Chromium OS 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 <sysexits.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/bind.h>
#include <base/json/json_writer.h>
#include <base/memory/ptr_util.h>
#include <chromeos/dbus/service_constants.h>
#include <google/protobuf/util/json_util.h>
#include "runtime_probe/daemon.h"
#include "runtime_probe/probe_config.h"
#include "runtime_probe/utils/config_utils.h"
namespace runtime_probe {
const char kErrorMsgFailedToPackProtobuf[] = "Failed to serailize the protobuf";
namespace {
void DumpProtocolBuffer(const google::protobuf::Message& protobuf,
std::string message_name) {
VLOG(3) << "---> Protobuf dump of " << message_name;
VLOG(3) << " DebugString():\n\n" << protobuf.DebugString();
std::string json_string;
google::protobuf::util::JsonPrintOptions options;
MessageToJsonString(protobuf, &json_string, options);
VLOG(3) << " JSON output:\n\n" << json_string << "\n";
VLOG(3) << "<--- Finished Protobuf dump\n";
}
} // namespace
Daemon::Daemon() {}
Daemon::~Daemon() {}
int Daemon::OnInit() {
int exit_code = DBusDaemon::OnInit();
if (exit_code != EX_OK)
return exit_code;
InitDBus();
return 0;
}
void Daemon::InitDBus() {
LOG(INFO) << "Init DBus for Runtime Probe";
// Get or create the ExportedObject for the Runtime Probe service.
auto const runtime_probe_exported_object =
bus_->GetExportedObject(dbus::ObjectPath(kRuntimeProbeServicePath));
CHECK(runtime_probe_exported_object);
// Register a handler of the ProbeCategories method.
CHECK(runtime_probe_exported_object->ExportMethodAndBlock(
kRuntimeProbeInterfaceName, kProbeCategoriesMethod,
base::Bind(&Daemon::ProbeCategories, weak_ptr_factory_.GetWeakPtr())));
// Take ownership of the RuntimeProbe service.
CHECK(bus_->RequestOwnershipAndBlock(kRuntimeProbeServiceName,
dbus::Bus::REQUIRE_PRIMARY));
LOG(INFO) << kRuntimeProbeServicePath << " DBus initialized.";
}
void Daemon::PostQuitTask() {
bus_->GetOriginTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&Daemon::QuitDaemonInternal, base::Unretained(this)));
}
void Daemon::QuitDaemonInternal() {
bus_->ShutdownAndBlock();
Quit();
}
void Daemon::SendProbeResult(
const ProbeResult& reply,
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender* response_sender) {
DumpProtocolBuffer(reply, "ProbeResult");
std::unique_ptr<dbus::Response> message(
dbus::Response::FromMethodCall(method_call));
dbus::MessageWriter writer(message.get());
if (!writer.AppendProtoAsArrayOfBytes(reply)) {
LOG(ERROR) << kErrorMsgFailedToPackProtobuf;
response_sender->Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_INVALID_ARGS, kErrorMsgFailedToPackProtobuf));
} else {
// TODO(itspeter): b/119939408, PII filter before return.
response_sender->Run(std::move(message));
}
PostQuitTask();
}
void Daemon::ProbeCategories(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
std::unique_ptr<dbus::Response> message(
dbus::Response::FromMethodCall(method_call));
dbus::MessageReader reader(method_call);
dbus::MessageWriter writer(message.get());
ProbeRequest request;
ProbeResult reply;
if (!reader.PopArrayOfBytesAsProto(&request)) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_REQUEST_INVALID);
return SendProbeResult(reply, method_call, &response_sender);
}
DumpProtocolBuffer(request, "ProbeRequest");
std::string probe_config_path;
if (!runtime_probe::GetProbeConfigPath(&probe_config_path, "")) {
reply.set_error(RUNTIME_PROBE_ERROR_DEFAULT_PROBE_CONFIG_NOT_FOUND);
return SendProbeResult(reply, method_call, &response_sender);
}
const auto probe_config_data =
runtime_probe::ParseProbeConfig(probe_config_path);
if (!probe_config_data) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_SYNTAX_ERROR);
return SendProbeResult(reply, method_call, &response_sender);
}
reply.set_probe_config_checksum(probe_config_data.value().sha1_hash);
VLOG(2) << "SHA1 checksum returned with protocol buffer: "
<< reply.probe_config_checksum();
const auto probe_config = runtime_probe::ProbeConfig::FromDictionaryValue(
probe_config_data.value().config_dv);
if (!probe_config) {
reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INCOMPLETE_PROBE_FUNCTION);
return SendProbeResult(reply, method_call, &response_sender);
}
std::unique_ptr<base::DictionaryValue> probe_result;
if (request.probe_default_category()) {
probe_result = probe_config->Eval();
} else {
// Convert the ProbeReuslt from enum into array of string.
std::vector<std::string> categories_to_probe;
const google::protobuf::EnumDescriptor* descriptor =
ProbeRequest_SupportCategory_descriptor();
for (int j = 0; j < request.categories_size(); j++)
categories_to_probe.push_back(
descriptor->FindValueByNumber(request.categories(j))->name());
probe_result = probe_config->Eval(categories_to_probe);
}
// TODO(itspeter): Report assigned but not in the probe config's category.
std::string output_js;
base::JSONWriter::Write(*probe_result, &output_js);
VLOG(3) << "Raw JSON probe result\n" << output_js;
// Convert JSON to Protocol Buffer.
auto options = google::protobuf::util::JsonParseOptions();
options.ignore_unknown_fields = true;
ProbeResult placeholder;
const auto json_parse_status = google::protobuf::util::JsonStringToMessage(
output_js, &placeholder, options);
reply.MergeFrom(placeholder);
VLOG(3) << "serialize JSON to Protobuf status: " << json_parse_status;
return SendProbeResult(reply, method_call, &response_sender);
}
} // namespace runtime_probe