Add function prototype for mesh saved network
[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 #if 0
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_dhcp_request(info->bridge_interface);
191         if (MESHD_ERROR_NONE != ret) {
192                 MESH_LOGE("Failed to mesh_dhcp_request [%d]", ret);
193         }
194 #endif
195
196 FINISH:
197         net_mesh_emit_mesh_enabled(object, ret);
198
199         return TRUE;
200 }
201
202 static gboolean _meshd_dbus_handle_disable(NetMesh *object,
203                 GDBusMethodInvocation *invocation,
204                 gpointer user_data)
205 {
206         int ret = MESHD_ERROR_NONE;
207         mesh_service *service = (mesh_service *)user_data;
208         mesh_interface_s *info = service->interface_info;
209
210         meshd_check_null_ret_error("info", info, FALSE);
211
212         if (FALSE == service->mesh_activated) {
213                 MESH_LOGD("Mesh network is not activated yet");
214                 ret = MESHD_ERROR_OPERATION_FAILED;
215                 goto FINISH;
216         }
217
218         ret = mesh_request_disable_mesh_gate(info->mesh_interface);
219         if (MESHD_ERROR_NONE != ret) {
220                 MESH_LOGE("Failed to mesh_request_disable_mesh_gate");
221                 goto FINISH;
222         }
223
224         ret = mesh_request_remove_bridge(info->bridge_interface);
225         if (MESHD_ERROR_NONE != ret) {
226                 MESH_LOGE("Failed to mesh_request_remove_bridge");
227         }
228
229 FINISH:
230         net_mesh_complete_disable(object, invocation, ret);
231
232         return TRUE;
233 }
234
235 static gboolean _meshd_dbus_handle_set_mesh_gate(NetMesh *object,
236                 GDBusMethodInvocation *invocation,
237                 gboolean state,
238                 gpointer user_data)
239 {
240         int ret = MESHD_ERROR_NONE;
241
242         MESH_LOGD("Not implemented yet !");
243         NOTUSED(state);
244         NOTUSED(user_data);
245
246         /* TODO: Check external interface and set it into bridge */
247
248         net_mesh_complete_set_mesh_gate(object, invocation, ret);
249
250         return TRUE;
251 }
252
253 static gboolean _meshd_dbus_handle_set_mesh_softap(NetMesh *object,
254                 GDBusMethodInvocation *invocation,
255                 gboolean state,
256                 gpointer user_data)
257 {
258         int ret = MESHD_ERROR_NONE;
259
260         MESH_LOGD("Not implemented yet !");
261         NOTUSED(state);
262         NOTUSED(user_data);
263
264         /* TODO: Check softAP interface and execute it */
265
266         net_mesh_complete_set_mesh_softap(object, invocation, ret);
267
268         return TRUE;
269 }
270
271 static gboolean _meshd_dbus_handle_scan(NetMesh *object,
272                 GDBusMethodInvocation *invocation,
273                 gpointer user_data)
274 {
275         int ret = MESHD_ERROR_NONE;
276         mesh_service *service = (mesh_service *)user_data;
277         mesh_interface_s *info = service->interface_info;
278
279         meshd_check_null_ret_error("info", info, FALSE);
280
281         ret = mesh_request_scan(info->mesh_interface);
282         if (MESHD_ERROR_NONE != ret) {
283                 MESH_LOGE("Failed to mesh_request_scan");
284         }
285
286         net_mesh_complete_scan(object, invocation, ret);
287
288         return TRUE;
289 }
290
291 static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
292                 GDBusMethodInvocation *invocation,
293                 gchar *mesh_id,
294                 gint channel,
295                 gpointer user_data)
296 {
297         int ret = MESHD_ERROR_NONE;
298         mesh_service *service = (mesh_service *)user_data;
299         mesh_interface_s *info = service->interface_info;
300
301         meshd_check_null_ret_error("info", info, FALSE);
302
303         ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel);
304         if (MESHD_ERROR_NONE != ret) {
305                 MESH_LOGE("Failed to mesh_request_specific_scan");
306         }
307
308         net_mesh_complete_specific_scan(object, invocation, ret);
309
310         return TRUE;
311 }
312
313 static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
314                 GDBusMethodInvocation *invocation,
315                 gpointer user_data)
316 {
317         int ret = MESHD_ERROR_NONE;
318         mesh_service *service = (mesh_service *)user_data;
319         mesh_interface_s *info = service->interface_info;
320
321         ret = mesh_request_cancel_scan(info->mesh_interface);
322         if (MESHD_ERROR_NONE != ret) {
323                 MESH_LOGE("Failed to mesh_request_cancel_scan");
324         }
325
326         net_mesh_complete_cancel_scan(object, invocation, ret);
327
328         return TRUE;
329 }
330
331 static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
332                 GDBusMethodInvocation *invocation)
333 {
334         int ret = MESHD_ERROR_NONE;
335
336         NOTUSED(ret);
337         NOTUSED(object);
338         NOTUSED(invocation);
339
340         MESH_LOGD("Not implemented yet !");
341         //net_mesh_complete_get_station_info(object, invocation, ret);
342
343         return TRUE;
344 }
345
346 static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
347                 GDBusMethodInvocation *invocation)
348 {
349         int ret = MESHD_ERROR_NONE;
350
351         NOTUSED(ret);
352         NOTUSED(object);
353         NOTUSED(invocation);
354
355         MESH_LOGD("Not implemented yet !");
356         //net_mesh_complete_get_mpath_info(object, invocation, ret);
357
358         return TRUE;
359 }
360
361 static gboolean _meshd_dbus_handle_join(NetMesh *object,
362                 GDBusMethodInvocation *invocation)
363 {
364         int ret = MESHD_ERROR_NONE;
365
366         MESH_LOGD("Not implemented yet !");
367         net_mesh_complete_join(object, invocation, ret);
368
369         return TRUE;
370 }
371
372 static gboolean _meshd_dbus_handle_is_joined(NetMesh *object,
373                 GDBusMethodInvocation *invocation)
374 {
375         int ret = MESHD_ERROR_NONE;
376
377         MESH_LOGD("Not implemented yet !");
378         net_mesh_complete_is_joined(object, invocation, ret);
379
380         return TRUE;
381 }
382
383 static gboolean _meshd_dbus_handle_disjoin(NetMesh *object,
384                 GDBusMethodInvocation *invocation)
385 {
386         int ret = MESHD_ERROR_NONE;
387
388         MESH_LOGD("Not implemented yet !");
389         net_mesh_complete_disjoin(object, invocation, ret);
390
391         return TRUE;
392 }
393
394 static gboolean _meshd_dbus_handle_load_softap_settings(NetMesh *object,
395                 GDBusMethodInvocation *invocation)
396 {
397         int ret = MESHD_ERROR_NONE;
398
399         MESH_LOGD("Not implemented yet !");
400         net_mesh_complete_load_softap_settings(object, invocation, ret);
401
402         return TRUE;
403 }
404
405 static gboolean _meshd_dbus_handle_start_bridge(NetMesh *object,
406                 GDBusMethodInvocation *invocation,
407                 gint mode,
408                 gchar *bridge_interface,
409                 gpointer user_data)
410 {
411         int ret = MESHD_ERROR_NONE;
412
413         NOTUSED(user_data);
414
415         MESH_LOGD("Mode : %d", mode);
416         MESH_LOGD("Interface : %s", bridge_interface);
417         ret = mesh_request_create_bridge(bridge_interface, NULL, NULL);
418
419         net_mesh_complete_start_bridge(object, invocation, ret);
420
421         return TRUE;
422 }
423
424 static gboolean _meshd_dbus_handle_stop_bridge(NetMesh *object,
425                 GDBusMethodInvocation *invocation,
426                 gchar *bridge_interface,
427                 gpointer user_data)
428 {
429         int ret = MESHD_ERROR_NONE;
430
431         NOTUSED(user_data);
432
433         MESH_LOGD("Interface : %s", bridge_interface);
434         ret = mesh_request_remove_bridge(bridge_interface);
435
436         net_mesh_complete_stop_bridge(object, invocation, ret);
437
438         return TRUE;
439 }
440
441 static gboolean _meshd_dbus_handle_add_mesh_network(NetMesh *object,
442                 GDBusMethodInvocation *invocation,
443                 gchar *mesh_id, gint channel, gint security,
444                 gpointer user_data)
445 {
446         int ret = MESHD_ERROR_NONE;
447
448         NOTUSED(user_data);
449         NOTUSED(mesh_id);
450         NOTUSED(channel);
451         NOTUSED(security);
452
453         MESH_LOGD("Not implemented yet !");
454
455         net_mesh_complete_add_mesh_network(object, invocation, ret);
456
457         return TRUE;
458 }
459
460 static gboolean _meshd_dbus_handle_get_saved_mesh_network(NetMesh *object,
461                 GDBusMethodInvocation *invocation,
462                 gpointer user_data)
463 {
464         GVariant *variant = NULL;
465
466         NOTUSED(user_data);
467
468         MESH_LOGD("Not implemented yet !");
469
470         net_mesh_complete_get_saved_mesh_network(object, invocation, variant);
471
472         return TRUE;
473 }
474
475 static gboolean _meshd_dbus_handle_select_saved_mesh_network(NetMesh *object,
476                 GDBusMethodInvocation *invocation,
477                 gchar *mesh_id, gint channel, gint security,
478                 gpointer user_data)
479 {
480         int ret = MESHD_ERROR_NONE;
481
482         NOTUSED(user_data);
483         NOTUSED(mesh_id);
484         NOTUSED(channel);
485         NOTUSED(security);
486
487         MESH_LOGD("Not implemented yet !");
488
489         net_mesh_complete_select_saved_mesh_network(object, invocation, ret);
490
491         return TRUE;
492 }
493
494 static gboolean _meshd_dbus_handle_forget_saved_mesh_network(NetMesh *object,
495                 GDBusMethodInvocation *invocation,
496                 gchar *mesh_id, gint channel, gint security,
497                 gpointer user_data)
498 {
499         int ret = MESHD_ERROR_NONE;
500
501         NOTUSED(user_data);
502         NOTUSED(mesh_id);
503         NOTUSED(channel);
504         NOTUSED(security);
505
506         MESH_LOGD("Not implemented yet !");
507
508         net_mesh_complete_forget_saved_mesh_network(object, invocation, ret);
509
510         return TRUE;
511 }
512
513
514
515 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
516                 gpointer user_data)
517 {
518         gboolean ret;
519         GError *error = NULL;
520         mesh_service *service = (mesh_service *)user_data;
521
522         NOTUSED(name);
523
524         meshd_dbus_object = net_mesh_skeleton_new();
525         if (NULL == meshd_dbus_object) {
526                 MESH_LOGE("net_mesh_skeleton_new() Fail");
527                 return;
528         }
529
530         g_signal_connect(meshd_dbus_object, "handle-enable",
531                         G_CALLBACK(_meshd_dbus_handle_enable), service);
532         g_signal_connect(meshd_dbus_object, "handle-disable",
533                         G_CALLBACK(_meshd_dbus_handle_disable), service);
534         g_signal_connect(meshd_dbus_object, "handle-set-mesh-gate",
535                         G_CALLBACK(_meshd_dbus_handle_set_mesh_gate), service);
536         g_signal_connect(meshd_dbus_object, "handle-set-mesh-softap",
537                         G_CALLBACK(_meshd_dbus_handle_set_mesh_softap), service);
538         g_signal_connect(meshd_dbus_object, "handle-scan",
539                         G_CALLBACK(_meshd_dbus_handle_scan), service);
540         g_signal_connect(meshd_dbus_object, "handle-specific-scan",
541                         G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
542         g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
543                         G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
544         g_signal_connect(meshd_dbus_object, "handle-get-station-info",
545                         G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
546         g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
547                         G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
548         g_signal_connect(meshd_dbus_object, "handle-join",
549                         G_CALLBACK(_meshd_dbus_handle_join), service);
550         g_signal_connect(meshd_dbus_object, "handle-is-joined",
551                         G_CALLBACK(_meshd_dbus_handle_is_joined), service);
552         g_signal_connect(meshd_dbus_object, "handle-disjoin",
553                         G_CALLBACK(_meshd_dbus_handle_disjoin), service);
554         g_signal_connect(meshd_dbus_object, "handle-load-softap-settings",
555                         G_CALLBACK(_meshd_dbus_handle_load_softap_settings), service);
556         g_signal_connect(meshd_dbus_object, "handle-start-bridge",
557                         G_CALLBACK(_meshd_dbus_handle_start_bridge), service);
558         g_signal_connect(meshd_dbus_object, "handle-stop-bridge",
559                         G_CALLBACK(_meshd_dbus_handle_stop_bridge), service);
560
561         g_signal_connect(meshd_dbus_object, "handle-add-mesh-network",
562                         G_CALLBACK(_meshd_dbus_handle_add_mesh_network), service);
563         g_signal_connect(meshd_dbus_object, "handle-get-saved-mesh-network",
564                         G_CALLBACK(_meshd_dbus_handle_get_saved_mesh_network), service);
565         g_signal_connect(meshd_dbus_object, "handle-select-saved-mesh-network",
566                         G_CALLBACK(_meshd_dbus_handle_select_saved_mesh_network), service);
567         g_signal_connect(meshd_dbus_object, "handle-forget-saved-mesh-network",
568                         G_CALLBACK(_meshd_dbus_handle_forget_saved_mesh_network), service);
569
570         ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
571                         conn, MESH_DBUS_OBJPATH, &error);
572         if (FALSE == ret) {
573                 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
574                 g_error_free(error);
575         }
576
577         ret = _meshd_dbus_subscribe_name_owner_changed(conn);
578         if (MESHD_ERROR_NONE != ret) {
579                 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
580                 return;
581         }
582 }
583
584 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
585                 gpointer user_data)
586 {
587         NOTUSED(conn);
588         NOTUSED(user_data);
589
590         MESH_LOGD("Lost the name %s", name);
591 }
592
593 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
594                 gpointer user_data)
595 {
596         NOTUSED(conn);
597         NOTUSED(user_data);
598
599         MESH_LOGD("Acquired the name %s", name);
600 }
601
602 static gboolean _meshd_dbus_interface_init(mesh_service *service)
603 {
604         guint id;
605         meshd_check_null_ret_error("service", service, FALSE);
606
607         id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
608                         MESH_DBUS_INTERFACE,
609                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
610                         _meshd_dbus_on_bus_acquired,
611                         _meshd_dbus_on_name_acquired,
612                         _meshd_dbus_on_name_lost,
613                         service,
614                         NULL);
615         if (0 == id) {
616                 MESH_LOGE("g_bus_own_name() Fail");
617                 return FALSE;
618         }
619
620         service->dbus_id = id;
621         service->interface_info = g_new0(mesh_interface_s, 1);
622
623         return TRUE;
624 }
625
626 static void _meshd_dbus_deinit(mesh_service *service)
627 {
628         mesh_interface_s *info = NULL;
629         meshd_check_null_ret("service", service);
630
631         g_bus_unown_name(service->dbus_id);
632
633         info = service->interface_info;
634         meshd_check_null_ret("info", info);
635         if (info->bridge_interface)
636                 g_free(info->bridge_interface);
637         if (info->base_interface)
638                 g_free(info->base_interface);
639         if (info->mesh_interface)
640                 g_free(info->mesh_interface);
641         if (info->softap_interface)
642                 g_free(info->softap_interface);
643         if (info->external_interface)
644                 g_free(info->external_interface);
645
646         g_free(service->interface_info);
647         service->interface_info = NULL;
648 }
649
650  /**< mesh service interface initialization */
651 gboolean meshd_service_interface_init(mesh_service *service)
652 {
653         guint ret;
654         meshd_check_null_ret_error("service", service, FALSE);
655
656         /* Initialize dbus interface */
657         ret = _meshd_dbus_interface_init(service);
658         if (FALSE == ret) {
659                 MESH_LOGE("zigbee_service_dbus_interface_init failed!!!");
660                 return FALSE;
661         }
662
663         return TRUE;
664 }
665
666 /**< Zigbee service interface de-initialization */
667 void meshd_service_interface_deinit(mesh_service *service)
668 {
669         meshd_check_null_ret("service", service);
670
671         /* De-initialize dbus interface */
672         _meshd_dbus_deinit(service);
673 }