1 #pragma once
2 
3 #include <sdbusplus/bus.hpp>
4 #include <sdbusplus/message.hpp>
5 #include <sdbusplus/bus/match.hpp>
6 #include "data_types.hpp"
7 
8 struct Loop;
9 
10 namespace phosphor
11 {
12 namespace dbus
13 {
14 namespace monitoring
15 {
16 
17 /** @class SDBusPlus
18  *  @brief DBus access delegate implementation for sdbusplus.
19  */
20 class SDBusPlus
21 {
22   private:
23     static auto& getWatches()
24     {
25         static std::vector<sdbusplus::bus::match::match> watches;
26         return watches;
27     }
28 
29   public:
30     static auto& getBus()
31     {
32         static auto bus = sdbusplus::bus::new_default();
33         return bus;
34     }
35 
36     /** @brief Invoke a method; ignore reply. */
37     template <typename... Args>
38     static void callMethodNoReply(const std::string& busName,
39                                   const std::string& path,
40                                   const std::string& interface,
41                                   const std::string& method, Args&&... args)
42     {
43         auto reqMsg = getBus().new_method_call(
44             busName.c_str(), path.c_str(), interface.c_str(), method.c_str());
45         reqMsg.append(std::forward<Args>(args)...);
46         getBus().call_noreply(reqMsg);
47 
48         // TODO: openbmc/openbmc#1719
49         // invoke these methods async, with a callback
50         // handler that checks for errors and logs.
51     }
52 
53     /** @brief Invoke a method. */
54     template <typename... Args>
55     static auto callMethod(const std::string& busName, const std::string& path,
56                            const std::string& interface,
57                            const std::string& method, Args&&... args)
58     {
59         auto reqMsg = getBus().new_method_call(
60             busName.c_str(), path.c_str(), interface.c_str(), method.c_str());
61         reqMsg.append(std::forward<Args>(args)...);
62         return getBus().call(reqMsg);
63     }
64 
65     /** @brief Invoke a method and read the response. */
66     template <typename Ret, typename... Args>
67     static auto callMethodAndRead(const std::string& busName,
68                                   const std::string& path,
69                                   const std::string& interface,
70                                   const std::string& method, Args&&... args)
71     {
72         Ret resp;
73         sdbusplus::message::message respMsg = callMethod<Args...>(
74             busName, path, interface, method, std::forward<Args>(args)...);
75         respMsg.read(resp);
76         return resp;
77     }
78 
79     /** @brief Register a DBus signal callback. */
80     static auto
81         addMatch(const std::string& match,
82                  const sdbusplus::bus::match::match::callback_t& callback)
83     {
84         getWatches().emplace_back(getBus(), match, callback);
85     }
86 
87     /** @brief Look up the bus name for a path and interface */
88     static auto getBusName(const std::string& path,
89                            const std::string& interface)
90     {
91         std::vector<std::string> interfaces{interface};
92 
93         auto object = callMethodAndRead<GetObject>(
94             MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject", path,
95             interfaces);
96 
97         std::string name;
98         if (!object.empty())
99         {
100             name = object.begin()->first;
101         }
102         return name;
103     }
104 
105     friend Loop;
106 };
107 
108 } // namespace monitoring
109 } // namespace dbus
110 } // namespace phosphor
111