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