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