1 #pragma once
2 
3 #include "callback.hpp"
4 
5 #include <experimental/tuple>
6 
7 namespace phosphor
8 {
9 namespace dbus
10 {
11 namespace monitoring
12 {
13 namespace detail
14 {
15 
16 /** @class CallDBusMethod
17  *  @brief Provide explicit call forwarding to
18  *     DBusInterface::callMethodNoReply.
19  *
20  *  @tparam DBusInterface - The DBus interface to use.
21  *  @tparam MethodArgs - DBus method argument types.
22  */
23 template <typename DBusInterface, typename... MethodArgs>
24 struct CallDBusMethod
25 {
26     static void op(const std::string& bus, const std::string& path,
27                    const std::string& iface, const std::string& method,
28                    MethodArgs&&... args)
29     {
30         DBusInterface::callMethodNoReply(bus, path, iface, method,
31                                          std::forward<MethodArgs>(args)...);
32     }
33 };
34 } // namespace detail
35 
36 /** @class MethodBase
37  *  @brief Invoke DBus method callback implementation.
38  *
39  *  The method callback invokes the client supplied DBus method.
40  */
41 class MethodBase : public Callback
42 {
43   public:
44     MethodBase() = delete;
45     MethodBase(const MethodBase&) = delete;
46     MethodBase(MethodBase&&) = default;
47     MethodBase& operator=(const MethodBase&) = delete;
48     MethodBase& operator=(MethodBase&&) = default;
49     virtual ~MethodBase() = default;
50     MethodBase(const std::string& b, const std::string& p, const std::string& i,
51                const std::string& m) :
52         Callback(),
53         bus(b), path(p), interface(i), method(m)
54     {
55     }
56 
57     /** @brief Callback interface implementation. */
58     void operator()(Context ctx) override = 0;
59 
60   protected:
61     const std::string& bus;
62     const std::string& path;
63     const std::string& interface;
64     const std::string& method;
65 };
66 
67 /** @class Method
68  *  @brief C++ type specific logic for the method callback.
69  *
70  *  @tparam DBusInterface - The DBus interface to use to call the method.
71  *  @tparam MethodArgs - DBus method argument types.
72  */
73 template <typename DBusInterface, typename... MethodArgs>
74 class Method : public MethodBase
75 {
76   public:
77     Method() = delete;
78     Method(const Method&) = default;
79     Method(Method&&) = default;
80     Method& operator=(const Method&) = default;
81     Method& operator=(Method&&) = default;
82     ~Method() = default;
83     Method(const std::string& bus, const std::string& path,
84            const std::string& iface, const std::string& method,
85            MethodArgs&&... arguments) :
86         MethodBase(bus, path, iface, method),
87         args(std::forward<MethodArgs>(arguments)...)
88     {
89     }
90 
91     /** @brief Callback interface implementation. */
92     void operator()(Context ctx) override
93     {
94         std::experimental::apply(
95             detail::CallDBusMethod<DBusInterface, MethodArgs...>::op,
96             std::tuple_cat(std::make_tuple(bus), std::make_tuple(path),
97                            std::make_tuple(interface), std::make_tuple(method),
98                            args));
99     }
100 
101   private:
102     std::tuple<MethodArgs...> args;
103 };
104 
105 /** @brief Argument type deduction for constructing Method instances. */
106 template <typename DBusInterface, typename... MethodArgs>
107 auto makeMethod(const std::string& bus, const std::string& path,
108                 const std::string& iface, const std::string& method,
109                 MethodArgs&&... arguments)
110 {
111     return std::make_unique<Method<DBusInterface, MethodArgs...>>(
112         bus, path, iface, method, std::forward<MethodArgs>(arguments)...);
113 }
114 
115 } // namespace monitoring
116 } // namespace dbus
117 } // namespace phosphor
118