diff --git a/lib/gtls.c b/lib/gtls.c index 4f5edaf..6622d84 100644 --- a/lib/gtls.c +++ b/lib/gtls.c @@ -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,8 +735,7 @@ 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, +static ssize_t gtls_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, @@ -741,7 +745,7 @@ ssize_t Curl_gtls_send(struct connectdata *conn, 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 */ + int *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; } diff --git a/lib/gtls.h b/lib/gtls.h index da3489b..51e0af1 100644 --- a/lib/gtls.h +++ b/lib/gtls.h @@ -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) diff --git a/lib/krb4.h b/lib/krb4.h index 81998b5..2642793 100644 --- a/lib/krb4.h +++ b/lib/krb4.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2010, Daniel Stenberg, , 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 *); diff --git a/lib/nss.c b/lib/nss.c index addb94b..a2488d0 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -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 { diff --git a/lib/nssg.h b/lib/nssg.h index 309c3d6..6eaa178 100644 --- a/lib/nssg.h +++ b/lib/nssg.h @@ -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) diff --git a/lib/polarssl.c b/lib/polarssl.c index 95baa13..0027e31 100644 --- a/lib/polarssl.c +++ b/lib/polarssl.c @@ -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; } diff --git a/lib/polarssl.h b/lib/polarssl.h index 7d406ef..be90598 100644 --- a/lib/polarssl.h +++ b/lib/polarssl.h @@ -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) diff --git a/lib/qssl.c b/lib/qssl.c index 5a08a25..74f9b57 100644 --- a/lib/qssl.c +++ b/lib/qssl.c @@ -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; } diff --git a/lib/qssl.h b/lib/qssl.h index a0cf8cc..45190e6 100644 --- a/lib/qssl.h +++ b/lib/qssl.h @@ -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 diff --git a/lib/security.c b/lib/security.c index 03fc679..03b1be2 100644 --- a/lib/security.c +++ b/lib/security.c @@ -10,7 +10,7 @@ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * - * Copyright (C) 2001 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 2001 - 2010, Daniel Stenberg, , 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 */ diff --git a/lib/sendf.c b/lib/sendf.c index ff4aee3..4843214 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -234,37 +234,6 @@ 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_socket_t sockfd = conn->sock[num]; - ssize_t bytes_written = swrite(sockfd, mem, len); - - if(-1 == bytes_written) { - 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 */ - bytes_written=0; - else - failf(conn->data, "Send failure: %s", - Curl_strerror(conn, err)); - } - return bytes_written; -} - /* * Curl_write() is an internal write function that sends data to the * server. Works with plain sockets, SCP, SSL or kerberos. @@ -279,19 +248,10 @@ CURLcode Curl_write(struct connectdata *conn, ssize_t *written) { ssize_t bytes_written; - int curlcode = CURLE_OK; + CURLcode 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); + bytes_written = conn->send(conn, num, mem, len, &curlcode); *written = bytes_written; if(-1 != bytes_written) @@ -300,8 +260,8 @@ CURLcode Curl_write(struct connectdata *conn, /* handle EWOULDBLOCK or a send failure */ switch(curlcode) { - case /* EWOULDBLOCK */ -1: - *written = /* EWOULDBLOCK */ 0; + case CURLE_AGAIN: + *written = 0; return CURLE_OK; case CURLE_OK: @@ -314,6 +274,8 @@ CURLcode Curl_write(struct connectdata *conn, } } +extern Curl_send Curl_send_plain; + /* * 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,10 +291,9 @@ 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; } @@ -513,6 +474,7 @@ int Curl_read(struct connectdata *conn, /* connection data */ 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 +514,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; - } - 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(pipelining) { + memcpy(buf, conn->master_buffer, nread); + conn->buf_len = nread; + conn->read_pos = nread; } - 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; } diff --git a/lib/ssh.c b/lib/ssh.c index e4e5767..4a93099 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -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; } diff --git a/lib/ssh.h b/lib/ssh.h index 4e268c2..b92b5c0 100644 --- a/lib/ssh.h +++ b/lib/ssh.h @@ -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 */ diff --git a/lib/sslgen.c b/lib/sslgen.c index 24b6dcb..bd8dc17 100644 --- a/lib/sslgen.c +++ b/lib/sslgen.c @@ -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. diff --git a/lib/sslgen.h b/lib/sslgen.h index c56265e..997e30d 100644 --- a/lib/sslgen.h +++ b/lib/sslgen.h @@ -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); diff --git a/lib/ssluse.c b/lib/ssluse.c index d9cf382..0e23c08 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -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" */ diff --git a/lib/ssluse.h b/lib/ssluse.h index 00357af..2ac0ad2 100644 --- a/lib/ssluse.h +++ b/lib/ssluse.h @@ -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) diff --git a/lib/url.c b/lib/url.c index 56dd5dc..412ddd1 100644 --- a/lib/url.c +++ b/lib/url.c @@ -4512,6 +4512,75 @@ static void reuse_conn(struct connectdata *old_conn, Curl_safefree(old_conn->master_buffer); } +static ssize_t 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); + + 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; +} + +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); + + if(-1 == bytes_written) { + 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 */ + bytes_written=0; + *code = CURLE_AGAIN; + } else { + failf(conn->data, "Send failure: %s", + Curl_strerror(conn, err)); + *code = CURLE_SEND_ERROR; + } + } + return bytes_written; +} + /** * create_conn() sets up a new connectdata struct, or re-uses an already * existing one, and resolves host name. @@ -4760,6 +4829,9 @@ static CURLcode create_conn(struct SessionHandle *data, return result; } + conn->recv = recv_plain; + conn->send = Curl_send_plain; + /*********************************************************************** * file: is a special case in that it doesn't need a network connection ***********************************************************************/ diff --git a/lib/urldata.h b/lib/urldata.h index 7e3afee..efc56d7 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -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;