xref: /openbmc/bmcweb/include/dbus_utility.hpp (revision f263e09c)
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, 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<sdbusplus::message::object_path, std::string,
74                            std::string, std::string>>
75  >;
76 
77 // clang-format on
78 using DBusPropertiesMap = std::vector<std::pair<std::string, DbusVariantType>>;
79 using DBusInteracesMap = std::vector<std::pair<std::string, DBusPropertiesMap>>;
80 using ManagedObjectType =
81     std::vector<std::pair<sdbusplus::message::object_path, DBusInteracesMap>>;
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 
102 inline void escapePathForDbus(std::string& path)
103 {
104     const std::regex reg("[^A-Za-z0-9_/]");
105     std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_");
106 }
107 
108 inline void logError(const boost::system::error_code& ec)
109 {
110     if (ec)
111     {
112         BMCWEB_LOG_ERROR << "DBus error: " << ec << ", cannot call method";
113     }
114 }
115 
116 // gets the string N strings deep into a path
117 // i.e.  /0th/1st/2nd/3rd
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>
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
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 
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 
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 
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 
228 inline void
229     getDbusObject(const std::string& path,
230                   std::span<const std::string_view> interfaces,
231                   std::function<void(const boost::system::error_code&,
232                                      const MapperGetObject&)>&& callback)
233 {
234     crow::connections::systemBus->async_method_call(
235         [callback{std::move(callback)}](const boost::system::error_code& ec,
236                                         const MapperGetObject& object) {
237         callback(ec, object);
238         },
239         "xyz.openbmc_project.ObjectMapper",
240         "/xyz/openbmc_project/object_mapper",
241         "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces);
242 }
243 
244 inline void getAssociationEndPoints(
245     const std::string& path,
246     std::function<void(const boost::system::error_code&,
247                        const MapperEndPoints&)>&& callback)
248 {
249     sdbusplus::asio::getProperty<MapperEndPoints>(
250         *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path,
251         "xyz.openbmc_project.Association", "endpoints", std::move(callback));
252 }
253 
254 inline void
255     getManagedObjects(const std::string& service,
256                       const sdbusplus::message::object_path& path,
257                       std::function<void(const boost::system::error_code&,
258                                          const ManagedObjectType&)>&& callback)
259 {
260     crow::connections::systemBus->async_method_call(
261         [callback{std::move(callback)}](const boost::system::error_code& ec,
262                                         const ManagedObjectType& objects) {
263         callback(ec, objects);
264         },
265         service, path, "org.freedesktop.DBus.ObjectManager",
266         "GetManagedObjects");
267 }
268 
269 } // namespace utility
270 } // namespace dbus
271