xref: /openbmc/bmcweb/include/dbus_utility.hpp (revision 9bcb9355)
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 DBusInteracesMap = std::vector<std::pair<std::string, DBusPropertiesMap>>;
82 using ManagedObjectType =
83     std::vector<std::pair<sdbusplus::message::object_path, DBusInteracesMap>>;
84 
85 // Map of service name to list of interfaces
86 using MapperServiceMap =
87     std::vector<std::pair<std::string, std::vector<std::string>>>;
88 
89 // Map of object paths to MapperServiceMaps
90 using MapperGetSubTreeResponse =
91     std::vector<std::pair<std::string, MapperServiceMap>>;
92 
93 using MapperGetObject =
94     std::vector<std::pair<std::string, std::vector<std::string>>>;
95 
96 using MapperGetAncestorsResponse = std::vector<
97     std::pair<std::string,
98               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
99 
100 using MapperGetSubTreePathsResponse = std::vector<std::string>;
101 
102 using MapperEndPoints = std::vector<std::string>;
103 
104 inline void escapePathForDbus(std::string& path)
105 {
106     const static std::regex reg("[^A-Za-z0-9_/]");
107     std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_");
108 }
109 
110 inline void logError(const boost::system::error_code& ec)
111 {
112     if (ec)
113     {
114         BMCWEB_LOG_ERROR("DBus error: {}, cannot call method", ec);
115     }
116 }
117 
118 // gets the string N strings deep into a path
119 // i.e.  /0th/1st/2nd/3rd
120 inline bool getNthStringFromPath(const std::string& path, int index,
121                                  std::string& result)
122 {
123     if (index < 0)
124     {
125         return false;
126     }
127 
128     std::filesystem::path p1(path);
129     int count = -1;
130     for (const auto& element : p1)
131     {
132         if (element.has_filename())
133         {
134             ++count;
135             if (count == index)
136             {
137                 result = element.stem().string();
138                 break;
139             }
140         }
141     }
142     return count >= index;
143 }
144 
145 template <typename Callback>
146 inline void checkDbusPathExists(const std::string& path, Callback&& callback)
147 {
148     crow::connections::systemBus->async_method_call(
149         [callback{std::forward<Callback>(callback)}](
150             const boost::system::error_code& ec,
151             const dbus::utility::MapperGetObject& objectNames) {
152         callback(!ec && !objectNames.empty());
153         },
154         "xyz.openbmc_project.ObjectMapper",
155         "/xyz/openbmc_project/object_mapper",
156         "xyz.openbmc_project.ObjectMapper", "GetObject", path,
157         std::array<std::string, 0>());
158 }
159 
160 inline void
161     getSubTree(const std::string& path, int32_t depth,
162                std::span<const std::string_view> interfaces,
163                std::function<void(const boost::system::error_code&,
164                                   const MapperGetSubTreeResponse&)>&& callback)
165 {
166     crow::connections::systemBus->async_method_call(
167         [callback{std::move(callback)}](
168             const boost::system::error_code& ec,
169             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
170         "xyz.openbmc_project.ObjectMapper",
171         "/xyz/openbmc_project/object_mapper",
172         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
173         interfaces);
174 }
175 
176 inline void getSubTreePaths(
177     const std::string& path, int32_t depth,
178     std::span<const std::string_view> interfaces,
179     std::function<void(const boost::system::error_code&,
180                        const MapperGetSubTreePathsResponse&)>&& callback)
181 {
182     crow::connections::systemBus->async_method_call(
183         [callback{std::move(callback)}](
184             const boost::system::error_code& ec,
185             const MapperGetSubTreePathsResponse& subtreePaths) {
186         callback(ec, subtreePaths);
187         },
188         "xyz.openbmc_project.ObjectMapper",
189         "/xyz/openbmc_project/object_mapper",
190         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
191         interfaces);
192 }
193 
194 inline void getAssociatedSubTree(
195     const sdbusplus::message::object_path& associatedPath,
196     const sdbusplus::message::object_path& path, int32_t depth,
197     std::span<const std::string_view> interfaces,
198     std::function<void(const boost::system::error_code&,
199                        const MapperGetSubTreeResponse&)>&& callback)
200 {
201     crow::connections::systemBus->async_method_call(
202         [callback{std::move(callback)}](
203             const boost::system::error_code& ec,
204             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
205         "xyz.openbmc_project.ObjectMapper",
206         "/xyz/openbmc_project/object_mapper",
207         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
208         associatedPath, path, depth, interfaces);
209 }
210 
211 inline void getAssociatedSubTreePaths(
212     const sdbusplus::message::object_path& associatedPath,
213     const sdbusplus::message::object_path& path, int32_t depth,
214     std::span<const std::string_view> interfaces,
215     std::function<void(const boost::system::error_code&,
216                        const MapperGetSubTreePathsResponse&)>&& callback)
217 {
218     crow::connections::systemBus->async_method_call(
219         [callback{std::move(callback)}](
220             const boost::system::error_code& ec,
221             const MapperGetSubTreePathsResponse& subtreePaths) {
222         callback(ec, subtreePaths);
223         },
224         "xyz.openbmc_project.ObjectMapper",
225         "/xyz/openbmc_project/object_mapper",
226         "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
227         associatedPath, path, depth, interfaces);
228 }
229 
230 inline void
231     getDbusObject(const std::string& path,
232                   std::span<const std::string_view> interfaces,
233                   std::function<void(const boost::system::error_code&,
234                                      const MapperGetObject&)>&& callback)
235 {
236     crow::connections::systemBus->async_method_call(
237         [callback{std::move(callback)}](const boost::system::error_code& ec,
238                                         const MapperGetObject& object) {
239         callback(ec, object);
240         },
241         "xyz.openbmc_project.ObjectMapper",
242         "/xyz/openbmc_project/object_mapper",
243         "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces);
244 }
245 
246 inline void getAssociationEndPoints(
247     const std::string& path,
248     std::function<void(const boost::system::error_code&,
249                        const MapperEndPoints&)>&& callback)
250 {
251     sdbusplus::asio::getProperty<MapperEndPoints>(
252         *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path,
253         "xyz.openbmc_project.Association", "endpoints", std::move(callback));
254 }
255 
256 inline void
257     getManagedObjects(const std::string& service,
258                       const sdbusplus::message::object_path& path,
259                       std::function<void(const boost::system::error_code&,
260                                          const ManagedObjectType&)>&& callback)
261 {
262     crow::connections::systemBus->async_method_call(
263         [callback{std::move(callback)}](const boost::system::error_code& ec,
264                                         const ManagedObjectType& objects) {
265         callback(ec, objects);
266         },
267         service, path, "org.freedesktop.DBus.ObjectManager",
268         "GetManagedObjects");
269 }
270 
271 } // namespace utility
272 } // namespace dbus
273