From c3c420f75359da299ffa8912e595c8b99ac40912 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 18 Apr 2009 08:29:28 -0400 Subject: [PATCH] =?utf8?q?Bug=20574414=20=E2=80=93=20Make=20SOUP=5FSESSION?= =?utf8?q?=5FTIMEOUT=20work=20with=20SoupSessionAsync?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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(+) 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; } -- 2.7.4