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);
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 !");
390 ret = mesh_request_test();
391 MESH_LOGD("TEST requested [%d]", ret);
393 net_mesh_complete_disjoin(object, invocation, ret);
398 static gboolean _meshd_dbus_handle_load_softap_settings(NetMesh *object,
399 GDBusMethodInvocation *invocation)
401 int ret = MESHD_ERROR_NONE;
403 MESH_LOGD("Not implemented yet !");
404 net_mesh_complete_load_softap_settings(object, invocation, ret);
409 static gboolean _meshd_dbus_handle_start_bridge(NetMesh *object,
410 GDBusMethodInvocation *invocation,
412 gchar *bridge_interface,
415 int ret = MESHD_ERROR_NONE;
419 MESH_LOGD("Mode : %d", mode);
420 MESH_LOGD("Interface : %s", bridge_interface);
421 ret = mesh_request_create_bridge(bridge_interface, NULL, NULL);
423 net_mesh_complete_start_bridge(object, invocation, ret);
428 static gboolean _meshd_dbus_handle_stop_bridge(NetMesh *object,
429 GDBusMethodInvocation *invocation,
430 gchar *bridge_interface,
433 int ret = MESHD_ERROR_NONE;
437 MESH_LOGD("Interface : %s", bridge_interface);
438 ret = mesh_request_remove_bridge(bridge_interface);
440 net_mesh_complete_stop_bridge(object, invocation, ret);
446 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
450 GError *error = NULL;
451 mesh_service *service = (mesh_service *)user_data;
455 meshd_dbus_object = net_mesh_skeleton_new();
456 if (NULL == meshd_dbus_object) {
457 MESH_LOGE("net_mesh_skeleton_new() Fail");
461 g_signal_connect(meshd_dbus_object, "handle-enable",
462 G_CALLBACK(_meshd_dbus_handle_enable), service);
463 g_signal_connect(meshd_dbus_object, "handle-disable",
464 G_CALLBACK(_meshd_dbus_handle_disable), service);
465 g_signal_connect(meshd_dbus_object, "handle-set-mesh-gate",
466 G_CALLBACK(_meshd_dbus_handle_set_mesh_gate), service);
467 g_signal_connect(meshd_dbus_object, "handle-set-mesh-softap",
468 G_CALLBACK(_meshd_dbus_handle_set_mesh_softap), service);
469 g_signal_connect(meshd_dbus_object, "handle-scan",
470 G_CALLBACK(_meshd_dbus_handle_scan), service);
471 g_signal_connect(meshd_dbus_object, "handle-specific-scan",
472 G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
473 g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
474 G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
475 g_signal_connect(meshd_dbus_object, "handle-get-station-info",
476 G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
477 g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
478 G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
479 g_signal_connect(meshd_dbus_object, "handle-join",
480 G_CALLBACK(_meshd_dbus_handle_join), service);
481 g_signal_connect(meshd_dbus_object, "handle-is-joined",
482 G_CALLBACK(_meshd_dbus_handle_is_joined), service);
483 g_signal_connect(meshd_dbus_object, "handle-disjoin",
484 G_CALLBACK(_meshd_dbus_handle_disjoin), service);
485 g_signal_connect(meshd_dbus_object, "handle-load-softap-settings",
486 G_CALLBACK(_meshd_dbus_handle_load_softap_settings), service);
487 g_signal_connect(meshd_dbus_object, "handle-start-bridge",
488 G_CALLBACK(_meshd_dbus_handle_start_bridge), service);
489 g_signal_connect(meshd_dbus_object, "handle-stop-bridge",
490 G_CALLBACK(_meshd_dbus_handle_stop_bridge), service);
492 ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
493 conn, MESH_DBUS_OBJPATH, &error);
495 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
499 ret = _meshd_dbus_subscribe_name_owner_changed(conn);
500 if (MESHD_ERROR_NONE != ret) {
501 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
506 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
512 MESH_LOGD("Lost the name %s", name);
515 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
521 MESH_LOGD("Acquired the name %s", name);
524 static gboolean _meshd_dbus_interface_init(mesh_service *service)
527 meshd_check_null_ret_error("service", service, FALSE);
529 id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
531 G_BUS_NAME_OWNER_FLAGS_REPLACE,
532 _meshd_dbus_on_bus_acquired,
533 _meshd_dbus_on_name_acquired,
534 _meshd_dbus_on_name_lost,
538 MESH_LOGE("g_bus_own_name() Fail");
542 service->dbus_id = id;
543 service->interface_info = g_new0(mesh_interface_s, 1);
548 static void _meshd_dbus_deinit(mesh_service *service)
550 mesh_interface_s *info = NULL;
551 meshd_check_null_ret("service", service);
553 g_bus_unown_name(service->dbus_id);
555 info = service->interface_info;
556 meshd_check_null_ret("info", info);
557 if (info->bridge_interface)
558 g_free(info->bridge_interface);
559 if (info->base_interface)
560 g_free(info->base_interface);
561 if (info->mesh_interface)
562 g_free(info->mesh_interface);
563 if (info->softap_interface)
564 g_free(info->softap_interface);
565 if (info->external_interface)
566 g_free(info->external_interface);
568 g_free(service->interface_info);
569 service->interface_info = NULL;
572 /**< mesh service interface initialization */
573 gboolean meshd_service_interface_init(mesh_service *service)
576 meshd_check_null_ret_error("service", service, FALSE);
578 /* Initialize dbus interface */
579 ret = _meshd_dbus_interface_init(service);
581 MESH_LOGE("zigbee_service_dbus_interface_init failed!!!");
588 /**< Zigbee service interface de-initialization */
589 void meshd_service_interface_deinit(mesh_service *service)
591 meshd_check_null_ret("service", service);
593 /* De-initialize dbus interface */
594 _meshd_dbus_deinit(service);