1 #pragma once 2 3 #include "callback.hpp" 4 5 #include <phosphor-logging/log.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 using namespace phosphor::logging; 21 22 /** @class CallDBusMethod 23 * @brief Provide explicit call forwarding to 24 * DBusInterface::callMethodNoReply. 25 * 26 * @tparam DBusInterface - The DBus interface to use. 27 * @tparam MethodArgs - DBus method argument types. 28 */ 29 template <typename DBusInterface, typename... MethodArgs> 30 struct CallDBusMethod 31 { 32 static void op(const std::string& bus, const std::string& path, 33 const std::string& iface, const std::string& method, 34 MethodArgs&&... args) 35 { 36 try 37 { 38 DBusInterface::callMethodNoReply(bus, path, iface, method, 39 std::forward<MethodArgs>(args)...); 40 } 41 catch (const sdbusplus::exception::exception& e) 42 { 43 // clang-format off 44 log<level::ERR>("Unable to call DBus method", 45 entry("BUS=%s", bus.c_str(), 46 "PATH=%s", path.c_str(), 47 "IFACE=%s", iface.c_str(), 48 "METHOD=%s", method.c_str(), 49 "ERROR=%s", e.what())); 50 // clang-format on 51 } 52 } 53 }; 54 } // namespace detail 55 56 /** @class MethodBase 57 * @brief Invoke DBus method callback implementation. 58 * 59 * The method callback invokes the client supplied DBus method. 60 */ 61 class MethodBase : public Callback 62 { 63 public: 64 MethodBase() = delete; 65 MethodBase(const MethodBase&) = delete; 66 MethodBase(MethodBase&&) = default; 67 MethodBase& operator=(const MethodBase&) = delete; 68 MethodBase& operator=(MethodBase&&) = default; 69 virtual ~MethodBase() = default; 70 MethodBase(const std::string& b, const std::string& p, const std::string& i, 71 const std::string& m) : 72 Callback(), 73 bus(b), path(p), interface(i), method(m) 74 {} 75 76 /** @brief Callback interface implementation. */ 77 void operator()(Context ctx) override = 0; 78 79 protected: 80 const std::string& bus; 81 const std::string& path; 82 const std::string& interface; 83 const std::string& method; 84 }; 85 86 /** @class Method 87 * @brief C++ type specific logic for the method callback. 88 * 89 * @tparam DBusInterface - The DBus interface to use to call the method. 90 * @tparam MethodArgs - DBus method argument types. 91 */ 92 template <typename DBusInterface, typename... MethodArgs> 93 class Method : public MethodBase 94 { 95 public: 96 Method() = delete; 97 Method(const Method&) = default; 98 Method(Method&&) = default; 99 Method& operator=(const Method&) = default; 100 Method& operator=(Method&&) = default; 101 ~Method() = default; 102 Method(const std::string& bus, const std::string& path, 103 const std::string& iface, const std::string& method, 104 MethodArgs&&... arguments) : 105 MethodBase(bus, path, iface, method), 106 args(std::forward<MethodArgs>(arguments)...) 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