xref: /openbmc/bmcweb/include/dbus_utility.hpp (revision 6be832e2)
1 /*
2 Copyright (c) 2018 Intel Corporation
3 
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8     http://www.apache.org/licenses/LICENSE-2.0
9 
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15  */
16 #pragma once
17 
18 #include "boost_formatters.hpp"
19 #include "dbus_singleton.hpp"
20 #include "logging.hpp"
21 
22 #include <boost/system/error_code.hpp>
23 #include <sdbusplus/asio/property.hpp>
24 #include <sdbusplus/message/native_types.hpp>
25 
26 #include <array>
27 #include <cstddef>
28 #include <cstdint>
29 #include <filesystem>
30 #include <functional>
31 #include <regex>
32 #include <span>
33 #include <sstream>
34 #include <string>
35 #include <string_view>
36 #include <tuple>
37 #include <utility>
38 #include <variant>
39 #include <vector>
40 
41 namespace dbus
42 {
43 
44 namespace utility
45 {
46 
47 // clang-format off
48 using DbusVariantType = std::variant<
49     std::vector<std::tuple<std::string, std::string, std::string>>,
50     std::vector<std::string>,
51     std::vector<double>,
52     std::string,
53     int64_t,
54     uint64_t,
55     double,
56     int32_t,
57     uint32_t,
58     int16_t,
59     uint16_t,
60     uint8_t,
61     bool,
62     sdbusplus::message::unix_fd,
63     std::vector<uint32_t>,
64     std::vector<uint16_t>,
65     sdbusplus::message::object_path,
66     std::tuple<uint64_t, std::vector<std::tuple<std::string, double, uint64_t>>>,
67     std::vector<sdbusplus::message::object_path>,
68     std::vector<std::tuple<std::string, std::string>>,
69     std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>,
70     std::vector<std::tuple<uint32_t, size_t>>,
71     std::vector<std::tuple<
72       std::vector<std::tuple<sdbusplus::message::object_path, std::string>>,
73       std::string, std::string, uint64_t>>
74  >;
75 
76 // clang-format on
77 using DBusPropertiesMap = std::vector<std::pair<std::string, DbusVariantType>>;
78 using DBusInterfacesMap =
79     std::vector<std::pair<std::string, DBusPropertiesMap>>;
80 using ManagedObjectType =
81     std::vector<std::pair<sdbusplus::message::object_path, DBusInterfacesMap>>;
82 
83 // Map of service name to list of interfaces
84 using MapperServiceMap =
85     std::vector<std::pair<std::string, std::vector<std::string>>>;
86 
87 // Map of object paths to MapperServiceMaps
88 using MapperGetSubTreeResponse =
89     std::vector<std::pair<std::string, MapperServiceMap>>;
90 
91 using MapperGetObject =
92     std::vector<std::pair<std::string, std::vector<std::string>>>;
93 
94 using MapperGetAncestorsResponse = std::vector<
95     std::pair<std::string,
96               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
97 
98 using MapperGetSubTreePathsResponse = std::vector<std::string>;
99 
100 using MapperEndPoints = std::vector<std::string>;
101 
escapePathForDbus(std::string & path)102 inline void escapePathForDbus(std::string& path)
103 {
104     const static std::regex reg("[^A-Za-z0-9_/]");
105     std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_");
106 }
107 
logError(const boost::system::error_code & ec)108 inline void logError(const boost::system::error_code& ec)
109 {
110     if (ec)
111     {
112         BMCWEB_LOG_ERROR("DBus error: {}, cannot call method", ec);
113     }
114 }
115 
116 // gets the string N strings deep into a path
117 // i.e.  /0th/1st/2nd/3rd
getNthStringFromPath(const std::string & path,int index,std::string & result)118 inline bool getNthStringFromPath(const std::string& path, int index,
119                                  std::string& result)
120 {
121     if (index < 0)
122     {
123         return false;
124     }
125 
126     std::filesystem::path p1(path);
127     int count = -1;
128     for (const auto& element : p1)
129     {
130         if (element.has_filename())
131         {
132             ++count;
133             if (count == index)
134             {
135                 result = element.stem().string();
136                 break;
137             }
138         }
139     }
140     return count >= index;
141 }
142 
143 template <typename Callback>
checkDbusPathExists(const std::string & path,Callback && callback)144 inline void checkDbusPathExists(const std::string& path, Callback&& callback)
145 {
146     crow::connections::systemBus->async_method_call(
147         [callback = std::forward<Callback>(callback)](
148             const boost::system::error_code& ec,
149             const dbus::utility::MapperGetObject& objectNames) {
150             callback(!ec && !objectNames.empty());
151         },
152         "xyz.openbmc_project.ObjectMapper",
153         "/xyz/openbmc_project/object_mapper",
154         "xyz.openbmc_project.ObjectMapper", "GetObject", path,
155         std::array<std::string, 0>());
156 }
157 
158 inline void
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)159     getSubTree(const std::string& path, int32_t depth,
160                std::span<const std::string_view> interfaces,
161                std::function<void(const boost::system::error_code&,
162                                   const MapperGetSubTreeResponse&)>&& callback)
163 {
164     crow::connections::systemBus->async_method_call(
165         [callback{std::move(callback)}](
166             const boost::system::error_code& ec,
167             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
168         "xyz.openbmc_project.ObjectMapper",
169         "/xyz/openbmc_project/object_mapper",
170         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
171         interfaces);
172 }
173 
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)174 inline void getSubTreePaths(
175     const std::string& path, int32_t depth,
176     std::span<const std::string_view> interfaces,
177     std::function<void(const boost::system::error_code&,
178                        const MapperGetSubTreePathsResponse&)>&& callback)
179 {
180     crow::connections::systemBus->async_method_call(
181         [callback{std::move(callback)}](
182             const boost::system::error_code& ec,
183             const MapperGetSubTreePathsResponse& subtreePaths) {
184             callback(ec, subtreePaths);
185         },
186         "xyz.openbmc_project.ObjectMapper",
187         "/xyz/openbmc_project/object_mapper",
188         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
189         interfaces);
190 }
191 
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)192 inline void getAssociatedSubTree(
193     const sdbusplus::message::object_path& associatedPath,
194     const sdbusplus::message::object_path& path, int32_t depth,
195     std::span<const std::string_view> interfaces,
196     std::function<void(const boost::system::error_code&,
197                        const MapperGetSubTreeResponse&)>&& callback)
198 {
199     crow::connections::systemBus->async_method_call(
200         [callback{std::move(callback)}](
201             const boost::system::error_code& ec,
202             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
203         "xyz.openbmc_project.ObjectMapper",
204         "/xyz/openbmc_project/object_mapper",
205         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
206         associatedPath, path, depth, interfaces);
207 }
208 
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)209 inline void getAssociatedSubTreePaths(
210     const sdbusplus::message::object_path& associatedPath,
211     const sdbusplus::message::object_path& path, int32_t depth,
212     std::span<const std::string_view> interfaces,
213     std::function<void(const boost::system::error_code&,
214                        const MapperGetSubTreePathsResponse&)>&& callback)
215 {
216     crow::connections::systemBus->async_method_call(
217         [callback{std::move(callback)}](
218             const boost::system::error_code& ec,
219             const MapperGetSubTreePathsResponse& subtreePaths) {
220             callback(ec, subtreePaths);
221         },
222         "xyz.openbmc_project.ObjectMapper",
223         "/xyz/openbmc_project/object_mapper",
224         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
225         associatedPath, path, depth, interfaces);
226 }
227 
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)228 inline void getAssociatedSubTreeById(
229     const std::string& id, const std::string& path,
230     std::span<const std::string_view> subtreeInterfaces,
231     std::string_view association,
232     std::span<const std::string_view> endpointInterfaces,
233     std::function<void(const boost::system::error_code&,
234                        const MapperGetSubTreeResponse&)>&& callback)
235 {
236     crow::connections::systemBus->async_method_call(
237         [callback{std::move(callback)}](
238             const boost::system::error_code& ec,
239             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
240         "xyz.openbmc_project.ObjectMapper",
241         "/xyz/openbmc_project/object_mapper",
242         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreeById", id,
243         path, subtreeInterfaces, association, endpointInterfaces);
244 }
245 
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)246 inline void getAssociatedSubTreePathsById(
247     const std::string& id, const std::string& path,
248     std::span<const std::string_view> subtreeInterfaces,
249     std::string_view association,
250     std::span<const std::string_view> endpointInterfaces,
251     std::function<void(const boost::system::error_code&,
252                        const MapperGetSubTreePathsResponse&)>&& callback)
253 {
254     crow::connections::systemBus->async_method_call(
255         [callback{std::move(callback)}](
256             const boost::system::error_code& ec,
257             const MapperGetSubTreePathsResponse& subtreePaths) {
258             callback(ec, subtreePaths);
259         },
260         "xyz.openbmc_project.ObjectMapper",
261         "/xyz/openbmc_project/object_mapper",
262         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePathsById", id,
263         path, subtreeInterfaces, association, endpointInterfaces);
264 }
265 
getDbusObject(const std::string & path,std::span<const std::string_view> interfaces,std::function<void (const boost::system::error_code &,const MapperGetObject &)> && callback)266 inline void getDbusObject(
267     const std::string& path, std::span<const std::string_view> interfaces,
268     std::function<void(const boost::system::error_code&,
269                        const MapperGetObject&)>&& callback)
270 {
271     crow::connections::systemBus->async_method_call(
272         [callback{std::move(callback)}](const boost::system::error_code& ec,
273                                         const MapperGetObject& object) {
274             callback(ec, object);
275         },
276         "xyz.openbmc_project.ObjectMapper",
277         "/xyz/openbmc_project/object_mapper",
278         "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces);
279 }
280 
getAssociationEndPoints(const std::string & path,std::function<void (const boost::system::error_code &,const MapperEndPoints &)> && callback)281 inline void getAssociationEndPoints(
282     const std::string& path,
283     std::function<void(const boost::system::error_code&,
284                        const MapperEndPoints&)>&& callback)
285 {
286     sdbusplus::asio::getProperty<MapperEndPoints>(
287         *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path,
288         "xyz.openbmc_project.Association", "endpoints", std::move(callback));
289 }
290 
getManagedObjects(const std::string & service,const sdbusplus::message::object_path & path,std::function<void (const boost::system::error_code &,const ManagedObjectType &)> && callback)291 inline void getManagedObjects(
292     const std::string& service, const sdbusplus::message::object_path& path,
293     std::function<void(const boost::system::error_code&,
294                        const ManagedObjectType&)>&& callback)
295 {
296     crow::connections::systemBus->async_method_call(
297         [callback{std::move(callback)}](const boost::system::error_code& ec,
298                                         const ManagedObjectType& objects) {
299             callback(ec, objects);
300         },
301         service, path, "org.freedesktop.DBus.ObjectManager",
302         "GetManagedObjects");
303 }
304 
305 } // namespace utility
306 } // namespace dbus
307