blob: 102351eb9fb957709fdf2b8637d476d84a336116 [file] [log] [blame]
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +10301/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
Brad Bishope45d8c72022-05-25 15:12:53 -040016/// \file perform_probe.cpp
17#include "entity_manager.hpp"
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103018
19#include <boost/algorithm/string/replace.hpp>
20
21#include <regex>
Andrew Jefferyea4ff022022-04-21 12:31:40 +093022#include <utility>
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103023
24constexpr const bool debug = false;
25
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103026// probes dbus interface dictionary for a key with a value that matches a regex
27// When an interface passes a probe, also save its D-Bus path with it.
Andrew Jefferyf5772d22022-04-12 22:05:30 +093028bool probeDbus(const std::string& interfaceName,
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103029 const std::map<std::string, nlohmann::json>& matches,
Andrew Jefferyf5772d22022-04-12 22:05:30 +093030 FoundDevices& devices, const std::shared_ptr<PerformScan>& scan,
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103031 bool& foundProbe)
32{
33 bool foundMatch = false;
34 foundProbe = false;
35
36 for (const auto& [path, interfaces] : scan->dbusProbeObjects)
37 {
Andrew Jefferyf5772d22022-04-12 22:05:30 +093038 auto it = interfaces.find(interfaceName);
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103039 if (it == interfaces.end())
40 {
41 continue;
42 }
43
44 foundProbe = true;
45
46 bool deviceMatches = true;
Andrew Jefferyf5772d22022-04-12 22:05:30 +093047 const DBusInterface& interface = it->second;
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103048
49 for (const auto& [matchProp, matchJSON] : matches)
50 {
Andrew Jefferyf5772d22022-04-12 22:05:30 +093051 auto deviceValue = interface.find(matchProp);
52 if (deviceValue != interface.end())
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103053 {
Patrick Williamsdf190612023-05-10 07:51:34 -050054 deviceMatches = deviceMatches &&
55 matchProbe(matchJSON, deviceValue->second);
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103056 }
57 else
58 {
59 // Move on to the next DBus path
60 deviceMatches = false;
61 break;
62 }
63 }
64 if (deviceMatches)
65 {
66 if constexpr (debug)
67 {
68 std::cerr << "probeDBus: Found probe match on " << path << " "
Andrew Jefferyf5772d22022-04-12 22:05:30 +093069 << interfaceName << "\n";
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103070 }
Patrick Williamsd2b78612023-10-20 17:24:54 -050071 devices.emplace_back(interface, path);
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103072 foundMatch = true;
73 }
74 }
75 return foundMatch;
76}
77
78// default probe entry point, iterates a list looking for specific types to
79// call specific probe functions
80bool probe(const std::vector<std::string>& probeCommand,
Andrew Jefferyf5772d22022-04-12 22:05:30 +093081 const std::shared_ptr<PerformScan>& scan, FoundDevices& foundDevs)
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103082{
83 const static std::regex command(R"(\((.*)\))");
84 std::smatch match;
85 bool ret = false;
86 bool matchOne = false;
87 bool cur = true;
88 probe_type_codes lastCommand = probe_type_codes::FALSE_T;
89 bool first = true;
90
Ed Tanous3013fb42022-07-09 08:27:06 -070091 for (const auto& probe : probeCommand)
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103092 {
Andrew Jeffery666583b2021-12-01 15:50:12 +103093 FoundProbeTypeT probeType = findProbeType(probe);
94 if (probeType)
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103095 {
Andrew Jeffery666583b2021-12-01 15:50:12 +103096 switch ((*probeType)->second)
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +103097 {
98 case probe_type_codes::FALSE_T:
99 {
100 cur = false;
101 break;
102 }
103 case probe_type_codes::TRUE_T:
104 {
105 cur = true;
106 break;
107 }
108 case probe_type_codes::MATCH_ONE:
109 {
110 // set current value to last, this probe type shouldn't
111 // affect the outcome
112 cur = ret;
113 matchOne = true;
114 break;
115 }
116 /*case probe_type_codes::AND:
117 break;
118 case probe_type_codes::OR:
119 break;
120 // these are no-ops until the last command switch
121 */
122 case probe_type_codes::FOUND:
123 {
124 if (!std::regex_search(probe, match, command))
125 {
126 std::cerr << "found probe syntax error " << probe
127 << "\n";
128 return false;
129 }
130 std::string commandStr = *(match.begin() + 1);
131 boost::replace_all(commandStr, "'", "");
132 cur = (std::find(scan->passedProbes.begin(),
133 scan->passedProbes.end(),
134 commandStr) != scan->passedProbes.end());
135 break;
136 }
137 default:
138 {
139 break;
140 }
141 }
142 }
143 // look on dbus for object
144 else
145 {
146 if (!std::regex_search(probe, match, command))
147 {
148 std::cerr << "dbus probe syntax error " << probe << "\n";
149 return false;
150 }
151 std::string commandStr = *(match.begin() + 1);
152 // convert single ticks and single slashes into legal json
153 boost::replace_all(commandStr, "'", "\"");
154 boost::replace_all(commandStr, R"(\)", R"(\\)");
Potin Lai0f3a4d92023-12-05 00:13:55 +0800155 auto json = nlohmann::json::parse(commandStr, nullptr, false, true);
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030156 if (json.is_discarded())
157 {
158 std::cerr << "dbus command syntax error " << commandStr << "\n";
159 return false;
160 }
161 // we can match any (string, variant) property. (string, string)
162 // does a regex
163 std::map<std::string, nlohmann::json> dbusProbeMap =
164 json.get<std::map<std::string, nlohmann::json>>();
165 auto findStart = probe.find('(');
166 if (findStart == std::string::npos)
167 {
168 return false;
169 }
Andrew Jeffery666583b2021-12-01 15:50:12 +1030170 bool foundProbe = !!probeType;
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030171 std::string probeInterface = probe.substr(0, findStart);
172 cur = probeDbus(probeInterface, dbusProbeMap, foundDevs, scan,
173 foundProbe);
174 }
175
176 // some functions like AND and OR only take affect after the
177 // fact
178 if (lastCommand == probe_type_codes::AND)
179 {
180 ret = cur && ret;
181 }
182 else if (lastCommand == probe_type_codes::OR)
183 {
184 ret = cur || ret;
185 }
186
187 if (first)
188 {
189 ret = cur;
190 first = false;
191 }
Patrick Williamsdf190612023-05-10 07:51:34 -0500192 lastCommand = probeType ? (*probeType)->second
193 : probe_type_codes::FALSE_T;
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030194 }
195
196 // probe passed, but empty device
Ed Tanous3013fb42022-07-09 08:27:06 -0700197 if (ret && foundDevs.empty())
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030198 {
Patrick Williamsd2b78612023-10-20 17:24:54 -0500199 foundDevs.emplace_back(
200 boost::container::flat_map<std::string, DBusValueVariant>{},
201 std::string{});
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030202 }
203 if (matchOne && ret)
204 {
205 // match the last one
206 auto last = foundDevs.back();
207 foundDevs.clear();
208
209 foundDevs.emplace_back(std::move(last));
210 }
211 return ret;
212}
213
Andrew Jefferyea4ff022022-04-21 12:31:40 +0930214PerformProbe::PerformProbe(nlohmann::json& recordRef,
215 const std::vector<std::string>& probeCommand,
216 std::string probeName,
217 std::shared_ptr<PerformScan>& scanPtr) :
218 recordRef(recordRef),
219 _probeCommand(probeCommand), probeName(std::move(probeName)), scan(scanPtr)
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030220{}
221PerformProbe::~PerformProbe()
222{
Andrew Jefferyf5772d22022-04-12 22:05:30 +0930223 FoundDevices foundDevs;
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030224 if (probe(_probeCommand, scan, foundDevs))
225 {
Andrew Jefferyaf9b46b2022-04-21 12:34:43 +0930226 scan->updateSystemConfiguration(recordRef, probeName, foundDevs);
Andrew Jefferyf07c5ed2021-12-01 14:22:04 +1030227 }
228}