GATT: Clear dbus pending invocation list when gatt disconnection occurs.
authorAnuj Jain <anuj01.jain@samsung.com>
Sun, 20 Jun 2021 04:08:32 +0000 (09:38 +0530)
committerAyush Garg <ayush.garg@samsung.com>
Sun, 20 Jun 2021 04:23:05 +0000 (09:53 +0530)
In GATT client role, When an application makes a dbus sync request
to BT-Service and is waiting for its reply,
Meanwhile BT-Service encounters GATT disconnection, because of which
it could not send the corresponding replies to application as the
connection info is already removed and thus causing dbus timeout error.

This patch will prevent such situation by sending BLUTOOTH_INTERNAL_ERROR
reply corresponding to all those pending dbus invocations when GATT
disconnection occurs.

Change-Id: Ib1cc93427a0d7156885381174e81616010cf9267
Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
bt-service/services/gatt/bt-service-gatt.c

index a4e312f6d0d5d9cd86fbdff3f15117ddca772b25..6b27dde1e342bb89efb058376f259c17f0e58dc6 100644 (file)
@@ -922,6 +922,137 @@ static void __bt_gatt_get_pending_request_info(int service_function,
        }
 }
 
+static void __bt_gatt_cleanup_invocation_list(int result,
+                                               void *data, unsigned int size)
+{
+       GSList *l;
+       GArray *out_param;
+       invocation_info_t *req_info = NULL;
+       ret_if(data == NULL);
+
+       for (l = _bt_get_invocation_list(); l != NULL; ) {
+               req_info = l->data;
+               l = g_slist_next(l);
+
+               if (req_info == NULL)
+                       continue;
+
+               switch (req_info->service_function) {
+               case BT_GATT_GET_PRIMARY_SERVICES: {
+                       if(!g_strcmp0((char*)req_info->user_data, (char*)data)){
+                               bt_services_browse_info_t param;
+                               _bt_convert_addr_string_to_type(param.device_addr.addr, (char*)data);
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, &param, sizeof(bt_services_browse_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               BT_DBG("BT_GATT_GET_PRIMARY_SERVICES request cleared for address [%s]", (char*)data);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       break;
+               }
+               case BT_GATT_GET_SERVICE_PROPERTIES: {
+                       bluetooth_gatt_client_svc_prop_info_t *prop = (bluetooth_gatt_client_svc_prop_info_t*)req_info->user_data;
+                       char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+                       _bt_convert_addr_type_to_string(addr, prop->device_address.addr);
+                       if (!g_strcmp0(addr, (char*)data)){
+                               bt_char_browse_info_t param;
+                               _bt_convert_addr_string_to_type(param.device_addr.addr,addr);
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, &param, sizeof(bt_char_browse_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               BT_DBG("BT_GATT_GET_SERVICE_PROPERTIES request cleared for address [%s]", addr);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       g_free(addr);
+                       break;
+               }
+               case BT_GATT_GET_CHARACTERISTIC_PROPERTIES: {
+                       bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data;
+                       char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+                       _bt_convert_addr_type_to_string(addr, prop->device_address.addr);
+                       if (!g_strcmp0(addr, (char*)data)){
+                               bt_descriptor_browse_info_t param ;
+                               _bt_convert_addr_string_to_type(param.device_addr.addr, addr);
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, &param, sizeof(bt_descriptor_browse_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               BT_DBG("BT_GATT_GET_CHARACTERISTIC_PROPERTIES request cleared for address [%s]", addr);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       g_free(addr);
+                       break;
+               }
+               case BT_GATT_WATCH_CHARACTERISTIC: {
+                       char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+                       bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data;
+                       _bt_convert_addr_type_to_string(addr, prop->device_address.addr);
+                       if (!g_strcmp0(addr, (char*)data)){
+                               bt_gatt_notif_reg_info_t param;
+                               _bt_convert_addr_string_to_type(param.addr.addr, addr);
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, &param, sizeof(bt_gatt_notif_reg_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       g_free(addr);
+                       break;
+               }
+               case BT_GATT_READ_CHARACTERISTIC:
+               case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: {
+                       char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+                       bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data;
+                       _bt_convert_addr_type_to_string(addr, prop->device_address.addr);
+                       if (!g_strcmp0(addr, (char*)data)){
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, prop, sizeof(bluetooth_gatt_client_char_prop_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               BT_DBG("BT_GATT_READ/WRITE_CHARACTERISTIC request cleared for address [%s]", addr);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       g_free(addr);
+                       break;
+               }
+               case BT_GATT_READ_DESCRIPTOR_VALUE:
+               case BT_GATT_WRITE_DESCRIPTOR_VALUE: {
+                       char *addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+                       bluetooth_gatt_client_desc_prop_info_t *prop = (bluetooth_gatt_client_desc_prop_info_t*)req_info->user_data;
+                       _bt_convert_addr_type_to_string(addr, prop->device_address.addr);
+                       if (!g_strcmp0(addr, (char*)data)){
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               g_array_append_vals(out_param, prop, sizeof(bluetooth_gatt_client_desc_prop_info_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               BT_DBG("BT_GATT_READ/WRITE_DESCRIPTOR_VALUE request cleared for address [%s]", addr);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       g_free(addr);
+                       break;
+               }
+               case BT_REQ_ATT_MTU: {
+                       char *addr = (char*)req_info->user_data;
+                       bluetooth_device_address_t address;
+                       if (!g_strcmp0(addr, (char*)data)) {
+                               out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+                               _bt_convert_addr_string_to_type(address.addr, addr);
+                               g_array_append_vals(out_param, (bluetooth_device_address_t*)&address,
+                                               sizeof(bluetooth_device_address_t));
+                               _bt_service_method_return(req_info->context, out_param, result);
+                               _bt_free_info_from_invocation_list(req_info);
+                               g_array_free(out_param, TRUE);
+                       }
+                       break;
+               }
+               default:
+                       break;
+               }
+       }
+}
+
 static void __bt_gatt_handle_pending_request_info(int result,
                int service_function, void *data, unsigned int size)
 {
@@ -3509,6 +3640,11 @@ static void __bt_handle_client_disconnected(event_gattc_conn_t *event_data)
 
                /* Remove info from List */
                gatt_server_info_list = g_slist_remove(gatt_server_info_list, conn_info);
+
+               /* Remove all pending invocations from invocatin_list */
+               BT_INFO("Clear all pending invocations");
+               __bt_gatt_cleanup_invocation_list(BLUETOOTH_ERROR_INTERNAL, address, BT_ADDRESS_STRING_SIZE);
+
                BT_INFO("Total num of connected GATT servers [%d]", g_slist_length(gatt_server_info_list));
                g_free(conn_info->addr);
                g_free(conn_info);