1 #pragma once 2 3 #include "callback.hpp" 4 5 #include <experimental/tuple> 6 #include <phosphor-logging/log.hpp> 7 8 namespace phosphor 9 { 10 namespace dbus 11 { 12 namespace monitoring 13 { 14 namespace detail 15 { 16 17 using namespace phosphor::logging; 18 19 /** @class CallDBusMethod 20 * @brief Provide explicit call forwarding to 21 * DBusInterface::callMethodNoReply. 22 * 23 * @tparam DBusInterface - The DBus interface to use. 24 * @tparam MethodArgs - DBus method argument types. 25 */ 26 template <typename DBusInterface, typename... MethodArgs> 27 struct CallDBusMethod 28 { 29 static void op(const std::string& bus, const std::string& path, 30 const std::string& iface, const std::string& method, 31 MethodArgs&&... args) 32 { 33 try 34 { 35 DBusInterface::callMethodNoReply(bus, path, iface, method, 36 std::forward<MethodArgs>(args)...); 37 } 38 catch (const sdbusplus::exception::SdBusError& e) 39 { 40 // clang-format off 41 log<level::ERR>("Unable to call DBus method", 42 entry("BUS=%s", bus.c_str(), 43 "PATH=%s", path.c_str(), 44 "IFACE=%s", iface.c_str(), 45 "METHOD=%s", method.c_str(), 46 "ERROR=%s", e.what())); 47 // clang-format on 48 } 49 } 50 }; 51 } // namespace detail 52 53 /** @class MethodBase 54 * @brief Invoke DBus method callback implementation. 55 * 56 * The method callback invokes the client supplied DBus method. 57 */ 58 class MethodBase : public Callback 59 { 60 public: 61 MethodBase() = delete; 62 MethodBase(const MethodBase&) = delete; 63 MethodBase(MethodBase&&) = default; 64 MethodBase& operator=(const MethodBase&) = delete; 65 MethodBase& operator=(MethodBase&&) = default; 66 virtual ~MethodBase() = default; 67 MethodBase(const std::string& b, const std::string& p, const std::string& i, 68 const std::string& m) : 69 Callback(), 70 bus(b), path(p), interface(i), method(m) 71 { 72 } 73 74 /** @brief Callback interface implementation. */ 75 void operator()(Context ctx) override = 0; 76 77 protected: 78 const std::string& bus; 79 const std::string& path; 80 const std::string& interface; 81 const std::string& method; 82 }; 83 84 /** @class Method 85 * @brief C++ type specific logic for the method callback. 86 * 87 * @tparam DBusInterface - The DBus interface to use to call the method. 88 * @tparam MethodArgs - DBus method argument types. 89 */ 90 template <typename DBusInterface, typename... MethodArgs> 91 class Method : public MethodBase 92 { 93 public: 94 Method() = delete; 95 Method(const Method&) = default; 96 Method(Method&&) = default; 97 Method& operator=(const Method&) = default; 98 Method& operator=(Method&&) = default; 99 ~Method() = default; 100 Method(const std::string& bus, const std::string& path, 101 const std::string& iface, const std::string& method, 102 MethodArgs&&... arguments) : 103 MethodBase(bus, path, iface, method), 104 args(std::forward<MethodArgs>(arguments)...) 105 { 106 } 107 108 /** @brief Callback interface implementation. */ 109 void operator()(Context ctx) override 110 { 111 std::experimental::apply( 112 detail::CallDBusMethod<DBusInterface, MethodArgs...>::op, 113 std::tuple_cat(std::make_tuple(bus), std::make_tuple(path), 114 std::make_tuple(interface), std::make_tuple(method), 115 args)); 116 } 117 118 private: 119 std::tuple<MethodArgs...> args; 120 }; 121 122 /** @brief Argument type deduction for constructing Method instances. */ 123 template <typename DBusInterface, typename... MethodArgs> 124 auto makeMethod(const std::string& bus, const std::string& path, 125 const std::string& iface, const std::string& method, 126 MethodArgs&&... arguments) 127 { 128 return std::make_unique<Method<DBusInterface, MethodArgs...>>( 129 bus, path, iface, method, std::forward<MethodArgs>(arguments)...); 130 } 131 132 } // namespace monitoring 133 } // namespace dbus 134 } // namespace phosphor 135