1 #pragma once 2 3 #include <phosphor-logging/log.hpp> 4 #include <sdbusplus/bus.hpp> 5 #include <sdbusplus/exception.hpp> 6 #include <sdbusplus/message.hpp> 7 #include <sdbusplus/bus/match.hpp> 8 #include "data_types.hpp" 9 10 struct Loop; 11 12 namespace phosphor 13 { 14 namespace dbus 15 { 16 namespace monitoring 17 { 18 19 using namespace phosphor::logging; 20 using sdbusplus::exception::SdBusError; 21 22 /** @class SDBusPlus 23 * @brief DBus access delegate implementation for sdbusplus. 24 */ 25 class SDBusPlus 26 { 27 private: 28 static auto& getWatches() 29 { 30 static std::vector<sdbusplus::bus::match::match> watches; 31 return watches; 32 } 33 34 public: 35 static auto& getBus() 36 { 37 static auto bus = sdbusplus::bus::new_default(); 38 return bus; 39 } 40 41 /** @brief Invoke a method; ignore reply. */ 42 template <typename... Args> 43 static void callMethodNoReply(const std::string& busName, 44 const std::string& path, 45 const std::string& interface, 46 const std::string& method, Args&&... args) 47 { 48 auto reqMsg = getBus().new_method_call( 49 busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); 50 reqMsg.append(std::forward<Args>(args)...); 51 getBus().call_noreply(reqMsg); 52 53 // TODO: openbmc/openbmc#1719 54 // invoke these methods async, with a callback 55 // handler that checks for errors and logs. 56 } 57 58 /** @brief Invoke a method. */ 59 template <typename... Args> 60 static auto callMethod(const std::string& busName, const std::string& path, 61 const std::string& interface, 62 const std::string& method, Args&&... args) 63 { 64 auto reqMsg = getBus().new_method_call( 65 busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); 66 reqMsg.append(std::forward<Args>(args)...); 67 return getBus().call(reqMsg); 68 } 69 70 /** @brief Invoke a method and read the response. */ 71 template <typename Ret, typename... Args> 72 static auto callMethodAndRead(const std::string& busName, 73 const std::string& path, 74 const std::string& interface, 75 const std::string& method, Args&&... args) 76 { 77 Ret resp; 78 sdbusplus::message::message respMsg = callMethod<Args...>( 79 busName, path, interface, method, std::forward<Args>(args)...); 80 try 81 { 82 respMsg.read(resp); 83 } 84 catch (const SdBusError& e) 85 { 86 log<level::ERR>("Failed to parse method response", 87 entry("ERROR=%s", e.what()), 88 entry("REPLY_SIG=%s", respMsg.get_signature())); 89 } 90 return resp; 91 } 92 93 /** @brief Register a DBus signal callback. */ 94 static auto 95 addMatch(const std::string& match, 96 const sdbusplus::bus::match::match::callback_t& callback) 97 { 98 getWatches().emplace_back(getBus(), match, callback); 99 } 100 101 /** @brief Look up the bus name for a path and interface */ 102 static auto getBusName(const std::string& path, 103 const std::string& interface) 104 { 105 std::vector<std::string> interfaces{interface}; 106 107 auto object = callMethodAndRead<GetObject>( 108 MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject", path, 109 interfaces); 110 111 std::string name; 112 if (!object.empty()) 113 { 114 name = object.begin()->first; 115 } 116 return name; 117 } 118 119 friend Loop; 120 }; 121 122 } // namespace monitoring 123 } // namespace dbus 124 } // namespace phosphor 125