From 9023aeef75e5cee620bbf2563e4a6c7a043b1759 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 29 Jun 2024 00:28:09 -0500 Subject: [PATCH] BIO/wolfio: refactor TranslateReturnCode(), wolfSSL_LastError(), and TranslateIoError() into complete+consistent wolfSSL_LastError() and TranslateIoReturnCode(), handling all special cases correctly, and correctly returning WOLFSSL_CBIO_ERR_WANT_WRITE and WOLFSSL_CBIO_ERR_TIMEOUT. use TranslateIoReturnCode() directly in wolfIO_Recv(), wolfIO_Send(), wolfIO_RecvFrom(), wolfIO_SendTo(), and remove now-superfluous TranslateIoError() calls from EmbedReceive(), EmbedSend(), EmbedReceiveFrom(), EmbedSendTo(), EmbedReceiveFromMcast(). --- src/bio.c | 16 +++- src/wolfio.c | 186 +++++++++++++++++------------------------------ wolfssl/wolfio.h | 7 ++ 3 files changed, 85 insertions(+), 124 deletions(-) diff --git a/src/bio.c b/src/bio.c index 914059db9..6ace590ca 100644 --- a/src/bio.c +++ b/src/bio.c @@ -353,8 +353,10 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) * (cannot be used with WOLFSSL_USER_IO) */ bio->flags &= ~WOLFSSL_BIO_FLAG_RETRY; ret = wolfIO_Recv(bio->num, (char*)buf, len, 0); - if (ret == WC_NO_ERR_TRACE(SOCKET_NODATA)) { + if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { bio->flags |= WOLFSSL_BIO_FLAG_RETRY; + } + if (ret < 0) { ret = WOLFSSL_BIO_ERROR; } #else @@ -374,8 +376,10 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) wolfSSL_BIO_ADDR_clear(&bio->peer_addr); ret = wolfIO_RecvFrom(bio->num, &bio->peer_addr, (char*)buf, len, 0); } - if (ret == WC_NO_ERR_TRACE(SOCKET_NODATA)) { + if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { bio->flags |= WOLFSSL_BIO_FLAG_RETRY; + } + if (ret < 0) { ret = WOLFSSL_BIO_ERROR; } #else @@ -772,8 +776,10 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) * (cannot be used with WOLFSSL_USER_IO) */ bio->flags &= ~WOLFSSL_BIO_FLAG_RETRY; ret = wolfIO_Send(bio->num, (char*)data, len, 0); - if (ret == WC_NO_ERR_TRACE(SOCKET_NODATA)) { + if (ret == WOLFSSL_CBIO_ERR_WANT_WRITE) { bio->flags |= WOLFSSL_BIO_FLAG_RETRY; + } + if (ret < 0) { ret = WOLFSSL_BIO_ERROR; } #else @@ -793,8 +799,10 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) ret = SOCKET_ERROR_E; else ret = wolfIO_SendTo(bio->num, &bio->peer_addr, (char*)data, len, 0); - if (ret == WC_NO_ERR_TRACE(SOCKET_NODATA)) { + if (ret == WOLFSSL_CBIO_ERR_WANT_WRITE) { bio->flags |= WOLFSSL_BIO_FLAG_RETRY; + } + if (ret < 0) { ret = WOLFSSL_BIO_ERROR; } #else diff --git a/src/wolfio.c b/src/wolfio.c index fbb5f28e2..e52565934 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -136,70 +136,65 @@ Possible IO enable options: #if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) -/* Translates return codes returned from - * send() and recv() if need be. - */ -static WC_INLINE int TranslateReturnCode(int old, int sd) +static WC_INLINE int wolfSSL_LastError(int err, SOCKET_T sd) { (void)sd; -#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - if (old == 0) { - errno = SOCKET_EWOULDBLOCK; - return -1; /* convert to BSD style wouldblock as error */ - } - - if (old < 0) { - errno = RTCS_geterror(sd); - if (errno == RTCSERR_TCP_CONN_CLOSING) - return 0; /* convert to BSD style closing */ - if (errno == RTCSERR_TCP_CONN_RLSD) - errno = SOCKET_ECONNRESET; - if (errno == RTCSERR_TCP_TIMED_OUT) - errno = SOCKET_EAGAIN; - } -#elif defined(WOLFSSL_EMNET) - if (old < 0) { /* SOCKET_ERROR */ - /* Get the real socket error */ - IP_SOCK_getsockopt(sd, SOL_SOCKET, SO_ERROR, &old, (int)sizeof(old)); - } -#endif - - return old; -} - -static WC_INLINE int wolfSSL_LastError(int err) -{ - (void)err; /* Suppress unused arg */ + if (err > 0) + return 0; #ifdef USE_WINDOWS_API return WSAGetLastError(); #elif defined(EBSNET) return xn_getlasterror(); #elif defined(WOLFSSL_LINUXKM) || defined(WOLFSSL_EMNET) - return -err; /* Return provided error value */ + return -err; /* Return provided error value with corrected sign. */ #elif defined(FUSION_RTOS) #include return FCL_GET_ERRNO; #elif defined(NUCLEUS_PLUS_2_3) return Nucleus_Net_Errno; +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + if ((err == 0) || (err == -SOCKET_EWOULDBLOCK)) { + return SOCKET_EWOULDBLOCK; /* convert to BSD style wouldblock */ + } else { + err = RTCS_geterror(sd); + if ((err == RTCSERR_TCP_CONN_CLOSING) || + (err == RTCSERR_TCP_CONN_RLSD)) + { + err = SOCKET_ECONNRESET; + } + return err; + } +#elif defined(WOLFSSL_EMNET) + /* Get the real socket error */ + IP_SOCK_getsockopt(sd, SOL_SOCKET, SO_ERROR, &err, (int)sizeof(old)); + return err; #else return errno; #endif } -static int TranslateIoError(int err) +/* Translates return codes returned from + * send(), recv(), and other network I/O calls. + */ +static int TranslateIoReturnCode(int err, SOCKET_T sd, int direction) { #ifdef _WIN32 size_t errstr_offset; char errstr[WOLFSSL_STRERROR_BUFFER_SIZE]; #endif /* _WIN32 */ - +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) if (err > 0) return err; +#else + if (err >= 0) + return err; +#endif + + err = wolfSSL_LastError(err, sd); - err = wolfSSL_LastError(err); #if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN if ((err == SOCKET_EWOULDBLOCK) || (err == SOCKET_EAGAIN)) #else @@ -207,8 +202,26 @@ static int TranslateIoError(int err) #endif { WOLFSSL_MSG("\tWould block"); - return WOLFSSL_CBIO_ERR_WANT_READ; + if (direction == SOCKET_SENDING) + return WOLFSSL_CBIO_ERR_WANT_WRITE; + else if (direction == SOCKET_RECEIVING) + return WOLFSSL_CBIO_ERR_WANT_READ; + else + return WOLFSSL_CBIO_ERR_GENERAL; } + +#ifdef SOCKET_ETIMEDOUT + else if (err == SOCKET_ETIMEDOUT) { + WOLFSSL_MSG("\tTimed out"); + if (direction == SOCKET_SENDING) + return WOLFSSL_CBIO_ERR_WANT_WRITE; + else if (direction == SOCKET_RECEIVING) + return WOLFSSL_CBIO_ERR_WANT_READ; + else + return WOLFSSL_CBIO_ERR_TIMEOUT; + } +#endif + else if (err == SOCKET_ECONNRESET) { WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; @@ -288,7 +301,7 @@ int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx) return WOLFSSL_CBIO_ERR_CONN_CLOSE; } #ifdef USE_WOLFSSL_IO - recvd = TranslateIoError(recvd); + recvd = TranslateIoReturnCode(recvd, ssl->biord->num, SOCKET_RECEIVING); #endif return recvd; } @@ -333,7 +346,7 @@ int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) if (sent <= 0) { if (ssl->biowr->type == WOLFSSL_BIO_SOCKET) { #ifdef USE_WOLFSSL_IO - sent = TranslateIoError(sent); + sent = TranslateIoReturnCode(sent, ssl->biowr->num, SOCKET_SENDING); #endif return sent; } @@ -377,7 +390,6 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); if (recvd < 0) { WOLFSSL_MSG("Embed Receive error"); - return TranslateIoError(recvd); } else if (recvd == 0) { WOLFSSL_MSG("Embed receive connection closed"); @@ -407,7 +419,6 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) sent = wolfIO_Send(sd, buf, sz, ssl->wflags); if (sent < 0) { WOLFSSL_MSG("Embed Send error"); - return TranslateIoError(sent); } return sent; @@ -746,11 +757,10 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz; } - recvd = TranslateReturnCode(recvd, sd); + recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING); if (recvd < 0) { WOLFSSL_MSG("Embed Receive From error"); - recvd = TranslateIoError(recvd); if (recvd == WOLFSSL_CBIO_ERR_WANT_READ && !wolfSSL_dtls_get_using_nonblock(ssl)) { recvd = WOLFSSL_CBIO_ERR_TIMEOUT; @@ -835,11 +845,10 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, ssl->wflags, (const SOCKADDR*)peer, peerSz); - sent = TranslateReturnCode(sent, sd); + sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING); if (sent < 0) { WOLFSSL_MSG("Embed Send To error"); - return TranslateIoError(sent); } return sent; @@ -861,16 +870,14 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags, NULL, NULL); - recvd = TranslateReturnCode(recvd, sd); + recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING); if (recvd < 0) { WOLFSSL_MSG("Embed Receive From error"); - recvd = TranslateIoError(recvd); if (recvd == WOLFSSL_CBIO_ERR_WANT_READ && !wolfSSL_dtls_get_using_nonblock(ssl)) { recvd = WOLFSSL_CBIO_ERR_TIMEOUT; } - return recvd; } return recvd; @@ -1098,22 +1105,7 @@ int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) int recvd; recvd = (int)RECV_FUNCTION(sd, buf, (size_t)sz, rdFlags); - recvd = TranslateReturnCode(recvd, (int)sd); - - if (recvd < 0) { - int last_err = wolfSSL_LastError(recvd); - if ((last_err == SOCKET_EWOULDBLOCK) -#if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN - || (last_err == SOCKET_EAGAIN) -#endif -#ifdef SOCKET_ETIMEDOUT - || (last_err == SOCKET_ETIMEDOUT) -#endif - ) - { - return SOCKET_NODATA; - } - } + recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING); return recvd; } @@ -1123,22 +1115,7 @@ int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) int sent; sent = (int)SEND_FUNCTION(sd, buf, (size_t)sz, wrFlags); - sent = TranslateReturnCode(sent, (int)sd); - - if (sent < 0) { - int last_err = wolfSSL_LastError(sent); - if ((last_err == SOCKET_EWOULDBLOCK) -#if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN - || (last_err == SOCKET_EAGAIN) -#endif -#ifdef SOCKET_ETIMEDOUT - || (last_err == SOCKET_ETIMEDOUT) -#endif - ) - { - return SOCKET_NODATA; - } - } + sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING); return sent; } @@ -1151,24 +1128,9 @@ int wolfIO_RecvFrom(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int socklen_t addr_len = (socklen_t)sizeof(*addr); recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, rdFlags, - addr ? &addr->sa : NULL, - addr ? &addr_len : 0); - recvd = TranslateReturnCode(recvd, (int)sd); - - if (recvd < 0) { - int last_err = wolfSSL_LastError(recvd); - if ((last_err == SOCKET_EWOULDBLOCK) -#if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN - || (last_err == SOCKET_EAGAIN) -#endif -#ifdef SOCKET_ETIMEDOUT - || (last_err == SOCKET_ETIMEDOUT) -#endif - ) - { - return SOCKET_NODATA; - } - } + addr ? &addr->sa : NULL, + addr ? &addr_len : 0); + recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING); return recvd; } @@ -1176,26 +1138,12 @@ int wolfIO_RecvFrom(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int int wolfIO_SendTo(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int wrFlags) { int sent; + socklen_t addr_len = addr ? wolfSSL_BIO_ADDR_size(addr) : 0; sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, wrFlags, - addr ? &addr->sa : NULL, - addr ? wolfSSL_BIO_ADDR_size(addr) : 0); - sent = TranslateReturnCode(sent, (int)sd); - - if (sent < 0) { - int last_err = wolfSSL_LastError(sent); - if ((last_err == SOCKET_EWOULDBLOCK) -#if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN - || (last_err == SOCKET_EAGAIN) -#endif -#ifdef SOCKET_ETIMEDOUT - || (last_err == SOCKET_ETIMEDOUT) -#endif - ) - { - return SOCKET_NODATA; - } - } + addr ? &addr->sa : NULL, + addr_len); + sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING); return sent; } @@ -1513,7 +1461,7 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) #ifdef HAVE_IO_TIMEOUT if ((ret != 0) && (to_sec > 0)) { #ifdef USE_WINDOWS_API - if ((ret == SOCKET_ERROR) && (wolfSSL_LastError(ret) == WSAEWOULDBLOCK)) + if ((ret == SOCKET_ERROR) && (wolfSSL_LastError(ret, *sockfd) == SOCKET_EWOULDBLOCK)) #else if (errno == EINPROGRESS) #endif @@ -1824,9 +1772,7 @@ int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, start[len] = 0; } else { - result = TranslateReturnCode(result, sfd); - result = wolfSSL_LastError(result); - if (result == SOCKET_EWOULDBLOCK || result == SOCKET_EAGAIN) { + if (result == WOLFSSL_CBIO_ERR_WANT_READ) { return OCSP_WANT_READ; } diff --git a/wolfssl/wolfio.h b/wolfssl/wolfio.h index eb8b20989..625ca3900 100644 --- a/wolfssl/wolfio.h +++ b/wolfssl/wolfio.h @@ -201,6 +201,9 @@ #include #endif +#define SOCKET_RECEIVING 1 +#define SOCKET_SENDING 2 + #ifdef USE_WINDOWS_API /* no epipe yet */ #ifndef WSAEPIPE @@ -228,6 +231,7 @@ /* RTCS old I/O doesn't have an EWOULDBLOCK */ #define SOCKET_EWOULDBLOCK EAGAIN #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ETIMEDOUT RTCSERR_TCP_TIMED_OUT #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET #define SOCKET_EINTR EINTR #define SOCKET_EPIPE EPIPE @@ -236,6 +240,7 @@ #else #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK #define SOCKET_EAGAIN NIO_EAGAIN + #define SOCKET_ETIMEDOUT NIO_ETIMEDOUT #define SOCKET_ECONNRESET NIO_ECONNRESET #define SOCKET_EINTR NIO_EINTR #define SOCKET_EPIPE NIO_EPIPE @@ -253,6 +258,7 @@ #elif defined(WOLFSSL_PICOTCP) #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN #define SOCKET_EAGAIN PICO_ERR_EAGAIN + #define SOCKET_ETIMEDOUT PICO_ERR_ETIMEDOUT #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET #define SOCKET_EINTR PICO_ERR_EINTR #define SOCKET_EPIPE PICO_ERR_EIO @@ -261,6 +267,7 @@ #elif defined(FREERTOS_TCP) #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK + #define SOCKET_ETIMEDOUT (-pdFREERTOS_ERRNO_ETIMEDOUT) #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR #define SOCKET_EINTR FREERTOS_SOCKET_ERROR #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR