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