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