From b7c676d13f0988bde9bb0e4c3cfc688072cdb2e0 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Wed, 11 Jun 2025 14:50:15 +0200 Subject: [PATCH] vtls: change send/recv signatures of tls backends Similar to connection filter changes, return a CURLcode and the read/written amount as size_t *. Closes #17593 --- lib/vtls/gtls.c | 110 ++++++++++++++++++------------------- lib/vtls/mbedtls.c | 71 ++++++++++++------------ lib/vtls/openssl.c | 92 +++++++++++++++---------------- lib/vtls/rustls.c | 128 ++++++++++++++++++++------------------------ lib/vtls/schannel.c | 121 ++++++++++++++++++++--------------------- lib/vtls/vtls.c | 39 +++++--------- lib/vtls/vtls_int.h | 8 +-- lib/vtls/wolfssl.c | 87 ++++++++++++++---------------- 8 files changed, 309 insertions(+), 347 deletions(-) diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 9fe09ac0ce..9ca0108c2f 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -1948,48 +1948,49 @@ static bool gtls_data_pending(struct Curl_cfilter *cf, return FALSE; } -static ssize_t gtls_send(struct Curl_cfilter *cf, - struct Curl_easy *data, - const void *buf, - size_t blen, - CURLcode *curlcode) +static CURLcode gtls_send(struct Curl_cfilter *cf, + struct Curl_easy *data, + const void *buf, + size_t blen, + size_t *pnwritten) { struct ssl_connect_data *connssl = cf->ctx; struct gtls_ssl_backend_data *backend = (struct gtls_ssl_backend_data *)connssl->backend; - ssize_t rc; - size_t nwritten, total_written = 0; + CURLcode result = CURLE_OK; + ssize_t nwritten; + size_t remain = blen; (void)data; DEBUGASSERT(backend); + *pnwritten = 0; - while(blen) { + while(remain) { backend->gtls.io_result = CURLE_OK; - rc = gnutls_record_send(backend->gtls.session, buf, blen); + nwritten = gnutls_record_send(backend->gtls.session, buf, remain); - if(rc < 0) { - if(total_written && (rc == GNUTLS_E_AGAIN)) { - *curlcode = CURLE_OK; - rc = (ssize_t)total_written; + if(nwritten >= 0) { + *pnwritten += (size_t)nwritten; + DEBUGASSERT((size_t)nwritten <= remain); + buf = (char *)CURL_UNCONST(buf) + (size_t)nwritten; + remain -= (size_t)nwritten; + } + else { + if(*pnwritten && (nwritten == GNUTLS_E_AGAIN)) { + result = CURLE_OK; goto out; } - *curlcode = (rc == GNUTLS_E_AGAIN) ? + result = (nwritten == GNUTLS_E_AGAIN) ? CURLE_AGAIN : (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR); - - rc = -1; goto out; } - nwritten = (size_t)rc; - total_written += nwritten; - DEBUGASSERT(nwritten <= blen); - buf = (char *)CURL_UNCONST(buf) + nwritten; - blen -= nwritten; } - rc = total_written; out: - return rc; + CURL_TRC_CF(data, cf, "gtls_send(len=%zu) -> %d, %zu", + blen, result, *pnwritten); + return result; } /* @@ -2095,50 +2096,49 @@ static void gtls_close(struct Curl_cfilter *cf, #endif } -static ssize_t gtls_recv(struct Curl_cfilter *cf, - struct Curl_easy *data, - char *buf, - size_t buffersize, - CURLcode *curlcode) +static CURLcode gtls_recv(struct Curl_cfilter *cf, + struct Curl_easy *data, + char *buf, size_t blen, + size_t *pnread) { struct ssl_connect_data *connssl = cf->ctx; struct gtls_ssl_backend_data *backend = (struct gtls_ssl_backend_data *)connssl->backend; - ssize_t ret; + CURLcode result = CURLE_OK; + ssize_t nread; (void)data; DEBUGASSERT(backend); - ret = gnutls_record_recv(backend->gtls.session, buf, buffersize); - if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { - *curlcode = CURLE_AGAIN; - ret = -1; - goto out; - } + nread = gnutls_record_recv(backend->gtls.session, buf, blen); - if(ret == GNUTLS_E_REHANDSHAKE) { - /* BLOCKING call, this is bad but a work-around for now. Fixing this "the - proper way" takes a whole lot of work. */ - CURLcode result = handshake(cf, data); - if(result) - *curlcode = result; - else - *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ - ret = -1; - goto out; - } - - if(ret < 0) { - failf(data, "GnuTLS recv error (%d): %s", - (int)ret, gnutls_strerror((int)ret)); - *curlcode = backend->gtls.io_result ? - backend->gtls.io_result : CURLE_RECV_ERROR; - ret = -1; - goto out; + if(nread >= 0) + *pnread = (size_t)nread; + else { + if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) { + result = CURLE_AGAIN; + goto out; + } + else if(nread == GNUTLS_E_REHANDSHAKE) { + /* BLOCKING call, this is bad but a work-around for now. Fixing this "the + proper way" takes a whole lot of work. */ + result = handshake(cf, data); + if(!result) + result = CURLE_AGAIN; /* then return as if this was a wouldblock */ + goto out; + } + else { + failf(data, "GnuTLS recv error (%d): %s", + (int)nread, gnutls_strerror((int)nread)); + result = backend->gtls.io_result ? + backend->gtls.io_result : CURLE_RECV_ERROR; + goto out; + } } out: - return ret; + CURL_TRC_CF(data, cf, "gtls_recv(len=%zu) -> 0, %zu", blen, *pnread); + return result; } size_t Curl_gtls_version(char *buffer, size_t size) diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 3e94fdff08..80d43aec86 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -1203,16 +1203,18 @@ out: return result; } -static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *mem, size_t len, - CURLcode *curlcode) +static CURLcode mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, + const void *mem, size_t len, + size_t *pnwritten) { struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = (struct mbed_ssl_backend_data *)connssl->backend; - int ret = -1; + CURLcode result = CURLE_OK; + int nwritten; (void)data; + *pnwritten = 0; DEBUGASSERT(backend); /* mbedtls is picky when a mbedtls_ssl_write) was previously blocked. * It requires to be called with the same amount of bytes again, or it @@ -1225,28 +1227,29 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, len = backend->send_blocked_len; } - ret = mbedtls_ssl_write(&backend->ssl, (const unsigned char *)mem, len); + nwritten = mbedtls_ssl_write(&backend->ssl, (const unsigned char *)mem, len); - if(ret < 0) { + if(nwritten >= 0) { + *pnwritten = (size_t)nwritten; + backend->send_blocked = FALSE; + } + else { CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X", - len, -ret); - *curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE) + len, -nwritten); + result = ((nwritten == MBEDTLS_ERR_SSL_WANT_WRITE) #ifdef HAS_TLS13_SUPPORT - || (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) + || (nwritten == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) #endif ) ? CURLE_AGAIN : CURLE_SEND_ERROR; - ret = -1; - if((*curlcode == CURLE_AGAIN) && !backend->send_blocked) { + if((result == CURLE_AGAIN) && !backend->send_blocked) { backend->send_blocked = TRUE; backend->send_blocked_len = len; } } - else { - CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d", len, ret); - backend->send_blocked = FALSE; - } - return ret; + CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d, %zu", + len, result, *pnwritten); + return result; } static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf, @@ -1365,48 +1368,48 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data) } } -static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t buffersize, - CURLcode *curlcode) +static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, + char *buf, size_t buffersize, + size_t *pnread) { struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = (struct mbed_ssl_backend_data *)connssl->backend; - int ret = -1; + CURLcode result = CURLE_OK; + int nread; (void)data; DEBUGASSERT(backend); + *pnread = 0; - ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, - buffersize); - if(ret <= 0) { + nread = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, buffersize); + if(nread > 0) + *pnread = (size_t)nread; + else { CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X", - buffersize, -ret); - switch(ret) { + buffersize, -nread); + switch(nread) { #ifdef HAS_SESSION_TICKETS case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: mbed_new_session(cf, data); FALLTHROUGH(); #endif case MBEDTLS_ERR_SSL_WANT_READ: - *curlcode = CURLE_AGAIN; - ret = -1; + result = CURLE_AGAIN; break; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: - *curlcode = CURLE_OK; - ret = 0; + result = CURLE_OK; break; default: { char errorbuf[128]; - mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "ssl_read returned: (-0x%04X) %s", -ret, errorbuf); - *curlcode = CURLE_RECV_ERROR; - ret = -1; + mbedtls_strerror(nread, errorbuf, sizeof(errorbuf)); + failf(data, "ssl_read returned: (-0x%04X) %s", -nread, errorbuf); + result = CURLE_RECV_ERROR; break; } } } - return (ssize_t)ret; + return result; } static size_t mbedtls_version(char *buffer, size_t size) diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index e7a82fffd5..d5f98eff27 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2177,6 +2177,8 @@ static CURLcode ossl_shutdown(struct Curl_cfilter *cf, out: cf->shutdown = (result || *done); + if(cf->shutdown || (connssl->io_need != CURL_SSL_IO_NEED_NONE)) + connssl->input_pending = FALSE; return result; } @@ -2188,6 +2190,7 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data) (void)data; DEBUGASSERT(octx); + connssl->input_pending = FALSE; if(octx->ssl) { SSL_free(octx->ssl); octx->ssl = NULL; @@ -5227,11 +5230,11 @@ static bool ossl_data_pending(struct Curl_cfilter *cf, return connssl->input_pending; } -static ssize_t ossl_send(struct Curl_cfilter *cf, - struct Curl_easy *data, - const void *mem, - size_t len, - CURLcode *curlcode) +static CURLcode ossl_send(struct Curl_cfilter *cf, + struct Curl_easy *data, + const void *mem, + size_t len, + size_t *pnwritten) { /* SSL_write() is said to return 'int' while write() and send() returns 'size_t' */ @@ -5239,39 +5242,39 @@ static ssize_t ossl_send(struct Curl_cfilter *cf, char error_buffer[256]; sslerr_t sslerror; int memlen; - int rc; struct ssl_connect_data *connssl = cf->ctx; struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend; + CURLcode result = CURLE_OK; + int nwritten; (void)data; DEBUGASSERT(octx); - + *pnwritten = 0; ERR_clear_error(); connssl->io_need = CURL_SSL_IO_NEED_NONE; memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; - rc = SSL_write(octx->ssl, mem, memlen); + nwritten = SSL_write(octx->ssl, mem, memlen); - if(rc <= 0) { - err = SSL_get_error(octx->ssl, rc); + if(nwritten > 0) + *pnwritten = (size_t)nwritten; + else { + err = SSL_get_error(octx->ssl, nwritten); switch(err) { case SSL_ERROR_WANT_READ: connssl->io_need = CURL_SSL_IO_NEED_RECV; - *curlcode = CURLE_AGAIN; - rc = -1; + result = CURLE_AGAIN; goto out; case SSL_ERROR_WANT_WRITE: - *curlcode = CURLE_AGAIN; - rc = -1; + result = CURLE_AGAIN; goto out; case SSL_ERROR_SYSCALL: { int sockerr = SOCKERRNO; if(octx->io_result == CURLE_AGAIN) { - *curlcode = CURLE_AGAIN; - rc = -1; + result = CURLE_AGAIN; goto out; } sslerror = ERR_get_error(); @@ -5285,8 +5288,7 @@ static ssize_t ossl_send(struct Curl_cfilter *cf, failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d", error_buffer, sockerr); - *curlcode = CURLE_SEND_ERROR; - rc = -1; + result = CURLE_SEND_ERROR; goto out; } case SSL_ERROR_SSL: { @@ -5295,49 +5297,50 @@ static ssize_t ossl_send(struct Curl_cfilter *cf, sslerror = ERR_get_error(); failf(data, "SSL_write() error: %s", ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); - *curlcode = CURLE_SEND_ERROR; - rc = -1; + result = CURLE_SEND_ERROR; goto out; } default: /* a true error */ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d", SSL_ERROR_to_str(err), SOCKERRNO); - *curlcode = CURLE_SEND_ERROR; - rc = -1; + result = CURLE_SEND_ERROR; goto out; } } - *curlcode = CURLE_OK; out: - return (ssize_t)rc; /* number of bytes */ + return result; } -static ssize_t ossl_recv(struct Curl_cfilter *cf, - struct Curl_easy *data, /* transfer */ - char *buf, /* store read data here */ - size_t buffersize, /* max amount to read */ - CURLcode *curlcode) +static CURLcode ossl_recv(struct Curl_cfilter *cf, + struct Curl_easy *data, /* transfer */ + char *buf, /* store read data here */ + size_t buffersize, /* max amount to read */ + size_t *pnread) { char error_buffer[256]; unsigned long sslerror; - ssize_t nread; int buffsize; struct connectdata *conn = cf->conn; struct ssl_connect_data *connssl = cf->ctx; struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend; + CURLcode result = CURLE_OK; + int nread; (void)data; DEBUGASSERT(octx); + *pnread = 0; ERR_clear_error(); connssl->io_need = CURL_SSL_IO_NEED_NONE; buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; - nread = (ssize_t)SSL_read(octx->ssl, buf, buffsize); + nread = SSL_read(octx->ssl, buf, buffsize); - if(nread <= 0) { + if(nread > 0) + *pnread = (size_t)nread; + else { /* failed SSL_read */ int err = SSL_get_error(octx->ssl, (int)nread); @@ -5352,21 +5355,18 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf, connclose(conn, "TLS close_notify"); break; case SSL_ERROR_WANT_READ: - *curlcode = CURLE_AGAIN; - nread = -1; + result = CURLE_AGAIN; goto out; case SSL_ERROR_WANT_WRITE: connssl->io_need = CURL_SSL_IO_NEED_SEND; - *curlcode = CURLE_AGAIN; - nread = -1; + result = CURLE_AGAIN; goto out; default: /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return value/errno" */ /* https://docs.openssl.org/master/man3/ERR_get_error/ */ if(octx->io_result == CURLE_AGAIN) { - *curlcode = CURLE_AGAIN; - nread = -1; + result = CURLE_AGAIN; goto out; } sslerror = ERR_get_error(); @@ -5383,18 +5383,17 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf, SSL_ERROR_to_str(err)); failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d", error_buffer, sockerr); - *curlcode = CURLE_RECV_ERROR; - nread = -1; + result = CURLE_RECV_ERROR; goto out; } else if(err == SSL_ERROR_SYSCALL) { if(octx->io_result) { /* logging handling in underlying filter already */ - *curlcode = octx->io_result; + result = octx->io_result; } else if(connssl->peer_closed) { failf(data, "Connection closed abruptly"); - *curlcode = CURLE_RECV_ERROR; + result = CURLE_RECV_ERROR; } else { /* We should no longer get here nowadays. But handle @@ -5408,16 +5407,15 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf, } failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d", error_buffer, sockerr); - *curlcode = CURLE_RECV_ERROR; + result = CURLE_RECV_ERROR; } - nread = -1; goto out; } } } out: - if(!nread || ((nread < 0) && (*curlcode == CURLE_AGAIN))) { + if((!result && !*pnread) || (result == CURLE_AGAIN)) { /* This happens when: * - we read an EOF * - OpenSSLs buffers are empty, there is no more data @@ -5426,7 +5424,9 @@ out: * until more data arrives */ connssl->input_pending = FALSE; } - return nread; + CURL_TRC_CF(data, cf, "ossl_recv(len=%zu) -> %d, %zu (in_pending=%d)", + buffersize, result, *pnread, connssl->input_pending); + return result; } static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex, diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index 391dede4c9..24f646078d 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -195,37 +195,37 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf, * buffer, and process packets, but will not consume bytes from Rustls' * plaintext output buffer. */ -static ssize_t +static CURLcode cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *plainbuf, size_t plainlen, CURLcode *err) + char *plainbuf, size_t plainlen, size_t *pnread) { const struct ssl_connect_data *const connssl = cf->ctx; struct rustls_ssl_backend_data *const backend = (struct rustls_ssl_backend_data *)connssl->backend; struct rustls_connection *rconn = NULL; + CURLcode result = CURLE_OK; size_t n = 0; - size_t plain_bytes_copied = 0; rustls_result rresult = 0; - ssize_t nread; bool eof = FALSE; DEBUGASSERT(backend); + *pnread = 0; rconn = backend->conn; - while(plain_bytes_copied < plainlen) { + while(*pnread < plainlen) { if(!backend->data_in_pending) { - if(tls_recv_more(cf, data, err) < 0) { - if(*err != CURLE_AGAIN) { - nread = -1; + if(tls_recv_more(cf, data, &result) < 0) { + if(result != CURLE_AGAIN) { goto out; } + result = CURLE_OK; break; } } rresult = rustls_connection_read(rconn, - (uint8_t *)plainbuf + plain_bytes_copied, - plainlen - plain_bytes_copied, + (uint8_t *)plainbuf + *pnread, + plainlen - *pnread, &n); if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) { backend->data_in_pending = FALSE; @@ -233,15 +233,13 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) { failf(data, "rustls: peer closed TCP connection " "without first closing TLS connection"); - *err = CURLE_RECV_ERROR; - nread = -1; + result = CURLE_RECV_ERROR; goto out; } else if(rresult != RUSTLS_RESULT_OK) { /* n always equals 0 in this case, do not need to check it */ rustls_failf(data, rresult, "rustls_connection_read"); - *err = CURLE_RECV_ERROR; - nread = -1; + result = CURLE_RECV_ERROR; goto out; } else if(n == 0) { @@ -252,27 +250,18 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, break; } else { - plain_bytes_copied += n; + *pnread += n; } } - if(plain_bytes_copied) { - *err = CURLE_OK; - nread = (ssize_t)plain_bytes_copied; - } - else if(eof) { - *err = CURLE_OK; - nread = 0; - } - else { - *err = CURLE_AGAIN; - nread = -1; + if(!eof && !*pnread) { + result = CURLE_AGAIN; } out: - CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", - plainlen, nread, *err); - return nread; + CURL_TRC_CF(data, cf, "rustls_recv(len=%zu) -> %d, %zu", + plainlen, result, *pnread); + return result; } static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -320,9 +309,9 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data, * In that case, it will not read anything into Rustls' plaintext input buffer. * It will only drain Rustls' plaintext output buffer into the socket. */ -static ssize_t +static CURLcode cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *plainbuf, size_t plainlen, CURLcode *err) + const void *plainbuf, size_t plainlen, size_t *pnwritten) { const struct ssl_connect_data *const connssl = cf->ctx; struct rustls_ssl_backend_data *const backend = @@ -330,10 +319,11 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, struct rustls_connection *rconn = NULL; size_t plainwritten = 0; const unsigned char *buf = plainbuf; + CURLcode result = CURLE_OK; size_t blen = plainlen; - ssize_t nwritten = 0; DEBUGASSERT(backend); + *pnwritten = 0; rconn = backend->conn; DEBUGASSERT(rconn); @@ -344,18 +334,18 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, * if successful, deduct the previous plain bytes from the current * send. */ if(backend->plain_out_buffered) { - *err = cr_flush_out(cf, data, rconn); + result = cr_flush_out(cf, data, rconn); CURL_TRC_CF(data, cf, "cf_send: flushing %zu previously added bytes -> %d", - backend->plain_out_buffered, *err); - if(*err) - return -1; + backend->plain_out_buffered, result); + if(result) + return result; if(blen > backend->plain_out_buffered) { blen -= backend->plain_out_buffered; buf += backend->plain_out_buffered; } else blen = 0; - nwritten += (ssize_t)backend->plain_out_buffered; + *pnwritten += (ssize_t)backend->plain_out_buffered; backend->plain_out_buffered = 0; } @@ -365,37 +355,35 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, rresult = rustls_connection_write(rconn, buf, blen, &plainwritten); if(rresult != RUSTLS_RESULT_OK) { rustls_failf(data, rresult, "rustls_connection_write"); - *err = CURLE_WRITE_ERROR; - return -1; + result = CURLE_WRITE_ERROR; + goto out; } else if(plainwritten == 0) { failf(data, "rustls_connection_write: EOF"); - *err = CURLE_WRITE_ERROR; - return -1; + result = CURLE_WRITE_ERROR; + goto out; } } - *err = cr_flush_out(cf, data, rconn); - if(*err) { - if(CURLE_AGAIN == *err) { + result = cr_flush_out(cf, data, rconn); + if(result) { + if(CURLE_AGAIN == result) { /* The TLS bytes may have been partially written, but we fail the * complete send() and remember how much we already added to Rustls. */ - CURL_TRC_CF(data, cf, "cf_send: EAGAIN, remember we added %zu plain" - " bytes already to Rustls", blen); backend->plain_out_buffered = plainwritten; - if(nwritten) { - *err = CURLE_OK; - return (ssize_t)nwritten; + if(*pnwritten) { + result = CURLE_OK; } } - return -1; + goto out; } else - nwritten += (ssize_t)plainwritten; + *pnwritten += (ssize_t)plainwritten; - CURL_TRC_CF(data, cf, "cf_send(len=%zu) -> %d, %zd", - plainlen, *err, nwritten); - return nwritten; +out: + CURL_TRC_CF(data, cf, "rustls_send(len=%zu) -> %d, %zd", + plainlen, result, *pnwritten); + return result; } /* A server certificate verify callback for Rustls that always returns @@ -1184,8 +1172,9 @@ cr_connect(struct Curl_cfilter *cf, * send its FINISHED message off. We attempt to let it write * one more time. Oh my. */ + size_t nwritten; cr_set_negotiated_alpn(cf, data, rconn); - cr_send(cf, data, NULL, 0, &tmperr); + tmperr = cr_send(cf, data, NULL, 0, &nwritten); if(tmperr == CURLE_AGAIN) { connssl->io_need = CURL_SSL_IO_NEED_SEND; return CURLE_OK; @@ -1258,8 +1247,9 @@ cr_connect(struct Curl_cfilter *cf, DEBUGASSERT(wants_read || wants_write); if(wants_write) { + size_t nwritten; CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls."); - cr_send(cf, data, NULL, 0, &tmperr); + tmperr = cr_send(cf, data, NULL, 0, &nwritten); if(tmperr == CURLE_AGAIN) { CURL_TRC_CF(data, cf, "writing would block"); connssl->io_need = CURL_SSL_IO_NEED_SEND; @@ -1312,8 +1302,7 @@ cr_shutdown(struct Curl_cfilter *cf, struct rustls_ssl_backend_data *backend = (struct rustls_ssl_backend_data *)connssl->backend; CURLcode result = CURLE_OK; - ssize_t nwritten, nread; - size_t i; + size_t i, nread, nwritten; DEBUGASSERT(backend); if(!backend->conn || cf->shutdown) { @@ -1332,8 +1321,8 @@ cr_shutdown(struct Curl_cfilter *cf, } } - nwritten = cr_send(cf, data, NULL, 0, &result); - if(nwritten < 0) { + result = cr_send(cf, data, NULL, 0, &nwritten); + if(result) { if(result == CURLE_AGAIN) { connssl->io_need = CURL_SSL_IO_NEED_SEND; result = CURLE_OK; @@ -1346,26 +1335,23 @@ cr_shutdown(struct Curl_cfilter *cf, for(i = 0; i < 10; ++i) { char buf[1024]; - nread = cr_recv(cf, data, buf, (int)sizeof(buf), &result); - if(nread <= 0) + result = cr_recv(cf, data, buf, (int)sizeof(buf), &nread); + if(result) break; } - if(nread > 0) { - /* still data coming in? */ - } - else if(nread == 0) { - /* We got the close notify alert and are done. */ - *done = TRUE; - } - else if(result == CURLE_AGAIN) { + if(result == CURLE_AGAIN) { connssl->io_need = CURL_SSL_IO_NEED_RECV; result = CURLE_OK; } - else { + else if(result) { DEBUGASSERT(result); CURL_TRC_CF(data, cf, "shutdown, error: %d", result); } + else if(nread == 0) { + /* We got the close notify alert and are done. */ + *done = TRUE; + } out: cf->shutdown = (result || *done); diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 0dfca37962..6afb4fe19c 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -1714,22 +1714,22 @@ static CURLcode schannel_connect(struct Curl_cfilter *cf, return CURLE_OK; } -static ssize_t +static CURLcode schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, CURLcode *err) + const void *buf, size_t len, size_t *pnwritten) { - ssize_t written = -1; size_t data_len = 0; unsigned char *ptr = NULL; struct ssl_connect_data *connssl = cf->ctx; SecBuffer outbuf[4]; SecBufferDesc outbuf_desc; SECURITY_STATUS sspi_status = SEC_E_OK; - CURLcode result; + CURLcode result = CURLE_OK; struct schannel_ssl_backend_data *backend = (struct schannel_ssl_backend_data *)connssl->backend; DEBUGASSERT(backend); + *pnwritten = 0; /* check if the maximum stream sizes were queried */ if(backend->stream_sizes.cbMaximumMessage == 0) { @@ -1738,8 +1738,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, SECPKG_ATTR_STREAM_SIZES, &backend->stream_sizes); if(sspi_status != SEC_E_OK) { - *err = CURLE_SEND_ERROR; - return -1; + return CURLE_SEND_ERROR; } } @@ -1753,8 +1752,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, backend->stream_sizes.cbTrailer; ptr = (unsigned char *) malloc(data_len); if(!ptr) { - *err = CURLE_OUT_OF_MEMORY; - return -1; + return CURLE_OUT_OF_MEMORY; } /* setup output buffers (header, data, trailer, empty) */ @@ -1777,7 +1775,6 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, /* check if the message was encrypted */ if(sspi_status == SEC_E_OK) { - written = 0; /* send the encrypted message including header, data and trailer */ len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; @@ -1799,16 +1796,15 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, */ /* send entire message or fail */ - while(len > (size_t)written) { + while(len > *pnwritten) { size_t this_write = 0; int what; timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE); if(timeout_ms < 0) { /* we already got the timeout */ failf(data, "schannel: timed out sending data " - "(bytes sent: %zd)", written); - *err = CURLE_OPERATION_TIMEDOUT; - written = -1; + "(bytes sent: %zu)", *pnwritten); + result = CURLE_OPERATION_TIMEDOUT; break; } else if(!timeout_ms) @@ -1817,53 +1813,49 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(what < 0) { /* fatal error */ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); - *err = CURLE_SEND_ERROR; - written = -1; + result = CURLE_SEND_ERROR; break; } else if(0 == what) { failf(data, "schannel: timed out sending data " - "(bytes sent: %zd)", written); - *err = CURLE_OPERATION_TIMEDOUT; - written = -1; + "(bytes sent: %zu)", *pnwritten); + result = CURLE_OPERATION_TIMEDOUT; break; } /* socket is writable */ result = Curl_conn_cf_send(cf->next, data, - ptr + written, len - written, + ptr + *pnwritten, len - *pnwritten, FALSE, &this_write); if(result == CURLE_AGAIN) continue; else if(result != CURLE_OK) { - *err = result; - written = -1; break; } - written += (ssize_t)this_write; + *pnwritten += this_write; } } else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { - *err = CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; } else{ - *err = CURLE_SEND_ERROR; + result = CURLE_SEND_ERROR; } Curl_safefree(ptr); - if(len == (size_t)written) + if(len == *pnwritten) /* Encrypted message including header, data and trailer entirely sent. The return value is the number of unencrypted bytes that were sent. */ - written = outbuf[1].cbBuffer; + *pnwritten = outbuf[1].cbBuffer; - return written; + return result; } -static ssize_t +static CURLcode schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t len, CURLcode *err) + char *buf, size_t len, size_t *pnread) { size_t size = 0; size_t nread = 0; @@ -1879,8 +1871,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE; struct schannel_ssl_backend_data *backend = (struct schannel_ssl_backend_data *)connssl->backend; + CURLcode result = CURLE_OK; DEBUGASSERT(backend); + *pnread = 0; /**************************************************************************** * Do not return or set backend->recv_unrecoverable_err unless in the @@ -1899,7 +1893,6 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, */ SCH_DEV(infof(data, "schannel: client wants to read %zu bytes", len)); - *err = CURLE_OK; if(len && len <= backend->decdata_offset) { SCH_DEV(infof(data, @@ -1907,7 +1900,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, goto cleanup; } else if(backend->recv_unrecoverable_err) { - *err = backend->recv_unrecoverable_err; + result = backend->recv_unrecoverable_err; infof(data, "schannel: an unrecoverable error occurred in a prior call"); goto cleanup; } @@ -1933,7 +1926,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, reallocated_buffer = realloc(backend->encdata_buffer, reallocated_length); if(!reallocated_buffer) { - *err = CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; } @@ -1950,17 +1943,17 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, backend->encdata_offset, backend->encdata_length)); /* read encrypted data from socket */ - *err = Curl_conn_cf_recv(cf->next, data, + result = Curl_conn_cf_recv(cf->next, data, (char *)(backend->encdata_buffer + backend->encdata_offset), size, &nread); - if(*err) { - if(*err == CURLE_AGAIN) + if(result) { + if(result == CURLE_AGAIN) SCH_DEV(infof(data, "schannel: recv returned CURLE_AGAIN")); - else if(*err == CURLE_RECV_ERROR) + else if(result == CURLE_RECV_ERROR) infof(data, "schannel: recv returned CURLE_RECV_ERROR"); else - infof(data, "schannel: recv returned error %d", *err); + infof(data, "schannel: recv returned error %d", result); } else if(nread == 0) { backend->recv_connection_closed = TRUE; @@ -2019,7 +2012,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, reallocated_buffer = realloc(backend->decdata_buffer, reallocated_length); if(!reallocated_buffer) { - *err = CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; } @@ -2070,7 +2063,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, /* check if server wants to renegotiate the connection context */ if(sspi_status == SEC_I_RENEGOTIATE) { infof(data, "schannel: remote party requests renegotiation"); - if(*err && *err != CURLE_AGAIN) { + if(result && result != CURLE_AGAIN) { infof(data, "schannel: cannot renegotiate, an error is pending"); goto cleanup; } @@ -2081,9 +2074,9 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, connssl->connecting_state = ssl_connect_2; connssl->io_need = CURL_SSL_IO_NEED_SEND; backend->recv_renegotiating = TRUE; - *err = schannel_connect(cf, data, &done); + result = schannel_connect(cf, data, &done); backend->recv_renegotiating = FALSE; - if(*err) { + if(result) { infof(data, "schannel: renegotiation failed"); goto cleanup; } @@ -2102,8 +2095,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, /* We received the close notify just fine, any error we got * from the lower filters afterwards (e.g. the socket), is not * an error on the TLS data stream. That one ended here. */ - if(*err == CURLE_RECV_ERROR) - *err = CURLE_OK; + if(result == CURLE_RECV_ERROR) + result = CURLE_OK; infof(data, "schannel: server close notification received (close_notify)"); goto cleanup; @@ -2111,8 +2104,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, } else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { backend->encdata_is_incomplete = TRUE; - if(!*err) - *err = CURLE_AGAIN; + if(!result) + result = CURLE_AGAIN; SCH_DEV(infof(data, "schannel: failed to decrypt data, need more data")); goto cleanup; } @@ -2122,7 +2115,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, failf(data, "schannel: failed to read data from server: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); #endif - *err = CURLE_RECV_ERROR; + result = CURLE_RECV_ERROR; goto cleanup; } } @@ -2145,13 +2138,13 @@ cleanup: */ if(len && !backend->decdata_offset && backend->recv_connection_closed && !backend->recv_sspi_close_notify) { - *err = CURLE_RECV_ERROR; + result = CURLE_RECV_ERROR; failf(data, "schannel: server closed abruptly (missing close_notify)"); } /* Any error other than CURLE_AGAIN is an unrecoverable error. */ - if(*err && *err != CURLE_AGAIN) - backend->recv_unrecoverable_err = *err; + if(result && result != CURLE_AGAIN) + backend->recv_unrecoverable_err = result; size = len < backend->decdata_offset ? len : backend->decdata_offset; if(size) { @@ -2163,21 +2156,21 @@ cleanup: SCH_DEV(infof(data, "schannel: decrypted data buffer: offset %zu length %zu", backend->decdata_offset, backend->decdata_length)); - *err = CURLE_OK; - return (ssize_t)size; + *pnread = size; + return CURLE_OK; } - if(!*err && !backend->recv_connection_closed) - *err = CURLE_AGAIN; + if(!result && !backend->recv_connection_closed) + result = CURLE_AGAIN; /* it is debatable what to return when !len. We could return whatever error we got from decryption but instead we override here so the return is consistent. */ if(!len) - *err = CURLE_OK; + return CURLE_OK; - return *err ? -1 : 0; + return result; } static bool schannel_data_pending(struct Curl_cfilter *cf, @@ -2319,23 +2312,23 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf, if(backend->cred && backend->ctxt && !backend->recv_sspi_close_notify && !backend->recv_connection_closed) { char buffer[1024]; - ssize_t nread; + size_t nread; - nread = schannel_recv(cf, data, buffer, sizeof(buffer), &result); - if(nread > 0) { - /* still data coming in? */ + result = schannel_recv(cf, data, buffer, sizeof(buffer), &nread); + if(result == CURLE_AGAIN) { + connssl->io_need = CURL_SSL_IO_NEED_RECV; + } + else if(result) { + CURL_TRC_CF(data, cf, "SSL shutdown, error %d", result); + result = CURLE_RECV_ERROR; } else if(nread == 0) { /* We got the close notify alert and are done. */ backend->recv_connection_closed = TRUE; *done = TRUE; } - else if(nread < 0 && result == CURLE_AGAIN) { - connssl->io_need = CURL_SSL_IO_NEED_RECV; - } else { - CURL_TRC_CF(data, cf, "SSL shutdown, error %d", result); - result = CURLE_RECV_ERROR; + /* still data coming in? */ } } diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 13431e1e1b..16b291cb45 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -917,23 +917,23 @@ static void multissl_close(struct Curl_cfilter *cf, struct Curl_easy *data) Curl_ssl->close(cf, data); } -static ssize_t multissl_recv_plain(struct Curl_cfilter *cf, - struct Curl_easy *data, - char *buf, size_t len, CURLcode *code) +static CURLcode multissl_recv_plain(struct Curl_cfilter *cf, + struct Curl_easy *data, + char *buf, size_t len, size_t *pnread) { if(multissl_setup(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->recv_plain(cf, data, buf, len, code); + return Curl_ssl->recv_plain(cf, data, buf, len, pnread); } -static ssize_t multissl_send_plain(struct Curl_cfilter *cf, - struct Curl_easy *data, - const void *mem, size_t len, - CURLcode *code) +static CURLcode multissl_send_plain(struct Curl_cfilter *cf, + struct Curl_easy *data, + const void *mem, size_t len, + size_t *pnwritten) { if(multissl_setup(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->send_plain(cf, data, mem, len, code); + return Curl_ssl->send_plain(cf, data, mem, len, pnwritten); } static const struct Curl_ssl Curl_ssl_multi = { @@ -1474,10 +1474,10 @@ static CURLcode ssl_cf_send(struct Curl_cfilter *cf, /* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */ if(blen > 0) { - ssize_t nwritten; - nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, &result); - if(nwritten > 0) - *pnwritten += (size_t)nwritten; + size_t nwritten; + result = connssl->ssl_impl->send_plain(cf, data, buf, blen, &nwritten); + if(!result) + *pnwritten += nwritten; } out: @@ -1492,7 +1492,6 @@ static CURLcode ssl_cf_recv(struct Curl_cfilter *cf, struct ssl_connect_data *connssl = cf->ctx; struct cf_call_data save; CURLcode result = CURLE_OK; - ssize_t nread; CF_DATA_SAVE(save, cf, data); *pnread = 0; @@ -1508,19 +1507,9 @@ static CURLcode ssl_cf_recv(struct Curl_cfilter *cf, DEBUGASSERT(connssl->state == ssl_connection_complete); } - nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, &result); - if(nread > 0) { - DEBUGASSERT((size_t)nread <= len); - *pnread = (size_t)nread; - } - else if(nread == 0) { - /* eof */ - result = CURLE_OK; - } + result = connssl->ssl_impl->recv_plain(cf, data, buf, len, pnread); out: - CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %d, %zd", len, - result, *pnread); CF_DATA_RESTORE(cf, save); return result; } diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h index 6cd2ae4d26..11987c382a 100644 --- a/lib/vtls/vtls_int.h +++ b/lib/vtls/vtls_int.h @@ -178,10 +178,10 @@ struct Curl_ssl { CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, unsigned char *sha256sum, size_t sha256sumlen); - ssize_t (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t len, CURLcode *code); - ssize_t (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *mem, size_t len, CURLcode *code); + CURLcode (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, + char *buf, size_t len, size_t *pnread); + CURLcode (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, + const void *mem, size_t len, size_t *pnwritten); CURLcode (*get_channel_binding)(struct Curl_easy *data, int sockindex, struct dynbuf *binding); diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index d842d88c26..610cc4d7e5 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -1789,49 +1789,48 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf, } } -static ssize_t wssl_send(struct Curl_cfilter *cf, - struct Curl_easy *data, - const void *buf, size_t blen, - CURLcode *curlcode) +static CURLcode wssl_send(struct Curl_cfilter *cf, + struct Curl_easy *data, + const void *buf, size_t blen, + size_t *pnwritten) { struct ssl_connect_data *connssl = cf->ctx; struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; - size_t total_written = 0; - ssize_t nwritten = -1; - DEBUGASSERT(wssl); + CURLcode result = CURLE_OK; + int nwritten; + DEBUGASSERT(wssl); + *pnwritten = 0; wolfSSL_ERR_clear_error(); if(blen) { int memlen = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen; - int rc; - rc = wolfSSL_write(wssl->ssl, buf, memlen); - if(rc <= 0) { - int err = wolfSSL_get_error(wssl->ssl, rc); + nwritten = wolfSSL_write(wssl->ssl, buf, memlen); + + if(nwritten > 0) + *pnwritten += (size_t)nwritten; + else { + int err = wolfSSL_get_error(wssl->ssl, nwritten); switch(err) { case WOLFSSL_ERROR_WANT_READ: case WOLFSSL_ERROR_WANT_WRITE: /* there is data pending, re-invoke wolfSSL_write() */ - if(total_written) { - *curlcode = CURLE_OK; - nwritten = total_written; + if(*pnwritten) { + result = CURLE_OK; goto out; } - *curlcode = CURLE_AGAIN; - nwritten = -1; + result = CURLE_AGAIN; goto out; default: if(wssl->io_result == CURLE_AGAIN) { - if(total_written) { - *curlcode = CURLE_OK; - nwritten = total_written; + if(*pnwritten) { + result = CURLE_OK; goto out; } - *curlcode = CURLE_AGAIN; - nwritten = -1; + result = CURLE_AGAIN; goto out; } { @@ -1841,21 +1840,16 @@ static ssize_t wssl_send(struct Curl_cfilter *cf, sizeof(error_buffer)), SOCKERRNO); } - *curlcode = CURLE_SEND_ERROR; - nwritten = -1; + result = CURLE_SEND_ERROR; goto out; } } - else - total_written += rc; } - *curlcode = CURLE_OK; - nwritten = total_written; out: - CURL_TRC_CF(data, cf, "wssl_send(len=%zu) -> %" FMT_OFF_T ", %d", - blen, nwritten, *curlcode); - return nwritten; + CURL_TRC_CF(data, cf, "wssl_send(len=%zu) -> %d, %zu", + blen, result, *pnwritten); + return result; } static CURLcode wssl_shutdown(struct Curl_cfilter *cf, @@ -1982,10 +1976,10 @@ static void wssl_close(struct Curl_cfilter *cf, struct Curl_easy *data) } } -static ssize_t wssl_recv(struct Curl_cfilter *cf, - struct Curl_easy *data, - char *buf, size_t blen, - CURLcode *curlcode) +static CURLcode wssl_recv(struct Curl_cfilter *cf, + struct Curl_easy *data, + char *buf, size_t blen, + size_t *pnread) { struct ssl_connect_data *connssl = cf->ctx; struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; @@ -1994,36 +1988,34 @@ static ssize_t wssl_recv(struct Curl_cfilter *cf, DEBUGASSERT(wssl); + *pnread = 0; wolfSSL_ERR_clear_error(); - *curlcode = CURLE_OK; nread = wolfSSL_read(wssl->ssl, buf, buffsize); - if(nread <= 0) { + if(nread > 0) + *pnread = (size_t)nread; + else { int err = wolfSSL_get_error(wssl->ssl, nread); switch(err) { case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */ CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen); - *curlcode = CURLE_OK; - return 0; + return CURLE_OK; case WOLFSSL_ERROR_NONE: case WOLFSSL_ERROR_WANT_READ: case WOLFSSL_ERROR_WANT_WRITE: if(!wssl->io_result && connssl->peer_closed) { CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen); - *curlcode = CURLE_OK; - return 0; + return CURLE_OK; } /* there is data pending, re-invoke wolfSSL_read() */ CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> AGAIN", blen); - *curlcode = CURLE_AGAIN; - return -1; + return CURLE_AGAIN; default: if(wssl->io_result == CURLE_AGAIN) { CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> AGAIN", blen); - *curlcode = CURLE_AGAIN; - return -1; + return CURLE_AGAIN; } else if(!wssl->io_result && connssl->peer_closed) { CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> CLOSED", blen); @@ -2036,13 +2028,12 @@ static ssize_t wssl_recv(struct Curl_cfilter *cf, sizeof(error_buffer)), SOCKERRNO); } - *curlcode = CURLE_RECV_ERROR; - return -1; + return CURLE_RECV_ERROR; } } - CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> %d", blen, nread); - return nread; + CURL_TRC_CF(data, cf, "wssl_recv(len=%zu) -> 0, %zu", blen, *pnread); + return CURLE_OK; } size_t Curl_wssl_version(char *buffer, size_t size) -- 2.47.2