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