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: 27 static auto& getWatches() 28 { 29 static std::vector<sdbusplus::bus::match_t> watches; 30 return watches; 31 } 32 33 public: 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> 42 static void callMethodNoReply(const std::string& busName, 43 const std::string& path, 44 const std::string& interface, 45 const std::string& method, Args&&... args) 46 { 47 auto reqMsg = getBus().new_method_call( 48 busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); 49 reqMsg.append(std::forward<Args>(args)...); 50 getBus().call_noreply(reqMsg); 51 52 // TODO: openbmc/openbmc#1719 53 // invoke these methods async, with a callback 54 // handler that checks for errors and logs. 55 } 56 57 /** @brief Invoke a method. */ 58 template <typename... Args> 59 static auto callMethod(const std::string& busName, const std::string& path, 60 const std::string& interface, 61 const std::string& method, Args&&... args) 62 { 63 auto reqMsg = getBus().new_method_call( 64 busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); 65 reqMsg.append(std::forward<Args>(args)...); 66 return getBus().call(reqMsg); 67 } 68 69 /** @brief Invoke a method and read the response. */ 70 template <typename Ret, typename... Args> 71 static auto callMethodAndRead(const std::string& busName, 72 const std::string& path, 73 const std::string& interface, 74 const std::string& method, Args&&... args) 75 { 76 Ret resp; 77 sdbusplus::message_t respMsg = callMethod<Args...>( 78 busName, path, interface, method, std::forward<Args>(args)...); 79 try 80 { 81 respMsg.read(resp); 82 } 83 catch (const sdbusplus::exception_t& e) 84 { 85 // Empty responses are expected sometimes, and the calling 86 // code is set up to handle it. 87 } 88 return resp; 89 } 90 91 /** @brief Register a DBus signal callback. */ 92 static auto addMatch(const std::string& match, 93 sdbusplus::bus::match_t::callback_t&& callback) 94 { 95 getWatches().emplace_back(getBus(), match, std::move(callback)); 96 } 97 98 /** @brief Look up the bus name for a path and interface */ 99 static auto getBusName(const std::string& path, 100 const std::string& interface) 101 { 102 std::vector<std::string> interfaces{interface}; 103 std::string name; 104 105 try 106 { 107 auto object = callMethodAndRead<GetObject>( 108 MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject", 109 path, interfaces); 110 111 if (!object.empty()) 112 { 113 name = object.begin()->first; 114 } 115 } 116 catch (const sdbusplus::exception_t& e) 117 { 118 // Empty responses are expected sometimes, and the calling 119 // code is set up to handle it. 120 } 121 return name; 122 } 123 124 friend Loop; 125 }; 126 127 } // namespace monitoring 128 } // namespace dbus 129 } // namespace phosphor 130