Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / src / dbus / server / dbus_object.cpp
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 #include <assert.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <dbus/dbus.h>
34
35 #include "common/logging.hpp"
36 #include "dbus/common/dbus_message_dump.hpp"
37 #include "dbus/server/dbus_object.hpp"
38
39 using std::placeholders::_1;
40
41 namespace otbr {
42 namespace DBus {
43
44 DBusObject::DBusObject(DBusConnection *aConnection, const std::string &aObjectPath)
45     : mConnection(aConnection)
46     , mObjectPath(aObjectPath)
47 {
48 }
49
50 otbrError DBusObject::Init(void)
51 {
52     otbrError            error = OTBR_ERROR_NONE;
53     DBusObjectPathVTable vTable;
54
55     memset(&vTable, 0, sizeof(vTable));
56
57     vTable.message_function = DBusObject::sMessageHandler;
58
59     VerifyOrExit(dbus_connection_register_object_path(mConnection, mObjectPath.c_str(), &vTable, this),
60                  error = OTBR_ERROR_DBUS);
61     RegisterMethod(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_GET_METHOD,
62                    std::bind(&DBusObject::GetPropertyMethodHandler, this, _1));
63     RegisterMethod(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_SET_METHOD,
64                    std::bind(&DBusObject::SetPropertyMethodHandler, this, _1));
65     RegisterMethod(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTY_GET_ALL_METHOD,
66                    std::bind(&DBusObject::GetAllPropertiesMethodHandler, this, _1));
67
68 exit:
69     return error;
70 }
71
72 void DBusObject::RegisterMethod(const std::string &      aInterfaceName,
73                                 const std::string &      aMethodName,
74                                 const MethodHandlerType &aHandler)
75 {
76     std::string fullPath = aInterfaceName + "." + aMethodName;
77
78     assert(mMethodHandlers.find(fullPath) == mMethodHandlers.end());
79     mMethodHandlers.emplace(fullPath, aHandler);
80 }
81
82 void DBusObject::RegisterGetPropertyHandler(const std::string &        aInterfaceName,
83                                             const std::string &        aPropertyName,
84                                             const PropertyHandlerType &aHandler)
85 {
86     mGetPropertyHandlers[aInterfaceName].emplace(aPropertyName, aHandler);
87 }
88
89 void DBusObject::RegisterSetPropertyHandler(const std::string &        aInterfaceName,
90                                             const std::string &        aPropertyName,
91                                             const PropertyHandlerType &aHandler)
92 {
93     std::string fullPath = aInterfaceName + "." + aPropertyName;
94
95     assert(mSetPropertyHandlers.find(fullPath) == mSetPropertyHandlers.end());
96     mSetPropertyHandlers.emplace(fullPath, aHandler);
97 }
98
99 DBusHandlerResult DBusObject::sMessageHandler(DBusConnection *aConnection, DBusMessage *aMessage, void *aData)
100 {
101     DBusObject *server = reinterpret_cast<DBusObject *>(aData);
102
103     return server->MessageHandler(aConnection, aMessage);
104 }
105
106 DBusHandlerResult DBusObject::MessageHandler(DBusConnection *aConnection, DBusMessage *aMessage)
107 {
108     DBusHandlerResult handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
109     DBusRequest       request(aConnection, aMessage);
110     std::string       interface  = dbus_message_get_interface(aMessage);
111     std::string       memberName = interface + "." + dbus_message_get_member(aMessage);
112     auto              iter       = mMethodHandlers.find(memberName);
113
114     if (dbus_message_get_type(aMessage) == DBUS_MESSAGE_TYPE_METHOD_CALL && iter != mMethodHandlers.end())
115     {
116         otbrLog(OTBR_LOG_INFO, "Handling method %s", memberName.c_str());
117         if (otbrLogGetLevel() >= OTBR_LOG_DEBUG)
118         {
119             DumpDBusMessage(*aMessage);
120         }
121         (iter->second)(request);
122         handled = DBUS_HANDLER_RESULT_HANDLED;
123     }
124
125     return handled;
126 }
127
128 void DBusObject::GetPropertyMethodHandler(DBusRequest &aRequest)
129 {
130     UniqueDBusMessage reply{dbus_message_new_method_return(aRequest.GetMessage())};
131
132     DBusMessageIter iter;
133     std::string     interfaceName;
134     std::string     propertyName;
135     otError         error = OT_ERROR_NONE;
136
137     VerifyOrExit(reply != nullptr, error = OT_ERROR_NO_BUFS);
138     VerifyOrExit(dbus_message_iter_init(aRequest.GetMessage(), &iter), error = OT_ERROR_FAILED);
139     VerifyOrExit(DBusMessageExtract(&iter, interfaceName) == OTBR_ERROR_NONE, error = OT_ERROR_PARSE);
140     VerifyOrExit(DBusMessageExtract(&iter, propertyName) == OTBR_ERROR_NONE, error = OT_ERROR_PARSE);
141     {
142         auto propertyIter = mGetPropertyHandlers.find(interfaceName);
143
144         otbrLog(OTBR_LOG_INFO, "GetProperty %s.%s", interfaceName.c_str(), propertyName.c_str());
145         VerifyOrExit(propertyIter != mGetPropertyHandlers.end(), error = OT_ERROR_NOT_FOUND);
146         {
147             DBusMessageIter replyIter;
148             auto &          interfaceHandlers = propertyIter->second;
149             auto            interfaceIter     = interfaceHandlers.find(propertyName);
150
151             VerifyOrExit(interfaceIter != interfaceHandlers.end(), error = OT_ERROR_NOT_FOUND);
152             dbus_message_iter_init_append(reply.get(), &replyIter);
153             SuccessOrExit(error = interfaceIter->second(replyIter));
154         }
155     }
156 exit:
157     if (error == OT_ERROR_NONE)
158     {
159         if (otbrLogGetLevel() >= OTBR_LOG_DEBUG)
160         {
161             otbrLog(OTBR_LOG_DEBUG, "GetProperty %s.%s reply:", interfaceName.c_str(), propertyName.c_str());
162             DumpDBusMessage(*reply);
163         }
164
165         dbus_connection_send(aRequest.GetConnection(), reply.get(), nullptr);
166     }
167     else
168     {
169         otbrLog(OTBR_LOG_WARNING, "GetProperty %s.%s error:%s", interfaceName.c_str(), propertyName.c_str(),
170                 ConvertToDBusErrorName(error));
171         aRequest.ReplyOtResult(error);
172     }
173 }
174
175 void DBusObject::GetAllPropertiesMethodHandler(DBusRequest &aRequest)
176 {
177     UniqueDBusMessage reply{dbus_message_new_method_return(aRequest.GetMessage())};
178     DBusMessageIter   iter, subIter, dictEntryIter;
179     std::string       interfaceName;
180     auto              args  = std::tie(interfaceName);
181     otError           error = OT_ERROR_NONE;
182
183     VerifyOrExit(reply != nullptr, error = OT_ERROR_NO_BUFS);
184     VerifyOrExit(DBusMessageToTuple(*aRequest.GetMessage(), args) == OTBR_ERROR_NONE, error = OT_ERROR_PARSE);
185     VerifyOrExit(mGetPropertyHandlers.find(interfaceName) != mGetPropertyHandlers.end(), error = OT_ERROR_NOT_FOUND);
186     dbus_message_iter_init_append(reply.get(), &iter);
187
188     for (auto &p : mGetPropertyHandlers.at(interfaceName))
189     {
190         VerifyOrExit(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
191                                                       "{" DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING "}",
192                                                       &subIter),
193                      error = OT_ERROR_FAILED);
194         VerifyOrExit(dbus_message_iter_open_container(&subIter, DBUS_TYPE_DICT_ENTRY, nullptr, &dictEntryIter),
195                      error = OT_ERROR_FAILED);
196         VerifyOrExit(DBusMessageEncode(&dictEntryIter, p.first) == OTBR_ERROR_NONE, error = OT_ERROR_FAILED);
197
198         SuccessOrExit(error = p.second(dictEntryIter));
199
200         VerifyOrExit(dbus_message_iter_close_container(&subIter, &dictEntryIter), error = OT_ERROR_FAILED);
201         VerifyOrExit(dbus_message_iter_close_container(&iter, &subIter));
202     }
203
204 exit:
205     if (error == OT_ERROR_NONE)
206     {
207         dbus_connection_send(aRequest.GetConnection(), reply.get(), nullptr);
208     }
209     else
210     {
211         aRequest.ReplyOtResult(error);
212     }
213 }
214
215 void DBusObject::SetPropertyMethodHandler(DBusRequest &aRequest)
216 {
217     DBusMessageIter iter;
218     std::string     interfaceName;
219     std::string     propertyName;
220     std::string     propertyFullPath;
221     otError         error = OT_ERROR_NONE;
222
223     VerifyOrExit(dbus_message_iter_init(aRequest.GetMessage(), &iter), error = OT_ERROR_FAILED);
224     VerifyOrExit(DBusMessageExtract(&iter, interfaceName) == OTBR_ERROR_NONE, error = OT_ERROR_PARSE);
225     VerifyOrExit(DBusMessageExtract(&iter, propertyName) == OTBR_ERROR_NONE, error = OT_ERROR_PARSE);
226
227     propertyFullPath = interfaceName + "." + propertyName;
228     otbrLog(OTBR_LOG_INFO, "SetProperty %s", propertyFullPath.c_str());
229     {
230         auto handlerIter = mSetPropertyHandlers.find(propertyFullPath);
231
232         VerifyOrExit(handlerIter != mSetPropertyHandlers.end(), error = OT_ERROR_NOT_FOUND);
233         error = handlerIter->second(iter);
234     }
235
236 exit:
237     if (error != OT_ERROR_NONE)
238     {
239         otbrLog(OTBR_LOG_WARNING, "SetProperty %s.%s error:%s", interfaceName.c_str(), propertyName.c_str(),
240                 ConvertToDBusErrorName(error));
241     }
242     aRequest.ReplyOtResult(error);
243     return;
244 }
245
246 DBusObject::~DBusObject(void)
247 {
248 }
249
250 } // namespace DBus
251 } // namespace otbr