diff --git a/lib/gtls.c b/lib/gtls.c index 4f5edaf..997b922 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 = Curl_gtls_recv; + conn->send = Curl_gtls_send; { /* we always unconditionally get the session id here, as even if we @@ -731,7 +736,7 @@ Curl_gtls_connect(struct connectdata *conn, } /* 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 +746,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; @@ -844,7 +849,7 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) } /* for documentation see Curl_ssl_recv() in sslgen.h */ -ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */ +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 */ @@ -854,7 +859,7 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */ 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..f949ba5 100644 --- a/lib/krb4.h +++ b/lib/krb4.h @@ -51,13 +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 *); diff --git a/lib/nss.c b/lib/nss.c index addb94b..4c52faf 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); @@ -1374,11 +1379,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) } /* for documentation see Curl_ssl_send() in sslgen.h */ -int Curl_nss_send(struct connectdata *conn, /* connection data */ +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 */ - int *curlcode) + CURLcode *curlcode) { int rc; @@ -1387,7 +1392,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 { @@ -1400,11 +1405,11 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */ } /* for documentation see Curl_ssl_recv() in sslgen.h */ -ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */ +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 */ - int *curlcode) + CURLcode *curlcode) { ssize_t nread; @@ -1414,7 +1419,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/qssl.c b/lib/qssl.c index 5a08a25..42189bf 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; } @@ -375,8 +381,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 +398,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; } @@ -420,8 +426,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 +446,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..b734663 100644 --- a/lib/security.c +++ b/lib/security.c @@ -107,7 +107,8 @@ 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) + CURLcode err; + if(Curl_sec_read(conn, fileno(F), &c, 1, &err) <= 0) return EOF; return c; } @@ -208,15 +209,13 @@ buffer_write(struct krb4buffer *buf, void *data, size_t len) return len; } -int -Curl_sec_read(struct connectdata *conn, int fd, void *buffer, int length) +static ssize_t +Curl_sec_read(struct connectdata *conn, int fd, void *buffer, int length, + CURLcode *err) { size_t len; int rx = 0; - if(conn->sec_complete == 0 || conn->data_prot == 0) - return read(fd, buffer, length); - if(conn->in_buffer.eof_flag){ conn->in_buffer.eof_flag = 0; return 0; @@ -304,9 +303,6 @@ Curl_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,8 +317,8 @@ 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) +static ssize_t +Curl_sec_send(struct connectdata *conn, int num, const char *buffer, int length, CURLcode *err) { curl_socket_t fd = conn->sock[num]; return (ssize_t)Curl_sec_write(conn, fd, buffer, length); @@ -517,6 +513,10 @@ Curl_sec_login(struct connectdata *conn) } conn->mech = *m; conn->sec_complete = 1; + if (conn->data_prot != prot_clear) { + conn->recv = Curl_sec_read; + conn->send = Curl_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..60ea867 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: @@ -513,6 +473,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 +513,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..eedf088 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 df2a407..642edb7 100644 --- a/lib/sslgen.c +++ b/lib/sslgen.c @@ -408,25 +408,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..8d57288 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 @@ -2483,11 +2488,11 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, } /* for documentation see Curl_ssl_send() in sslgen.h */ -ssize_t Curl_ossl_send(struct connectdata *conn, +static ssize_t ossl_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, - int *curlcode) + CURLcode *curlcode) { /* SSL_write() is said to return 'int' while write() and send() returns 'size_t' */ @@ -2510,7 +2515,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", @@ -2535,11 +2540,11 @@ ssize_t Curl_ossl_send(struct connectdata *conn, } /* for documentation see Curl_ssl_recv() in sslgen.h */ -ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */ +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 */ - int *curlcode) + CURLcode *curlcode) { char error_buffer[120]; /* OpenSSL documents that this must be at least 120 bytes long. */ @@ -2560,7 +2565,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..6196221 100644 --- a/lib/url.c +++ b/lib/url.c @@ -4512,6 +4521,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; +} + +static ssize_t 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 +4838,9 @@ static CURLcode create_conn(struct SessionHandle *data, return result; } + conn->recv = recv_plain; + conn->send = 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 42065d1..8ad03ce 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -633,6 +633,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. @@ -729,6 +743,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;