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