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