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