Fix GVariantBuilder wrong use
[platform/core/connectivity/uwb-manager.git] / src / UwbDbusIfaceAdapter.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <utility>
17
18 #include <uwb-log-def.h>
19 #include <uwb-error-def.h>
20
21 #include <GdbusError.h>
22 #include <UwbDbusIfaceAdapter.h>
23
24 using namespace UwbManagerNamespace;
25
26 #define ret_err_if_nullptr(value) do { \
27                 if ((value) == nullptr) { \
28                         __dbus_return_err(UWB_ERROR_OPERATION_FAILED, invocation); \
29                         __UWB_LOG_FUNC_EXIT__; \
30                         return TRUE; \
31                 } \
32         } while (0)
33
34 #define ret_err_if_non_zero(value) do { \
35                 if ((value) != 0) { \
36                         __dbus_return_err(UWB_ERROR_OPERATION_FAILED, invocation); \
37                         __UWB_LOG_FUNC_EXIT__; \
38                         return TRUE; \
39                 } \
40         } while (0)
41
42 #define DBUS_DEBUG_VARIANT(parameters) \
43         do {\
44                 gchar *parameters_debug_str = NULL;\
45                 if (parameters)\
46                         parameters_debug_str = g_variant_print(parameters, TRUE);\
47                 UWB_LOGI("signal params [%s]", parameters_debug_str ? parameters_debug_str : "NULL");\
48                 g_free(parameters_debug_str);\
49         } while (0)
50
51 static void __dbus_return_err(uwb_error_e ret, GDBusMethodInvocation *invocation)
52 {
53         GdbusError gdbus_error;
54         GError *err = NULL;
55         gchar* dbus_error_name = NULL;
56
57         if (!invocation)
58                 return;
59
60         gdbus_error.setGerror(ret, &err);
61         dbus_error_name = g_dbus_error_encode_gerror(err);
62         UWB_LOGI("g_dbus_method_invocation_return_gerror with [%s]", dbus_error_name);
63         g_free(dbus_error_name);
64         g_dbus_method_invocation_return_gerror(invocation, err);
65         g_clear_error(&err);
66         return;
67 }
68
69 static gboolean __handle_test(
70                        UwbGdbuslibManager *gdbus_manager,
71                        GDBusMethodInvocation *invocation,
72                        gpointer user_data)
73 {
74         __UWB_LOG_FUNC_ENTER__;
75
76         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
77         ret_err_if_nullptr(iface_adapter);
78
79         auto handler = iface_adapter->getTest();
80         ret_err_if_nullptr(handler);
81
82         int ret = handler();
83         ret_err_if_non_zero(ret);
84
85         uwb_gdbuslib_manager_complete_test(gdbus_manager, invocation);
86
87         __UWB_LOG_FUNC_EXIT__;
88         return TRUE;
89 }
90
91 static gboolean __handle_reset(
92                        UwbGdbuslibManager *gdbus_manager,
93                        GDBusMethodInvocation *invocation,
94                        gpointer user_data)
95 {
96         __UWB_LOG_FUNC_ENTER__;
97
98
99         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
100         ret_err_if_nullptr(iface_adapter);
101
102         auto handler = iface_adapter->getReset();
103         ret_err_if_nullptr(handler);
104
105         int ret = handler();
106         ret_err_if_non_zero(ret);
107
108         uwb_gdbuslib_manager_complete_reset(gdbus_manager, invocation);
109
110         __UWB_LOG_FUNC_EXIT__;
111         return TRUE;
112 }
113
114 static gboolean __handle_factory_reset(
115                        UwbGdbuslibManager *gdbus_manager,
116                        GDBusMethodInvocation *invocation,
117                        gpointer user_data)
118 {
119         __UWB_LOG_FUNC_ENTER__;
120
121
122         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
123         ret_err_if_nullptr(iface_adapter);
124
125         auto handler = iface_adapter->getFactoryReset();
126         ret_err_if_nullptr(handler);
127
128         int ret = handler();
129         ret_err_if_non_zero(ret);
130
131         uwb_gdbuslib_manager_complete_factory_reset(gdbus_manager, invocation);
132
133         __UWB_LOG_FUNC_EXIT__;
134         return TRUE;
135 }
136
137 static gboolean __handle_enable_network(
138                        UwbGdbuslibManager *gdbus_manager,
139                        GDBusMethodInvocation *invocation,
140                        gpointer user_data)
141 {
142         __UWB_LOG_FUNC_ENTER__;
143
144
145         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
146         ret_err_if_nullptr(iface_adapter);
147
148         auto handler = iface_adapter->getEnableNetwork();
149         ret_err_if_nullptr(handler);
150
151         int ret = handler();
152         ret_err_if_non_zero(ret);
153
154         uwb_gdbuslib_manager_complete_enable_network(gdbus_manager, invocation);
155
156         __UWB_LOG_FUNC_EXIT__;
157         return TRUE;
158 }
159
160 static gboolean __handle_disable_network(
161                        UwbGdbuslibManager *gdbus_manager,
162                        GDBusMethodInvocation *invocation,
163                        gpointer user_data)
164 {
165         __UWB_LOG_FUNC_ENTER__;
166
167
168         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
169         ret_err_if_nullptr(iface_adapter);
170
171         auto handler = iface_adapter->getDisableNetwork();
172         ret_err_if_nullptr(handler);
173
174         int ret = handler();
175         ret_err_if_non_zero(ret);
176
177         uwb_gdbuslib_manager_complete_disable_network(gdbus_manager, invocation);
178
179         __UWB_LOG_FUNC_EXIT__;
180         return TRUE;
181 }
182
183 static gboolean __handle_start_location_engine(
184                        UwbGdbuslibManager *gdbus_manager,
185                        GDBusMethodInvocation *invocation,
186                                    const gchar *server,
187                                    gint32 port,
188                        gpointer user_data)
189 {
190         __UWB_LOG_FUNC_ENTER__;
191
192
193         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
194         ret_err_if_nullptr(iface_adapter);
195
196         auto handler = iface_adapter->getStartLocationEngine();
197         ret_err_if_nullptr(handler);
198
199         int ret = handler(server, port);
200         ret_err_if_non_zero(ret);
201
202         uwb_gdbuslib_manager_complete_start_location_engine(gdbus_manager, invocation);
203
204         __UWB_LOG_FUNC_EXIT__;
205         return TRUE;
206 }
207
208 static gboolean __handle_stop_location_engine(
209                        UwbGdbuslibManager *gdbus_manager,
210                        GDBusMethodInvocation *invocation,
211                        gpointer user_data)
212 {
213         __UWB_LOG_FUNC_ENTER__;
214
215
216         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
217         ret_err_if_nullptr(iface_adapter);
218
219         auto handler = iface_adapter->getStopLocationEngine();
220         ret_err_if_nullptr(handler);
221
222         int ret = handler();
223         ret_err_if_non_zero(ret);
224
225         uwb_gdbuslib_manager_complete_stop_location_engine(gdbus_manager, invocation);
226
227         __UWB_LOG_FUNC_EXIT__;
228         return TRUE;
229 }
230
231 static void __build_node_variant(Node &node, GVariant **node_gvar)
232 {
233         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
234
235         g_variant_builder_add(builder, "{sv}", "Distance",
236                                                         g_variant_new_uint64(node.getDistance()));
237         g_variant_builder_add(builder, "{sv}", "PanID",
238                                                         g_variant_new_uint16(node.getPanId()));
239         g_variant_builder_add(builder, "{sv}", "NodeID",
240                                                         g_variant_new_uint64(node.getNodeId()));
241         g_variant_builder_add(builder, "{sv}", "X",
242                                                         g_variant_new_int32(node.getX()));
243         g_variant_builder_add(builder, "{sv}", "Y",
244                                                         g_variant_new_int32(node.getY()));
245         g_variant_builder_add(builder, "{sv}", "Z",
246                                                         g_variant_new_int32(node.getZ()));
247
248         *node_gvar = g_variant_builder_end(builder);
249         g_variant_builder_unref(builder);
250 }
251
252 static gboolean __handle_get_own_node(
253                        UwbGdbuslibManager *gdbus_manager,
254                        GDBusMethodInvocation *invocation,
255                        gpointer user_data)
256 {
257         __UWB_LOG_FUNC_ENTER__;
258
259
260         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
261         ret_err_if_nullptr(iface_adapter);
262
263         auto handler = iface_adapter->getGetOwnNode();
264         ret_err_if_nullptr(handler);
265
266         Node &node_ref = handler();
267         GVariant *node_gvar = nullptr;
268         __build_node_variant(node_ref, &node_gvar);
269
270         uwb_gdbuslib_manager_complete_get_own_node(gdbus_manager, invocation, node_gvar);
271
272         __UWB_LOG_FUNC_EXIT__;
273         return TRUE;
274 }
275
276 static void __build_network_variant(std::map<int, std::unique_ptr<Node>> &node_map, GVariant **networks_gvar)
277 {
278         GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
279
280         for (const auto &elem : node_map) {
281                 Node *node_ptr = elem.second.get();
282                 g_variant_builder_open(builder, G_VARIANT_TYPE_VARDICT);
283                 g_variant_builder_add(builder, "{sv}", "Distance",
284                                                 g_variant_new_uint64(node_ptr->getDistance()));
285                 g_variant_builder_add(builder, "{sv}", "PanID",
286                                                 g_variant_new_uint16(node_ptr->getPanId()));
287                 g_variant_builder_add(builder, "{sv}", "NodeID",
288                                                 g_variant_new_uint64(node_ptr->getNodeId()));
289                 g_variant_builder_add(builder, "{sv}", "X",
290                                                 g_variant_new_int32(node_ptr->getX()));
291                 g_variant_builder_add(builder, "{sv}", "Y",
292                                                 g_variant_new_int32(node_ptr->getY()));
293                 g_variant_builder_add(builder, "{sv}", "Z",
294                                                 g_variant_new_int32(node_ptr->getZ()));
295                 g_variant_builder_add(builder, "{sv}", "Range",
296                                                 g_variant_new_int32(node_ptr->getRange()));
297                 g_variant_builder_add(builder, "{sv}", "Aoa",
298                                                 g_variant_new_int32(node_ptr->getAoa()));
299                 g_variant_builder_add(builder, "{sv}", "Pdoa",
300                                                 g_variant_new_int32(node_ptr->getPdoa()));
301                 g_variant_builder_add(builder, "{sv}", "FilteredRange",
302                                                 g_variant_new_int32((int)node_ptr->getFilteredRange()));
303                 g_variant_builder_add(builder, "{sv}", "FilteredAoa",
304                                                 g_variant_new_int32((int)node_ptr->getFilteredAoa()));
305                 g_variant_builder_close(builder);
306         }
307
308         *networks_gvar = g_variant_builder_end(builder);
309         g_variant_builder_unref(builder);
310 }
311
312 static gboolean __handle_get_network_info(
313                        UwbGdbuslibManager *gdbus_manager,
314                        GDBusMethodInvocation *invocation,
315                        gpointer user_data)
316 {
317         __UWB_LOG_FUNC_ENTER__;
318
319
320         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
321         ret_err_if_nullptr(iface_adapter);
322
323         auto handler = iface_adapter->getGetNetworkInfo();
324         ret_err_if_nullptr(handler);
325
326         GVariant *networks_gvar = nullptr;
327         auto &network_map = handler();
328         __build_network_variant(network_map, &networks_gvar);
329
330         uwb_gdbuslib_manager_complete_get_network_info(gdbus_manager, invocation,
331                         (uint16_t)0, networks_gvar);
332
333         __UWB_LOG_FUNC_EXIT__;
334         return TRUE;
335 }
336
337 static gboolean __handle_set_configurations(
338                        UwbGdbuslibManager *gdbus_manager,
339                        GDBusMethodInvocation *invocation,
340                                    guint16 node_id,
341                                    GVariant *configurations,
342                        gpointer user_data)
343 {
344         __UWB_LOG_FUNC_ENTER__;
345
346
347         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
348         ret_err_if_nullptr(iface_adapter);
349
350         auto handler = iface_adapter->getSetConfigurations();
351         ret_err_if_nullptr(handler);
352
353         DBUS_DEBUG_VARIANT(configurations);
354         int ret = handler(configurations);
355         ret_err_if_non_zero(ret);
356
357         uwb_gdbuslib_manager_complete_set_configurations(gdbus_manager, invocation);
358
359         __UWB_LOG_FUNC_EXIT__;
360         return TRUE;
361 }
362
363 static gboolean __handle_get_configurations(
364                        UwbGdbuslibManager *gdbus_manager,
365                        GDBusMethodInvocation *invocation,
366                                    guint16 node_id,
367                        gpointer user_data)
368 {
369         __UWB_LOG_FUNC_ENTER__;
370
371
372         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
373         ret_err_if_nullptr(iface_adapter);
374
375         auto handler = iface_adapter->getGetConfigurations();
376         ret_err_if_nullptr(handler);
377
378         GVariant *config_gvar = handler();
379         ret_err_if_nullptr(config_gvar);
380
381         g_variant_ref(config_gvar);
382         DBUS_DEBUG_VARIANT(config_gvar);
383         uwb_gdbuslib_manager_complete_get_configurations(gdbus_manager, invocation, config_gvar);
384
385         __UWB_LOG_FUNC_EXIT__;
386         return TRUE;
387 }
388
389 static gboolean __handle_set_position(
390                        UwbGdbuslibManager *gdbus_manager,
391                        GDBusMethodInvocation *invocation,
392                                    guint16 node_id,
393                                    gint x,
394                                    gint y,
395                                    gint z,
396                        gpointer user_data)
397 {
398         __UWB_LOG_FUNC_ENTER__;
399
400
401         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
402         ret_err_if_nullptr(iface_adapter);
403
404         auto handler = iface_adapter->getSetPosition();
405         ret_err_if_nullptr(handler);
406
407         handler(x, y, z);
408
409         uwb_gdbuslib_manager_complete_set_position(gdbus_manager, invocation);
410
411         __UWB_LOG_FUNC_EXIT__;
412         return TRUE;
413 }
414
415 static gint __ay_to_guchar(GVariant *src, int size, guchar **dst)
416 {
417         if (src == nullptr || dst == nullptr || size == 0)
418                 return 0;
419
420         GVariantIter *iter;
421         g_variant_get(src, "a(y)", &iter);
422
423         int result_size = g_variant_iter_n_children(iter);
424         if (result_size == 0 || result_size != size)
425                 return 0;
426
427         guchar *buffer = (guchar *)g_try_malloc0(result_size);
428         if (!buffer)
429                 return 0;
430
431         guint8 element;
432         guint pos = 0;
433
434         while (g_variant_iter_loop(iter, "(y)", &element)) {
435                 *(buffer + pos) = element;
436                 ++pos;
437         }
438
439         g_variant_iter_free(iter);
440
441         *dst = buffer;
442         return result_size;
443 }
444
445 static gboolean __handle_send_message(
446                        UwbGdbuslibManager *gdbus_manager,
447                        GDBusMethodInvocation *invocation,
448                                    GVariant * message,
449                                    gint message_length,
450                        gpointer user_data)
451 {
452         __UWB_LOG_FUNC_ENTER__;
453
454
455         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
456         ret_err_if_nullptr(iface_adapter);
457
458         auto handler = iface_adapter->getSendMessage();
459         ret_err_if_nullptr(handler);
460
461         guchar *buffer = nullptr;
462         if (__ay_to_guchar(message, message_length, &buffer) == 0) {
463                 __dbus_return_err(UWB_ERROR_INVALID_PARAMETER, invocation);
464                 __UWB_LOG_FUNC_EXIT__;
465                 return TRUE;
466         }
467
468         int ret = handler(buffer, message_length);
469         g_free(buffer);
470         ret_err_if_non_zero(ret);
471
472         uwb_gdbuslib_manager_complete_send_message(gdbus_manager, invocation);
473
474         __UWB_LOG_FUNC_EXIT__;
475         return TRUE;
476 }
477
478 static gboolean __handle_send_message_to(
479                        UwbGdbuslibManager *gdbus_manager,
480                        GDBusMethodInvocation *invocation,
481                                    guint16 node_id,
482                                    GVariant * message,
483                                    gint message_length,
484                        gpointer user_data)
485 {
486         __UWB_LOG_FUNC_ENTER__;
487
488         UwbDbusIfaceAdapter *iface_adapter = (UwbDbusIfaceAdapter *)user_data;
489         ret_err_if_nullptr(iface_adapter);
490
491         auto handler = iface_adapter->getSendMessageTo();
492         ret_err_if_nullptr(handler);
493
494         guchar *buffer = nullptr;
495         if (__ay_to_guchar(message, message_length, &buffer) == 0) {
496                 __dbus_return_err(UWB_ERROR_INVALID_PARAMETER, invocation);
497                 __UWB_LOG_FUNC_EXIT__;
498                 return TRUE;
499         }
500
501         int ret = handler(node_id, buffer, message_length);
502         g_free(buffer);
503         ret_err_if_non_zero(ret);
504
505         uwb_gdbuslib_manager_complete_send_message_to(gdbus_manager, invocation);
506
507         __UWB_LOG_FUNC_EXIT__;
508         return TRUE;
509 }
510
511 static std::pair<std::string, void *> handlers[] = {
512                 std::make_pair(std::string{"handle-test"}, (void *)__handle_test),
513                 std::make_pair(std::string{"handle-reset"}, (void *)__handle_reset),
514                 std::make_pair(std::string{"handle-factory-reset"}, (void *)__handle_factory_reset),
515
516                 std::make_pair(std::string{"handle-enable-network"}, (void *)__handle_enable_network),
517                 std::make_pair(std::string{"handle-disable-network"}, (void *)__handle_disable_network),
518
519                 std::make_pair(std::string{"handle-start-location-engine"}, (void *)__handle_start_location_engine),
520                 std::make_pair(std::string{"handle-stop-location-engine"}, (void *)__handle_stop_location_engine),
521
522                 std::make_pair(std::string{"handle-get-own-node"}, (void *)__handle_get_own_node),
523                 std::make_pair(std::string{"handle-get-network-info"}, (void *)__handle_get_network_info),
524
525                 std::make_pair(std::string{"handle-set-configurations"}, (void *)__handle_set_configurations),
526                 std::make_pair(std::string{"handle-get-configurations"}, (void *)__handle_get_configurations),
527
528                 std::make_pair(std::string{"handle-set-position"}, (void *)__handle_set_position),
529
530                 std::make_pair(std::string{"handle-send-message"}, (void *)__handle_send_message),
531                 std::make_pair(std::string{"handle-send-message-to"}, (void *)__handle_send_message_to)
532 };
533
534 void UwbDbusIfaceAdapter::init(GDBusConnection *connection,
535                 UwbGdbuslibManager *manager_skeleton)
536 {
537         __UWB_LOG_FUNC_ENTER__;
538
539         /* Register method callbacks as signal callback */
540         for (const auto &handler : handlers)
541                 g_signal_connect(
542                                 manager_skeleton,
543                                 handler.first.c_str(),
544                                 G_CALLBACK(handler.second),
545                                 gpointer(this));
546
547         /* Set connection to 'manager' */
548         GDBusObjectManagerServer *manager =
549                         g_dbus_object_manager_server_new(this->_uwb_dbus_path_str.c_str());
550         g_dbus_object_manager_server_set_connection(manager, connection);
551
552         /* Export 'manager' interface on UWB DBUS */
553         GError *error = NULL;
554         gboolean ret = g_dbus_interface_skeleton_export(
555                 G_DBUS_INTERFACE_SKELETON(manager_skeleton),
556                 connection, this->_uwb_dbus_path_str.c_str(), &error);
557
558         if (ret == FALSE) {
559                 UWB_LOGE("Can not skeleton_export %s", error->message);
560                 g_error_free(error);
561         }
562
563         __UWB_LOG_FUNC_EXIT__;
564 }
565
566 void deinit(void)
567 {
568
569 }