• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef OTBR_LOG_TAG
38 #define OTBR_LOG_TAG "DBUS"
39 #endif
40 
41 #include <functional>
42 #include <memory>
43 #include <string>
44 #include <unordered_map>
45 
46 #include <dbus/dbus.h>
47 
48 #include "common/code_utils.hpp"
49 #include "common/types.hpp"
50 #include "dbus/common/constants.hpp"
51 #include "dbus/common/dbus_message_dump.hpp"
52 #include "dbus/common/dbus_message_helper.hpp"
53 #include "dbus/common/dbus_resources.hpp"
54 #include "dbus/server/dbus_request.hpp"
55 
56 namespace otbr {
57 namespace DBus {
58 
59 /**
60  * This class is a base class for implementing a d-bus object.
61  *
62  */
63 class DBusObject : private NonCopyable
64 {
65 public:
66     using MethodHandlerType = std::function<void(DBusRequest &)>;
67 
68     using PropertyHandlerType = std::function<otError(DBusMessageIter &)>;
69 
70     /**
71      * The constructor of a d-bus object.
72      *
73      * @param[in] aConnection  The dbus-connection the object bounds to.
74      * @param[in] aObjectPath  The path of the object.
75      *
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      */
88     virtual otbrError Init(void);
89 
90     /**
91      * This method registers the method handler.
92      *
93      * @param[in] aInterfaceName  The interface name.
94      * @param[in] aMethodName     The method name.
95      * @param[in] aHandler        The method handler.
96      *
97      */
98     void RegisterMethod(const std::string &      aInterfaceName,
99                         const std::string &      aMethodName,
100                         const MethodHandlerType &aHandler);
101 
102     /**
103      * This method registers the get handler for a property.
104      *
105      * @param[in] aInterfaceName  The interface name.
106      * @param[in] aPropertyName   The property name.
107      * @param[in] aHandler        The method handler.
108      *
109      */
110     virtual void RegisterGetPropertyHandler(const std::string &        aInterfaceName,
111                                             const std::string &        aPropertyName,
112                                             const PropertyHandlerType &aHandler);
113 
114     /**
115      * This method registers the set handler for a property.
116      *
117      * @param[in] aInterfaceName  The interface name.
118      * @param[in] aPropertyName   The property name.
119      * @param[in] aHandler        The method handler.
120      *
121      */
122     virtual void RegisterSetPropertyHandler(const std::string &        aInterfaceName,
123                                             const std::string &        aPropertyName,
124                                             const PropertyHandlerType &aHandler);
125 
126     /**
127      * This method sends a signal.
128      *
129      * @param[in] aInterfaceName  The interface name.
130      * @param[in] aSignalName     The signal name.
131      * @param[in] aArgs           The tuple to be encoded into the signal.
132      *
133      * @retval OTBR_ERROR_NONE  Signal successfully sent.
134      * @retval OTBR_ERROR_DBUS  Failed to send the signal.
135      *
136      */
137     template <typename... FieldTypes>
Signal(const std::string & aInterfaceName,const std::string & aSignalName,const std::tuple<FieldTypes...> & aArgs)138     otbrError Signal(const std::string &              aInterfaceName,
139                      const std::string &              aSignalName,
140                      const std::tuple<FieldTypes...> &aArgs)
141     {
142         UniqueDBusMessage signalMsg = NewSignalMessage(aInterfaceName, aSignalName);
143         otbrError         error     = OTBR_ERROR_NONE;
144 
145         VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS);
146         SuccessOrExit(error = otbr::DBus::TupleToDBusMessage(*signalMsg, aArgs));
147 
148         VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS);
149 
150     exit:
151         return error;
152     }
153 
154     /**
155      * This method sends a property changed signal.
156      *
157      * @param[in] aInterfaceName  The interface name.
158      * @param[in] aPropertyName   The property name.
159      * @param[in] aValue          New value of the property.
160      *
161      * @retval OTBR_ERROR_NONE  Signal successfully sent.
162      * @retval OTBR_ERROR_DBUS  Failed to send the signal.
163      *
164      */
165     template <typename ValueType>
SignalPropertyChanged(const std::string & aInterfaceName,const std::string & aPropertyName,const ValueType & aValue)166     otbrError SignalPropertyChanged(const std::string &aInterfaceName,
167                                     const std::string &aPropertyName,
168                                     const ValueType &  aValue)
169     {
170         UniqueDBusMessage signalMsg = NewSignalMessage(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL);
171         DBusMessageIter   iter, subIter, dictEntryIter;
172         otbrError         error = OTBR_ERROR_NONE;
173 
174         VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS);
175         dbus_message_iter_init_append(signalMsg.get(), &iter);
176 
177         // interface_name
178         VerifyOrExit(DBusMessageEncode(&iter, aInterfaceName) == OTBR_ERROR_NONE, error = OTBR_ERROR_DBUS);
179 
180         // changed_properties
181         VerifyOrExit(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
182                                                       "{" DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING "}",
183                                                       &subIter),
184                      error = OTBR_ERROR_DBUS);
185         VerifyOrExit(dbus_message_iter_open_container(&subIter, DBUS_TYPE_DICT_ENTRY, nullptr, &dictEntryIter),
186                      error = OTBR_ERROR_DBUS);
187 
188         SuccessOrExit(error = DBusMessageEncode(&dictEntryIter, aPropertyName));
189         SuccessOrExit(error = DBusMessageEncodeToVariant(&dictEntryIter, aValue));
190 
191         VerifyOrExit(dbus_message_iter_close_container(&subIter, &dictEntryIter), error = OTBR_ERROR_DBUS);
192         VerifyOrExit(dbus_message_iter_close_container(&iter, &subIter), error = OTBR_ERROR_DBUS);
193 
194         // invalidated_properties
195         SuccessOrExit(error = DBusMessageEncode(&iter, std::vector<std::string>()));
196 
197         if (otbrLogGetLevel() >= OTBR_LOG_DEBUG)
198         {
199             otbrLogDebug("Signal %s.%s", aInterfaceName.c_str(), aPropertyName.c_str());
200             DumpDBusMessage(*signalMsg);
201         }
202 
203         VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS);
204 
205     exit:
206         return error;
207     }
208 
209     /**
210      * The destructor of a d-bus object.
211      *
212      */
213     virtual ~DBusObject(void);
214 
215 private:
216     void GetAllPropertiesMethodHandler(DBusRequest &aRequest);
217     void GetPropertyMethodHandler(DBusRequest &aRequest);
218     void SetPropertyMethodHandler(DBusRequest &aRequest);
219 
220     static DBusHandlerResult sMessageHandler(DBusConnection *aConnection, DBusMessage *aMessage, void *aData);
221     DBusHandlerResult        MessageHandler(DBusConnection *aConnection, DBusMessage *aMessage);
222 
223     UniqueDBusMessage NewSignalMessage(const std::string &aInterfaceName, const std::string &aSignalName);
224 
225     std::unordered_map<std::string, MethodHandlerType>                                    mMethodHandlers;
226     std::unordered_map<std::string, std::unordered_map<std::string, PropertyHandlerType>> mGetPropertyHandlers;
227     std::unordered_map<std::string, PropertyHandlerType>                                  mSetPropertyHandlers;
228     DBusConnection *                                                                      mConnection;
229     std::string                                                                           mObjectPath;
230 };
231 
232 } // namespace DBus
233 } // namespace otbr
234 
235 #endif // OTBR_DBUS_DBUS_SERVER_HPP_
236