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