2 * Network Configuration Module
4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include "mesh-util.h"
27 #include "mesh-service-interface.h"
28 #include "mesh-generated-code.h"
30 #include "mesh-request.h"
31 #include "mesh-interface.h"
33 static NetMesh *meshd_dbus_object;
35 /* global list to care resource handle for each client */
36 static GList *meshd_dbus_client_list;
37 static GMutex meshd_dbus_client_list_mutex;
39 typedef struct _meshd_dbus_client_s {
41 } meshd_dbus_client_s;
43 NetMesh* meshd_dbus_get_object()
45 return meshd_dbus_object;
48 int64_t meshd_dbus_generate_signal_number()
55 static int _meshd_dbus_client_list_cleanup(GList *client_list)
57 meshd_dbus_client_s *client;
59 meshd_check_null_ret_error("client_list", client_list, FALSE);
61 client = client_list->data;
63 free(client->bus_name);
64 client->bus_name = NULL;
66 g_list_free(client_list);
68 return MESHD_ERROR_NONE;
71 static int _meshd_dbus_client_list_compare_bus_name(const void *a, const void *b)
73 const meshd_dbus_client_s *client = a;
75 return g_strcmp0(client->bus_name, b);
78 static inline GList* _meshd_dbus_client_list_find_client(const gchar *owner)
80 return g_list_find_custom(meshd_dbus_client_list, owner,
81 _meshd_dbus_client_list_compare_bus_name);
84 static void _meshd_dbus_name_owner_changed_cb(GDBusConnection *conn,
85 const gchar *sender_name,
86 const gchar *object_path,
87 const gchar *interface_name,
88 const gchar *signal_name,
94 gchar *name, *old_owner, *new_owner;
99 NOTUSED(interface_name);
100 NOTUSED(signal_name);
103 g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
105 if (0 == strlen(new_owner)) {
106 g_mutex_lock(&meshd_dbus_client_list_mutex);
107 client = _meshd_dbus_client_list_find_client(old_owner);
108 if (client) { /* found bus name in our bus list */
109 MESH_LOGD("bus(%s) stopped", old_owner);
110 meshd_dbus_client_list = g_list_remove_link(meshd_dbus_client_list, client);
112 g_mutex_unlock(&meshd_dbus_client_list_mutex);
115 ret = _meshd_dbus_client_list_cleanup(client);
116 if (MESHD_ERROR_NONE != ret)
117 MESH_LOGE("_meshd_dbus_client_list_cleanup() Fail(%d)", ret);
122 static int _meshd_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
126 id = g_dbus_connection_signal_subscribe(conn,
127 "org.freedesktop.DBus", /* bus name */
128 "org.freedesktop.DBus", /* interface */
129 "NameOwnerChanged", /* member */
130 "/org/freedesktop/DBus", /* path */
132 G_DBUS_SIGNAL_FLAGS_NONE,
133 _meshd_dbus_name_owner_changed_cb,
137 MESH_LOGE("g_dbus_connection_signal_subscribe() Fail");
138 return MESHD_ERROR_IO_ERROR;
141 return MESHD_ERROR_NONE;
144 static gboolean _meshd_dbus_handle_enable(NetMesh *object,
145 GDBusMethodInvocation *invocation,
148 int ret = MESHD_ERROR_NONE;
149 mesh_service *service = (mesh_service *)user_data;
150 mesh_interface_s *info = service->interface_info;
152 if (service->mesh_activated) {
153 /* Already activated */
154 net_mesh_complete_enable(object, invocation,
155 MESHD_ERROR_OPERATION_FAILED);
157 /* Do API response first */
158 net_mesh_complete_enable(object, invocation, ret);
159 service->mesh_activated = TRUE;
162 meshd_check_null_ret_error("info", info, FALSE);
164 ret = mesh_interface_initialize(service->interface_info);
165 if (MESHD_ERROR_NONE != ret) {
166 MESH_LOGE("Failed to mesh_interface_initialize [%d]", ret);
170 ret = mesh_request_enable_mesh_gate(info->base_interface,
171 info->mesh_interface, info->mesh_id, info->mesh_channel);
172 if (MESHD_ERROR_NONE != ret) {
173 MESH_LOGE("Failed to mesh_request_enable_mesh_gate [%d]", ret);
177 ret = mesh_request_create_bridge(info->bridge_interface,
178 info->mesh_interface, info->external_interface);
179 if (MESHD_ERROR_NONE != ret) {
180 MESH_LOGE("Failed to mesh_request_create_bridge [%d]", ret);
184 ret = mesh_request_specific_scan(info->mesh_interface,
185 info->mesh_id, info->mesh_channel);
186 if (MESHD_ERROR_NONE != ret) {
187 MESH_LOGE("Failed to mesh_request_specific_scan [%d]", ret);
190 ret = mesh_dhcp_request(info->bridge_interface);
191 if (MESHD_ERROR_NONE != ret) {
192 MESH_LOGE("Failed to mesh_dhcp_request [%d]", ret);
197 net_mesh_emit_mesh_enabled(object, ret);
202 static gboolean _meshd_dbus_handle_disable(NetMesh *object,
203 GDBusMethodInvocation *invocation,
206 int ret = MESHD_ERROR_NONE;
207 mesh_service *service = (mesh_service *)user_data;
208 mesh_interface_s *info = service->interface_info;
210 meshd_check_null_ret_error("info", info, FALSE);
212 if (FALSE == service->mesh_activated) {
213 MESH_LOGD("Mesh network is not activated yet");
214 ret = MESHD_ERROR_OPERATION_FAILED;
218 ret = mesh_request_disable_mesh_gate(info->mesh_interface);
219 if (MESHD_ERROR_NONE != ret) {
220 MESH_LOGE("Failed to mesh_request_disable_mesh_gate");
224 ret = mesh_request_remove_bridge(info->bridge_interface);
225 if (MESHD_ERROR_NONE != ret) {
226 MESH_LOGE("Failed to mesh_request_remove_bridge");
230 net_mesh_complete_disable(object, invocation, ret);
235 static gboolean _meshd_dbus_handle_set_mesh_gate(NetMesh *object,
236 GDBusMethodInvocation *invocation,
240 int ret = MESHD_ERROR_NONE;
242 MESH_LOGD("Not implemented yet !");
246 /* TODO: Check external interface and set it into bridge */
248 net_mesh_complete_set_mesh_gate(object, invocation, ret);
253 static gboolean _meshd_dbus_handle_set_mesh_softap(NetMesh *object,
254 GDBusMethodInvocation *invocation,
258 int ret = MESHD_ERROR_NONE;
260 MESH_LOGD("Not implemented yet !");
264 /* TODO: Check softAP interface and execute it */
266 net_mesh_complete_set_mesh_softap(object, invocation, ret);
271 static gboolean _meshd_dbus_handle_scan(NetMesh *object,
272 GDBusMethodInvocation *invocation,
275 int ret = MESHD_ERROR_NONE;
276 mesh_service *service = (mesh_service *)user_data;
277 mesh_interface_s *info = service->interface_info;
279 meshd_check_null_ret_error("info", info, FALSE);
281 ret = mesh_request_scan(info->mesh_interface);
282 if (MESHD_ERROR_NONE != ret) {
283 MESH_LOGE("Failed to mesh_request_scan");
286 net_mesh_complete_scan(object, invocation, ret);
291 static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
292 GDBusMethodInvocation *invocation,
297 int ret = MESHD_ERROR_NONE;
298 mesh_service *service = (mesh_service *)user_data;
299 mesh_interface_s *info = service->interface_info;
301 meshd_check_null_ret_error("info", info, FALSE);
303 ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel);
304 if (MESHD_ERROR_NONE != ret) {
305 MESH_LOGE("Failed to mesh_request_specific_scan");
308 net_mesh_complete_specific_scan(object, invocation, ret);
313 static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
314 GDBusMethodInvocation *invocation,
317 int ret = MESHD_ERROR_NONE;
318 mesh_service *service = (mesh_service *)user_data;
319 mesh_interface_s *info = service->interface_info;
321 ret = mesh_request_cancel_scan(info->mesh_interface);
322 if (MESHD_ERROR_NONE != ret) {
323 MESH_LOGE("Failed to mesh_request_cancel_scan");
326 net_mesh_complete_cancel_scan(object, invocation, ret);
331 static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
332 GDBusMethodInvocation *invocation)
334 int ret = MESHD_ERROR_NONE;
340 MESH_LOGD("Not implemented yet !");
341 //net_mesh_complete_get_station_info(object, invocation, ret);
346 static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
347 GDBusMethodInvocation *invocation)
349 int ret = MESHD_ERROR_NONE;
355 MESH_LOGD("Not implemented yet !");
356 //net_mesh_complete_get_mpath_info(object, invocation, ret);
361 static gboolean _meshd_dbus_handle_join(NetMesh *object,
362 GDBusMethodInvocation *invocation)
364 int ret = MESHD_ERROR_NONE;
366 MESH_LOGD("Not implemented yet !");
367 net_mesh_complete_join(object, invocation, ret);
372 static gboolean _meshd_dbus_handle_is_joined(NetMesh *object,
373 GDBusMethodInvocation *invocation)
375 int ret = MESHD_ERROR_NONE;
377 MESH_LOGD("Not implemented yet !");
378 net_mesh_complete_is_joined(object, invocation, ret);
383 static gboolean _meshd_dbus_handle_disjoin(NetMesh *object,
384 GDBusMethodInvocation *invocation)
386 int ret = MESHD_ERROR_NONE;
388 MESH_LOGD("Not implemented yet !");
389 net_mesh_complete_disjoin(object, invocation, ret);
394 static gboolean _meshd_dbus_handle_load_softap_settings(NetMesh *object,
395 GDBusMethodInvocation *invocation)
397 int ret = MESHD_ERROR_NONE;
399 MESH_LOGD("Not implemented yet !");
400 net_mesh_complete_load_softap_settings(object, invocation, ret);
405 static gboolean _meshd_dbus_handle_start_bridge(NetMesh *object,
406 GDBusMethodInvocation *invocation,
408 gchar *bridge_interface,
411 int ret = MESHD_ERROR_NONE;
415 MESH_LOGD("Mode : %d", mode);
416 MESH_LOGD("Interface : %s", bridge_interface);
417 ret = mesh_request_create_bridge(bridge_interface, NULL, NULL);
419 net_mesh_complete_start_bridge(object, invocation, ret);
424 static gboolean _meshd_dbus_handle_stop_bridge(NetMesh *object,
425 GDBusMethodInvocation *invocation,
426 gchar *bridge_interface,
429 int ret = MESHD_ERROR_NONE;
433 MESH_LOGD("Interface : %s", bridge_interface);
434 ret = mesh_request_remove_bridge(bridge_interface);
436 net_mesh_complete_stop_bridge(object, invocation, ret);
441 static gboolean _meshd_dbus_handle_add_mesh_network(NetMesh *object,
442 GDBusMethodInvocation *invocation,
443 gchar *mesh_id, gint channel, gint security,
446 int ret = MESHD_ERROR_NONE;
453 MESH_LOGD("Not implemented yet !");
455 net_mesh_complete_add_mesh_network(object, invocation, ret);
460 static gboolean _meshd_dbus_handle_get_saved_mesh_network(NetMesh *object,
461 GDBusMethodInvocation *invocation,
464 GVariant *variant = NULL;
468 MESH_LOGD("Not implemented yet !");
470 net_mesh_complete_get_saved_mesh_network(object, invocation, variant);
475 static gboolean _meshd_dbus_handle_select_saved_mesh_network(NetMesh *object,
476 GDBusMethodInvocation *invocation,
477 gchar *mesh_id, gint channel, gint security,
480 int ret = MESHD_ERROR_NONE;
487 MESH_LOGD("Not implemented yet !");
489 net_mesh_complete_select_saved_mesh_network(object, invocation, ret);
494 static gboolean _meshd_dbus_handle_forget_saved_mesh_network(NetMesh *object,
495 GDBusMethodInvocation *invocation,
496 gchar *mesh_id, gint channel, gint security,
499 int ret = MESHD_ERROR_NONE;
506 MESH_LOGD("Not implemented yet !");
508 net_mesh_complete_forget_saved_mesh_network(object, invocation, ret);
515 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
519 GError *error = NULL;
520 mesh_service *service = (mesh_service *)user_data;
524 meshd_dbus_object = net_mesh_skeleton_new();
525 if (NULL == meshd_dbus_object) {
526 MESH_LOGE("net_mesh_skeleton_new() Fail");
530 g_signal_connect(meshd_dbus_object, "handle-enable",
531 G_CALLBACK(_meshd_dbus_handle_enable), service);
532 g_signal_connect(meshd_dbus_object, "handle-disable",
533 G_CALLBACK(_meshd_dbus_handle_disable), service);
534 g_signal_connect(meshd_dbus_object, "handle-set-mesh-gate",
535 G_CALLBACK(_meshd_dbus_handle_set_mesh_gate), service);
536 g_signal_connect(meshd_dbus_object, "handle-set-mesh-softap",
537 G_CALLBACK(_meshd_dbus_handle_set_mesh_softap), service);
538 g_signal_connect(meshd_dbus_object, "handle-scan",
539 G_CALLBACK(_meshd_dbus_handle_scan), service);
540 g_signal_connect(meshd_dbus_object, "handle-specific-scan",
541 G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
542 g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
543 G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
544 g_signal_connect(meshd_dbus_object, "handle-get-station-info",
545 G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
546 g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
547 G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
548 g_signal_connect(meshd_dbus_object, "handle-join",
549 G_CALLBACK(_meshd_dbus_handle_join), service);
550 g_signal_connect(meshd_dbus_object, "handle-is-joined",
551 G_CALLBACK(_meshd_dbus_handle_is_joined), service);
552 g_signal_connect(meshd_dbus_object, "handle-disjoin",
553 G_CALLBACK(_meshd_dbus_handle_disjoin), service);
554 g_signal_connect(meshd_dbus_object, "handle-load-softap-settings",
555 G_CALLBACK(_meshd_dbus_handle_load_softap_settings), service);
556 g_signal_connect(meshd_dbus_object, "handle-start-bridge",
557 G_CALLBACK(_meshd_dbus_handle_start_bridge), service);
558 g_signal_connect(meshd_dbus_object, "handle-stop-bridge",
559 G_CALLBACK(_meshd_dbus_handle_stop_bridge), service);
561 g_signal_connect(meshd_dbus_object, "handle-add-mesh-network",
562 G_CALLBACK(_meshd_dbus_handle_add_mesh_network), service);
563 g_signal_connect(meshd_dbus_object, "handle-get-saved-mesh-network",
564 G_CALLBACK(_meshd_dbus_handle_get_saved_mesh_network), service);
565 g_signal_connect(meshd_dbus_object, "handle-select-saved-mesh-network",
566 G_CALLBACK(_meshd_dbus_handle_select_saved_mesh_network), service);
567 g_signal_connect(meshd_dbus_object, "handle-forget-saved-mesh-network",
568 G_CALLBACK(_meshd_dbus_handle_forget_saved_mesh_network), service);
570 ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
571 conn, MESH_DBUS_OBJPATH, &error);
573 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
577 ret = _meshd_dbus_subscribe_name_owner_changed(conn);
578 if (MESHD_ERROR_NONE != ret) {
579 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
584 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
590 MESH_LOGD("Lost the name %s", name);
593 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
599 MESH_LOGD("Acquired the name %s", name);
602 static gboolean _meshd_dbus_interface_init(mesh_service *service)
605 meshd_check_null_ret_error("service", service, FALSE);
607 id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
609 G_BUS_NAME_OWNER_FLAGS_REPLACE,
610 _meshd_dbus_on_bus_acquired,
611 _meshd_dbus_on_name_acquired,
612 _meshd_dbus_on_name_lost,
616 MESH_LOGE("g_bus_own_name() Fail");
620 service->dbus_id = id;
621 service->interface_info = g_new0(mesh_interface_s, 1);
626 static void _meshd_dbus_deinit(mesh_service *service)
628 mesh_interface_s *info = NULL;
629 meshd_check_null_ret("service", service);
631 g_bus_unown_name(service->dbus_id);
633 info = service->interface_info;
634 meshd_check_null_ret("info", info);
635 if (info->bridge_interface)
636 g_free(info->bridge_interface);
637 if (info->base_interface)
638 g_free(info->base_interface);
639 if (info->mesh_interface)
640 g_free(info->mesh_interface);
641 if (info->softap_interface)
642 g_free(info->softap_interface);
643 if (info->external_interface)
644 g_free(info->external_interface);
646 g_free(service->interface_info);
647 service->interface_info = NULL;
650 /**< mesh service interface initialization */
651 gboolean meshd_service_interface_init(mesh_service *service)
654 meshd_check_null_ret_error("service", service, FALSE);
656 /* Initialize dbus interface */
657 ret = _meshd_dbus_interface_init(service);
659 MESH_LOGE("zigbee_service_dbus_interface_init failed!!!");
666 /**< Zigbee service interface de-initialization */
667 void meshd_service_interface_deinit(mesh_service *service)
669 meshd_check_null_ret("service", service);
671 /* De-initialize dbus interface */
672 _meshd_dbus_deinit(service);