diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | ChangeLog.ja | 8 | ||||
-rw-r--r-- | libsylph/session.c | 30 | ||||
-rw-r--r-- | libsylph/socket.c | 79 |
4 files changed, 100 insertions, 25 deletions
@@ -1,3 +1,11 @@ +2006-10-13 + + * libsylph/socket.c: win32: properly handle WSAEWOULDBLOCK. + is_nonblocking_mode(): implemented by saving SockInfo list. + * libsylph/session.c: win32: session_ping_cb(): only dispatch if no + event occurs for more than one second. + Don't use sock_has_read_data() anymore. + 2006-10-12 * src/messageview.c: removed the border. diff --git a/ChangeLog.ja b/ChangeLog.ja index 00ec499e..d50c076d 100644 --- a/ChangeLog.ja +++ b/ChangeLog.ja @@ -1,3 +1,11 @@ +2006-10-13 + + * libsylph/socket.c: win32: WSAEWOULDBLOCK を正しく処理するようにした。 + is_nonblocking_mode(): SockInfo のリストを保持することで実装。 + * libsylph/session.c: win32: session_ping_cb(): 1秒以上イベントが発生 + しなかった場合のみ発行するようにした。 + sock_has_read_data() を使わないようにした。 + 2006-10-12 * src/messageview.c: 境界を除去。 diff --git a/libsylph/session.c b/libsylph/session.c index 5852cfeb..8a2779f7 100644 --- a/libsylph/session.c +++ b/libsylph/session.c @@ -264,8 +264,22 @@ static gboolean session_ping_cb(gpointer data) Session *session = SESSION(data); SockInfo *sock = session->sock; - if (session->io_tag > 0 && sock && sock->callback) - sock->callback(sock, sock->condition, sock->data); + if (session->io_tag > 0 && sock && sock->callback) { + GTimeVal tv_cur, tv_result; + + g_get_current_time(&tv_cur); + tv_result.tv_sec = tv_cur.tv_sec - session->tv_prev.tv_sec; + tv_result.tv_usec = tv_cur.tv_usec - session->tv_prev.tv_usec; + if (tv_result.tv_usec < 0) { + tv_result.tv_sec--; + tv_result.tv_usec += G_USEC_PER_SEC; + } + if (tv_result.tv_sec * G_USEC_PER_SEC + tv_result.tv_usec > + G_USEC_PER_SEC) { + debug_print("state machine freeze for 1 second detected, forcing dispatch.\n"); + sock->callback(sock, sock->condition, sock->data); + } + } return TRUE; } @@ -541,8 +555,6 @@ static gboolean session_read_msg_cb(SockInfo *source, GIOCondition condition, if (session->read_buf_len == 0) { gint read_len; - if (!sock_has_read_data(session->sock)) - return TRUE; read_len = sock_read(session->sock, session->read_buf, SESSION_BUFFSIZE - 1); @@ -557,7 +569,7 @@ static gboolean session_read_msg_cb(SockInfo *source, GIOCondition condition, case EAGAIN: return TRUE; default: - g_warning("sock_read: %s\n", g_strerror(errno)); + g_warning("%s: sock_read: %s\n", G_STRFUNC, g_strerror(errno)); session->state = SESSION_ERROR; return FALSE; } @@ -629,8 +641,6 @@ static gboolean session_read_data_cb(SockInfo *source, GIOCondition condition, if (session->read_buf_len == 0) { gint read_len; - if (!sock_has_read_data(session->sock)) - return TRUE; read_len = sock_read(session->sock, session->read_buf, SESSION_BUFFSIZE); @@ -645,7 +655,7 @@ static gboolean session_read_data_cb(SockInfo *source, GIOCondition condition, case EAGAIN: return TRUE; default: - g_warning("sock_read: %s\n", g_strerror(errno)); + g_warning("%s: sock_read: %s\n", G_STRFUNC, g_strerror(errno)); session->state = SESSION_ERROR; return FALSE; } @@ -742,8 +752,6 @@ static gboolean session_read_data_as_file_cb(SockInfo *source, session_set_timeout(session, session->timeout_interval); if (session->read_buf_len == 0) { - if (!sock_has_read_data(session->sock)) - return TRUE; read_len = sock_read(session->sock, session->read_buf_p, READ_BUF_LEFT()); @@ -758,7 +766,7 @@ static gboolean session_read_data_as_file_cb(SockInfo *source, case EAGAIN: return TRUE; default: - g_warning("sock_read: %s\n", g_strerror(errno)); + g_warning("%s: sock_read: %s\n", G_STRFUNC, g_strerror(errno)); session->state = SESSION_ERROR; return FALSE; } diff --git a/libsylph/socket.c b/libsylph/socket.c index c0395177..3e0982d1 100644 --- a/libsylph/socket.c +++ b/libsylph/socket.c @@ -111,6 +111,7 @@ struct _SockSource { static guint io_timeout = 60; static GList *sock_connect_data_list = NULL; +static GList *sock_list = NULL; static gboolean sock_prepare (GSource *source, gint *timeout); @@ -126,6 +127,8 @@ GSourceFuncs sock_watch_funcs = { NULL }; +static SockInfo *sock_find_from_fd (gint fd); + static gint sock_connect_with_timeout (gint sock, const struct sockaddr *serv_addr, gint addrlen, @@ -345,17 +348,36 @@ gint fd_accept(gint sock) return accept(sock, (struct sockaddr *)&caddr, &caddr_len); } + +static SockInfo *sock_find_from_fd(gint fd) +{ + GList *cur; + + for (cur = sock_list; cur != NULL; cur = cur->next) { + if (((SockInfo *)cur->data)->sock == fd) + return (SockInfo *)cur->data; + } + + return NULL; +} + static gint set_nonblocking_mode(gint fd, gboolean nonblock) { #ifdef G_OS_WIN32 gulong val = nonblock ? 1 : 0; + SockInfo *sock; if (!nonblock) WSAEventSelect(fd, NULL, 0); if (ioctlsocket(fd, FIONBIO, &val) == SOCKET_ERROR) { - g_warning("set_nonblocking_mode(): ioctlsocket() failed: %ld\n", WSAGetLastError()); + g_warning("set_nonblocking_mode(): ioctlsocket() failed: %ld\n", + WSAGetLastError()); return -1; } + + sock = sock_find_from_fd(fd); + if (sock) + sock->nonblock = nonblock; debug_print("set nonblocking mode to %d\n", nonblock); return 0; @@ -392,7 +414,15 @@ gint sock_set_nonblocking_mode(SockInfo *sock, gboolean nonblock) static gboolean is_nonblocking_mode(gint fd) { -#ifdef G_OS_UNIX +#ifdef G_OS_WIN32 + SockInfo *sock; + + sock = sock_find_from_fd(fd); + if (sock) + return sock->nonblock; + + return FALSE; +#else gint flags; flags = fcntl(fd, F_GETFL, 0); @@ -402,8 +432,6 @@ static gboolean is_nonblocking_mode(gint fd) } return ((flags & O_NONBLOCK) != 0); -#else - return FALSE; #endif } @@ -427,8 +455,11 @@ gboolean sock_has_read_data(SockInfo *sock) if (sock->ssl) return TRUE; #endif - if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) + if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) { + g_warning("sock_has_read_data(): ioctlsocket() failed: %ld\n", + WSAGetLastError()); return TRUE; + } if (val == 0) return FALSE; @@ -770,6 +801,8 @@ SockInfo *sock_connect(const gchar *hostname, gushort port) sockinfo->state = CONN_ESTABLISHED; sockinfo->nonblock = FALSE; + sock_list = g_list_prepend(sock_list, sockinfo); + g_usleep(100000); return sockinfo; @@ -828,6 +861,8 @@ static gboolean sock_connect_async_cb(GIOChannel *source, sockinfo->state = CONN_ESTABLISHED; sockinfo->nonblock = TRUE; + sock_list = g_list_prepend(sock_list, sockinfo); + conn_data->func(sockinfo, conn_data->data); sock_connect_async_cancel(conn_data->id); @@ -1200,16 +1235,15 @@ gint sock_printf(SockInfo *sock, const gchar *format, ...) } #ifdef G_OS_WIN32 -static void sock_set_errno_from_last_error(void) +static void sock_set_errno_from_last_error(gint error) { - gint err; - - errno = 0; - switch ((err = WSAGetLastError())) { + switch (error) { case WSAEWOULDBLOCK: errno = EAGAIN; break; default: + debug_print("last error = %d\n", error); + errno = 0; break; } } @@ -1290,8 +1324,12 @@ gint fd_write(gint fd, const gchar *buf, gint len) #ifdef G_OS_WIN32 ret = send(fd, buf, len, 0); if (ret == SOCKET_ERROR) { - g_warning("fd_write() failed: %ld\n", WSAGetLastError()); - sock_set_errno_from_last_error(); + gint err; + err = WSAGetLastError(); + sock_set_errno_from_last_error(err); + if (err != WSAEWOULDBLOCK) + g_warning("fd_write() failed with %d (errno = %d)\n", + err, errno); } return ret; #else @@ -1375,8 +1413,12 @@ gint fd_recv(gint fd, gchar *buf, gint len, gint flags) #ifdef G_OS_WIN32 ret = recv(fd, buf, len, flags); if (ret == SOCKET_ERROR) { - g_warning("fd_recv() failed: %ld\n", WSAGetLastError()); - sock_set_errno_from_last_error(); + gint err; + err = WSAGetLastError(); + sock_set_errno_from_last_error(err); + if (err != WSAEWOULDBLOCK) + g_warning("fd_recv(): failed with %d (errno = %d)\n", + err, errno); } return ret; #else @@ -1558,6 +1600,8 @@ gint sock_peek(SockInfo *sock, gchar *buf, gint len) gint sock_close(SockInfo *sock) { + GList *cur; + if (!sock) return 0; @@ -1571,6 +1615,13 @@ gint sock_close(SockInfo *sock) g_io_channel_unref(sock->sock_ch); } + for (cur = sock_list; cur != NULL; cur = cur->next) { + if ((SockInfo *)cur->data == sock) { + sock_list = g_list_remove(sock_list, sock); + break; + } + } + g_free(sock->hostname); g_free(sock); |