[libsoup] Bug 574414 – Make SOUP_SESSION_TIMEOUT work with SoupSessionAsync



commit c3c420f75359da299ffa8912e595c8b99ac40912
Author: Dan Winship <danw gnome org>
Date:   Sat Apr 18 08:29:28 2009 -0400

    Bug 574414 â?? Make SOUP_SESSION_TIMEOUT work with SoupSessionAsync
    
    soup-socket.c: when adding an IO watch to wait for an async socket to
    become readable/writable, add a timeout as well, and fail if the
    timeout times out.
    
    soup-connection.c: Pass the TIMEOUT flag to async sockets too
---
 libsoup/soup-connection.c |    1 +
 libsoup/soup-socket.c     |   59 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 4671ce9..99ec6c2 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -540,6 +540,7 @@ address_resolved (SoupAddress *addr, guint status, gpointer data)
 		soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr,
 				 SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
 				 SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
+				 SOUP_SOCKET_TIMEOUT, priv->io_timeout,
 				 NULL);
 	soup_socket_connect_async (priv->socket, NULL,
 				   socket_connect_result, conn);
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index f7b1a5c..d3f77f9 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -68,11 +68,13 @@ typedef struct {
 
 	guint non_blocking:1;
 	guint is_server:1;
+	guint timed_out:1;
 	gpointer ssl_creds;
 
 	GMainContext   *async_context;
 	GSource        *watch_src;
 	GSource        *read_src, *write_src;
+	GSource        *read_timeout, *write_timeout;
 	GByteArray     *read_buf;
 
 	GMutex *iolock, *addrlock;
@@ -129,6 +131,14 @@ disconnect_internal (SoupSocketPrivate *priv)
 		g_source_destroy (priv->write_src);
 		priv->write_src = NULL;
 	}
+	if (priv->read_timeout) {
+		g_source_destroy (priv->read_timeout);
+		priv->read_timeout = NULL;
+	}
+	if (priv->write_timeout) {
+		g_source_destroy (priv->write_timeout);
+		priv->write_timeout = NULL;
+	}
 }
 
 static void
@@ -1100,7 +1110,29 @@ soup_socket_get_remote_address (SoupSocket *sock)
 }
 
 
+static gboolean
+socket_timeout (gpointer sock)
+{
+	SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
+	gboolean readable = FALSE, writable = FALSE;
+
+	priv->timed_out = TRUE;
+	if (priv->read_timeout) {
+		priv->read_timeout = NULL;
+		readable = TRUE;
+	}
+	if (priv->write_timeout) {
+		priv->write_timeout = NULL;
+		writable = TRUE;
+	}
+
+	if (readable)
+		g_signal_emit (sock, signals[READABLE], 0);
+	if (writable)
+		g_signal_emit (sock, signals[WRITABLE], 0);
 
+	return FALSE;
+}
 
 static gboolean
 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
@@ -1109,6 +1141,10 @@ socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
 	SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
 
 	priv->read_src = NULL;
+	if (priv->read_timeout) {
+		g_source_destroy (priv->read_timeout);
+		priv->read_timeout = NULL;
+	}
 
 	if (cond & (G_IO_ERR | G_IO_HUP))
 		soup_socket_disconnect (sock);
@@ -1132,6 +1168,9 @@ read_from_network (SoupSocket *sock, gpointer buffer, gsize len,
 	if (!priv->iochannel)
 		return SOUP_SOCKET_EOF;
 
+	if (priv->timed_out)
+		return SOUP_SOCKET_ERROR;
+
 	status = g_io_channel_read_chars (priv->iochannel,
 					  buffer, len, nread, &my_err);
 	if (my_err) {
@@ -1162,6 +1201,12 @@ read_from_network (SoupSocket *sock, gpointer buffer, gsize len,
 						   priv->iochannel,
 						   cond | G_IO_HUP | G_IO_ERR,
 						   socket_read_watch, sock);
+			if (priv->timeout) {
+				priv->read_timeout =
+					soup_add_timeout (priv->async_context,
+							  priv->timeout * 1000,
+							  socket_timeout, sock);
+			}
 		}
 		g_clear_error (error);
 		return SOUP_SOCKET_WOULD_BLOCK;
@@ -1351,6 +1396,10 @@ socket_write_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
 	SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
 
 	priv->write_src = NULL;
+	if (priv->write_timeout) {
+		g_source_destroy (priv->write_timeout);
+		priv->write_timeout = NULL;
+	}
 
 	if (cond & (G_IO_ERR | G_IO_HUP))
 		soup_socket_disconnect (sock);
@@ -1407,6 +1456,10 @@ soup_socket_write (SoupSocket *sock, gconstpointer buffer,
 		g_mutex_unlock (priv->iolock);
 		return SOUP_SOCKET_EOF;
 	}
+	if (priv->timed_out) {
+		g_mutex_unlock (priv->iolock);
+		return SOUP_SOCKET_ERROR;
+	}
 	if (priv->write_src) {
 		g_mutex_unlock (priv->iolock);
 		return SOUP_SOCKET_WOULD_BLOCK;
@@ -1446,6 +1499,12 @@ soup_socket_write (SoupSocket *sock, gconstpointer buffer,
 				   priv->iochannel,
 				   cond | G_IO_HUP | G_IO_ERR, 
 				   socket_write_watch, sock);
+	if (priv->timeout) {
+		priv->write_timeout = soup_add_timeout (priv->async_context,
+							priv->timeout * 1000,
+							socket_timeout, sock);
+	}
+
 	g_mutex_unlock (priv->iolock);
 	return SOUP_SOCKET_WOULD_BLOCK;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]