xref: /openbmc/phosphor-dbus-monitor/src/sdbusplus.hpp (revision c3dfe6176d17966daeb8a27e55b09f1fbb70fe56)
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(
39             const std::string& busName,
40             const std::string& path,
41             const std::string& interface,
42             const std::string& method,
43             Args&& ... args)
44         {
45             auto reqMsg = getBus().new_method_call(
46                               busName.c_str(),
47                               path.c_str(),
48                               interface.c_str(),
49                               method.c_str());
50             reqMsg.append(std::forward<Args>(args)...);
51             getBus().call_noreply(reqMsg);
52 
53             // TODO: openbmc/openbmc#1719
54             // invoke these methods async, with a callback
55             // handler that checks for errors and logs.
56         }
57 
58         /** @brief Invoke a method. */
59         template <typename ...Args>
60         static auto callMethod(
61             const std::string& busName,
62             const std::string& path,
63             const std::string& interface,
64             const std::string& method,
65             Args&& ... args)
66         {
67             auto reqMsg = getBus().new_method_call(
68                               busName.c_str(),
69                               path.c_str(),
70                               interface.c_str(),
71                               method.c_str());
72             reqMsg.append(std::forward<Args>(args)...);
73             return getBus().call(reqMsg);
74         }
75 
76         /** @brief Invoke a method and read the response. */
77         template <typename Ret, typename ...Args>
78         static auto callMethodAndRead(
79             const std::string& busName,
80             const std::string& path,
81             const std::string& interface,
82             const std::string& method,
83             Args&& ... args)
84         {
85             Ret resp;
86             sdbusplus::message::message respMsg =
87                 callMethod<Args...>(
88                     busName,
89                     path,
90                     interface,
91                     method,
92                     std::forward<Args>(args)...);
93             respMsg.read(resp);
94             return resp;
95         }
96 
97         /** @brief Register a DBus signal callback. */
98         static auto addMatch(
99             const std::string& match,
100             const sdbusplus::bus::match::match::callback_t& callback)
101         {
102             getWatches().emplace_back(
103                     getBus(),
104                     match,
105                     callback);
106         }
107 
108         /** @brief Look up the bus name for a path and interface */
109         static auto getBusName(
110             const std::string& path,
111             const std::string& interface)
112         {
113             std::vector<std::string> interfaces{interface};
114 
115             auto object = callMethodAndRead<GetObject>(
116                     MAPPER_BUSNAME,
117                     MAPPER_PATH,
118                     MAPPER_INTERFACE,
119                     "GetObject",
120                     path,
121                     interfaces);
122 
123             std::string name;
124             if (!object.empty())
125             {
126                 name = object.begin()->first;
127             }
128             return name;
129         }
130 
131         friend Loop;
132 };
133 
134 } // namespace monitoring
135 } // namespace dbus
136 } // namespace phosphor
137