sendrecv: split the I/O handling into private handler

Howard Chu brought the bulk work of this patch that properly
moves out the sending and recving of data to the parts of the
code that are properly responsible for the various ways of doing
so.

Daniel Stenberg assisted with polishing a few bits and fixed some
minor flaws in the original patch.

Another upside of this patch is that we now abuse CURLcodes less
with the "magic" -1 return codes and instead use CURLE_AGAIN more
consistently.
This commit is contained in:
Howard Chu 2010-05-07 15:05:34 +02:00 committed by Daniel Stenberg
parent cb6647ce1c
commit d64bd82bdc
26 changed files with 297 additions and 433 deletions

View File

@ -1108,7 +1108,6 @@ CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
{ {
curl_socket_t sfd; curl_socket_t sfd;
CURLcode ret; CURLcode ret;
int ret1;
ssize_t n1; ssize_t n1;
struct connectdata *c; struct connectdata *c;
struct SessionHandle *data = (struct SessionHandle *)curl; struct SessionHandle *data = (struct SessionHandle *)curl;
@ -1118,13 +1117,10 @@ CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
return ret; return ret;
*n = 0; *n = 0;
ret1 = Curl_read(c, sfd, buffer, buflen, &n1); ret = Curl_read(c, sfd, buffer, buflen, &n1);
if(ret1 == -1) if(ret != CURLE_OK)
return CURLE_AGAIN; return ret;
if(ret1 != CURLE_OK)
return (CURLcode)ret1;
*n = (size_t)n1; *n = (size_t)n1;

View File

@ -419,6 +419,9 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static Curl_recv gtls_recv;
static Curl_send gtls_send;
static CURLcode static CURLcode
gtls_connect_step3(struct connectdata *conn, gtls_connect_step3(struct connectdata *conn,
int sockindex) int sockindex)
@ -630,6 +633,8 @@ gtls_connect_step3(struct connectdata *conn,
infof(data, "\t MAC: %s\n", ptr); infof(data, "\t MAC: %s\n", ptr);
conn->ssl[sockindex].state = ssl_connection_complete; conn->ssl[sockindex].state = ssl_connection_complete;
conn->recv = gtls_recv;
conn->send = gtls_send;
{ {
/* we always unconditionally get the session id here, as even if we /* we always unconditionally get the session id here, as even if we
@ -730,18 +735,17 @@ Curl_gtls_connect(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/* for documentation see Curl_ssl_send() in sslgen.h */ static ssize_t gtls_send(struct connectdata *conn,
ssize_t Curl_gtls_send(struct connectdata *conn, int sockindex,
int sockindex, const void *mem,
const void *mem, size_t len,
size_t len, CURLcode *curlcode)
int *curlcode)
{ {
ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len); ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
if(rc < 0 ) { if(rc < 0 ) {
*curlcode = (rc == GNUTLS_E_AGAIN) *curlcode = (rc == GNUTLS_E_AGAIN)
? /* EWOULDBLOCK */ -1 ? CURLE_AGAIN
: CURLE_SEND_ERROR; : CURLE_SEND_ERROR;
rc = -1; rc = -1;
@ -843,18 +847,17 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
return retval; return retval;
} }
/* for documentation see Curl_ssl_recv() in sslgen.h */ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */ int num, /* socketindex */
int num, /* socketindex */ char *buf, /* store read data here */
char *buf, /* store read data here */ size_t buffersize, /* max amount to read */
size_t buffersize, /* max amount to read */ CURLcode *curlcode)
int *curlcode)
{ {
ssize_t ret; ssize_t ret;
ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize); ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = -1; *curlcode = CURLE_AGAIN;
return -1; return -1;
} }
@ -866,7 +869,7 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
/* handshake() writes error message on its own */ /* handshake() writes error message on its own */
*curlcode = rc; *curlcode = rc;
else else
*curlcode = -1; /* then return as if this was a wouldblock */ *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
return -1; return -1;
} }

View File

@ -38,14 +38,6 @@ void Curl_gtls_close_all(struct SessionHandle *data);
/* close a SSL connection */ /* close a SSL connection */
void Curl_gtls_close(struct connectdata *conn, int sockindex); void Curl_gtls_close(struct connectdata *conn, int sockindex);
/* 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, 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); void Curl_gtls_session_free(void *ptr);
size_t Curl_gtls_version(char *buffer, size_t size); size_t Curl_gtls_version(char *buffer, size_t size);
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex); int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
@ -63,8 +55,6 @@ int Curl_gtls_seed(struct SessionHandle *data);
#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT) #define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT) #define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) #define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
#define curlssl_send Curl_gtls_send
#define curlssl_recv Curl_gtls_recv
#define curlssl_version Curl_gtls_version #define curlssl_version Curl_gtls_version
#define curlssl_check_cxn(x) (x=x, -1) #define curlssl_check_cxn(x) (x=x, -1)
#define curlssl_data_pending(x,y) (x=x, y=y, 0) #define curlssl_data_pending(x,y) (x=x, y=y, 0)

View File

@ -1283,7 +1283,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
CURLcode result; CURLcode result;
int res;
long timeout = long timeout =
data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */ data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
curl_socket_t tunnelsocket = conn->sock[sockindex]; curl_socket_t tunnelsocket = conn->sock[sockindex];
@ -1467,11 +1466,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
break; break;
default: default:
DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes); result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
if(res< 0) if(result==CURLE_AGAIN)
/* EWOULDBLOCK */
continue; /* go loop yourself */ continue; /* go loop yourself */
else if(res) else if(result)
keepon = FALSE; keepon = FALSE;
else if(gotbytes <= 0) { else if(gotbytes <= 0) {
keepon = FALSE; keepon = FALSE;

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2006, 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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -51,14 +51,11 @@ int Curl_sec_fflush_fd(struct connectdata *conn, int fd);
int Curl_sec_fprintf (struct connectdata *, FILE *, const char *, ...); int Curl_sec_fprintf (struct connectdata *, FILE *, const char *, ...);
int Curl_sec_getc (struct connectdata *conn, FILE *); int Curl_sec_getc (struct connectdata *conn, FILE *);
int Curl_sec_putc (struct connectdata *conn, int, FILE *); int Curl_sec_putc (struct connectdata *conn, int, FILE *);
int Curl_sec_read (struct connectdata *conn, int, void *, int);
int Curl_sec_read_msg (struct connectdata *conn, char *, int); int Curl_sec_read_msg (struct connectdata *conn, char *, int);
int Curl_sec_vfprintf(struct connectdata *, FILE *, const char *, va_list); int Curl_sec_vfprintf(struct connectdata *, FILE *, const char *, va_list);
int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...); int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
int Curl_sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list); int Curl_sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list);
ssize_t Curl_sec_send(struct connectdata *conn, int, const char *, int);
int Curl_sec_write(struct connectdata *conn, int, const char *, int);
void Curl_sec_end (struct connectdata *); void Curl_sec_end (struct connectdata *);
int Curl_sec_login (struct connectdata *); int Curl_sec_login (struct connectdata *);

View File

@ -1010,6 +1010,9 @@ static bool handle_cc_error(PRInt32 err, struct SessionHandle *data)
} }
} }
static Curl_recv nss_recv;
static Curl_send nss_send;
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{ {
PRInt32 err; PRInt32 err;
@ -1321,6 +1324,8 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
} }
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
conn->recv = nss_recv;
conn->send = nss_send;
display_conn_info(conn, connssl->handle); display_conn_info(conn, connssl->handle);
@ -1373,12 +1378,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
return curlerr; return curlerr;
} }
/* for documentation see Curl_ssl_send() in sslgen.h */ static ssize_t nss_send(struct connectdata *conn, /* connection data */
int Curl_nss_send(struct connectdata *conn, /* connection data */ int sockindex, /* socketindex */
int sockindex, /* socketindex */ const void *mem, /* send this data */
const void *mem, /* send this data */ size_t len, /* amount to write */
size_t len, /* amount to write */ CURLcode *curlcode)
int *curlcode)
{ {
int rc; int rc;
@ -1387,7 +1391,7 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
if(rc < 0) { if(rc < 0) {
PRInt32 err = PR_GetError(); PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR) if(err == PR_WOULD_BLOCK_ERROR)
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
else if(handle_cc_error(err, conn->data)) else if(handle_cc_error(err, conn->data))
*curlcode = CURLE_SSL_CERTPROBLEM; *curlcode = CURLE_SSL_CERTPROBLEM;
else { else {
@ -1399,12 +1403,11 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */ return rc; /* number of bytes */
} }
/* for documentation see Curl_ssl_recv() in sslgen.h */ static ssize_t nss_recv(struct connectdata * conn, /* connection data */
ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */ int num, /* socketindex */
int num, /* socketindex */ char *buf, /* store read data here */
char *buf, /* store read data here */ size_t buffersize, /* max amount to read */
size_t buffersize, /* max amount to read */ CURLcode *curlcode)
int *curlcode)
{ {
ssize_t nread; ssize_t nread;
@ -1414,7 +1417,7 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
PRInt32 err = PR_GetError(); PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR) if(err == PR_WOULD_BLOCK_ERROR)
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
else if(handle_cc_error(err, conn->data)) else if(handle_cc_error(err, conn->data))
*curlcode = CURLE_SSL_CERTPROBLEM; *curlcode = CURLE_SSL_CERTPROBLEM;
else { else {

View File

@ -42,20 +42,6 @@ int Curl_nss_close_all(struct SessionHandle *data);
int Curl_nss_init(void); int Curl_nss_init(void);
void Curl_nss_cleanup(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,
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 */
int *curlcode);
size_t Curl_nss_version(char *buffer, size_t size); size_t Curl_nss_version(char *buffer, size_t size);
int Curl_nss_check_cxn(struct connectdata *cxn); int Curl_nss_check_cxn(struct connectdata *cxn);
int Curl_nss_seed(struct SessionHandle *data); int Curl_nss_seed(struct SessionHandle *data);
@ -74,8 +60,6 @@ int Curl_nss_seed(struct SessionHandle *data);
#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT) #define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT) #define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) #define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
#define curlssl_send Curl_nss_send
#define curlssl_recv Curl_nss_recv
#define curlssl_version Curl_nss_version #define curlssl_version Curl_nss_version
#define curlssl_check_cxn(x) Curl_nss_check_cxn(x) #define curlssl_check_cxn(x) Curl_nss_check_cxn(x)
#define curlssl_data_pending(x,y) (x=x, y=y, 0) #define curlssl_data_pending(x,y) (x=x, y=y, 0)

View File

@ -340,8 +340,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot; conn->data_prot = prot;
#endif #endif
if(res < 0) if(res == CURLE_AGAIN)
/* EWOULDBLOCK */
return CURLE_OK; /* return */ return CURLE_OK; /* return */
#ifdef CURL_DOES_CONVERSIONS #ifdef CURL_DOES_CONVERSIONS

View File

@ -76,6 +76,9 @@ static void polarssl_debug(void *context, int level, char *line)
#else #else
#endif #endif
static Curl_recv polarssl_recv;
static Curl_send polarssl_send;
/* /*
* This function loads all the client/CA certificates and CRLs. Setup the TLS * This function loads all the client/CA certificates and CRLs. Setup the TLS
* layer and do all necessary magic. * layer and do all necessary magic.
@ -299,6 +302,8 @@ Curl_polarssl_connect(struct connectdata *conn,
} }
conn->ssl[sockindex].state = ssl_connection_complete; conn->ssl[sockindex].state = ssl_connection_complete;
conn->recv = polarssl_recv;
conn->send = polarssl_send;
/* Save the current session data for possible re-use */ /* Save the current session data for possible re-use */
{ {
@ -319,12 +324,11 @@ Curl_polarssl_connect(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
/* for documentation see Curl_ssl_send() in sslgen.h */ static ssize_t polarssl_send(struct connectdata *conn,
ssize_t Curl_polarssl_send(struct connectdata *conn, int sockindex,
int sockindex, const void *mem,
const void *mem, size_t len,
size_t len, CURLcode *curlcode)
int *curlcode)
{ {
int ret = -1; int ret = -1;
@ -332,7 +336,8 @@ ssize_t Curl_polarssl_send(struct connectdata *conn,
(unsigned char *)mem, len); (unsigned char *)mem, len);
if(ret < 0) { if(ret < 0) {
*curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_SEND_ERROR; *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ?
CURLE_AGAIN : CURLE_SEND_ERROR;
ret = -1; ret = -1;
} }
@ -355,12 +360,11 @@ void Curl_polarssl_close(struct connectdata *conn, int sockindex)
ssl_free(&conn->ssl[sockindex].ssl); ssl_free(&conn->ssl[sockindex].ssl);
} }
/* for documentation see Curl_ssl_recv() in sslgen.h */ static ssize_t polarssl_recv(struct connectdata *conn,
ssize_t Curl_polarssl_recv(struct connectdata *conn, int num,
int num, char *buf,
char *buf, size_t buffersize,
size_t buffersize, CURLcode *curlcode)
int *curlcode)
{ {
int ret = -1; int ret = -1;
ssize_t len = -1; ssize_t len = -1;
@ -369,7 +373,8 @@ ssize_t Curl_polarssl_recv(struct connectdata *conn,
ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
if(ret <= 0) { if(ret <= 0) {
*curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ? -1 : CURLE_RECV_ERROR; *curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ?
CURLE_AGAIN : CURLE_RECV_ERROR;
return -1; return -1;
} }

View File

@ -34,14 +34,6 @@ void Curl_polarssl_close_all(struct SessionHandle *data);
/* close a SSL connection */ /* close a SSL connection */
void Curl_polarssl_close(struct connectdata *conn, int sockindex); void Curl_polarssl_close(struct connectdata *conn, int sockindex);
/* return number of sent (non-SSL) bytes */
ssize_t Curl_polarssl_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, int *curlcode);
ssize_t Curl_polarssl_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
int *curlcode);
void Curl_polarssl_session_free(void *ptr); void Curl_polarssl_session_free(void *ptr);
size_t Curl_polarssl_version(char *buffer, size_t size); size_t Curl_polarssl_version(char *buffer, size_t size);
int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex); int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
@ -57,8 +49,6 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT) #define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT) #define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL) #define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
#define curlssl_send Curl_polarssl_send
#define curlssl_recv Curl_polarssl_recv
#define curlssl_version Curl_polarssl_version #define curlssl_version Curl_polarssl_version
#define curlssl_check_cxn(x) (x=x, -1) #define curlssl_check_cxn(x) (x=x, -1)
#define curlssl_data_pending(x,y) (x=x, y=y, 0) #define curlssl_data_pending(x,y) (x=x, y=y, 0)

View File

@ -242,6 +242,9 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
} }
static Curl_recv qsossl_recv;
static Curl_send qsossl_send;
CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex) CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
{ {
@ -263,8 +266,11 @@ CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
connssl->state = ssl_connection_none; connssl->state = ssl_connection_none;
} }
} }
if (rc == CURLE_OK) if (rc == CURLE_OK) {
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
conn->recv = qsossl_recv;
conn->send = qsossl_send;
}
return rc; return rc;
} }
@ -374,9 +380,8 @@ int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex)
} }
/* for documentation see Curl_ssl_send() in sslgen.h */ static ssize_t qsossl_send(struct connectdata * conn, int sockindex,
ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex, const void * mem, size_t len, CURLcode * curlcode)
const void * mem, size_t len, int * curlcode)
{ {
/* SSL_Write() is said to return 'int' while write() and send() returns /* SSL_Write() is said to return 'int' while write() and send() returns
@ -392,14 +397,14 @@ ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex,
/* The operation did not complete; the same SSL I/O function /* The operation did not complete; the same SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK should be called again later. This is basicly an EWOULDBLOCK
equivalent. */ equivalent. */
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
return -1; return -1;
case SSL_ERROR_IO: case SSL_ERROR_IO:
switch (errno) { switch (errno) {
case EWOULDBLOCK: case EWOULDBLOCK:
case EINTR: case EINTR:
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
return -1; return -1;
} }
@ -419,9 +424,8 @@ ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex,
} }
/* for documentation see Curl_ssl_recv() in sslgen.h */ static ssize_t qsossl_recv(struct connectdata * conn, int num, char * buf,
ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf, size_t buffersize, CURLcode * curlcode)
size_t buffersize, int * curlcode)
{ {
char error_buffer[120]; /* OpenSSL documents that this must be at char error_buffer[120]; /* OpenSSL documents that this must be at
@ -440,13 +444,13 @@ ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf,
case SSL_ERROR_BAD_STATE: case SSL_ERROR_BAD_STATE:
/* there's data pending, re-invoke SSL_Read(). */ /* there's data pending, re-invoke SSL_Read(). */
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
return -1; return -1;
case SSL_ERROR_IO: case SSL_ERROR_IO:
switch (errno) { switch (errno) {
case EWOULDBLOCK: case EWOULDBLOCK:
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
return -1; return -1;
} }

View File

@ -36,20 +36,6 @@ void Curl_qsossl_close(struct connectdata *conn, int sockindex);
int Curl_qsossl_close_all(struct SessionHandle * data); int Curl_qsossl_close_all(struct SessionHandle * data);
int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex); int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex);
/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_qsossl_send(struct connectdata * conn,
int sockindex,
const void * mem,
size_t len,
int * curlcode);
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_qsossl_recv(struct connectdata * conn, /* connection data */
int num, /* socketindex */
char * buf, /* store read data here */
size_t buffersize, /* max amount to read */
int * curlcode);
size_t Curl_qsossl_version(char * buffer, size_t size); size_t Curl_qsossl_version(char * buffer, size_t size);
int Curl_qsossl_check_cxn(struct connectdata * cxn); int Curl_qsossl_check_cxn(struct connectdata * cxn);
@ -66,8 +52,6 @@ int Curl_qsossl_check_cxn(struct connectdata * cxn);
#define curlssl_set_engine(x,y) CURLE_FAILED_INIT #define curlssl_set_engine(x,y) CURLE_FAILED_INIT
#define curlssl_set_engine_default(x) CURLE_FAILED_INIT #define curlssl_set_engine_default(x) CURLE_FAILED_INIT
#define curlssl_engines_list(x) NULL #define curlssl_engines_list(x) NULL
#define curlssl_send Curl_qsossl_send
#define curlssl_recv Curl_qsossl_recv
#define curlssl_version Curl_qsossl_version #define curlssl_version Curl_qsossl_version
#define curlssl_check_cxn(x) Curl_qsossl_check_cxn(x) #define curlssl_check_cxn(x) Curl_qsossl_check_cxn(x)
#define curlssl_data_pending(x,y) 0 #define curlssl_data_pending(x,y) 0

View File

@ -10,7 +10,7 @@
* Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden). * (Royal Institute of Technology, Stockholm, Sweden).
* *
* Copyright (C) 2001 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2001 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* All rights reserved. * All rights reserved.
* *
@ -101,20 +101,6 @@ static const struct Curl_sec_client_mech * const mechs[] = {
NULL NULL
}; };
/* TODO: This function isn't actually used anywhere and should be removed */
int
Curl_sec_getc(struct connectdata *conn, FILE *F)
{
if(conn->sec_complete && conn->data_prot) {
char c;
if(Curl_sec_read(conn, fileno(F), &c, 1) <= 0)
return EOF;
return c;
}
else
return getc(F);
}
static int static int
block_read(int fd, void *buf, size_t len) block_read(int fd, void *buf, size_t len)
{ {
@ -189,35 +175,16 @@ buffer_read(struct krb4buffer *buf, void *data, size_t len)
return len; return len;
} }
static size_t static ssize_t sec_read(struct connectdata *conn, int num,
buffer_write(struct krb4buffer *buf, void *data, size_t len) char *buffer, size_t length, CURLcode *err)
{
if(buf->index + len > buf->size) {
void *tmp;
if(buf->data == NULL)
tmp = malloc(1024);
else
tmp = realloc(buf->data, buf->index + len);
if(tmp == NULL)
return -1;
buf->data = tmp;
buf->size = buf->index + len;
}
memcpy((char*)buf->data + buf->index, data, len);
buf->index += len;
return len;
}
int
Curl_sec_read(struct connectdata *conn, int fd, void *buffer, int length)
{ {
size_t len; size_t len;
int rx = 0; int rx = 0;
curl_socket_t fd = conn->sock[num];
if(conn->sec_complete == 0 || conn->data_prot == 0) *err = CURLE_OK;
return read(fd, buffer, length);
if(conn->in_buffer.eof_flag){ if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0; conn->in_buffer.eof_flag = 0;
return 0; return 0;
} }
@ -284,29 +251,12 @@ sec_send(struct connectdata *conn, int fd, const char *from, int length)
return length; return length;
} }
int static ssize_t sec_write(struct connectdata *conn, int fd,
Curl_sec_fflush_fd(struct connectdata *conn, int fd) const char *buffer, int length)
{
if(conn->data_prot != prot_clear) {
if(conn->out_buffer.index > 0){
Curl_sec_write(conn, fd,
conn->out_buffer.data, conn->out_buffer.index);
conn->out_buffer.index = 0;
}
sec_send(conn, fd, NULL, 0);
}
return 0;
}
int
Curl_sec_write(struct connectdata *conn, int fd, const char *buffer, int length)
{ {
int len = conn->buffer_size; int len = conn->buffer_size;
int tx = 0; int tx = 0;
if(conn->data_prot == prot_clear)
return write(fd, buffer, length);
len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len); len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len);
if(len <= 0) if(len <= 0)
len = length; len = length;
@ -321,27 +271,25 @@ Curl_sec_write(struct connectdata *conn, int fd, const char *buffer, int length)
return tx; return tx;
} }
ssize_t int
Curl_sec_send(struct connectdata *conn, int num, const char *buffer, int length) Curl_sec_fflush_fd(struct connectdata *conn, int fd)
{ {
curl_socket_t fd = conn->sock[num]; if(conn->data_prot != prot_clear) {
return (ssize_t)Curl_sec_write(conn, fd, buffer, length); if(conn->out_buffer.index > 0){
sec_write(conn, fd, conn->out_buffer.data, conn->out_buffer.index);
conn->out_buffer.index = 0;
}
sec_send(conn, fd, NULL, 0);
}
return 0;
} }
int static ssize_t _sec_send(struct connectdata *conn, int num,
Curl_sec_putc(struct connectdata *conn, int c, FILE *F) const void *buffer, size_t length, CURLcode *err)
{ {
char ch = (char)c; curl_socket_t fd = conn->sock[num];
if(conn->data_prot == prot_clear) *err = CURLE_OK;
return putc(c, F); return sec_write(conn, fd, buffer, length);
buffer_write(&conn->out_buffer, &ch, 1);
if(c == '\n' || conn->out_buffer.index >= 1024 /* XXX */) {
Curl_sec_write(conn, fileno(F), conn->out_buffer.data,
conn->out_buffer.index);
conn->out_buffer.index = 0;
}
return c;
} }
int int
@ -517,6 +465,10 @@ Curl_sec_login(struct connectdata *conn)
} }
conn->mech = *m; conn->mech = *m;
conn->sec_complete = 1; conn->sec_complete = 1;
if (conn->data_prot != prot_clear) {
conn->recv = sec_read;
conn->send = _sec_send;
}
conn->command_prot = prot_safe; conn->command_prot = prot_safe;
/* Set the requested protection level */ /* Set the requested protection level */
/* BLOCKING */ /* BLOCKING */

View File

@ -234,14 +234,53 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
return res; return res;
} }
static ssize_t send_plain(struct connectdata *conn, /*
int num, * Curl_write() is an internal write function that sends data to the
const void *mem, * server. Works with plain sockets, SCP, SSL or kerberos.
size_t len) *
* If the write would block (CURLE_AGAIN), we return CURLE_OK and
* (*written == 0). Otherwise we return regular CURLcode value.
*/
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
const void *mem,
size_t len,
ssize_t *written)
{
ssize_t bytes_written;
CURLcode curlcode = CURLE_OK;
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
bytes_written = conn->send(conn, num, mem, len, &curlcode);
*written = bytes_written;
if(-1 != bytes_written)
/* we completely ignore the curlcode value when -1 is not returned */
return CURLE_OK;
/* handle CURLE_AGAIN or a send failure */
switch(curlcode) {
case CURLE_AGAIN:
*written = 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;
}
}
ssize_t Curl_send_plain(struct connectdata *conn, int num,
const void *mem, size_t len, CURLcode *code)
{ {
curl_socket_t sockfd = conn->sock[num]; curl_socket_t sockfd = conn->sock[num];
ssize_t bytes_written = swrite(sockfd, mem, len); ssize_t bytes_written = swrite(sockfd, mem, len);
*code = CURLE_OK;
if(-1 == bytes_written) { if(-1 == bytes_written) {
int err = SOCKERRNO; int err = SOCKERRNO;
@ -255,65 +294,19 @@ static ssize_t send_plain(struct connectdata *conn,
treat both error codes the same here */ treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif #endif
) ) {
/* this is just a case of EWOULDBLOCK */ /* this is just a case of EWOULDBLOCK */
bytes_written=0; bytes_written=0;
else *code = CURLE_AGAIN;
} else {
failf(conn->data, "Send failure: %s", failf(conn->data, "Send failure: %s",
Curl_strerror(conn, err)); Curl_strerror(conn, err));
*code = CURLE_SEND_ERROR;
}
} }
return bytes_written; return bytes_written;
} }
/*
* 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,
const void *mem,
size_t len,
ssize_t *written)
{
ssize_t bytes_written;
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, &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))
bytes_written = Curl_sftp_send(conn, num, mem, len);
else if(conn->sec_complete)
bytes_written = Curl_sec_send(conn, num, mem, len);
else
bytes_written = send_plain(conn, num, mem, len);
*written = bytes_written;
if(-1 != bytes_written)
/* we completely ignore the curlcode value when -1 is not returned */
return CURLE_OK;
/* 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;
}
}
/* /*
* Curl_write_plain() is an internal write function that sends data to the * Curl_write_plain() is an internal write function that sends data to the
* server using plain sockets only. Otherwise meant to have the exact same * server using plain sockets only. Otherwise meant to have the exact same
@ -329,14 +322,45 @@ CURLcode Curl_write_plain(struct connectdata *conn,
CURLcode retcode; CURLcode retcode;
int num = (sockfd == conn->sock[SECONDARYSOCKET]); int num = (sockfd == conn->sock[SECONDARYSOCKET]);
bytes_written = send_plain(conn, num, mem, len); bytes_written = Curl_send_plain(conn, num, mem, len, &retcode);
*written = bytes_written; *written = bytes_written;
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
return retcode; return retcode;
} }
ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
size_t len, CURLcode *code)
{
curl_socket_t sockfd = conn->sock[num];
ssize_t nread = sread(sockfd, buf, len);
*code = CURLE_OK;
if(-1 == nread) {
int err = SOCKERRNO;
if(
#ifdef WSAEWOULDBLOCK
/* This is how Windows does it */
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We therefor
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
) {
/* this is just a case of EWOULDBLOCK */
*code = CURLE_AGAIN;
} else {
failf(conn->data, "Recv failure: %s",
Curl_strerror(conn, err));
*code = CURLE_RECV_ERROR;
}
}
return nread;
}
static CURLcode pausewrite(struct SessionHandle *data, static CURLcode pausewrite(struct SessionHandle *data,
int type, /* what type of data */ int type, /* what type of data */
const char *ptr, const char *ptr,
@ -476,7 +500,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
int Curl_read_plain(curl_socket_t sockfd, CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf, char *buf,
size_t bytesfromsocket, size_t bytesfromsocket,
ssize_t *n) ssize_t *n)
@ -490,7 +514,7 @@ int Curl_read_plain(curl_socket_t sockfd,
#else #else
if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)) if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif #endif
return -1; return CURLE_AGAIN;
else else
return CURLE_RECV_ERROR; return CURLE_RECV_ERROR;
} }
@ -504,15 +528,15 @@ int Curl_read_plain(curl_socket_t sockfd,
* Internal read-from-socket function. This is meant to deal with plain * Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets. * sockets, SSL sockets and kerberos sockets.
* *
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return * Returns a regular CURLcode value.
* a regular CURLcode value.
*/ */
int Curl_read(struct connectdata *conn, /* connection data */ CURLcode Curl_read(struct connectdata *conn, /* connection data */
curl_socket_t sockfd, /* read from this socket */ curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */ char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */ size_t sizerequested, /* max amount to read */
ssize_t *n) /* amount bytes read */ ssize_t *n) /* amount bytes read */
{ {
CURLcode curlcode = CURLE_RECV_ERROR;
ssize_t nread = 0; ssize_t nread = 0;
size_t bytesfromsocket = 0; size_t bytesfromsocket = 0;
char *buffertofill = NULL; char *buffertofill = NULL;
@ -552,50 +576,17 @@ int Curl_read(struct connectdata *conn, /* connection data */
buffertofill = buf; buffertofill = buf;
} }
if(conn->ssl[num].state == ssl_connection_complete) { nread = conn->recv(conn, num, buffertofill, bytesfromsocket, &curlcode);
int curlcode = CURLE_RECV_ERROR; if(nread == -1)
nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket, &curlcode); return curlcode;
if(nread == -1) if(pipelining) {
return curlcode; memcpy(buf, conn->master_buffer, nread);
conn->buf_len = nread;
conn->read_pos = nread;
} }
else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
if(conn->protocol & PROT_SCP)
nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
else if(conn->protocol & PROT_SFTP)
nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
#ifdef LIBSSH2CHANNEL_EAGAIN
if(nread == LIBSSH2CHANNEL_EAGAIN)
/* EWOULDBLOCK */
return -1;
#endif
if(nread < 0)
/* since it is negative and not EAGAIN, it was a protocol-layer error */
return CURLE_RECV_ERROR;
}
else {
if(conn->sec_complete)
nread = Curl_sec_read(conn, sockfd, buffertofill,
bytesfromsocket);
/* TODO: Need to handle EAGAIN here somehow, similar to how it
* is done in Curl_read_plain, either right here or in Curl_sec_read
* itself. */
else {
int ret = Curl_read_plain(sockfd, buffertofill, bytesfromsocket,
&nread);
if(ret)
return ret;
}
}
if(nread >= 0) {
if(pipelining) {
memcpy(buf, conn->master_buffer, nread);
conn->buf_len = nread;
conn->read_pos = nread;
}
*n += nread; *n += nread;
}
return CURLE_OK; return CURLE_OK;
} }

View File

@ -55,15 +55,20 @@ CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len); size_t len);
/* internal read-function, does plain socket only */ /* internal read-function, does plain socket only */
int Curl_read_plain(curl_socket_t sockfd, CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf, char *buf,
size_t bytesfromsocket, size_t bytesfromsocket,
ssize_t *n); ssize_t *n);
ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
size_t len, CURLcode *code);
ssize_t Curl_send_plain(struct connectdata *conn, int num,
const void *mem, size_t len, CURLcode *code);
/* internal read-function, does plain socket, SSL and krb4 */ /* internal read-function, does plain socket, SSL and krb4 */
int Curl_read(struct connectdata *conn, curl_socket_t sockfd, CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize, char *buf, size_t buffersize,
ssize_t *n); ssize_t *n);
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ /* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
CURLcode Curl_write(struct connectdata *conn, CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd, curl_socket_t sockfd,

View File

@ -77,7 +77,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
conntime = Curl_tvdiff(tvnow, conn->created); conntime = Curl_tvdiff(tvnow, conn->created);
if(conntime > conn_timeout) { if(conntime > conn_timeout) {
/* we already got the timeout */ /* we already got the timeout */
result = ~CURLE_OK; result = CURLE_OPERATION_TIMEDOUT;
break; break;
} }
if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD,
@ -86,7 +86,9 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
break; break;
} }
result = Curl_read_plain(sockfd, buf, buffersize, &nread); result = Curl_read_plain(sockfd, buf, buffersize, &nread);
if(result) if(CURLE_AGAIN == result)
continue;
else if(result)
break; break;
if(buffersize == nread) { if(buffersize == nread) {

View File

@ -2464,6 +2464,9 @@ static CURLcode ssh_init(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static Curl_recv scp_recv, sftp_recv;
static Curl_send scp_send, sftp_send;
/* /*
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. * do protocol-specific actions at connect-time.
@ -2489,6 +2492,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
if(conn->protocol & PROT_SCP) {
conn->recv = scp_recv;
conn->send = scp_send;
} else {
conn->recv = sftp_recv;
conn->send = sftp_send;
}
ssh = &conn->proto.sshc; ssh = &conn->proto.sshc;
#ifdef CURL_LIBSSH2_DEBUG #ifdef CURL_LIBSSH2_DEBUG
@ -2703,8 +2713,8 @@ static CURLcode scp_done(struct connectdata *conn, CURLcode status,
} }
/* return number of received (decrypted) bytes */ /* return number of received (decrypted) bytes */
ssize_t Curl_scp_send(struct connectdata *conn, int sockindex, static ssize_t scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len) const void *mem, size_t len, CURLcode *err)
{ {
ssize_t nwrite; ssize_t nwrite;
(void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)sockindex; /* we only support SCP on the fixed known primary socket */
@ -2715,8 +2725,10 @@ ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) if(nwrite == LIBSSH2_ERROR_EAGAIN) {
return 0; *err = CURLE_AGAIN;
nwrite = 0;
}
return nwrite; return nwrite;
} }
@ -2725,8 +2737,8 @@ ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value. * a regular CURLcode value.
*/ */
ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex, static ssize_t scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
(void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)sockindex; /* we only support SCP on the fixed known primary socket */
@ -2736,6 +2748,10 @@ ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len); libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if (nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
return nread; return nread;
} }
@ -2840,8 +2856,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
} }
/* return number of sent bytes */ /* return number of sent bytes */
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex, static ssize_t sftp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len) const void *mem, size_t len, CURLcode *err)
{ {
ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
but is changed to ssize_t in 0.15. These days we don't but is changed to ssize_t in 0.15. These days we don't
@ -2852,8 +2868,10 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) if(nwrite == LIBSSH2_ERROR_EAGAIN) {
return 0; *err = CURLE_AGAIN;
nwrite = 0;
}
return nwrite; return nwrite;
} }
@ -2861,8 +2879,8 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
/* /*
* Return number of received (decrypted) bytes * Return number of received (decrypted) bytes
*/ */
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex, static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len) char *mem, size_t len, CURLcode *err)
{ {
ssize_t nread; ssize_t nread;
(void)sockindex; (void)sockindex;
@ -2871,6 +2889,10 @@ ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE); ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
return nread; return nread;
} }

View File

@ -162,26 +162,6 @@ struct ssh_conn {
extern const struct Curl_handler Curl_handler_scp; extern const struct Curl_handler Curl_handler_scp;
extern const struct Curl_handler Curl_handler_sftp; extern const struct Curl_handler Curl_handler_sftp;
ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len);
ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len);
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len);
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len);
#define Curl_ssh_enabled(conn,prot) (conn->protocol & prot)
#else /* USE_LIBSSH2 */
#define Curl_ssh_enabled(x,y) 0
#define Curl_scp_send(a,b,c,d) 0
#define Curl_sftp_send(a,b,c,d) 0
#define Curl_scp_recv(a,b,c,d) 0
#define Curl_sftp_recv(a,b,c,d) 0
#endif /* USE_LIBSSH2 */ #endif /* USE_LIBSSH2 */
#endif /* HEADER_CURL_SSH_H */ #endif /* HEADER_CURL_SSH_H */

View File

@ -410,25 +410,6 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
return curlssl_engines_list(data); return curlssl_engines_list(data);
} }
ssize_t Curl_ssl_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
int *curlcode)
{
return curlssl_send(conn, sockindex, mem, len, curlcode);
}
ssize_t Curl_ssl_recv(struct connectdata *conn,
int sockindex,
char *mem,
size_t len,
int *curlcode)
{
return curlssl_recv(conn, sockindex, mem, len, curlcode);
}
/* /*
* This sets up a session ID cache to the specified size. Make sure this code * This sets up a session ID cache to the specified size. Make sure this code
* is agnostic to what underlying SSL technology we use. * is agnostic to what underlying SSL technology we use.

View File

@ -45,28 +45,6 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine);
CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data); CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data);
struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data); struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data);
/* 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 */
int *curlcode); /* error to return,
-1 means EWOULDBLOCK */
/* init the SSL session ID cache */ /* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct SessionHandle *, long); CURLcode Curl_ssl_initsessions(struct SessionHandle *, long);
size_t Curl_ssl_version(char *buffer, size_t size); size_t Curl_ssl_version(char *buffer, size_t size);

View File

@ -2352,6 +2352,9 @@ ossl_connect_step3(struct connectdata *conn,
return retcode; return retcode;
} }
static Curl_recv ossl_recv;
static Curl_send ossl_send;
static CURLcode static CURLcode
ossl_connect_common(struct connectdata *conn, ossl_connect_common(struct connectdata *conn,
int sockindex, int sockindex,
@ -2437,6 +2440,8 @@ ossl_connect_common(struct connectdata *conn,
if(ssl_connect_done==connssl->connecting_state) { if(ssl_connect_done==connssl->connecting_state) {
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
conn->recv = ossl_recv;
conn->send = ossl_send;
*done = TRUE; *done = TRUE;
} }
else else
@ -2482,12 +2487,11 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
return FALSE; return FALSE;
} }
/* for documentation see Curl_ssl_send() in sslgen.h */ static ssize_t ossl_send(struct connectdata *conn,
ssize_t Curl_ossl_send(struct connectdata *conn, int sockindex,
int sockindex, const void *mem,
const void *mem, size_t len,
size_t len, CURLcode *curlcode)
int *curlcode)
{ {
/* SSL_write() is said to return 'int' while write() and send() returns /* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */ 'size_t' */
@ -2510,7 +2514,7 @@ ssize_t Curl_ossl_send(struct connectdata *conn,
/* The operation did not complete; the same TLS/SSL I/O function /* The operation did not complete; the same TLS/SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK should be called again later. This is basicly an EWOULDBLOCK
equivalent. */ equivalent. */
*curlcode = /* EWOULDBLOCK */ -1; *curlcode = CURLE_AGAIN;
return -1; return -1;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d", failf(conn->data, "SSL_write() returned SYSCALL, errno = %d",
@ -2534,12 +2538,11 @@ ssize_t Curl_ossl_send(struct connectdata *conn,
return (ssize_t)rc; /* number of bytes */ return (ssize_t)rc; /* number of bytes */
} }
/* for documentation see Curl_ssl_recv() in sslgen.h */ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */ int num, /* socketindex */
int num, /* socketindex */ char *buf, /* store read data here */
char *buf, /* store read data here */ size_t buffersize, /* max amount to read */
size_t buffersize, /* max amount to read */ CURLcode *curlcode)
int *curlcode)
{ {
char error_buffer[120]; /* OpenSSL documents that this must be at char error_buffer[120]; /* OpenSSL documents that this must be at
least 120 bytes long. */ least 120 bytes long. */
@ -2560,7 +2563,7 @@ ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */ /* there's data pending, re-invoke SSL_read() */
*curlcode = -1; /* EWOULDBLOCK */ *curlcode = CURLE_AGAIN;
return -1; return -1;
default: default:
/* openssl/ssl.h says "look at error stack/return value/errno" */ /* openssl/ssl.h says "look at error stack/return value/errno" */

View File

@ -56,20 +56,6 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
int Curl_ossl_init(void); int Curl_ossl_init(void);
void Curl_ossl_cleanup(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,
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 */
int *curlcode);
size_t Curl_ossl_version(char *buffer, size_t size); size_t Curl_ossl_version(char *buffer, size_t size);
int Curl_ossl_check_cxn(struct connectdata *cxn); int Curl_ossl_check_cxn(struct connectdata *cxn);
int Curl_ossl_seed(struct SessionHandle *data); int Curl_ossl_seed(struct SessionHandle *data);
@ -90,8 +76,6 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y) #define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y)
#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x) #define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x)
#define curlssl_engines_list(x) Curl_ossl_engines_list(x) #define curlssl_engines_list(x) Curl_ossl_engines_list(x)
#define curlssl_send Curl_ossl_send
#define curlssl_recv Curl_ossl_recv
#define curlssl_version Curl_ossl_version #define curlssl_version Curl_ossl_version
#define curlssl_check_cxn Curl_ossl_check_cxn #define curlssl_check_cxn Curl_ossl_check_cxn
#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y) #define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)

View File

@ -1209,7 +1209,6 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
struct pollfd pfd[2]; struct pollfd pfd[2];
int poll_cnt; int poll_cnt;
#endif #endif
int ret;
ssize_t nread; ssize_t nread;
struct timeval now; struct timeval now;
bool keepon = TRUE; bool keepon = TRUE;
@ -1383,14 +1382,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
} }
if(events.lNetworkEvents & FD_READ) { if(events.lNetworkEvents & FD_READ) {
/* read data from network */ /* read data from network */
ret = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* returned sub-zero, this would've blocked. Loop again */ /* read would've blocked. Loop again */
if(ret < 0) if(code == CURLE_AGAIN)
break; break;
/* returned not-zero, this an error */ /* returned not-zero, this an error */
else if(ret) { else if(code) {
keepon = FALSE; keepon = FALSE;
code = (CURLcode)ret;
break; break;
} }
/* returned zero but actually received 0 or less here, /* returned zero but actually received 0 or less here,
@ -1472,14 +1470,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
default: /* read! */ default: /* read! */
if(pfd[0].revents & POLLIN) { if(pfd[0].revents & POLLIN) {
/* read data from network */ /* read data from network */
ret = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* returned sub-zero, this would've blocked. Loop again */ /* read would've blocked. Loop again */
if(ret < 0) if(code == CURLE_AGAIN)
break; break;
/* returned not-zero, this an error */ /* returned not-zero, this an error */
else if(ret) { else if(code) {
keepon = FALSE; keepon = FALSE;
code = (CURLcode)ret;
break; break;
} }
/* returned zero but actually received 0 or less here, /* returned zero but actually received 0 or less here,

View File

@ -376,12 +376,11 @@ static CURLcode readwrite_data(struct SessionHandle *data,
*done = FALSE; *done = FALSE;
/* This is where we loop until we have read everything there is to /* This is where we loop until we have read everything there is to
read or we get a EWOULDBLOCK */ read or we get a CURLE_AGAIN */
do { do {
size_t buffersize = data->set.buffer_size? size_t buffersize = data->set.buffer_size?
data->set.buffer_size : BUFSIZE; data->set.buffer_size : BUFSIZE;
size_t bytestoread = buffersize; size_t bytestoread = buffersize;
int readrc;
if(k->size != -1 && !k->header) { if(k->size != -1 && !k->header) {
/* make sure we don't read "too much" if we can help it since we /* make sure we don't read "too much" if we can help it since we
@ -394,15 +393,12 @@ static CURLcode readwrite_data(struct SessionHandle *data,
if(bytestoread) { if(bytestoread) {
/* receive data from the network! */ /* receive data from the network! */
readrc = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread); result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread);
/* subzero, this would've blocked */ /* read would've blocked */
if(0 > readrc) if(CURLE_AGAIN == result)
break; /* get out of loop */ break; /* get out of loop */
/* get the CURLcode from the int */
result = (CURLcode)readrc;
if(result>0) if(result>0)
return result; return result;
} }

View File

@ -4760,6 +4760,9 @@ static CURLcode create_conn(struct SessionHandle *data,
return result; return result;
} }
conn->recv = Curl_recv_plain;
conn->send = Curl_send_plain;
/*********************************************************************** /***********************************************************************
* file: is a special case in that it doesn't need a network connection * file: is a special case in that it doesn't need a network connection
***********************************************************************/ ***********************************************************************/

View File

@ -650,6 +650,20 @@ struct Curl_handler {
long protocol; /* PROT_* flags concerning the protocol set */ long protocol; /* PROT_* flags concerning the protocol set */
}; };
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
const void *buf, /* data to write */
size_t len, /* max amount to write */
CURLcode *err); /* error to return */
/* return the count of bytes read, or -1 on error */
typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
char *buf, /* store data here */
size_t len, /* max amount to read */
CURLcode *err); /* error to return */
/* /*
* The connectdata struct contains all fields and variables that should be * The connectdata struct contains all fields and variables that should be
* unique for an entire connection. * unique for an entire connection.
@ -746,6 +760,9 @@ struct connectdata {
curl_socket_t sock[2]; /* two sockets, the second is used for the data curl_socket_t sock[2]; /* two sockets, the second is used for the data
transfer when doing FTP */ transfer when doing FTP */
Curl_recv *recv;
Curl_send *send;
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
struct ssl_config_data ssl_config; struct ssl_config_data ssl_config;