1 #pragma once 2 3 #include "callback.hpp" 4 5 #include <experimental/tuple> 6 #include <phosphor-logging/log.hpp> 7 #include <string> 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::experimental::apply( 113 detail::CallDBusMethod<DBusInterface, MethodArgs...>::op, 114 std::tuple_cat(std::make_tuple(bus), std::make_tuple(path), 115 std::make_tuple(interface), std::make_tuple(method), 116 args)); 117 } 118 119 private: 120 std::tuple<MethodArgs...> args; 121 }; 122 123 /** @brief Argument type deduction for constructing Method instances. */ 124 template <typename DBusInterface, typename... MethodArgs> 125 auto makeMethod(const std::string& bus, const std::string& path, 126 const std::string& iface, const std::string& method, 127 MethodArgs&&... arguments) 128 { 129 return std::make_unique<Method<DBusInterface, MethodArgs...>>( 130 bus, path, iface, method, std::forward<MethodArgs>(arguments)...); 131 } 132 133 } // namespace monitoring 134 } // namespace dbus 135 } // namespace phosphor 136