xref: /aosp_15_r20/external/ot-br-posix/src/dbus/server/dbus_object.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2019, The OpenThread Authors.
3  *    All rights reserved.
4  *
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.
15  *
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.
27  */
28 
29 /**
30  * @file
31  * This file includes definitions for a d-bus object.
32  */
33 
34 #ifndef OTBR_DBUS_DBUS_OBJECT_HPP_
35 #define OTBR_DBUS_DBUS_OBJECT_HPP_
36 
37 #include "openthread-br/config.h"
38 
39 #ifndef OTBR_LOG_TAG
40 #define OTBR_LOG_TAG "DBUS"
41 #endif
42 
43 #include <functional>
44 #include <memory>
45 #include <string>
46 #include <unordered_map>
47 
48 #include <dbus/dbus.h>
49 
50 #include "common/code_utils.hpp"
51 #include "common/types.hpp"
52 #include "dbus/common/constants.hpp"
53 #include "dbus/common/dbus_message_dump.hpp"
54 #include "dbus/common/dbus_message_helper.hpp"
55 #include "dbus/common/dbus_resources.hpp"
56 #include "dbus/server/dbus_request.hpp"
57 
58 namespace otbr {
59 namespace DBus {
60 
61 /**
62  * This class is a base class for implementing a d-bus object.
63  */
64 class DBusObject : private NonCopyable
65 {
66 public:
67     using MethodHandlerType        = std::function<void(DBusRequest &)>;
68     using AsyncPropertyHandlerType = std::function<void(DBusRequest &)>;
69     using PropertyHandlerType      = std::function<otError(DBusMessageIter &)>;
70 
71     /**
72      * The constructor of a d-bus object.
73      *
74      * @param[in] aConnection  The dbus-connection the object bounds to.
75      * @param[in] aObjectPath  The path of the object.
76      */
77     DBusObject(DBusConnection *aConnection, const std::string &aObjectPath);
78 
79     /**
80      * This method initializes the d-bus object.
81      *
82      * This method will register the object to the d-bus library.
83      *
84      * @retval OTBR_ERROR_NONE  Successfully registered the object.
85      * @retval OTBR_ERROR_DBUS  Failed to ragister an object.
86      */
87     virtual otbrError Init(void);
88 
89     /**
90      * This method registers the method handler.
91      *
92      * @param[in] aInterfaceName  The interface name.
93      * @param[in] aMethodName     The method name.
94      * @param[in] aHandler        The method handler.
95      */
96     void RegisterMethod(const std::string       &aInterfaceName,
97                         const std::string       &aMethodName,
98                         const MethodHandlerType &aHandler);
99 
100     /**
101      * This method registers the get handler for a property.
102      *
103      * @param[in] aInterfaceName  The interface name.
104      * @param[in] aPropertyName   The property name.
105      * @param[in] aHandler        The method handler.
106      */
107     virtual void RegisterGetPropertyHandler(const std::string         &aInterfaceName,
108                                             const std::string         &aPropertyName,
109                                             const PropertyHandlerType &aHandler);
110 
111     /**
112      * This method registers the set handler for a property.
113      *
114      * @param[in] aInterfaceName  The interface name.
115      * @param[in] aPropertyName   The property name.
116      * @param[in] aHandler        The method handler.
117      */
118     virtual void RegisterSetPropertyHandler(const std::string         &aInterfaceName,
119                                             const std::string         &aPropertyName,
120                                             const PropertyHandlerType &aHandler);
121 
122     /**
123      * This method registers the async get handler for a property.
124      *
125      * @param[in] aInterfaceName  The interface name.
126      * @param[in] aPropertyName   The property name.
127      * @param[in] aHandler        The method handler.
128      */
129     virtual void RegisterAsyncGetPropertyHandler(const std::string              &aInterfaceName,
130                                                  const std::string              &aPropertyName,
131                                                  const AsyncPropertyHandlerType &aHandler);
132 
133     /**
134      * This method sends a signal.
135      *
136      * @param[in] aInterfaceName  The interface name.
137      * @param[in] aSignalName     The signal name.
138      * @param[in] aArgs           The tuple to be encoded into the signal.
139      *
140      * @retval OTBR_ERROR_NONE  Signal successfully sent.
141      * @retval OTBR_ERROR_DBUS  Failed to send the signal.
142      */
143     template <typename... FieldTypes>
Signal(const std::string & aInterfaceName,const std::string & aSignalName,const std::tuple<FieldTypes...> & aArgs)144     otbrError Signal(const std::string               &aInterfaceName,
145                      const std::string               &aSignalName,
146                      const std::tuple<FieldTypes...> &aArgs)
147     {
148         UniqueDBusMessage signalMsg = NewSignalMessage(aInterfaceName, aSignalName);
149         otbrError         error     = OTBR_ERROR_NONE;
150 
151         VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS);
152         SuccessOrExit(error = otbr::DBus::TupleToDBusMessage(*signalMsg, aArgs));
153 
154         VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS);
155 
156     exit:
157         return error;
158     }
159 
160     /**
161      * This method sends a property changed signal.
162      *
163      * @param[in] aInterfaceName  The interface name.
164      * @param[in] aPropertyName   The property name.
165      * @param[in] aValue          New value of the property.
166      *
167      * @retval OTBR_ERROR_NONE  Signal successfully sent.
168      * @retval OTBR_ERROR_DBUS  Failed to send the signal.
169      */
170     template <typename ValueType>
SignalPropertyChanged(const std::string & aInterfaceName,const std::string & aPropertyName,const ValueType & aValue)171     otbrError SignalPropertyChanged(const std::string &aInterfaceName,
172                                     const std::string &aPropertyName,
173                                     const ValueType   &aValue)
174     {
175         UniqueDBusMessage signalMsg = NewSignalMessage(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL);
176         DBusMessageIter   iter, subIter, dictEntryIter;
177         otbrError         error = OTBR_ERROR_NONE;
178 
179         VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS);
180         dbus_message_iter_init_append(signalMsg.get(), &iter);
181 
182         // interface_name
183         VerifyOrExit(DBusMessageEncode(&iter, aInterfaceName) == OTBR_ERROR_NONE, error = OTBR_ERROR_DBUS);
184 
185         // changed_properties
186         VerifyOrExit(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
187                                                       "{" DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING "}",
188                                                       &subIter),
189                      error = OTBR_ERROR_DBUS);
190         VerifyOrExit(dbus_message_iter_open_container(&subIter, DBUS_TYPE_DICT_ENTRY, nullptr, &dictEntryIter),
191                      error = OTBR_ERROR_DBUS);
192 
193         SuccessOrExit(error = DBusMessageEncode(&dictEntryIter, aPropertyName));
194         SuccessOrExit(error = DBusMessageEncodeToVariant(&dictEntryIter, aValue));
195 
196         VerifyOrExit(dbus_message_iter_close_container(&subIter, &dictEntryIter), error = OTBR_ERROR_DBUS);
197         VerifyOrExit(dbus_message_iter_close_container(&iter, &subIter), error = OTBR_ERROR_DBUS);
198 
199         // invalidated_properties
200         SuccessOrExit(error = DBusMessageEncode(&iter, std::vector<std::string>()));
201 
202         if (otbrLogGetLevel() >= OTBR_LOG_DEBUG)
203         {
204             otbrLogDebug("Signal %s.%s", aInterfaceName.c_str(), aPropertyName.c_str());
205             DumpDBusMessage(*signalMsg);
206         }
207 
208         VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS);
209 
210     exit:
211         return error;
212     }
213 
214     /**
215      * The destructor of a d-bus object.
216      */
217     virtual ~DBusObject(void);
218 
219     /**
220      * Sends all outgoing messages, blocks until the message queue is empty.
221      */
222     void Flush(void);
223 
224 protected:
225     otbrError Initialize(bool aIsAsyncPropertyHandler);
226 
227 private:
228     void GetAllPropertiesMethodHandler(DBusRequest &aRequest);
229     void GetPropertyMethodHandler(DBusRequest &aRequest);
230     void SetPropertyMethodHandler(DBusRequest &aRequest);
231     void AsyncGetPropertyMethodHandler(DBusRequest &aRequest);
232 
233     static DBusHandlerResult sMessageHandler(DBusConnection *aConnection, DBusMessage *aMessage, void *aData);
234     DBusHandlerResult        MessageHandler(DBusConnection *aConnection, DBusMessage *aMessage);
235 
236     UniqueDBusMessage NewSignalMessage(const std::string &aInterfaceName, const std::string &aSignalName);
237 
238     std::unordered_map<std::string, MethodHandlerType>                                    mMethodHandlers;
239     std::unordered_map<std::string, std::unordered_map<std::string, PropertyHandlerType>> mGetPropertyHandlers;
240     std::unordered_map<std::string, std::unordered_map<std::string, AsyncPropertyHandlerType>>
241                                                          mAsyncGetPropertyHandlers;
242     std::unordered_map<std::string, PropertyHandlerType> mSetPropertyHandlers;
243     DBusConnection                                      *mConnection;
244     std::string                                          mObjectPath;
245 };
246 
247 } // namespace DBus
248 } // namespace otbr
249 
250 #endif // OTBR_DBUS_DBUS_SERVER_HPP_
251