Add mesh join/left event handler
[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 #include <string.h>
21
22 #include <glib.h>
23 #include <gio/gio.h>
24
25 #include "mesh.h"
26 #include "mesh-log.h"
27 #include "mesh-util.h"
28 #include "mesh-service.h"
29 #include "mesh-service-interface.h"
30 #include "mesh-generated-code.h"
31
32 #include "mesh-request.h"
33 #include "mesh-interface.h"
34
35 static NetMesh *meshd_dbus_object;
36
37 /* global list to care resource handle for each client */
38 static GList *meshd_dbus_client_list;
39 static GMutex meshd_dbus_client_list_mutex;
40
41 typedef struct _meshd_dbus_client_s {
42         gchar *bus_name;
43 } meshd_dbus_client_s;
44
45 NetMesh* meshd_dbus_get_object()
46 {
47         return meshd_dbus_object;
48 }
49
50 int64_t meshd_dbus_generate_signal_number()
51 {
52         static int64_t i = 0;
53
54         return i++;
55 }
56
57 static int _meshd_dbus_client_list_cleanup(GList *client_list)
58 {
59         meshd_dbus_client_s *client;
60
61         meshd_check_null_ret_error("client_list", client_list, FALSE);
62
63         client = client_list->data;
64
65         free(client->bus_name);
66         client->bus_name = NULL;
67         free(client);
68         g_list_free(client_list);
69
70         return MESHD_ERROR_NONE;
71 }
72
73 static int _meshd_dbus_client_list_compare_bus_name(const void *a, const void *b)
74 {
75         const meshd_dbus_client_s *client = a;
76
77         return g_strcmp0(client->bus_name, b);
78 }
79
80 static inline GList* _meshd_dbus_client_list_find_client(const gchar *owner)
81 {
82         return g_list_find_custom(meshd_dbus_client_list, owner,
83                         _meshd_dbus_client_list_compare_bus_name);
84 }
85
86 static void _meshd_dbus_name_owner_changed_cb(GDBusConnection *conn,
87                 const gchar *sender_name,
88                 const gchar *object_path,
89                 const gchar *interface_name,
90                 const gchar *signal_name,
91                 GVariant *parameters,
92                 gpointer user_data)
93 {
94         int ret;
95         GList *client = NULL;
96         gchar *name, *old_owner, *new_owner;
97
98         NOTUSED(conn);
99         NOTUSED(sender_name);
100         NOTUSED(object_path);
101         NOTUSED(interface_name);
102         NOTUSED(signal_name);
103         NOTUSED(user_data);
104
105         g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
106
107         if (0 == strlen(new_owner)) {
108                 g_mutex_lock(&meshd_dbus_client_list_mutex);
109                 client = _meshd_dbus_client_list_find_client(old_owner);
110                 if (client) { /* found bus name in our bus list */
111                         MESH_LOGD("bus(%s) stopped", old_owner);
112                         meshd_dbus_client_list = g_list_remove_link(meshd_dbus_client_list, client);
113                 }
114                 g_mutex_unlock(&meshd_dbus_client_list_mutex);
115
116                 if (client) {
117                         ret = _meshd_dbus_client_list_cleanup(client);
118                         if (MESHD_ERROR_NONE != ret)
119                                 MESH_LOGE("_meshd_dbus_client_list_cleanup() Fail(%d)", ret);
120                 }
121         }
122 }
123
124 static int _meshd_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
125 {
126         unsigned int id;
127
128         id = g_dbus_connection_signal_subscribe(conn,
129                         "org.freedesktop.DBus", /* bus name */
130                         "org.freedesktop.DBus", /* interface */
131                         "NameOwnerChanged", /* member */
132                         "/org/freedesktop/DBus", /* path */
133                         NULL, /* arg0 */
134                         G_DBUS_SIGNAL_FLAGS_NONE,
135                         _meshd_dbus_name_owner_changed_cb,
136                         NULL,
137                         NULL);
138         if (0 == id) {
139                 MESH_LOGE("g_dbus_connection_signal_subscribe() Fail");
140                 return MESHD_ERROR_IO_ERROR;
141         }
142
143         return MESHD_ERROR_NONE;
144 }
145
146 static gboolean _meshd_dbus_handle_enable(NetMesh *object,
147                 GDBusMethodInvocation *invocation,
148                 gpointer user_data)
149 {
150         int ret = MESHD_ERROR_NONE;
151         mesh_service *service = (mesh_service *)user_data;
152         mesh_interface_s *info = service->interface_info;
153
154         if (service->mesh_activated) {
155                 /* Already activated */
156                 net_mesh_complete_enable(object, invocation,
157                                 MESHD_ERROR_OPERATION_FAILED);
158         } else {
159                 /* Do API response first */
160                 net_mesh_complete_enable(object, invocation, ret);
161                 service->mesh_activated = TRUE;
162         }
163
164         meshd_check_null_ret_error("info", info, FALSE);
165
166         /* Register event handler first */
167         ret = mesh_request_register_event_handler();
168         if (MESHD_ERROR_NONE != ret) {
169                 MESH_LOGE("Failed to register mesh event handler !! [%d]", ret);
170         }
171
172         ret = mesh_interface_initialize(service->interface_info);
173         if (MESHD_ERROR_NONE != ret) {
174                 MESH_LOGE("Failed to mesh_interface_initialize [%d]", ret);
175                 goto FINISH;
176         }
177
178 FINISH:
179         net_mesh_emit_mesh_enabled(object, ret);
180
181         return TRUE;
182 }
183
184 static gboolean _meshd_dbus_handle_disable(NetMesh *object,
185                 GDBusMethodInvocation *invocation,
186                 gpointer user_data)
187 {
188         int ret = MESHD_ERROR_NONE;
189         mesh_service *service = (mesh_service *)user_data;
190         mesh_interface_s *info = service->interface_info;
191
192         meshd_check_null_ret_error("info", info, FALSE);
193
194         /* Make response first */
195         net_mesh_complete_disable(object, invocation, ret);
196
197         ret = mesh_request_unregister_event_handler();
198         if (MESHD_ERROR_NONE != ret) {
199                 MESH_LOGE("Failed to unregister mesh event handler !! [%d]", ret);
200         }
201
202         /* Terminate daemon */
203         meshd_service_exit(service);
204
205         return TRUE;
206 }
207
208 static gboolean _meshd_dbus_handle_scan(NetMesh *object,
209                 GDBusMethodInvocation *invocation,
210                 gpointer user_data)
211 {
212         int ret = MESHD_ERROR_NONE;
213         mesh_service *service = (mesh_service *)user_data;
214         mesh_interface_s *info = service->interface_info;
215
216         meshd_check_null_ret_error("info", info, FALSE);
217
218         ret = mesh_request_scan(info->mesh_interface);
219         if (MESHD_ERROR_NONE != ret) {
220                 MESH_LOGE("Failed to mesh_request_scan on mesh interface[%s] !",
221                                 info->mesh_interface);
222         }
223
224         /* Fall-back */
225         if (MESHD_ERROR_IN_PROGRESS != ret) {
226                 ret = mesh_request_scan(info->base_interface);
227                 if (MESHD_ERROR_NONE != ret)
228                         MESH_LOGE("Failed to mesh_request_scan on base interface[%s] !",
229                                         info->base_interface);
230         }
231
232         net_mesh_complete_scan(object, invocation, ret);
233
234         return TRUE;
235 }
236
237 static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
238                 GDBusMethodInvocation *invocation,
239                 gchar *mesh_id,
240                 gint channel,
241                 gpointer user_data)
242 {
243         int ret = MESHD_ERROR_NONE;
244         mesh_service *service = (mesh_service *)user_data;
245         mesh_interface_s *info = service->interface_info;
246
247         meshd_check_null_ret_error("info", info, FALSE);
248
249         ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel);
250         if (MESHD_ERROR_NONE != ret) {
251                 MESH_LOGE("Failed to mesh_request_specific_scan on mesh interface[%s]",
252                                 info->mesh_interface);
253         }
254
255         /* Fall-back */
256         if (MESHD_ERROR_IN_PROGRESS != ret) {
257                 ret = mesh_request_specific_scan(info->base_interface, mesh_id, channel);
258                 if (MESHD_ERROR_NONE != ret)
259                         MESH_LOGE("Failed to mesh_request_specific_scan on base interface[%s]",
260                                         info->base_interface);
261         }
262
263         net_mesh_complete_specific_scan(object, invocation, ret);
264
265         return TRUE;
266 }
267
268 static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
269                 GDBusMethodInvocation *invocation,
270                 gpointer user_data)
271 {
272         int ret = MESHD_ERROR_NONE;
273         mesh_service *service = (mesh_service *)user_data;
274         mesh_interface_s *info = service->interface_info;
275
276         ret = mesh_request_cancel_scan(info->mesh_interface);
277         if (MESHD_ERROR_NONE != ret) {
278                 MESH_LOGE("Failed to mesh_request_cancel_scan");
279         }
280
281         net_mesh_complete_cancel_scan(object, invocation, ret);
282
283         return TRUE;
284 }
285
286 static void _on_scan_result_destroy(gpointer data)
287 {
288         mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data;
289
290         if (scan_item) {
291                 g_free(scan_item->mesh_id);
292                 g_free(scan_item->bssid);
293         }
294 }
295
296 static void _on_station_list_destroy(gpointer data)
297 {
298         mesh_station_info_s *info = (mesh_station_info_s*)data;
299
300         if (info) {
301                 g_free(info->bssid);
302                 g_free(info);
303         }
304 }
305
306 static void _on_mpath_list_destroy(gpointer data)
307 {
308         mesh_mpath_info_s *info = (mesh_mpath_info_s*)data;
309
310         if (info) {
311                 g_free(info->dest_addr);
312                 g_free(info->next_hop);
313                 g_free(info->interface);
314                 g_free(info);
315         }
316 }
317
318 static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object,
319                 GDBusMethodInvocation *invocation,
320                 gpointer user_data)
321 {
322         int ret = MESHD_ERROR_NONE;
323         mesh_service *service = (mesh_service *)user_data;
324         mesh_interface_s *info = service->interface_info;
325
326         GVariantBuilder builder;
327         GVariant* networks;
328         GList *iter = NULL;
329         mesh_scan_result_s *scan_item = NULL;
330
331         MESH_LOGD("Request to get scanned mesh network list");
332
333         ret = mesh_request_get_scan_result(info->mesh_interface, &service->scanned_mesh_network);
334         if (MESHD_ERROR_NONE != ret) {
335                 MESH_LOGE("Failed to mesh_request_get_scan_result");
336
337                 /* Fall-back */
338                 ret = mesh_request_get_scan_result(info->base_interface,
339                                 &service->scanned_mesh_network);
340                 if (MESHD_ERROR_NONE != ret) {
341                         MESH_LOGE("Failed to mesh_request_get_scan_result on base interface[%s]",
342                                         info->base_interface);
343
344                         g_dbus_method_invocation_return_error(invocation,
345                                         G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
346                 }
347         }
348
349         g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
350
351         iter = service->scanned_mesh_network;
352         while (iter != NULL) {
353                 scan_item = (mesh_scan_result_s*)iter->data;
354
355                 g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
356                 g_variant_builder_add(&builder, "{sv}", "mesh_id",
357                                 g_variant_new_string(scan_item->mesh_id));
358                 g_variant_builder_add(&builder, "{sv}", "bssid",
359                                 g_variant_new_string(scan_item->bssid));
360                 g_variant_builder_add(&builder, "{sv}", "rssi",
361                                 g_variant_new_int32(scan_item->rssi));
362                 g_variant_builder_add(&builder, "{sv}", "channel",
363                                 g_variant_new_uint32(scan_item->channel));
364                 g_variant_builder_close(&builder);
365
366                 iter = g_list_next(iter);
367         }
368
369         /* Clear scan list */
370         g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
371         service->scanned_mesh_network = NULL;
372
373         networks = g_variant_builder_end(&builder);
374         net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
375
376         return TRUE;
377 }
378
379 static gboolean _meshd_dbus_handle_enable_mesh(NetMesh *object,
380                 GDBusMethodInvocation *invocation,
381                 gpointer user_data)
382 {
383         int ret = MESHD_ERROR_NONE;
384         mesh_service *service = (mesh_service *)user_data;
385         mesh_interface_s *info = service->interface_info;
386
387         /* Create or join mesh network and create bridge */
388         ret = mesh_request_enable_mesh(info->base_interface, info->mesh_interface);
389         if (MESHD_ERROR_NONE != ret) {
390                 MESH_LOGE("Failed to mesh_request_enable_mesh [%d]", ret);
391                 goto FINISH;
392         }
393
394         ret = mesh_request_create_bridge(info->bridge_interface, info->mesh_interface);
395         if (MESHD_ERROR_NONE != ret) {
396                 MESH_LOGE("Failed to mesh_request_create_bridge [%d]", ret);
397                 goto FINISH;
398         }
399
400
401         ret = mesh_request_join_mesh(info->mesh_interface,
402                         service->saved_mesh_network, &service->joined_network);
403         if (MESHD_ERROR_NONE != ret) {
404                 MESH_LOGE("Failed to mesh_request_join_mesh [%d]", ret);
405                 goto FINISH;
406         }
407
408         /* Detect external network state (i.e. Ethernet)
409                         and decide to make gate enabled */
410         ret = mesh_request_set_mesh_gate(info->bridge_interface,
411                         info->mesh_interface, info->external_interface);
412         if (MESHD_ERROR_NONE != ret) {
413                 MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
414         }
415
416 #if 0
417         /* TODO: Check if specific scan is required */
418         ret = mesh_request_specific_scan(info->mesh_interface,
419                         info->mesh_id, info->mesh_channel);
420         if (MESHD_ERROR_NONE != ret) {
421                 MESH_LOGE("Failed to mesh_request_specific_scan [%d]", ret);
422         }
423         ret = mesh_request_get_scan_result(info->mesh_interface,
424                         &service->scanned_mesh_network);
425 #endif
426
427         /* Request DHCP on bridge interface */
428         ret = mesh_request_dhcp(info->bridge_interface);
429         if (MESHD_ERROR_NONE != ret) {
430                 MESH_LOGE("Failed to mesh_request_dhcp [%d]", ret);
431         }
432
433         /* TODO: Notify bridge status to Connman */
434
435 FINISH:
436         net_mesh_complete_enable_mesh(object, invocation, ret);
437
438         return TRUE;
439 }
440
441 static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object,
442                 GDBusMethodInvocation *invocation,
443                 gpointer user_data)
444 {
445         int ret = MESHD_ERROR_NONE;
446         mesh_service *service = (mesh_service *)user_data;
447         mesh_interface_s *info = service->interface_info;
448
449         meshd_check_null_ret_error("info", info, FALSE);
450
451         /* Destroy bridge and return from mesh to infra mode */
452         if (service->joined_network) {
453                 g_free(service->joined_network->mesh_id);
454                 g_free(service->joined_network);
455                 service->joined_network = NULL;
456         }
457
458         if (FALSE == service->mesh_activated) {
459                 MESH_LOGD("Mesh network is not activated yet");
460                 ret = MESHD_ERROR_OPERATION_FAILED;
461                 net_mesh_complete_disable_mesh(object, invocation, ret);
462                 return TRUE;
463         }
464
465         ret = mesh_request_disable_mesh(info->mesh_interface);
466         if (MESHD_ERROR_NONE != ret) {
467                 MESH_LOGE("Failed to mesh_request_disable_mesh_gate");
468         }
469
470         ret = mesh_request_remove_bridge(info->bridge_interface);
471         if (MESHD_ERROR_NONE != ret) {
472                 MESH_LOGE("Failed to mesh_request_remove_bridge");
473         }
474
475         /* Make response */
476         net_mesh_complete_disable_mesh(object, invocation, ret);
477
478         /* Make notification */
479         mesh_notify_left_network();
480
481         return TRUE;
482 }
483
484 static gboolean _meshd_dbus_handle_get_joined_mesh_network(NetMesh *object,
485                 GDBusMethodInvocation *invocation,
486                 gpointer user_data)
487 {
488         int ret = MESHD_ERROR_NONE;
489         mesh_service *service = (mesh_service *)user_data;
490         mesh_network_info_s *joined = service->joined_network;
491
492         //gchar *meshid = strdup("meshnet");
493         //gchar *bssid = strdup("7c:dd:90:d8:2a:64");
494         //gint channel = 161;
495         //gint max_speed = 866;
496
497         if (joined) {
498                 net_mesh_complete_get_joined_mesh_network(object, invocation,
499                         joined->mesh_id, joined->bssid, joined->channel, ret);
500         } else {
501                 net_mesh_complete_get_joined_mesh_network(object, invocation,
502                         "", "", 0, MESHD_ERROR_NO_DATA);
503         }
504
505         return TRUE;
506 }
507
508 static gboolean _meshd_dbus_handle_set_gate(NetMesh *object,
509                 GDBusMethodInvocation *invocation, gboolean stp, gboolean gate_announce,
510                 gpointer user_data)
511 {
512         int ret = MESHD_ERROR_NONE;
513         mesh_service *service = (mesh_service *)user_data;
514         mesh_interface_s *info = service->interface_info;
515
516         MESH_LOGD("STP = %d", stp);
517         MESH_LOGD("gate_announce = %d", gate_announce);
518
519         /* Set STP and gate_announce */
520         ret = mesh_request_set_mesh_gate(info->bridge_interface,
521                         info->mesh_interface, info->external_interface);
522         if (MESHD_ERROR_NONE != ret) {
523                 MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
524         }
525
526         net_mesh_complete_set_gate(object, invocation, ret);
527
528         return TRUE;
529 }
530
531 static gboolean _meshd_dbus_handle_unset_gate(NetMesh *object,
532                 GDBusMethodInvocation *invocation,
533                 gpointer user_data)
534 {
535         int ret = MESHD_ERROR_NONE;
536         mesh_service *service = (mesh_service *)user_data;
537         mesh_interface_s *info = service->interface_info;
538
539         ret = mesh_request_unset_mesh_gate(info->bridge_interface,
540                         info->mesh_interface, info->external_interface);
541         if (MESHD_ERROR_NONE != ret) {
542                 MESH_LOGE("Failed to mesh_request_unset_mesh_gate [%d]", ret);
543         }
544         net_mesh_complete_unset_gate(object, invocation, ret);
545
546         return TRUE;
547 }
548
549 static gboolean _meshd_dbus_handle_set_softap(NetMesh *object,
550                 GDBusMethodInvocation *invocation, gchar *ssid, gchar *key,
551                 gchar *mode, gint channel, gint visibility, gint max_sta,
552                 gint security, gchar *passphrase, gpointer user_data)
553 {
554         int ret = MESHD_ERROR_NONE;
555         mesh_service *service = (mesh_service *)user_data;
556         mesh_interface_s *info = service->interface_info;
557
558         MESH_LOGD("SSID      : %s", ssid);
559         MESH_LOGD("key       : %s", key);
560         MESH_LOGD("mode      : %s", mode);
561         MESH_LOGD("channel   : %d", channel);
562         MESH_LOGD("visibility: %d", visibility);
563         MESH_LOGD("max_sta   : %d", max_sta);
564         MESH_LOGD("security  : %d", security);
565
566         /* Save softAP information */
567         ret = mesh_request_set_softap_config(info->softap_interface,
568                 ssid, mode, channel, visibility, max_sta,
569                 security, passphrase);
570         if (MESHD_ERROR_NONE != ret) {
571                 MESH_LOGE("Failed to mesh_request_set_softap_config [%d]", ret);
572         }
573
574         net_mesh_complete_set_softap(object, invocation, ret);
575
576         return TRUE;
577 }
578
579 static gboolean _meshd_dbus_handle_enable_softap(NetMesh *object,
580                 GDBusMethodInvocation *invocation, gpointer user_data)
581 {
582         int ret = MESHD_ERROR_NONE;
583         mesh_service *service = (mesh_service *)user_data;
584         mesh_interface_s *info = service->interface_info;
585
586         /* Check softAP interface and execute it */
587         ret = mesh_request_enable_softap(info->bridge_interface, info->softap_interface);
588         if (MESHD_ERROR_NONE != ret) {
589                 MESH_LOGE("Failed to mesh_request_enable_softap [%d]", ret);
590         }
591
592         net_mesh_complete_enable_softap(object, invocation, ret);
593
594         return TRUE;
595 }
596
597 static gboolean _meshd_dbus_handle_disable_softap(NetMesh *object,
598                 GDBusMethodInvocation *invocation, gpointer user_data)
599 {
600         int ret = MESHD_ERROR_NONE;
601         mesh_service *service = (mesh_service *)user_data;
602         mesh_interface_s *info = service->interface_info;
603
604         /* Destroy softAP */
605         ret = mesh_request_disable_softap(info->bridge_interface, info->softap_interface);
606         if (MESHD_ERROR_NONE != ret) {
607                 MESH_LOGE("Failed to mesh_request_disable_softap [%d]", ret);
608         }
609
610         net_mesh_complete_disable_softap(object, invocation, ret);
611
612         return TRUE;
613 }
614
615 static gboolean _meshd_dbus_handle_add_mesh_network(NetMesh *object,
616                 GDBusMethodInvocation *invocation,
617                 gchar *mesh_id, gint channel, gint security,
618                 gpointer user_data)
619 {
620         int ret = MESHD_ERROR_NONE;
621         mesh_service *service = (mesh_service *)user_data;
622
623         ret = mesh_request_add_mesh_network(&service->saved_mesh_network,
624                         mesh_id, channel, security);
625
626         net_mesh_complete_add_mesh_network(object, invocation, ret);
627
628         return TRUE;
629 }
630
631 static gboolean _meshd_dbus_handle_get_saved_mesh_network(NetMesh *object,
632                 GDBusMethodInvocation *invocation,
633                 gpointer user_data)
634 {
635         int ret = MESHD_ERROR_NONE;
636         mesh_service *service = (mesh_service *)user_data;
637
638         GVariantBuilder builder;
639         GVariant* networks;
640         GList *iter = NULL;
641
642         ret = mesh_request_get_saved_mesh_network(&service->saved_mesh_network);
643         if (MESHD_ERROR_NONE != ret) {
644                 MESH_LOGE("Failed to mesh_request_get_saved_mesh_network");
645
646                 g_dbus_method_invocation_return_error(invocation,
647                                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
648         } else {
649                 /* TODO: Get station information and make variant data */
650                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
651
652                 iter = service->saved_mesh_network;
653                 while (iter != NULL) {
654                         mesh_network_info_s *item = (mesh_network_info_s*)iter->data;
655
656                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
657                         g_variant_builder_add(&builder, "{sv}", "mesh_id",
658                                         g_variant_new_string(item->mesh_id));
659                         g_variant_builder_add(&builder, "{sv}", "channel",
660                                         g_variant_new_uint32(item->channel));
661                         g_variant_builder_add(&builder, "{sv}", "security",
662                                         g_variant_new_uint32(item->security));
663                         g_variant_builder_close(&builder);
664
665                         iter = g_list_next(iter);
666                 }
667
668                 networks = g_variant_builder_end(&builder);
669                 net_mesh_complete_get_saved_mesh_network(object, invocation, networks, ret);
670         }
671
672         return TRUE;
673 }
674
675 static gboolean _meshd_dbus_handle_select_saved_mesh_network(NetMesh *object,
676                 GDBusMethodInvocation *invocation,
677                 gchar *mesh_id, gint channel, gint security,
678                 gpointer user_data)
679 {
680         int ret = MESHD_ERROR_NONE;
681         mesh_service *service = (mesh_service *)user_data;
682
683         ret = mesh_request_select_saved_mesh_network(&service->saved_mesh_network,
684                         mesh_id, channel, security);
685
686         net_mesh_complete_select_saved_mesh_network(object, invocation, ret);
687
688         return TRUE;
689 }
690
691 static gboolean _meshd_dbus_handle_forget_saved_mesh_network(NetMesh *object,
692                 GDBusMethodInvocation *invocation,
693                 gchar *mesh_id, gint channel, gint security,
694                 gpointer user_data)
695 {
696         int ret = MESHD_ERROR_NONE;
697         mesh_service *service = (mesh_service *)user_data;
698
699         ret = mesh_request_forget_saved_mesh_network(&service->saved_mesh_network,
700                         mesh_id, channel, security);
701
702         net_mesh_complete_forget_saved_mesh_network(object, invocation, ret);
703
704         return TRUE;
705 }
706
707 static gboolean _meshd_dbus_handle_set_interfaces(NetMesh *object,
708                 GDBusMethodInvocation *invocation,
709                 gchar *mesh, gchar *gate, gchar *softap,
710                 gpointer user_data)
711 {
712         int ret = MESHD_ERROR_NONE;
713         mesh_service *service = (mesh_service *)user_data;
714         mesh_interface_s *info = service->interface_info;
715
716         g_free(info->mesh_interface);
717         info->mesh_interface = g_strdup(mesh);
718
719         g_free(info->external_interface);
720         info->external_interface = g_strdup(gate);
721
722         g_free(info->softap_interface);
723         info->softap_interface = g_strdup(softap);
724
725         net_mesh_complete_set_interfaces(object, invocation, ret);
726
727         return TRUE;
728 }
729
730 static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
731                 GDBusMethodInvocation *invocation,
732                 gpointer user_data)
733 {
734         int ret = MESHD_ERROR_NONE;
735
736         GVariantBuilder builder;
737         GVariant* station;
738         GList *iter = NULL;
739
740         mesh_service *service = (mesh_service *)user_data;
741         mesh_interface_s *info = service->interface_info;
742
743         /* Clear mesh station list */
744         g_list_free_full(service->station_list, _on_station_list_destroy);
745         service->station_list = NULL;
746
747         ret = mesh_request_get_station_info(
748                                 info->mesh_interface, &service->station_list);
749         if (MESHD_ERROR_NONE != ret) {
750                 MESH_LOGE("Failed to mesh_request_get_station_info");
751
752                 g_dbus_method_invocation_return_error(invocation,
753                                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
754         } else {
755         /*
756          * sh-3.2#  iw mesh0 station dump
757          * Station 7c:dd:90:62:37:cf (on mesh0)
758          * inactive time:       1685 ms
759          * rx bytes:    34174
760          * rx packets:  1181
761          * tx bytes:    6877
762          * tx packets:  76
763          * tx retries:  0
764          * tx failed:   0
765          * beacon loss: 0
766          * signal:      -64 dBm
767          * signal avg:  -63 dBm
768          * tx bitrate:  54.0 MBit/s
769          * rx bitrate:  5.5 MBit/s
770          * mesh llid:   51731
771          * mesh plid:   35432
772          * mesh plink:  ESTAB
773          * mesh local PS mode:  ACTIVE
774          * mesh peer PS mode:   ACTIVE
775          * mesh non-peer PS mode:       ACTIVE
776          * authorized:  yes
777          * authenticated:       yes
778          * associated:  yes
779          * preamble:    long
780          * WMM/WME:     yes
781          * MFP:         no
782          * TDLS peer:   no
783          * DTIM period: 0
784          * beacon interval:1000
785          * short slot time:yes
786          * connected time:      256 seconds
787          */
788                 /* Get station information and make variant data */
789                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
790
791                 iter = service->station_list;
792                 while (iter != NULL) {
793                         mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
794
795                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
796                         g_variant_builder_add(&builder, "{sv}", "bssid",
797                                                 g_variant_new_string(item->bssid));
798                         g_variant_builder_add(&builder, "{sv}", "inactive_time",
799                                                 g_variant_new_uint32(item->inactive_time));
800                         g_variant_builder_add(&builder, "{sv}", "rx_bytes",
801                                                 g_variant_new_uint64(item->rx_bytes));
802                         g_variant_builder_add(&builder, "{sv}", "rx_packets",
803                                                 g_variant_new_uint32(item->rx_packets));
804                         g_variant_builder_add(&builder, "{sv}", "tx_bytes",
805                                                 g_variant_new_uint64(item->tx_bytes));
806                         g_variant_builder_add(&builder, "{sv}", "tx_packets",
807                                                 g_variant_new_uint32(item->tx_packets));
808                         g_variant_builder_add(&builder, "{sv}", "tx_retries",
809                                                 g_variant_new_uint32(item->tx_retries));
810                         g_variant_builder_add(&builder, "{sv}", "tx_failed",
811                                                 g_variant_new_uint32(item->tx_failed));
812                         g_variant_builder_add(&builder, "{sv}", "beacon_loss",
813                                                 g_variant_new_uint32(item->beacon_loss));
814                         g_variant_builder_add(&builder, "{sv}", "signal",
815                                                 g_variant_new_int32(item->rssi));
816                         g_variant_builder_add(&builder, "{sv}", "signal_avg",
817                                                 g_variant_new_int32(item->rssi_avg));
818                         g_variant_builder_add(&builder, "{sv}", "tx_bitrate",
819                                                 g_variant_new_uint32(item->tx_bitrate)); /* 10 times */
820                         g_variant_builder_add(&builder, "{sv}", "rx_bitrate",
821                                                 g_variant_new_uint32(item->rx_bitrate)); /* 10 times */
822                         g_variant_builder_add(&builder, "{sv}", "mesh_llid",
823                                                 g_variant_new_uint16(item->llid));
824                         g_variant_builder_add(&builder, "{sv}", "mesh_plid",
825                                                 g_variant_new_uint16(item->plid));
826                         g_variant_builder_add(&builder, "{sv}", "mesh_plink",
827                                                 g_variant_new_byte(item->mesh_plink)); /* 0 : DISCON, 1 : ESTAB */
828                         g_variant_builder_add(&builder, "{sv}", "local_ps_mode",
829                                                 g_variant_new_uint32(item->local_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
830                         g_variant_builder_add(&builder, "{sv}", "peer_ps_mode",
831                                                 g_variant_new_uint32(item->peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
832                         g_variant_builder_add(&builder, "{sv}", "non_peer_ps_mode",
833                                                 g_variant_new_uint32(item->non_peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
834                         g_variant_builder_add(&builder, "{sv}", "authorized",
835                                                 g_variant_new_boolean(item->authorized));
836                         g_variant_builder_add(&builder, "{sv}", "associated",
837                                                 g_variant_new_boolean(item->associated));
838                         g_variant_builder_add(&builder, "{sv}", "preamble",
839                                                 g_variant_new_boolean(item->preamble));
840                         g_variant_builder_add(&builder, "{sv}", "WMM_WME",
841                                                 g_variant_new_boolean(item->wme));
842                         g_variant_builder_add(&builder, "{sv}", "MFP",
843                                                 g_variant_new_boolean(item->mfp));
844                         g_variant_builder_add(&builder, "{sv}", "TDLS_peer",
845                                                 g_variant_new_boolean(item->tdls_peer));
846                         g_variant_builder_add(&builder, "{sv}", "DTIM_period",
847                                                 g_variant_new_byte(item->dtim_period));
848                         g_variant_builder_add(&builder, "{sv}", "beacon_interval",
849                                                 g_variant_new_uint16(item->beacon_interval));
850                         g_variant_builder_add(&builder, "{sv}", "short_slot_time",
851                                                 g_variant_new_boolean(item->short_slot_time));
852                         g_variant_builder_add(&builder, "{sv}", "connected_time",
853                                                 g_variant_new_uint32(item->connected_time));
854                         g_variant_builder_close(&builder);
855
856                         iter = g_list_next(iter);
857                 }
858
859                 station = g_variant_builder_end(&builder);
860                 net_mesh_complete_get_saved_mesh_network(object, invocation, station, ret);
861
862                 g_object_unref(station);
863         }
864
865 #if 0
866         g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
867         g_variant_builder_add(&builder, "{sv}", "station", g_variant_new_string("7c:dd:90:62:37:cf"));
868         g_variant_builder_add(&builder, "{sv}", "inactive_time", g_variant_new_uint32(1685));
869         g_variant_builder_add(&builder, "{sv}", "rx_bytes", g_variant_new_uint32(34174));
870         g_variant_builder_add(&builder, "{sv}", "rx_packets", g_variant_new_uint32(1181));
871         g_variant_builder_add(&builder, "{sv}", "tx_bytes", g_variant_new_uint32(6877));
872         g_variant_builder_add(&builder, "{sv}", "tx_packets", g_variant_new_uint32(76));
873         g_variant_builder_add(&builder, "{sv}", "tx_retries", g_variant_new_uint32(0));
874         g_variant_builder_add(&builder, "{sv}", "tx_failed", g_variant_new_uint32(0));
875         g_variant_builder_add(&builder, "{sv}", "beacon_loss", g_variant_new_uint32(0));
876         g_variant_builder_add(&builder, "{sv}", "signal", g_variant_new_int32(-64));
877         g_variant_builder_add(&builder, "{sv}", "signal_avg", g_variant_new_int32(-63));
878         g_variant_builder_add(&builder, "{sv}", "tx_bitrate", g_variant_new_uint32(540)); /* 10 times */
879         g_variant_builder_add(&builder, "{sv}", "rx_bitrate", g_variant_new_uint32(55)); /* 10 times */
880         g_variant_builder_add(&builder, "{sv}", "mesh_llid", g_variant_new_uint32(51731));
881         g_variant_builder_add(&builder, "{sv}", "mesh_plid", g_variant_new_uint32(35432));
882         g_variant_builder_add(&builder, "{sv}", "mesh_plink", g_variant_new_uint32(1)); /* 0 : DISCON, 1 : ESTAB */
883         g_variant_builder_add(&builder, "{sv}", "mesh_local_PS_mode", g_variant_new_uint32(1)); /* 0 : INACTIVE, 1 : ACTIVE */
884         g_variant_builder_add(&builder, "{sv}", "mesh_peer_PS_mode", g_variant_new_uint32(1)); /* 0 : INACTIVE, 1 : ACTIVE */
885         g_variant_builder_add(&builder, "{sv}", "mesh_none_peer_PS_mode", g_variant_new_uint32(1)); /* 0 : INACTIVE, 1 : ACTIVE */
886         g_variant_builder_add(&builder, "{sv}", "authorized", g_variant_new_boolean(TRUE));
887         g_variant_builder_add(&builder, "{sv}", "associated", g_variant_new_boolean(TRUE));
888         g_variant_builder_add(&builder, "{sv}", "preamble",g_variant_new_string("long"));
889         g_variant_builder_add(&builder, "{sv}", "WMM_WME", g_variant_new_boolean(TRUE));
890         g_variant_builder_add(&builder, "{sv}", "MFP", g_variant_new_boolean(FALSE));
891         g_variant_builder_add(&builder, "{sv}", "TDLS_peer", g_variant_new_boolean(FALSE));
892         g_variant_builder_add(&builder, "{sv}", "DTIM_period", g_variant_new_uint32(0));
893         g_variant_builder_add(&builder, "{sv}", "beacon_interval", g_variant_new_uint32(1000));
894         g_variant_builder_add(&builder, "{sv}", "short_slot_time", g_variant_new_boolean(TRUE));
895         g_variant_builder_add(&builder, "{sv}", "connected_time", g_variant_new_uint32(256));
896         station = g_variant_builder_end(&builder);
897
898         net_mesh_complete_get_station_info(object, invocation, station, ret);
899
900         g_object_unref(station);
901 #endif
902         return TRUE;
903 }
904
905 static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
906                 GDBusMethodInvocation *invocation,
907                 gpointer user_data)
908 {
909         int ret = MESHD_ERROR_NONE;
910         GVariantBuilder builder;
911         GVariant* mpath_data;
912         GList *iter = NULL;
913
914         mesh_service *service = (mesh_service *)user_data;
915         mesh_interface_s *info = service->interface_info;
916
917         /* Clear mesh path list */
918         g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
919         service->mpath_list = NULL;
920
921         ret = mesh_request_get_mpath_info(
922                                 info->mesh_interface, &service->mpath_list);
923         if (MESHD_ERROR_NONE != ret) {
924                 MESH_LOGE("Failed to mesh_request_get_mpath_info");
925
926                 g_dbus_method_invocation_return_error(invocation,
927                                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
928         } else {
929         /*
930          * Example) sh-3.2# iw mesh0 mpath dump
931          * DEST ADDR         NEXT HOP          IFACE    SN      METRIC  QLEN    EXPTIME         DTIM    DRET    FLAGS
932          * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0    221     152             0               10                      100             0               0x5
933          */
934                 /* Get mesh path information and make variant data */
935                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
936         
937                 iter = service->mpath_list;
938                 while (iter != NULL) {
939                         mesh_mpath_info_s *item = (mesh_mpath_info_s*)iter->data;
940
941                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
942                         g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
943                                                 g_variant_new_string(item->dest_addr));
944                         g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
945                                                 g_variant_new_string(item->next_hop));
946                         g_variant_builder_add(&builder, "{sv}", "IFACE",
947                                                 g_variant_new_string(item->interface));
948                         g_variant_builder_add(&builder, "{sv}", "SN",
949                                                 g_variant_new_uint32(item->sn));
950                         g_variant_builder_add(&builder, "{sv}", "METRIC",
951                                                 g_variant_new_uint32(item->metric));
952                         g_variant_builder_add(&builder, "{sv}", "QLEN",
953                                                 g_variant_new_uint32(item->qlen));
954                         g_variant_builder_add(&builder, "{sv}", "EXPTIME",
955                                                 g_variant_new_uint32(item->exptime));
956                         g_variant_builder_add(&builder, "{sv}", "DTIM",
957                                                 g_variant_new_uint32(item->discovery_timeout));
958                         g_variant_builder_add(&builder, "{sv}", "DRET",
959                                                 g_variant_new_byte(item->discovery_retries));
960                         g_variant_builder_add(&builder, "{sv}", "FLAGS",
961                                                 g_variant_new_byte(item->flags));
962                         g_variant_builder_close(&builder);
963
964                         iter = g_list_next(iter);
965                 }
966
967                 mpath_data = g_variant_builder_end(&builder);
968                 net_mesh_complete_get_mpath_info(object, invocation, mpath_data, ret);
969
970                 g_object_unref(mpath_data);
971         }
972
973         return TRUE;
974 }
975
976 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
977                 gpointer user_data)
978 {
979         gboolean ret;
980         GError *error = NULL;
981         mesh_service *service = (mesh_service *)user_data;
982
983         NOTUSED(name);
984
985         meshd_dbus_object = net_mesh_skeleton_new();
986         if (NULL == meshd_dbus_object) {
987                 MESH_LOGE("net_mesh_skeleton_new() Fail");
988                 return;
989         }
990
991         g_signal_connect(meshd_dbus_object, "handle-enable",
992                         G_CALLBACK(_meshd_dbus_handle_enable), service);
993         g_signal_connect(meshd_dbus_object, "handle-disable",
994                         G_CALLBACK(_meshd_dbus_handle_disable), service);
995         g_signal_connect(meshd_dbus_object, "handle-scan",
996                         G_CALLBACK(_meshd_dbus_handle_scan), service);
997         g_signal_connect(meshd_dbus_object, "handle-specific-scan",
998                         G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
999         g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
1000                         G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
1001         g_signal_connect(meshd_dbus_object, "handle-get-found-mesh-networks",
1002                         G_CALLBACK(_meshd_dbus_handle_get_found_mesh_networks), service);
1003         g_signal_connect(meshd_dbus_object, "handle-enable-mesh",
1004                         G_CALLBACK(_meshd_dbus_handle_enable_mesh), service);
1005         g_signal_connect(meshd_dbus_object, "handle-disable-mesh",
1006                         G_CALLBACK(_meshd_dbus_handle_disable_mesh), service);
1007         g_signal_connect(meshd_dbus_object, "handle-get-joined-mesh-network",
1008                         G_CALLBACK(_meshd_dbus_handle_get_joined_mesh_network), service);
1009         g_signal_connect(meshd_dbus_object, "handle-set-gate",
1010                         G_CALLBACK(_meshd_dbus_handle_set_gate), service);
1011         g_signal_connect(meshd_dbus_object, "handle-unset-gate",
1012                         G_CALLBACK(_meshd_dbus_handle_unset_gate), service);
1013         g_signal_connect(meshd_dbus_object, "handle-set-softap",
1014                         G_CALLBACK(_meshd_dbus_handle_set_softap), service);
1015         g_signal_connect(meshd_dbus_object, "handle-enable-softap",
1016                         G_CALLBACK(_meshd_dbus_handle_enable_softap), service);
1017         g_signal_connect(meshd_dbus_object, "handle-disable-softap",
1018                         G_CALLBACK(_meshd_dbus_handle_disable_softap), service);
1019         g_signal_connect(meshd_dbus_object, "handle-add-mesh-network",
1020                         G_CALLBACK(_meshd_dbus_handle_add_mesh_network), service);
1021         g_signal_connect(meshd_dbus_object, "handle-get-saved-mesh-network",
1022                         G_CALLBACK(_meshd_dbus_handle_get_saved_mesh_network), service);
1023         g_signal_connect(meshd_dbus_object, "handle-select-saved-mesh-network",
1024                         G_CALLBACK(_meshd_dbus_handle_select_saved_mesh_network), service);
1025         g_signal_connect(meshd_dbus_object, "handle-forget-saved-mesh-network",
1026                         G_CALLBACK(_meshd_dbus_handle_forget_saved_mesh_network), service);
1027         g_signal_connect(meshd_dbus_object, "handle-set-interfaces",
1028                         G_CALLBACK(_meshd_dbus_handle_set_interfaces), service);
1029         g_signal_connect(meshd_dbus_object, "handle-get-station-info",
1030                         G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
1031         g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
1032                         G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
1033
1034         ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
1035                         conn, MESH_DBUS_OBJPATH, &error);
1036         if (FALSE == ret) {
1037                 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
1038                 g_error_free(error);
1039         }
1040
1041         ret = _meshd_dbus_subscribe_name_owner_changed(conn);
1042         if (MESHD_ERROR_NONE != ret) {
1043                 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
1044                 return;
1045         }
1046 }
1047
1048 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
1049                 gpointer user_data)
1050 {
1051         NOTUSED(conn);
1052         NOTUSED(user_data);
1053
1054         MESH_LOGD("Lost the name %s", name);
1055 }
1056
1057 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
1058                 gpointer user_data)
1059 {
1060         NOTUSED(conn);
1061         NOTUSED(user_data);
1062
1063         MESH_LOGD("Acquired the name %s", name);
1064 }
1065
1066 static gboolean _meshd_dbus_interface_init(mesh_service *service)
1067 {
1068         guint id;
1069         meshd_check_null_ret_error("service", service, FALSE);
1070
1071         id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1072                         MESH_DBUS_INTERFACE,
1073                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
1074                         _meshd_dbus_on_bus_acquired,
1075                         _meshd_dbus_on_name_acquired,
1076                         _meshd_dbus_on_name_lost,
1077                         service,
1078                         NULL);
1079         if (0 == id) {
1080                 MESH_LOGE("g_bus_own_name() Fail");
1081                 return FALSE;
1082         }
1083
1084         service->dbus_id = id;
1085         service->interface_info = g_new0(mesh_interface_s, 1);
1086         service->scanned_mesh_network = NULL;
1087
1088         return TRUE;
1089 }
1090
1091 static void _meshd_dbus_deinit(mesh_service *service)
1092 {
1093         mesh_interface_s *info = NULL;
1094         meshd_check_null_ret("service", service);
1095
1096         g_bus_unown_name(service->dbus_id);
1097
1098         info = service->interface_info;
1099         meshd_check_null_ret("info", info);
1100         if (info->bridge_interface)
1101                 g_free(info->bridge_interface);
1102         if (info->base_interface)
1103                 g_free(info->base_interface);
1104         if (info->mesh_interface)
1105                 g_free(info->mesh_interface);
1106         if (info->softap_interface)
1107                 g_free(info->softap_interface);
1108         if (info->external_interface)
1109                 g_free(info->external_interface);
1110
1111         if (service->joined_network) {
1112                 g_free(service->joined_network->mesh_id);
1113                 g_free(service->joined_network);
1114                 service->joined_network = NULL;
1115         }
1116         mesh_request_clear_saved_mesh_network(&service->saved_mesh_network);
1117
1118         /* Clear scan list */
1119         g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
1120         service->scanned_mesh_network = NULL;
1121
1122         g_free(service->interface_info);
1123         service->interface_info = NULL;
1124 }
1125
1126  /**< mesh service interface initialization */
1127 gboolean meshd_service_interface_init(mesh_service *service)
1128 {
1129         guint ret;
1130         meshd_check_null_ret_error("service", service, FALSE);
1131
1132         /* Initialize dbus interface */
1133         ret = _meshd_dbus_interface_init(service);
1134         if (FALSE == ret) {
1135                 MESH_LOGE("zigbee_service_dbus_interface_init failed!!!");
1136                 return FALSE;
1137         }
1138
1139         return TRUE;
1140 }
1141
1142 /**< Zigbee service interface de-initialization */
1143 void meshd_service_interface_deinit(mesh_service *service)
1144 {
1145         meshd_check_null_ret("service", service);
1146
1147         /* De-initialize dbus interface */
1148         _meshd_dbus_deinit(service);
1149 }