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;
CURLcode ret;
int ret1;
ssize_t n1;
struct connectdata *c;
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;
*n = 0;
ret1 = Curl_read(c, sfd, buffer, buflen, &n1);
ret = Curl_read(c, sfd, buffer, buflen, &n1);
if(ret1 == -1)
return CURLE_AGAIN;
if(ret1 != CURLE_OK)
return (CURLcode)ret1;
if(ret != CURLE_OK)
return ret;
*n = (size_t)n1;

View File

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

View File

@ -38,14 +38,6 @@ void Curl_gtls_close_all(struct SessionHandle *data);
/* close a SSL connection */
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);
size_t Curl_gtls_version(char *buffer, size_t size);
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_default(x) (x=x, CURLE_FAILED_INIT)
#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_check_cxn(x) (x=x, -1)
#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 SingleRequest *k = &data->req;
CURLcode result;
int res;
long timeout =
data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
curl_socket_t tunnelsocket = conn->sock[sockindex];
@ -1467,11 +1466,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
break;
default:
DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
if(res< 0)
/* EWOULDBLOCK */
result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
if(result==CURLE_AGAIN)
continue; /* go loop yourself */
else if(res)
else if(result)
keepon = FALSE;
else if(gotbytes <= 0) {
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
* 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_getc (struct connectdata *conn, 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_vfprintf(struct connectdata *, FILE *, const char *, va_list);
int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
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 *);
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)
{
PRInt32 err;
@ -1321,6 +1324,8 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
}
connssl->state = ssl_connection_complete;
conn->recv = nss_recv;
conn->send = nss_send;
display_conn_info(conn, connssl->handle);
@ -1373,12 +1378,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
return curlerr;
}
/* 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 */
int *curlcode)
static ssize_t nss_send(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
const void *mem, /* send this data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
int rc;
@ -1387,7 +1391,7 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
if(rc < 0) {
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
else if(handle_cc_error(err, conn->data))
*curlcode = CURLE_SSL_CERTPROBLEM;
else {
@ -1399,12 +1403,11 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */
}
/* 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)
static ssize_t nss_recv(struct connectdata * conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
ssize_t nread;
@ -1414,7 +1417,7 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
else if(handle_cc_error(err, conn->data))
*curlcode = CURLE_SSL_CERTPROBLEM;
else {

View File

@ -42,20 +42,6 @@ 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,
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);
int Curl_nss_check_cxn(struct connectdata *cxn);
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_default(x) (x=x, CURLE_FAILED_INIT)
#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_check_cxn(x) Curl_nss_check_cxn(x)
#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)
conn->data_prot = prot;
#endif
if(res < 0)
/* EWOULDBLOCK */
if(res == CURLE_AGAIN)
return CURLE_OK; /* return */
#ifdef CURL_DOES_CONVERSIONS

View File

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

View File

@ -34,14 +34,6 @@ void Curl_polarssl_close_all(struct SessionHandle *data);
/* close a SSL connection */
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);
size_t Curl_polarssl_version(char *buffer, size_t size);
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_default(x) (x=x, CURLE_FAILED_INIT)
#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_check_cxn(x) (x=x, -1)
#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)
{
@ -263,8 +266,11 @@ CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
connssl->state = ssl_connection_none;
}
}
if (rc == CURLE_OK)
if (rc == CURLE_OK) {
connssl->state = ssl_connection_complete;
conn->recv = qsossl_recv;
conn->send = qsossl_send;
}
return rc;
}
@ -374,9 +380,8 @@ 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)
static ssize_t qsossl_send(struct connectdata * conn, int sockindex,
const void * mem, size_t len, CURLcode * curlcode)
{
/* 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
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
case SSL_ERROR_IO:
switch (errno) {
case EWOULDBLOCK:
case EINTR:
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
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 */
ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf,
size_t buffersize, int * curlcode)
static ssize_t qsossl_recv(struct connectdata * conn, int num, char * buf,
size_t buffersize, CURLcode * curlcode)
{
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:
/* there's data pending, re-invoke SSL_Read(). */
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
case SSL_ERROR_IO:
switch (errno) {
case EWOULDBLOCK:
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
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_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);
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_default(x) CURLE_FAILED_INIT
#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_check_cxn(x) Curl_qsossl_check_cxn(x)
#define curlssl_data_pending(x,y) 0

View File

@ -10,7 +10,7 @@
* Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
* (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.
*
@ -101,20 +101,6 @@ static const struct Curl_sec_client_mech * const mechs[] = {
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
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;
}
static size_t
buffer_write(struct krb4buffer *buf, void *data, size_t len)
{
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)
static ssize_t sec_read(struct connectdata *conn, int num,
char *buffer, size_t length, CURLcode *err)
{
size_t len;
int rx = 0;
curl_socket_t fd = conn->sock[num];
if(conn->sec_complete == 0 || conn->data_prot == 0)
return read(fd, buffer, length);
*err = CURLE_OK;
if(conn->in_buffer.eof_flag){
if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0;
return 0;
}
@ -284,29 +251,12 @@ sec_send(struct connectdata *conn, int fd, const char *from, int length)
return length;
}
int
Curl_sec_fflush_fd(struct connectdata *conn, int fd)
{
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)
static ssize_t sec_write(struct connectdata *conn, int fd,
const char *buffer, int length)
{
int len = conn->buffer_size;
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);
if(len <= 0)
len = length;
@ -321,27 +271,25 @@ Curl_sec_write(struct connectdata *conn, int fd, const char *buffer, int length)
return tx;
}
ssize_t
Curl_sec_send(struct connectdata *conn, int num, const char *buffer, int length)
int
Curl_sec_fflush_fd(struct connectdata *conn, int fd)
{
curl_socket_t fd = conn->sock[num];
return (ssize_t)Curl_sec_write(conn, fd, buffer, length);
if(conn->data_prot != prot_clear) {
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
Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
static ssize_t _sec_send(struct connectdata *conn, int num,
const void *buffer, size_t length, CURLcode *err)
{
char ch = (char)c;
if(conn->data_prot == prot_clear)
return putc(c, F);
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;
curl_socket_t fd = conn->sock[num];
*err = CURLE_OK;
return sec_write(conn, fd, buffer, length);
}
int
@ -517,6 +465,10 @@ Curl_sec_login(struct connectdata *conn)
}
conn->mech = *m;
conn->sec_complete = 1;
if (conn->data_prot != prot_clear) {
conn->recv = sec_read;
conn->send = _sec_send;
}
conn->command_prot = prot_safe;
/* Set the requested protection level */
/* BLOCKING */

View File

@ -234,14 +234,53 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
return res;
}
static ssize_t send_plain(struct connectdata *conn,
int num,
const void *mem,
size_t len)
/*
* 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 (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];
ssize_t bytes_written = swrite(sockfd, mem, len);
*code = CURLE_OK;
if(-1 == bytes_written) {
int err = SOCKERRNO;
@ -255,65 +294,19 @@ static ssize_t send_plain(struct connectdata *conn,
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
)
) {
/* this is just a case of EWOULDBLOCK */
bytes_written=0;
else
*code = CURLE_AGAIN;
} else {
failf(conn->data, "Send failure: %s",
Curl_strerror(conn, err));
*code = CURLE_SEND_ERROR;
}
}
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
* 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;
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;
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
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,
int type, /* what type of data */
const char *ptr,
@ -476,7 +500,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
return CURLE_OK;
}
int Curl_read_plain(curl_socket_t sockfd,
CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
ssize_t *n)
@ -490,7 +514,7 @@ int Curl_read_plain(curl_socket_t sockfd,
#else
if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif
return -1;
return CURLE_AGAIN;
else
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
* sockets, SSL sockets and kerberos sockets.
*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
* Returns 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 */
char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */
ssize_t *n) /* amount bytes read */
{
CURLcode curlcode = CURLE_RECV_ERROR;
ssize_t nread = 0;
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
@ -552,50 +576,17 @@ int Curl_read(struct connectdata *conn, /* connection data */
buffertofill = buf;
}
if(conn->ssl[num].state == ssl_connection_complete) {
int curlcode = CURLE_RECV_ERROR;
nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket, &curlcode);
nread = conn->recv(conn, num, buffertofill, bytesfromsocket, &curlcode);
if(nread == -1)
return curlcode;
if(nread == -1)
return curlcode;
if(pipelining) {
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;
}

View File

@ -55,15 +55,20 @@ CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len);
/* internal read-function, does plain socket only */
int Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
ssize_t *n);
CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
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 */
int Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
CURLcode Curl_write(struct connectdata *conn,
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);
if(conntime > conn_timeout) {
/* we already got the timeout */
result = ~CURLE_OK;
result = CURLE_OPERATION_TIMEDOUT;
break;
}
if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD,
@ -86,7 +86,9 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
break;
}
result = Curl_read_plain(sockfd, buf, buffersize, &nread);
if(result)
if(CURLE_AGAIN == result)
continue;
else if(result)
break;
if(buffersize == nread) {

View File

@ -2464,6 +2464,9 @@ static CURLcode ssh_init(struct connectdata *conn)
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
* do protocol-specific actions at connect-time.
@ -2489,6 +2492,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
if(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;
#ifdef CURL_LIBSSH2_DEBUG
@ -2703,8 +2713,8 @@ static CURLcode scp_done(struct connectdata *conn, CURLcode status,
}
/* return number of received (decrypted) bytes */
ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len)
static ssize_t scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
(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);
if(nwrite == LIBSSH2_ERROR_EAGAIN)
return 0;
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nwrite = 0;
}
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
* a regular CURLcode value.
*/
ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len)
static ssize_t scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
(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);
ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if (nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
return nread;
}
@ -2840,8 +2856,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
}
/* return number of sent bytes */
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len)
static ssize_t sftp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
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
@ -2852,8 +2868,10 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN)
return 0;
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nwrite = 0;
}
return nwrite;
}
@ -2861,8 +2879,8 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
/*
* Return number of received (decrypted) bytes
*/
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len)
static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
(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);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
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_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 /* 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);
}
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
* 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);
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 */
CURLcode Curl_ssl_initsessions(struct SessionHandle *, long);
size_t Curl_ssl_version(char *buffer, size_t size);

View File

@ -2352,6 +2352,9 @@ ossl_connect_step3(struct connectdata *conn,
return retcode;
}
static Curl_recv ossl_recv;
static Curl_send ossl_send;
static CURLcode
ossl_connect_common(struct connectdata *conn,
int sockindex,
@ -2437,6 +2440,8 @@ ossl_connect_common(struct connectdata *conn,
if(ssl_connect_done==connssl->connecting_state) {
connssl->state = ssl_connection_complete;
conn->recv = ossl_recv;
conn->send = ossl_send;
*done = TRUE;
}
else
@ -2482,12 +2487,11 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
return FALSE;
}
/* 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)
static ssize_t ossl_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
/* SSL_write() is said to return 'int' while write() and send() returns
'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
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
*curlcode = /* EWOULDBLOCK */ -1;
*curlcode = CURLE_AGAIN;
return -1;
case SSL_ERROR_SYSCALL:
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 */
}
/* 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)
static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
char error_buffer[120]; /* OpenSSL documents that this must be at
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_WRITE:
/* there's data pending, re-invoke SSL_read() */
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
default:
/* 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);
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);
int Curl_ossl_check_cxn(struct connectdata *cxn);
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_default(x) Curl_ossl_set_engine_default(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_check_cxn Curl_ossl_check_cxn
#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];
int poll_cnt;
#endif
int ret;
ssize_t nread;
struct timeval now;
bool keepon = TRUE;
@ -1383,14 +1382,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
ret = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* returned sub-zero, this would've blocked. Loop again */
if(ret < 0)
code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* read would've blocked. Loop again */
if(code == CURLE_AGAIN)
break;
/* returned not-zero, this an error */
else if(ret) {
else if(code) {
keepon = FALSE;
code = (CURLcode)ret;
break;
}
/* returned zero but actually received 0 or less here,
@ -1472,14 +1470,13 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
ret = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* returned sub-zero, this would've blocked. Loop again */
if(ret < 0)
code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
/* read would've blocked. Loop again */
if(code == CURLE_AGAIN)
break;
/* returned not-zero, this an error */
else if(ret) {
else if(code) {
keepon = FALSE;
code = (CURLcode)ret;
break;
}
/* returned zero but actually received 0 or less here,

View File

@ -376,12 +376,11 @@ static CURLcode readwrite_data(struct SessionHandle *data,
*done = FALSE;
/* 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 {
size_t buffersize = data->set.buffer_size?
data->set.buffer_size : BUFSIZE;
size_t bytestoread = buffersize;
int readrc;
if(k->size != -1 && !k->header) {
/* 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) {
/* 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 */
if(0 > readrc)
/* read would've blocked */
if(CURLE_AGAIN == result)
break; /* get out of loop */
/* get the CURLcode from the int */
result = (CURLcode)readrc;
if(result>0)
return result;
}

View File

@ -4760,6 +4760,9 @@ static CURLcode create_conn(struct SessionHandle *data,
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
***********************************************************************/

View File

@ -650,6 +650,20 @@ struct Curl_handler {
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
* 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
transfer when doing FTP */
Curl_recv *recv;
Curl_send *send;
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
struct ssl_config_data ssl_config;