aboutsummaryrefslogtreecommitdiff
path: root/libsylph
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2006-10-13 08:19:36 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2006-10-13 08:19:36 +0000
commitfd29edf0a3aa8112cd3b00e49eef3fa103f3ec7e (patch)
tree5c8f22055c0e40e7f9bbcf1c59e80a5c892dce93 /libsylph
parent55692f4e09779ca2e5b898ea328080036d38f9bb (diff)
win32: fixed socket.c and session.c.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1230 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph')
-rw-r--r--libsylph/session.c30
-rw-r--r--libsylph/socket.c79
2 files changed, 84 insertions, 25 deletions
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);