On Fri, 19 Mar 2010, Kamil Dudka wrote:

I am fine with either variant. You choose. If it the negative value based one is the way to go, we need to decide what to return in case of EWOULDBLOCK.

How about something along the lines I made in the attached patch? I modified the internal API for the SSL receive function to allow the SSL library to properly return the exact error code or -1 for EWOULDBLOCK.

--

 / daniel.haxx.se
From facc421cdf5319832b4edd203dcdef133175268c Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <[email protected]>
Date: Sun, 21 Mar 2010 00:27:11 +0100
Subject: [PATCH] internal SSL API fix: push back error codes better

---
 lib/gtls.c   |   14 ++++++++------
 lib/gtls.h   |    4 ++--
 lib/nss.c    |   11 ++++++-----
 lib/nssg.h   |    4 ++--
 lib/sendf.c  |    8 +++-----
 lib/sslgen.c |   23 +++++++----------------
 lib/sslgen.h |    5 +++--
 lib/ssluse.c |    8 ++++----
 lib/ssluse.h |    4 ++--
 9 files changed, 37 insertions(+), 44 deletions(-)

diff --git a/lib/gtls.c b/lib/gtls.c
index 797d18b..fae89bb 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -758,13 +758,13 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
                        int num,                  /* socketindex */
                        char *buf,                /* store read data here */
                        size_t buffersize,        /* max amount to read */
-                       bool *wouldblock)
+                       int *curlcode)
 {
   ssize_t ret;
 
   ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
-    *wouldblock = TRUE;
+    *curlcode = -1;
     return -1;
   }
 
@@ -774,20 +774,22 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
     CURLcode rc = handshake(conn, conn->ssl[num].session, num, FALSE);
     if(rc)
       /* handshake() writes error message on its own */
-      return rc;
-    *wouldblock = TRUE; /* then return as if this was a wouldblock */
+      *curlcode = rc;
+    else
+      *curlcode = -1; /* then return as if this was a wouldblock */
     return -1;
   }
 
-  *wouldblock = FALSE;
   if(!ret) {
     failf(conn->data, "Peer closed the TLS connection");
+    *curlcode = CURLE_RECV_ERROR;
     return -1;
   }
 
   if(ret < 0) {
     failf(conn->data, "GnuTLS recv error (%d): %s",
           (int)ret, gnutls_strerror((int)ret));
+    *curlcode = CURLE_RECV_ERROR;
     return -1;
   }
 
diff --git a/lib/gtls.h b/lib/gtls.h
index 661cfef..5216c73 100644
--- a/lib/gtls.h
+++ b/lib/gtls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -43,7 +43,7 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
                        int num,                  /* socketindex */
                        char *buf,                /* store read data here */
                        size_t buffersize,        /* max amount to read */
-                       bool *wouldblock);
+                       int *curlcode);
 void Curl_gtls_session_free(void *ptr);
 size_t Curl_gtls_version(char *buffer, size_t size);
 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
diff --git a/lib/nss.c b/lib/nss.c
index d3f31bd..1515228 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -1367,7 +1367,7 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
                       int num,                   /* socketindex */
                       char *buf,                 /* store read data here */
                       size_t buffersize,         /* max amount to read */
-                      bool * wouldblock)
+                      int *curlcode)
 {
   ssize_t nread;
 
@@ -1377,11 +1377,12 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
     /* failed SSL read */
     PRInt32 err = PR_GetError();
 
-    if(err == PR_WOULD_BLOCK_ERROR) {
-      *wouldblock = TRUE;
-      return -1; /* basically EWOULDBLOCK */
+    if(err == PR_WOULD_BLOCK_ERROR)
+      *curlcode = -1; /* EWOULDBLOCK */
+    else {
+      failf(conn->data, "SSL read: errno %d", err);
+      *curlcode = CURLE_RECV_ERROR;
     }
-    failf(conn->data, "SSL read: errno %d", err);
     return -1;
   }
   return nread;
diff --git a/lib/nssg.h b/lib/nssg.h
index 0af2a74..345ff57 100644
--- a/lib/nssg.h
+++ b/lib/nssg.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -51,7 +51,7 @@ ssize_t Curl_nss_recv(struct connectdata *conn, /* connection data */
                       int num,                  /* socketindex */
                       char *buf,                /* store read data here */
                       size_t buffersize,        /* max amount to read */
-                      bool *wouldblock);
+                      int *curlcode);
 
 size_t Curl_nss_version(char *buffer, size_t size);
 int Curl_nss_check_cxn(struct connectdata *cxn);
diff --git a/lib/sendf.c b/lib/sendf.c
index 79ffce7..2985147 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -536,13 +536,11 @@ int Curl_read(struct connectdata *conn, /* connection data */
   }
 
   if(conn->ssl[num].state == ssl_connection_complete) {
-    nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
+    int curlcode;
+    nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket, &curlcode);
 
     if(nread == -1)
-      return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
-    else if(nread == -2)
-      /* -2 from Curl_ssl_recv() means a true error, not EWOULDBLOCK */
-      return CURLE_RECV_ERROR;
+      return curlcode;
   }
   else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
     if(conn->protocol & PROT_SCP)
diff --git a/lib/sslgen.c b/lib/sslgen.c
index 6707e0a..57950fb 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -411,26 +411,17 @@ ssize_t Curl_ssl_send(struct connectdata *conn,
 /* return number of received (decrypted) bytes */
 
 /*
- * If the read would block (EWOULDBLOCK) we return -1. If an error occurs during
- * the read, we return -2. Otherwise we return the count of bytes transfered.
+ * If the read would block (EWOULDBLOCK) or fail, we we return -1.
+ * The error or -1 (for EWOULDBLOCK) is then stored in 'curlcode'
+ * Otherwise we return the count of bytes transfered.
  */
 ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
                       int sockindex,            /* socketindex */
                       char *mem,                /* store read data here */
-                      size_t len)               /* max amount to read */
+                      size_t len,               /* max amount to read */
+                      int *curlcode)
 {
-  ssize_t nread;
-  bool block = FALSE;
-
-  nread = curlssl_recv(conn, sockindex, mem, len, &block);
-  if(nread == -1) {
-    if(!block)
-      return -2; /* this is a true error, not EWOULDBLOCK */
-    else
-      return -1; /* EWOULDBLOCK */
-  }
-
-  return nread;
+  return curlssl_recv(conn, sockindex, mem, len, curlcode);
 }
 
 
diff --git a/lib/sslgen.h b/lib/sslgen.h
index d55bd1b..ef0b8a8 100644
--- a/lib/sslgen.h
+++ b/lib/sslgen.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2008, 2010, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -52,7 +52,8 @@ ssize_t Curl_ssl_send(struct connectdata *conn,
 ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
                       int sockindex,            /* socketindex */
                       char *mem,                /* store read data here */
-                      size_t len);              /* max amount to read */
+                      size_t len,               /* max amount to read */
+                      int *curlcode);           /* error to return */
 /* init the SSL session ID cache */
 CURLcode Curl_ssl_initsessions(struct SessionHandle *, long);
 size_t Curl_ssl_version(char *buffer, size_t size);
diff --git a/lib/ssluse.c b/lib/ssluse.c
index ec5c33b..2549634 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -2539,7 +2539,7 @@ ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
                        int num,                  /* socketindex */
                        char *buf,                /* store read data here */
                        size_t buffersize,        /* max amount to read */
-                       bool *wouldblock)
+                       int *curlcode)
 {
   char error_buffer[120]; /* OpenSSL documents that this must be at
                              least 120 bytes long. */
@@ -2549,7 +2549,6 @@ ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
 
   buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
   nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
-  *wouldblock = FALSE;
   if(nread < 0) {
     /* failed SSL_read */
     int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
@@ -2561,14 +2560,15 @@ ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
     case SSL_ERROR_WANT_READ:
     case SSL_ERROR_WANT_WRITE:
       /* there's data pending, re-invoke SSL_read() */
-      *wouldblock = TRUE;
-      return -1; /* basically EWOULDBLOCK */
+      *curlcode = -1;  /* EWOULDBLOCK */
+      return -1;
     default:
       /* openssl/ssl.h says "look at error stack/return value/errno" */
       sslerror = ERR_get_error();
       failf(conn->data, "SSL read: %s, errno %d",
             ERR_error_string(sslerror, error_buffer),
             SOCKERRNO);
+      *curlcode = CURLE_RECV_ERROR;
       return -1;
     }
   }
diff --git a/lib/ssluse.h b/lib/ssluse.h
index f0dd2be..3d13728 100644
--- a/lib/ssluse.h
+++ b/lib/ssluse.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
                        int num,                  /* socketindex */
                        char *buf,                /* store read data here */
                        size_t buffersize,        /* max amount to read */
-                       bool *wouldblock);
+                       int *curlcode);
 
 size_t Curl_ossl_version(char *buffer, size_t size);
 int Curl_ossl_check_cxn(struct connectdata *cxn);
-- 
1.7.0

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to