#pragma once #include #include #include #include #include #include "data_types.hpp" struct Loop; namespace phosphor { namespace dbus { namespace monitoring { using namespace phosphor::logging; using sdbusplus::exception::SdBusError; /** @class SDBusPlus * @brief DBus access delegate implementation for sdbusplus. */ class SDBusPlus { private: static auto& getWatches() { static std::vector watches; return watches; } public: static auto& getBus() { static auto bus = sdbusplus::bus::new_default(); return bus; } /** @brief Invoke a method; ignore reply. */ template static void callMethodNoReply(const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { auto reqMsg = getBus().new_method_call( busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); reqMsg.append(std::forward(args)...); getBus().call_noreply(reqMsg); // TODO: openbmc/openbmc#1719 // invoke these methods async, with a callback // handler that checks for errors and logs. } /** @brief Invoke a method. */ template static auto callMethod(const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { auto reqMsg = getBus().new_method_call( busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); reqMsg.append(std::forward(args)...); return getBus().call(reqMsg); } /** @brief Invoke a method and read the response. */ template static auto callMethodAndRead(const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { Ret resp; sdbusplus::message::message respMsg = callMethod( busName, path, interface, method, std::forward(args)...); try { respMsg.read(resp); } catch (const SdBusError& e) { log("Failed to parse method response", entry("ERROR=%s", e.what()), entry("REPLY_SIG=%s", respMsg.get_signature())); } return resp; } /** @brief Register a DBus signal callback. */ static auto addMatch(const std::string& match, const sdbusplus::bus::match::match::callback_t& callback) { getWatches().emplace_back(getBus(), match, callback); } /** @brief Look up the bus name for a path and interface */ static auto getBusName(const std::string& path, const std::string& interface) { std::vector interfaces{interface}; auto object = callMethodAndRead( MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject", path, interfaces); std::string name; if (!object.empty()) { name = object.begin()->first; } return name; } friend Loop; }; } // namespace monitoring } // namespace dbus } // namespace phosphor