From ada2c47597069f8c996c42c6b6339b8e5cbae6f2 Mon Sep 17 00:00:00 2001 From: Atul Rai Date: Fri, 11 Nov 2016 14:16:21 +0530 Subject: [PATCH] [Adapt:HDP]Fix HDP app unexpected termination This patch fixes unexpected crash of HDP application in bt-api when HDP connection is terminated from remote device. Change-Id: I282260b9ac0fb2bd10b5374e8f1c8791f8172076 Signed-off-by: Atul Rai --- bt-api/bt-hdp.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/bt-api/bt-hdp.c b/bt-api/bt-hdp.c index 52fb3d9..9481c1c 100755 --- a/bt-api/bt-hdp.c +++ b/bt-api/bt-hdp.c @@ -56,11 +56,15 @@ static int privilege_token; static void __bt_hdp_obj_info_free(hdp_obj_info_t *info) { - if (info) { - g_source_remove(info->watch_id); - close(info->fd); - g_free(info); - } + BT_DBG("+"); + + ret_if(NULL == info); + + g_source_remove(info->watch_id); + close(info->fd); + g_free(info); + + BT_DBG("-"); } static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle) @@ -111,6 +115,33 @@ static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_ch_id(unsigned in return NULL; } +static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(unsigned int sock_fd) +{ + GSList *l; + GSList *iter; + + retv_if(g_app_list == NULL, NULL); + + BT_DBG("List length = %d\n", g_slist_length(g_app_list)); + + for (l = g_app_list; l != NULL; l = l->next) { + hdp_app_list_t *list = l->data; + if (!list) + return NULL; + + for (iter = list->obj_info; iter != NULL; iter = iter->next) { + hdp_obj_info_t *info = iter->data; + if (!info) + return NULL; + + if (sock_fd == info->fd) + return info; + } + } + + return NULL; +} + static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, GIOCondition cond, gpointer data) { @@ -120,19 +151,41 @@ static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, char buff[HDP_BUFFER_SIZE] = { 0, }; GError *err = NULL; GIOStatus status = G_IO_STATUS_NORMAL; - hdp_obj_info_t *info = data; + bluetooth_device_address_t *address = data; + hdp_obj_info_t *info; BT_DBG("+"); - retv_if(NULL == info, FALSE); - fd = g_io_channel_unix_get_fd(gio); + BT_DBG("fd: %d", fd); + + info = __bt_hdp_internal_gslist_obj_find_using_fd(fd); + if (!info) { + BT_INFO("No obj info found for fd: %d", fd); + g_free(address); + return FALSE; + } + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + bt_hdp_disconnected_t disconn_info; + bt_user_info_t *user_info; + hdp_app_list_t *list; + BT_DBG("GIOCondition %d", cond); - g_io_channel_shutdown(gio, TRUE, NULL); - g_io_channel_unref(gio); - _bt_hdp_app_remove_obj_info(info->channel_id); - /* TODO: call hdp_disconnect and send disconnect event if needed */ + disconn_info.channel_id = info->channel_id; + memcpy(&disconn_info.device_address, address, sizeof(bluetooth_device_address_t)); + + list = __bt_hdp_internal_gslist_find_app_handler(info->app_handle); + if (list) { + list->obj_info = g_slist_remove(list->obj_info, info); + __bt_hdp_obj_info_free(info); + } + + user_info = _bt_get_user_data(BT_COMMON); + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, + BLUETOOTH_ERROR_NONE, &disconn_info, + user_info->cb, user_info->user_data); + g_free(address); return FALSE; } @@ -143,6 +196,7 @@ static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, BT_ERR("IO Channel read error [%s]", err->message); g_error_free(err); } + g_free(address); return FALSE; } @@ -168,6 +222,7 @@ static void __hdp_handle_new_connection(bt_hdp_connected_t *conn_info, int fd) { hdp_obj_info_t *info; hdp_app_list_t *list; + bluetooth_device_address_t *address; GIOChannel *gio; BT_DBG("+"); @@ -182,11 +237,12 @@ static void __hdp_handle_new_connection(bt_hdp_connected_t *conn_info, int fd) info->channel_id = conn_info->channel_id; info->app_handle = list->app_handle; info->fd = fd; + address = g_memdup(&(conn_info->device_address), sizeof(bluetooth_device_address_t)); gio = g_io_channel_unix_new(fd); g_io_channel_set_close_on_unref(gio, TRUE); info->watch_id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - __bt_hdp_internal_data_received, (void *)info); + __bt_hdp_internal_data_received, (void *)address); g_io_channel_unref(gio); list->obj_info = g_slist_append(list->obj_info, info); @@ -207,6 +263,7 @@ void _bt_hdp_app_remove_obj_info(unsigned int channel_id) ret_if(NULL == list); list->obj_info = g_slist_remove(list->obj_info, info); + BT_DBG("obj_info length = %d\n", g_slist_length(list->obj_info)); __bt_hdp_obj_info_free(info); BT_DBG("-"); -- 2.7.4