File libsoup-2.2.96-blocking-eagain.patch of Package libsoup
--- trunk/libsoup/soup-gnutls.c 2006/11/20 21:47:04 900
+++ trunk/libsoup/soup-gnutls.c 2007/03/08 21:11:00 914
@@ -2,10 +2,7 @@
/*
* soup-gnutls.c
*
- * Authors:
- * Ian Peters <itp@ximian.com>
- *
- * Copyright (C) 2003, Ximian, Inc.
+ * Copyright (C) 2003-2006, Novell, Inc.
*/
#ifdef HAVE_CONFIG_H
@@ -15,6 +12,7 @@
#ifdef HAVE_SSL
#include <errno.h>
+#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
@@ -129,21 +127,26 @@
return TRUE;
}
+#define SOUP_GNUTLS_CHANNEL_NONBLOCKING(chan) (fcntl ((chan)->fd, F_GETFL, 0) & O_NONBLOCK)
+
static GIOStatus
do_handshake (SoupGNUTLSChannel *chan, GError **err)
{
int result;
+again:
result = gnutls_handshake (chan->session);
- if (result == GNUTLS_E_AGAIN ||
- result == GNUTLS_E_INTERRUPTED) {
- g_set_error (err, SOUP_SSL_ERROR,
- (gnutls_record_get_direction (chan->session) ?
- SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE :
- SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ),
- "Handshaking...");
- return G_IO_STATUS_AGAIN;
+ if (result == GNUTLS_E_AGAIN || result == GNUTLS_E_INTERRUPTED) {
+ if (SOUP_GNUTLS_CHANNEL_NONBLOCKING (chan)) {
+ g_set_error (err, SOUP_SSL_ERROR,
+ (gnutls_record_get_direction (chan->session) ?
+ SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE :
+ SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ),
+ "Handshaking...");
+ return G_IO_STATUS_AGAIN;
+ } else
+ goto again;
}
if (result < 0) {
@@ -172,6 +175,7 @@
*bytes_read = 0;
+again:
if (!chan->established) {
result = do_handshake (chan, err);
@@ -186,13 +190,17 @@
if (result == GNUTLS_E_REHANDSHAKE) {
chan->established = FALSE;
- return G_IO_STATUS_AGAIN;
+ goto again;
}
- if (result < 0) {
- if ((result == GNUTLS_E_INTERRUPTED) ||
- (result == GNUTLS_E_AGAIN))
+ if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) {
+ if (SOUP_GNUTLS_CHANNEL_NONBLOCKING (chan))
return G_IO_STATUS_AGAIN;
+ else
+ goto again;
+ }
+
+ if (result < 0) {
g_set_error (err, G_IO_CHANNEL_ERROR,
G_IO_CHANNEL_ERROR_FAILED,
"Received corrupted data");
@@ -216,6 +224,7 @@
*bytes_written = 0;
+again:
if (!chan->established) {
result = do_handshake (chan, err);
@@ -228,15 +237,22 @@
result = gnutls_record_send (chan->session, buf, count);
+ /* I'm pretty sure this can't actually happen in response to a
+ * write, but...
+ */
if (result == GNUTLS_E_REHANDSHAKE) {
chan->established = FALSE;
- return G_IO_STATUS_AGAIN;
+ goto again;
}
- if (result < 0) {
- if ((result == GNUTLS_E_INTERRUPTED) ||
- (result == GNUTLS_E_AGAIN))
+ if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) {
+ if (SOUP_GNUTLS_CHANNEL_NONBLOCKING (chan))
return G_IO_STATUS_AGAIN;
+ else
+ goto again;
+ }
+
+ if (result < 0) {
g_set_error (err, G_IO_CHANNEL_ERROR,
G_IO_CHANNEL_ERROR_FAILED,
"Received corrupted data");