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 template <typename Callback> 190 inline void checkDbusPathExists(const std::string& path, Callback&& callback) 191 { 192 crow::connections::systemBus->async_method_call( 193 [callback = std::forward<Callback>(callback)]( 194 const boost::system::error_code& ec, 195 const MapperGetObject& objectNames) { 196 callback(!ec && !objectNames.empty()); 197 }, 198 "xyz.openbmc_project.ObjectMapper", 199 "/xyz/openbmc_project/object_mapper", 200 "xyz.openbmc_project.ObjectMapper", "GetObject", path, 201 std::array<std::string, 0>()); 202 } 203 204 inline void 205 getSubTree(const std::string& path, int32_t depth, 206 std::span<const std::string_view> interfaces, 207 std::function<void(const boost::system::error_code&, 208 const MapperGetSubTreeResponse&)>&& callback) 209 { 210 crow::connections::systemBus->async_method_call( 211 [callback{std::move(callback)}]( 212 const boost::system::error_code& ec, 213 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 214 "xyz.openbmc_project.ObjectMapper", 215 "/xyz/openbmc_project/object_mapper", 216 "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth, 217 interfaces); 218 } 219 220 inline void getSubTreePaths( 221 const std::string& path, int32_t depth, 222 std::span<const std::string_view> interfaces, 223 std::function<void(const boost::system::error_code&, 224 const MapperGetSubTreePathsResponse&)>&& callback) 225 { 226 crow::connections::systemBus->async_method_call( 227 [callback{std::move(callback)}]( 228 const boost::system::error_code& ec, 229 const MapperGetSubTreePathsResponse& subtreePaths) { 230 callback(ec, subtreePaths); 231 }, 232 "xyz.openbmc_project.ObjectMapper", 233 "/xyz/openbmc_project/object_mapper", 234 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth, 235 interfaces); 236 } 237 238 inline void getAssociatedSubTree( 239 const sdbusplus::message::object_path& associatedPath, 240 const sdbusplus::message::object_path& path, int32_t depth, 241 std::span<const std::string_view> interfaces, 242 std::function<void(const boost::system::error_code&, 243 const MapperGetSubTreeResponse&)>&& callback) 244 { 245 crow::connections::systemBus->async_method_call( 246 [callback{std::move(callback)}]( 247 const boost::system::error_code& ec, 248 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 249 "xyz.openbmc_project.ObjectMapper", 250 "/xyz/openbmc_project/object_mapper", 251 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree", 252 associatedPath, path, depth, interfaces); 253 } 254 255 inline void getAssociatedSubTreePaths( 256 const sdbusplus::message::object_path& associatedPath, 257 const sdbusplus::message::object_path& path, int32_t depth, 258 std::span<const std::string_view> interfaces, 259 std::function<void(const boost::system::error_code&, 260 const MapperGetSubTreePathsResponse&)>&& callback) 261 { 262 crow::connections::systemBus->async_method_call( 263 [callback{std::move(callback)}]( 264 const boost::system::error_code& ec, 265 const MapperGetSubTreePathsResponse& subtreePaths) { 266 callback(ec, subtreePaths); 267 }, 268 "xyz.openbmc_project.ObjectMapper", 269 "/xyz/openbmc_project/object_mapper", 270 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths", 271 associatedPath, path, depth, interfaces); 272 } 273 274 inline void getAssociatedSubTreeById( 275 const std::string& id, const std::string& path, 276 std::span<const std::string_view> subtreeInterfaces, 277 std::string_view association, 278 std::span<const std::string_view> endpointInterfaces, 279 std::function<void(const boost::system::error_code&, 280 const MapperGetSubTreeResponse&)>&& callback) 281 { 282 crow::connections::systemBus->async_method_call( 283 [callback{std::move(callback)}]( 284 const boost::system::error_code& ec, 285 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 286 "xyz.openbmc_project.ObjectMapper", 287 "/xyz/openbmc_project/object_mapper", 288 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreeById", id, 289 path, subtreeInterfaces, association, endpointInterfaces); 290 } 291 292 inline void getAssociatedSubTreePathsById( 293 const std::string& id, const std::string& path, 294 std::span<const std::string_view> subtreeInterfaces, 295 std::string_view association, 296 std::span<const std::string_view> endpointInterfaces, 297 std::function<void(const boost::system::error_code&, 298 const MapperGetSubTreePathsResponse&)>&& callback) 299 { 300 crow::connections::systemBus->async_method_call( 301 [callback{std::move(callback)}]( 302 const boost::system::error_code& ec, 303 const MapperGetSubTreePathsResponse& subtreePaths) { 304 callback(ec, subtreePaths); 305 }, 306 "xyz.openbmc_project.ObjectMapper", 307 "/xyz/openbmc_project/object_mapper", 308 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePathsById", id, 309 path, subtreeInterfaces, association, endpointInterfaces); 310 } 311 312 inline void getDbusObject( 313 const std::string& path, std::span<const std::string_view> interfaces, 314 std::function<void(const boost::system::error_code&, 315 const MapperGetObject&)>&& callback) 316 { 317 crow::connections::systemBus->async_method_call( 318 [callback{std::move(callback)}](const boost::system::error_code& ec, 319 const MapperGetObject& object) { 320 callback(ec, object); 321 }, 322 "xyz.openbmc_project.ObjectMapper", 323 "/xyz/openbmc_project/object_mapper", 324 "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces); 325 } 326 327 inline void getAssociationEndPoints( 328 const std::string& path, 329 std::function<void(const boost::system::error_code&, 330 const MapperEndPoints&)>&& callback) 331 { 332 getProperty<MapperEndPoints>("xyz.openbmc_project.ObjectMapper", path, 333 "xyz.openbmc_project.Association", "endpoints", 334 std::move(callback)); 335 } 336 337 inline void getManagedObjects( 338 const std::string& service, const sdbusplus::message::object_path& path, 339 std::function<void(const boost::system::error_code&, 340 const ManagedObjectType&)>&& callback) 341 { 342 crow::connections::systemBus->async_method_call( 343 [callback{std::move(callback)}](const boost::system::error_code& ec, 344 const ManagedObjectType& objects) { 345 callback(ec, objects); 346 }, 347 service, path, "org.freedesktop.DBus.ObjectManager", 348 "GetManagedObjects"); 349 } 350 351 } // namespace utility 352 } // namespace dbus 353