blob: 64031b8f0837bb842ef88c247ed37365f3875db3 [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;
Matt Spinlerdd945862018-09-07 12:41:05 -050026
Brad Bishopa098a372022-05-05 15:19:04 -040027void updateOwners(sdbusplus::asio::connection* conn,
28 boost::container::flat_map<std::string, std::string>& owners,
29 const std::string& newObject)
Ed Tanous60520632018-06-11 17:46:52 -070030{
Brad Bishopa098a372022-05-05 15:19:04 -040031 if (boost::starts_with(newObject, ":"))
Ed Tanous60520632018-06-11 17:46:52 -070032 {
33 return;
34 }
35 conn->async_method_call(
Brad Bishopa098a372022-05-05 15:19:04 -040036 [&, newObject](const boost::system::error_code ec,
37 const std::string& nameOwner) {
Ed Tanous60520632018-06-11 17:46:52 -070038 if (ec)
39 {
Brad Bishopa098a372022-05-05 15:19:04 -040040 std::cerr << "Error getting owner of " << newObject << " : "
Ed Tanous60520632018-06-11 17:46:52 -070041 << ec << "\n";
42 return;
43 }
Brad Bishopa098a372022-05-05 15:19:04 -040044 owners[nameOwner] = newObject;
Ed Tanous60520632018-06-11 17:46:52 -070045 },
46 "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner",
Brad Bishopa098a372022-05-05 15:19:04 -040047 newObject);
Ed Tanous60520632018-06-11 17:46:52 -070048}
49
Brad Bishopa098a372022-05-05 15:19:04 -040050void sendIntrospectionCompleteSignal(sdbusplus::asio::connection* systemBus,
51 const std::string& processName)
Ed Tanous60520632018-06-11 17:46:52 -070052{
53 // TODO(ed) This signal doesn't get exposed properly in the
54 // introspect right now. Find out how to register signals in
55 // sdbusplus
Patrick Williamscc8070b2022-07-22 19:26:55 -050056 sdbusplus::message_t m = systemBus->new_signal(
Brad Bishopa02cd542021-10-12 19:12:42 -040057 "/xyz/openbmc_project/object_mapper",
58 "xyz.openbmc_project.ObjectMapper.Private", "IntrospectionComplete");
Brad Bishopa098a372022-05-05 15:19:04 -040059 m.append(processName);
Ed Tanous60520632018-06-11 17:46:52 -070060 m.signal_send();
61}
62
63struct InProgressIntrospect
64{
Brad Bishop1f623802022-05-31 18:22:10 -040065 InProgressIntrospect() = delete;
66 InProgressIntrospect(const InProgressIntrospect&) = delete;
67 InProgressIntrospect(InProgressIntrospect&&) = delete;
68 InProgressIntrospect& operator=(const InProgressIntrospect&) = delete;
69 InProgressIntrospect& operator=(InProgressIntrospect&&) = delete;
Ed Tanous60520632018-06-11 17:46:52 -070070 InProgressIntrospect(
Brad Bishopa098a372022-05-05 15:19:04 -040071 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
72 const std::string& processName, AssociationMaps& am
Brad Bishopd6aa5522022-05-31 19:23:48 -040073#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050074 ,
Ed Tanous60520632018-06-11 17:46:52 -070075 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -040076 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -050077#endif
78 ) :
Brad Bishopa098a372022-05-05 15:19:04 -040079 systemBus(systemBus),
80 io(io), processName(processName), assocMaps(am)
Brad Bishopd6aa5522022-05-31 19:23:48 -040081#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050082 ,
Brad Bishop1f623802022-05-31 18:22:10 -040083 globalStartTime(std::move(globalStartTime)),
Brad Bishopa098a372022-05-05 15:19:04 -040084 processStartTime(std::chrono::steady_clock::now())
Matt Spinleraecabe82018-09-19 13:25:42 -050085#endif
Brad Bishop23520882022-05-26 21:39:53 -040086 {}
Ed Tanous60520632018-06-11 17:46:52 -070087 ~InProgressIntrospect()
88 {
Brad Bishopea119462022-05-31 20:32:04 -040089 try
Ed Tanous60520632018-06-11 17:46:52 -070090 {
Brad Bishopea119462022-05-31 20:32:04 -040091 sendIntrospectionCompleteSignal(systemBus, processName);
Brad Bishopd6aa5522022-05-31 19:23:48 -040092#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopea119462022-05-31 20:32:04 -040093 std::chrono::duration<float> diff =
94 std::chrono::steady_clock::now() - processStartTime;
95 std::cout << std::setw(50) << processName << " scan took "
96 << diff.count() << " seconds\n";
97
98 // If we're the last outstanding caller globally, calculate the
99 // time it took
100 if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
101 {
102 diff = std::chrono::steady_clock::now() - *globalStartTime;
103 std::cout << "Total scan took " << diff.count()
104 << " seconds to complete\n";
105 }
Matt Spinleraecabe82018-09-19 13:25:42 -0500106#endif
Brad Bishopea119462022-05-31 20:32:04 -0400107 }
108 catch (const std::exception& e)
109 {
110 std::cerr
111 << "Terminating, unhandled exception while introspecting: "
112 << e.what() << "\n";
113 std::terminate();
114 }
115 catch (...)
116 {
117 std::cerr
118 << "Terminating, unhandled exception while introspecting\n";
119 std::terminate();
120 }
Ed Tanous60520632018-06-11 17:46:52 -0700121 }
Brad Bishopa098a372022-05-05 15:19:04 -0400122 sdbusplus::asio::connection* systemBus;
Ed Tanous21c60592020-08-17 23:43:46 -0700123 boost::asio::io_context& io;
Brad Bishopa098a372022-05-05 15:19:04 -0400124 std::string processName;
Matt Spinler11401e22019-04-08 13:13:25 -0500125 AssociationMaps& assocMaps;
Brad Bishopd6aa5522022-05-31 19:23:48 -0400126#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700127 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400128 globalStartTime;
129 std::chrono::time_point<std::chrono::steady_clock> processStartTime;
Matt Spinleraecabe82018-09-19 13:25:42 -0500130#endif
Ed Tanous60520632018-06-11 17:46:52 -0700131};
132
Brad Bishopa098a372022-05-05 15:19:04 -0400133void doAssociations(sdbusplus::asio::connection* systemBus,
134 InterfaceMapType& interfaceMap,
135 sdbusplus::asio::object_server& objectServer,
136 const std::string& processName, const std::string& path,
137 int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700138{
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100139 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400140 systemBus->async_method_call(
141 [&objectServer, path, processName, &interfaceMap, systemBus,
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100142 timeoutRetries](
Matt Spinler937a2322019-01-23 13:54:22 -0600143 const boost::system::error_code ec,
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500144 const std::variant<std::vector<Association>>& variantAssociations) {
Ed Tanous60520632018-06-11 17:46:52 -0700145 if (ec)
146 {
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100147 if (ec.value() == boost::system::errc::timed_out &&
148 timeoutRetries < maxTimeoutRetries)
149 {
Brad Bishopa098a372022-05-05 15:19:04 -0400150 doAssociations(systemBus, interfaceMap, objectServer,
151 processName, path, timeoutRetries + 1);
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100152 return;
153 }
Ed Tanous60520632018-06-11 17:46:52 -0700154 std::cerr << "Error getting associations from " << path << "\n";
155 }
156 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500157 std::get<std::vector<Association>>(variantAssociations);
Andrew Geissler4511b332019-02-21 15:40:40 -0600158 associationChanged(objectServer, associations, path, processName,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500159 interfaceMap, associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700160 },
161 processName, path, "org.freedesktop.DBus.Properties", "Get",
John Wangd0cf9422019-09-17 16:01:34 +0800162 assocDefsInterface, assocDefsProperty);
Ed Tanous60520632018-06-11 17:46:52 -0700163}
164
Brad Bishopa098a372022-05-05 15:19:04 -0400165void doIntrospect(sdbusplus::asio::connection* systemBus,
Brad Bishop1f623802022-05-31 18:22:10 -0400166 const std::shared_ptr<InProgressIntrospect>& transaction,
Brad Bishopa098a372022-05-05 15:19:04 -0400167 InterfaceMapType& interfaceMap,
168 sdbusplus::asio::object_server& objectServer,
Brad Bishop1f623802022-05-31 18:22:10 -0400169 const std::string& path, int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700170{
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800171 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400172 systemBus->async_method_call(
173 [&interfaceMap, &objectServer, transaction, path, systemBus,
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800174 timeoutRetries](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400175 const std::string& introspectXml) {
Ed Tanous60520632018-06-11 17:46:52 -0700176 if (ec)
177 {
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800178 if (ec.value() == boost::system::errc::timed_out &&
179 timeoutRetries < maxTimeoutRetries)
180 {
Brad Bishopa098a372022-05-05 15:19:04 -0400181 doIntrospect(systemBus, transaction, interfaceMap,
182 objectServer, path, timeoutRetries + 1);
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800183 return;
184 }
Ed Tanous60520632018-06-11 17:46:52 -0700185 std::cerr << "Introspect call failed with error: " << ec << ", "
186 << ec.message()
Brad Bishopa098a372022-05-05 15:19:04 -0400187 << " on process: " << transaction->processName
Ed Tanous60520632018-06-11 17:46:52 -0700188 << " path: " << path << "\n";
189 return;
190 }
191
192 tinyxml2::XMLDocument doc;
193
Brad Bishopa098a372022-05-05 15:19:04 -0400194 tinyxml2::XMLError e = doc.Parse(introspectXml.c_str());
Ed Tanous60520632018-06-11 17:46:52 -0700195 if (e != tinyxml2::XMLError::XML_SUCCESS)
196 {
197 std::cerr << "XML parsing failed\n";
198 return;
199 }
200
201 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
202 if (pRoot == nullptr)
203 {
204 std::cerr << "XML document did not contain any data\n";
205 return;
206 }
Brad Bishopa098a372022-05-05 15:19:04 -0400207 auto& thisPathMap = interfaceMap[path];
Ed Tanous60520632018-06-11 17:46:52 -0700208 tinyxml2::XMLElement* pElement =
209 pRoot->FirstChildElement("interface");
210 while (pElement != nullptr)
211 {
Brad Bishopa098a372022-05-05 15:19:04 -0400212 const char* ifaceName = pElement->Attribute("name");
213 if (ifaceName == nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700214 {
215 continue;
216 }
217
Brad Bishopa098a372022-05-05 15:19:04 -0400218 thisPathMap[transaction->processName].emplace(ifaceName);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800219
Brad Bishopa098a372022-05-05 15:19:04 -0400220 if (std::strcmp(ifaceName, assocDefsInterface) == 0)
Ed Tanous60520632018-06-11 17:46:52 -0700221 {
Brad Bishopa098a372022-05-05 15:19:04 -0400222 doAssociations(systemBus, interfaceMap, objectServer,
223 transaction->processName, path);
Ed Tanous60520632018-06-11 17:46:52 -0700224 }
Ed Tanous60520632018-06-11 17:46:52 -0700225
226 pElement = pElement->NextSiblingElement("interface");
227 }
228
Matt Spinler11401e22019-04-08 13:13:25 -0500229 // Check if this new path has a pending association that can
230 // now be completed.
Brad Bishopa098a372022-05-05 15:19:04 -0400231 checkIfPendingAssociation(path, interfaceMap,
Matt Spinler11401e22019-04-08 13:13:25 -0500232 transaction->assocMaps, objectServer);
233
Ed Tanous50232cd2018-11-12 11:34:43 -0800234 pElement = pRoot->FirstChildElement("node");
235 while (pElement != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700236 {
Brad Bishopa098a372022-05-05 15:19:04 -0400237 const char* childPath = pElement->Attribute("name");
238 if (childPath != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700239 {
Brad Bishopa098a372022-05-05 15:19:04 -0400240 std::string parentPath(path);
241 if (parentPath == "/")
Ed Tanous60520632018-06-11 17:46:52 -0700242 {
Brad Bishopa098a372022-05-05 15:19:04 -0400243 parentPath.clear();
Ed Tanous60520632018-06-11 17:46:52 -0700244 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800245
Brad Bishopa098a372022-05-05 15:19:04 -0400246 doIntrospect(systemBus, transaction, interfaceMap,
247 objectServer, parentPath + "/" + childPath);
Ed Tanous60520632018-06-11 17:46:52 -0700248 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800249 pElement = pElement->NextSiblingElement("node");
Ed Tanous60520632018-06-11 17:46:52 -0700250 }
251 },
Brad Bishopa098a372022-05-05 15:19:04 -0400252 transaction->processName, path, "org.freedesktop.DBus.Introspectable",
Ed Tanous60520632018-06-11 17:46:52 -0700253 "Introspect");
254}
255
Brad Bishopa098a372022-05-05 15:19:04 -0400256void startNewIntrospect(
257 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
258 InterfaceMapType& interfaceMap, const std::string& processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500259 AssociationMaps& assocMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400260#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700261 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400262 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500263#endif
Ed Tanous60520632018-06-11 17:46:52 -0700264 sdbusplus::asio::object_server& objectServer)
265{
Brad Bishopd5542322022-06-02 19:56:23 -0400266 if (needToIntrospect(processName, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700267 {
Ed Tanous60520632018-06-11 17:46:52 -0700268 std::shared_ptr<InProgressIntrospect> transaction =
Brad Bishopa098a372022-05-05 15:19:04 -0400269 std::make_shared<InProgressIntrospect>(systemBus, io, processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500270 assocMaps
Brad Bishopd6aa5522022-05-31 19:23:48 -0400271#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -0500272 ,
Brad Bishopa098a372022-05-05 15:19:04 -0400273 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -0500274#endif
275 );
Ed Tanous60520632018-06-11 17:46:52 -0700276
Brad Bishopa098a372022-05-05 15:19:04 -0400277 doIntrospect(systemBus, transaction, interfaceMap, objectServer, "/");
Ed Tanous60520632018-06-11 17:46:52 -0700278 }
279}
280
281// TODO(ed) replace with std::set_intersection once c++17 is available
282template <class InputIt1, class InputIt2>
283bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
284{
285 while (first1 != last1 && first2 != last2)
286 {
287 if (*first1 < *first2)
288 {
289 ++first1;
290 continue;
291 }
292 if (*first2 < *first1)
293 {
294 ++first2;
295 continue;
296 }
297 return true;
298 }
299 return false;
300}
301
302void doListNames(
Brad Bishopa098a372022-05-05 15:19:04 -0400303 boost::asio::io_context& io, InterfaceMapType& interfaceMap,
304 sdbusplus::asio::connection* systemBus,
305 boost::container::flat_map<std::string, std::string>& nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500306 AssociationMaps& assocMaps, sdbusplus::asio::object_server& objectServer)
Ed Tanous60520632018-06-11 17:46:52 -0700307{
Brad Bishopa098a372022-05-05 15:19:04 -0400308 systemBus->async_method_call(
309 [&io, &interfaceMap, &nameOwners, &objectServer, systemBus,
Matt Spinler11401e22019-04-08 13:13:25 -0500310 &assocMaps](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400311 std::vector<std::string> processNames) {
Ed Tanous60520632018-06-11 17:46:52 -0700312 if (ec)
313 {
314 std::cerr << "Error getting names: " << ec << "\n";
315 std::exit(EXIT_FAILURE);
316 return;
317 }
Ed Tanous60520632018-06-11 17:46:52 -0700318 // Try to make startup consistent
Brad Bishopa098a372022-05-05 15:19:04 -0400319 std::sort(processNames.begin(), processNames.end());
Brad Bishopd6aa5522022-05-31 19:23:48 -0400320#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700321 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400322 globalStartTime = std::make_shared<
Ed Tanous60520632018-06-11 17:46:52 -0700323 std::chrono::time_point<std::chrono::steady_clock>>(
324 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500325#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400326 for (const std::string& processName : processNames)
Ed Tanous60520632018-06-11 17:46:52 -0700327 {
Brad Bishopd5542322022-06-02 19:56:23 -0400328 if (needToIntrospect(processName, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700329 {
Brad Bishopa098a372022-05-05 15:19:04 -0400330 startNewIntrospect(systemBus, io, interfaceMap, processName,
331 assocMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400332#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400333 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500334#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400335 objectServer);
336 updateOwners(systemBus, nameOwners, processName);
Ed Tanous60520632018-06-11 17:46:52 -0700337 }
338 }
339 },
340 "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
341 "ListNames");
342}
343
Matt Spinlerdd945862018-09-07 12:41:05 -0500344void splitArgs(const std::string& stringArgs,
345 boost::container::flat_set<std::string>& listArgs)
346{
347 std::istringstream args;
348 std::string arg;
349
350 args.str(stringArgs);
351
352 while (!args.eof())
353 {
354 args >> arg;
355 if (!arg.empty())
356 {
357 listArgs.insert(arg);
358 }
359 }
360}
361
Ed Tanous964681c2022-07-08 12:47:24 -0700362void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
363 const std::string& objectPath,
364 const ConnectionNames::value_type& interfaceMap)
Matt Spinler9f0958e2018-09-11 08:26:10 -0500365{
366 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600367 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500368 // If an entry for the object path already exists, just add the
369 // service name and interfaces to that entry, otherwise create
370 // a new entry.
371 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600372 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500373 [&objectPath](const auto& i) { return objectPath == i.first; });
374
Matt Spinler47c09752018-11-29 14:54:13 -0600375 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500376 {
377 entry->second.emplace(interfaceMap);
378 }
379 else
380 {
Brad Bishopa098a372022-05-05 15:19:04 -0400381 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500382 object.first = objectPath;
383 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600384 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500385 }
386}
387
Matt Spinlera82779f2019-01-09 12:39:42 -0600388// Remove parents of the passed in path that:
389// 1) Only have the 3 default interfaces on them
390// - Means D-Bus created these, not application code,
391// with the Properties, Introspectable, and Peer ifaces
392// 2) Have no other child for this owner
393void removeUnneededParents(const std::string& objectPath,
394 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400395 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600396{
397 auto parent = objectPath;
398
399 while (true)
400 {
401 auto pos = parent.find_last_of('/');
402 if ((pos == std::string::npos) || (pos == 0))
403 {
404 break;
405 }
406 parent = parent.substr(0, pos);
407
Brad Bishopa098a372022-05-05 15:19:04 -0400408 auto parentIt = interfaceMap.find(parent);
409 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600410 {
411 break;
412 }
413
Brad Bishopa098a372022-05-05 15:19:04 -0400414 auto ifacesIt = parentIt->second.find(owner);
415 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600416 {
417 break;
418 }
419
Brad Bishopa098a372022-05-05 15:19:04 -0400420 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600421 {
422 break;
423 }
424
Brad Bishopa098a372022-05-05 15:19:04 -0400425 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600426
427 // Remove this parent if there isn't a remaining child on this owner
428 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400429 interfaceMap.begin(), interfaceMap.end(),
430 [&owner, &childPath](const auto& entry) {
431 return boost::starts_with(entry.first, childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600432 (entry.second.find(owner) != entry.second.end());
433 });
434
Brad Bishopa098a372022-05-05 15:19:04 -0400435 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600436 {
Brad Bishopa098a372022-05-05 15:19:04 -0400437 parentIt->second.erase(ifacesIt);
438 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600439 {
Brad Bishopa098a372022-05-05 15:19:04 -0400440 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600441 }
442 }
443 else
444 {
445 break;
446 }
447 }
448}
449
Brad Bishopa098a372022-05-05 15:19:04 -0400450std::vector<InterfaceMapType::value_type>
451 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700452 std::vector<std::string>& interfaces)
453{
454 // Interfaces need to be sorted for intersect to function
455 std::sort(interfaces.begin(), interfaces.end());
456
Brad Bishopa098a372022-05-05 15:19:04 -0400457 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700458 {
Brad Bishopa098a372022-05-05 15:19:04 -0400459 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700460 }
Brad Bishop1f623802022-05-31 18:22:10 -0400461 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700462 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300463 throw sdbusplus::xyz::openbmc_project::Common::Error::
464 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700465 }
466
Brad Bishopa098a372022-05-05 15:19:04 -0400467 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400468 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700469 {
Brad Bishop1f623802022-05-31 18:22:10 -0400470 const auto& thisPath = objectPath.first;
Brandon Kim82720f02022-07-08 09:57:22 -0700471
472 if (reqPath == thisPath)
473 {
474 continue;
475 }
476
477 if (boost::starts_with(reqPath, thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700478 {
479 if (interfaces.empty())
480 {
Brad Bishopa098a372022-05-05 15:19:04 -0400481 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700482 }
483 else
484 {
Brad Bishop1f623802022-05-31 18:22:10 -0400485 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700486 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700487 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400488 interfaceMap.second.begin(),
489 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700490 {
Brad Bishopa098a372022-05-05 15:19:04 -0400491 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700492 }
493 }
494 }
495 }
496 }
497
498 return ret;
499}
500
Ed Tanous964681c2022-07-08 12:47:24 -0700501ConnectionNames getObject(const InterfaceMapType& interfaceMap,
502 const std::string& path,
503 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700504{
Ed Tanous964681c2022-07-08 12:47:24 -0700505 ConnectionNames results;
Ed Tanous0a13c762021-09-28 13:29:25 -0700506
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());
Ed Tanous0a13c762021-09-28 13:29:25 -0700547
Brad Bishopa098a372022-05-05 15:19:04 -0400548 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700549 {
Brad Bishopa098a372022-05-05 15:19:04 -0400550 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700551 }
Brad Bishop1f623802022-05-31 18:22:10 -0400552 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700553 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300554 throw sdbusplus::xyz::openbmc_project::Common::Error::
555 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700556 }
557
Brandon Kim82720f02022-07-08 09:57:22 -0700558 std::vector<InterfaceMapType::value_type> ret;
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());
Ed Tanous0a13c762021-09-28 13:29:25 -0700602
Brad Bishopa098a372022-05-05 15:19:04 -0400603 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700604 {
Brad Bishopa098a372022-05-05 15:19:04 -0400605 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700606 }
Brad Bishop1f623802022-05-31 18:22:10 -0400607 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700608 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300609 throw sdbusplus::xyz::openbmc_project::Common::Error::
610 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700611 }
612
Brandon Kim82720f02022-07-08 09:57:22 -0700613 std::vector<std::string> ret;
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);
Matt Spinlerdd945862018-09-07 12:41:05 -0500661
Brad Bishopa098a372022-05-05 15:19:04 -0400662 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700663
664 // Construct a signal set registered for process termination.
665 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400666 signals.async_wait(
667 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700668
Brad Bishopa098a372022-05-05 15:19:04 -0400669 InterfaceMapType interfaceMap;
670 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700671
Patrick Williamscc8070b2022-07-22 19:26:55 -0500672 std::function<void(sdbusplus::message_t & message)> nameChangeHandler =
673 [&interfaceMap, &io, &nameOwners, &server,
674 systemBus](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400675 std::string name; // well-known
676 std::string oldOwner; // unique-name
677 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700678
Brad Bishopa098a372022-05-05 15:19:04 -0400679 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700680
Brad Bishopa098a372022-05-05 15:19:04 -0400681 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700682 {
Brad Bishopa098a372022-05-05 15:19:04 -0400683 processNameChangeDelete(nameOwners, name, oldOwner,
684 interfaceMap, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700685 }
686
Brad Bishopa098a372022-05-05 15:19:04 -0400687 if (!newOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700688 {
Brad Bishopd6aa5522022-05-31 19:23:48 -0400689#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700690 auto transaction = std::make_shared<
691 std::chrono::time_point<std::chrono::steady_clock>>(
692 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500693#endif
Ed Tanous60520632018-06-11 17:46:52 -0700694 // New daemon added
Brad Bishopd5542322022-06-02 19:56:23 -0400695 if (needToIntrospect(name, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700696 {
Brad Bishopa098a372022-05-05 15:19:04 -0400697 nameOwners[newOwner] = name;
698 startNewIntrospect(systemBus.get(), io, interfaceMap, name,
699 associationMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400700#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400701 transaction,
Matt Spinleraecabe82018-09-19 13:25:42 -0500702#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400703 server);
Ed Tanous60520632018-06-11 17:46:52 -0700704 }
705 }
706 };
707
Patrick Williamscc8070b2022-07-22 19:26:55 -0500708 sdbusplus::bus::match_t nameOwnerChanged(
709 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700710 sdbusplus::bus::match::rules::nameOwnerChanged(), nameChangeHandler);
711
Patrick Williamscc8070b2022-07-22 19:26:55 -0500712 std::function<void(sdbusplus::message_t & message)> interfacesAddedHandler =
713 [&interfaceMap, &nameOwners, &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400714 sdbusplus::message::object_path objPath;
715 InterfacesAdded interfacesAdded;
716 message.read(objPath, interfacesAdded);
717 std::string wellKnown;
718 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700719 {
720 return; // only introspect well-known
721 }
Brad Bishopd5542322022-06-02 19:56:23 -0400722 if (needToIntrospect(wellKnown, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700723 {
Brad Bishopa098a372022-05-05 15:19:04 -0400724 processInterfaceAdded(interfaceMap, objPath, interfacesAdded,
725 wellKnown, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700726 }
727 };
728
Patrick Williamscc8070b2022-07-22 19:26:55 -0500729 sdbusplus::bus::match_t interfacesAdded(
730 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700731 sdbusplus::bus::match::rules::interfacesAdded(),
732 interfacesAddedHandler);
733
Patrick Williamscc8070b2022-07-22 19:26:55 -0500734 std::function<void(sdbusplus::message_t & message)>
735 interfacesRemovedHandler = [&interfaceMap, &nameOwners,
736 &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400737 sdbusplus::message::object_path objPath;
738 std::vector<std::string> interfacesRemoved;
739 message.read(objPath, interfacesRemoved);
740 auto connectionMap = interfaceMap.find(objPath.str);
741 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700742 {
743 return;
744 }
745
746 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400747 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700748 {
749 return;
750 }
Brad Bishopa098a372022-05-05 15:19:04 -0400751 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700752 {
Brad Bishopa098a372022-05-05 15:19:04 -0400753 auto interfaceSet = connectionMap->second.find(sender);
754 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700755 {
756 continue;
757 }
758
John Wangd0cf9422019-09-17 16:01:34 +0800759 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700760 {
Brad Bishopa098a372022-05-05 15:19:04 -0400761 removeAssociation(objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500762 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700763 }
764
Brad Bishopa098a372022-05-05 15:19:04 -0400765 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500766
Brad Bishopa098a372022-05-05 15:19:04 -0400767 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700768 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500769 // If this was the last interface on this connection,
770 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400771 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500772
773 // Instead of checking if every single path is the endpoint
774 // of an association that needs to be moved to pending,
775 // only check when the only remaining owner of this path is
776 // ourself, which would be because we still own the
777 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400778 if ((connectionMap->second.size() == 1) &&
779 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400780 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500781 {
782 // Remove the 2 association D-Bus paths and move the
783 // association to pending.
Brad Bishopa098a372022-05-05 15:19:04 -0400784 moveAssociationToPending(objPath.str, associationMaps,
Matt Spinler9c3d2852019-04-08 15:57:19 -0500785 server);
786 }
Ed Tanous60520632018-06-11 17:46:52 -0700787 }
788 }
789 // If this was the last connection on this object path,
790 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400791 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700792 {
Brad Bishopa098a372022-05-05 15:19:04 -0400793 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700794 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600795
Brad Bishopa098a372022-05-05 15:19:04 -0400796 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700797 };
798
Patrick Williamscc8070b2022-07-22 19:26:55 -0500799 sdbusplus::bus::match_t interfacesRemoved(
800 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700801 sdbusplus::bus::match::rules::interfacesRemoved(),
802 interfacesRemovedHandler);
803
Patrick Williamscc8070b2022-07-22 19:26:55 -0500804 std::function<void(sdbusplus::message_t & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400805 associationChangedHandler = [&server, &nameOwners, &interfaceMap](
Patrick Williamscc8070b2022-07-22 19:26:55 -0500806 sdbusplus::message_t& message) {
Matt Spinler8f876a52019-04-15 13:22:50 -0500807 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500808 boost::container::flat_map<std::string,
809 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500810 values;
811 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800812 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500813 if (prop != values.end())
814 {
815 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500816 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500817
Brad Bishopa098a372022-05-05 15:19:04 -0400818 std::string wellKnown;
819 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500820 {
821 return;
Ed Tanous60520632018-06-11 17:46:52 -0700822 }
Matt Spinler8f876a52019-04-15 13:22:50 -0500823 associationChanged(server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400824 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500825 }
826 };
Patrick Williamscc8070b2022-07-22 19:26:55 -0500827 sdbusplus::bus::match_t assocChangedMatch(
828 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700829 sdbusplus::bus::match::rules::interface(
830 "org.freedesktop.DBus.Properties") +
831 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500832 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
833 associationChangedHandler);
834
Ed Tanous60520632018-06-11 17:46:52 -0700835 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400836 server.add_interface("/xyz/openbmc_project/object_mapper",
837 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700838
839 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400840 "GetAncestors", [&interfaceMap](std::string& reqPath,
841 std::vector<std::string>& interfaces) {
842 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700843 });
844
845 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400846 "GetObject", [&interfaceMap](const std::string& path,
847 std::vector<std::string>& interfaces) {
848 return getObject(interfaceMap, path, interfaces);
849 });
850
851 iface->register_method(
852 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700853 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400854 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700855 });
856
857 iface->register_method(
858 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400859 [&interfaceMap](std::string& reqPath, int32_t depth,
860 std::vector<std::string>& interfaces) {
861 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700862 });
863
864 iface->initialize();
865
866 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400867 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500868 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700869 });
870
Brad Bishopa098a372022-05-05 15:19:04 -0400871 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500872
Ed Tanous60520632018-06-11 17:46:52 -0700873 io.run();
874}