blob: c9697770d22c7765f33470d753c26e2f4a1835cd [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>
Brad Bishop1f623802022-05-31 18:22:10 -040020#include <utility>
Brad Bishop23520882022-05-26 21:39:53 -040021
Matt Spinlere2359fb2019-04-05 14:11:33 -050022AssociationMaps associationMaps;
Matt Spinler937a2322019-01-23 13:54:22 -060023
Brad Bishopf944a452022-05-05 15:06:46 -040024static AllowDenyList serviceAllowList;
25static AllowDenyList serviceDenyList;
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
Brad Bishopa098a372022-05-05 15:19:04 -040056 sdbusplus::message::message 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
Matt Spinleraecabe82018-09-19 13:25:42 -050073#ifdef DEBUG
74 ,
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)
Matt Spinleraecabe82018-09-19 13:25:42 -050081#ifdef DEBUG
82 ,
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 Bishopa098a372022-05-05 15:19:04 -040089 sendIntrospectionCompleteSignal(systemBus, processName);
Matt Spinleraecabe82018-09-19 13:25:42 -050090
91#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -070092 std::chrono::duration<float> diff =
Brad Bishopa098a372022-05-05 15:19:04 -040093 std::chrono::steady_clock::now() - processStartTime;
94 std::cout << std::setw(50) << processName << " scan took "
Ed Tanous60520632018-06-11 17:46:52 -070095 << diff.count() << " seconds\n";
96
97 // If we're the last outstanding caller globally, calculate the
98 // time it took
Brad Bishopa098a372022-05-05 15:19:04 -040099 if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
Ed Tanous60520632018-06-11 17:46:52 -0700100 {
Brad Bishopa098a372022-05-05 15:19:04 -0400101 diff = std::chrono::steady_clock::now() - *globalStartTime;
Ed Tanous60520632018-06-11 17:46:52 -0700102 std::cout << "Total scan took " << diff.count()
103 << " seconds to complete\n";
104 }
Matt Spinleraecabe82018-09-19 13:25:42 -0500105#endif
Ed Tanous60520632018-06-11 17:46:52 -0700106 }
Brad Bishopa098a372022-05-05 15:19:04 -0400107 sdbusplus::asio::connection* systemBus;
Ed Tanous21c60592020-08-17 23:43:46 -0700108 boost::asio::io_context& io;
Brad Bishopa098a372022-05-05 15:19:04 -0400109 std::string processName;
Matt Spinler11401e22019-04-08 13:13:25 -0500110 AssociationMaps& assocMaps;
Matt Spinleraecabe82018-09-19 13:25:42 -0500111#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700112 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400113 globalStartTime;
114 std::chrono::time_point<std::chrono::steady_clock> processStartTime;
Matt Spinleraecabe82018-09-19 13:25:42 -0500115#endif
Ed Tanous60520632018-06-11 17:46:52 -0700116};
117
Brad Bishopa098a372022-05-05 15:19:04 -0400118void doAssociations(sdbusplus::asio::connection* systemBus,
119 InterfaceMapType& interfaceMap,
120 sdbusplus::asio::object_server& objectServer,
121 const std::string& processName, const std::string& path,
122 int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700123{
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100124 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400125 systemBus->async_method_call(
126 [&objectServer, path, processName, &interfaceMap, systemBus,
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100127 timeoutRetries](
Matt Spinler937a2322019-01-23 13:54:22 -0600128 const boost::system::error_code ec,
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500129 const std::variant<std::vector<Association>>& variantAssociations) {
Ed Tanous60520632018-06-11 17:46:52 -0700130 if (ec)
131 {
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100132 if (ec.value() == boost::system::errc::timed_out &&
133 timeoutRetries < maxTimeoutRetries)
134 {
Brad Bishopa098a372022-05-05 15:19:04 -0400135 doAssociations(systemBus, interfaceMap, objectServer,
136 processName, path, timeoutRetries + 1);
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100137 return;
138 }
Ed Tanous60520632018-06-11 17:46:52 -0700139 std::cerr << "Error getting associations from " << path << "\n";
140 }
141 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500142 std::get<std::vector<Association>>(variantAssociations);
Andrew Geissler4511b332019-02-21 15:40:40 -0600143 associationChanged(objectServer, associations, path, processName,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500144 interfaceMap, associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700145 },
146 processName, path, "org.freedesktop.DBus.Properties", "Get",
John Wangd0cf9422019-09-17 16:01:34 +0800147 assocDefsInterface, assocDefsProperty);
Ed Tanous60520632018-06-11 17:46:52 -0700148}
149
Brad Bishopa098a372022-05-05 15:19:04 -0400150void doIntrospect(sdbusplus::asio::connection* systemBus,
Brad Bishop1f623802022-05-31 18:22:10 -0400151 const std::shared_ptr<InProgressIntrospect>& transaction,
Brad Bishopa098a372022-05-05 15:19:04 -0400152 InterfaceMapType& interfaceMap,
153 sdbusplus::asio::object_server& objectServer,
Brad Bishop1f623802022-05-31 18:22:10 -0400154 const std::string& path, int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700155{
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800156 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400157 systemBus->async_method_call(
158 [&interfaceMap, &objectServer, transaction, path, systemBus,
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800159 timeoutRetries](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400160 const std::string& introspectXml) {
Ed Tanous60520632018-06-11 17:46:52 -0700161 if (ec)
162 {
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800163 if (ec.value() == boost::system::errc::timed_out &&
164 timeoutRetries < maxTimeoutRetries)
165 {
Brad Bishopa098a372022-05-05 15:19:04 -0400166 doIntrospect(systemBus, transaction, interfaceMap,
167 objectServer, path, timeoutRetries + 1);
Vernon Maueryc52be0d2020-01-14 11:14:25 -0800168 return;
169 }
Ed Tanous60520632018-06-11 17:46:52 -0700170 std::cerr << "Introspect call failed with error: " << ec << ", "
171 << ec.message()
Brad Bishopa098a372022-05-05 15:19:04 -0400172 << " on process: " << transaction->processName
Ed Tanous60520632018-06-11 17:46:52 -0700173 << " path: " << path << "\n";
174 return;
175 }
176
177 tinyxml2::XMLDocument doc;
178
Brad Bishopa098a372022-05-05 15:19:04 -0400179 tinyxml2::XMLError e = doc.Parse(introspectXml.c_str());
Ed Tanous60520632018-06-11 17:46:52 -0700180 if (e != tinyxml2::XMLError::XML_SUCCESS)
181 {
182 std::cerr << "XML parsing failed\n";
183 return;
184 }
185
186 tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
187 if (pRoot == nullptr)
188 {
189 std::cerr << "XML document did not contain any data\n";
190 return;
191 }
Brad Bishopa098a372022-05-05 15:19:04 -0400192 auto& thisPathMap = interfaceMap[path];
Ed Tanous60520632018-06-11 17:46:52 -0700193 tinyxml2::XMLElement* pElement =
194 pRoot->FirstChildElement("interface");
195 while (pElement != nullptr)
196 {
Brad Bishopa098a372022-05-05 15:19:04 -0400197 const char* ifaceName = pElement->Attribute("name");
198 if (ifaceName == nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700199 {
200 continue;
201 }
202
Brad Bishopa098a372022-05-05 15:19:04 -0400203 thisPathMap[transaction->processName].emplace(ifaceName);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800204
Brad Bishopa098a372022-05-05 15:19:04 -0400205 if (std::strcmp(ifaceName, assocDefsInterface) == 0)
Ed Tanous60520632018-06-11 17:46:52 -0700206 {
Brad Bishopa098a372022-05-05 15:19:04 -0400207 doAssociations(systemBus, interfaceMap, objectServer,
208 transaction->processName, path);
Ed Tanous60520632018-06-11 17:46:52 -0700209 }
Ed Tanous60520632018-06-11 17:46:52 -0700210
211 pElement = pElement->NextSiblingElement("interface");
212 }
213
Matt Spinler11401e22019-04-08 13:13:25 -0500214 // Check if this new path has a pending association that can
215 // now be completed.
Brad Bishopa098a372022-05-05 15:19:04 -0400216 checkIfPendingAssociation(path, interfaceMap,
Matt Spinler11401e22019-04-08 13:13:25 -0500217 transaction->assocMaps, objectServer);
218
Ed Tanous50232cd2018-11-12 11:34:43 -0800219 pElement = pRoot->FirstChildElement("node");
220 while (pElement != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700221 {
Brad Bishopa098a372022-05-05 15:19:04 -0400222 const char* childPath = pElement->Attribute("name");
223 if (childPath != nullptr)
Ed Tanous60520632018-06-11 17:46:52 -0700224 {
Brad Bishopa098a372022-05-05 15:19:04 -0400225 std::string parentPath(path);
226 if (parentPath == "/")
Ed Tanous60520632018-06-11 17:46:52 -0700227 {
Brad Bishopa098a372022-05-05 15:19:04 -0400228 parentPath.clear();
Ed Tanous60520632018-06-11 17:46:52 -0700229 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800230
Brad Bishopa098a372022-05-05 15:19:04 -0400231 doIntrospect(systemBus, transaction, interfaceMap,
232 objectServer, parentPath + "/" + childPath);
Ed Tanous60520632018-06-11 17:46:52 -0700233 }
Ed Tanous50232cd2018-11-12 11:34:43 -0800234 pElement = pElement->NextSiblingElement("node");
Ed Tanous60520632018-06-11 17:46:52 -0700235 }
236 },
Brad Bishopa098a372022-05-05 15:19:04 -0400237 transaction->processName, path, "org.freedesktop.DBus.Introspectable",
Ed Tanous60520632018-06-11 17:46:52 -0700238 "Introspect");
239}
240
Brad Bishopa098a372022-05-05 15:19:04 -0400241void startNewIntrospect(
242 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
243 InterfaceMapType& interfaceMap, const std::string& processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500244 AssociationMaps& assocMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500245#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700246 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400247 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500248#endif
Ed Tanous60520632018-06-11 17:46:52 -0700249 sdbusplus::asio::object_server& objectServer)
250{
Brad Bishopa098a372022-05-05 15:19:04 -0400251 if (needToIntrospect(processName, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700252 {
Ed Tanous60520632018-06-11 17:46:52 -0700253 std::shared_ptr<InProgressIntrospect> transaction =
Brad Bishopa098a372022-05-05 15:19:04 -0400254 std::make_shared<InProgressIntrospect>(systemBus, io, processName,
Matt Spinler11401e22019-04-08 13:13:25 -0500255 assocMaps
Matt Spinleraecabe82018-09-19 13:25:42 -0500256#ifdef DEBUG
257 ,
Brad Bishopa098a372022-05-05 15:19:04 -0400258 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -0500259#endif
260 );
Ed Tanous60520632018-06-11 17:46:52 -0700261
Brad Bishopa098a372022-05-05 15:19:04 -0400262 doIntrospect(systemBus, transaction, interfaceMap, objectServer, "/");
Ed Tanous60520632018-06-11 17:46:52 -0700263 }
264}
265
266// TODO(ed) replace with std::set_intersection once c++17 is available
267template <class InputIt1, class InputIt2>
268bool intersect(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
269{
270 while (first1 != last1 && first2 != last2)
271 {
272 if (*first1 < *first2)
273 {
274 ++first1;
275 continue;
276 }
277 if (*first2 < *first1)
278 {
279 ++first2;
280 continue;
281 }
282 return true;
283 }
284 return false;
285}
286
287void doListNames(
Brad Bishopa098a372022-05-05 15:19:04 -0400288 boost::asio::io_context& io, InterfaceMapType& interfaceMap,
289 sdbusplus::asio::connection* systemBus,
290 boost::container::flat_map<std::string, std::string>& nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500291 AssociationMaps& assocMaps, sdbusplus::asio::object_server& objectServer)
Ed Tanous60520632018-06-11 17:46:52 -0700292{
Brad Bishopa098a372022-05-05 15:19:04 -0400293 systemBus->async_method_call(
294 [&io, &interfaceMap, &nameOwners, &objectServer, systemBus,
Matt Spinler11401e22019-04-08 13:13:25 -0500295 &assocMaps](const boost::system::error_code ec,
Brad Bishopa098a372022-05-05 15:19:04 -0400296 std::vector<std::string> processNames) {
Ed Tanous60520632018-06-11 17:46:52 -0700297 if (ec)
298 {
299 std::cerr << "Error getting names: " << ec << "\n";
300 std::exit(EXIT_FAILURE);
301 return;
302 }
Ed Tanous60520632018-06-11 17:46:52 -0700303 // Try to make startup consistent
Brad Bishopa098a372022-05-05 15:19:04 -0400304 std::sort(processNames.begin(), processNames.end());
Matt Spinleraecabe82018-09-19 13:25:42 -0500305#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700306 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400307 globalStartTime = std::make_shared<
Ed Tanous60520632018-06-11 17:46:52 -0700308 std::chrono::time_point<std::chrono::steady_clock>>(
309 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500310#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400311 for (const std::string& processName : processNames)
Ed Tanous60520632018-06-11 17:46:52 -0700312 {
Brad Bishopa098a372022-05-05 15:19:04 -0400313 if (needToIntrospect(processName, serviceAllowList,
Brad Bishopf944a452022-05-05 15:06:46 -0400314 serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700315 {
Brad Bishopa098a372022-05-05 15:19:04 -0400316 startNewIntrospect(systemBus, io, interfaceMap, processName,
317 assocMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500318#ifdef DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400319 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500320#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400321 objectServer);
322 updateOwners(systemBus, nameOwners, processName);
Ed Tanous60520632018-06-11 17:46:52 -0700323 }
324 }
325 },
326 "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
327 "ListNames");
328}
329
Matt Spinlerdd945862018-09-07 12:41:05 -0500330void splitArgs(const std::string& stringArgs,
331 boost::container::flat_set<std::string>& listArgs)
332{
333 std::istringstream args;
334 std::string arg;
335
336 args.str(stringArgs);
337
338 while (!args.eof())
339 {
340 args >> arg;
341 if (!arg.empty())
342 {
343 listArgs.insert(arg);
344 }
345 }
346}
347
Matt Spinler47c09752018-11-29 14:54:13 -0600348void addObjectMapResult(
Brad Bishopa098a372022-05-05 15:19:04 -0400349 std::vector<InterfaceMapType::value_type>& objectMap,
Matt Spinler9f0958e2018-09-11 08:26:10 -0500350 const std::string& objectPath,
351 const std::pair<std::string, boost::container::flat_set<std::string>>&
352 interfaceMap)
353{
354 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600355 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500356 // If an entry for the object path already exists, just add the
357 // service name and interfaces to that entry, otherwise create
358 // a new entry.
359 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600360 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500361 [&objectPath](const auto& i) { return objectPath == i.first; });
362
Matt Spinler47c09752018-11-29 14:54:13 -0600363 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500364 {
365 entry->second.emplace(interfaceMap);
366 }
367 else
368 {
Brad Bishopa098a372022-05-05 15:19:04 -0400369 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500370 object.first = objectPath;
371 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600372 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500373 }
374}
375
Matt Spinlera82779f2019-01-09 12:39:42 -0600376// Remove parents of the passed in path that:
377// 1) Only have the 3 default interfaces on them
378// - Means D-Bus created these, not application code,
379// with the Properties, Introspectable, and Peer ifaces
380// 2) Have no other child for this owner
381void removeUnneededParents(const std::string& objectPath,
382 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400383 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600384{
385 auto parent = objectPath;
386
387 while (true)
388 {
389 auto pos = parent.find_last_of('/');
390 if ((pos == std::string::npos) || (pos == 0))
391 {
392 break;
393 }
394 parent = parent.substr(0, pos);
395
Brad Bishopa098a372022-05-05 15:19:04 -0400396 auto parentIt = interfaceMap.find(parent);
397 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600398 {
399 break;
400 }
401
Brad Bishopa098a372022-05-05 15:19:04 -0400402 auto ifacesIt = parentIt->second.find(owner);
403 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600404 {
405 break;
406 }
407
Brad Bishopa098a372022-05-05 15:19:04 -0400408 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600409 {
410 break;
411 }
412
Brad Bishopa098a372022-05-05 15:19:04 -0400413 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600414
415 // Remove this parent if there isn't a remaining child on this owner
416 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400417 interfaceMap.begin(), interfaceMap.end(),
418 [&owner, &childPath](const auto& entry) {
419 return boost::starts_with(entry.first, childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600420 (entry.second.find(owner) != entry.second.end());
421 });
422
Brad Bishopa098a372022-05-05 15:19:04 -0400423 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600424 {
Brad Bishopa098a372022-05-05 15:19:04 -0400425 parentIt->second.erase(ifacesIt);
426 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600427 {
Brad Bishopa098a372022-05-05 15:19:04 -0400428 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600429 }
430 }
431 else
432 {
433 break;
434 }
435 }
436}
437
Brad Bishopa098a372022-05-05 15:19:04 -0400438std::vector<InterfaceMapType::value_type>
439 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700440 std::vector<std::string>& interfaces)
441{
442 // Interfaces need to be sorted for intersect to function
443 std::sort(interfaces.begin(), interfaces.end());
444
Brad Bishopa098a372022-05-05 15:19:04 -0400445 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700446 {
Brad Bishopa098a372022-05-05 15:19:04 -0400447 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700448 }
Brad Bishop1f623802022-05-31 18:22:10 -0400449 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700450 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300451 throw sdbusplus::xyz::openbmc_project::Common::Error::
452 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700453 }
454
Brad Bishopa098a372022-05-05 15:19:04 -0400455 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400456 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700457 {
Brad Bishop1f623802022-05-31 18:22:10 -0400458 const auto& thisPath = objectPath.first;
Brad Bishopa098a372022-05-05 15:19:04 -0400459 if (boost::starts_with(reqPath, thisPath) && (reqPath != thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700460 {
461 if (interfaces.empty())
462 {
Brad Bishopa098a372022-05-05 15:19:04 -0400463 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700464 }
465 else
466 {
Brad Bishop1f623802022-05-31 18:22:10 -0400467 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700468 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700469 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400470 interfaceMap.second.begin(),
471 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700472 {
Brad Bishopa098a372022-05-05 15:19:04 -0400473 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700474 }
475 }
476 }
477 }
478 }
479
480 return ret;
481}
482
483boost::container::flat_map<std::string, boost::container::flat_set<std::string>>
Brad Bishopa098a372022-05-05 15:19:04 -0400484 getObject(const InterfaceMapType& interfaceMap, const std::string& path,
Ed Tanous0a13c762021-09-28 13:29:25 -0700485 std::vector<std::string>& interfaces)
486{
487 boost::container::flat_map<std::string,
488 boost::container::flat_set<std::string>>
489 results;
490
491 // Interfaces need to be sorted for intersect to function
492 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400493 auto pathRef = interfaceMap.find(path);
494 if (pathRef == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700495 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300496 throw sdbusplus::xyz::openbmc_project::Common::Error::
497 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700498 }
499 if (interfaces.empty())
500 {
Brad Bishopa098a372022-05-05 15:19:04 -0400501 return pathRef->second;
Ed Tanous0a13c762021-09-28 13:29:25 -0700502 }
Brad Bishop1f623802022-05-31 18:22:10 -0400503 for (const auto& interfaceMap : pathRef->second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700504 {
505 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400506 interfaceMap.second.begin(), interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700507 {
Brad Bishopa098a372022-05-05 15:19:04 -0400508 results.emplace(interfaceMap.first, interfaceMap.second);
Ed Tanous0a13c762021-09-28 13:29:25 -0700509 }
510 }
511
512 if (results.empty())
513 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300514 throw sdbusplus::xyz::openbmc_project::Common::Error::
515 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700516 }
517
518 return results;
519}
520
Brad Bishopa098a372022-05-05 15:19:04 -0400521std::vector<InterfaceMapType::value_type>
522 getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700523 int32_t depth, std::vector<std::string>& interfaces)
524{
525 if (depth <= 0)
526 {
527 depth = std::numeric_limits<int32_t>::max();
528 }
529 // Interfaces need to be sorted for intersect to function
530 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400531 std::vector<InterfaceMapType::value_type> ret;
Ed Tanous0a13c762021-09-28 13:29:25 -0700532
Brad Bishopa098a372022-05-05 15:19:04 -0400533 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700534 {
Brad Bishopa098a372022-05-05 15:19:04 -0400535 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700536 }
Brad Bishop1f623802022-05-31 18:22:10 -0400537 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700538 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300539 throw sdbusplus::xyz::openbmc_project::Common::Error::
540 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700541 }
542
Brad Bishop1f623802022-05-31 18:22:10 -0400543 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700544 {
Brad Bishop1f623802022-05-31 18:22:10 -0400545 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700546
Brad Bishopa098a372022-05-05 15:19:04 -0400547 if (thisPath == reqPath)
Ed Tanous0a13c762021-09-28 13:29:25 -0700548 {
549 continue;
550 }
551
Brad Bishopa098a372022-05-05 15:19:04 -0400552 if (boost::starts_with(thisPath, reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700553 {
554 // count the number of slashes past the search term
Brad Bishopa098a372022-05-05 15:19:04 -0400555 int32_t thisDepth = std::count(thisPath.begin() + reqPath.size(),
556 thisPath.end(), '/');
557 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700558 {
Brad Bishop1f623802022-05-31 18:22:10 -0400559 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700560 {
561 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400562 interfaceMap.second.begin(),
563 interfaceMap.second.end()) ||
Ed Tanous0a13c762021-09-28 13:29:25 -0700564 interfaces.empty())
565 {
Brad Bishopa098a372022-05-05 15:19:04 -0400566 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700567 }
568 }
569 }
570 }
571 }
572
573 return ret;
574}
575
Brad Bishopa098a372022-05-05 15:19:04 -0400576std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
577 std::string reqPath, int32_t depth,
578 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700579{
580 if (depth <= 0)
581 {
582 depth = std::numeric_limits<int32_t>::max();
583 }
584 // Interfaces need to be sorted for intersect to function
585 std::sort(interfaces.begin(), interfaces.end());
586 std::vector<std::string> ret;
587
Brad Bishopa098a372022-05-05 15:19:04 -0400588 if (boost::ends_with(reqPath, "/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700589 {
Brad Bishopa098a372022-05-05 15:19:04 -0400590 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700591 }
Brad Bishop1f623802022-05-31 18:22:10 -0400592 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700593 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300594 throw sdbusplus::xyz::openbmc_project::Common::Error::
595 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700596 }
597
Brad Bishop1f623802022-05-31 18:22:10 -0400598 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700599 {
Brad Bishop1f623802022-05-31 18:22:10 -0400600 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700601
Brad Bishopa098a372022-05-05 15:19:04 -0400602 if (thisPath == reqPath)
Ed Tanous0a13c762021-09-28 13:29:25 -0700603 {
604 continue;
605 }
606
Brad Bishopa098a372022-05-05 15:19:04 -0400607 if (boost::starts_with(thisPath, reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700608 {
609 // count the number of slashes past the search term
Brad Bishopa098a372022-05-05 15:19:04 -0400610 int thisDepth = std::count(thisPath.begin() + reqPath.size(),
611 thisPath.end(), '/');
612 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700613 {
614 bool add = interfaces.empty();
Brad Bishop1f623802022-05-31 18:22:10 -0400615 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700616 {
617 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400618 interfaceMap.second.begin(),
619 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700620 {
621 add = true;
622 break;
623 }
624 }
625 if (add)
626 {
627 // TODO(ed) this is a copy
Brad Bishopa098a372022-05-05 15:19:04 -0400628 ret.emplace_back(thisPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700629 }
630 }
631 }
632 }
633
634 return ret;
635}
636
Ed Tanous60520632018-06-11 17:46:52 -0700637int main(int argc, char** argv)
638{
Matt Spinlerdd945862018-09-07 12:41:05 -0500639 auto options = ArgumentParser(argc, argv);
Ed Tanous21c60592020-08-17 23:43:46 -0700640 boost::asio::io_context io;
Brad Bishopa098a372022-05-05 15:19:04 -0400641 std::shared_ptr<sdbusplus::asio::connection> systemBus =
Ed Tanous60520632018-06-11 17:46:52 -0700642 std::make_shared<sdbusplus::asio::connection>(io);
643
Brad Bishopf944a452022-05-05 15:06:46 -0400644 splitArgs(options["service-namespaces"], serviceAllowList);
645 splitArgs(options["service-blacklists"], serviceDenyList);
Matt Spinlerdd945862018-09-07 12:41:05 -0500646
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800647 // TODO(Ed) Remove this once all service files are updated to not use this.
648 // For now, simply squash the input, and ignore it.
Brad Bishopf944a452022-05-05 15:06:46 -0400649 boost::container::flat_set<std::string> ifaceAllowlist;
650 splitArgs(options["interface-namespaces"], ifaceAllowlist);
Ed Tanousd4dd96a2018-11-12 11:37:44 -0800651
Brad Bishopa098a372022-05-05 15:19:04 -0400652 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700653
654 // Construct a signal set registered for process termination.
655 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400656 signals.async_wait(
657 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700658
Brad Bishopa098a372022-05-05 15:19:04 -0400659 InterfaceMapType interfaceMap;
660 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700661
662 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400663 nameChangeHandler = [&interfaceMap, &io, &nameOwners, &server,
664 systemBus](sdbusplus::message::message& message) {
665 std::string name; // well-known
666 std::string oldOwner; // unique-name
667 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700668
Brad Bishopa098a372022-05-05 15:19:04 -0400669 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700670
Brad Bishopa098a372022-05-05 15:19:04 -0400671 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700672 {
Brad Bishopa098a372022-05-05 15:19:04 -0400673 processNameChangeDelete(nameOwners, name, oldOwner,
674 interfaceMap, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700675 }
676
Brad Bishopa098a372022-05-05 15:19:04 -0400677 if (!newOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700678 {
Matt Spinleraecabe82018-09-19 13:25:42 -0500679#ifdef DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700680 auto transaction = std::make_shared<
681 std::chrono::time_point<std::chrono::steady_clock>>(
682 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500683#endif
Ed Tanous60520632018-06-11 17:46:52 -0700684 // New daemon added
Brad Bishopf944a452022-05-05 15:06:46 -0400685 if (needToIntrospect(name, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700686 {
Brad Bishopa098a372022-05-05 15:19:04 -0400687 nameOwners[newOwner] = name;
688 startNewIntrospect(systemBus.get(), io, interfaceMap, name,
689 associationMaps,
Matt Spinleraecabe82018-09-19 13:25:42 -0500690#ifdef DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400691 transaction,
Matt Spinleraecabe82018-09-19 13:25:42 -0500692#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400693 server);
Ed Tanous60520632018-06-11 17:46:52 -0700694 }
695 }
696 };
697
698 sdbusplus::bus::match::match nameOwnerChanged(
Brad Bishopa098a372022-05-05 15:19:04 -0400699 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700700 sdbusplus::bus::match::rules::nameOwnerChanged(), nameChangeHandler);
701
702 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400703 interfacesAddedHandler = [&interfaceMap, &nameOwners, &server](
Ed Tanous60520632018-06-11 17:46:52 -0700704 sdbusplus::message::message& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400705 sdbusplus::message::object_path objPath;
706 InterfacesAdded interfacesAdded;
707 message.read(objPath, interfacesAdded);
708 std::string wellKnown;
709 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700710 {
711 return; // only introspect well-known
712 }
Brad Bishopa098a372022-05-05 15:19:04 -0400713 if (needToIntrospect(wellKnown, serviceAllowList, serviceDenyList))
Ed Tanous60520632018-06-11 17:46:52 -0700714 {
Brad Bishopa098a372022-05-05 15:19:04 -0400715 processInterfaceAdded(interfaceMap, objPath, interfacesAdded,
716 wellKnown, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700717 }
718 };
719
720 sdbusplus::bus::match::match interfacesAdded(
Brad Bishopa098a372022-05-05 15:19:04 -0400721 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700722 sdbusplus::bus::match::rules::interfacesAdded(),
723 interfacesAddedHandler);
724
725 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400726 interfacesRemovedHandler = [&interfaceMap, &nameOwners, &server](
Ed Tanous60520632018-06-11 17:46:52 -0700727 sdbusplus::message::message& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400728 sdbusplus::message::object_path objPath;
729 std::vector<std::string> interfacesRemoved;
730 message.read(objPath, interfacesRemoved);
731 auto connectionMap = interfaceMap.find(objPath.str);
732 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700733 {
734 return;
735 }
736
737 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400738 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700739 {
740 return;
741 }
Brad Bishopa098a372022-05-05 15:19:04 -0400742 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700743 {
Brad Bishopa098a372022-05-05 15:19:04 -0400744 auto interfaceSet = connectionMap->second.find(sender);
745 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700746 {
747 continue;
748 }
749
John Wangd0cf9422019-09-17 16:01:34 +0800750 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700751 {
Brad Bishopa098a372022-05-05 15:19:04 -0400752 removeAssociation(objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500753 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700754 }
755
Brad Bishopa098a372022-05-05 15:19:04 -0400756 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500757
Brad Bishopa098a372022-05-05 15:19:04 -0400758 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700759 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500760 // If this was the last interface on this connection,
761 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400762 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500763
764 // Instead of checking if every single path is the endpoint
765 // of an association that needs to be moved to pending,
766 // only check when the only remaining owner of this path is
767 // ourself, which would be because we still own the
768 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400769 if ((connectionMap->second.size() == 1) &&
770 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400771 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500772 {
773 // Remove the 2 association D-Bus paths and move the
774 // association to pending.
Brad Bishopa098a372022-05-05 15:19:04 -0400775 moveAssociationToPending(objPath.str, associationMaps,
Matt Spinler9c3d2852019-04-08 15:57:19 -0500776 server);
777 }
Ed Tanous60520632018-06-11 17:46:52 -0700778 }
779 }
780 // If this was the last connection on this object path,
781 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400782 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700783 {
Brad Bishopa098a372022-05-05 15:19:04 -0400784 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700785 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600786
Brad Bishopa098a372022-05-05 15:19:04 -0400787 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700788 };
789
790 sdbusplus::bus::match::match interfacesRemoved(
Brad Bishopa098a372022-05-05 15:19:04 -0400791 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700792 sdbusplus::bus::match::rules::interfacesRemoved(),
793 interfacesRemovedHandler);
794
795 std::function<void(sdbusplus::message::message & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400796 associationChangedHandler = [&server, &nameOwners, &interfaceMap](
Matt Spinler8f876a52019-04-15 13:22:50 -0500797 sdbusplus::message::message& message) {
798 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500799 boost::container::flat_map<std::string,
800 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500801 values;
802 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800803 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500804 if (prop != values.end())
805 {
806 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500807 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500808
Brad Bishopa098a372022-05-05 15:19:04 -0400809 std::string wellKnown;
810 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500811 {
812 return;
Ed Tanous60520632018-06-11 17:46:52 -0700813 }
Matt Spinler8f876a52019-04-15 13:22:50 -0500814 associationChanged(server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400815 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500816 }
817 };
818 sdbusplus::bus::match::match assocChangedMatch(
Brad Bishopa098a372022-05-05 15:19:04 -0400819 static_cast<sdbusplus::bus::bus&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700820 sdbusplus::bus::match::rules::interface(
821 "org.freedesktop.DBus.Properties") +
822 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500823 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
824 associationChangedHandler);
825
Ed Tanous60520632018-06-11 17:46:52 -0700826 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400827 server.add_interface("/xyz/openbmc_project/object_mapper",
828 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700829
830 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400831 "GetAncestors", [&interfaceMap](std::string& reqPath,
832 std::vector<std::string>& interfaces) {
833 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700834 });
835
836 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400837 "GetObject", [&interfaceMap](const std::string& path,
838 std::vector<std::string>& interfaces) {
839 return getObject(interfaceMap, path, interfaces);
840 });
841
842 iface->register_method(
843 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700844 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400845 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700846 });
847
848 iface->register_method(
849 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400850 [&interfaceMap](std::string& reqPath, int32_t depth,
851 std::vector<std::string>& interfaces) {
852 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700853 });
854
855 iface->initialize();
856
857 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400858 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500859 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700860 });
861
Brad Bishopa098a372022-05-05 15:19:04 -0400862 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500863
Ed Tanous60520632018-06-11 17:46:52 -0700864 io.run();
865}