From 3163467423257f6567fe977810ad42388a95fcdb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 7 Nov 2010 12:33:23 +0100 Subject: [PATCH] Deal with EAGAIN and GnuTLS channels --- gweb/giognutls.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gweb/giognutls.c b/gweb/giognutls.c index e6c1bde..06eff4a 100644 --- a/gweb/giognutls.c +++ b/gweb/giognutls.c @@ -44,6 +44,7 @@ struct _GIOGnuTLSChannel { gnutls_certificate_credentials_t cred; gnutls_session session; gboolean established; + gboolean again; }; struct _GIOGnuTLSWatch { @@ -68,15 +69,18 @@ static GIOStatus check_handshake(GIOChannel *channel, GError **err) DBG("channel %p", channel); -again: if (gnutls_channel->established == TRUE) return G_IO_STATUS_NORMAL; +again: result = gnutls_handshake(gnutls_channel->session); if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) { GIOFlags flags = g_io_channel_get_flags(channel); + if (gnutls_channel->again == TRUE) + return G_IO_STATUS_AGAIN; + if (flags & G_IO_FLAG_NONBLOCK) return G_IO_STATUS_AGAIN; @@ -124,6 +128,9 @@ again: if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) { GIOFlags flags = g_io_channel_get_flags(channel); + if (gnutls_channel->again == TRUE) + return G_IO_STATUS_AGAIN; + if (flags & G_IO_FLAG_NONBLOCK) return G_IO_STATUS_AGAIN; @@ -172,6 +179,9 @@ again: if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) { GIOFlags flags = g_io_channel_get_flags(channel); + if (gnutls_channel->again == TRUE) + return G_IO_STATUS_AGAIN; + if (flags & G_IO_FLAG_NONBLOCK) return G_IO_STATUS_AGAIN; @@ -352,6 +362,11 @@ static ssize_t g_io_gnutls_push_func(gnutls_transport_ptr_t transport_data, result = write(fd, buf, count); + if (result < 0 && errno == EAGAIN) + gnutls_channel->again = TRUE; + else + gnutls_channel->again = FALSE; + DBG("result %zd", result); return result; @@ -370,6 +385,11 @@ static ssize_t g_io_gnutls_pull_func(gnutls_transport_ptr_t transport_data, result = read(fd, buf, count); + if (result < 0 && errno == EAGAIN) + gnutls_channel->again = TRUE; + else + gnutls_channel->again = FALSE; + DBG("result %zd", result); return result; -- 2.7.4