Fix the Svace issues
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-gatt-service.c
index ade3c14..66c0632 100644 (file)
@@ -29,7 +29,6 @@
 #define NUMBER_OF_FLAGS        10
 
 GDBusConnection *g_conn;
-GDBusNodeInfo *obj_info;
 guint owner_id;
 guint manager_id;
 static gboolean new_service = FALSE;
@@ -207,6 +206,34 @@ static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info(
 
 static struct gatt_req_info *__bt_gatt_find_request_info(guint request_id);
 
+static void __bt_gatt_close_gdbus_connection(void)
+{
+       GError *err = NULL;
+
+       BT_DBG("+");
+
+       ret_if(g_conn == NULL);
+
+       if (!g_dbus_connection_flush_sync(g_conn, NULL, &err)) {
+               BT_ERR("Fail to flush the connection: %s", err->message);
+               g_error_free(err);
+               err = NULL;
+       }
+
+       if (!g_dbus_connection_close_sync(g_conn, NULL, &err)) {
+               if (err) {
+                       BT_ERR("Fail to close the dbus connection: %s", err->message);
+                       g_error_free(err);
+               }
+       }
+
+       g_object_unref(g_conn);
+
+       g_conn = NULL;
+
+       BT_DBG("-");
+}
+
 #ifdef HPS_FEATURE
 static int __bt_send_event_to_hps(int event, GVariant *var)
 {
@@ -1006,22 +1033,22 @@ static GDBusNodeInfo *__bt_gatt_create_method_node_info(
                                const gchar *introspection_data)
 {
        GError *err = NULL;
+       GDBusNodeInfo *node_info = NULL;
 
        if (introspection_data == NULL)
                return NULL;
 
-       if (obj_info == NULL) {
-               BT_DBG("Create new node info");
-               obj_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
 
-               if (err) {
-                       BT_ERR("Unable to create node: %s", err->message);
-                       g_clear_error(&err);
-                       return NULL;
-               }
+       BT_DBG("Create new node info");
+       node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
+
+       if (err) {
+               BT_ERR("Unable to create node: %s", err->message);
+               g_clear_error(&err);
+               return NULL;
        }
 
-       return obj_info;
+       return node_info;
 }
 
 static struct gatt_service_info *__bt_gatt_find_gatt_service_info(
@@ -1434,19 +1461,48 @@ BT_EXPORT_API int bluetooth_gatt_unregister_application(void)
 static GDBusConnection *__bt_gatt_get_gdbus_connection(void)
 {
        GDBusConnection *local_system_gconn = NULL;
+       char *address;
        GError *err = NULL;
 
        if (g_conn == NULL) {
-               g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+               address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+               if (address == NULL) {
+                       if (err) {
+                               BT_ERR("Failed to get bus address: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return NULL;
+               }
+
+               g_conn = g_dbus_connection_new_for_address_sync(address,
+                                       G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+                                       G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+                                       NULL, /* GDBusAuthObserver */
+                                       NULL,
+                                       &err);
                if (!g_conn) {
                        if (err) {
                                BT_ERR("Unable to connect to dbus: %s", err->message);
                                g_clear_error(&err);
                        }
-                       g_conn = NULL;
+                       return NULL;
                }
        } else if (g_dbus_connection_is_closed(g_conn)) {
-               local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+               address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+               if (address == NULL) {
+                       if (err) {
+                               BT_ERR("Failed to get bus address: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return NULL;
+               }
+
+               local_system_gconn = g_dbus_connection_new_for_address_sync(address,
+                                       G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+                                       G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+                                       NULL, /* GDBusAuthObserver */
+                                       NULL,
+                                       &err);
 
                if (!local_system_gconn) {
                        BT_ERR("Unable to connect to dbus: %s", err->message);
@@ -1497,10 +1553,14 @@ BT_EXPORT_API int bluetooth_gatt_init(void)
                goto failed;
        }
 
-       manager_id = g_dbus_connection_register_object(g_conn, app_path,
-                                               node_info->interfaces[0],
-                                               &manager_interface_vtable,
-                                               NULL, NULL, &error);
+       if (manager_id == 0) {
+               BT_INFO("manager_id does not exists");
+
+               manager_id = g_dbus_connection_register_object(g_conn, app_path,
+                                                       node_info->interfaces[0],
+                                                       &manager_interface_vtable,
+                                                       NULL, NULL, &error);
+       }
 
        if (manager_id == 0) {
                BT_ERR("failed to register: %s", error->message);
@@ -1511,18 +1571,16 @@ BT_EXPORT_API int bluetooth_gatt_init(void)
        return BLUETOOTH_ERROR_NONE;
 
 failed:
-       if (obj_info)
-               g_dbus_node_info_unref(obj_info);
-
        if (owner_id)
                g_bus_unown_name(owner_id);
 
        g_free(app_path);
 
-       obj_info = NULL;
        app_path = NULL;
        owner_id = 0;
 
+       __bt_gatt_close_gdbus_connection();
+
        return BLUETOOTH_ERROR_INTERNAL;
 }
 
@@ -1539,6 +1597,8 @@ BT_EXPORT_API int bluetooth_gatt_deinit()
                g_dbus_connection_unregister_object(g_conn,
                                        manager_id);
 
+               manager_id = 0;
+
                ret = bluetooth_gatt_unregister_application();
                if (ret != BLUETOOTH_ERROR_NONE)
                        BT_ERR("Fail to unregister application\n");
@@ -1554,16 +1614,16 @@ BT_EXPORT_API int bluetooth_gatt_deinit()
                g_slist_free(gatt_services);
                gatt_services = NULL;
 
-               /* Temperary block under codes to avoid TC blocking issue.
-                   But we should unref node info in later. */
-#if 0
-               g_dbus_node_info_unref(obj_info);
-               obj_info = NULL;
-#endif
+               g_object_unref(manager_gproxy);
+               manager_gproxy = NULL;
+
+               __bt_gatt_close_gdbus_connection();
 
                return ret;
        }
 
+       __bt_gatt_close_gdbus_connection();
+
        return BLUETOOTH_ERROR_NOT_FOUND;
 }
 
@@ -1883,6 +1943,7 @@ BT_EXPORT_API int bluetooth_gatt_add_descriptor(
        char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
        if (char_info == NULL) {
                g_strfreev(line_argv);
+               g_free(serv_path);
                return BLUETOOTH_ERROR_INVALID_PARAM;
        }
 
@@ -1891,6 +1952,7 @@ BT_EXPORT_API int bluetooth_gatt_add_descriptor(
 
        if (node_info == NULL) {
                g_strfreev(line_argv);
+               g_free(serv_path);
                return BLUETOOTH_ERROR_INTERNAL;
        }
 
@@ -1907,6 +1969,7 @@ BT_EXPORT_API int bluetooth_gatt_add_descriptor(
                g_error_free(error);
                g_free(path);
                g_strfreev(line_argv);
+               g_free(serv_path);
 
                return BLUETOOTH_ERROR_INTERNAL;
        }
@@ -1959,6 +2022,7 @@ BT_EXPORT_API int bluetooth_gatt_add_descriptor(
        *desc_path = g_strdup(path);
 
        g_free(path);
+       g_free(serv_path);
        g_strfreev(line_argv);
        g_variant_builder_unref(inner_builder);
        g_variant_builder_unref(builder);
@@ -2171,6 +2235,7 @@ BT_EXPORT_API int bluetooth_gatt_update_characteristic(
 
        if (!__bt_gatt_get_service_state(serv_path)) {
                BT_DBG("service not registered for this characteristic \n");
+               g_free(serv_path);
                g_strfreev(line_argv);
                return BLUETOOTH_ERROR_INTERNAL;
        }
@@ -2212,6 +2277,12 @@ BT_EXPORT_API int bluetooth_gatt_update_characteristic(
 
                char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path);
                if (char_info == NULL) {
+                       g_free(serv_path);
+                       g_strfreev(line_argv);
+                       g_variant_builder_unref(inner_builder);
+                       g_variant_builder_unref(outer_builder);
+                       g_variant_builder_unref(invalidated_builder);
+
                        return BLUETOOTH_ERROR_INVALID_DATA;
                }
 
@@ -2225,6 +2296,7 @@ BT_EXPORT_API int bluetooth_gatt_update_characteristic(
                }
        }
 
+       g_free(serv_path);
        g_strfreev(line_argv);
        g_variant_builder_unref(inner_builder);
        g_variant_builder_unref(outer_builder);
@@ -2233,13 +2305,56 @@ BT_EXPORT_API int bluetooth_gatt_update_characteristic(
        return err;
 }
 
+static void __bt_gatt_free_descriptor_info(struct gatt_desc_info *desc_info)
+{
+       int i;
+
+       if (!desc_info)
+               return;
+
+       g_free(desc_info->desc_path);
+       g_free(desc_info->desc_uuid);
+       g_free(desc_info->desc_value);
+
+       for (i = 0; i < desc_info->flags_length; i++)
+               g_free(desc_info->desc_flags[i]);
+
+       g_free(desc_info);
+}
+
+static void __bt_gatt_free_characteristic_info(struct gatt_char_info *char_info)
+{
+       int i;
+
+       if (!char_info)
+               return;
+
+       g_free(char_info->char_path);
+       g_free(char_info->char_uuid);
+       g_free(char_info->char_value);
+
+       for (i = 0; i < char_info->flags_length; i++)
+               g_free(char_info->char_flags[i]);
+
+       g_free(char_info);
+}
+
+static void __bt_gatt_free_service_info(struct gatt_service_info *svc_info)
+{
+       if (!svc_info)
+               return;
+
+       g_free(svc_info->serv_path);
+       g_free(svc_info->service_uuid);
+       g_free(svc_info);
+}
+
 BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
 {
        GSList *l, *l1;
        struct gatt_service_info *svc_info;
        gboolean ret;
        int err = BLUETOOTH_ERROR_NONE;
-       GSList *tmp;
 
        BT_DBG("svc_path %s", svc_path);
        svc_info = __bt_gatt_find_gatt_service_info(svc_path);
@@ -2258,9 +2373,15 @@ BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
        for (l = svc_info->char_data; l != NULL; l = l->next) {
                struct gatt_char_info *char_info = l->data;
 
+               if (char_info == NULL)
+                       break;
+
                for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) {
                        struct gatt_desc_info *desc_info = l1->data;
 
+                       if (desc_info == NULL)
+                               break;
+
                        ret = g_dbus_connection_unregister_object(g_conn,
                                                desc_info->desc_id);
                        if (ret) {
@@ -2270,7 +2391,15 @@ BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
                        } else {
                                err = BLUETOOTH_ERROR_INTERNAL;
                        }
+
+                       /* list remove & free */
+                       char_info->desc_data = g_slist_remove(char_info->desc_data, desc_info);
+                       __bt_gatt_free_descriptor_info(desc_info);
                }
+
+               g_slist_free(char_info->desc_data);
+               char_info->desc_data = NULL;
+
                ret = g_dbus_connection_unregister_object(g_conn,
                                        char_info->char_id);
                if (ret) {
@@ -2279,7 +2408,15 @@ BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
                } else {
                        err = BLUETOOTH_ERROR_INTERNAL;
                }
+
+               /* list remove & free */
+               svc_info->char_data = g_slist_remove(svc_info->char_data, char_info);
+               __bt_gatt_free_characteristic_info(char_info);
        }
+
+       g_slist_free(svc_info->char_data);
+       svc_info->char_data = NULL;
+
        ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id);
        if (ret) {
                __bt_gatt_emit_interface_removed(svc_info->serv_path,
@@ -2293,18 +2430,17 @@ BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path)
                BT_DBG("Unregistered the service on properties interface");
        }
 
-       for (tmp = gatt_services; tmp != NULL; tmp = tmp->next) {
-               struct gatt_service_info *info = tmp->data;
-
-               if (g_strcmp0(info->serv_path, svc_path) == 0) {
-                       gatt_services = g_slist_delete_link(gatt_services, tmp->data);
-               }
-       }
+       /* list remove & free */
+       gatt_services = g_slist_remove(gatt_services, svc_info);
+       __bt_gatt_free_service_info(svc_info);
 
        new_service = FALSE;
 
-       if (gatt_services->next == NULL)
+       if (gatt_services == NULL) {
+               serv_id = 1;
+       } else if (gatt_services->next == NULL) {
                serv_id--;
+       }
 
        return err;
 }
@@ -2324,11 +2460,8 @@ BT_EXPORT_API int bluetooth_gatt_send_response(int request_id, guint req_type,
 
        if (req_info) {
                if (resp_state != BLUETOOTH_ERROR_NONE) {
-
-                       GQuark quark = g_quark_from_string("gatt-server");
-                       GError *err = g_error_new(quark, 0, "Application Error");
-                       g_dbus_method_invocation_return_gerror(req_info->context, err);
-                       g_error_free(err);
+                       g_dbus_method_invocation_return_dbus_error(req_info->context,
+                                               "org.bluez.Error.Failed", "Application Error");
 
                        gatt_requests = g_slist_remove(gatt_requests, req_info);
 
@@ -2388,10 +2521,13 @@ BT_EXPORT_API int bluetooth_gatt_server_set_notification(const char *char_path,
 
        if (!__bt_gatt_get_service_state(serv_path)) {
                BT_DBG("service not registered for this characteristic \n");
+               g_free(serv_path);
                g_strfreev(line_argv);
                return BLUETOOTH_ERROR_INTERNAL;
        }
 
+       g_free(serv_path);
+
        outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));