/*! *\brief child and parent cleanup (child closes first) * *\param session Contains session information * *\return 0 : success */ static gint session_close(Session *session) { g_return_val_if_fail(session != NULL, -1); if (session->conn_id > 0) { sock_connect_async_cancel(session->conn_id); session->conn_id = 0; debug_print("session (%p): connection cancelled\n", session); } session_set_timeout(session, 0); if (session->io_tag > 0) { g_source_remove(session->io_tag); session->io_tag = 0; } if (session->sock) { sock_close(session->sock); session->sock = NULL; session->state = SESSION_DISCONNECTED; debug_print("session (%p): closed\n", session); } return 0; }
static gboolean sock_connect_async_cb(GIOChannel *source, GIOCondition condition, gpointer data) { SockConnectData *conn_data = (SockConnectData *)data; gint fd; gint val; guint len; SockInfo *sockinfo; fd = g_io_channel_unix_get_fd(source); conn_data->io_tag = 0; conn_data->channel = NULL; g_io_channel_unref(source); if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { debug_print("sock_connect_async_cb: condition = %d\n", condition); fd_close(fd); sock_connect_address_list_async(conn_data); return FALSE; } len = sizeof(val); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &len) < 0) { perror("getsockopt"); fd_close(fd); sock_connect_address_list_async(conn_data); return FALSE; } if (val != 0) { debug_print("getsockopt(SOL_SOCKET, SO_ERROR) returned error\n"); fd_close(fd); sock_connect_address_list_async(conn_data); return FALSE; } sockinfo = g_new0(SockInfo, 1); sockinfo->sock = fd; sockinfo->sock_ch = g_io_channel_unix_new(fd); sockinfo->hostname = g_strdup(conn_data->hostname); sockinfo->port = conn_data->port; sockinfo->state = CONN_ESTABLISHED; sockinfo->flags = SYL_SOCK_NONBLOCK; sock_list = g_list_prepend(sock_list, sockinfo); conn_data->func(sockinfo, conn_data->data); sock_connect_async_cancel(conn_data->id); return FALSE; }
static gboolean sock_connect_async_cb(GIOChannel *source, GIOCondition condition, gpointer data) { SockConnectData *conn_data = (SockConnectData *)data; gint fd; gint val; guint len; SockInfo *sockinfo; if (conn_data->io_tag == 0 && conn_data->channel == NULL) return FALSE; fd = g_io_channel_unix_get_fd(source); conn_data->io_tag = 0; conn_data->channel = NULL; g_io_channel_unref(source); len = sizeof(val); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &len) < 0) { perror("getsockopt"); close(fd); sock_connect_address_list_async(conn_data); return FALSE; } if (val != 0) { close(fd); log_error(LOG_PROTOCOL, _("%s:%d: connection failed (%s).\n"), conn_data->hostname, conn_data->port, strerror(val)); sock_connect_address_list_async(conn_data); return FALSE; } sockinfo = g_new0(SockInfo, 1); sockinfo->sock = fd; #ifndef G_OS_WIN32 sockinfo->sock_ch = g_io_channel_unix_new(fd); #else sockinfo->sock_ch = g_io_channel_win32_new_socket(fd); #endif sockinfo->hostname = g_strdup(conn_data->hostname); sockinfo->port = conn_data->port; sockinfo->state = CONN_ESTABLISHED; sockinfo->canonical_name = g_strdup(conn_data->canonical_name); conn_data->func(sockinfo, conn_data->data); sock_connect_async_cancel(conn_data->id); return FALSE; }
static gint sock_connect_address_list_async(SockConnectData *conn_data) { SockAddrData *addr_data; gint sock = -1; for (; conn_data->cur_addr != NULL; conn_data->cur_addr = conn_data->cur_addr->next) { addr_data = (SockAddrData *)conn_data->cur_addr->data; if ((sock = socket(addr_data->family, addr_data->socktype, addr_data->protocol)) < 0) { perror("socket"); continue; } sock_set_buffer_size(sock); set_nonblocking_mode(sock, TRUE); if (connect(sock, addr_data->addr, addr_data->addr_len) < 0) { if (EINPROGRESS == errno) { break; } else { perror("connect"); fd_close(sock); } } else break; } if (conn_data->cur_addr == NULL) { g_warning("sock_connect_address_list_async: " "connection to %s:%d failed\n", conn_data->hostname, conn_data->port); conn_data->func(NULL, conn_data->data); sock_connect_async_cancel(conn_data->id); return -1; } debug_print("sock_connect_address_list_async: waiting for connect\n"); conn_data->cur_addr = conn_data->cur_addr->next; conn_data->channel = g_io_channel_unix_new(sock); conn_data->io_tag = g_io_add_watch (conn_data->channel, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, sock_connect_async_cb, conn_data); return 0; }
static gint sock_connect_address_list_async(SockConnectData *conn_data) { SockAddrData *addr_data; gint sock = -1; for (; conn_data->cur_addr != NULL; conn_data->cur_addr = conn_data->cur_addr->next) { addr_data = (SockAddrData *)conn_data->cur_addr->data; if ((sock = socket(addr_data->family, addr_data->socktype, addr_data->protocol)) < 0) { perror("socket"); continue; } set_nonblocking_mode(sock, TRUE); if (connect(sock, addr_data->addr, addr_data->addr_len) < 0) { if (EINPROGRESS == errno) { break; } else { perror("connect"); close(sock); } } else { break; } } if (conn_data->cur_addr == NULL) { conn_data->func(NULL, conn_data->data); sock_connect_async_cancel(conn_data->id); return -1; } conn_data->cur_addr = conn_data->cur_addr->next; #ifndef G_OS_WIN32 conn_data->channel = g_io_channel_unix_new(sock); #else conn_data->channel = g_io_channel_win32_new_socket(sock); #endif conn_data->io_tag = g_io_add_watch(conn_data->channel, G_IO_IN|G_IO_OUT, sock_connect_async_cb, conn_data); return 0; }