Initian code sync up from private gerrit
[platform/core/connectivity/wifi-mesh-manager.git] / src / mesh-service-interface.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <stdlib.h>
20
21 #include <glib.h>
22 #include <gio/gio.h>
23
24 #include "mesh.h"
25 #include "mesh-log.h"
26 #include "mesh-util.h"
27 #include "mesh-service-interface.h"
28 #include "mesh-generated-code.h"
29
30 #include "mesh-request.h"
31 #include "mesh-interface.h"
32
33 static NetMesh *meshd_dbus_object;
34
35 /* global list to care resource handle for each client */
36 static GList *meshd_dbus_client_list;
37 static GMutex meshd_dbus_client_list_mutex;
38
39 typedef struct _meshd_dbus_client_s {
40         gchar *bus_name;
41 } meshd_dbus_client_s;
42
43 NetMesh* meshd_dbus_get_object()
44 {
45         return meshd_dbus_object;
46 }
47
48 int64_t meshd_dbus_generate_signal_number()
49 {
50         static int64_t i = 0;
51
52         return i++;
53 }
54
55 static int _meshd_dbus_client_list_cleanup(GList *client_list)
56 {
57         meshd_dbus_client_s *client;
58
59         meshd_check_null_ret_error("client_list", client_list, FALSE);
60
61         client = client_list->data;
62
63         free(client->bus_name);
64         client->bus_name = NULL;
65         free(client);
66         g_list_free(client_list);
67
68         return MESHD_ERROR_NONE;
69 }
70
71 static int _meshd_dbus_client_list_compare_bus_name(const void *a, const void *b)
72 {
73         const meshd_dbus_client_s *client = a;
74
75         return g_strcmp0(client->bus_name, b);
76 }
77
78 static inline GList* _meshd_dbus_client_list_find_client(const gchar *owner)
79 {
80         return g_list_find_custom(meshd_dbus_client_list, owner,
81                         _meshd_dbus_client_list_compare_bus_name);
82 }
83
84 static void _meshd_dbus_name_owner_changed_cb(GDBusConnection *conn,
85                 const gchar *sender_name,
86                 const gchar *object_path,
87                 const gchar *interface_name,
88                 const gchar *signal_name,
89                 GVariant *parameters,
90                 gpointer user_data)
91 {
92         int ret;
93         GList *client = NULL;
94         gchar *name, *old_owner, *new_owner;
95
96         NOTUSED(conn);
97         NOTUSED(sender_name);
98         NOTUSED(object_path);
99         NOTUSED(interface_name);
100         NOTUSED(signal_name);
101         NOTUSED(user_data);
102
103         g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
104
105         if (0 == strlen(new_owner)) {
106                 g_mutex_lock(&meshd_dbus_client_list_mutex);
107                 client = _meshd_dbus_client_list_find_client(old_owner);
108                 if (client) { /* found bus name in our bus list */
109                         MESH_LOGD("bus(%s) stopped", old_owner);
110                         meshd_dbus_client_list = g_list_remove_link(meshd_dbus_client_list, client);
111                 }
112                 g_mutex_unlock(&meshd_dbus_client_list_mutex);
113
114                 if (client) {
115                         ret = _meshd_dbus_client_list_cleanup(client);
116                         if (MESHD_ERROR_NONE != ret)
117                                 MESH_LOGE("_meshd_dbus_client_list_cleanup() Fail(%d)", ret);
118                 }
119         }
120 }
121
122 static int _meshd_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
123 {
124         unsigned int id;
125
126         id = g_dbus_connection_signal_subscribe(conn,
127                         "org.freedesktop.DBus", /* bus name */
128                         "org.freedesktop.DBus", /* interface */
129                         "NameOwnerChanged", /* member */
130                         "/org/freedesktop/DBus", /* path */
131                         NULL, /* arg0 */
132                         G_DBUS_SIGNAL_FLAGS_NONE,
133                         _meshd_dbus_name_owner_changed_cb,
134                         NULL,
135                         NULL);
136         if (0 == id) {
137                 MESH_LOGE("g_dbus_connection_signal_subscribe() Fail");
138                 return MESHD_ERROR_IO_ERROR;
139         }
140
141         return MESHD_ERROR_NONE;
142 }
143
144 static gboolean _meshd_dbus_handle_enable(NetMesh *object,
145                 GDBusMethodInvocation *invocation,
146                 gpointer user_data)
147 {
148         int ret = MESHD_ERROR_NONE;
149         mesh_service *service = (mesh_service *)user_data;
150         mesh_interface_s *info = service->interface_info;
151
152         if (service->mesh_activated) {
153                 /* Already activated */
154                 net_mesh_complete_enable(object, invocation,
155                                 MESHD_ERROR_OPERATION_FAILED);
156         } else {
157                 /* Do API response first */
158                 net_mesh_complete_enable(object, invocation, ret);
159                 service->mesh_activated = TRUE;
160         }
161
162         meshd_check_null_ret_error("info", info, FALSE);
163
164         ret = mesh_interface_initialize(service->interface_info);
165         if (MESHD_ERROR_NONE != ret) {
166                 MESH_LOGE("Failed to mesh_interface_initialize [%d]", ret);
167                 goto FINISH;
168         }
169
170         ret = mesh_request_enable_mesh_gate(info->base_interface,
171                         info->mesh_interface, info->mesh_id, info->mesh_channel);
172         if (MESHD_ERROR_NONE != ret) {
173                 MESH_LOGE("Failed to mesh_request_enable_mesh_gate [%d]", ret);
174                 goto FINISH;
175         }
176
177         ret = mesh_request_create_bridge(info->bridge_interface,
178                         info->mesh_interface, info->external_interface);
179         if (MESHD_ERROR_NONE != ret) {
180                 MESH_LOGE("Failed to mesh_request_create_bridge [%d]", ret);
181                 goto FINISH;
182         }
183
184         ret = mesh_request_specific_scan(info->mesh_interface,
185                         info->mesh_id, info->mesh_channel);
186         if (MESHD_ERROR_NONE != ret) {
187                 MESH_LOGE("Failed to mesh_request_specific_scan [%d]", ret);
188         }
189
190         ret = mesh_request_dhcp(info->bridge_interface);
191         if (MESHD_ERROR_NONE != ret) {
192                 MESH_LOGE("Failed to mesh_request_dhcp [%d]", ret);
193         }
194
195 FINISH:
196         net_mesh_emit_mesh_enabled(object, ret);
197
198         return TRUE;
199 }
200
201 static gboolean _meshd_dbus_handle_disable(NetMesh *object,
202                 GDBusMethodInvocation *invocation,
203                 gpointer user_data)
204 {
205         int ret = MESHD_ERROR_NONE;
206         mesh_service *service = (mesh_service *)user_data;
207         mesh_interface_s *info = service->interface_info;
208
209         meshd_check_null_ret_error("info", info, FALSE);
210
211         if (FALSE == service->mesh_activated) {
212                 MESH_LOGD("Mesh network is not activated yet");
213                 ret = MESHD_ERROR_OPERATION_FAILED;
214                 goto FINISH;
215         }
216
217         ret = mesh_request_disable_mesh_gate(info->mesh_interface);
218         if (MESHD_ERROR_NONE != ret) {
219                 MESH_LOGE("Failed to mesh_request_disable_mesh_gate");
220                 goto FINISH;
221         }
222
223         ret = mesh_request_remove_bridge(info->bridge_interface);
224         if (MESHD_ERROR_NONE != ret) {
225                 MESH_LOGE("Failed to mesh_request_remove_bridge");
226         }
227
228 FINISH:
229         net_mesh_complete_disable(object, invocation, ret);
230
231         return TRUE;
232 }
233
234 static gboolean _meshd_dbus_handle_set_mesh_gate(NetMesh *object,
235                 GDBusMethodInvocation *invocation,
236                 gboolean state,
237                 gpointer user_data)
238 {
239         int ret = MESHD_ERROR_NONE;
240
241         MESH_LOGD("Not implemented yet !");
242         NOTUSED(state);
243         NOTUSED(user_data);
244
245         /* TODO: Check external interface and set it into bridge */
246
247         net_mesh_complete_set_mesh_gate(object, invocation, ret);
248
249         return TRUE;
250 }
251
252 static gboolean _meshd_dbus_handle_set_mesh_softap(NetMesh *object,
253                 GDBusMethodInvocation *invocation,
254                 gboolean state,
255                 gpointer user_data)
256 {
257         int ret = MESHD_ERROR_NONE;
258
259         MESH_LOGD("Not implemented yet !");
260         NOTUSED(state);
261         NOTUSED(user_data);
262
263         /* TODO: Check softAP interface and execute it */
264
265         net_mesh_complete_set_mesh_softap(object, invocation, ret);
266
267         return TRUE;
268 }
269
270 static gboolean _meshd_dbus_handle_scan(NetMesh *object,
271                 GDBusMethodInvocation *invocation,
272                 gpointer user_data)
273 {
274         int ret = MESHD_ERROR_NONE;
275         mesh_service *service = (mesh_service *)user_data;
276         mesh_interface_s *info = service->interface_info;
277
278         meshd_check_null_ret_error("info", info, FALSE);
279
280         ret = mesh_request_scan(info->mesh_interface);
281         if (MESHD_ERROR_NONE != ret) {
282                 MESH_LOGE("Failed to mesh_request_scan");
283         }
284
285         net_mesh_complete_scan(object, invocation, ret);
286
287         return TRUE;
288 }
289
290 static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
291                 GDBusMethodInvocation *invocation,
292                 gchar *mesh_id,
293                 gint channel,
294                 gpointer user_data)
295 {
296         int ret = MESHD_ERROR_NONE;
297         mesh_service *service = (mesh_service *)user_data;
298         mesh_interface_s *info = service->interface_info;
299
300         meshd_check_null_ret_error("info", info, FALSE);
301
302         ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel);
303         if (MESHD_ERROR_NONE != ret) {
304                 MESH_LOGE("Failed to mesh_request_specific_scan");
305         }
306
307         net_mesh_complete_specific_scan(object, invocation, ret);
308
309         return TRUE;
310 }
311
312 static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
313                 GDBusMethodInvocation *invocation,
314                 gpointer user_data)
315 {
316         int ret = MESHD_ERROR_NONE;
317         mesh_service *service = (mesh_service *)user_data;
318         mesh_interface_s *info = service->interface_info;
319
320         ret = mesh_request_cancel_scan(info->mesh_interface);
321         if (MESHD_ERROR_NONE != ret) {
322                 MESH_LOGE("Failed to mesh_request_cancel_scan");
323         }
324
325         net_mesh_complete_cancel_scan(object, invocation, ret);
326
327         return TRUE;
328 }
329
330 static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
331                 GDBusMethodInvocation *invocation)
332 {
333         int ret = MESHD_ERROR_NONE;
334
335         NOTUSED(ret);
336         NOTUSED(object);
337         NOTUSED(invocation);
338
339         MESH_LOGD("Not implemented yet !");
340         //net_mesh_complete_get_station_info(object, invocation, ret);
341
342         return TRUE;
343 }
344
345 static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
346                 GDBusMethodInvocation *invocation)
347 {
348         int ret = MESHD_ERROR_NONE;
349
350         NOTUSED(ret);
351         NOTUSED(object);
352         NOTUSED(invocation);
353
354         MESH_LOGD("Not implemented yet !");
355         //net_mesh_complete_get_mpath_info(object, invocation, ret);
356
357         return TRUE;
358 }
359
360 static gboolean _meshd_dbus_handle_join(NetMesh *object,
361                 GDBusMethodInvocation *invocation)
362 {
363         int ret = MESHD_ERROR_NONE;
364
365         MESH_LOGD("Not implemented yet !");
366         net_mesh_complete_join(object, invocation, ret);
367
368         return TRUE;
369 }
370
371 static gboolean _meshd_dbus_handle_is_joined(NetMesh *object,
372                 GDBusMethodInvocation *invocation)
373 {
374         int ret = MESHD_ERROR_NONE;
375
376         MESH_LOGD("Not implemented yet !");
377         net_mesh_complete_is_joined(object, invocation, ret);
378
379         return TRUE;
380 }
381
382 static gboolean _meshd_dbus_handle_disjoin(NetMesh *object,
383                 GDBusMethodInvocation *invocation)
384 {
385         int ret = MESHD_ERROR_NONE;
386
387         MESH_LOGD("Not implemented yet !");
388         net_mesh_complete_disjoin(object, invocation, ret);
389
390         return TRUE;
391 }
392
393 static gboolean _meshd_dbus_handle_load_softap_settings(NetMesh *object,
394                 GDBusMethodInvocation *invocation)
395 {
396         int ret = MESHD_ERROR_NONE;
397
398         MESH_LOGD("Not implemented yet !");
399         net_mesh_complete_load_softap_settings(object, invocation, ret);
400
401         return TRUE;
402 }
403
404 static gboolean _meshd_dbus_handle_start_bridge(NetMesh *object,
405                 GDBusMethodInvocation *invocation,
406                 gint mode,
407                 gchar *bridge_interface,
408                 gpointer user_data)
409 {
410         int ret = MESHD_ERROR_NONE;
411
412         NOTUSED(user_data);
413
414         MESH_LOGD("Mode : %d", mode);
415         MESH_LOGD("Interface : %s", bridge_interface);
416         ret = mesh_request_create_bridge(bridge_interface, NULL, NULL);
417
418         net_mesh_complete_start_bridge(object, invocation, ret);
419
420         return TRUE;
421 }
422
423 static gboolean _meshd_dbus_handle_stop_bridge(NetMesh *object,
424                 GDBusMethodInvocation *invocation,
425                 gchar *bridge_interface,
426                 gpointer user_data)
427 {
428         int ret = MESHD_ERROR_NONE;
429
430         NOTUSED(user_data);
431
432         MESH_LOGD("Interface : %s", bridge_interface);
433         ret = mesh_request_remove_bridge(bridge_interface);
434
435         net_mesh_complete_stop_bridge(object, invocation, ret);
436
437         return TRUE;
438 }
439
440
441 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
442                 gpointer user_data)
443 {
444         gboolean ret;
445         GError *error = NULL;
446         mesh_service *service = (mesh_service *)user_data;
447
448         NOTUSED(name);
449
450         meshd_dbus_object = net_mesh_skeleton_new();
451         if (NULL == meshd_dbus_object) {
452                 MESH_LOGE("net_mesh_skeleton_new() Fail");
453                 return;
454         }
455
456         g_signal_connect(meshd_dbus_object, "handle-enable",
457                         G_CALLBACK(_meshd_dbus_handle_enable), service);
458         g_signal_connect(meshd_dbus_object, "handle-disable",
459                         G_CALLBACK(_meshd_dbus_handle_disable), service);
460         g_signal_connect(meshd_dbus_object, "handle-set-mesh-gate",
461                         G_CALLBACK(_meshd_dbus_handle_set_mesh_gate), service);
462         g_signal_connect(meshd_dbus_object, "handle-set-mesh-softap",
463                         G_CALLBACK(_meshd_dbus_handle_set_mesh_softap), service);
464         g_signal_connect(meshd_dbus_object, "handle-scan",
465                         G_CALLBACK(_meshd_dbus_handle_scan), service);
466         g_signal_connect(meshd_dbus_object, "handle-specific-scan",
467                         G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
468         g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
469                         G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
470         g_signal_connect(meshd_dbus_object, "handle-get-station-info",
471                         G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
472         g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
473                         G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
474         g_signal_connect(meshd_dbus_object, "handle-join",
475                         G_CALLBACK(_meshd_dbus_handle_join), service);
476         g_signal_connect(meshd_dbus_object, "handle-is-joined",
477                         G_CALLBACK(_meshd_dbus_handle_is_joined), service);
478         g_signal_connect(meshd_dbus_object, "handle-disjoin",
479                         G_CALLBACK(_meshd_dbus_handle_disjoin), service);
480         g_signal_connect(meshd_dbus_object, "handle-load-softap-settings",
481                         G_CALLBACK(_meshd_dbus_handle_load_softap_settings), service);
482         g_signal_connect(meshd_dbus_object, "handle-start-bridge",
483                         G_CALLBACK(_meshd_dbus_handle_start_bridge), service);
484         g_signal_connect(meshd_dbus_object, "handle-stop-bridge",
485                         G_CALLBACK(_meshd_dbus_handle_stop_bridge), service);
486
487         ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
488                         conn, MESH_DBUS_OBJPATH, &error);
489         if (FALSE == ret) {
490                 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
491                 g_error_free(error);
492         }
493
494         ret = _meshd_dbus_subscribe_name_owner_changed(conn);
495         if (MESHD_ERROR_NONE != ret) {
496                 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
497                 return;
498         }
499 }
500
501 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
502                 gpointer user_data)
503 {
504         NOTUSED(conn);
505         NOTUSED(user_data);
506
507         MESH_LOGD("Lost the name %s", name);
508 }
509
510 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
511                 gpointer user_data)
512 {
513         NOTUSED(conn);
514         NOTUSED(user_data);
515
516         MESH_LOGD("Acquired the name %s", name);
517 }
518
519 static gboolean _meshd_dbus_interface_init(mesh_service *service)
520 {
521         guint id;
522         meshd_check_null_ret_error("service", service, FALSE);
523
524         id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
525                         MESH_DBUS_INTERFACE,
526                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
527                         _meshd_dbus_on_bus_acquired,
528                         _meshd_dbus_on_name_acquired,
529                         _meshd_dbus_on_name_lost,
530                         service,
531                         NULL);
532         if (0 == id) {
533                 MESH_LOGE("g_bus_own_name() Fail");
534                 return FALSE;
535         }
536
537         service->dbus_id = id;
538         service->interface_info = g_new0(mesh_interface_s, 1);
539
540         return TRUE;
541 }
542
543 static void _meshd_dbus_deinit(mesh_service *service)
544 {
545         mesh_interface_s *info = NULL;
546         meshd_check_null_ret("service", service);
547
548         g_bus_unown_name(service->dbus_id);
549
550         info = service->interface_info;
551         meshd_check_null_ret("info", info);
552         if (info->bridge_interface)
553                 g_free(info->bridge_interface);
554         if (info->base_interface)
555                 g_free(info->base_interface);
556         if (info->mesh_interface)
557                 g_free(info->mesh_interface);
558         if (info->softap_interface)
559                 g_free(info->softap_interface);
560         if (info->external_interface)
561                 g_free(info->external_interface);
562
563         g_free(service->interface_info);
564         service->interface_info = NULL;
565 }
566
567  /**< mesh service interface initialization */
568 gboolean meshd_service_interface_init(mesh_service *service)
569 {
570         guint ret;
571         meshd_check_null_ret_error("service", service, FALSE);
572
573         /* Initialize dbus interface */
574         ret = _meshd_dbus_interface_init(service);
575         if (FALSE == ret) {
576                 MESH_LOGE("zigbee_service_dbus_interface_init failed!!!");
577                 return FALSE;
578         }
579
580         return TRUE;
581 }
582
583 /**< Zigbee service interface de-initialization */
584 void meshd_service_interface_deinit(mesh_service *service)
585 {
586         meshd_check_null_ret("service", service);
587
588         /* De-initialize dbus interface */
589         _meshd_dbus_deinit(service);
590 }