xref: /openbmc/bmcweb/include/dbus_utility.hpp (revision 5315c1b1)
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 
99 using MapperEndPoints = std::vector<std::string>;
100 
101 inline void escapePathForDbus(std::string& path)
102 {
103     const std::regex reg("[^A-Za-z0-9_/]");
104     std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_");
105 }
106 
107 // gets the string N strings deep into a path
108 // i.e.  /0th/1st/2nd/3rd
109 inline bool getNthStringFromPath(const std::string& path, int index,
110                                  std::string& result)
111 {
112     if (index < 0)
113     {
114         return false;
115     }
116 
117     std::filesystem::path p1(path);
118     int count = -1;
119     for (auto const& element : p1)
120     {
121         if (element.has_filename())
122         {
123             ++count;
124             if (count == index)
125             {
126                 result = element.stem().string();
127                 break;
128             }
129         }
130     }
131     return count >= index;
132 }
133 
134 template <typename Callback>
135 inline void checkDbusPathExists(const std::string& path, Callback&& callback)
136 {
137     crow::connections::systemBus->async_method_call(
138         [callback{std::forward<Callback>(callback)}](
139             const boost::system::error_code& ec,
140             const dbus::utility::MapperGetObject& objectNames) {
141         callback(!ec && !objectNames.empty());
142         },
143         "xyz.openbmc_project.ObjectMapper",
144         "/xyz/openbmc_project/object_mapper",
145         "xyz.openbmc_project.ObjectMapper", "GetObject", path,
146         std::array<std::string, 0>());
147 }
148 
149 inline void
150     getSubTree(const std::string& path, int32_t depth,
151                std::span<const std::string_view> interfaces,
152                std::function<void(const boost::system::error_code&,
153                                   const MapperGetSubTreeResponse&)>&& callback)
154 {
155     crow::connections::systemBus->async_method_call(
156         [callback{std::move(callback)}](
157             const boost::system::error_code& ec,
158             const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); },
159         "xyz.openbmc_project.ObjectMapper",
160         "/xyz/openbmc_project/object_mapper",
161         "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
162         interfaces);
163 }
164 
165 inline void getSubTreePaths(
166     const std::string& path, int32_t depth,
167     std::span<const std::string_view> interfaces,
168     std::function<void(const boost::system::error_code&,
169                        const MapperGetSubTreePathsResponse&)>&& callback)
170 {
171     crow::connections::systemBus->async_method_call(
172         [callback{std::move(callback)}](
173             const boost::system::error_code& ec,
174             const MapperGetSubTreePathsResponse& subtreePaths) {
175         callback(ec, subtreePaths);
176         },
177         "xyz.openbmc_project.ObjectMapper",
178         "/xyz/openbmc_project/object_mapper",
179         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
180         interfaces);
181 }
182 
183 inline void
184     getDbusObject(const std::string& path,
185                   std::span<const std::string_view> interfaces,
186                   std::function<void(const boost::system::error_code&,
187                                      const MapperGetObject&)>&& callback)
188 {
189     crow::connections::systemBus->async_method_call(
190         [callback{std::move(callback)}](const boost::system::error_code& ec,
191                                         const MapperGetObject& object) {
192         callback(ec, object);
193         },
194         "xyz.openbmc_project.ObjectMapper",
195         "/xyz/openbmc_project/object_mapper",
196         "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces);
197 }
198 
199 inline void getAssociationEndPoints(
200     const std::string& path,
201     std::function<void(const boost::system::error_code&,
202                        const MapperEndPoints&)>&& callback)
203 {
204     sdbusplus::asio::getProperty<MapperEndPoints>(
205         *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path,
206         "xyz.openbmc_project.Association", "endpoints", std::move(callback));
207 }
208 
209 } // namespace utility
210 } // namespace dbus
211