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