1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4 #pragma once 5 6 #include "boost_formatters.hpp" 7 #include "dbus_singleton.hpp" 8 #include "logging.hpp" 9 10 #include <boost/system/error_code.hpp> 11 #include <sdbusplus/asio/property.hpp> 12 #include <sdbusplus/message/native_types.hpp> 13 14 #include <array> 15 #include <cstddef> 16 #include <cstdint> 17 #include <filesystem> 18 #include <functional> 19 #include <regex> 20 #include <span> 21 #include <sstream> 22 #include <string> 23 #include <string_view> 24 #include <tuple> 25 #include <utility> 26 #include <variant> 27 #include <vector> 28 29 namespace dbus 30 { 31 32 namespace utility 33 { 34 35 // clang-format off 36 using DbusVariantType = std::variant< 37 std::vector<std::tuple<std::string, std::string, std::string>>, 38 std::vector<std::string>, 39 std::vector<double>, 40 std::string, 41 int64_t, 42 uint64_t, 43 double, 44 int32_t, 45 uint32_t, 46 int16_t, 47 uint16_t, 48 uint8_t, 49 bool, 50 std::vector<uint32_t>, 51 std::vector<uint16_t>, 52 sdbusplus::message::object_path, 53 std::tuple<uint64_t, std::vector<std::tuple<std::string, double, uint64_t>>>, 54 std::vector<sdbusplus::message::object_path>, 55 std::vector<std::tuple<std::string, std::string>>, 56 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>, 57 std::vector<std::tuple<uint32_t, size_t>>, 58 std::vector<std::tuple< 59 std::vector<std::tuple<sdbusplus::message::object_path, std::string>>, 60 std::string, std::string, uint64_t>>, 61 std::vector<std::pair<sdbusplus::message::object_path, std::string>>, 62 std::vector<std::tuple<std::string, uint64_t, std::string, double>>, 63 std::vector<std::tuple<std::string, std::string, uint64_t, std::string>> 64 >; 65 66 // clang-format on 67 using DBusPropertiesMap = std::vector<std::pair<std::string, DbusVariantType>>; 68 using DBusInterfacesMap = 69 std::vector<std::pair<std::string, DBusPropertiesMap>>; 70 using ManagedObjectType = 71 std::vector<std::pair<sdbusplus::message::object_path, DBusInterfacesMap>>; 72 73 // Map of service name to list of interfaces 74 using MapperServiceMap = 75 std::vector<std::pair<std::string, std::vector<std::string>>>; 76 77 // Map of object paths to MapperServiceMaps 78 using MapperGetSubTreeResponse = 79 std::vector<std::pair<std::string, MapperServiceMap>>; 80 81 using MapperGetObject = 82 std::vector<std::pair<std::string, std::vector<std::string>>>; 83 84 using MapperGetAncestorsResponse = std::vector< 85 std::pair<std::string, 86 std::vector<std::pair<std::string, std::vector<std::string>>>>>; 87 88 using MapperGetSubTreePathsResponse = std::vector<std::string>; 89 90 using MapperEndPoints = std::vector<std::string>; 91 92 inline void escapePathForDbus(std::string& path) 93 { 94 const static std::regex reg("[^A-Za-z0-9_/]"); 95 std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_"); 96 } 97 98 inline void logError(const boost::system::error_code& ec) 99 { 100 if (ec) 101 { 102 BMCWEB_LOG_ERROR("DBus error: {}, cannot call method", ec); 103 } 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 (const auto& 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 inline void 134 getAllProperties(const std::string& service, const std::string& objectPath, 135 const std::string& interface, 136 std::function<void(const boost::system::error_code&, 137 const DBusPropertiesMap&)>&& callback) 138 { 139 sdbusplus::asio::getAllProperties(*crow::connections::systemBus, service, 140 objectPath, interface, 141 std::move(callback)); 142 } 143 144 template <typename PropertyType> 145 inline void getProperty( 146 const std::string& service, const std::string& objectPath, 147 const std::string& interface, const std::string& propertyName, 148 std::function<void(const boost::system::error_code&, const PropertyType&)>&& 149 callback) 150 { 151 sdbusplus::asio::getProperty<PropertyType>( 152 *crow::connections::systemBus, service, objectPath, interface, 153 propertyName, std::move(callback)); 154 } 155 156 template <typename PropertyType> 157 inline void getProperty( 158 sdbusplus::asio::connection& /*conn*/, const std::string& service, 159 const std::string& objectPath, const std::string& interface, 160 const std::string& propertyName, 161 std::function<void(const boost::system::error_code&, const PropertyType&)>&& 162 callback) 163 { 164 getProperty(service, objectPath, interface, propertyName, 165 std::move(callback)); 166 } 167 168 inline void getAllProperties( 169 sdbusplus::asio::connection& /*conn*/, const std::string& service, 170 const std::string& objectPath, const std::string& interface, 171 std::function<void(const boost::system::error_code&, 172 const DBusPropertiesMap&)>&& callback) 173 { 174 getAllProperties(service, objectPath, interface, std::move(callback)); 175 } 176 177 inline void checkDbusPathExists(const std::string& path, 178 std::function<void(bool)>&& callback) 179 { 180 crow::connections::systemBus->async_method_call( 181 [callback = std::move(callback)](const boost::system::error_code& ec, 182 const MapperGetObject& objectNames) { 183 callback(!ec && !objectNames.empty()); 184 }, 185 "xyz.openbmc_project.ObjectMapper", 186 "/xyz/openbmc_project/object_mapper", 187 "xyz.openbmc_project.ObjectMapper", "GetObject", path, 188 std::array<std::string, 0>()); 189 } 190 191 inline void 192 getSubTree(const std::string& path, int32_t depth, 193 std::span<const std::string_view> interfaces, 194 std::function<void(const boost::system::error_code&, 195 const MapperGetSubTreeResponse&)>&& callback) 196 { 197 crow::connections::systemBus->async_method_call( 198 [callback{std::move(callback)}]( 199 const boost::system::error_code& ec, 200 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 201 "xyz.openbmc_project.ObjectMapper", 202 "/xyz/openbmc_project/object_mapper", 203 "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth, 204 interfaces); 205 } 206 207 inline void getSubTreePaths( 208 const std::string& path, int32_t depth, 209 std::span<const std::string_view> interfaces, 210 std::function<void(const boost::system::error_code&, 211 const MapperGetSubTreePathsResponse&)>&& callback) 212 { 213 crow::connections::systemBus->async_method_call( 214 [callback{std::move(callback)}]( 215 const boost::system::error_code& ec, 216 const MapperGetSubTreePathsResponse& subtreePaths) { 217 callback(ec, subtreePaths); 218 }, 219 "xyz.openbmc_project.ObjectMapper", 220 "/xyz/openbmc_project/object_mapper", 221 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth, 222 interfaces); 223 } 224 225 inline void getAssociatedSubTree( 226 const sdbusplus::message::object_path& associatedPath, 227 const sdbusplus::message::object_path& path, int32_t depth, 228 std::span<const std::string_view> interfaces, 229 std::function<void(const boost::system::error_code&, 230 const MapperGetSubTreeResponse&)>&& callback) 231 { 232 crow::connections::systemBus->async_method_call( 233 [callback{std::move(callback)}]( 234 const boost::system::error_code& ec, 235 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 236 "xyz.openbmc_project.ObjectMapper", 237 "/xyz/openbmc_project/object_mapper", 238 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree", 239 associatedPath, path, depth, interfaces); 240 } 241 242 inline void getAssociatedSubTreePaths( 243 const sdbusplus::message::object_path& associatedPath, 244 const sdbusplus::message::object_path& path, int32_t depth, 245 std::span<const std::string_view> interfaces, 246 std::function<void(const boost::system::error_code&, 247 const MapperGetSubTreePathsResponse&)>&& callback) 248 { 249 crow::connections::systemBus->async_method_call( 250 [callback{std::move(callback)}]( 251 const boost::system::error_code& ec, 252 const MapperGetSubTreePathsResponse& subtreePaths) { 253 callback(ec, subtreePaths); 254 }, 255 "xyz.openbmc_project.ObjectMapper", 256 "/xyz/openbmc_project/object_mapper", 257 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths", 258 associatedPath, path, depth, interfaces); 259 } 260 261 inline void getAssociatedSubTreeById( 262 const std::string& id, const std::string& path, 263 std::span<const std::string_view> subtreeInterfaces, 264 std::string_view association, 265 std::span<const std::string_view> endpointInterfaces, 266 std::function<void(const boost::system::error_code&, 267 const MapperGetSubTreeResponse&)>&& callback) 268 { 269 crow::connections::systemBus->async_method_call( 270 [callback{std::move(callback)}]( 271 const boost::system::error_code& ec, 272 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 273 "xyz.openbmc_project.ObjectMapper", 274 "/xyz/openbmc_project/object_mapper", 275 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreeById", id, 276 path, subtreeInterfaces, association, endpointInterfaces); 277 } 278 279 inline void getAssociatedSubTreePathsById( 280 const std::string& id, const std::string& path, 281 std::span<const std::string_view> subtreeInterfaces, 282 std::string_view association, 283 std::span<const std::string_view> endpointInterfaces, 284 std::function<void(const boost::system::error_code&, 285 const MapperGetSubTreePathsResponse&)>&& callback) 286 { 287 crow::connections::systemBus->async_method_call( 288 [callback{std::move(callback)}]( 289 const boost::system::error_code& ec, 290 const MapperGetSubTreePathsResponse& subtreePaths) { 291 callback(ec, subtreePaths); 292 }, 293 "xyz.openbmc_project.ObjectMapper", 294 "/xyz/openbmc_project/object_mapper", 295 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePathsById", id, 296 path, subtreeInterfaces, association, endpointInterfaces); 297 } 298 299 inline void getDbusObject( 300 const std::string& path, std::span<const std::string_view> interfaces, 301 std::function<void(const boost::system::error_code&, 302 const MapperGetObject&)>&& callback) 303 { 304 crow::connections::systemBus->async_method_call( 305 [callback{std::move(callback)}](const boost::system::error_code& ec, 306 const MapperGetObject& object) { 307 callback(ec, object); 308 }, 309 "xyz.openbmc_project.ObjectMapper", 310 "/xyz/openbmc_project/object_mapper", 311 "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces); 312 } 313 314 inline void getAssociationEndPoints( 315 const std::string& path, 316 std::function<void(const boost::system::error_code&, 317 const MapperEndPoints&)>&& callback) 318 { 319 getProperty<MapperEndPoints>("xyz.openbmc_project.ObjectMapper", path, 320 "xyz.openbmc_project.Association", "endpoints", 321 std::move(callback)); 322 } 323 324 inline void getManagedObjects( 325 const std::string& service, const sdbusplus::message::object_path& path, 326 std::function<void(const boost::system::error_code&, 327 const ManagedObjectType&)>&& callback) 328 { 329 crow::connections::systemBus->async_method_call( 330 [callback{std::move(callback)}](const boost::system::error_code& ec, 331 const ManagedObjectType& objects) { 332 callback(ec, objects); 333 }, 334 service, path, "org.freedesktop.DBus.ObjectManager", 335 "GetManagedObjects"); 336 } 337 338 } // namespace utility 339 } // namespace dbus 340