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_request_dhcp(info->bridge_interface);
191 if (MESHD_ERROR_NONE != ret) {
192 MESH_LOGE("Failed to mesh_request_dhcp [%d]", ret);
196 net_mesh_emit_mesh_enabled(object, ret);
201 static gboolean _meshd_dbus_handle_disable(NetMesh *object,
202 GDBusMethodInvocation *invocation,
205 int ret = MESHD_ERROR_NONE;
206 mesh_service *service = (mesh_service *)user_data;
207 mesh_interface_s *info = service->interface_info;
209 meshd_check_null_ret_error("info", info, FALSE);
211 if (FALSE == service->mesh_activated) {
212 MESH_LOGD("Mesh network is not activated yet");
213 ret = MESHD_ERROR_OPERATION_FAILED;
217 ret = mesh_request_disable_mesh_gate(info->mesh_interface);
218 if (MESHD_ERROR_NONE != ret) {
219 MESH_LOGE("Failed to mesh_request_disable_mesh_gate");
223 ret = mesh_request_remove_bridge(info->bridge_interface);
224 if (MESHD_ERROR_NONE != ret) {
225 MESH_LOGE("Failed to mesh_request_remove_bridge");
229 net_mesh_complete_disable(object, invocation, ret);
234 static gboolean _meshd_dbus_handle_set_mesh_gate(NetMesh *object,
235 GDBusMethodInvocation *invocation,
239 int ret = MESHD_ERROR_NONE;
241 MESH_LOGD("Not implemented yet !");
245 /* TODO: Check external interface and set it into bridge */
247 net_mesh_complete_set_mesh_gate(object, invocation, ret);
252 static gboolean _meshd_dbus_handle_set_mesh_softap(NetMesh *object,
253 GDBusMethodInvocation *invocation,
257 int ret = MESHD_ERROR_NONE;
259 MESH_LOGD("Not implemented yet !");
263 /* TODO: Check softAP interface and execute it */
265 net_mesh_complete_set_mesh_softap(object, invocation, ret);
270 static gboolean _meshd_dbus_handle_scan(NetMesh *object,
271 GDBusMethodInvocation *invocation,
274 int ret = MESHD_ERROR_NONE;
275 mesh_service *service = (mesh_service *)user_data;
276 mesh_interface_s *info = service->interface_info;
278 meshd_check_null_ret_error("info", info, FALSE);
280 ret = mesh_request_scan(info->mesh_interface);
281 if (MESHD_ERROR_NONE != ret) {
282 MESH_LOGE("Failed to mesh_request_scan");
285 net_mesh_complete_scan(object, invocation, ret);
290 static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
291 GDBusMethodInvocation *invocation,
296 int ret = MESHD_ERROR_NONE;
297 mesh_service *service = (mesh_service *)user_data;
298 mesh_interface_s *info = service->interface_info;
300 meshd_check_null_ret_error("info", info, FALSE);
302 ret = mesh_request_specific_scan(info->mesh_interface, mesh_id, channel);
303 if (MESHD_ERROR_NONE != ret) {
304 MESH_LOGE("Failed to mesh_request_specific_scan");
307 net_mesh_complete_specific_scan(object, invocation, ret);
312 static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
313 GDBusMethodInvocation *invocation,
316 int ret = MESHD_ERROR_NONE;
317 mesh_service *service = (mesh_service *)user_data;
318 mesh_interface_s *info = service->interface_info;
320 ret = mesh_request_cancel_scan(info->mesh_interface);
321 if (MESHD_ERROR_NONE != ret) {
322 MESH_LOGE("Failed to mesh_request_cancel_scan");
325 net_mesh_complete_cancel_scan(object, invocation, ret);
330 static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
331 GDBusMethodInvocation *invocation)
333 int ret = MESHD_ERROR_NONE;
339 MESH_LOGD("Not implemented yet !");
340 //net_mesh_complete_get_station_info(object, invocation, ret);
345 static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
346 GDBusMethodInvocation *invocation)
348 int ret = MESHD_ERROR_NONE;
354 MESH_LOGD("Not implemented yet !");
355 //net_mesh_complete_get_mpath_info(object, invocation, ret);
360 static gboolean _meshd_dbus_handle_join(NetMesh *object,
361 GDBusMethodInvocation *invocation)
363 int ret = MESHD_ERROR_NONE;
365 MESH_LOGD("Not implemented yet !");
366 net_mesh_complete_join(object, invocation, ret);
371 static gboolean _meshd_dbus_handle_is_joined(NetMesh *object,
372 GDBusMethodInvocation *invocation)
374 int ret = MESHD_ERROR_NONE;
376 MESH_LOGD("Not implemented yet !");
377 net_mesh_complete_is_joined(object, invocation, ret);
382 static gboolean _meshd_dbus_handle_disjoin(NetMesh *object,
383 GDBusMethodInvocation *invocation)
385 int ret = MESHD_ERROR_NONE;
387 MESH_LOGD("Not implemented yet !");
388 net_mesh_complete_disjoin(object, invocation, ret);
393 static gboolean _meshd_dbus_handle_load_softap_settings(NetMesh *object,
394 GDBusMethodInvocation *invocation)
396 int ret = MESHD_ERROR_NONE;
398 MESH_LOGD("Not implemented yet !");
399 net_mesh_complete_load_softap_settings(object, invocation, ret);
404 static gboolean _meshd_dbus_handle_start_bridge(NetMesh *object,
405 GDBusMethodInvocation *invocation,
407 gchar *bridge_interface,
410 int ret = MESHD_ERROR_NONE;
414 MESH_LOGD("Mode : %d", mode);
415 MESH_LOGD("Interface : %s", bridge_interface);
416 ret = mesh_request_create_bridge(bridge_interface, NULL, NULL);
418 net_mesh_complete_start_bridge(object, invocation, ret);
423 static gboolean _meshd_dbus_handle_stop_bridge(NetMesh *object,
424 GDBusMethodInvocation *invocation,
425 gchar *bridge_interface,
428 int ret = MESHD_ERROR_NONE;
432 MESH_LOGD("Interface : %s", bridge_interface);
433 ret = mesh_request_remove_bridge(bridge_interface);
435 net_mesh_complete_stop_bridge(object, invocation, ret);
441 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
445 GError *error = NULL;
446 mesh_service *service = (mesh_service *)user_data;
450 meshd_dbus_object = net_mesh_skeleton_new();
451 if (NULL == meshd_dbus_object) {
452 MESH_LOGE("net_mesh_skeleton_new() Fail");
456 g_signal_connect(meshd_dbus_object, "handle-enable",
457 G_CALLBACK(_meshd_dbus_handle_enable), service);
458 g_signal_connect(meshd_dbus_object, "handle-disable",
459 G_CALLBACK(_meshd_dbus_handle_disable), service);
460 g_signal_connect(meshd_dbus_object, "handle-set-mesh-gate",
461 G_CALLBACK(_meshd_dbus_handle_set_mesh_gate), service);
462 g_signal_connect(meshd_dbus_object, "handle-set-mesh-softap",
463 G_CALLBACK(_meshd_dbus_handle_set_mesh_softap), service);
464 g_signal_connect(meshd_dbus_object, "handle-scan",
465 G_CALLBACK(_meshd_dbus_handle_scan), service);
466 g_signal_connect(meshd_dbus_object, "handle-specific-scan",
467 G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
468 g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
469 G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
470 g_signal_connect(meshd_dbus_object, "handle-get-station-info",
471 G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
472 g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
473 G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
474 g_signal_connect(meshd_dbus_object, "handle-join",
475 G_CALLBACK(_meshd_dbus_handle_join), service);
476 g_signal_connect(meshd_dbus_object, "handle-is-joined",
477 G_CALLBACK(_meshd_dbus_handle_is_joined), service);
478 g_signal_connect(meshd_dbus_object, "handle-disjoin",
479 G_CALLBACK(_meshd_dbus_handle_disjoin), service);
480 g_signal_connect(meshd_dbus_object, "handle-load-softap-settings",
481 G_CALLBACK(_meshd_dbus_handle_load_softap_settings), service);
482 g_signal_connect(meshd_dbus_object, "handle-start-bridge",
483 G_CALLBACK(_meshd_dbus_handle_start_bridge), service);
484 g_signal_connect(meshd_dbus_object, "handle-stop-bridge",
485 G_CALLBACK(_meshd_dbus_handle_stop_bridge), service);
487 ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
488 conn, MESH_DBUS_OBJPATH, &error);
490 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
494 ret = _meshd_dbus_subscribe_name_owner_changed(conn);
495 if (MESHD_ERROR_NONE != ret) {
496 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
501 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
507 MESH_LOGD("Lost the name %s", name);
510 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
516 MESH_LOGD("Acquired the name %s", name);
519 static gboolean _meshd_dbus_interface_init(mesh_service *service)
522 meshd_check_null_ret_error("service", service, FALSE);
524 id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
526 G_BUS_NAME_OWNER_FLAGS_REPLACE,
527 _meshd_dbus_on_bus_acquired,
528 _meshd_dbus_on_name_acquired,
529 _meshd_dbus_on_name_lost,
533 MESH_LOGE("g_bus_own_name() Fail");
537 service->dbus_id = id;
538 service->interface_info = g_new0(mesh_interface_s, 1);
543 static void _meshd_dbus_deinit(mesh_service *service)
545 mesh_interface_s *info = NULL;
546 meshd_check_null_ret("service", service);
548 g_bus_unown_name(service->dbus_id);
550 info = service->interface_info;
551 meshd_check_null_ret("info", info);
552 if (info->bridge_interface)
553 g_free(info->bridge_interface);
554 if (info->base_interface)
555 g_free(info->base_interface);
556 if (info->mesh_interface)
557 g_free(info->mesh_interface);
558 if (info->softap_interface)
559 g_free(info->softap_interface);
560 if (info->external_interface)
561 g_free(info->external_interface);
563 g_free(service->interface_info);
564 service->interface_info = NULL;
567 /**< mesh service interface initialization */
568 gboolean meshd_service_interface_init(mesh_service *service)
571 meshd_check_null_ret_error("service", service, FALSE);
573 /* Initialize dbus interface */
574 ret = _meshd_dbus_interface_init(service);
576 MESH_LOGE("zigbee_service_dbus_interface_init failed!!!");
583 /**< Zigbee service interface de-initialization */
584 void meshd_service_interface_deinit(mesh_service *service)
586 meshd_check_null_ret("service", service);
588 /* De-initialize dbus interface */
589 _meshd_dbus_deinit(service);