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 // Empty responses are expected sometimes, and the calling 87 // code is set up to handle it. 88 } 89 return resp; 90 } 91 92 /** @brief Register a DBus signal callback. */ 93 static auto 94 addMatch(const std::string& match, 95 const sdbusplus::bus::match::match::callback_t& callback) 96 { 97 getWatches().emplace_back(getBus(), match, callback); 98 } 99 100 /** @brief Look up the bus name for a path and interface */ 101 static auto getBusName(const std::string& path, 102 const std::string& interface) 103 { 104 std::vector<std::string> interfaces{interface}; 105 106 auto object = callMethodAndRead<GetObject>( 107 MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject", path, 108 interfaces); 109 110 std::string name; 111 if (!object.empty()) 112 { 113 name = object.begin()->first; 114 } 115 return name; 116 } 117 118 friend Loop; 119 }; 120 121 } // namespace monitoring 122 } // namespace dbus 123 } // namespace phosphor 124