Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion doc/dox_comments/header_files/wolfio.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,9 @@ void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
\param nxsocket a pointer to type NX_TCP_SOCKET that is set to the
nxTcpSocket member of the nxCtx structure.
\param waitoption a ULONG type that is set to the nxWait member of
the nxCtx structure.
the nxCtx structure. With NX_NO_WAIT, or any wait option that can expire,
the callbacks report WANT_READ/WANT_WRITE instead of a fatal error, so
the wolfSSL call can be retried.
Comment thread
embhorn marked this conversation as resolved.

_Example_
\code
Expand Down Expand Up @@ -496,6 +498,10 @@ void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket,
\param nxdip the destination NXD_ADDRESS (passed by value; IPv4 or IPv6).
\param nxport the destination UDP port number.
\param waitoption a ULONG NetX wait option (e.g. NX_WAIT_FOREVER or ticks).
With NX_NO_WAIT, or any wait option that can expire, NetX_SendTo reports
WANT_WRITE instead of a fatal error. A receive that expires reports
WANT_READ when the session is set non blocking, and a timeout otherwise so
that DTLS can retransmit.

_Example_
\code
Expand Down
91 changes: 70 additions & 21 deletions src/wolfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,46 @@ void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)

#ifdef HAVE_NETX

/* Map a failing NetX status onto a wolfSSL CBIO error code.
* Transient conditions must not be reported as fatal, otherwise a non
* blocking (or short wait option) setup cannot retry the operation. */
static int NetX_TranslateReturnCode(UINT status, int direction)
{
int ret;

switch (status) {
/* Receive queue empty, packet pool exhausted, peer receive window
* full or transmit queue at max depth. All clear on their own. */
case NX_NO_PACKET:
case NX_WINDOW_OVERFLOW:
case NX_TX_QUEUE_DEPTH:
WOLFSSL_MSG("\tWould block");
ret = (direction == SOCKET_SENDING) ? WOLFSSL_CBIO_ERR_WANT_WRITE
: WOLFSSL_CBIO_ERR_WANT_READ;
break;

/* A suspended wait was aborted, treated like an interrupted call. */
case NX_WAIT_ABORTED:
WOLFSSL_MSG("\tSocket interrupted");
ret = WOLFSSL_CBIO_ERR_ISR;
break;

/* NetX has no separate reset status, so a peer reset also lands
* here and is reported as a close. */
case NX_NOT_CONNECTED:
WOLFSSL_MSG("\tConnection closed");
ret = WOLFSSL_CBIO_ERR_CONN_CLOSE;
break;

default:
WOLFSSL_MSG_EX("\tGeneral error: %u", (unsigned int)status);
ret = WOLFSSL_CBIO_ERR_GENERAL;
break;
}

return ret;
}

/* The NetX receive callback for TLS
* return : bytes read, or error
*/
Expand All @@ -2830,7 +2870,7 @@ int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
nxCtx->nxWait);
if (status != NX_SUCCESS) {
WOLFSSL_MSG("NetX Recv receive error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_RECEIVING);
}
}

Expand Down Expand Up @@ -2885,21 +2925,21 @@ int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
nxCtx->nxWait);
if (status != NX_SUCCESS) {
WOLFSSL_MSG("NetX Send packet alloc error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_SENDING);
}

status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
if (status != NX_SUCCESS) {
nx_packet_release(packet);
WOLFSSL_MSG("NetX Send data append error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_SENDING);
}

status = nx_tcp_socket_send(nxCtx->nxTcpSocket, packet, nxCtx->nxWait);
if (status != NX_SUCCESS) {
nx_packet_release(packet);
WOLFSSL_MSG("NetX Send socket send error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_SENDING);
}

return sz;
Expand Down Expand Up @@ -2930,13 +2970,25 @@ static int NetX_PeerAddrEqual(const NXD_ADDRESS* left, const NXD_ADDRESS* right)
if (left->nxd_ip_version != right->nxd_ip_version)
return 0;

/* NXD_ADDRESS only carries the union member for the families the NetX Duo
* build was configured with, so guard each access. NX_DISABLE_IPV4 and
* NX_DISABLE_IPV6 are set in nx_user.h, FEATURE_NX_IPV6 is derived from
* NX_DISABLE_IPV6 by nx_api.h. */
#ifndef NX_DISABLE_IPV4
if (left->nxd_ip_version == NX_IP_VERSION_V4)
return left->nxd_ip_address.v4 == right->nxd_ip_address.v4;
#endif
#ifdef FEATURE_NX_IPV6
if (left->nxd_ip_version == NX_IP_VERSION_V6) {
return left->nxd_ip_address.v6[0] == right->nxd_ip_address.v6[0] &&
left->nxd_ip_address.v6[1] == right->nxd_ip_address.v6[1] &&
left->nxd_ip_address.v6[2] == right->nxd_ip_address.v6[2] &&
left->nxd_ip_address.v6[3] == right->nxd_ip_address.v6[3];
}
#endif

return left->nxd_ip_address.v6[0] == right->nxd_ip_address.v6[0] &&
left->nxd_ip_address.v6[1] == right->nxd_ip_address.v6[1] &&
left->nxd_ip_address.v6[2] == right->nxd_ip_address.v6[2] &&
left->nxd_ip_address.v6[3] == right->nxd_ip_address.v6[3];
/* Unknown or unsupported address family, do not treat it as our peer. */
return 0;
}

/* The NetX receive callback for DTLS
Expand Down Expand Up @@ -3019,7 +3071,7 @@ int NetX_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
: WOLFSSL_CBIO_ERR_TIMEOUT;
}
WOLFSSL_MSG("NetX Recv receive error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_RECEIVING);
}

status = nxd_udp_source_extract(nxCtx->nxPacket, &srcIp, &srcPort);
Expand Down Expand Up @@ -3137,29 +3189,26 @@ int NetX_SendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
nxCtx->nxWait);
if (status != NX_SUCCESS) {
WOLFSSL_MSG("NetX Send packet alloc error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_SENDING);
}

status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
if (status != NX_SUCCESS) {
nx_packet_release(packet);
WOLFSSL_MSG("NetX Send data append error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_SENDING);
}

if (nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V4) {
status = nx_udp_socket_send(nxCtx->nxUdpSocket, packet,
nxCtx->nxdIp.nxd_ip_address.v4,
(UINT)nxCtx->nxPort);
}
else {
status = nxd_udp_socket_send(nxCtx->nxUdpSocket, packet,
&nxCtx->nxdIp, (UINT)nxCtx->nxPort);
}
/* nxd_udp_socket_send() takes the NXD_ADDRESS itself and dispatches on
* nxd_ip_version, so it serves IPv4 and IPv6 without reaching into the
* nxd_ip_address union, which is only partly populated when the NetX Duo
* build disables a family. */
status = nxd_udp_socket_send(nxCtx->nxUdpSocket, packet,
&nxCtx->nxdIp, (UINT)nxCtx->nxPort);
if (status != NX_SUCCESS) {
nx_packet_release(packet);
WOLFSSL_MSG("NetX Send socket send error");
return WOLFSSL_CBIO_ERR_GENERAL;
return NetX_TranslateReturnCode(status, SOCKET_SENDING);
}

return sz;
Expand Down
10 changes: 7 additions & 3 deletions wolfssl/wolfio.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,14 @@
#define SOCKET_ECONNREFUSED SOCKET_ERROR
#define SOCKET_ECONNABORTED SOCKET_ERROR
#elif defined(HAVE_NETX)
#define SOCKET_EWOULDBLOCK NX_NOT_CONNECTED
#define SOCKET_EAGAIN NX_NOT_CONNECTED
/* NetX has no errno, these map onto the closest nx_api.h status codes.
* A send can also block as NX_WINDOW_OVERFLOW or NX_TX_QUEUE_DEPTH, so
* use the WANT_READ/WANT_WRITE the callbacks return rather than testing
* a NetX status against these. */
#define SOCKET_EWOULDBLOCK NX_NO_PACKET
#define SOCKET_EAGAIN NX_NO_PACKET
#define SOCKET_ECONNRESET NX_NOT_CONNECTED
#define SOCKET_EINTR NX_NOT_CONNECTED
#define SOCKET_EINTR NX_WAIT_ABORTED
#define SOCKET_EPIPE NX_NOT_CONNECTED
#define SOCKET_ECONNREFUSED NX_NOT_CONNECTED
#define SOCKET_ECONNABORTED NX_NOT_CONNECTED
Expand Down
Loading