blob: 767bda080fbfe84de83c3f2560fd6ca1c5283761 [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 Spinler35396c12019-04-05 11:46:57 -05003#include "types.hpp"
Matt Spinlerdd945862018-09-07 12:41:05 -05004
Ed Tanous60520632018-06-11 17:46:52 -07005#include <tinyxml2.h>
6
Ed Tanous21c60592020-08-17 23:43:46 -07007#include <boost/asio/io_context.hpp>
8#include <boost/asio/signal_set.hpp>
Ed Tanous60520632018-06-11 17:46:52 -07009#include <boost/container/flat_map.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070010#include <sdbusplus/asio/connection.hpp>
11#include <sdbusplus/asio/object_server.hpp>
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +030012#include <xyz/openbmc_project/Common/error.hpp>
Ed Tanous60520632018-06-11 17:46:52 -070013
Brad Bishop23520882022-05-26 21:39:53 -040014#include <atomic>
15#include <chrono>
Brad Bishopea119462022-05-31 20:32:04 -040016#include <exception>
Brad Bishop23520882022-05-26 21:39:53 -040017#include <iomanip>
18#include <iostream>
Brandon Kimf6ebfc72022-07-07 12:53:44 -070019#include <string>
20#include <string_view>
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 Bishopa098a372022-05-05 15:19:04 -040025void updateOwners(sdbusplus::asio::connection* conn,
26 boost::container::flat_map<std::string, std::string>& owners,
27 const std::string& newObject)
Ed Tanous60520632018-06-11 17:46:52 -070028{
Brad Bishop86d28802022-07-11 15:49:31 -040029 if (newObject.starts_with(":"))
Ed Tanous60520632018-06-11 17:46:52 -070030 {
31 return;
32 }
33 conn->async_method_call(
Brad Bishopa098a372022-05-05 15:19:04 -040034 [&, newObject](const boost::system::error_code ec,
35 const std::string& nameOwner) {
Ed Tanous60520632018-06-11 17:46:52 -070036 if (ec)
37 {
Brad Bishopa098a372022-05-05 15:19:04 -040038 std::cerr << "Error getting owner of " << newObject << " : "
Ed Tanous60520632018-06-11 17:46:52 -070039 << ec << "\n";
40 return;
41 }
Brad Bishopa098a372022-05-05 15:19:04 -040042 owners[nameOwner] = newObject;
Ed Tanous60520632018-06-11 17:46:52 -070043 },
44 "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner",
Brad Bishopa098a372022-05-05 15:19:04 -040045 newObject);
Ed Tanous60520632018-06-11 17:46:52 -070046}
47
Brad Bishopa098a372022-05-05 15:19:04 -040048void sendIntrospectionCompleteSignal(sdbusplus::asio::connection* systemBus,
49 const std::string& processName)
Ed Tanous60520632018-06-11 17:46:52 -070050{
51 // TODO(ed) This signal doesn't get exposed properly in the
52 // introspect right now. Find out how to register signals in
53 // sdbusplus
Patrick Williamscc8070b2022-07-22 19:26:55 -050054 sdbusplus::message_t m = systemBus->new_signal(
Brad Bishopa02cd542021-10-12 19:12:42 -040055 "/xyz/openbmc_project/object_mapper",
56 "xyz.openbmc_project.ObjectMapper.Private", "IntrospectionComplete");
Brad Bishopa098a372022-05-05 15:19:04 -040057 m.append(processName);
Ed Tanous60520632018-06-11 17:46:52 -070058 m.signal_send();
59}
60
61struct InProgressIntrospect
62{
Brad Bishop1f623802022-05-31 18:22:10 -040063 InProgressIntrospect() = delete;
64 InProgressIntrospect(const InProgressIntrospect&) = delete;
65 InProgressIntrospect(InProgressIntrospect&&) = delete;
66 InProgressIntrospect& operator=(const InProgressIntrospect&) = delete;
67 InProgressIntrospect& operator=(InProgressIntrospect&&) = delete;
Ed Tanous60520632018-06-11 17:46:52 -070068 InProgressIntrospect(
Brad Bishopa098a372022-05-05 15:19:04 -040069 sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
70 const std::string& processName, AssociationMaps& am
Brad Bishopd6aa5522022-05-31 19:23:48 -040071#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050072 ,
Ed Tanous60520632018-06-11 17:46:52 -070073 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -040074 globalStartTime
Matt Spinleraecabe82018-09-19 13:25:42 -050075#endif
76 ) :
Brad Bishopa098a372022-05-05 15:19:04 -040077 systemBus(systemBus),
78 io(io), processName(processName), assocMaps(am)
Brad Bishopd6aa5522022-05-31 19:23:48 -040079#ifdef MAPPER_ENABLE_DEBUG
Matt Spinleraecabe82018-09-19 13:25:42 -050080 ,
Brad Bishop1f623802022-05-31 18:22:10 -040081 globalStartTime(std::move(globalStartTime)),
Brad Bishopa098a372022-05-05 15:19:04 -040082 processStartTime(std::chrono::steady_clock::now())
Matt Spinleraecabe82018-09-19 13:25:42 -050083#endif
Brad Bishop23520882022-05-26 21:39:53 -040084 {}
Ed Tanous60520632018-06-11 17:46:52 -070085 ~InProgressIntrospect()
86 {
Brad Bishopea119462022-05-31 20:32:04 -040087 try
Ed Tanous60520632018-06-11 17:46:52 -070088 {
Brad Bishopea119462022-05-31 20:32:04 -040089 sendIntrospectionCompleteSignal(systemBus, processName);
Brad Bishopd6aa5522022-05-31 19:23:48 -040090#ifdef MAPPER_ENABLE_DEBUG
Brad Bishopea119462022-05-31 20:32:04 -040091 std::chrono::duration<float> diff =
92 std::chrono::steady_clock::now() - processStartTime;
93 std::cout << std::setw(50) << processName << " scan took "
94 << diff.count() << " seconds\n";
95
96 // If we're the last outstanding caller globally, calculate the
97 // time it took
98 if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
99 {
100 diff = std::chrono::steady_clock::now() - *globalStartTime;
101 std::cout << "Total scan took " << diff.count()
102 << " seconds to complete\n";
103 }
Matt Spinleraecabe82018-09-19 13:25:42 -0500104#endif
Brad Bishopea119462022-05-31 20:32:04 -0400105 }
106 catch (const std::exception& e)
107 {
108 std::cerr
109 << "Terminating, unhandled exception while introspecting: "
110 << e.what() << "\n";
111 std::terminate();
112 }
113 catch (...)
114 {
115 std::cerr
116 << "Terminating, unhandled exception while introspecting\n";
117 std::terminate();
118 }
Ed Tanous60520632018-06-11 17:46:52 -0700119 }
Brad Bishopa098a372022-05-05 15:19:04 -0400120 sdbusplus::asio::connection* systemBus;
Ed Tanous21c60592020-08-17 23:43:46 -0700121 boost::asio::io_context& io;
Brad Bishopa098a372022-05-05 15:19:04 -0400122 std::string processName;
Matt Spinler11401e22019-04-08 13:13:25 -0500123 AssociationMaps& assocMaps;
Brad Bishopd6aa5522022-05-31 19:23:48 -0400124#ifdef MAPPER_ENABLE_DEBUG
Ed Tanous60520632018-06-11 17:46:52 -0700125 std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
Brad Bishopa098a372022-05-05 15:19:04 -0400126 globalStartTime;
127 std::chrono::time_point<std::chrono::steady_clock> processStartTime;
Matt Spinleraecabe82018-09-19 13:25:42 -0500128#endif
Ed Tanous60520632018-06-11 17:46:52 -0700129};
130
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200131void doAssociations(boost::asio::io_context& io,
132 sdbusplus::asio::connection* systemBus,
Brad Bishopa098a372022-05-05 15:19:04 -0400133 InterfaceMapType& interfaceMap,
134 sdbusplus::asio::object_server& objectServer,
135 const std::string& processName, const std::string& path,
136 int timeoutRetries = 0)
Ed Tanous60520632018-06-11 17:46:52 -0700137{
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100138 constexpr int maxTimeoutRetries = 3;
Brad Bishopa098a372022-05-05 15:19:04 -0400139 systemBus->async_method_call(
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200140 [&io, &objectServer, path, processName, &interfaceMap, systemBus,
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100141 timeoutRetries](
Matt Spinler937a2322019-01-23 13:54:22 -0600142 const boost::system::error_code ec,
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500143 const std::variant<std::vector<Association>>& variantAssociations) {
Ed Tanous60520632018-06-11 17:46:52 -0700144 if (ec)
145 {
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100146 if (ec.value() == boost::system::errc::timed_out &&
147 timeoutRetries < maxTimeoutRetries)
148 {
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200149 doAssociations(io, systemBus, interfaceMap, objectServer,
Brad Bishopa098a372022-05-05 15:19:04 -0400150 processName, path, timeoutRetries + 1);
Adrian Ambrożewiczbb40bd32021-02-12 13:36:26 +0100151 return;
152 }
Ed Tanous60520632018-06-11 17:46:52 -0700153 std::cerr << "Error getting associations from " << path << "\n";
154 }
155 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500156 std::get<std::vector<Association>>(variantAssociations);
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200157 associationChanged(io, objectServer, associations, path,
158 processName, interfaceMap, associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700159 },
160 processName, path, "org.freedesktop.DBus.Properties", "Get",
John Wangd0cf9422019-09-17 16:01:34 +0800161 assocDefsInterface, assocDefsProperty);
Ed Tanous60520632018-06-11 17:46:52 -0700162}
163
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200164void doIntrospect(boost::asio::io_context& io,
165 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(
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200173 [&io, &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 {
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200181 doIntrospect(io, systemBus, transaction, interfaceMap,
Brad Bishopa098a372022-05-05 15:19:04 -0400182 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 {
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200222 doAssociations(io, systemBus, interfaceMap, objectServer,
Brad Bishopa098a372022-05-05 15:19:04 -0400223 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.
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200231 checkIfPendingAssociation(io, 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
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200246 doIntrospect(io, systemBus, transaction, interfaceMap,
Brad Bishopa098a372022-05-05 15:19:04 -0400247 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 Bishop1e94e602022-06-02 19:47:53 -0400266 if (needToIntrospect(processName))
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
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200277 doIntrospect(io, systemBus, transaction, interfaceMap, objectServer,
278 "/");
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 Bishop1e94e602022-06-02 19:47:53 -0400329 if (needToIntrospect(processName))
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
Ed Tanous964681c2022-07-08 12:47:24 -0700345void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
346 const std::string& objectPath,
347 const ConnectionNames::value_type& interfaceMap)
Matt Spinler9f0958e2018-09-11 08:26:10 -0500348{
349 // Adds an object path/service name/interface list entry to
Matt Spinler47c09752018-11-29 14:54:13 -0600350 // the results of GetSubTree and GetAncestors.
Matt Spinler9f0958e2018-09-11 08:26:10 -0500351 // If an entry for the object path already exists, just add the
352 // service name and interfaces to that entry, otherwise create
353 // a new entry.
354 auto entry = std::find_if(
Matt Spinler47c09752018-11-29 14:54:13 -0600355 objectMap.begin(), objectMap.end(),
Matt Spinler9f0958e2018-09-11 08:26:10 -0500356 [&objectPath](const auto& i) { return objectPath == i.first; });
357
Matt Spinler47c09752018-11-29 14:54:13 -0600358 if (entry != objectMap.end())
Matt Spinler9f0958e2018-09-11 08:26:10 -0500359 {
360 entry->second.emplace(interfaceMap);
361 }
362 else
363 {
Brad Bishopa098a372022-05-05 15:19:04 -0400364 InterfaceMapType::value_type object;
Matt Spinler9f0958e2018-09-11 08:26:10 -0500365 object.first = objectPath;
366 object.second.emplace(interfaceMap);
Matt Spinler47c09752018-11-29 14:54:13 -0600367 objectMap.push_back(object);
Matt Spinler9f0958e2018-09-11 08:26:10 -0500368 }
369}
370
Matt Spinlera82779f2019-01-09 12:39:42 -0600371// Remove parents of the passed in path that:
372// 1) Only have the 3 default interfaces on them
373// - Means D-Bus created these, not application code,
374// with the Properties, Introspectable, and Peer ifaces
375// 2) Have no other child for this owner
376void removeUnneededParents(const std::string& objectPath,
377 const std::string& owner,
Brad Bishopa098a372022-05-05 15:19:04 -0400378 InterfaceMapType& interfaceMap)
Matt Spinlera82779f2019-01-09 12:39:42 -0600379{
380 auto parent = objectPath;
381
382 while (true)
383 {
384 auto pos = parent.find_last_of('/');
385 if ((pos == std::string::npos) || (pos == 0))
386 {
387 break;
388 }
389 parent = parent.substr(0, pos);
390
Brad Bishopa098a372022-05-05 15:19:04 -0400391 auto parentIt = interfaceMap.find(parent);
392 if (parentIt == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600393 {
394 break;
395 }
396
Brad Bishopa098a372022-05-05 15:19:04 -0400397 auto ifacesIt = parentIt->second.find(owner);
398 if (ifacesIt == parentIt->second.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600399 {
400 break;
401 }
402
Brad Bishopa098a372022-05-05 15:19:04 -0400403 if (ifacesIt->second.size() != 3)
Matt Spinlera82779f2019-01-09 12:39:42 -0600404 {
405 break;
406 }
407
Brad Bishopa098a372022-05-05 15:19:04 -0400408 auto childPath = parent + '/';
Matt Spinlera82779f2019-01-09 12:39:42 -0600409
410 // Remove this parent if there isn't a remaining child on this owner
411 auto child = std::find_if(
Brad Bishopa098a372022-05-05 15:19:04 -0400412 interfaceMap.begin(), interfaceMap.end(),
413 [&owner, &childPath](const auto& entry) {
Brad Bishop86d28802022-07-11 15:49:31 -0400414 return entry.first.starts_with(childPath) &&
Matt Spinlera82779f2019-01-09 12:39:42 -0600415 (entry.second.find(owner) != entry.second.end());
416 });
417
Brad Bishopa098a372022-05-05 15:19:04 -0400418 if (child == interfaceMap.end())
Matt Spinlera82779f2019-01-09 12:39:42 -0600419 {
Brad Bishopa098a372022-05-05 15:19:04 -0400420 parentIt->second.erase(ifacesIt);
421 if (parentIt->second.empty())
Matt Spinlera82779f2019-01-09 12:39:42 -0600422 {
Brad Bishopa098a372022-05-05 15:19:04 -0400423 interfaceMap.erase(parentIt);
Matt Spinlera82779f2019-01-09 12:39:42 -0600424 }
425 }
426 else
427 {
428 break;
429 }
430 }
431}
432
Brad Bishopa098a372022-05-05 15:19:04 -0400433std::vector<InterfaceMapType::value_type>
434 getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700435 std::vector<std::string>& interfaces)
436{
437 // Interfaces need to be sorted for intersect to function
438 std::sort(interfaces.begin(), interfaces.end());
439
Brad Bishop86d28802022-07-11 15:49:31 -0400440 if (reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700441 {
Brad Bishopa098a372022-05-05 15:19:04 -0400442 reqPath.pop_back();
Ed Tanous0a13c762021-09-28 13:29:25 -0700443 }
Brad Bishop1f623802022-05-31 18:22:10 -0400444 if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700445 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300446 throw sdbusplus::xyz::openbmc_project::Common::Error::
447 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700448 }
449
Brad Bishopa098a372022-05-05 15:19:04 -0400450 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400451 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700452 {
Brad Bishop1f623802022-05-31 18:22:10 -0400453 const auto& thisPath = objectPath.first;
Brandon Kim82720f02022-07-08 09:57:22 -0700454
455 if (reqPath == thisPath)
456 {
457 continue;
458 }
459
Brad Bishop86d28802022-07-11 15:49:31 -0400460 if (reqPath.starts_with(thisPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700461 {
462 if (interfaces.empty())
463 {
Brad Bishopa098a372022-05-05 15:19:04 -0400464 ret.emplace_back(objectPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700465 }
466 else
467 {
Brad Bishop1f623802022-05-31 18:22:10 -0400468 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700469 {
Ed Tanous0a13c762021-09-28 13:29:25 -0700470 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400471 interfaceMap.second.begin(),
472 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700473 {
Brad Bishopa098a372022-05-05 15:19:04 -0400474 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700475 }
476 }
477 }
478 }
479 }
480
481 return ret;
482}
483
Ed Tanous964681c2022-07-08 12:47:24 -0700484ConnectionNames getObject(const InterfaceMapType& interfaceMap,
485 const std::string& path,
486 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700487{
Ed Tanous964681c2022-07-08 12:47:24 -0700488 ConnectionNames results;
Ed Tanous0a13c762021-09-28 13:29:25 -0700489
490 // Interfaces need to be sorted for intersect to function
491 std::sort(interfaces.begin(), interfaces.end());
Brad Bishopa098a372022-05-05 15:19:04 -0400492 auto pathRef = interfaceMap.find(path);
493 if (pathRef == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700494 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300495 throw sdbusplus::xyz::openbmc_project::Common::Error::
496 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700497 }
498 if (interfaces.empty())
499 {
Brad Bishopa098a372022-05-05 15:19:04 -0400500 return pathRef->second;
Ed Tanous0a13c762021-09-28 13:29:25 -0700501 }
Brad Bishop1f623802022-05-31 18:22:10 -0400502 for (const auto& interfaceMap : pathRef->second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700503 {
504 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400505 interfaceMap.second.begin(), interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700506 {
Brad Bishopa098a372022-05-05 15:19:04 -0400507 results.emplace(interfaceMap.first, interfaceMap.second);
Ed Tanous0a13c762021-09-28 13:29:25 -0700508 }
509 }
510
511 if (results.empty())
512 {
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
517 return results;
518}
519
Brad Bishopa098a372022-05-05 15:19:04 -0400520std::vector<InterfaceMapType::value_type>
521 getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
Ed Tanous0a13c762021-09-28 13:29:25 -0700522 int32_t depth, std::vector<std::string>& interfaces)
523{
524 if (depth <= 0)
525 {
526 depth = std::numeric_limits<int32_t>::max();
527 }
528 // Interfaces need to be sorted for intersect to function
529 std::sort(interfaces.begin(), interfaces.end());
Ed Tanous0a13c762021-09-28 13:29:25 -0700530
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700531 // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
532 // will be guaranteed not to have a trailing "/"
Brad Bishop86d28802022-07-11 15:49:31 -0400533 if (!reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700534 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700535 reqPath += "/";
Ed Tanous0a13c762021-09-28 13:29:25 -0700536 }
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700537 std::string_view reqPathStripped =
538 std::string_view(reqPath).substr(0, reqPath.size() - 1);
539
540 if (!reqPathStripped.empty() &&
541 interfaceMap.find(reqPathStripped) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700542 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300543 throw sdbusplus::xyz::openbmc_project::Common::Error::
544 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700545 }
546
Brandon Kim82720f02022-07-08 09:57:22 -0700547 std::vector<InterfaceMapType::value_type> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400548 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700549 {
Brad Bishop1f623802022-05-31 18:22:10 -0400550 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700551
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700552 // Skip exact match on stripped search term
553 if (thisPath == reqPathStripped)
Ed Tanous0a13c762021-09-28 13:29:25 -0700554 {
555 continue;
556 }
557
Brad Bishop86d28802022-07-11 15:49:31 -0400558 if (thisPath.starts_with(reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700559 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700560 // count the number of slashes past the stripped search term
561 int32_t thisDepth = std::count(
562 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
Brad Bishopa098a372022-05-05 15:19:04 -0400563 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700564 {
Brad Bishop1f623802022-05-31 18:22:10 -0400565 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700566 {
567 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400568 interfaceMap.second.begin(),
569 interfaceMap.second.end()) ||
Ed Tanous0a13c762021-09-28 13:29:25 -0700570 interfaces.empty())
571 {
Brad Bishopa098a372022-05-05 15:19:04 -0400572 addObjectMapResult(ret, thisPath, interfaceMap);
Ed Tanous0a13c762021-09-28 13:29:25 -0700573 }
574 }
575 }
576 }
577 }
578
579 return ret;
580}
581
Brad Bishopa098a372022-05-05 15:19:04 -0400582std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
583 std::string reqPath, int32_t depth,
584 std::vector<std::string>& interfaces)
Ed Tanous0a13c762021-09-28 13:29:25 -0700585{
586 if (depth <= 0)
587 {
588 depth = std::numeric_limits<int32_t>::max();
589 }
590 // Interfaces need to be sorted for intersect to function
591 std::sort(interfaces.begin(), interfaces.end());
Ed Tanous0a13c762021-09-28 13:29:25 -0700592
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700593 // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
594 // will be guaranteed not to have a trailing "/"
Brad Bishop86d28802022-07-11 15:49:31 -0400595 if (!reqPath.ends_with("/"))
Ed Tanous0a13c762021-09-28 13:29:25 -0700596 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700597 reqPath += "/";
Ed Tanous0a13c762021-09-28 13:29:25 -0700598 }
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700599 std::string_view reqPathStripped =
600 std::string_view(reqPath).substr(0, reqPath.size() - 1);
601
602 if (!reqPathStripped.empty() &&
603 interfaceMap.find(reqPathStripped) == interfaceMap.end())
Ed Tanous0a13c762021-09-28 13:29:25 -0700604 {
Konstantin Aladyshevb15df6b2022-01-11 14:50:55 +0300605 throw sdbusplus::xyz::openbmc_project::Common::Error::
606 ResourceNotFound();
Ed Tanous0a13c762021-09-28 13:29:25 -0700607 }
608
Brandon Kim82720f02022-07-08 09:57:22 -0700609 std::vector<std::string> ret;
Brad Bishop1f623802022-05-31 18:22:10 -0400610 for (const auto& objectPath : interfaceMap)
Ed Tanous0a13c762021-09-28 13:29:25 -0700611 {
Brad Bishop1f623802022-05-31 18:22:10 -0400612 const auto& thisPath = objectPath.first;
Ed Tanous0a13c762021-09-28 13:29:25 -0700613
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700614 // Skip exact match on stripped search term
615 if (thisPath == reqPathStripped)
Ed Tanous0a13c762021-09-28 13:29:25 -0700616 {
617 continue;
618 }
619
Brad Bishop86d28802022-07-11 15:49:31 -0400620 if (thisPath.starts_with(reqPath))
Ed Tanous0a13c762021-09-28 13:29:25 -0700621 {
Brandon Kimf6ebfc72022-07-07 12:53:44 -0700622 // count the number of slashes past the stripped search term
623 int thisDepth = std::count(
624 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
Brad Bishopa098a372022-05-05 15:19:04 -0400625 if (thisDepth <= depth)
Ed Tanous0a13c762021-09-28 13:29:25 -0700626 {
627 bool add = interfaces.empty();
Brad Bishop1f623802022-05-31 18:22:10 -0400628 for (const auto& interfaceMap : objectPath.second)
Ed Tanous0a13c762021-09-28 13:29:25 -0700629 {
630 if (intersect(interfaces.begin(), interfaces.end(),
Brad Bishopa098a372022-05-05 15:19:04 -0400631 interfaceMap.second.begin(),
632 interfaceMap.second.end()))
Ed Tanous0a13c762021-09-28 13:29:25 -0700633 {
634 add = true;
635 break;
636 }
637 }
638 if (add)
639 {
640 // TODO(ed) this is a copy
Brad Bishopa098a372022-05-05 15:19:04 -0400641 ret.emplace_back(thisPath);
Ed Tanous0a13c762021-09-28 13:29:25 -0700642 }
643 }
644 }
645 }
646
647 return ret;
648}
649
Brad Bishop1e94e602022-06-02 19:47:53 -0400650int main()
Ed Tanous60520632018-06-11 17:46:52 -0700651{
Ed Tanous21c60592020-08-17 23:43:46 -0700652 boost::asio::io_context io;
Brad Bishopa098a372022-05-05 15:19:04 -0400653 std::shared_ptr<sdbusplus::asio::connection> systemBus =
Ed Tanous60520632018-06-11 17:46:52 -0700654 std::make_shared<sdbusplus::asio::connection>(io);
655
Brad Bishopa098a372022-05-05 15:19:04 -0400656 sdbusplus::asio::object_server server(systemBus);
Ed Tanous60520632018-06-11 17:46:52 -0700657
658 // Construct a signal set registered for process termination.
659 boost::asio::signal_set signals(io, SIGINT, SIGTERM);
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400660 signals.async_wait(
661 [&io](const boost::system::error_code&, int) { io.stop(); });
Ed Tanous60520632018-06-11 17:46:52 -0700662
Brad Bishopa098a372022-05-05 15:19:04 -0400663 InterfaceMapType interfaceMap;
664 boost::container::flat_map<std::string, std::string> nameOwners;
Ed Tanous60520632018-06-11 17:46:52 -0700665
Patrick Williamscc8070b2022-07-22 19:26:55 -0500666 std::function<void(sdbusplus::message_t & message)> nameChangeHandler =
667 [&interfaceMap, &io, &nameOwners, &server,
668 systemBus](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400669 std::string name; // well-known
670 std::string oldOwner; // unique-name
671 std::string newOwner; // unique-name
Ed Tanous60520632018-06-11 17:46:52 -0700672
Brad Bishopa098a372022-05-05 15:19:04 -0400673 message.read(name, oldOwner, newOwner);
Ed Tanous60520632018-06-11 17:46:52 -0700674
Patrick Williams48248202022-10-10 10:26:47 -0500675 if (name.starts_with(':'))
676 {
677 // We should do nothing with unique-name connections.
678 return;
679 }
680
Brad Bishopa098a372022-05-05 15:19:04 -0400681 if (!oldOwner.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700682 {
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200683 processNameChangeDelete(io, nameOwners, name, oldOwner,
Brad Bishopa098a372022-05-05 15:19:04 -0400684 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 Bishop1e94e602022-06-02 19:47:53 -0400695 if (needToIntrospect(name))
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 =
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200713 [&io, &interfaceMap, &nameOwners,
714 &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400715 sdbusplus::message::object_path objPath;
716 InterfacesAdded interfacesAdded;
717 message.read(objPath, interfacesAdded);
718 std::string wellKnown;
719 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700720 {
721 return; // only introspect well-known
722 }
Brad Bishop1e94e602022-06-02 19:47:53 -0400723 if (needToIntrospect(wellKnown))
Ed Tanous60520632018-06-11 17:46:52 -0700724 {
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200725 processInterfaceAdded(io, interfaceMap, objPath,
726 interfacesAdded, wellKnown,
727 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700728 }
729 };
730
Patrick Williamscc8070b2022-07-22 19:26:55 -0500731 sdbusplus::bus::match_t interfacesAdded(
732 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700733 sdbusplus::bus::match::rules::interfacesAdded(),
734 interfacesAddedHandler);
735
Patrick Williamscc8070b2022-07-22 19:26:55 -0500736 std::function<void(sdbusplus::message_t & message)>
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200737 interfacesRemovedHandler = [&io, &interfaceMap, &nameOwners,
Patrick Williamscc8070b2022-07-22 19:26:55 -0500738 &server](sdbusplus::message_t& message) {
Brad Bishopa098a372022-05-05 15:19:04 -0400739 sdbusplus::message::object_path objPath;
740 std::vector<std::string> interfacesRemoved;
741 message.read(objPath, interfacesRemoved);
742 auto connectionMap = interfaceMap.find(objPath.str);
743 if (connectionMap == interfaceMap.end())
Ed Tanous60520632018-06-11 17:46:52 -0700744 {
745 return;
746 }
747
748 std::string sender;
Brad Bishopa098a372022-05-05 15:19:04 -0400749 if (!getWellKnown(nameOwners, message.get_sender(), sender))
Ed Tanous60520632018-06-11 17:46:52 -0700750 {
751 return;
752 }
Brad Bishopa098a372022-05-05 15:19:04 -0400753 for (const std::string& interface : interfacesRemoved)
Ed Tanous60520632018-06-11 17:46:52 -0700754 {
Brad Bishopa098a372022-05-05 15:19:04 -0400755 auto interfaceSet = connectionMap->second.find(sender);
756 if (interfaceSet == connectionMap->second.end())
Ed Tanous60520632018-06-11 17:46:52 -0700757 {
758 continue;
759 }
760
John Wangd0cf9422019-09-17 16:01:34 +0800761 if (interface == assocDefsInterface)
Ed Tanous60520632018-06-11 17:46:52 -0700762 {
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200763 removeAssociation(io, objPath.str, sender, server,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500764 associationMaps);
Ed Tanous60520632018-06-11 17:46:52 -0700765 }
766
Brad Bishopa098a372022-05-05 15:19:04 -0400767 interfaceSet->second.erase(interface);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500768
Brad Bishopa098a372022-05-05 15:19:04 -0400769 if (interfaceSet->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700770 {
Matt Spinler9c3d2852019-04-08 15:57:19 -0500771 // If this was the last interface on this connection,
772 // erase the connection
Brad Bishopa098a372022-05-05 15:19:04 -0400773 connectionMap->second.erase(interfaceSet);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500774
775 // Instead of checking if every single path is the endpoint
776 // of an association that needs to be moved to pending,
777 // only check when the only remaining owner of this path is
778 // ourself, which would be because we still own the
779 // association path.
Brad Bishopa098a372022-05-05 15:19:04 -0400780 if ((connectionMap->second.size() == 1) &&
781 (connectionMap->second.begin()->first ==
Brad Bishopa02cd542021-10-12 19:12:42 -0400782 "xyz.openbmc_project.ObjectMapper"))
Matt Spinler9c3d2852019-04-08 15:57:19 -0500783 {
784 // Remove the 2 association D-Bus paths and move the
785 // association to pending.
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200786 moveAssociationToPending(io, objPath.str,
787 associationMaps, server);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500788 }
Ed Tanous60520632018-06-11 17:46:52 -0700789 }
790 }
791 // If this was the last connection on this object path,
792 // erase the object path
Brad Bishopa098a372022-05-05 15:19:04 -0400793 if (connectionMap->second.empty())
Ed Tanous60520632018-06-11 17:46:52 -0700794 {
Brad Bishopa098a372022-05-05 15:19:04 -0400795 interfaceMap.erase(connectionMap);
Ed Tanous60520632018-06-11 17:46:52 -0700796 }
Matt Spinlera82779f2019-01-09 12:39:42 -0600797
Brad Bishopa098a372022-05-05 15:19:04 -0400798 removeUnneededParents(objPath.str, sender, interfaceMap);
Ed Tanous60520632018-06-11 17:46:52 -0700799 };
800
Patrick Williamscc8070b2022-07-22 19:26:55 -0500801 sdbusplus::bus::match_t interfacesRemoved(
802 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700803 sdbusplus::bus::match::rules::interfacesRemoved(),
804 interfacesRemovedHandler);
805
Patrick Williamscc8070b2022-07-22 19:26:55 -0500806 std::function<void(sdbusplus::message_t & message)>
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200807 associationChangedHandler = [&io, &server, &nameOwners, &interfaceMap](
Patrick Williamscc8070b2022-07-22 19:26:55 -0500808 sdbusplus::message_t& message) {
Matt Spinler8f876a52019-04-15 13:22:50 -0500809 std::string objectName;
Patrick Williams2bb2d6b2020-05-13 17:59:02 -0500810 boost::container::flat_map<std::string,
811 std::variant<std::vector<Association>>>
Matt Spinler8f876a52019-04-15 13:22:50 -0500812 values;
813 message.read(objectName, values);
John Wangd0cf9422019-09-17 16:01:34 +0800814 auto prop = values.find(assocDefsProperty);
Matt Spinler8f876a52019-04-15 13:22:50 -0500815 if (prop != values.end())
816 {
817 std::vector<Association> associations =
Patrick Williamsb05bc122020-05-13 12:21:00 -0500818 std::get<std::vector<Association>>(prop->second);
Matt Spinler8f876a52019-04-15 13:22:50 -0500819
Brad Bishopa098a372022-05-05 15:19:04 -0400820 std::string wellKnown;
821 if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
Matt Spinler8f876a52019-04-15 13:22:50 -0500822 {
823 return;
Ed Tanous60520632018-06-11 17:46:52 -0700824 }
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200825 associationChanged(io, server, associations, message.get_path(),
Brad Bishopa098a372022-05-05 15:19:04 -0400826 wellKnown, interfaceMap, associationMaps);
Matt Spinler8f876a52019-04-15 13:22:50 -0500827 }
828 };
Patrick Williamscc8070b2022-07-22 19:26:55 -0500829 sdbusplus::bus::match_t assocChangedMatch(
830 static_cast<sdbusplus::bus_t&>(*systemBus),
Ed Tanous60520632018-06-11 17:46:52 -0700831 sdbusplus::bus::match::rules::interface(
832 "org.freedesktop.DBus.Properties") +
833 sdbusplus::bus::match::rules::member("PropertiesChanged") +
Matt Spinler8f876a52019-04-15 13:22:50 -0500834 sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
835 associationChangedHandler);
836
Ed Tanous60520632018-06-11 17:46:52 -0700837 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
Brad Bishopa02cd542021-10-12 19:12:42 -0400838 server.add_interface("/xyz/openbmc_project/object_mapper",
839 "xyz.openbmc_project.ObjectMapper");
Ed Tanous60520632018-06-11 17:46:52 -0700840
841 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400842 "GetAncestors", [&interfaceMap](std::string& reqPath,
843 std::vector<std::string>& interfaces) {
844 return getAncestors(interfaceMap, reqPath, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700845 });
846
847 iface->register_method(
Brad Bishopa098a372022-05-05 15:19:04 -0400848 "GetObject", [&interfaceMap](const std::string& path,
849 std::vector<std::string>& interfaces) {
850 return getObject(interfaceMap, path, interfaces);
851 });
852
853 iface->register_method(
854 "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
Ed Tanous60520632018-06-11 17:46:52 -0700855 std::vector<std::string>& interfaces) {
Brad Bishopa098a372022-05-05 15:19:04 -0400856 return getSubTree(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700857 });
858
859 iface->register_method(
860 "GetSubTreePaths",
Brad Bishopa098a372022-05-05 15:19:04 -0400861 [&interfaceMap](std::string& reqPath, int32_t depth,
862 std::vector<std::string>& interfaces) {
863 return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
Ed Tanous60520632018-06-11 17:46:52 -0700864 });
865
866 iface->initialize();
867
868 io.post([&]() {
Brad Bishopa098a372022-05-05 15:19:04 -0400869 doListNames(io, interfaceMap, systemBus.get(), nameOwners,
Matt Spinler11401e22019-04-08 13:13:25 -0500870 associationMaps, server);
Ed Tanous60520632018-06-11 17:46:52 -0700871 });
872
Brad Bishopa098a372022-05-05 15:19:04 -0400873 systemBus->request_name("xyz.openbmc_project.ObjectMapper");
Vishwanatha Subbanna64354ef2020-08-21 03:35:26 -0500874
Ed Tanous60520632018-06-11 17:46:52 -0700875 io.run();
876}