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