1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3
4 #include "dbus_utility.hpp"
5
6 #include "boost_formatters.hpp"
7 #include "dbus_singleton.hpp"
8 #include "logging.hpp"
9
10 #include <boost/system/error_code.hpp>
11 #include <sdbusplus/asio/connection.hpp>
12 #include <sdbusplus/asio/property.hpp>
13 #include <sdbusplus/message/native_types.hpp>
14
15 #include <array>
16 #include <cstdint>
17 #include <filesystem>
18 #include <functional>
19 #include <regex>
20 #include <span>
21 #include <string>
22 #include <string_view>
23 #include <utility>
24
25 namespace dbus
26 {
27
28 namespace utility
29 {
30
escapePathForDbus(std::string & path)31 void escapePathForDbus(std::string& path)
32 {
33 const static std::regex reg("[^A-Za-z0-9_/]");
34 std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_");
35 }
36
logError(const boost::system::error_code & ec)37 void logError(const boost::system::error_code& ec)
38 {
39 if (ec)
40 {
41 BMCWEB_LOG_ERROR("DBus error: {}, cannot call method", ec);
42 }
43 }
44
45 // gets the string N strings deep into a path
46 // i.e. /0th/1st/2nd/3rd
getNthStringFromPath(const std::string & path,int index,std::string & result)47 bool getNthStringFromPath(const std::string& path, int index,
48 std::string& result)
49 {
50 if (index < 0)
51 {
52 return false;
53 }
54
55 std::filesystem::path p1(path);
56 int count = -1;
57 for (const auto& element : p1)
58 {
59 if (element.has_filename())
60 {
61 ++count;
62 if (count == index)
63 {
64 result = element.stem().string();
65 break;
66 }
67 }
68 }
69 return count >= index;
70 }
71
getAllProperties(const std::string & service,const std::string & objectPath,const std::string & interface,std::function<void (const boost::system::error_code &,const DBusPropertiesMap &)> && callback)72 void getAllProperties(const std::string& service, const std::string& objectPath,
73 const std::string& interface,
74 std::function<void(const boost::system::error_code&,
75 const DBusPropertiesMap&)>&& callback)
76 {
77 sdbusplus::asio::getAllProperties(*crow::connections::systemBus, service,
78 objectPath, interface,
79 std::move(callback));
80 }
81
getAllProperties(sdbusplus::asio::connection &,const std::string & service,const std::string & objectPath,const std::string & interface,std::function<void (const boost::system::error_code &,const DBusPropertiesMap &)> && callback)82 void getAllProperties(sdbusplus::asio::connection& /*conn*/,
83 const std::string& service, const std::string& objectPath,
84 const std::string& interface,
85 std::function<void(const boost::system::error_code&,
86 const DBusPropertiesMap&)>&& callback)
87 {
88 getAllProperties(service, objectPath, interface, std::move(callback));
89 }
90
checkDbusPathExists(const std::string & path,std::function<void (bool)> && callback)91 void checkDbusPathExists(const std::string& path,
92 std::function<void(bool)>&& callback)
93 {
94 crow::connections::systemBus->async_method_call(
95 [callback = std::move(callback)](const boost::system::error_code& ec,
96 const MapperGetObject& objectNames) {
97 callback(!ec && !objectNames.empty());
98 },
99 "xyz.openbmc_project.ObjectMapper",
100 "/xyz/openbmc_project/object_mapper",
101 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
102 std::array<std::string, 0>());
103 }
104
getSubTree(const std::string & path,int32_t depth,std::span<const std::string_view> interfaces,std::function<void (const boost::system::error_code &,const MapperGetSubTreeResponse &)> && callback)105 void getSubTree(const std::string& path, int32_t depth,
106 std::span<const std::string_view> interfaces,
107 std::function<void(const boost::system::error_code&,
108 const MapperGetSubTreeResponse&)>&& callback)
109 {
110 crow::connections::systemBus->async_method_call(
111 [callback{std::move(callback)}](
112 const boost::system::error_code& ec,
113 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
114 "xyz.openbmc_project.ObjectMapper",
115 "/xyz/openbmc_project/object_mapper",
116 "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
117 interfaces);
118 }
119
getSubTreePaths(const std::string & path,int32_t depth,std::span<const std::string_view> interfaces,std::function<void (const boost::system::error_code &,const MapperGetSubTreePathsResponse &)> && callback)120 void getSubTreePaths(
121 const std::string& path, int32_t depth,
122 std::span<const std::string_view> interfaces,
123 std::function<void(const boost::system::error_code&,
124 const MapperGetSubTreePathsResponse&)>&& callback)
125 {
126 crow::connections::systemBus->async_method_call(
127 [callback{std::move(callback)}](
128 const boost::system::error_code& ec,
129 const MapperGetSubTreePathsResponse& subtreePaths) {
130 callback(ec, subtreePaths);
131 },
132 "xyz.openbmc_project.ObjectMapper",
133 "/xyz/openbmc_project/object_mapper",
134 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
135 interfaces);
136 }
137
getAssociatedSubTree(const sdbusplus::message::object_path & associatedPath,const sdbusplus::message::object_path & path,int32_t depth,std::span<const std::string_view> interfaces,std::function<void (const boost::system::error_code &,const MapperGetSubTreeResponse &)> && callback)138 void getAssociatedSubTree(
139 const sdbusplus::message::object_path& associatedPath,
140 const sdbusplus::message::object_path& path, int32_t depth,
141 std::span<const std::string_view> interfaces,
142 std::function<void(const boost::system::error_code&,
143 const MapperGetSubTreeResponse&)>&& callback)
144 {
145 crow::connections::systemBus->async_method_call(
146 [callback{std::move(callback)}](
147 const boost::system::error_code& ec,
148 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
149 "xyz.openbmc_project.ObjectMapper",
150 "/xyz/openbmc_project/object_mapper",
151 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
152 associatedPath, path, depth, interfaces);
153 }
154
getAssociatedSubTreePaths(const sdbusplus::message::object_path & associatedPath,const sdbusplus::message::object_path & path,int32_t depth,std::span<const std::string_view> interfaces,std::function<void (const boost::system::error_code &,const MapperGetSubTreePathsResponse &)> && callback)155 void getAssociatedSubTreePaths(
156 const sdbusplus::message::object_path& associatedPath,
157 const sdbusplus::message::object_path& path, int32_t depth,
158 std::span<const std::string_view> interfaces,
159 std::function<void(const boost::system::error_code&,
160 const MapperGetSubTreePathsResponse&)>&& callback)
161 {
162 crow::connections::systemBus->async_method_call(
163 [callback{std::move(callback)}](
164 const boost::system::error_code& ec,
165 const MapperGetSubTreePathsResponse& subtreePaths) {
166 callback(ec, subtreePaths);
167 },
168 "xyz.openbmc_project.ObjectMapper",
169 "/xyz/openbmc_project/object_mapper",
170 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
171 associatedPath, path, depth, interfaces);
172 }
173
getAssociatedSubTreeById(const std::string & id,const std::string & path,std::span<const std::string_view> subtreeInterfaces,std::string_view association,std::span<const std::string_view> endpointInterfaces,std::function<void (const boost::system::error_code &,const MapperGetSubTreeResponse &)> && callback)174 void getAssociatedSubTreeById(
175 const std::string& id, const std::string& path,
176 std::span<const std::string_view> subtreeInterfaces,
177 std::string_view association,
178 std::span<const std::string_view> endpointInterfaces,
179 std::function<void(const boost::system::error_code&,
180 const MapperGetSubTreeResponse&)>&& callback)
181 {
182 crow::connections::systemBus->async_method_call(
183 [callback{std::move(callback)}](
184 const boost::system::error_code& ec,
185 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
186 "xyz.openbmc_project.ObjectMapper",
187 "/xyz/openbmc_project/object_mapper",
188 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreeById", id,
189 path, subtreeInterfaces, association, endpointInterfaces);
190 }
191
getAssociatedSubTreePathsById(const std::string & id,const std::string & path,std::span<const std::string_view> subtreeInterfaces,std::string_view association,std::span<const std::string_view> endpointInterfaces,std::function<void (const boost::system::error_code &,const MapperGetSubTreePathsResponse &)> && callback)192 void getAssociatedSubTreePathsById(
193 const std::string& id, const std::string& path,
194 std::span<const std::string_view> subtreeInterfaces,
195 std::string_view association,
196 std::span<const std::string_view> endpointInterfaces,
197 std::function<void(const boost::system::error_code&,
198 const MapperGetSubTreePathsResponse&)>&& callback)
199 {
200 crow::connections::systemBus->async_method_call(
201 [callback{std::move(callback)}](
202 const boost::system::error_code& ec,
203 const MapperGetSubTreePathsResponse& subtreePaths) {
204 callback(ec, subtreePaths);
205 },
206 "xyz.openbmc_project.ObjectMapper",
207 "/xyz/openbmc_project/object_mapper",
208 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePathsById", id,
209 path, subtreeInterfaces, association, endpointInterfaces);
210 }
211
getDbusObject(const std::string & path,std::span<const std::string_view> interfaces,std::function<void (const boost::system::error_code &,const MapperGetObject &)> && callback)212 void getDbusObject(const std::string& path,
213 std::span<const std::string_view> interfaces,
214 std::function<void(const boost::system::error_code&,
215 const MapperGetObject&)>&& callback)
216 {
217 crow::connections::systemBus->async_method_call(
218 [callback{std::move(callback)}](const boost::system::error_code& ec,
219 const MapperGetObject& object) {
220 callback(ec, object);
221 },
222 "xyz.openbmc_project.ObjectMapper",
223 "/xyz/openbmc_project/object_mapper",
224 "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces);
225 }
226
getAssociationEndPoints(const std::string & path,std::function<void (const boost::system::error_code &,const MapperEndPoints &)> && callback)227 void getAssociationEndPoints(
228 const std::string& path,
229 std::function<void(const boost::system::error_code&,
230 const MapperEndPoints&)>&& callback)
231 {
232 getProperty<MapperEndPoints>("xyz.openbmc_project.ObjectMapper", path,
233 "xyz.openbmc_project.Association", "endpoints",
234 std::move(callback));
235 }
236
getManagedObjects(const std::string & service,const sdbusplus::message::object_path & path,std::function<void (const boost::system::error_code &,const ManagedObjectType &)> && callback)237 void getManagedObjects(const std::string& service,
238 const sdbusplus::message::object_path& path,
239 std::function<void(const boost::system::error_code&,
240 const ManagedObjectType&)>&& callback)
241 {
242 crow::connections::systemBus->async_method_call(
243 [callback{std::move(callback)}](const boost::system::error_code& ec,
244 const ManagedObjectType& objects) {
245 callback(ec, objects);
246 },
247 service, path, "org.freedesktop.DBus.ObjectManager",
248 "GetManagedObjects");
249 }
250
251 } // namespace utility
252 } // namespace dbus
253