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 getDbusObject( 229 const std::string& path, std::span<const std::string_view> interfaces, 230 std::function<void(const boost::system::error_code&, 231 const MapperGetObject&)>&& callback) 232 { 233 crow::connections::systemBus->async_method_call( 234 [callback{std::move(callback)}](const boost::system::error_code& ec, 235 const MapperGetObject& object) { 236 callback(ec, object); 237 }, 238 "xyz.openbmc_project.ObjectMapper", 239 "/xyz/openbmc_project/object_mapper", 240 "xyz.openbmc_project.ObjectMapper", "GetObject", path, interfaces); 241 } 242 243 inline void getAssociationEndPoints( 244 const std::string& path, 245 std::function<void(const boost::system::error_code&, 246 const MapperEndPoints&)>&& callback) 247 { 248 sdbusplus::asio::getProperty<MapperEndPoints>( 249 *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", path, 250 "xyz.openbmc_project.Association", "endpoints", std::move(callback)); 251 } 252 253 inline void getManagedObjects( 254 const std::string& service, const sdbusplus::message::object_path& path, 255 std::function<void(const boost::system::error_code&, 256 const ManagedObjectType&)>&& callback) 257 { 258 crow::connections::systemBus->async_method_call( 259 [callback{std::move(callback)}](const boost::system::error_code& ec, 260 const ManagedObjectType& objects) { 261 callback(ec, objects); 262 }, 263 service, path, "org.freedesktop.DBus.ObjectManager", 264 "GetManagedObjects"); 265 } 266 267 } // namespace utility 268 } // namespace dbus 269