2 * Copyright (c) 2019, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
31 * This file includes definitions for a d-bus object.
34 #ifndef OTBR_DBUS_DBUS_OBJECT_HPP_
35 #define OTBR_DBUS_DBUS_OBJECT_HPP_
40 #include <unordered_map>
42 #include <dbus/dbus.h>
44 #include "common/code_utils.hpp"
45 #include "common/types.hpp"
46 #include "dbus/common/constants.hpp"
47 #include "dbus/common/dbus_message_dump.hpp"
48 #include "dbus/common/dbus_message_helper.hpp"
49 #include "dbus/common/dbus_resources.hpp"
50 #include "dbus/server/dbus_request.hpp"
56 * This class is a base class for implementing a d-bus object.
62 using MethodHandlerType = std::function<void(DBusRequest &)>;
64 using PropertyHandlerType = std::function<otError(DBusMessageIter &)>;
67 * The constructor of a d-bus object.
69 * @param[in] aConnection The dbus-connection the object bounds to.
70 * @param[in] aObjectPath The path of the object.
73 DBusObject(DBusConnection *aConnection, const std::string &aObjectPath);
76 * This method initializes the d-bus object.
78 * This method will register the object to the d-bus library.
80 * @retval OTBR_ERROR_NONE Successfully registered the object.
81 * @retval OTBR_ERROR_DBUS Failed to ragister an object.
84 virtual otbrError Init(void);
87 * This method registers the method handler.
89 * @param[in] aInterfaceName The interface name.
90 * @param[in] aMethodName The method name.
91 * @param[in] aHandler The method handler.
94 void RegisterMethod(const std::string & aInterfaceName,
95 const std::string & aMethodName,
96 const MethodHandlerType &aHandler);
99 * This method registers the get handler for a property.
101 * @param[in] aInterfaceName The interface name.
102 * @param[in] aMethodName The method name.
103 * @param[in] aHandler The method handler.
106 void RegisterGetPropertyHandler(const std::string & aInterfaceName,
107 const std::string & aMethodName,
108 const PropertyHandlerType &aHandler);
111 * This method registers the set handler for a property.
113 * @param[in] aInterfaceName The interface name.
114 * @param[in] aMethodName The method name.
115 * @param[in] aHandler The method handler.
118 void RegisterSetPropertyHandler(const std::string & aInterfaceName,
119 const std::string & aPropertyName,
120 const PropertyHandlerType &aHandler);
123 * This method sends a signal.
125 * @param[in] aInterfaceName The interface name.
126 * @param[in] aSignalName The signal name.
127 * @param[in] aArgs The tuple to be encoded into the signal.
129 * @retval OTBR_ERROR_NONE Signal successfully sent.
130 * @retval OTBR_ERROR_DBUS Failed to send the signal.
133 template <typename... FieldTypes>
134 otbrError Signal(const std::string & aInterfaceName,
135 const std::string & aSignalName,
136 const std::tuple<FieldTypes...> &aArgs)
138 UniqueDBusMessage signalMsg{
139 dbus_message_new_signal(mObjectPath.c_str(), aInterfaceName.c_str(), aSignalName.c_str())};
140 otbrError error = OTBR_ERROR_NONE;
142 VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS);
143 VerifyOrExit(error = otbr::DBus::TupleToDBusMessage(*signalMsg, aArgs));
145 VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS);
152 * This method sends a property changed signal.
154 * @param[in] aInterfaceName The interface name.
155 * @param[in] aPropertyName The property name.
156 * @param[in] aValue New value of the property.
158 * @retval OTBR_ERROR_NONE Signal successfully sent.
159 * @retval OTBR_ERROR_DBUS Failed to send the signal.
162 template <typename ValueType>
163 otbrError SignalPropertyChanged(const std::string &aInterfaceName,
164 const std::string &aPropertyName,
165 const ValueType & aValue)
167 UniqueDBusMessage signalMsg{
168 dbus_message_new_signal(mObjectPath.c_str(), DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL)};
169 DBusMessageIter iter, subIter, dictEntryIter;
170 otbrError error = OTBR_ERROR_NONE;
172 VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS);
173 dbus_message_iter_init_append(signalMsg.get(), &iter);
176 VerifyOrExit(DBusMessageEncode(&iter, aInterfaceName) == OTBR_ERROR_NONE, error = OTBR_ERROR_DBUS);
178 // changed_properties
179 VerifyOrExit(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
180 "{" DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING "}",
182 error = OTBR_ERROR_DBUS);
183 VerifyOrExit(dbus_message_iter_open_container(&subIter, DBUS_TYPE_DICT_ENTRY, nullptr, &dictEntryIter),
184 error = OTBR_ERROR_DBUS);
186 SuccessOrExit(error = DBusMessageEncode(&dictEntryIter, aPropertyName));
187 SuccessOrExit(error = DBusMessageEncodeToVariant(&dictEntryIter, aValue));
189 VerifyOrExit(dbus_message_iter_close_container(&subIter, &dictEntryIter), error = OTBR_ERROR_DBUS);
190 VerifyOrExit(dbus_message_iter_close_container(&iter, &subIter), error = OTBR_ERROR_DBUS);
192 // invalidated_properties
193 SuccessOrExit(error = DBusMessageEncode(&iter, std::vector<std::string>()));
195 if (otbrLogGetLevel() >= OTBR_LOG_DEBUG)
197 otbrLog(OTBR_LOG_DEBUG, "Signal %s.%s", aInterfaceName.c_str(), aPropertyName.c_str());
198 DumpDBusMessage(*signalMsg);
201 VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS);
208 * The destructor of a d-bus object.
211 virtual ~DBusObject(void);
214 void GetAllPropertiesMethodHandler(DBusRequest &aRequest);
216 void GetPropertyMethodHandler(DBusRequest &aRequest);
218 void SetPropertyMethodHandler(DBusRequest &aRequest);
220 static DBusHandlerResult sMessageHandler(DBusConnection *aConnection, DBusMessage *aMessage, void *aData);
221 DBusHandlerResult MessageHandler(DBusConnection *aConnection, DBusMessage *aMessage);
223 std::unordered_map<std::string, MethodHandlerType> mMethodHandlers;
224 std::unordered_map<std::string, std::unordered_map<std::string, PropertyHandlerType>> mGetPropertyHandlers;
225 std::unordered_map<std::string, PropertyHandlerType> mSetPropertyHandlers;
226 DBusConnection * mConnection;
227 std::string mObjectPath;
233 #endif // OTBR_DBUS_DBUS_SERVER_HPP_