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