blob: d6b5aa78eccec0f6ec60bfec1739a46612ca9b49 [file] [log] [blame]
Patrick Williams5acb5492016-09-02 15:14:16 -05001#pragma once
2
3#include <memory>
Patrick Williams560e5fd2017-01-12 10:00:17 -06004#include <type_traits>
Patrick Williams5acb5492016-09-02 15:14:16 -05005#include <systemd/sd-bus.h>
6#include <sdbusplus/message/append.hpp>
Patrick Williams4fe85a32016-09-08 15:03:56 -05007#include <sdbusplus/message/read.hpp>
Patrick Williams9db28642017-01-06 15:55:05 -06008#include <sdbusplus/message/native_types.hpp>
Patrick Venture4c3427c2018-04-13 17:09:55 -07009#include <sdbusplus/sdbus.hpp>
10
11extern sdbusplus::SdBusImpl sdbus_impl;
Patrick Williams5acb5492016-09-02 15:14:16 -050012
13namespace sdbusplus
14{
15
Andrew Geissler072da3e2018-01-18 07:21:42 -080016// Forward declare sdbusplus::bus::bus for 'friend'ship.
17namespace bus
18{
19struct bus;
20};
Patrick Williams5acb5492016-09-02 15:14:16 -050021
22namespace message
23{
24
25using msgp_t = sd_bus_message*;
26class message;
27
28namespace details
29{
30
31/** @brief unique_ptr functor to release a msg reference. */
Patrick Venture4c3427c2018-04-13 17:09:55 -070032// TODO(venture): Consider using template <SdBusInterfaceType> for this so that
33// it doesn't require creating a specific instance of it, unless that's ok --
Patrick Williams5acb5492016-09-02 15:14:16 -050034struct MsgDeleter
35{
36 void operator()(msgp_t ptr) const
37 {
38 sd_bus_message_unref(ptr);
39 }
40};
41
42/* @brief Alias 'msg' to a unique_ptr type for auto-release. */
43using msg = std::unique_ptr<sd_bus_message, MsgDeleter>;
44
45} // namespace details
46
47/** @class message
48 * @brief Provides C++ bindings to the sd_bus_message_* class functions.
49 */
Patrick Venture4c3427c2018-04-13 17:09:55 -070050class message
Patrick Williams5acb5492016-09-02 15:14:16 -050051{
Andrew Geissler072da3e2018-01-18 07:21:42 -080052 /* Define all of the basic class operations:
53 * Not allowed:
54 * - Default constructor to avoid nullptrs.
55 * - Copy operations due to internal unique_ptr.
56 * Allowed:
57 * - Move operations.
58 * - Destructor.
59 */
Patrick Venture4c3427c2018-04-13 17:09:55 -070060 public:
Patrick Williams5acb5492016-09-02 15:14:16 -050061 message() = delete;
62 message(const message&) = delete;
63 message& operator=(const message&) = delete;
64 message(message&&) = default;
65 message& operator=(message&&) = default;
66 ~message() = default;
67
Patrick Venture4c3427c2018-04-13 17:09:55 -070068 message(msgp_t m, sdbusplus::SdBusInterface* intf) :
69 _intf(std::move(intf)), _msg(_intf->sd_bus_message_ref(m))
70 {
71 }
72
Patrick Williams5acb5492016-09-02 15:14:16 -050073 /** @brief Conversion constructor for 'msgp_t'.
74 *
Patrick Williams560e5fd2017-01-12 10:00:17 -060075 * Takes increment ref-count of the msg-pointer and release when
76 * destructed.
77 */
Patrick Venture4c3427c2018-04-13 17:09:55 -070078 explicit message(msgp_t m) : message(m, &sdbus_impl)
Andrew Geissler072da3e2018-01-18 07:21:42 -080079 {
80 }
Patrick Williams560e5fd2017-01-12 10:00:17 -060081
Patrick Ventureff095682018-04-13 20:54:32 -070082 message(msgp_t m, sdbusplus::SdBusInterface* intf, std::false_type) :
83 _intf(intf), _msg(m)
84 {
85 }
86
Patrick Williams560e5fd2017-01-12 10:00:17 -060087 /** @brief Constructor for 'msgp_t'.
88 *
Patrick Williams5acb5492016-09-02 15:14:16 -050089 * Takes ownership of the msg-pointer and releases it when done.
90 */
Patrick Venture4c3427c2018-04-13 17:09:55 -070091 message(msgp_t m, std::false_type) : _intf(&sdbus_impl), _msg(m)
Andrew Geissler072da3e2018-01-18 07:21:42 -080092 {
93 }
Patrick Williams5acb5492016-09-02 15:14:16 -050094
95 /** @brief Release ownership of the stored msg-pointer. */
Andrew Geissler072da3e2018-01-18 07:21:42 -080096 msgp_t release()
97 {
98 return _msg.release();
99 }
Patrick Williams5acb5492016-09-02 15:14:16 -0500100
Patrick Williams4fe85a32016-09-08 15:03:56 -0500101 /** @brief Check if message contains a real pointer. (non-nullptr). */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800102 explicit operator bool() const
103 {
104 return bool(_msg);
105 }
Patrick Williams4fe85a32016-09-08 15:03:56 -0500106
Patrick Williams5acb5492016-09-02 15:14:16 -0500107 /** @brief Perform sd_bus_message_append, with automatic type deduction.
108 *
109 * @tparam ...Args - Type of items to append to message.
110 * @param[in] args - Items to append to message.
111 */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800112 template <typename... Args> void append(Args&&... args)
Patrick Williams5acb5492016-09-02 15:14:16 -0500113 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700114 sdbusplus::message::append(_intf, _msg.get(),
115 std::forward<Args>(args)...);
Patrick Williams5acb5492016-09-02 15:14:16 -0500116 }
117
Patrick Williams4fe85a32016-09-08 15:03:56 -0500118 /** @brief Perform sd_bus_message_read, with automatic type deduction.
119 *
120 * @tparam ...Args - Type of items to read from message.
121 * @param[out] args - Items to read from message.
122 */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800123 template <typename... Args> void read(Args&&... args)
Patrick Williams4fe85a32016-09-08 15:03:56 -0500124 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700125 sdbusplus::message::read(_intf, _msg.get(),
126 std::forward<Args>(args)...);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500127 }
128
Adriana Kobylak63122252017-01-26 15:09:00 -0600129 /** @brief Get the dbus bus from the message. */
130 // Forward declare.
131 auto get_bus();
132
Patrick Williams4fe85a32016-09-08 15:03:56 -0500133 /** @brief Get the signature of a message.
134 *
135 * @return A [weak] pointer to the signature of the message.
136 */
137 const char* get_signature()
138 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700139 return _intf->sd_bus_message_get_signature(_msg.get(), true);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500140 }
141
Brad Bishop61f57a42017-05-12 13:27:50 -0400142 /** @brief Get the path of a message.
143 *
144 * @return A [weak] pointer to the path of the message.
145 */
146 const char* get_path()
147 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700148 return _intf->sd_bus_message_get_path(_msg.get());
Brad Bishop61f57a42017-05-12 13:27:50 -0400149 }
150
151 /** @brief Get the interface of a message.
152 *
153 * @return A [weak] pointer to the interface of the message.
154 */
155 const char* get_interface()
156 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700157 return _intf->sd_bus_message_get_interface(_msg.get());
Brad Bishop61f57a42017-05-12 13:27:50 -0400158 }
159
160 /** @brief Get the member of a message.
161 *
162 * @return A [weak] pointer to the member of the message.
163 */
164 const char* get_member()
165 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700166 return _intf->sd_bus_message_get_member(_msg.get());
Brad Bishop61f57a42017-05-12 13:27:50 -0400167 }
168
169 /** @brief Get the destination of a message.
170 *
171 * @return A [weak] pointer to the destination of the message.
172 */
173 const char* get_destination()
174 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700175 return _intf->sd_bus_message_get_destination(_msg.get());
Brad Bishop61f57a42017-05-12 13:27:50 -0400176 }
177
178 /** @brief Get the sender of a message.
179 *
180 * @return A [weak] pointer to the sender of the message.
181 */
182 const char* get_sender()
183 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700184 return _intf->sd_bus_message_get_sender(_msg.get());
Brad Bishop61f57a42017-05-12 13:27:50 -0400185 }
186
Christian Andersen9b970622016-12-15 15:05:44 +0100187 /** @brief Check if message is a method error.
188 *
189 * @return True - if message is a method error.
190 */
191 bool is_method_error()
192 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700193 return _intf->sd_bus_message_is_method_error(_msg.get(), nullptr);
Christian Andersen9b970622016-12-15 15:05:44 +0100194 }
195
James Feist284a0f92018-04-05 15:28:16 -0700196 /** @brief Get the errno from the message.
197 *
198 * @return The errno of the message.
199 */
200 int get_errno()
201 {
202 return sd_bus_message_get_errno(_msg.get());
203 }
204
Adriana Kobylakb6dcf972017-01-04 12:14:04 -0600205 /** @brief Get the transaction cookie of a message.
Andrew Geissler072da3e2018-01-18 07:21:42 -0800206 *
207 * @return The transaction cookie of a message.
208 */
Adriana Kobylakb6dcf972017-01-04 12:14:04 -0600209 auto get_cookie()
210 {
211 uint64_t cookie;
Patrick Venture4c3427c2018-04-13 17:09:55 -0700212 _intf->sd_bus_message_get_cookie(_msg.get(), &cookie);
Adriana Kobylakb6dcf972017-01-04 12:14:04 -0600213 return cookie;
214 }
215
Patrick Williams4fe85a32016-09-08 15:03:56 -0500216 /** @brief Check if message is a method call for an interface/method.
217 *
218 * @param[in] interface - The interface to match.
219 * @param[in] method - The method to match.
220 *
221 * @return True - if message is a method call for interface/method.
222 */
223 bool is_method_call(const char* interface, const char* method)
224 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700225 return _intf->sd_bus_message_is_method_call(_msg.get(), interface,
226 method);
Patrick Williams4fe85a32016-09-08 15:03:56 -0500227 }
228
Patrick Williams20d82462016-10-18 08:01:33 -0500229 /** @brief Check if message is a signal for an interface/member.
230 *
231 * @param[in] interface - The interface to match.
232 * @param[in] member - The member to match.
233 */
234 bool is_signal(const char* interface, const char* member)
235 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700236 return _intf->sd_bus_message_is_signal(_msg.get(), interface, member);
Patrick Williams20d82462016-10-18 08:01:33 -0500237 }
238
Patrick Williams2a47ecd2016-10-16 17:16:58 -0500239 /** @brief Create a 'method_return' type message from an existing message.
240 *
241 * @return method-return message.
242 */
243 message new_method_return()
244 {
245 msgp_t reply = nullptr;
Patrick Venture4c3427c2018-04-13 17:09:55 -0700246 _intf->sd_bus_message_new_method_return(this->get(), &reply);
Patrick Williams2a47ecd2016-10-16 17:16:58 -0500247
Patrick Williams560e5fd2017-01-12 10:00:17 -0600248 return message(reply, std::false_type());
Patrick Williams2a47ecd2016-10-16 17:16:58 -0500249 }
250
Patrick Williams425dc9b2016-10-17 16:50:53 -0500251 /** @brief Perform a 'method-return' response call. */
252 void method_return()
253 {
Patrick Venture4c3427c2018-04-13 17:09:55 -0700254 auto b = _intf->sd_bus_message_get_bus(this->get());
255 _intf->sd_bus_send(b, this->get(), nullptr);
Patrick Williams425dc9b2016-10-17 16:50:53 -0500256 }
257
Patrick Williamscfea00a2016-10-18 11:11:21 -0500258 /** @brief Perform a 'signal-send' call. */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800259 void signal_send()
260 {
261 method_return();
262 }
Patrick Williamscfea00a2016-10-18 11:11:21 -0500263
Patrick Williams5acb5492016-09-02 15:14:16 -0500264 friend struct sdbusplus::bus::bus;
265
Andrew Geissler072da3e2018-01-18 07:21:42 -0800266 /** @brief Get a pointer to the owned 'msgp_t'. */
267 msgp_t get()
268 {
269 return _msg.get();
270 }
James Feist284a0f92018-04-05 15:28:16 -0700271
272 private:
Patrick Venture4c3427c2018-04-13 17:09:55 -0700273 sdbusplus::SdBusInterface* _intf;
Andrew Geissler072da3e2018-01-18 07:21:42 -0800274 details::msg _msg;
Patrick Williams5acb5492016-09-02 15:14:16 -0500275};
276
277} // namespace message
278
279} // namespace sdbusplus