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