xref: /openbmc/phosphor-dbus-monitor/mslverify/util.hpp (revision 78199b44b1438295b79f562e9d240034c05e4171)
1 #pragma once
2 
3 #include <sdbusplus/bus.hpp>
4 #include <sdbusplus/message.hpp>
5 #include <phosphor-logging/log.hpp>
6 #include <phosphor-logging/elog.hpp>
7 #include <phosphor-logging/elog-errors.hpp>
8 #include <xyz/openbmc_project/Common/error.hpp>
9 
10 namespace util
11 {
12 namespace detail
13 {
14 namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
15 } // namespace detail
16 
17 /** @brief Alias for PropertiesChanged signal callbacks. */
18 template <typename ...T>
19 using Properties = std::map<std::string, sdbusplus::message::variant<T...>>;
20 
21 namespace sdbusplus
22 {
23 
24 /** @brief Get the bus connection. */
25 static auto& getBus() __attribute__((pure));
26 static auto& getBus()
27 {
28     static auto bus = ::sdbusplus::bus::new_default();
29     return bus;
30 }
31 
32 /** @brief Invoke a method. */
33 template <typename ...Args>
34 static auto callMethod(
35         ::sdbusplus::bus::bus& bus,
36         const std::string& busName,
37         const std::string& path,
38         const std::string& interface,
39         const std::string& method,
40         Args&& ... args)
41 {
42     auto reqMsg = bus.new_method_call(
43             busName.c_str(),
44             path.c_str(),
45             interface.c_str(),
46             method.c_str());
47     reqMsg.append(std::forward<Args>(args)...);
48     auto respMsg = bus.call(reqMsg);
49 
50     if (respMsg.is_method_error())
51     {
52         phosphor::logging::log<phosphor::logging::level::INFO>(
53                 "Failed to invoke DBus method.",
54                 phosphor::logging::entry("PATH=%s", path.c_str()),
55                 phosphor::logging::entry(
56                     "INTERFACE=%s", interface.c_str()),
57                 phosphor::logging::entry("METHOD=%s", method.c_str()));
58         phosphor::logging::elog<detail::errors::InternalFailure>();
59     }
60 
61     return respMsg;
62 }
63 
64 /** @brief Invoke a method. */
65 template <typename ...Args>
66 static auto callMethod(
67         const std::string& busName,
68         const std::string& path,
69         const std::string& interface,
70         const std::string& method,
71         Args&& ... args)
72 {
73     return callMethod(
74             getBus(),
75             busName,
76             path,
77             interface,
78             method,
79             std::forward<Args>(args)...);
80 }
81 
82 /** @brief Invoke a method and read the response. */
83 template <typename Ret, typename ...Args>
84 static auto callMethodAndRead(
85         ::sdbusplus::bus::bus& bus,
86         const std::string& busName,
87         const std::string& path,
88         const std::string& interface,
89         const std::string& method,
90         Args&& ... args)
91 {
92     ::sdbusplus::message::message respMsg =
93         callMethod<Args...>(
94                 bus,
95                 busName,
96                 path,
97                 interface,
98                 method,
99                 std::forward<Args>(args)...);
100     Ret resp;
101     respMsg.read(resp);
102     return resp;
103 }
104 
105 /** @brief Invoke a method and read the response. */
106  template <typename Ret, typename ...Args>
107 static auto callMethodAndRead(
108         const std::string& busName,
109         const std::string& path,
110         const std::string& interface,
111         const std::string& method,
112         Args&& ... args)
113 {
114     return callMethodAndRead<Ret>(
115             getBus(),
116             busName,
117             path,
118             interface,
119             method,
120             std::forward<Args>(args)...);
121 }
122 
123 
124 /** @brief Get service from the mapper. */
125 static auto getService(
126         ::sdbusplus::bus::bus& bus,
127         const std::string& path,
128         const std::string& interface)
129 {
130     using namespace std::literals::string_literals;
131     using GetObject = std::map<std::string, std::vector<std::string>>;
132 
133     auto mapperResp = callMethodAndRead<GetObject>(
134             bus,
135             "xyz.openbmc_project.ObjectMapper"s,
136             "/xyz/openbmc_project/object_mapper"s,
137             "xyz.openbmc_project.ObjectMapper"s,
138             "GetObject"s,
139             path,
140             GetObject::mapped_type{interface});
141 
142     if (mapperResp.empty())
143     {
144         phosphor::logging::log<phosphor::logging::level::INFO>(
145                 "Object not found.",
146                 phosphor::logging::entry("PATH=%s", path.c_str()),
147                 phosphor::logging::entry(
148                     "INTERFACE=%s", interface.c_str()));
149         phosphor::logging::elog<detail::errors::InternalFailure>();
150     }
151     return mapperResp.begin()->first;
152 }
153 
154 /** @brief Get a property without mapper lookup. */
155 template <typename Property>
156 static auto getProperty(
157         ::sdbusplus::bus::bus& bus,
158         const std::string& busName,
159         const std::string& path,
160         const std::string& interface,
161         const std::string& property)
162 {
163     using namespace std::literals::string_literals;
164 
165     auto msg = callMethod(
166             bus,
167             busName,
168             path,
169             "org.freedesktop.DBus.Properties"s,
170             "Get"s,
171             interface,
172             property);
173     ::sdbusplus::message::variant<Property> value;
174     msg.read(value);
175     return value.template get<Property>();
176 }
177 
178 /** @brief Get a property without mapper lookup. */
179 template <typename Property>
180 static auto getProperty(
181         const std::string& busName,
182         const std::string& path,
183         const std::string& interface,
184         const std::string& property)
185 {
186     return getProperty<Property>(
187             getBus(),
188             busName,
189             path,
190             interface,
191             property);
192 }
193 
194 /** @brief Get a property with mapper lookup. */
195 template <typename Property>
196 static auto getProperty(
197         ::sdbusplus::bus::bus& bus,
198         const std::string& path,
199         const std::string& interface,
200         const std::string& property)
201 {
202     return getProperty<Property>(
203             bus,
204             getService(bus, path, interface),
205             path,
206             interface,
207             property);
208 }
209 
210 /** @brief Get a property with mapper lookup. */
211 template <typename Property>
212 static auto getProperty(
213         const std::string& path,
214         const std::string& interface,
215         const std::string& property)
216 {
217     return getProperty<Property>(
218             getBus(),
219             path,
220             interface,
221             property);
222 }
223 
224 } // namespace sdbusplus
225 } // namespace util
226