Clear sender socket info when receive socket disconnected event 18/99418/4
authorHyunho Kang <hhstark.kang@samsung.com>
Wed, 23 Nov 2016 00:41:50 +0000 (09:41 +0900)
committerjusung son <jusung07.son@samsung.com>
Thu, 24 Nov 2016 01:31:19 +0000 (10:31 +0900)
Change-Id: Ic4a3d75aaa6a0c487c54315b84c0b4e83039d457
Signed-off-by: Hyunho Kang <hhstark.kang@samsung.com>
Signed-off-by: jusung son <jusung07.son@samsung.com>
src/message-port.c

index 523027a..216dc5d 100755 (executable)
@@ -131,6 +131,8 @@ typedef struct port_list_info {
        int send_sock_fd;
        int watcher_id;
        bool exist;
+       GIOChannel *gio_read;
+       int g_src_id;
 } port_list_info_s;
 
 static void __callback_info_free(gpointer data)
@@ -419,6 +421,42 @@ out:
        return remote_app_info;
 }
 
+static void __clear_disconnect_socket(port_list_info_s *port_info)
+{
+       GError *error = NULL;
+
+       if (port_info == NULL)
+               return;
+       _LOGI("__clear_disconnect_socket : fd [%d]", port_info->send_sock_fd);
+
+       if (port_info->gio_read != NULL) {
+               g_io_channel_shutdown(port_info->gio_read, TRUE, &error);
+               if (error) {
+                       _LOGE("g_io_channel_shutdown error : %s", error->message);
+                       g_error_free(error);
+               }
+               g_io_channel_unref(port_info->gio_read);
+               port_info->gio_read = NULL;
+       }
+
+       if (port_info->g_src_id != 0) {
+               g_source_remove(port_info->g_src_id);
+               port_info->g_src_id = 0;
+       }
+       port_info->send_sock_fd = 0;
+}
+
+static gboolean __socket_disconnect_handler(GIOChannel *gio,
+               GIOCondition cond,
+               gpointer data)
+{
+       /* It's sender socket's gio channel so, only EOF can be received */
+       port_list_info_s *port_info = (port_list_info_s *)data;
+       _LOGI("__socket_disconnect_handler %d", cond);
+       __clear_disconnect_socket(port_info);
+       return FALSE;
+}
+
 static void __watch_remote_port_info(port_list_info_s *port_info)
 {
        if (port_info == NULL)
@@ -843,7 +881,7 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation
                if (returned_fds == NULL) {
                        _LOGE("fail to get fds");
                        __callback_info_free(callback_info);
-                       return -1;
+                       return false;
                }
                fd = returned_fds[0];
 
@@ -854,7 +892,7 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation
                        if (!callback_info->gio_read) {
                                _LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf)));
                                __callback_info_free(callback_info);
-                               return -1;
+                               return false;
                        }
 
                        callback_info->g_src_id = g_io_add_watch(callback_info->gio_read, G_IO_IN | G_IO_HUP,
@@ -862,7 +900,7 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation
                        if (callback_info->g_src_id == 0) {
                                _LOGE("fail to add watch on socket");
                                __callback_info_free(callback_info);
-                               return -1;
+                               return false;
                        }
 
                        callback_info_list = g_hash_table_lookup(__callback_info_hash, GUINT_TO_POINTER(mi->local_id));
@@ -871,7 +909,7 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation
                                if (head_callback_info == NULL) {
                                        _LOGE("fail to alloc head_callback_info");
                                        __callback_info_free(callback_info);
-                                       return -1;
+                                       return false;
                                }
                                head_callback_info->local_id = 0;
                                head_callback_info->remote_app_id = NULL;
@@ -1384,22 +1422,26 @@ int __message_port_send_async(int sockfd, bundle *kb, const char *local_port,
 
        if (__write_string_to_socket(sockfd, local_port, local_port_len) != MESSAGEPORT_ERROR_NONE) {
                _LOGE("write local_port fail");
-               return MESSAGEPORT_ERROR_IO_ERROR;
+               ret = MESSAGEPORT_ERROR_IO_ERROR;
+               goto out;
        }
 
        if (__write_socket(sockfd, (char *)&is_bidirection, sizeof(is_bidirection), &nb) != MESSAGEPORT_ERROR_NONE) {
                _LOGE("write is_bidirection fail");
-               return MESSAGEPORT_ERROR_IO_ERROR;
+               ret = MESSAGEPORT_ERROR_IO_ERROR;
+               goto out;
        }
 
        if (__write_socket(sockfd, (char *)&local_trusted, sizeof(local_trusted), &nb) != MESSAGEPORT_ERROR_NONE) {
                _LOGE("write local_trusted fail");
-               return MESSAGEPORT_ERROR_IO_ERROR;
+               ret = MESSAGEPORT_ERROR_IO_ERROR;
+               goto out;
        }
 
        if (__write_string_to_socket(sockfd, (void *)kb_data, data_len) != MESSAGEPORT_ERROR_NONE) {
                _LOGE("write kb_data fail");
                ret = MESSAGEPORT_ERROR_IO_ERROR;
+               goto out;
        }
 out:
        if (kb_data)
@@ -1426,6 +1468,7 @@ static int __message_port_send_message(const char *remote_appid, const char *rem
        GError *err = NULL;
        GVariant *body = NULL;
        int sock_pair[2] = {0,};
+       char buf[1024];
 
        ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
        if (ret != MESSAGEPORT_ERROR_NONE)
@@ -1442,7 +1485,6 @@ static int __message_port_send_message(const char *remote_appid, const char *rem
                        goto out;
                }
        }
-       __watch_remote_port_info(port_info);
 
        if (port_info->send_sock_fd > 0) {
                ret = __message_port_send_async(port_info->send_sock_fd, message,
@@ -1480,12 +1522,28 @@ static int __message_port_send_message(const char *remote_appid, const char *rem
                                        _LOGE("g_unix_fd_list_append [%s]", err->message);
                                        ret = MESSAGEPORT_ERROR_IO_ERROR;
                                        g_error_free(err);
-                                       close(sock_pair[SOCK_PAIR_SENDER]);
-                                       close(sock_pair[SOCK_PAIR_RECEIVER]);
                                        goto out;
                                }
+
                                port_info->send_sock_fd = sock_pair[SOCK_PAIR_SENDER];
                                close(sock_pair[SOCK_PAIR_RECEIVER]);
+                               sock_pair[SOCK_PAIR_RECEIVER] = 0;
+
+                               port_info->gio_read = g_io_channel_unix_new(port_info->send_sock_fd);
+                               if (!port_info->gio_read) {
+                                       _LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf)));
+                                       ret = MESSAGEPORT_ERROR_IO_ERROR;
+                                       goto out;
+                               }
+
+                               port_info->g_src_id = g_io_add_watch(port_info->gio_read, G_IO_IN | G_IO_HUP,
+                                               __socket_disconnect_handler, (gpointer)port_info);
+                               if (port_info->g_src_id == 0) {
+                                       _LOGE("fail to add watch on socket");
+                                       ret = MESSAGEPORT_ERROR_IO_ERROR;
+                                       goto out;
+                               }
+
                        }
                }
 
@@ -1505,7 +1563,7 @@ static int __message_port_send_message(const char *remote_appid, const char *rem
                        ret = MESSAGEPORT_ERROR_IO_ERROR;
                        goto out;
                }
-
+               __watch_remote_port_info(port_info);
 
        }
 
@@ -1517,6 +1575,13 @@ out:
        if (fd_list)
                g_object_unref(fd_list);
 
+       if (ret != MESSAGEPORT_ERROR_NONE) {
+               __clear_disconnect_socket(port_info);
+               if (sock_pair[SOCK_PAIR_SENDER])
+                       close(sock_pair[SOCK_PAIR_SENDER]);
+               if (sock_pair[SOCK_PAIR_RECEIVER])
+                       close(sock_pair[SOCK_PAIR_RECEIVER]);
+       }
 
        return ret;
 }