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