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 sdbusplus::message::unix_fd, 63 std::vector<uint32_t>, 64 std::vector<uint16_t>, 65 sdbusplus::message::object_path, 66 std::tuple<uint64_t, std::vector<std::tuple<std::string, double, uint64_t>>>, 67 std::vector<sdbusplus::message::object_path>, 68 std::vector<std::tuple<std::string, std::string>>, 69 std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>, 70 std::vector<std::tuple<uint32_t, size_t>>, 71 std::vector<std::tuple< 72 std::vector<std::tuple<sdbusplus::message::object_path, std::string>>, 73 std::string, std::string, uint64_t>> 74 >; 75 76 // clang-format on 77 using DBusPropertiesMap = std::vector<std::pair<std::string, DbusVariantType>>; 78 using DBusInterfacesMap = 79 std::vector<std::pair<std::string, DBusPropertiesMap>>; 80 using ManagedObjectType = 81 std::vector<std::pair<sdbusplus::message::object_path, DBusInterfacesMap>>; 82 83 // Map of service name to list of interfaces 84 using MapperServiceMap = 85 std::vector<std::pair<std::string, std::vector<std::string>>>; 86 87 // Map of object paths to MapperServiceMaps 88 using MapperGetSubTreeResponse = 89 std::vector<std::pair<std::string, MapperServiceMap>>; 90 91 using MapperGetObject = 92 std::vector<std::pair<std::string, std::vector<std::string>>>; 93 94 using MapperGetAncestorsResponse = std::vector< 95 std::pair<std::string, 96 std::vector<std::pair<std::string, std::vector<std::string>>>>>; 97 98 using MapperGetSubTreePathsResponse = std::vector<std::string>; 99 100 using MapperEndPoints = std::vector<std::string>; 101 102 inline void escapePathForDbus(std::string& path) 103 { 104 const static std::regex reg("[^A-Za-z0-9_/]"); 105 std::regex_replace(path.begin(), path.begin(), path.end(), reg, "_"); 106 } 107 108 inline void logError(const boost::system::error_code& ec) 109 { 110 if (ec) 111 { 112 BMCWEB_LOG_ERROR("DBus error: {}, cannot call method", ec); 113 } 114 } 115 116 // gets the string N strings deep into a path 117 // i.e. /0th/1st/2nd/3rd 118 inline bool getNthStringFromPath(const std::string& path, int index, 119 std::string& result) 120 { 121 if (index < 0) 122 { 123 return false; 124 } 125 126 std::filesystem::path p1(path); 127 int count = -1; 128 for (const auto& element : p1) 129 { 130 if (element.has_filename()) 131 { 132 ++count; 133 if (count == index) 134 { 135 result = element.stem().string(); 136 break; 137 } 138 } 139 } 140 return count >= index; 141 } 142 143 template <typename Callback> 144 inline void checkDbusPathExists(const std::string& path, Callback&& callback) 145 { 146 crow::connections::systemBus->async_method_call( 147 [callback = std::forward<Callback>(callback)]( 148 const boost::system::error_code& ec, 149 const dbus::utility::MapperGetObject& objectNames) { 150 callback(!ec && !objectNames.empty()); 151 }, 152 "xyz.openbmc_project.ObjectMapper", 153 "/xyz/openbmc_project/object_mapper", 154 "xyz.openbmc_project.ObjectMapper", "GetObject", path, 155 std::array<std::string, 0>()); 156 } 157 158 inline void 159 getSubTree(const std::string& path, int32_t depth, 160 std::span<const std::string_view> interfaces, 161 std::function<void(const boost::system::error_code&, 162 const MapperGetSubTreeResponse&)>&& callback) 163 { 164 crow::connections::systemBus->async_method_call( 165 [callback{std::move(callback)}]( 166 const boost::system::error_code& ec, 167 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 168 "xyz.openbmc_project.ObjectMapper", 169 "/xyz/openbmc_project/object_mapper", 170 "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth, 171 interfaces); 172 } 173 174 inline void getSubTreePaths( 175 const std::string& path, int32_t depth, 176 std::span<const std::string_view> interfaces, 177 std::function<void(const boost::system::error_code&, 178 const MapperGetSubTreePathsResponse&)>&& callback) 179 { 180 crow::connections::systemBus->async_method_call( 181 [callback{std::move(callback)}]( 182 const boost::system::error_code& ec, 183 const MapperGetSubTreePathsResponse& subtreePaths) { 184 callback(ec, subtreePaths); 185 }, 186 "xyz.openbmc_project.ObjectMapper", 187 "/xyz/openbmc_project/object_mapper", 188 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth, 189 interfaces); 190 } 191 192 inline void getAssociatedSubTree( 193 const sdbusplus::message::object_path& associatedPath, 194 const sdbusplus::message::object_path& path, int32_t depth, 195 std::span<const std::string_view> interfaces, 196 std::function<void(const boost::system::error_code&, 197 const MapperGetSubTreeResponse&)>&& callback) 198 { 199 crow::connections::systemBus->async_method_call( 200 [callback{std::move(callback)}]( 201 const boost::system::error_code& ec, 202 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 203 "xyz.openbmc_project.ObjectMapper", 204 "/xyz/openbmc_project/object_mapper", 205 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree", 206 associatedPath, path, depth, interfaces); 207 } 208 209 inline void getAssociatedSubTreePaths( 210 const sdbusplus::message::object_path& associatedPath, 211 const sdbusplus::message::object_path& path, int32_t depth, 212 std::span<const std::string_view> interfaces, 213 std::function<void(const boost::system::error_code&, 214 const MapperGetSubTreePathsResponse&)>&& callback) 215 { 216 crow::connections::systemBus->async_method_call( 217 [callback{std::move(callback)}]( 218 const boost::system::error_code& ec, 219 const MapperGetSubTreePathsResponse& subtreePaths) { 220 callback(ec, subtreePaths); 221 }, 222 "xyz.openbmc_project.ObjectMapper", 223 "/xyz/openbmc_project/object_mapper", 224 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths", 225 associatedPath, path, depth, interfaces); 226 } 227 228 inline void getAssociatedSubTreeById( 229 const std::string& id, const std::string& path, 230 std::span<const std::string_view> subtreeInterfaces, 231 std::string_view association, 232 std::span<const std::string_view> endpointInterfaces, 233 std::function<void(const boost::system::error_code&, 234 const MapperGetSubTreeResponse&)>&& callback) 235 { 236 crow::connections::systemBus->async_method_call( 237 [callback{std::move(callback)}]( 238 const boost::system::error_code& ec, 239 const MapperGetSubTreeResponse& subtree) { callback(ec, subtree); }, 240 "xyz.openbmc_project.ObjectMapper", 241 "/xyz/openbmc_project/object_mapper", 242 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreeById", id, 243 path, subtreeInterfaces, association, endpointInterfaces); 244 } 245 246 inline void getAssociatedSubTreePathsById( 247 const std::string& id, const std::string& path, 248 std::span<const std::string_view> subtreeInterfaces, 249 std::string_view association, 250 std::span<const std::string_view> endpointInterfaces, 251 std::function<void(const boost::system::error_code&, 252 const MapperGetSubTreePathsResponse&)>&& callback) 253 { 254 crow::connections::systemBus->async_method_call( 255 [callback{std::move(callback)}]( 256 const boost::system::error_code& ec, 257 const MapperGetSubTreePathsResponse& subtreePaths) { 258 callback(ec, subtreePaths); 259 }, 260 "xyz.openbmc_project.ObjectMapper", 261 "/xyz/openbmc_project/object_mapper", 262 "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePathsById", id, 263 path, subtreeInterfaces, association, endpointInterfaces); 264 } 265 266 inline void getDbusObject( 267 const std::string& path, std::span<const std::string_view> interfaces, 268 std::function<void(const boost::system::error_code&, 269 const MapperGetObject&)>&& callback) 270 { 271 crow::connections::systemBus->async_method_call( 272 [callback{std::move(callback)}](const boost::system::error_code& ec, 273 const MapperGetObject& object) { 274 callback(ec, object); 275 }, 276 "xyz.openbmc_project.ObjectMapper", 277 "/xyz/openbmc_project/object_mapper", 278 "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces); 279 } 280 281 inline void getAssociationEndPoints( 282 const std::string& path, 283 std::function<void(const boost::system::error_code&, 284 const MapperEndPoints&)>&& callback) 285 { 286 sdbusplus::asio::getProperty<MapperEndPoints>( 287 *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path, 288 "xyz.openbmc_project.Association", "endpoints", std::move(callback)); 289 } 290 291 inline void getManagedObjects( 292 const std::string& service, const sdbusplus::message::object_path& path, 293 std::function<void(const boost::system::error_code&, 294 const ManagedObjectType&)>&& callback) 295 { 296 crow::connections::systemBus->async_method_call( 297 [callback{std::move(callback)}](const boost::system::error_code& ec, 298 const ManagedObjectType& objects) { 299 callback(ec, objects); 300 }, 301 service, path, "org.freedesktop.DBus.ObjectManager", 302 "GetManagedObjects"); 303 } 304 305 } // namespace utility 306 } // namespace dbus 307