xref: /openbmc/phosphor-dbus-monitor/src/sdbusplus.hpp (revision 195550c6071571aa01945cf061efe26d12dba4cc)
1 #pragma once
2 
3 #include <phosphor-logging/log.hpp>
4 #include <sdbusplus/bus.hpp>
5 #include <sdbusplus/exception.hpp>
6 #include <sdbusplus/message.hpp>
7 #include <sdbusplus/bus/match.hpp>
8 #include "data_types.hpp"
9 
10 struct Loop;
11 
12 namespace phosphor
13 {
14 namespace dbus
15 {
16 namespace monitoring
17 {
18 
19 using namespace phosphor::logging;
20 using sdbusplus::exception::SdBusError;
21 
22 /** @class SDBusPlus
23  *  @brief DBus access delegate implementation for sdbusplus.
24  */
25 class SDBusPlus
26 {
27   private:
28     static auto& getWatches()
29     {
30         static std::vector<sdbusplus::bus::match::match> watches;
31         return watches;
32     }
33 
34   public:
35     static auto& getBus()
36     {
37         static auto bus = sdbusplus::bus::new_default();
38         return bus;
39     }
40 
41     /** @brief Invoke a method; ignore reply. */
42     template <typename... Args>
43     static void callMethodNoReply(const std::string& busName,
44                                   const std::string& path,
45                                   const std::string& interface,
46                                   const std::string& method, Args&&... args)
47     {
48         auto reqMsg = getBus().new_method_call(
49             busName.c_str(), path.c_str(), interface.c_str(), 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(const std::string& busName, const std::string& path,
61                            const std::string& interface,
62                            const std::string& method, Args&&... args)
63     {
64         auto reqMsg = getBus().new_method_call(
65             busName.c_str(), path.c_str(), interface.c_str(), method.c_str());
66         reqMsg.append(std::forward<Args>(args)...);
67         return getBus().call(reqMsg);
68     }
69 
70     /** @brief Invoke a method and read the response. */
71     template <typename Ret, typename... Args>
72     static auto callMethodAndRead(const std::string& busName,
73                                   const std::string& path,
74                                   const std::string& interface,
75                                   const std::string& method, Args&&... args)
76     {
77         Ret resp;
78         sdbusplus::message::message respMsg = callMethod<Args...>(
79             busName, path, interface, method, std::forward<Args>(args)...);
80         try
81         {
82             respMsg.read(resp);
83         }
84         catch (const SdBusError& e)
85         {
86             // Empty responses are expected sometimes, and the calling
87             // code is set up to handle it.
88         }
89         return resp;
90     }
91 
92     /** @brief Register a DBus signal callback. */
93     static auto
94         addMatch(const std::string& match,
95                  const sdbusplus::bus::match::match::callback_t& callback)
96     {
97         getWatches().emplace_back(getBus(), match, callback);
98     }
99 
100     /** @brief Look up the bus name for a path and interface */
101     static auto getBusName(const std::string& path,
102                            const std::string& interface)
103     {
104         std::vector<std::string> interfaces{interface};
105 
106         auto object = callMethodAndRead<GetObject>(
107             MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject", path,
108             interfaces);
109 
110         std::string name;
111         if (!object.empty())
112         {
113             name = object.begin()->first;
114         }
115         return name;
116     }
117 
118     friend Loop;
119 };
120 
121 } // namespace monitoring
122 } // namespace dbus
123 } // namespace phosphor
124