blob: 69ab8e1ddeb9527340c4287be7beef3e36ef1205 [file] [log] [blame]
Andrew Geisslera80a3af2019-02-04 14:01:49 -06001#include "associations.hpp"
Andrew Geissler3b025e62019-02-01 10:33:54 -06002#include "processing.hpp"
Matt Spinlerdd945862018-09-07 12:41:05 -05003#include "src/argument.hpp"
Matt Spinler35396c12019-04-05 11:46:57 -05004#include "types.hpp"
Matt Spinlerdd945862018-09-07 12:41:05 -05005
Ed Tanous60520632018-06-11 17:46:52 -07006#include <tinyxml2.h>
7
Ed Tanous60520632018-06-11 17:46:52 -07008#include <boost/algorithm/string/predicate.hpp>
Ed Tanous21c60592020-08-17 23:43:46 -07009#include <boost/asio/io_context.hpp>
10#include <boost/asio/signal_set.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070011#include <boost/container/flat_map.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070012#include <sdbusplus/asio/connection.hpp>
13#include <sdbusplus/asio/object_server.hpp>
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +030014#include <xyz/openbmc_project/Common/error.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070015
Brad Bishop23520882022-05-26 21:39:53 -040016#include <atomic>
17#include <chrono>
18#include <iomanip>
19#include <iostream>
20
Matt Spinlere2359fb2019-04-05 14:11:33 -050021AssociationMaps associationMaps;
Matt Spinler937a2322019-01-23 13:54:22 -060022
Brad Bishopf944a452022-05-05 15:06:46 -040023static AllowDenyList serviceAllowList;
24static AllowDenyList serviceDenyList;
Matt Spinlerdd945862018-09-07 12:41:05 -050025
Brad Bishopa098a372022-05-05 15:19:04 -040026void updateOwners(sdbusplus::asio::connection* conn,
27 boost::container::flat_map<std::string, std::string>& owners,
28 const std::string& newObject)
Ed Tanous60520632018-06-11 17:46:52 -070029{
Brad Bishopa098a372022-05-05 15:19:04 -040030 if (boost::starts_with(newObject, ":"))
Ed Tanous60520632018-06-11 17:46:52 -070031 {
32 return;
33 }
34 conn->async_method_call(
Brad Bishopa098a372022-05-05 15:19:04 -040035 [&, newObject](const boost::system::error_code ec,
36 const std::string& nameOwner) {
Ed Tanous60520632018-06-11 17:46:52 -070037 if (ec)
38 {
Brad Bishopa098a372022-05-05 15:19:04 -040039 std::cerr << "Error getting owner of " << newObject << " : "
Ed Tanous60520632018-06-11 17:46:52 -070040 << ec << "\n";
41 return;
42 }
Brad Bishopa098a372022-05-05 15:19:04 -040043 owners[nameOwner] = newObject;
Ed Tanous60520632018-06-11 17:46:52 -070044 },
45 "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner",
Brad Bishopa098a372022-05-05 15:19:04 -040046 newObject);
Ed Tanous60520632018-06-11 17:46:52 -070047}
48
Brad Bishopa098a372022-05-05 15:19:04 -040049void sendIntrospectionCompleteSignal(sdbusplus::asio::connection* systemBus,
50 const std::string& processName)
Ed Tanous60520632018-06-11 17:46:52 -070051{
52 // TODO(ed) This signal doesn't get exposed properly in the
53 // introspect right now. Find out how to register signals in
54 // sdbusplus
Brad Bishopa098a372022-05-05 15:19:04 -040055 sdbusplus::message::message m = systemBus->new_signal(
Brad Bishopa02cd542021-10-12 19:12:42 -040056 "/xyz/openbmc_project/object_mapper",
57 "xyz.openbmc_project.ObjectMapper.Private", "IntrospectionComplete");
Brad Bishopa098a372022-05-05 15:19:04 -040058 m.append(processName);
Ed Tanous60520632018-06-11 17:46:52 -070059 m.signal_send();
60}
61
62struct InProgressIntrospect
63{
64 InProgressIntrospect(
Brad Bishopa098a372022-05-05 15:19:04 -040065 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
66 const std::string& processName, AssociationMaps& am
Matt Spinleraecabe82018-09-19 13:25:42 -050067#ifdef DEBUG
68 ,
Ed Tanous60520632018-06-11 17:46:52 -070069 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -040070 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -050071#endif
72 ) :
Brad Bishopa098a372022-05-05 15:19:04 -040073 systemBus(systemBus),
74 io(io), processName(processName), assocMaps(am)
Matt Spinleraecabe82018-09-19 13:25:42 -050075#ifdef DEBUG
76 ,
Brad Bishopa098a372022-05-05 15:19:04 -040077 globalStartTime(globalStartTime),
78 processStartTime(std::chrono::steady_clock::now())
Matt Spinleraecabe82018-09-19 13:25:42 -050079#endif
Brad Bishop23520882022-05-26 21:39:53 -040080 {}
Ed Tanous60520632018-06-11 17:46:52 -070081 ~InProgressIntrospect()
82 {
Brad Bishopa098a372022-05-05 15:19:04 -040083 sendIntrospectionCompleteSignal(systemBus, processName);
Matt Spinleraecabe82018-09-19 13:25:42 -050084
85#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -070086 std::chrono::duration<float> diff =
Brad Bishopa098a372022-05-05 15:19:04 -040087 std::chrono::steady_clock::now() - processStartTime;
88 std::cout << std::setw(50) << processName << " scan took "
Ed Tanous60520632018-06-11 17:46:52 -070089 << diff.count() << " seconds\n";
90
91 // If we're the last outstanding caller globally, calculate the
92 // time it took
Brad Bishopa098a372022-05-05 15:19:04 -040093 if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
Ed Tanous60520632018-06-11 17:46:52 -070094 {
Brad Bishopa098a372022-05-05 15:19:04 -040095 diff = std::chrono::steady_clock::now() - *globalStartTime;
Ed Tanous60520632018-06-11 17:46:52 -070096 std::cout << "Total scan took " << diff.count()
97 << " seconds to complete\n";
98 }
Matt Spinleraecabe82018-09-19 13:25:42 -050099#endif
Ed Tanous60520632018-06-11 17:46:52 -0700100 }
Brad Bishopa098a372022-05-05 15:19:04 -0400101 sdbusplus::asio::connection* systemBus;
Ed Tanous21c60592020-08-17 23:43:46 -0700102 boost::asio::io_context& io;
Brad Bishopa098a372022-05-05 15:19:04 -0400103 std::string processName;
Matt Spinler11401e22019-04-08 13:13:25 -0500104 AssociationMaps& assocMaps;
Matt Spinleraecabe82018-09-19 13:25:42 -0500105#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700106 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400107 globalStartTime;
108 std::chrono::time_point<std::chrono::steady_clock> processStartTime;
Matt Spinleraecabe82018-09-19 13:25:42 -0500109#endif
Ed Tanous60520632018-06-11 17:46:52 -0700110};
111
Brad Bishopa098a372022-05-05 15:19:04 -0400112void doAssociations(sdbusplus::asio::connection* systemBus,
113 InterfaceMapType& interfaceMap,
114 sdbusplus::asio::object_server& objectServer,
115 const std::string& processName, const std::string& path,
116 int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700117{
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100118 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400119 systemBus->async_method_call(
120 [&objectServer, path, processName, &interfaceMap, systemBus,
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100121 timeoutRetries](
Matt Spinler937a2322019-01-23 13:54:22 -0600122 const boost::system::error_code ec,
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500123 const std::variant<std::vector<Association>>& variantAssociations) {
Ed Tanous60520632018-06-11 17:46:52 -0700124 if (ec)
125 {
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100126 if (ec.value() == boost::system::errc::timed_out &&
127 timeoutRetries < maxTimeoutRetries)
128 {
Brad Bishopa098a372022-05-05 15:19:04 -0400129 doAssociations(systemBus, interfaceMap, objectServer,
130 processName, path, timeoutRetries + 1);
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100131 return;
132 }
Ed Tanous60520632018-06-11 17:46:52 -0700133 std::cerr << "Error getting associations from " << path << "\n";
134 }
135 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500136 std::get<std::vector<Association>>(variantAssociations);
Andrew Geissler4511b332019-02-21 15:40:40 -0600137 associationChanged(objectServer, associations, path, processName,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500138 interfaceMap, associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700139 },
140 processName, path, "org.freedesktop.DBus.Properties", "Get",
John Wangd0cf9422019-09-17 16:01:34 +0800141 assocDefsInterface, assocDefsProperty);
Ed Tanous60520632018-06-11 17:46:52 -0700142}
143
Brad Bishopa098a372022-05-05 15:19:04 -0400144void doIntrospect(sdbusplus::asio::connection* systemBus,
145 std::shared_ptr<InProgressIntrospect> transaction,
146 InterfaceMapType& interfaceMap,
147 sdbusplus::asio::object_server& objectServer,
148 std::string path, int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700149{
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800150 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400151 systemBus->async_method_call(
152 [&interfaceMap, &objectServer, transaction, path, systemBus,
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800153 timeoutRetries](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400154 const std::string& introspectXml) {
Ed Tanous60520632018-06-11 17:46:52 -0700155 if (ec)
156 {
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800157 if (ec.value() == boost::system::errc::timed_out &&
158 timeoutRetries < maxTimeoutRetries)
159 {
Brad Bishopa098a372022-05-05 15:19:04 -0400160 doIntrospect(systemBus, transaction, interfaceMap,
161 objectServer, path, timeoutRetries + 1);
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800162 return;
163 }
Ed Tanous60520632018-06-11 17:46:52 -0700164 std::cerr << "Introspect call failed with error: " << ec << ", "
165 << ec.message()
Brad Bishopa098a372022-05-05 15:19:04 -0400166 << " on process: " << transaction->processName
Ed Tanous60520632018-06-11 17:46:52 -0700167 << " path: " << path << "\n";
168 return;
169 }
170
171 tinyxml2::XMLDocument doc;
172
Brad Bishopa098a372022-05-05 15:19:04 -0400173 tinyxml2::XMLError e = doc.Parse(introspectXml.c_str());
Ed Tanous60520632018-06-11 17:46:52 -0700174 if (e != tinyxml2::XMLError::XML_SUCCESS)
175 {
176 std::cerr << "XML parsing failed\n";
177 return;
178 }
179
180 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
181 if (pRoot == nullptr)
182 {
183 std::cerr << "XML document did not contain any data\n";
184 return;
185 }
Brad Bishopa098a372022-05-05 15:19:04 -0400186 auto& thisPathMap = interfaceMap[path];
Ed Tanous60520632018-06-11 17:46:52 -0700187 tinyxml2::XMLElement* pElement =
188 pRoot->FirstChildElement("interface");
189 while (pElement != nullptr)
190 {
Brad Bishopa098a372022-05-05 15:19:04 -0400191 const char* ifaceName = pElement->Attribute("name");
192 if (ifaceName == nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700193 {
194 continue;
195 }
196
Brad Bishopa098a372022-05-05 15:19:04 -0400197 thisPathMap[transaction->processName].emplace(ifaceName);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800198
Brad Bishopa098a372022-05-05 15:19:04 -0400199 if (std::strcmp(ifaceName, assocDefsInterface) == 0)
Ed Tanous60520632018-06-11 17:46:52 -0700200 {
Brad Bishopa098a372022-05-05 15:19:04 -0400201 doAssociations(systemBus, interfaceMap, objectServer,
202 transaction->processName, path);
Ed Tanous60520632018-06-11 17:46:52 -0700203 }
Ed Tanous60520632018-06-11 17:46:52 -0700204
205 pElement = pElement->NextSiblingElement("interface");
206 }
207
Matt Spinler11401e22019-04-08 13:13:25 -0500208 // Check if this new path has a pending association that can
209 // now be completed.
Brad Bishopa098a372022-05-05 15:19:04 -0400210 checkIfPendingAssociation(path, interfaceMap,
Matt Spinler11401e22019-04-08 13:13:25 -0500211 transaction->assocMaps, objectServer);
212
Ed Tanous50232cd2018-11-12 11:34:43 -0800213 pElement = pRoot->FirstChildElement("node");
214 while (pElement != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700215 {
Brad Bishopa098a372022-05-05 15:19:04 -0400216 const char* childPath = pElement->Attribute("name");
217 if (childPath != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700218 {
Brad Bishopa098a372022-05-05 15:19:04 -0400219 std::string parentPath(path);
220 if (parentPath == "/")
Ed Tanous60520632018-06-11 17:46:52 -0700221 {
Brad Bishopa098a372022-05-05 15:19:04 -0400222 parentPath.clear();
Ed Tanous60520632018-06-11 17:46:52 -0700223 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800224
Brad Bishopa098a372022-05-05 15:19:04 -0400225 doIntrospect(systemBus, transaction, interfaceMap,
226 objectServer, parentPath + "/" + childPath);
Ed Tanous60520632018-06-11 17:46:52 -0700227 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800228 pElement = pElement->NextSiblingElement("node");
Ed Tanous60520632018-06-11 17:46:52 -0700229 }
230 },
Brad Bishopa098a372022-05-05 15:19:04 -0400231 transaction->processName, path, "org.freedesktop.DBus.Introspectable",
Ed Tanous60520632018-06-11 17:46:52 -0700232 "Introspect");
233}
234
Brad Bishopa098a372022-05-05 15:19:04 -0400235void startNewIntrospect(
236 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
237 InterfaceMapType& interfaceMap, const std::string& processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500238 AssociationMaps& assocMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500239#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700240 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400241 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500242#endif
Ed Tanous60520632018-06-11 17:46:52 -0700243 sdbusplus::asio::object_server& objectServer)
244{
Brad Bishopa098a372022-05-05 15:19:04 -0400245 if (needToIntrospect(processName, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700246 {
Ed Tanous60520632018-06-11 17:46:52 -0700247 std::shared_ptr<InProgressIntrospect> transaction =
Brad Bishopa098a372022-05-05 15:19:04 -0400248 std::make_shared<InProgressIntrospect>(systemBus, io, processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500249 assocMaps
Matt Spinleraecabe82018-09-19 13:25:42 -0500250#ifdef DEBUG
251 ,
Brad Bishopa098a372022-05-05 15:19:04 -0400252 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -0500253#endif
254 );
Ed Tanous60520632018-06-11 17:46:52 -0700255
Brad Bishopa098a372022-05-05 15:19:04 -0400256 doIntrospect(systemBus, transaction, interfaceMap, objectServer, "/");
Ed Tanous60520632018-06-11 17:46:52 -0700257 }
258}
259
260// TODO(ed) replace with std::set_intersection once c++17 is available
261template <class InputIt1, class InputIt2>
262bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
263{
264 while (first1 != last1 && first2 != last2)
265 {
266 if (*first1 < *first2)
267 {
268 ++first1;
269 continue;
270 }
271 if (*first2 < *first1)
272 {
273 ++first2;
274 continue;
275 }
276 return true;
277 }
278 return false;
279}
280
281void doListNames(
Brad Bishopa098a372022-05-05 15:19:04 -0400282 boost::asio::io_context& io, InterfaceMapType& interfaceMap,
283 sdbusplus::asio::connection* systemBus,
284 boost::container::flat_map<std::string, std::string>& nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500285 AssociationMaps& assocMaps, sdbusplus::asio::object_server& objectServer)
Ed Tanous60520632018-06-11 17:46:52 -0700286{
Brad Bishopa098a372022-05-05 15:19:04 -0400287 systemBus->async_method_call(
288 [&io, &interfaceMap, &nameOwners, &objectServer, systemBus,
Matt Spinler11401e22019-04-08 13:13:25 -0500289 &assocMaps](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400290 std::vector<std::string> processNames) {
Ed Tanous60520632018-06-11 17:46:52 -0700291 if (ec)
292 {
293 std::cerr << "Error getting names: " << ec << "\n";
294 std::exit(EXIT_FAILURE);
295 return;
296 }
Ed Tanous60520632018-06-11 17:46:52 -0700297 // Try to make startup consistent
Brad Bishopa098a372022-05-05 15:19:04 -0400298 std::sort(processNames.begin(), processNames.end());
Matt Spinleraecabe82018-09-19 13:25:42 -0500299#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700300 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400301 globalStartTime = std::make_shared<
Ed Tanous60520632018-06-11 17:46:52 -0700302 std::chrono::time_point<std::chrono::steady_clock>>(
303 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500304#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400305 for (const std::string& processName : processNames)
Ed Tanous60520632018-06-11 17:46:52 -0700306 {
Brad Bishopa098a372022-05-05 15:19:04 -0400307 if (needToIntrospect(processName, serviceAllowList,
Brad Bishopf944a452022-05-05 15:06:46 -0400308 serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700309 {
Brad Bishopa098a372022-05-05 15:19:04 -0400310 startNewIntrospect(systemBus, io, interfaceMap, processName,
311 assocMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500312#ifdef DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400313 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500314#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400315 objectServer);
316 updateOwners(systemBus, nameOwners, processName);
Ed Tanous60520632018-06-11 17:46:52 -0700317 }
318 }
319 },
320 "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
321 "ListNames");
322}
323
Matt Spinlerdd945862018-09-07 12:41:05 -0500324void splitArgs(const std::string& stringArgs,
325 boost::container::flat_set<std::string>& listArgs)
326{
327 std::istringstream args;
328 std::string arg;
329
330 args.str(stringArgs);
331
332 while (!args.eof())
333 {
334 args >> arg;
335 if (!arg.empty())
336 {
337 listArgs.insert(arg);
338 }
339 }
340}
341
Matt Spinler47c09752018-11-29 14:54:13 -0600342void addObjectMapResult(
Brad Bishopa098a372022-05-05 15:19:04 -0400343 std::vector<InterfaceMapType::value_type>& objectMap,
Matt Spinler9f0958e2018-09-11 08:26:10 -0500344 const std::string& objectPath,
345 const std::pair<std::string, boost::container::flat_set<std::string>>&
346 interfaceMap)
347{
348 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600349 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500350 // If an entry for the object path already exists, just add the
351 // service name and interfaces to that entry, otherwise create
352 // a new entry.
353 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600354 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500355 [&objectPath](const auto& i) { return objectPath == i.first; });
356
Matt Spinler47c09752018-11-29 14:54:13 -0600357 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500358 {
359 entry->second.emplace(interfaceMap);
360 }
361 else
362 {
Brad Bishopa098a372022-05-05 15:19:04 -0400363 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500364 object.first = objectPath;
365 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600366 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500367 }
368}
369
Matt Spinlera82779f2019-01-09 12:39:42 -0600370// Remove parents of the passed in path that:
371// 1) Only have the 3 default interfaces on them
372// - Means D-Bus created these, not application code,
373// with the Properties, Introspectable, and Peer ifaces
374// 2) Have no other child for this owner
375void removeUnneededParents(const std::string& objectPath,
376 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400377 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600378{
379 auto parent = objectPath;
380
381 while (true)
382 {
383 auto pos = parent.find_last_of('/');
384 if ((pos == std::string::npos) || (pos == 0))
385 {
386 break;
387 }
388 parent = parent.substr(0, pos);
389
Brad Bishopa098a372022-05-05 15:19:04 -0400390 auto parentIt = interfaceMap.find(parent);
391 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600392 {
393 break;
394 }
395
Brad Bishopa098a372022-05-05 15:19:04 -0400396 auto ifacesIt = parentIt->second.find(owner);
397 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600398 {
399 break;
400 }
401
Brad Bishopa098a372022-05-05 15:19:04 -0400402 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600403 {
404 break;
405 }
406
Brad Bishopa098a372022-05-05 15:19:04 -0400407 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600408
409 // Remove this parent if there isn't a remaining child on this owner
410 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400411 interfaceMap.begin(), interfaceMap.end(),
412 [&owner, &childPath](const auto& entry) {
413 return boost::starts_with(entry.first, childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600414 (entry.second.find(owner) != entry.second.end());
415 });
416
Brad Bishopa098a372022-05-05 15:19:04 -0400417 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600418 {
Brad Bishopa098a372022-05-05 15:19:04 -0400419 parentIt->second.erase(ifacesIt);
420 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600421 {
Brad Bishopa098a372022-05-05 15:19:04 -0400422 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600423 }
424 }
425 else
426 {
427 break;
428 }
429 }
430}
431
Brad Bishopa098a372022-05-05 15:19:04 -0400432std::vector<InterfaceMapType::value_type>
433 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700434 std::vector<std::string>& interfaces)
435{
436 // Interfaces need to be sorted for intersect to function
437 std::sort(interfaces.begin(), interfaces.end());
438
Brad Bishopa098a372022-05-05 15:19:04 -0400439 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700440 {
Brad Bishopa098a372022-05-05 15:19:04 -0400441 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700442 }
Brad Bishopa098a372022-05-05 15:19:04 -0400443 if (reqPath.size() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700444 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300445 throw sdbusplus::xyz::openbmc_project::Common::Error::
446 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700447 }
448
Brad Bishopa098a372022-05-05 15:19:04 -0400449 std::vector<InterfaceMapType::value_type> ret;
450 for (auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700451 {
Brad Bishopa098a372022-05-05 15:19:04 -0400452 auto& thisPath = objectPath.first;
453 if (boost::starts_with(reqPath, thisPath) && (reqPath != thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700454 {
455 if (interfaces.empty())
456 {
Brad Bishopa098a372022-05-05 15:19:04 -0400457 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700458 }
459 else
460 {
Brad Bishopa098a372022-05-05 15:19:04 -0400461 for (auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700462 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700463 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400464 interfaceMap.second.begin(),
465 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700466 {
Brad Bishopa098a372022-05-05 15:19:04 -0400467 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700468 }
469 }
470 }
471 }
472 }
473
474 return ret;
475}
476
477boost::container::flat_map<std::string, boost::container::flat_set<std::string>>
Brad Bishopa098a372022-05-05 15:19:04 -0400478 getObject(const InterfaceMapType& interfaceMap, const std::string& path,
Ed Tanous0a13c762021-09-28 13:29:25 -0700479 std::vector<std::string>& interfaces)
480{
481 boost::container::flat_map<std::string,
482 boost::container::flat_set<std::string>>
483 results;
484
485 // Interfaces need to be sorted for intersect to function
486 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400487 auto pathRef = interfaceMap.find(path);
488 if (pathRef == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700489 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300490 throw sdbusplus::xyz::openbmc_project::Common::Error::
491 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700492 }
493 if (interfaces.empty())
494 {
Brad Bishopa098a372022-05-05 15:19:04 -0400495 return pathRef->second;
Ed Tanous0a13c762021-09-28 13:29:25 -0700496 }
Brad Bishopa098a372022-05-05 15:19:04 -0400497 for (auto& interfaceMap : pathRef->second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700498 {
499 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400500 interfaceMap.second.begin(), interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700501 {
Brad Bishopa098a372022-05-05 15:19:04 -0400502 results.emplace(interfaceMap.first, interfaceMap.second);
Ed Tanous0a13c762021-09-28 13:29:25 -0700503 }
504 }
505
506 if (results.empty())
507 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300508 throw sdbusplus::xyz::openbmc_project::Common::Error::
509 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700510 }
511
512 return results;
513}
514
Brad Bishopa098a372022-05-05 15:19:04 -0400515std::vector<InterfaceMapType::value_type>
516 getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700517 int32_t depth, std::vector<std::string>& interfaces)
518{
519 if (depth <= 0)
520 {
521 depth = std::numeric_limits<int32_t>::max();
522 }
523 // Interfaces need to be sorted for intersect to function
524 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400525 std::vector<InterfaceMapType::value_type> ret;
Ed Tanous0a13c762021-09-28 13:29:25 -0700526
Brad Bishopa098a372022-05-05 15:19:04 -0400527 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700528 {
Brad Bishopa098a372022-05-05 15:19:04 -0400529 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700530 }
Brad Bishopa098a372022-05-05 15:19:04 -0400531 if (reqPath.size() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700532 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300533 throw sdbusplus::xyz::openbmc_project::Common::Error::
534 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700535 }
536
Brad Bishopa098a372022-05-05 15:19:04 -0400537 for (auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700538 {
Brad Bishopa098a372022-05-05 15:19:04 -0400539 auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700540
Brad Bishopa098a372022-05-05 15:19:04 -0400541 if (thisPath == reqPath)
Ed Tanous0a13c762021-09-28 13:29:25 -0700542 {
543 continue;
544 }
545
Brad Bishopa098a372022-05-05 15:19:04 -0400546 if (boost::starts_with(thisPath, reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700547 {
548 // count the number of slashes past the search term
Brad Bishopa098a372022-05-05 15:19:04 -0400549 int32_t thisDepth = std::count(thisPath.begin() + reqPath.size(),
550 thisPath.end(), '/');
551 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700552 {
Brad Bishopa098a372022-05-05 15:19:04 -0400553 for (auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700554 {
555 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400556 interfaceMap.second.begin(),
557 interfaceMap.second.end()) ||
Ed Tanous0a13c762021-09-28 13:29:25 -0700558 interfaces.empty())
559 {
Brad Bishopa098a372022-05-05 15:19:04 -0400560 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700561 }
562 }
563 }
564 }
565 }
566
567 return ret;
568}
569
Brad Bishopa098a372022-05-05 15:19:04 -0400570std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
571 std::string reqPath, int32_t depth,
572 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700573{
574 if (depth <= 0)
575 {
576 depth = std::numeric_limits<int32_t>::max();
577 }
578 // Interfaces need to be sorted for intersect to function
579 std::sort(interfaces.begin(), interfaces.end());
580 std::vector<std::string> ret;
581
Brad Bishopa098a372022-05-05 15:19:04 -0400582 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700583 {
Brad Bishopa098a372022-05-05 15:19:04 -0400584 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700585 }
Brad Bishopa098a372022-05-05 15:19:04 -0400586 if (reqPath.size() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700587 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300588 throw sdbusplus::xyz::openbmc_project::Common::Error::
589 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700590 }
591
Brad Bishopa098a372022-05-05 15:19:04 -0400592 for (auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700593 {
Brad Bishopa098a372022-05-05 15:19:04 -0400594 auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700595
Brad Bishopa098a372022-05-05 15:19:04 -0400596 if (thisPath == reqPath)
Ed Tanous0a13c762021-09-28 13:29:25 -0700597 {
598 continue;
599 }
600
Brad Bishopa098a372022-05-05 15:19:04 -0400601 if (boost::starts_with(thisPath, reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700602 {
603 // count the number of slashes past the search term
Brad Bishopa098a372022-05-05 15:19:04 -0400604 int thisDepth = std::count(thisPath.begin() + reqPath.size(),
605 thisPath.end(), '/');
606 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700607 {
608 bool add = interfaces.empty();
Brad Bishopa098a372022-05-05 15:19:04 -0400609 for (auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700610 {
611 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400612 interfaceMap.second.begin(),
613 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700614 {
615 add = true;
616 break;
617 }
618 }
619 if (add)
620 {
621 // TODO(ed) this is a copy
Brad Bishopa098a372022-05-05 15:19:04 -0400622 ret.emplace_back(thisPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700623 }
624 }
625 }
626 }
627
628 return ret;
629}
630
Ed Tanous60520632018-06-11 17:46:52 -0700631int main(int argc, char** argv)
632{
Matt Spinlerdd945862018-09-07 12:41:05 -0500633 auto options = ArgumentParser(argc, argv);
Ed Tanous21c60592020-08-17 23:43:46 -0700634 boost::asio::io_context io;
Brad Bishopa098a372022-05-05 15:19:04 -0400635 std::shared_ptr<sdbusplus::asio::connection> systemBus =
Ed Tanous60520632018-06-11 17:46:52 -0700636 std::make_shared<sdbusplus::asio::connection>(io);
637
Brad Bishopf944a452022-05-05 15:06:46 -0400638 splitArgs(options["service-namespaces"], serviceAllowList);
639 splitArgs(options["service-blacklists"], serviceDenyList);
Matt Spinlerdd945862018-09-07 12:41:05 -0500640
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800641 // TODO(Ed) Remove this once all service files are updated to not use this.
642 // For now, simply squash the input, and ignore it.
Brad Bishopf944a452022-05-05 15:06:46 -0400643 boost::container::flat_set<std::string> ifaceAllowlist;
644 splitArgs(options["interface-namespaces"], ifaceAllowlist);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800645
Brad Bishopa098a372022-05-05 15:19:04 -0400646 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700647
648 // Construct a signal set registered for process termination.
649 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400650 signals.async_wait(
651 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700652
Brad Bishopa098a372022-05-05 15:19:04 -0400653 InterfaceMapType interfaceMap;
654 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700655
656 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400657 nameChangeHandler = [&interfaceMap, &io, &nameOwners, &server,
658 systemBus](sdbusplus::message::message& message) {
659 std::string name; // well-known
660 std::string oldOwner; // unique-name
661 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700662
Brad Bishopa098a372022-05-05 15:19:04 -0400663 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700664
Brad Bishopa098a372022-05-05 15:19:04 -0400665 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700666 {
Brad Bishopa098a372022-05-05 15:19:04 -0400667 processNameChangeDelete(nameOwners, name, oldOwner,
668 interfaceMap, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700669 }
670
Brad Bishopa098a372022-05-05 15:19:04 -0400671 if (!newOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700672 {
Matt Spinleraecabe82018-09-19 13:25:42 -0500673#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700674 auto transaction = std::make_shared<
675 std::chrono::time_point<std::chrono::steady_clock>>(
676 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500677#endif
Ed Tanous60520632018-06-11 17:46:52 -0700678 // New daemon added
Brad Bishopf944a452022-05-05 15:06:46 -0400679 if (needToIntrospect(name, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700680 {
Brad Bishopa098a372022-05-05 15:19:04 -0400681 nameOwners[newOwner] = name;
682 startNewIntrospect(systemBus.get(), io, interfaceMap, name,
683 associationMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500684#ifdef DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400685 transaction,
Matt Spinleraecabe82018-09-19 13:25:42 -0500686#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400687 server);
Ed Tanous60520632018-06-11 17:46:52 -0700688 }
689 }
690 };
691
692 sdbusplus::bus::match::match nameOwnerChanged(
Brad Bishopa098a372022-05-05 15:19:04 -0400693 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700694 sdbusplus::bus::match::rules::nameOwnerChanged(), nameChangeHandler);
695
696 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400697 interfacesAddedHandler = [&interfaceMap, &nameOwners, &server](
Ed Tanous60520632018-06-11 17:46:52 -0700698 sdbusplus::message::message& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400699 sdbusplus::message::object_path objPath;
700 InterfacesAdded interfacesAdded;
701 message.read(objPath, interfacesAdded);
702 std::string wellKnown;
703 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700704 {
705 return; // only introspect well-known
706 }
Brad Bishopa098a372022-05-05 15:19:04 -0400707 if (needToIntrospect(wellKnown, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700708 {
Brad Bishopa098a372022-05-05 15:19:04 -0400709 processInterfaceAdded(interfaceMap, objPath, interfacesAdded,
710 wellKnown, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700711 }
712 };
713
714 sdbusplus::bus::match::match interfacesAdded(
Brad Bishopa098a372022-05-05 15:19:04 -0400715 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700716 sdbusplus::bus::match::rules::interfacesAdded(),
717 interfacesAddedHandler);
718
719 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400720 interfacesRemovedHandler = [&interfaceMap, &nameOwners, &server](
Ed Tanous60520632018-06-11 17:46:52 -0700721 sdbusplus::message::message& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400722 sdbusplus::message::object_path objPath;
723 std::vector<std::string> interfacesRemoved;
724 message.read(objPath, interfacesRemoved);
725 auto connectionMap = interfaceMap.find(objPath.str);
726 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700727 {
728 return;
729 }
730
731 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400732 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700733 {
734 return;
735 }
Brad Bishopa098a372022-05-05 15:19:04 -0400736 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700737 {
Brad Bishopa098a372022-05-05 15:19:04 -0400738 auto interfaceSet = connectionMap->second.find(sender);
739 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700740 {
741 continue;
742 }
743
John Wangd0cf9422019-09-17 16:01:34 +0800744 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700745 {
Brad Bishopa098a372022-05-05 15:19:04 -0400746 removeAssociation(objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500747 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700748 }
749
Brad Bishopa098a372022-05-05 15:19:04 -0400750 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500751
Brad Bishopa098a372022-05-05 15:19:04 -0400752 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700753 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500754 // If this was the last interface on this connection,
755 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400756 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500757
758 // Instead of checking if every single path is the endpoint
759 // of an association that needs to be moved to pending,
760 // only check when the only remaining owner of this path is
761 // ourself, which would be because we still own the
762 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400763 if ((connectionMap->second.size() == 1) &&
764 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400765 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500766 {
767 // Remove the 2 association D-Bus paths and move the
768 // association to pending.
Brad Bishopa098a372022-05-05 15:19:04 -0400769 moveAssociationToPending(objPath.str, associationMaps,
Matt Spinler9c3d2852019-04-08 15:57:19 -0500770 server);
771 }
Ed Tanous60520632018-06-11 17:46:52 -0700772 }
773 }
774 // If this was the last connection on this object path,
775 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400776 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700777 {
Brad Bishopa098a372022-05-05 15:19:04 -0400778 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700779 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600780
Brad Bishopa098a372022-05-05 15:19:04 -0400781 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700782 };
783
784 sdbusplus::bus::match::match interfacesRemoved(
Brad Bishopa098a372022-05-05 15:19:04 -0400785 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700786 sdbusplus::bus::match::rules::interfacesRemoved(),
787 interfacesRemovedHandler);
788
789 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400790 associationChangedHandler = [&server, &nameOwners, &interfaceMap](
Matt Spinler8f876a52019-04-15 13:22:50 -0500791 sdbusplus::message::message& message) {
792 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500793 boost::container::flat_map<std::string,
794 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500795 values;
796 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800797 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500798 if (prop != values.end())
799 {
800 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500801 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500802
Brad Bishopa098a372022-05-05 15:19:04 -0400803 std::string wellKnown;
804 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500805 {
806 return;
Ed Tanous60520632018-06-11 17:46:52 -0700807 }
Matt Spinler8f876a52019-04-15 13:22:50 -0500808 associationChanged(server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400809 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500810 }
811 };
812 sdbusplus::bus::match::match assocChangedMatch(
Brad Bishopa098a372022-05-05 15:19:04 -0400813 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700814 sdbusplus::bus::match::rules::interface(
815 "org.freedesktop.DBus.Properties") +
816 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500817 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
818 associationChangedHandler);
819
Ed Tanous60520632018-06-11 17:46:52 -0700820 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400821 server.add_interface("/xyz/openbmc_project/object_mapper",
822 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700823
824 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400825 "GetAncestors", [&interfaceMap](std::string& reqPath,
826 std::vector<std::string>& interfaces) {
827 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700828 });
829
830 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400831 "GetObject", [&interfaceMap](const std::string& path,
832 std::vector<std::string>& interfaces) {
833 return getObject(interfaceMap, path, interfaces);
834 });
835
836 iface->register_method(
837 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700838 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400839 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700840 });
841
842 iface->register_method(
843 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400844 [&interfaceMap](std::string& reqPath, int32_t depth,
845 std::vector<std::string>& interfaces) {
846 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700847 });
848
849 iface->initialize();
850
851 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400852 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500853 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700854 });
855
Brad Bishopa098a372022-05-05 15:19:04 -0400856 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500857
Ed Tanous60520632018-06-11 17:46:52 -0700858 io.run();
859}