aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES2
-rw-r--r--lib/gtls.c33
-rw-r--r--lib/gtls.h16
-rw-r--r--lib/nss.c31
-rw-r--r--lib/nssg.h10
-rw-r--r--lib/sendf.c34
-rw-r--r--lib/sslgen.c36
-rw-r--r--lib/sslgen.h27
-rw-r--r--lib/ssluse.c25
-rw-r--r--lib/ssluse.h10
10 files changed, 127 insertions, 97 deletions
diff --git a/CHANGES b/CHANGES
index 17a4d5991..cd84cf358 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,8 @@
Kamil Dudka (4 Apr 2010)
- Eliminated a race condition in Curl_resolv_timeout().
+- Refactorized interface of Curl_ssl_recv()/Curl_ssl_send().
+
Daniel Stenberg (1 Apr 2010)
- Matt Wixson found and fixed a bug in the SCP/SFTP area where the code
treated a 0 return code from libssh2 to be the same as EAGAIN while in
diff --git a/lib/gtls.c b/lib/gtls.c
index 079c6b1b0..b7fa3c926 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -638,18 +638,21 @@ Curl_gtls_connect(struct connectdata *conn,
}
-/* return number of sent (non-SSL) bytes */
+/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_gtls_send(struct connectdata *conn,
int sockindex,
const void *mem,
- size_t len)
+ size_t len,
+ int *curlcode)
{
ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
if(rc < 0 ) {
- if(rc == GNUTLS_E_AGAIN)
- return 0; /* EWOULDBLOCK equivalent */
- rc = -1; /* generic error code for send failure */
+ *curlcode = (rc == GNUTLS_E_AGAIN)
+ ? /* EWOULDBLOCK */ -1
+ : CURLE_SEND_ERROR;
+
+ rc = -1;
}
return rc;
@@ -748,22 +751,18 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
return retval;
}
-/*
- * If the read would block we return -1 and set 'wouldblock' to TRUE.
- * Otherwise we return the amount of data read. Other errors should return -1
- * and set 'wouldblock' to FALSE.
- */
+/* for documentation see Curl_ssl_recv() in sslgen.h */
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;
}
@@ -773,20 +772,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 0d3f3fa6e..9fe618a32 100644
--- a/lib/gtls.h
+++ b/lib/gtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,14 +35,14 @@ void Curl_gtls_close_all(struct SessionHandle *data);
/* close a SSL connection */
void Curl_gtls_close(struct connectdata *conn, int sockindex);
-/* return number of sent (non-SSL) bytes */
+/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_gtls_send(struct connectdata *conn, int sockindex,
- const void *mem, size_t len);
-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);
+ const void *mem, size_t len, int *curlcode);
+
+/* for documentation see Curl_ssl_recv() in sslgen.h */
+ssize_t Curl_gtls_recv(struct connectdata *conn, int num, char *buf,
+ size_t buffersize, 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 2babfdf1d..560154dd1 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -1340,47 +1340,50 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
return curlerr;
}
-/* return number of sent (non-SSL) bytes */
+/* for documentation see Curl_ssl_send() in sslgen.h */
int Curl_nss_send(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
const void *mem, /* send this data */
- size_t len) /* amount to write */
+ size_t len, /* amount to write */
+ int *curlcode)
{
int rc;
rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);
if(rc < 0) {
- failf(conn->data, "SSL write: error %d", PR_GetError());
+ PRInt32 err = PR_GetError();
+ if(err == PR_WOULD_BLOCK_ERROR)
+ *curlcode = -1; /* EWOULDBLOCK */
+ else {
+ failf(conn->data, "SSL write: error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
+ }
return -1;
}
return rc; /* number of bytes */
}
-/*
- * If the read would block we return -1 and set 'wouldblock' to TRUE.
- * Otherwise we return the amount of data read. Other errors should return -1
- * and set 'wouldblock' to FALSE.
- */
+/* for documentation see Curl_ssl_recv() in sslgen.h */
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;
nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, -1);
- *wouldblock = FALSE;
if(nread < 0) {
/* 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 6486e6275..309c3d6d8 100644
--- a/lib/nssg.h
+++ b/lib/nssg.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,15 +42,19 @@ int Curl_nss_close_all(struct SessionHandle *data);
int Curl_nss_init(void);
void Curl_nss_cleanup(void);
+/* for documentation see Curl_ssl_send() in sslgen.h */
int Curl_nss_send(struct connectdata *conn,
int sockindex,
const void *mem,
- size_t len);
+ size_t len,
+ int *curlcode);
+
+/* for documentation see Curl_ssl_recv() in sslgen.h */
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 7f7c2cb9d..90c527558 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -268,6 +268,9 @@ static ssize_t send_plain(struct connectdata *conn,
/*
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
+ *
+ * If the write would block (EWOULDBLOCK), we return CURLE_OK and
+ * (*written == 0). Otherwise we return regular CURLcode value.
*/
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
@@ -276,11 +279,11 @@ CURLcode Curl_write(struct connectdata *conn,
ssize_t *written)
{
ssize_t bytes_written;
- CURLcode retcode;
+ int curlcode = CURLE_OK;
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
if(conn->ssl[num].state == ssl_connection_complete)
- bytes_written = Curl_ssl_send(conn, num, mem, len);
+ bytes_written = Curl_ssl_send(conn, num, mem, len, &curlcode);
else if(Curl_ssh_enabled(conn, PROT_SCP))
bytes_written = Curl_scp_send(conn, num, mem, len);
else if(Curl_ssh_enabled(conn, PROT_SFTP))
@@ -291,9 +294,24 @@ CURLcode Curl_write(struct connectdata *conn,
bytes_written = send_plain(conn, num, mem, len);
*written = bytes_written;
- retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
+ if(-1 != bytes_written)
+ /* we completely ignore the curlcode value when -1 is not returned */
+ return CURLE_OK;
- return retcode;
+ /* handle EWOULDBLOCK or a send failure */
+ switch(curlcode) {
+ case /* EWOULDBLOCK */ -1:
+ *written = /* EWOULDBLOCK */ 0;
+ return CURLE_OK;
+
+ case CURLE_OK:
+ /* general send failure */
+ return CURLE_SEND_ERROR;
+
+ default:
+ /* we got a specific curlcode, forward it */
+ return (CURLcode)curlcode;
+ }
}
/*
@@ -535,13 +553,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 a050f1094..df2a4075a 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -408,38 +408,22 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
return curlssl_engines_list(data);
}
-/* return number of sent (non-SSL) bytes; -1 on error */
ssize_t Curl_ssl_send(struct connectdata *conn,
int sockindex,
const void *mem,
- size_t len)
+ size_t len,
+ int *curlcode)
{
- return curlssl_send(conn, sockindex, mem, len);
+ return curlssl_send(conn, sockindex, mem, len, curlcode);
}
-/* 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.
- */
-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 */
+ssize_t Curl_ssl_recv(struct connectdata *conn,
+ int sockindex,
+ char *mem,
+ size_t len,
+ 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 820f532f0..18858af15 100644
--- a/lib/sslgen.h
+++ b/lib/sslgen.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,14 +44,29 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data);
struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data);
-ssize_t Curl_ssl_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len);
+
+/* If the write 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 (non-SSL) bytes transfered.
+ */
+ssize_t Curl_ssl_send(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *mem, /* data to write */
+ size_t len, /* max amount to write */
+ int *curlcode); /* error to return,
+ -1 means EWOULDBLOCK */
+
+/* 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 (non-SSL) 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); /* error to return,
+ -1 means EWOULDBLOCK */
+
/* 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 bc354322a..d9cf38290 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -2482,11 +2482,12 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
return FALSE;
}
-/* return number of sent (non-SSL) bytes */
+/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_ossl_send(struct connectdata *conn,
int sockindex,
const void *mem,
- size_t len)
+ size_t len,
+ int *curlcode)
{
/* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */
@@ -2509,10 +2510,12 @@ ssize_t Curl_ossl_send(struct connectdata *conn,
/* The operation did not complete; the same TLS/SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
- return 0;
+ *curlcode = /* EWOULDBLOCK */ -1;
+ return -1;
case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d",
SOCKERRNO);
+ *curlcode = CURLE_SEND_ERROR;
return -1;
case SSL_ERROR_SSL:
/* A failure in the SSL library occurred, usually a protocol error.
@@ -2520,25 +2523,23 @@ ssize_t Curl_ossl_send(struct connectdata *conn,
sslerror = ERR_get_error();
failf(conn->data, "SSL_write() error: %s",
ERR_error_string(sslerror, error_buffer));
+ *curlcode = CURLE_SEND_ERROR;
return -1;
}
/* a true error */
failf(conn->data, "SSL_write() return error %d", err);
+ *curlcode = CURLE_SEND_ERROR;
return -1;
}
return (ssize_t)rc; /* number of bytes */
}
-/*
- * If the read would block we return -1 and set 'wouldblock' to TRUE.
- * Otherwise we return the amount of data read. Other errors should return -1
- * and set 'wouldblock' to FALSE.
- */
+/* for documentation see Curl_ssl_recv() in sslgen.h */
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. */
@@ -2548,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);
@@ -2560,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 9e58d204b..00357afc5 100644
--- a/lib/ssluse.h
+++ b/lib/ssluse.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -56,15 +56,19 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
int Curl_ossl_init(void);
void Curl_ossl_cleanup(void);
+/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_ossl_send(struct connectdata *conn,
int sockindex,
const void *mem,
- size_t len);
+ size_t len,
+ int *curlcode);
+
+/* for documentation see Curl_ssl_recv() in sslgen.h */
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);