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