blob: 109b1b3d1052cf7de758bdd050f8cd93c5d99533 [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 Tanous21c60592020-08-17 23:43:46 -07008#include <boost/asio/io_context.hpp>
9#include <boost/asio/signal_set.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070010#include <boost/container/flat_map.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070011#include <sdbusplus/asio/connection.hpp>
12#include <sdbusplus/asio/object_server.hpp>
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +030013#include <xyz/openbmc_project/Common/error.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070014
Brad Bishop23520882022-05-26 21:39:53 -040015#include <atomic>
16#include <chrono>
Brad Bishopea119462022-05-31 20:32:04 -040017#include <exception>
Brad Bishop23520882022-05-26 21:39:53 -040018#include <iomanip>
19#include <iostream>
Brandon Kimf6ebfc72022-07-07 12:53:44 -070020#include <string>
21#include <string_view>
Brad Bishop1f623802022-05-31 18:22:10 -040022#include <utility>
Brad Bishop23520882022-05-26 21:39:53 -040023
Matt Spinlere2359fb2019-04-05 14:11:33 -050024AssociationMaps associationMaps;
Matt Spinler937a2322019-01-23 13:54:22 -060025
Brad Bishopf944a452022-05-05 15:06:46 -040026static AllowDenyList serviceAllowList;
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 Bishop86d28802022-07-11 15:49:31 -040032 if (newObject.starts_with(":"))
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
Patrick Williamscc8070b2022-07-22 19:26:55 -050057 sdbusplus::message_t 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
Brad Bishopd6aa5522022-05-31 19:23:48 -040074#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050075 ,
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)
Brad Bishopd6aa5522022-05-31 19:23:48 -040082#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050083 ,
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);
Brad Bishopd6aa5522022-05-31 19:23:48 -040093#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopea119462022-05-31 20:32:04 -040094 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;
Brad Bishopd6aa5522022-05-31 19:23:48 -0400127#ifdef MAPPER_ENABLE_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,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400261#ifdef MAPPER_ENABLE_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 Bishopd5542322022-06-02 19:56:23 -0400267 if (needToIntrospect(processName, serviceAllowList))
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
Brad Bishopd6aa5522022-05-31 19:23:48 -0400272#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -0500273 ,
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());
Brad Bishopd6aa5522022-05-31 19:23:48 -0400321#ifdef MAPPER_ENABLE_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 Bishopd5542322022-06-02 19:56:23 -0400329 if (needToIntrospect(processName, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700330 {
Brad Bishopa098a372022-05-05 15:19:04 -0400331 startNewIntrospect(systemBus, io, interfaceMap, processName,
332 assocMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400333#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400334 globalStartTime,
Matt Spinleraecabe82018-09-19 13:25:42 -0500335#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400336 objectServer);
337 updateOwners(systemBus, nameOwners, processName);
Ed Tanous60520632018-06-11 17:46:52 -0700338 }
339 }
340 },
341 "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
342 "ListNames");
343}
344
Matt Spinlerdd945862018-09-07 12:41:05 -0500345void splitArgs(const std::string& stringArgs,
346 boost::container::flat_set<std::string>& listArgs)
347{
348 std::istringstream args;
349 std::string arg;
350
351 args.str(stringArgs);
352
353 while (!args.eof())
354 {
355 args >> arg;
356 if (!arg.empty())
357 {
358 listArgs.insert(arg);
359 }
360 }
361}
362
Ed Tanous964681c2022-07-08 12:47:24 -0700363void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
364 const std::string& objectPath,
365 const ConnectionNames::value_type& interfaceMap)
Matt Spinler9f0958e2018-09-11 08:26:10 -0500366{
367 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600368 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500369 // If an entry for the object path already exists, just add the
370 // service name and interfaces to that entry, otherwise create
371 // a new entry.
372 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600373 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500374 [&objectPath](const auto& i) { return objectPath == i.first; });
375
Matt Spinler47c09752018-11-29 14:54:13 -0600376 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500377 {
378 entry->second.emplace(interfaceMap);
379 }
380 else
381 {
Brad Bishopa098a372022-05-05 15:19:04 -0400382 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500383 object.first = objectPath;
384 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600385 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500386 }
387}
388
Matt Spinlera82779f2019-01-09 12:39:42 -0600389// Remove parents of the passed in path that:
390// 1) Only have the 3 default interfaces on them
391// - Means D-Bus created these, not application code,
392// with the Properties, Introspectable, and Peer ifaces
393// 2) Have no other child for this owner
394void removeUnneededParents(const std::string& objectPath,
395 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400396 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600397{
398 auto parent = objectPath;
399
400 while (true)
401 {
402 auto pos = parent.find_last_of('/');
403 if ((pos == std::string::npos) || (pos == 0))
404 {
405 break;
406 }
407 parent = parent.substr(0, pos);
408
Brad Bishopa098a372022-05-05 15:19:04 -0400409 auto parentIt = interfaceMap.find(parent);
410 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600411 {
412 break;
413 }
414
Brad Bishopa098a372022-05-05 15:19:04 -0400415 auto ifacesIt = parentIt->second.find(owner);
416 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600417 {
418 break;
419 }
420
Brad Bishopa098a372022-05-05 15:19:04 -0400421 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600422 {
423 break;
424 }
425
Brad Bishopa098a372022-05-05 15:19:04 -0400426 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600427
428 // Remove this parent if there isn't a remaining child on this owner
429 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400430 interfaceMap.begin(), interfaceMap.end(),
431 [&owner, &childPath](const auto& entry) {
Brad Bishop86d28802022-07-11 15:49:31 -0400432 return entry.first.starts_with(childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600433 (entry.second.find(owner) != entry.second.end());
434 });
435
Brad Bishopa098a372022-05-05 15:19:04 -0400436 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600437 {
Brad Bishopa098a372022-05-05 15:19:04 -0400438 parentIt->second.erase(ifacesIt);
439 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600440 {
Brad Bishopa098a372022-05-05 15:19:04 -0400441 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600442 }
443 }
444 else
445 {
446 break;
447 }
448 }
449}
450
Brad Bishopa098a372022-05-05 15:19:04 -0400451std::vector<InterfaceMapType::value_type>
452 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700453 std::vector<std::string>& interfaces)
454{
455 // Interfaces need to be sorted for intersect to function
456 std::sort(interfaces.begin(), interfaces.end());
457
Brad Bishop86d28802022-07-11 15:49:31 -0400458 if (reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700459 {
Brad Bishopa098a372022-05-05 15:19:04 -0400460 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700461 }
Brad Bishop1f623802022-05-31 18:22:10 -0400462 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700463 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300464 throw sdbusplus::xyz::openbmc_project::Common::Error::
465 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700466 }
467
Brad Bishopa098a372022-05-05 15:19:04 -0400468 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400469 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700470 {
Brad Bishop1f623802022-05-31 18:22:10 -0400471 const auto& thisPath = objectPath.first;
Brandon Kim82720f02022-07-08 09:57:22 -0700472
473 if (reqPath == thisPath)
474 {
475 continue;
476 }
477
Brad Bishop86d28802022-07-11 15:49:31 -0400478 if (reqPath.starts_with(thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700479 {
480 if (interfaces.empty())
481 {
Brad Bishopa098a372022-05-05 15:19:04 -0400482 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700483 }
484 else
485 {
Brad Bishop1f623802022-05-31 18:22:10 -0400486 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700487 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700488 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400489 interfaceMap.second.begin(),
490 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700491 {
Brad Bishopa098a372022-05-05 15:19:04 -0400492 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700493 }
494 }
495 }
496 }
497 }
498
499 return ret;
500}
501
Ed Tanous964681c2022-07-08 12:47:24 -0700502ConnectionNames getObject(const InterfaceMapType& interfaceMap,
503 const std::string& path,
504 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700505{
Ed Tanous964681c2022-07-08 12:47:24 -0700506 ConnectionNames results;
Ed Tanous0a13c762021-09-28 13:29:25 -0700507
508 // Interfaces need to be sorted for intersect to function
509 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400510 auto pathRef = interfaceMap.find(path);
511 if (pathRef == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700512 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300513 throw sdbusplus::xyz::openbmc_project::Common::Error::
514 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700515 }
516 if (interfaces.empty())
517 {
Brad Bishopa098a372022-05-05 15:19:04 -0400518 return pathRef->second;
Ed Tanous0a13c762021-09-28 13:29:25 -0700519 }
Brad Bishop1f623802022-05-31 18:22:10 -0400520 for (const auto& interfaceMap : pathRef->second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700521 {
522 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400523 interfaceMap.second.begin(), interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700524 {
Brad Bishopa098a372022-05-05 15:19:04 -0400525 results.emplace(interfaceMap.first, interfaceMap.second);
Ed Tanous0a13c762021-09-28 13:29:25 -0700526 }
527 }
528
529 if (results.empty())
530 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300531 throw sdbusplus::xyz::openbmc_project::Common::Error::
532 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700533 }
534
535 return results;
536}
537
Brad Bishopa098a372022-05-05 15:19:04 -0400538std::vector<InterfaceMapType::value_type>
539 getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700540 int32_t depth, std::vector<std::string>& interfaces)
541{
542 if (depth <= 0)
543 {
544 depth = std::numeric_limits<int32_t>::max();
545 }
546 // Interfaces need to be sorted for intersect to function
547 std::sort(interfaces.begin(), interfaces.end());
Ed Tanous0a13c762021-09-28 13:29:25 -0700548
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700549 // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
550 // will be guaranteed not to have a trailing "/"
Brad Bishop86d28802022-07-11 15:49:31 -0400551 if (!reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700552 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700553 reqPath += "/";
Ed Tanous0a13c762021-09-28 13:29:25 -0700554 }
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700555 std::string_view reqPathStripped =
556 std::string_view(reqPath).substr(0, reqPath.size() - 1);
557
558 if (!reqPathStripped.empty() &&
559 interfaceMap.find(reqPathStripped) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700560 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300561 throw sdbusplus::xyz::openbmc_project::Common::Error::
562 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700563 }
564
Brandon Kim82720f02022-07-08 09:57:22 -0700565 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400566 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700567 {
Brad Bishop1f623802022-05-31 18:22:10 -0400568 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700569
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700570 // Skip exact match on stripped search term
571 if (thisPath == reqPathStripped)
Ed Tanous0a13c762021-09-28 13:29:25 -0700572 {
573 continue;
574 }
575
Brad Bishop86d28802022-07-11 15:49:31 -0400576 if (thisPath.starts_with(reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700577 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700578 // count the number of slashes past the stripped search term
579 int32_t thisDepth = std::count(
580 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
Brad Bishopa098a372022-05-05 15:19:04 -0400581 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700582 {
Brad Bishop1f623802022-05-31 18:22:10 -0400583 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700584 {
585 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400586 interfaceMap.second.begin(),
587 interfaceMap.second.end()) ||
Ed Tanous0a13c762021-09-28 13:29:25 -0700588 interfaces.empty())
589 {
Brad Bishopa098a372022-05-05 15:19:04 -0400590 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700591 }
592 }
593 }
594 }
595 }
596
597 return ret;
598}
599
Brad Bishopa098a372022-05-05 15:19:04 -0400600std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
601 std::string reqPath, int32_t depth,
602 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700603{
604 if (depth <= 0)
605 {
606 depth = std::numeric_limits<int32_t>::max();
607 }
608 // Interfaces need to be sorted for intersect to function
609 std::sort(interfaces.begin(), interfaces.end());
Ed Tanous0a13c762021-09-28 13:29:25 -0700610
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700611 // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
612 // will be guaranteed not to have a trailing "/"
Brad Bishop86d28802022-07-11 15:49:31 -0400613 if (!reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700614 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700615 reqPath += "/";
Ed Tanous0a13c762021-09-28 13:29:25 -0700616 }
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700617 std::string_view reqPathStripped =
618 std::string_view(reqPath).substr(0, reqPath.size() - 1);
619
620 if (!reqPathStripped.empty() &&
621 interfaceMap.find(reqPathStripped) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700622 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300623 throw sdbusplus::xyz::openbmc_project::Common::Error::
624 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700625 }
626
Brandon Kim82720f02022-07-08 09:57:22 -0700627 std::vector<std::string> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400628 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700629 {
Brad Bishop1f623802022-05-31 18:22:10 -0400630 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700631
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700632 // Skip exact match on stripped search term
633 if (thisPath == reqPathStripped)
Ed Tanous0a13c762021-09-28 13:29:25 -0700634 {
635 continue;
636 }
637
Brad Bishop86d28802022-07-11 15:49:31 -0400638 if (thisPath.starts_with(reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700639 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700640 // count the number of slashes past the stripped search term
641 int thisDepth = std::count(
642 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
Brad Bishopa098a372022-05-05 15:19:04 -0400643 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700644 {
645 bool add = interfaces.empty();
Brad Bishop1f623802022-05-31 18:22:10 -0400646 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700647 {
648 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400649 interfaceMap.second.begin(),
650 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700651 {
652 add = true;
653 break;
654 }
655 }
656 if (add)
657 {
658 // TODO(ed) this is a copy
Brad Bishopa098a372022-05-05 15:19:04 -0400659 ret.emplace_back(thisPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700660 }
661 }
662 }
663 }
664
665 return ret;
666}
667
Ed Tanous60520632018-06-11 17:46:52 -0700668int main(int argc, char** argv)
669{
Matt Spinlerdd945862018-09-07 12:41:05 -0500670 auto options = ArgumentParser(argc, argv);
Ed Tanous21c60592020-08-17 23:43:46 -0700671 boost::asio::io_context io;
Brad Bishopa098a372022-05-05 15:19:04 -0400672 std::shared_ptr<sdbusplus::asio::connection> systemBus =
Ed Tanous60520632018-06-11 17:46:52 -0700673 std::make_shared<sdbusplus::asio::connection>(io);
674
Brad Bishopf944a452022-05-05 15:06:46 -0400675 splitArgs(options["service-namespaces"], serviceAllowList);
Matt Spinlerdd945862018-09-07 12:41:05 -0500676
Brad Bishopa098a372022-05-05 15:19:04 -0400677 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700678
679 // Construct a signal set registered for process termination.
680 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400681 signals.async_wait(
682 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700683
Brad Bishopa098a372022-05-05 15:19:04 -0400684 InterfaceMapType interfaceMap;
685 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700686
Patrick Williamscc8070b2022-07-22 19:26:55 -0500687 std::function<void(sdbusplus::message_t & message)> nameChangeHandler =
688 [&interfaceMap, &io, &nameOwners, &server,
689 systemBus](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400690 std::string name; // well-known
691 std::string oldOwner; // unique-name
692 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700693
Brad Bishopa098a372022-05-05 15:19:04 -0400694 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700695
Brad Bishopa098a372022-05-05 15:19:04 -0400696 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700697 {
Brad Bishopa098a372022-05-05 15:19:04 -0400698 processNameChangeDelete(nameOwners, name, oldOwner,
699 interfaceMap, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700700 }
701
Brad Bishopa098a372022-05-05 15:19:04 -0400702 if (!newOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700703 {
Brad Bishopd6aa5522022-05-31 19:23:48 -0400704#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700705 auto transaction = std::make_shared<
706 std::chrono::time_point<std::chrono::steady_clock>>(
707 std::chrono::steady_clock::now());
Matt Spinleraecabe82018-09-19 13:25:42 -0500708#endif
Ed Tanous60520632018-06-11 17:46:52 -0700709 // New daemon added
Brad Bishopd5542322022-06-02 19:56:23 -0400710 if (needToIntrospect(name, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700711 {
Brad Bishopa098a372022-05-05 15:19:04 -0400712 nameOwners[newOwner] = name;
713 startNewIntrospect(systemBus.get(), io, interfaceMap, name,
714 associationMaps,
Brad Bishopd6aa5522022-05-31 19:23:48 -0400715#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopa098a372022-05-05 15:19:04 -0400716 transaction,
Matt Spinleraecabe82018-09-19 13:25:42 -0500717#endif
Brad Bishopa098a372022-05-05 15:19:04 -0400718 server);
Ed Tanous60520632018-06-11 17:46:52 -0700719 }
720 }
721 };
722
Patrick Williamscc8070b2022-07-22 19:26:55 -0500723 sdbusplus::bus::match_t nameOwnerChanged(
724 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700725 sdbusplus::bus::match::rules::nameOwnerChanged(), nameChangeHandler);
726
Patrick Williamscc8070b2022-07-22 19:26:55 -0500727 std::function<void(sdbusplus::message_t & message)> interfacesAddedHandler =
728 [&interfaceMap, &nameOwners, &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400729 sdbusplus::message::object_path objPath;
730 InterfacesAdded interfacesAdded;
731 message.read(objPath, interfacesAdded);
732 std::string wellKnown;
733 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700734 {
735 return; // only introspect well-known
736 }
Brad Bishopd5542322022-06-02 19:56:23 -0400737 if (needToIntrospect(wellKnown, serviceAllowList))
Ed Tanous60520632018-06-11 17:46:52 -0700738 {
Brad Bishopa098a372022-05-05 15:19:04 -0400739 processInterfaceAdded(interfaceMap, objPath, interfacesAdded,
740 wellKnown, associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700741 }
742 };
743
Patrick Williamscc8070b2022-07-22 19:26:55 -0500744 sdbusplus::bus::match_t interfacesAdded(
745 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700746 sdbusplus::bus::match::rules::interfacesAdded(),
747 interfacesAddedHandler);
748
Patrick Williamscc8070b2022-07-22 19:26:55 -0500749 std::function<void(sdbusplus::message_t & message)>
750 interfacesRemovedHandler = [&interfaceMap, &nameOwners,
751 &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400752 sdbusplus::message::object_path objPath;
753 std::vector<std::string> interfacesRemoved;
754 message.read(objPath, interfacesRemoved);
755 auto connectionMap = interfaceMap.find(objPath.str);
756 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700757 {
758 return;
759 }
760
761 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400762 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700763 {
764 return;
765 }
Brad Bishopa098a372022-05-05 15:19:04 -0400766 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700767 {
Brad Bishopa098a372022-05-05 15:19:04 -0400768 auto interfaceSet = connectionMap->second.find(sender);
769 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700770 {
771 continue;
772 }
773
John Wangd0cf9422019-09-17 16:01:34 +0800774 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700775 {
Brad Bishopa098a372022-05-05 15:19:04 -0400776 removeAssociation(objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500777 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700778 }
779
Brad Bishopa098a372022-05-05 15:19:04 -0400780 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500781
Brad Bishopa098a372022-05-05 15:19:04 -0400782 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700783 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500784 // If this was the last interface on this connection,
785 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400786 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500787
788 // Instead of checking if every single path is the endpoint
789 // of an association that needs to be moved to pending,
790 // only check when the only remaining owner of this path is
791 // ourself, which would be because we still own the
792 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400793 if ((connectionMap->second.size() == 1) &&
794 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400795 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500796 {
797 // Remove the 2 association D-Bus paths and move the
798 // association to pending.
Brad Bishopa098a372022-05-05 15:19:04 -0400799 moveAssociationToPending(objPath.str, associationMaps,
Matt Spinler9c3d2852019-04-08 15:57:19 -0500800 server);
801 }
Ed Tanous60520632018-06-11 17:46:52 -0700802 }
803 }
804 // If this was the last connection on this object path,
805 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400806 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700807 {
Brad Bishopa098a372022-05-05 15:19:04 -0400808 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700809 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600810
Brad Bishopa098a372022-05-05 15:19:04 -0400811 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700812 };
813
Patrick Williamscc8070b2022-07-22 19:26:55 -0500814 sdbusplus::bus::match_t interfacesRemoved(
815 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700816 sdbusplus::bus::match::rules::interfacesRemoved(),
817 interfacesRemovedHandler);
818
Patrick Williamscc8070b2022-07-22 19:26:55 -0500819 std::function<void(sdbusplus::message_t & message)>
Brad Bishopa098a372022-05-05 15:19:04 -0400820 associationChangedHandler = [&server, &nameOwners, &interfaceMap](
Patrick Williamscc8070b2022-07-22 19:26:55 -0500821 sdbusplus::message_t& message) {
Matt Spinler8f876a52019-04-15 13:22:50 -0500822 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500823 boost::container::flat_map<std::string,
824 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500825 values;
826 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800827 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500828 if (prop != values.end())
829 {
830 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500831 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500832
Brad Bishopa098a372022-05-05 15:19:04 -0400833 std::string wellKnown;
834 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500835 {
836 return;
Ed Tanous60520632018-06-11 17:46:52 -0700837 }
Matt Spinler8f876a52019-04-15 13:22:50 -0500838 associationChanged(server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400839 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500840 }
841 };
Patrick Williamscc8070b2022-07-22 19:26:55 -0500842 sdbusplus::bus::match_t assocChangedMatch(
843 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700844 sdbusplus::bus::match::rules::interface(
845 "org.freedesktop.DBus.Properties") +
846 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500847 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
848 associationChangedHandler);
849
Ed Tanous60520632018-06-11 17:46:52 -0700850 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400851 server.add_interface("/xyz/openbmc_project/object_mapper",
852 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700853
854 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400855 "GetAncestors", [&interfaceMap](std::string& reqPath,
856 std::vector<std::string>& interfaces) {
857 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700858 });
859
860 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400861 "GetObject", [&interfaceMap](const std::string& path,
862 std::vector<std::string>& interfaces) {
863 return getObject(interfaceMap, path, interfaces);
864 });
865
866 iface->register_method(
867 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700868 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400869 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700870 });
871
872 iface->register_method(
873 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400874 [&interfaceMap](std::string& reqPath, int32_t depth,
875 std::vector<std::string>& interfaces) {
876 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700877 });
878
879 iface->initialize();
880
881 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400882 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500883 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700884 });
885
Brad Bishopa098a372022-05-05 15:19:04 -0400886 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500887
Ed Tanous60520632018-06-11 17:46:52 -0700888 io.run();
889}