blob: 65de2ad45d7fcf9246460ae4215d2a8e05383ef3 [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>
Brad Bishopea119462022-05-31 20:32:04 -040018#include <exception>
Brad Bishop23520882022-05-26 21:39:53 -040019#include <iomanip>
20#include <iostream>
Brad Bishop1f623802022-05-31 18:22:10 -040021#include <utility>
Brad Bishop23520882022-05-26 21:39:53 -040022
Matt Spinlere2359fb2019-04-05 14:11:33 -050023AssociationMaps associationMaps;
Matt Spinler937a2322019-01-23 13:54:22 -060024
Brad Bishopf944a452022-05-05 15:06:46 -040025static AllowDenyList serviceAllowList;
26static AllowDenyList serviceDenyList;
Matt Spinlerdd945862018-09-07 12:41:05 -050027
Brad Bishopa098a372022-05-05 15:19:04 -040028void updateOwners(sdbusplus::asio::connection* conn,
29 boost::container::flat_map<std::string, std::string>& owners,
30 const std::string& newObject)
Ed Tanous60520632018-06-11 17:46:52 -070031{
Brad Bishopa098a372022-05-05 15:19:04 -040032 if (boost::starts_with(newObject, ":"))
Ed Tanous60520632018-06-11 17:46:52 -070033 {
34 return;
35 }
36 conn->async_method_call(
Brad Bishopa098a372022-05-05 15:19:04 -040037 [&, newObject](const boost::system::error_code ec,
38 const std::string& nameOwner) {
Ed Tanous60520632018-06-11 17:46:52 -070039 if (ec)
40 {
Brad Bishopa098a372022-05-05 15:19:04 -040041 std::cerr << "Error getting owner of " << newObject << " : "
Ed Tanous60520632018-06-11 17:46:52 -070042 << ec << "\n";
43 return;
44 }
Brad Bishopa098a372022-05-05 15:19:04 -040045 owners[nameOwner] = newObject;
Ed Tanous60520632018-06-11 17:46:52 -070046 },
47 "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner",
Brad Bishopa098a372022-05-05 15:19:04 -040048 newObject);
Ed Tanous60520632018-06-11 17:46:52 -070049}
50
Brad Bishopa098a372022-05-05 15:19:04 -040051void sendIntrospectionCompleteSignal(sdbusplus::asio::connection* systemBus,
52 const std::string& processName)
Ed Tanous60520632018-06-11 17:46:52 -070053{
54 // TODO(ed) This signal doesn't get exposed properly in the
55 // introspect right now. Find out how to register signals in
56 // sdbusplus
Brad Bishopa098a372022-05-05 15:19:04 -040057 sdbusplus::message::message m = systemBus->new_signal(
Brad Bishopa02cd542021-10-12 19:12:42 -040058 "/xyz/openbmc_project/object_mapper",
59 "xyz.openbmc_project.ObjectMapper.Private", "IntrospectionComplete");
Brad Bishopa098a372022-05-05 15:19:04 -040060 m.append(processName);
Ed Tanous60520632018-06-11 17:46:52 -070061 m.signal_send();
62}
63
64struct InProgressIntrospect
65{
Brad Bishop1f623802022-05-31 18:22:10 -040066 InProgressIntrospect() = delete;
67 InProgressIntrospect(const InProgressIntrospect&) = delete;
68 InProgressIntrospect(InProgressIntrospect&&) = delete;
69 InProgressIntrospect& operator=(const InProgressIntrospect&) = delete;
70 InProgressIntrospect& operator=(InProgressIntrospect&&) = delete;
Ed Tanous60520632018-06-11 17:46:52 -070071 InProgressIntrospect(
Brad Bishopa098a372022-05-05 15:19:04 -040072 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
73 const std::string& processName, AssociationMaps& am
Matt Spinleraecabe82018-09-19 13:25:42 -050074#ifdef DEBUG
75 ,
Ed Tanous60520632018-06-11 17:46:52 -070076 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -040077 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -050078#endif
79 ) :
Brad Bishopa098a372022-05-05 15:19:04 -040080 systemBus(systemBus),
81 io(io), processName(processName), assocMaps(am)
Matt Spinleraecabe82018-09-19 13:25:42 -050082#ifdef DEBUG
83 ,
Brad Bishop1f623802022-05-31 18:22:10 -040084 globalStartTime(std::move(globalStartTime)),
Brad Bishopa098a372022-05-05 15:19:04 -040085 processStartTime(std::chrono::steady_clock::now())
Matt Spinleraecabe82018-09-19 13:25:42 -050086#endif
Brad Bishop23520882022-05-26 21:39:53 -040087 {}
Ed Tanous60520632018-06-11 17:46:52 -070088 ~InProgressIntrospect()
89 {
Brad Bishopea119462022-05-31 20:32:04 -040090 try
Ed Tanous60520632018-06-11 17:46:52 -070091 {
Brad Bishopea119462022-05-31 20:32:04 -040092 sendIntrospectionCompleteSignal(systemBus, processName);
93#ifdef DEBUG
94 std::chrono::duration<float> diff =
95 std::chrono::steady_clock::now() - processStartTime;
96 std::cout << std::setw(50) << processName << " scan took "
97 << diff.count() << " seconds\n";
98
99 // If we're the last outstanding caller globally, calculate the
100 // time it took
101 if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
102 {
103 diff = std::chrono::steady_clock::now() - *globalStartTime;
104 std::cout << "Total scan took " << diff.count()
105 << " seconds to complete\n";
106 }
Matt Spinleraecabe82018-09-19 13:25:42 -0500107#endif
Brad Bishopea119462022-05-31 20:32:04 -0400108 }
109 catch (const std::exception& e)
110 {
111 std::cerr
112 << "Terminating, unhandled exception while introspecting: "
113 << e.what() << "\n";
114 std::terminate();
115 }
116 catch (...)
117 {
118 std::cerr
119 << "Terminating, unhandled exception while introspecting\n";
120 std::terminate();
121 }
Ed Tanous60520632018-06-11 17:46:52 -0700122 }
Brad Bishopa098a372022-05-05 15:19:04 -0400123 sdbusplus::asio::connection* systemBus;
Ed Tanous21c60592020-08-17 23:43:46 -0700124 boost::asio::io_context& io;
Brad Bishopa098a372022-05-05 15:19:04 -0400125 std::string processName;
Matt Spinler11401e22019-04-08 13:13:25 -0500126 AssociationMaps& assocMaps;
Matt Spinleraecabe82018-09-19 13:25:42 -0500127#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700128 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400129 globalStartTime;
130 std::chrono::time_point<std::chrono::steady_clock> processStartTime;
Matt Spinleraecabe82018-09-19 13:25:42 -0500131#endif
Ed Tanous60520632018-06-11 17:46:52 -0700132};
133
Brad Bishopa098a372022-05-05 15:19:04 -0400134void doAssociations(sdbusplus::asio::connection* systemBus,
135 InterfaceMapType& interfaceMap,
136 sdbusplus::asio::object_server& objectServer,
137 const std::string& processName, const std::string& path,
138 int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700139{
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100140 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400141 systemBus->async_method_call(
142 [&objectServer, path, processName, &interfaceMap, systemBus,
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100143 timeoutRetries](
Matt Spinler937a2322019-01-23 13:54:22 -0600144 const boost::system::error_code ec,
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500145 const std::variant<std::vector<Association>>& variantAssociations) {
Ed Tanous60520632018-06-11 17:46:52 -0700146 if (ec)
147 {
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100148 if (ec.value() == boost::system::errc::timed_out &&
149 timeoutRetries < maxTimeoutRetries)
150 {
Brad Bishopa098a372022-05-05 15:19:04 -0400151 doAssociations(systemBus, interfaceMap, objectServer,
152 processName, path, timeoutRetries + 1);
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100153 return;
154 }
Ed Tanous60520632018-06-11 17:46:52 -0700155 std::cerr << "Error getting associations from " << path << "\n";
156 }
157 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500158 std::get<std::vector<Association>>(variantAssociations);
Andrew Geissler4511b332019-02-21 15:40:40 -0600159 associationChanged(objectServer, associations, path, processName,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500160 interfaceMap, associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700161 },
162 processName, path, "org.freedesktop.DBus.Properties", "Get",
John Wangd0cf9422019-09-17 16:01:34 +0800163 assocDefsInterface, assocDefsProperty);
Ed Tanous60520632018-06-11 17:46:52 -0700164}
165
Brad Bishopa098a372022-05-05 15:19:04 -0400166void doIntrospect(sdbusplus::asio::connection* systemBus,
Brad Bishop1f623802022-05-31 18:22:10 -0400167 const std::shared_ptr<InProgressIntrospect>& transaction,
Brad Bishopa098a372022-05-05 15:19:04 -0400168 InterfaceMapType& interfaceMap,
169 sdbusplus::asio::object_server& objectServer,
Brad Bishop1f623802022-05-31 18:22:10 -0400170 const std::string& path, int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700171{
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800172 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400173 systemBus->async_method_call(
174 [&interfaceMap, &objectServer, transaction, path, systemBus,
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800175 timeoutRetries](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400176 const std::string& introspectXml) {
Ed Tanous60520632018-06-11 17:46:52 -0700177 if (ec)
178 {
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800179 if (ec.value() == boost::system::errc::timed_out &&
180 timeoutRetries < maxTimeoutRetries)
181 {
Brad Bishopa098a372022-05-05 15:19:04 -0400182 doIntrospect(systemBus, transaction, interfaceMap,
183 objectServer, path, timeoutRetries + 1);
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800184 return;
185 }
Ed Tanous60520632018-06-11 17:46:52 -0700186 std::cerr << "Introspect call failed with error: " << ec << ", "
187 << ec.message()
Brad Bishopa098a372022-05-05 15:19:04 -0400188 << " on process: " << transaction->processName
Ed Tanous60520632018-06-11 17:46:52 -0700189 << " path: " << path << "\n";
190 return;
191 }
192
193 tinyxml2::XMLDocument doc;
194
Brad Bishopa098a372022-05-05 15:19:04 -0400195 tinyxml2::XMLError e = doc.Parse(introspectXml.c_str());
Ed Tanous60520632018-06-11 17:46:52 -0700196 if (e != tinyxml2::XMLError::XML_SUCCESS)
197 {
198 std::cerr << "XML parsing failed\n";
199 return;
200 }
201
202 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
203 if (pRoot == nullptr)
204 {
205 std::cerr << "XML document did not contain any data\n";
206 return;
207 }
Brad Bishopa098a372022-05-05 15:19:04 -0400208 auto& thisPathMap = interfaceMap[path];
Ed Tanous60520632018-06-11 17:46:52 -0700209 tinyxml2::XMLElement* pElement =
210 pRoot->FirstChildElement("interface");
211 while (pElement != nullptr)
212 {
Brad Bishopa098a372022-05-05 15:19:04 -0400213 const char* ifaceName = pElement->Attribute("name");
214 if (ifaceName == nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700215 {
216 continue;
217 }
218
Brad Bishopa098a372022-05-05 15:19:04 -0400219 thisPathMap[transaction->processName].emplace(ifaceName);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800220
Brad Bishopa098a372022-05-05 15:19:04 -0400221 if (std::strcmp(ifaceName, assocDefsInterface) == 0)
Ed Tanous60520632018-06-11 17:46:52 -0700222 {
Brad Bishopa098a372022-05-05 15:19:04 -0400223 doAssociations(systemBus, interfaceMap, objectServer,
224 transaction->processName, path);
Ed Tanous60520632018-06-11 17:46:52 -0700225 }
Ed Tanous60520632018-06-11 17:46:52 -0700226
227 pElement = pElement->NextSiblingElement("interface");
228 }
229
Matt Spinler11401e22019-04-08 13:13:25 -0500230 // Check if this new path has a pending association that can
231 // now be completed.
Brad Bishopa098a372022-05-05 15:19:04 -0400232 checkIfPendingAssociation(path, interfaceMap,
Matt Spinler11401e22019-04-08 13:13:25 -0500233 transaction->assocMaps, objectServer);
234
Ed Tanous50232cd2018-11-12 11:34:43 -0800235 pElement = pRoot->FirstChildElement("node");
236 while (pElement != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700237 {
Brad Bishopa098a372022-05-05 15:19:04 -0400238 const char* childPath = pElement->Attribute("name");
239 if (childPath != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700240 {
Brad Bishopa098a372022-05-05 15:19:04 -0400241 std::string parentPath(path);
242 if (parentPath == "/")
Ed Tanous60520632018-06-11 17:46:52 -0700243 {
Brad Bishopa098a372022-05-05 15:19:04 -0400244 parentPath.clear();
Ed Tanous60520632018-06-11 17:46:52 -0700245 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800246
Brad Bishopa098a372022-05-05 15:19:04 -0400247 doIntrospect(systemBus, transaction, interfaceMap,
248 objectServer, parentPath + "/" + childPath);
Ed Tanous60520632018-06-11 17:46:52 -0700249 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800250 pElement = pElement->NextSiblingElement("node");
Ed Tanous60520632018-06-11 17:46:52 -0700251 }
252 },
Brad Bishopa098a372022-05-05 15:19:04 -0400253 transaction->processName, path, "org.freedesktop.DBus.Introspectable",
Ed Tanous60520632018-06-11 17:46:52 -0700254 "Introspect");
255}
256
Brad Bishopa098a372022-05-05 15:19:04 -0400257void startNewIntrospect(
258 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
259 InterfaceMapType& interfaceMap, const std::string& processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500260 AssociationMaps& assocMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500261#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700262 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400263 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500264#endif
Ed Tanous60520632018-06-11 17:46:52 -0700265 sdbusplus::asio::object_server& objectServer)
266{
Brad Bishopa098a372022-05-05 15:19:04 -0400267 if (needToIntrospect(processName, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700268 {
Ed Tanous60520632018-06-11 17:46:52 -0700269 std::shared_ptr<InProgressIntrospect> transaction =
Brad Bishopa098a372022-05-05 15:19:04 -0400270 std::make_shared<InProgressIntrospect>(systemBus, io, processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500271 assocMaps
Matt Spinleraecabe82018-09-19 13:25:42 -0500272#ifdef DEBUG
273 ,
Brad Bishopa098a372022-05-05 15:19:04 -0400274 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -0500275#endif
276 );
Ed Tanous60520632018-06-11 17:46:52 -0700277
Brad Bishopa098a372022-05-05 15:19:04 -0400278 doIntrospect(systemBus, transaction, interfaceMap, objectServer, "/");
Ed Tanous60520632018-06-11 17:46:52 -0700279 }
280}
281
282// TODO(ed) replace with std::set_intersection once c++17 is available
283template <class InputIt1, class InputIt2>
284bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
285{
286 while (first1 != last1 && first2 != last2)
287 {
288 if (*first1 < *first2)
289 {
290 ++first1;
291 continue;
292 }
293 if (*first2 < *first1)
294 {
295 ++first2;
296 continue;
297 }
298 return true;
299 }
300 return false;
301}
302
303void doListNames(
Brad Bishopa098a372022-05-05 15:19:04 -0400304 boost::asio::io_context& io, InterfaceMapType& interfaceMap,
305 sdbusplus::asio::connection* systemBus,
306 boost::container::flat_map<std::string, std::string>& nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500307 AssociationMaps& assocMaps, sdbusplus::asio::object_server& objectServer)
Ed Tanous60520632018-06-11 17:46:52 -0700308{
Brad Bishopa098a372022-05-05 15:19:04 -0400309 systemBus->async_method_call(
310 [&io, &interfaceMap, &nameOwners, &objectServer, systemBus,
Matt Spinler11401e22019-04-08 13:13:25 -0500311 &assocMaps](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400312 std::vector<std::string> processNames) {
Ed Tanous60520632018-06-11 17:46:52 -0700313 if (ec)
314 {
315 std::cerr << "Error getting names: " << ec << "\n";
316 std::exit(EXIT_FAILURE);
317 return;
318 }
Ed Tanous60520632018-06-11 17:46:52 -0700319 // Try to make startup consistent
Brad Bishopa098a372022-05-05 15:19:04 -0400320 std::sort(processNames.begin(), processNames.end());
Matt Spinleraecabe82018-09-19 13:25:42 -0500321#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700322 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400323 globalStartTime = std::make_shared<
Ed Tanous60520632018-06-11 17:46:52 -0700324 std::chrono::time_point<std::chrono::steady_clock>>(
325 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500326#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400327 for (const std::string& processName : processNames)
Ed Tanous60520632018-06-11 17:46:52 -0700328 {
Brad Bishopa098a372022-05-05 15:19:04 -0400329 if (needToIntrospect(processName, serviceAllowList,
Brad Bishopf944a452022-05-05 15:06:46 -0400330 serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700331 {
Brad Bishopa098a372022-05-05 15:19:04 -0400332 startNewIntrospect(systemBus, io, interfaceMap, processName,
333 assocMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500334#ifdef DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400335 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500336#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400337 objectServer);
338 updateOwners(systemBus, nameOwners, processName);
Ed Tanous60520632018-06-11 17:46:52 -0700339 }
340 }
341 },
342 "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
343 "ListNames");
344}
345
Matt Spinlerdd945862018-09-07 12:41:05 -0500346void splitArgs(const std::string& stringArgs,
347 boost::container::flat_set<std::string>& listArgs)
348{
349 std::istringstream args;
350 std::string arg;
351
352 args.str(stringArgs);
353
354 while (!args.eof())
355 {
356 args >> arg;
357 if (!arg.empty())
358 {
359 listArgs.insert(arg);
360 }
361 }
362}
363
Matt Spinler47c09752018-11-29 14:54:13 -0600364void addObjectMapResult(
Brad Bishopa098a372022-05-05 15:19:04 -0400365 std::vector<InterfaceMapType::value_type>& objectMap,
Matt Spinler9f0958e2018-09-11 08:26:10 -0500366 const std::string& objectPath,
367 const std::pair<std::string, boost::container::flat_set<std::string>>&
368 interfaceMap)
369{
370 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600371 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500372 // If an entry for the object path already exists, just add the
373 // service name and interfaces to that entry, otherwise create
374 // a new entry.
375 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600376 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500377 [&objectPath](const auto& i) { return objectPath == i.first; });
378
Matt Spinler47c09752018-11-29 14:54:13 -0600379 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500380 {
381 entry->second.emplace(interfaceMap);
382 }
383 else
384 {
Brad Bishopa098a372022-05-05 15:19:04 -0400385 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500386 object.first = objectPath;
387 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600388 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500389 }
390}
391
Matt Spinlera82779f2019-01-09 12:39:42 -0600392// Remove parents of the passed in path that:
393// 1) Only have the 3 default interfaces on them
394// - Means D-Bus created these, not application code,
395// with the Properties, Introspectable, and Peer ifaces
396// 2) Have no other child for this owner
397void removeUnneededParents(const std::string& objectPath,
398 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400399 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600400{
401 auto parent = objectPath;
402
403 while (true)
404 {
405 auto pos = parent.find_last_of('/');
406 if ((pos == std::string::npos) || (pos == 0))
407 {
408 break;
409 }
410 parent = parent.substr(0, pos);
411
Brad Bishopa098a372022-05-05 15:19:04 -0400412 auto parentIt = interfaceMap.find(parent);
413 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600414 {
415 break;
416 }
417
Brad Bishopa098a372022-05-05 15:19:04 -0400418 auto ifacesIt = parentIt->second.find(owner);
419 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600420 {
421 break;
422 }
423
Brad Bishopa098a372022-05-05 15:19:04 -0400424 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600425 {
426 break;
427 }
428
Brad Bishopa098a372022-05-05 15:19:04 -0400429 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600430
431 // Remove this parent if there isn't a remaining child on this owner
432 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400433 interfaceMap.begin(), interfaceMap.end(),
434 [&owner, &childPath](const auto& entry) {
435 return boost::starts_with(entry.first, childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600436 (entry.second.find(owner) != entry.second.end());
437 });
438
Brad Bishopa098a372022-05-05 15:19:04 -0400439 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600440 {
Brad Bishopa098a372022-05-05 15:19:04 -0400441 parentIt->second.erase(ifacesIt);
442 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600443 {
Brad Bishopa098a372022-05-05 15:19:04 -0400444 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600445 }
446 }
447 else
448 {
449 break;
450 }
451 }
452}
453
Brad Bishopa098a372022-05-05 15:19:04 -0400454std::vector<InterfaceMapType::value_type>
455 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700456 std::vector<std::string>& interfaces)
457{
458 // Interfaces need to be sorted for intersect to function
459 std::sort(interfaces.begin(), interfaces.end());
460
Brad Bishopa098a372022-05-05 15:19:04 -0400461 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700462 {
Brad Bishopa098a372022-05-05 15:19:04 -0400463 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700464 }
Brad Bishop1f623802022-05-31 18:22:10 -0400465 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700466 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300467 throw sdbusplus::xyz::openbmc_project::Common::Error::
468 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700469 }
470
Brad Bishopa098a372022-05-05 15:19:04 -0400471 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400472 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700473 {
Brad Bishop1f623802022-05-31 18:22:10 -0400474 const auto& thisPath = objectPath.first;
Brad Bishopa098a372022-05-05 15:19:04 -0400475 if (boost::starts_with(reqPath, thisPath) && (reqPath != thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700476 {
477 if (interfaces.empty())
478 {
Brad Bishopa098a372022-05-05 15:19:04 -0400479 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700480 }
481 else
482 {
Brad Bishop1f623802022-05-31 18:22:10 -0400483 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700484 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700485 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400486 interfaceMap.second.begin(),
487 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700488 {
Brad Bishopa098a372022-05-05 15:19:04 -0400489 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700490 }
491 }
492 }
493 }
494 }
495
496 return ret;
497}
498
499boost::container::flat_map<std::string, boost::container::flat_set<std::string>>
Brad Bishopa098a372022-05-05 15:19:04 -0400500 getObject(const InterfaceMapType& interfaceMap, const std::string& path,
Ed Tanous0a13c762021-09-28 13:29:25 -0700501 std::vector<std::string>& interfaces)
502{
503 boost::container::flat_map<std::string,
504 boost::container::flat_set<std::string>>
505 results;
506
507 // Interfaces need to be sorted for intersect to function
508 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400509 auto pathRef = interfaceMap.find(path);
510 if (pathRef == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700511 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300512 throw sdbusplus::xyz::openbmc_project::Common::Error::
513 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700514 }
515 if (interfaces.empty())
516 {
Brad Bishopa098a372022-05-05 15:19:04 -0400517 return pathRef->second;
Ed Tanous0a13c762021-09-28 13:29:25 -0700518 }
Brad Bishop1f623802022-05-31 18:22:10 -0400519 for (const auto& interfaceMap : pathRef->second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700520 {
521 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400522 interfaceMap.second.begin(), interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700523 {
Brad Bishopa098a372022-05-05 15:19:04 -0400524 results.emplace(interfaceMap.first, interfaceMap.second);
Ed Tanous0a13c762021-09-28 13:29:25 -0700525 }
526 }
527
528 if (results.empty())
529 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300530 throw sdbusplus::xyz::openbmc_project::Common::Error::
531 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700532 }
533
534 return results;
535}
536
Brad Bishopa098a372022-05-05 15:19:04 -0400537std::vector<InterfaceMapType::value_type>
538 getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700539 int32_t depth, std::vector<std::string>& interfaces)
540{
541 if (depth <= 0)
542 {
543 depth = std::numeric_limits<int32_t>::max();
544 }
545 // Interfaces need to be sorted for intersect to function
546 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400547 std::vector<InterfaceMapType::value_type> ret;
Ed Tanous0a13c762021-09-28 13:29:25 -0700548
Brad Bishopa098a372022-05-05 15:19:04 -0400549 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700550 {
Brad Bishopa098a372022-05-05 15:19:04 -0400551 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700552 }
Brad Bishop1f623802022-05-31 18:22:10 -0400553 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700554 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300555 throw sdbusplus::xyz::openbmc_project::Common::Error::
556 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700557 }
558
Brad Bishop1f623802022-05-31 18:22:10 -0400559 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700560 {
Brad Bishop1f623802022-05-31 18:22:10 -0400561 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700562
Brad Bishopa098a372022-05-05 15:19:04 -0400563 if (thisPath == reqPath)
Ed Tanous0a13c762021-09-28 13:29:25 -0700564 {
565 continue;
566 }
567
Brad Bishopa098a372022-05-05 15:19:04 -0400568 if (boost::starts_with(thisPath, reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700569 {
570 // count the number of slashes past the search term
Brad Bishopa098a372022-05-05 15:19:04 -0400571 int32_t thisDepth = std::count(thisPath.begin() + reqPath.size(),
572 thisPath.end(), '/');
573 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700574 {
Brad Bishop1f623802022-05-31 18:22:10 -0400575 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700576 {
577 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400578 interfaceMap.second.begin(),
579 interfaceMap.second.end()) ||
Ed Tanous0a13c762021-09-28 13:29:25 -0700580 interfaces.empty())
581 {
Brad Bishopa098a372022-05-05 15:19:04 -0400582 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700583 }
584 }
585 }
586 }
587 }
588
589 return ret;
590}
591
Brad Bishopa098a372022-05-05 15:19:04 -0400592std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
593 std::string reqPath, int32_t depth,
594 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700595{
596 if (depth <= 0)
597 {
598 depth = std::numeric_limits<int32_t>::max();
599 }
600 // Interfaces need to be sorted for intersect to function
601 std::sort(interfaces.begin(), interfaces.end());
602 std::vector<std::string> ret;
603
Brad Bishopa098a372022-05-05 15:19:04 -0400604 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700605 {
Brad Bishopa098a372022-05-05 15:19:04 -0400606 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700607 }
Brad Bishop1f623802022-05-31 18:22:10 -0400608 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700609 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300610 throw sdbusplus::xyz::openbmc_project::Common::Error::
611 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700612 }
613
Brad Bishop1f623802022-05-31 18:22:10 -0400614 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700615 {
Brad Bishop1f623802022-05-31 18:22:10 -0400616 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700617
Brad Bishopa098a372022-05-05 15:19:04 -0400618 if (thisPath == reqPath)
Ed Tanous0a13c762021-09-28 13:29:25 -0700619 {
620 continue;
621 }
622
Brad Bishopa098a372022-05-05 15:19:04 -0400623 if (boost::starts_with(thisPath, reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700624 {
625 // count the number of slashes past the search term
Brad Bishopa098a372022-05-05 15:19:04 -0400626 int thisDepth = std::count(thisPath.begin() + reqPath.size(),
627 thisPath.end(), '/');
628 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700629 {
630 bool add = interfaces.empty();
Brad Bishop1f623802022-05-31 18:22:10 -0400631 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700632 {
633 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400634 interfaceMap.second.begin(),
635 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700636 {
637 add = true;
638 break;
639 }
640 }
641 if (add)
642 {
643 // TODO(ed) this is a copy
Brad Bishopa098a372022-05-05 15:19:04 -0400644 ret.emplace_back(thisPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700645 }
646 }
647 }
648 }
649
650 return ret;
651}
652
Ed Tanous60520632018-06-11 17:46:52 -0700653int main(int argc, char** argv)
654{
Matt Spinlerdd945862018-09-07 12:41:05 -0500655 auto options = ArgumentParser(argc, argv);
Ed Tanous21c60592020-08-17 23:43:46 -0700656 boost::asio::io_context io;
Brad Bishopa098a372022-05-05 15:19:04 -0400657 std::shared_ptr<sdbusplus::asio::connection> systemBus =
Ed Tanous60520632018-06-11 17:46:52 -0700658 std::make_shared<sdbusplus::asio::connection>(io);
659
Brad Bishopf944a452022-05-05 15:06:46 -0400660 splitArgs(options["service-namespaces"], serviceAllowList);
661 splitArgs(options["service-blacklists"], serviceDenyList);
Matt Spinlerdd945862018-09-07 12:41:05 -0500662
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800663 // TODO(Ed) Remove this once all service files are updated to not use this.
664 // For now, simply squash the input, and ignore it.
Brad Bishopf944a452022-05-05 15:06:46 -0400665 boost::container::flat_set<std::string> ifaceAllowlist;
666 splitArgs(options["interface-namespaces"], ifaceAllowlist);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800667
Brad Bishopa098a372022-05-05 15:19:04 -0400668 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700669
670 // Construct a signal set registered for process termination.
671 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400672 signals.async_wait(
673 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700674
Brad Bishopa098a372022-05-05 15:19:04 -0400675 InterfaceMapType interfaceMap;
676 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700677
678 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400679 nameChangeHandler = [&interfaceMap, &io, &nameOwners, &server,
680 systemBus](sdbusplus::message::message& message) {
681 std::string name; // well-known
682 std::string oldOwner; // unique-name
683 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700684
Brad Bishopa098a372022-05-05 15:19:04 -0400685 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700686
Brad Bishopa098a372022-05-05 15:19:04 -0400687 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700688 {
Brad Bishopa098a372022-05-05 15:19:04 -0400689 processNameChangeDelete(nameOwners, name, oldOwner,
690 interfaceMap, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700691 }
692
Brad Bishopa098a372022-05-05 15:19:04 -0400693 if (!newOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700694 {
Matt Spinleraecabe82018-09-19 13:25:42 -0500695#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700696 auto transaction = std::make_shared<
697 std::chrono::time_point<std::chrono::steady_clock>>(
698 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500699#endif
Ed Tanous60520632018-06-11 17:46:52 -0700700 // New daemon added
Brad Bishopf944a452022-05-05 15:06:46 -0400701 if (needToIntrospect(name, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700702 {
Brad Bishopa098a372022-05-05 15:19:04 -0400703 nameOwners[newOwner] = name;
704 startNewIntrospect(systemBus.get(), io, interfaceMap, name,
705 associationMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500706#ifdef DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400707 transaction,
Matt Spinleraecabe82018-09-19 13:25:42 -0500708#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400709 server);
Ed Tanous60520632018-06-11 17:46:52 -0700710 }
711 }
712 };
713
714 sdbusplus::bus::match::match nameOwnerChanged(
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::nameOwnerChanged(), nameChangeHandler);
717
718 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400719 interfacesAddedHandler = [&interfaceMap, &nameOwners, &server](
Ed Tanous60520632018-06-11 17:46:52 -0700720 sdbusplus::message::message& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400721 sdbusplus::message::object_path objPath;
722 InterfacesAdded interfacesAdded;
723 message.read(objPath, interfacesAdded);
724 std::string wellKnown;
725 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700726 {
727 return; // only introspect well-known
728 }
Brad Bishopa098a372022-05-05 15:19:04 -0400729 if (needToIntrospect(wellKnown, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700730 {
Brad Bishopa098a372022-05-05 15:19:04 -0400731 processInterfaceAdded(interfaceMap, objPath, interfacesAdded,
732 wellKnown, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700733 }
734 };
735
736 sdbusplus::bus::match::match interfacesAdded(
Brad Bishopa098a372022-05-05 15:19:04 -0400737 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700738 sdbusplus::bus::match::rules::interfacesAdded(),
739 interfacesAddedHandler);
740
741 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400742 interfacesRemovedHandler = [&interfaceMap, &nameOwners, &server](
Ed Tanous60520632018-06-11 17:46:52 -0700743 sdbusplus::message::message& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400744 sdbusplus::message::object_path objPath;
745 std::vector<std::string> interfacesRemoved;
746 message.read(objPath, interfacesRemoved);
747 auto connectionMap = interfaceMap.find(objPath.str);
748 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700749 {
750 return;
751 }
752
753 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400754 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700755 {
756 return;
757 }
Brad Bishopa098a372022-05-05 15:19:04 -0400758 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700759 {
Brad Bishopa098a372022-05-05 15:19:04 -0400760 auto interfaceSet = connectionMap->second.find(sender);
761 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700762 {
763 continue;
764 }
765
John Wangd0cf9422019-09-17 16:01:34 +0800766 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700767 {
Brad Bishopa098a372022-05-05 15:19:04 -0400768 removeAssociation(objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500769 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700770 }
771
Brad Bishopa098a372022-05-05 15:19:04 -0400772 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500773
Brad Bishopa098a372022-05-05 15:19:04 -0400774 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700775 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500776 // If this was the last interface on this connection,
777 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400778 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500779
780 // Instead of checking if every single path is the endpoint
781 // of an association that needs to be moved to pending,
782 // only check when the only remaining owner of this path is
783 // ourself, which would be because we still own the
784 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400785 if ((connectionMap->second.size() == 1) &&
786 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400787 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500788 {
789 // Remove the 2 association D-Bus paths and move the
790 // association to pending.
Brad Bishopa098a372022-05-05 15:19:04 -0400791 moveAssociationToPending(objPath.str, associationMaps,
Matt Spinler9c3d2852019-04-08 15:57:19 -0500792 server);
793 }
Ed Tanous60520632018-06-11 17:46:52 -0700794 }
795 }
796 // If this was the last connection on this object path,
797 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400798 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700799 {
Brad Bishopa098a372022-05-05 15:19:04 -0400800 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700801 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600802
Brad Bishopa098a372022-05-05 15:19:04 -0400803 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700804 };
805
806 sdbusplus::bus::match::match interfacesRemoved(
Brad Bishopa098a372022-05-05 15:19:04 -0400807 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700808 sdbusplus::bus::match::rules::interfacesRemoved(),
809 interfacesRemovedHandler);
810
811 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400812 associationChangedHandler = [&server, &nameOwners, &interfaceMap](
Matt Spinler8f876a52019-04-15 13:22:50 -0500813 sdbusplus::message::message& message) {
814 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500815 boost::container::flat_map<std::string,
816 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500817 values;
818 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800819 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500820 if (prop != values.end())
821 {
822 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500823 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500824
Brad Bishopa098a372022-05-05 15:19:04 -0400825 std::string wellKnown;
826 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500827 {
828 return;
Ed Tanous60520632018-06-11 17:46:52 -0700829 }
Matt Spinler8f876a52019-04-15 13:22:50 -0500830 associationChanged(server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400831 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500832 }
833 };
834 sdbusplus::bus::match::match assocChangedMatch(
Brad Bishopa098a372022-05-05 15:19:04 -0400835 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700836 sdbusplus::bus::match::rules::interface(
837 "org.freedesktop.DBus.Properties") +
838 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500839 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
840 associationChangedHandler);
841
Ed Tanous60520632018-06-11 17:46:52 -0700842 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400843 server.add_interface("/xyz/openbmc_project/object_mapper",
844 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700845
846 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400847 "GetAncestors", [&interfaceMap](std::string& reqPath,
848 std::vector<std::string>& interfaces) {
849 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700850 });
851
852 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400853 "GetObject", [&interfaceMap](const std::string& path,
854 std::vector<std::string>& interfaces) {
855 return getObject(interfaceMap, path, interfaces);
856 });
857
858 iface->register_method(
859 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700860 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400861 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700862 });
863
864 iface->register_method(
865 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400866 [&interfaceMap](std::string& reqPath, int32_t depth,
867 std::vector<std::string>& interfaces) {
868 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700869 });
870
871 iface->initialize();
872
873 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400874 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500875 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700876 });
877
Brad Bishopa098a372022-05-05 15:19:04 -0400878 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500879
Ed Tanous60520632018-06-11 17:46:52 -0700880 io.run();
881}