xref: /openbmc/phosphor-dbus-monitor/src/method.hpp (revision 92907da08e311656bd5980476c252c19e8dbad11)
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