xref: /openbmc/bmcweb/include/dbus_utility.hpp (revision 2ae81db9)
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 "dbus_singleton.hpp"
19 #include "logging.hpp"
20 
21 #include <boost/system/error_code.hpp> // IWYU pragma: keep
22 #include <sdbusplus/asio/property.hpp>
23 #include <sdbusplus/message/native_types.hpp>
24 
25 #include <array>
26 #include <cstddef>
27 #include <cstdint>
28 #include <filesystem>
29 #include <functional>
30 #include <regex>
31 #include <span>
32 #include <sstream>
33 #include <string>
34 #include <string_view>
35 #include <tuple>
36 #include <utility>
37 #include <variant>
38 #include <vector>
39 
40 // IWYU pragma: no_include <stddef.h>
41 // IWYU pragma: no_include <stdint.h>
42 // IWYU pragma: no_include <boost/system/detail/error_code.hpp>
43 
44 namespace dbus
45 {
46 
47 namespace utility
48 {
49 
50 // clang-format off
51 using DbusVariantType = std::variant<
52     std::vector<std::tuple<std::string, std::string, std::string>>,
53     std::vector<std::string>,
54     std::vector<double>,
55     std::string,
56     int64_t,
57     uint64_t,
58     double,
59     int32_t,
60     uint32_t,
61     int16_t,
62     uint16_t,
63     uint8_t,
64     bool,
65     sdbusplus::message::unix_fd,
66     std::vector<uint32_t>,
67     std::vector<uint16_t>,
68     sdbusplus::message::object_path,
69     std::tuple<uint64_t, std::vector<std::tuple<std::string, double, uint64_t>>>,
70     std::vector<sdbusplus::message::object_path>,
71     std::vector<std::tuple<std::string, std::string>>,
72     std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>,
73     std::vector<std::tuple<uint32_t, size_t>>,
74     std::vector<std::tuple<
75       std::vector<std::tuple<sdbusplus::message::object_path, std::string>>,
76       std::string, std::string, uint64_t>>
77  >;
78 
79 // clang-format on
80 using DBusPropertiesMap = std::vector<std::pair<std::string, DbusVariantType>>;
81 using DBusInterfacesMap =
82     std::vector<std::pair<std::string, DBusPropertiesMap>>;
83 using ManagedObjectType =
84     std::vector<std::pair<sdbusplus::message::object_path, DBusInterfacesMap>>;
85 
86 // Map of service name to list of interfaces
87 using MapperServiceMap =
88     std::vector<std::pair<std::string, std::vector<std::string>>>;
89 
90 // Map of object paths to MapperServiceMaps
91 using MapperGetSubTreeResponse =
92     std::vector<std::pair<std::string, MapperServiceMap>>;
93 
94 using MapperGetObject =
95     std::vector<std::pair<std::string, std::vector<std::string>>>;
96 
97 using MapperGetAncestorsResponse = std::vector<
98     std::pair<std::string,
99               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
100 
101 using MapperGetSubTreePathsResponse = std::vector<std::string>;
102 
103 using MapperEndPoints = std::vector<std::string>;
104 
105 inline void escapePathForDbus(std::string& path)
106 {
107     const static std::regex reg("[^A-Za-z0-9_/]");
108     std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_");
109 }
110 
111 inline void logError(const boost::system::error_code& ec)
112 {
113     if (ec)
114     {
115         BMCWEB_LOG_ERROR("DBus error: {}, cannot call method", ec);
116     }
117 }
118 
119 // gets the string N strings deep into a path
120 // i.e.  /0th/1st/2nd/3rd
121 inline bool getNthStringFromPath(const std::string& path, int index,
122                                  std::string& result)
123 {
124     if (index < 0)
125     {
126         return false;
127     }
128 
129     std::filesystem::path p1(path);
130     int count = -1;
131     for (const auto& element : p1)
132     {
133         if (element.has_filename())
134         {
135             ++count;
136             if (count == index)
137             {
138                 result = element.stem().string();
139                 break;
140             }
141         }
142     }
143     return count >= index;
144 }
145 
146 template <typename Callback>
147 inline void checkDbusPathExists(const std::string& path, Callback&& callback)
148 {
149     crow::connections::systemBus->async_method_call(
150         [callback{std::forward<Callback>(callback)}](
151             const boost::system::error_code& ec,
152             const dbus::utility::MapperGetObject& objectNames) {
153         callback(!ec && !objectNames.empty());
154     },
155         "xyz.openbmc_project.ObjectMapper",
156         "/xyz/openbmc_project/object_mapper",
157         "xyz.openbmc_project.ObjectMapper", "GetObject", path,
158         std::array<std::string, 0>());
159 }
160 
161 inline void
162     getSubTree(const std::string& path, int32_t depth,
163                std::span<const std::string_view> interfaces,
164                std::function<void(const boost::system::error_code&,
165                                   const MapperGetSubTreeResponse&)>&& callback)
166 {
167     crow::connections::systemBus->async_method_call(
168         [callback{std::move(callback)}](
169             const boost::system::error_code& ec,
170             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
171         "xyz.openbmc_project.ObjectMapper",
172         "/xyz/openbmc_project/object_mapper",
173         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
174         interfaces);
175 }
176 
177 inline void getSubTreePaths(
178     const std::string& path, int32_t depth,
179     std::span<const std::string_view> interfaces,
180     std::function<void(const boost::system::error_code&,
181                        const MapperGetSubTreePathsResponse&)>&& callback)
182 {
183     crow::connections::systemBus->async_method_call(
184         [callback{std::move(callback)}](
185             const boost::system::error_code& ec,
186             const MapperGetSubTreePathsResponse& subtreePaths) {
187         callback(ec, subtreePaths);
188     },
189         "xyz.openbmc_project.ObjectMapper",
190         "/xyz/openbmc_project/object_mapper",
191         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
192         interfaces);
193 }
194 
195 inline void getAssociatedSubTree(
196     const sdbusplus::message::object_path& associatedPath,
197     const sdbusplus::message::object_path& path, int32_t depth,
198     std::span<const std::string_view> interfaces,
199     std::function<void(const boost::system::error_code&,
200                        const MapperGetSubTreeResponse&)>&& callback)
201 {
202     crow::connections::systemBus->async_method_call(
203         [callback{std::move(callback)}](
204             const boost::system::error_code& ec,
205             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
206         "xyz.openbmc_project.ObjectMapper",
207         "/xyz/openbmc_project/object_mapper",
208         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
209         associatedPath, path, depth, interfaces);
210 }
211 
212 inline void getAssociatedSubTreePaths(
213     const sdbusplus::message::object_path& associatedPath,
214     const sdbusplus::message::object_path& path, int32_t depth,
215     std::span<const std::string_view> interfaces,
216     std::function<void(const boost::system::error_code&,
217                        const MapperGetSubTreePathsResponse&)>&& callback)
218 {
219     crow::connections::systemBus->async_method_call(
220         [callback{std::move(callback)}](
221             const boost::system::error_code& ec,
222             const MapperGetSubTreePathsResponse& subtreePaths) {
223         callback(ec, subtreePaths);
224     },
225         "xyz.openbmc_project.ObjectMapper",
226         "/xyz/openbmc_project/object_mapper",
227         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
228         associatedPath, path, depth, interfaces);
229 }
230 
231 inline void
232     getDbusObject(const std::string& path,
233                   std::span<const std::string_view> interfaces,
234                   std::function<void(const boost::system::error_code&,
235                                      const MapperGetObject&)>&& callback)
236 {
237     crow::connections::systemBus->async_method_call(
238         [callback{std::move(callback)}](const boost::system::error_code& ec,
239                                         const MapperGetObject& object) {
240         callback(ec, object);
241     },
242         "xyz.openbmc_project.ObjectMapper",
243         "/xyz/openbmc_project/object_mapper",
244         "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces);
245 }
246 
247 inline void getAssociationEndPoints(
248     const std::string& path,
249     std::function<void(const boost::system::error_code&,
250                        const MapperEndPoints&)>&& callback)
251 {
252     sdbusplus::asio::getProperty<MapperEndPoints>(
253         *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path,
254         "xyz.openbmc_project.Association", "endpoints", std::move(callback));
255 }
256 
257 inline void
258     getManagedObjects(const std::string& service,
259                       const sdbusplus::message::object_path& path,
260                       std::function<void(const boost::system::error_code&,
261                                          const ManagedObjectType&)>&& callback)
262 {
263     crow::connections::systemBus->async_method_call(
264         [callback{std::move(callback)}](const boost::system::error_code& ec,
265                                         const ManagedObjectType& objects) {
266         callback(ec, objects);
267     },
268         service, path, "org.freedesktop.DBus.ObjectManager",
269         "GetManagedObjects");
270 }
271 
272 } // namespace utility
273 } // namespace dbus
274