1 #pragma once
2 
3 #include "callback.hpp"
4 
5 #include <phosphor-logging/lg2.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 /** @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             lg2::error(
42                 "Unable to call DBus method: {ERROR}. {BUS}, {PATH}, {INTF}, {METHOD}",
43                 "ERROR", e, "BUS", bus, "PATH", path, "INTF", iface, "METHOD",
44                 method);
45         }
46     }
47 };
48 } // namespace detail
49 
50 /** @class MethodBase
51  *  @brief Invoke DBus method callback implementation.
52  *
53  *  The method callback invokes the client supplied DBus method.
54  */
55 class MethodBase : public Callback
56 {
57   public:
58     MethodBase() = delete;
59     MethodBase(const MethodBase&) = delete;
60     MethodBase(MethodBase&&) = default;
61     MethodBase& operator=(const MethodBase&) = delete;
62     MethodBase& operator=(MethodBase&&) = default;
63     virtual ~MethodBase() = default;
64     MethodBase(const std::string& b, const std::string& p, const std::string& i,
65                const std::string& m) :
66         Callback(),
67         bus(b), path(p), interface(i), method(m)
68     {}
69 
70     /** @brief Callback interface implementation. */
71     void operator()(Context ctx) override = 0;
72 
73   protected:
74     const std::string& bus;
75     const std::string& path;
76     const std::string& interface;
77     const std::string& method;
78 };
79 
80 /** @class Method
81  *  @brief C++ type specific logic for the method callback.
82  *
83  *  @tparam DBusInterface - The DBus interface to use to call the method.
84  *  @tparam MethodArgs - DBus method argument types.
85  */
86 template <typename DBusInterface, typename... MethodArgs>
87 class Method : public MethodBase
88 {
89   public:
90     Method() = delete;
91     Method(const Method&) = default;
92     Method(Method&&) = default;
93     Method& operator=(const Method&) = default;
94     Method& operator=(Method&&) = default;
95     ~Method() = default;
96     Method(const std::string& bus, const std::string& path,
97            const std::string& iface, const std::string& method,
98            MethodArgs&&... arguments) :
99         MethodBase(bus, path, iface, method),
100         args(std::forward<MethodArgs>(arguments)...)
101     {}
102 
103     /** @brief Callback interface implementation. */
104     void operator()(Context /* ctx */) override
105     {
106         std::apply(detail::CallDBusMethod<DBusInterface, MethodArgs...>::op,
107                    std::tuple_cat(std::make_tuple(bus), std::make_tuple(path),
108                                   std::make_tuple(interface),
109                                   std::make_tuple(method), args));
110     }
111 
112   private:
113     std::tuple<MethodArgs...> args;
114 };
115 
116 /** @brief Argument type deduction for constructing Method instances. */
117 template <typename DBusInterface, typename... MethodArgs>
118 auto makeMethod(const std::string& bus, const std::string& path,
119                 const std::string& iface, const std::string& method,
120                 MethodArgs&&... arguments)
121 {
122     return std::make_unique<Method<DBusInterface, MethodArgs...>>(
123         bus, path, iface, method, std::forward<MethodArgs>(arguments)...);
124 }
125 
126 } // namespace monitoring
127 } // namespace dbus
128 } // namespace phosphor
129