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