1 #pragma once 2 3 #include "callback.hpp" 4 5 #include <phosphor-logging/log.hpp> 6 #include <string> 7 #include <tuple> 8 9 namespace phosphor 10 { 11 namespace dbus 12 { 13 namespace monitoring 14 { 15 namespace detail 16 { 17 18 using namespace phosphor::logging; 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 // clang-format off 42 log<level::ERR>("Unable to call DBus method", 43 entry("BUS=%s", bus.c_str(), 44 "PATH=%s", path.c_str(), 45 "IFACE=%s", iface.c_str(), 46 "METHOD=%s", method.c_str(), 47 "ERROR=%s", e.what())); 48 // clang-format on 49 } 50 } 51 }; 52 } // namespace detail 53 54 /** @class MethodBase 55 * @brief Invoke DBus method callback implementation. 56 * 57 * The method callback invokes the client supplied DBus method. 58 */ 59 class MethodBase : public Callback 60 { 61 public: 62 MethodBase() = delete; 63 MethodBase(const MethodBase&) = delete; 64 MethodBase(MethodBase&&) = default; 65 MethodBase& operator=(const MethodBase&) = delete; 66 MethodBase& operator=(MethodBase&&) = default; 67 virtual ~MethodBase() = default; 68 MethodBase(const std::string& b, const std::string& p, const std::string& i, 69 const std::string& m) : 70 Callback(), 71 bus(b), path(p), interface(i), method(m) 72 { 73 } 74 75 /** @brief Callback interface implementation. */ 76 void operator()(Context ctx) override = 0; 77 78 protected: 79 const std::string& bus; 80 const std::string& path; 81 const std::string& interface; 82 const std::string& method; 83 }; 84 85 /** @class Method 86 * @brief C++ type specific logic for the method callback. 87 * 88 * @tparam DBusInterface - The DBus interface to use to call the method. 89 * @tparam MethodArgs - DBus method argument types. 90 */ 91 template <typename DBusInterface, typename... MethodArgs> 92 class Method : public MethodBase 93 { 94 public: 95 Method() = delete; 96 Method(const Method&) = default; 97 Method(Method&&) = default; 98 Method& operator=(const Method&) = default; 99 Method& operator=(Method&&) = default; 100 ~Method() = default; 101 Method(const std::string& bus, const std::string& path, 102 const std::string& iface, const std::string& method, 103 MethodArgs&&... arguments) : 104 MethodBase(bus, path, iface, method), 105 args(std::forward<MethodArgs>(arguments)...) 106 { 107 } 108 109 /** @brief Callback interface implementation. */ 110 void operator()(Context ctx) override 111 { 112 std::apply(detail::CallDBusMethod<DBusInterface, MethodArgs...>::op, 113 std::tuple_cat(std::make_tuple(bus), std::make_tuple(path), 114 std::make_tuple(interface), 115 std::make_tuple(method), 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