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