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