Merge pull request #10408 from hmohide/master

Add UDP support to NetX sockets for DTLS sessions
This commit is contained in:
HAJA MOHIDEEN M
2026-07-09 00:54:31 +05:30
committed by GitHub
parent b4d51dbbda
commit c2b9cc55fb
7 changed files with 387 additions and 29 deletions
+1
View File
@@ -835,6 +835,7 @@ WOLFSSL_MONT_RED_CT
WOLFSSL_MP_COND_COPY
WOLFSSL_MP_INVMOD_CONSTANT_TIME
WOLFSSL_MULTICIRCULATE_ALTNAMELIST
WOLFSSL_NETX_DUO
WOLFSSL_NEW_PRIME_CHECK
WOLFSSL_NONBLOCK_OCSP
WOLFSSL_NOSHA3_384
+41 -7
View File
@@ -404,22 +404,22 @@ void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
/*!
\ingroup IO
\brief この関数は、WOLFSSL構造体内のnxCtx構造体のnxSocketおよびnxWaitメンバーを設定します。
\brief この関数は、WOLFSSL構造体内のnxCtx構造体のnxTcpSocketおよびnxWaitメンバーを設定します。
\return none 戻り値なし。
\param ssl wolfSSL_new()を使用して作成されたWOLFSSL構造体へのポインタ。
\param nxSocket nxCTX構造体のnxSocketメンバーに設定されるNX_TCP_SOCKET型へのポインタ。
\param waitOption nxCtx構造体のnxWaitメンバーに設定されるULONG型。
\param nxsocket nxCtx構造体のnxTcpSocketメンバーに設定されるNX_TCP_SOCKET型へのポインタ。
\param waitoption nxCtx構造体のnxWaitメンバーに設定されるULONG型。
_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
NX_TCP_SOCKET* nxSocket;
ULONG waitOption;
NX_TCP_SOCKET* nxsocket;
ULONG waitoption;
if(ssl != NULL || nxSocket != NULL || waitOption <= 0){
wolfSSL_SetIO_NetX(ssl, nxSocket, waitOption);
if(ssl != NULL || nxsocket != NULL || waitoption <= 0){
wolfSSL_SetIO_NetX(ssl, nxsocket, waitoption);
} else {
// 適切なパラメータを渡す必要があります。
}
@@ -432,6 +432,40 @@ void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket,
ULONG waitoption);
/*!
\ingroup IO
\brief この関数は、DTLSセッション用のNetX Duo UDPコンテキストを設定します。
UDPソケット、送信先IPアドレス(値渡し)、送信先ポート、待機オプションを
WOLFSSL nxCtx構造体に格納します。WOLFSSL_NETX_DUOの定義が必要です(ThreadX NetX Duo SDK)。
\return none 戻り値なし。
\param ssl wolfSSL_new()を使用して作成されたWOLFSSL構造体へのポインタ。
\param nxsocket 作成・バインド済みのNX_UDP_SOCKETへのポインタ。
\param nxdip 送信先NXD_ADDRESS(値渡し;IPv4またはIPv6)。
\param nxport 送信先UDPポート番号。
\param waitoption NetX待機オプション(例:NX_WAIT_FOREVERまたはティック数)。
_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
NX_UDP_SOCKET udpsocket;
NXD_ADDRESS peeraddr;
USHORT peerport = 4433;
ULONG wait = NX_WAIT_FOREVER;
// … udpsocketとpeeraddrを初期化 …
wolfSSL_SetIO_NetX_Dtls(ssl, &udpsocket, peeraddr, peerport, wait);
\endcode
\sa wolfSSL_SetIO_NetX
\sa NetX_SendTo
\sa NetX_ReceiveFrom
*/
void wolfSSL_SetIO_NetX_Dtls(WOLFSSL* ssl, NX_UDP_SOCKET* nxsocket,
NXD_ADDRESS nxdip, USHORT nxport,
ULONG waitoption);
/*!
\brief この関数は、WOLFSSL_CTX構造体のCBIOCookieメンバーのコールバックを設定します。
CallbackGenCookie型は関数ポインタで、次のシグネチャを持ちます:
+43 -8
View File
@@ -450,25 +450,25 @@ void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
/*!
\ingroup IO
\brief This function sets the nxSocket and nxWait members of the nxCtx
\brief This function sets the nxTcpSocket and nxWait members of the nxCtx
struct within the WOLFSSL structure.
\return none No returns.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param nxSocket a pointer to type NX_TCP_SOCKET that is set to the
nxSocket member of the nxCTX structure.
\param waitOption a ULONG type that is set to the nxWait member of
\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.
_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
NX_TCP_SOCKET* nxSocket;
ULONG waitOption;
NX_TCP_SOCKET* nxsocket;
ULONG waitoption;
if(ssl != NULL || nxSocket != NULL || waitOption <= 0){
wolfSSL_SetIO_NetX(ssl, nxSocket, waitOption);
if(ssl != NULL || nxsocket != NULL || waitoption <= 0){
wolfSSL_SetIO_NetX(ssl, nxsocket, waitoption);
} else {
// You need to pass in good parameters.
}
@@ -481,6 +481,41 @@ void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket,
ULONG waitoption);
/*!
\ingroup IO
\brief This function configures the NetX Duo UDP context for a DTLS
session. It stores the UDP socket, destination IP address (by value),
destination port, and wait option into the WOLFSSL nxCtx structure.
Requires WOLFSSL_NETX_DUO to be defined (ThreadX NetX Duo SDK).
\return none No returns.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param nxsocket a pointer to an NX_UDP_SOCKET already created and bound.
\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).
_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
NX_UDP_SOCKET udpsocket;
NXD_ADDRESS peeraddr;
USHORT peerport = 4433;
ULONG wait = NX_WAIT_FOREVER;
// … initialise udpsocket and peeraddr …
wolfSSL_SetIO_NetX_Dtls(ssl, &udpsocket, peeraddr, peerport, wait);
\endcode
\sa wolfSSL_SetIO_NetX
\sa NetX_SendTo
\sa NetX_ReceiveFrom
*/
void wolfSSL_SetIO_NetX_Dtls(WOLFSSL* ssl, NX_UDP_SOCKET* nxsocket,
NXD_ADDRESS nxdip, USHORT nxport,
ULONG waitoption);
/*!
\brief This function sets the callback for the CBIOCookie member of the
WOLFSSL_CTX structure. The CallbackGenCookie type is a function pointer
+11 -1
View File
@@ -2706,6 +2706,12 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
#ifdef HAVE_NETX
ctx->CBIORecv = NetX_Receive;
ctx->CBIOSend = NetX_Send;
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_NETX_DUO)
if (method->version.major == DTLS_MAJOR) {
ctx->CBIORecv = NetX_ReceiveFrom;
ctx->CBIOSend = NetX_SendTo;
}
#endif /* WOLFSSL_DTLS && WOLFSSL_NETX_DUO */
#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
ctx->CBIORecv = Mynewt_Receive;
ctx->CBIOSend = Mynewt_Send;
@@ -8110,9 +8116,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
if (wc_InitRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
return BAD_MUTEX_E;
#endif
#ifdef HAVE_NETX
ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */
ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */
#else
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; /* prevent invalid pointer access if not */
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; /* correctly set */
#endif
#else
#ifdef HAVE_NETX
ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */
+275 -11
View File
@@ -2577,7 +2577,7 @@ void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
#ifdef HAVE_NETX
/* The NetX receive callback
/* The NetX receive callback for TLS
* return : bytes read, or error
*/
int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
@@ -2590,13 +2590,13 @@ int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
(void)ssl;
if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
if (nxCtx == NULL || nxCtx->nxTcpSocket == NULL) {
WOLFSSL_MSG("NetX Recv NULL parameters");
return WOLFSSL_CBIO_ERR_GENERAL;
}
if (nxCtx->nxPacket == NULL) {
status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
status = nx_tcp_socket_receive(nxCtx->nxTcpSocket, &nxCtx->nxPacket,
nxCtx->nxWait);
if (status != NX_SUCCESS) {
WOLFSSL_MSG("NetX Recv receive error");
@@ -2633,7 +2633,7 @@ int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
}
/* The NetX send callback
/* The NetX send callback for TLS
* return : bytes sent, or error
*/
int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
@@ -2645,12 +2645,12 @@ int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
(void)ssl;
if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
if (nxCtx == NULL || nxCtx->nxTcpSocket == NULL) {
WOLFSSL_MSG("NetX Send NULL parameters");
return WOLFSSL_CBIO_ERR_GENERAL;
}
pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
pool = nxCtx->nxTcpSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
nxCtx->nxWait);
if (status != NX_SUCCESS) {
@@ -2665,7 +2665,7 @@ int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
return WOLFSSL_CBIO_ERR_GENERAL;
}
status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
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");
@@ -2675,16 +2675,280 @@ int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
return sz;
}
/* like set_fd, but for default NetX context */
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, ULONG waitoption)
{
if (ssl) {
ssl->nxCtx.nxSocket = nxSocket;
ssl->nxCtx.nxWait = waitOption;
ssl->nxCtx.nxTcpSocket = nxsocket;
ssl->nxCtx.nxWait = waitoption;
}
}
/* WOLFSSL_NETX_DUO: requires ThreadX NetX Duo (NXD_ADDRESS, nxd_udp_socket_send) */
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_NETX_DUO)
static void NetX_ResetPacket(NetX_Ctx* nxCtx)
{
if (nxCtx->nxPacket != NULL) {
nx_packet_release(nxCtx->nxPacket);
nxCtx->nxPacket = NULL;
}
nxCtx->nxOffset = 0;
}
static int NetX_PeerAddrEqual(const NXD_ADDRESS* left, const NXD_ADDRESS* right)
{
if (left->nxd_ip_version != right->nxd_ip_version)
return 0;
if (left->nxd_ip_version == NX_IP_VERSION_V4)
return left->nxd_ip_address.v4 == right->nxd_ip_address.v4;
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];
}
/* The NetX receive callback for DTLS
* return : bytes read, or error
*/
int NetX_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
NXD_ADDRESS srcIp;
ULONG left;
ULONG total;
ULONG copied = 0;
UINT srcPort;
UINT status;
ULONG waitOption;
int dtls_timeout;
int usingNonblock;
byte doDtlsTimeout;
word32 invalidPeerPackets = 0;
#if defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
const word32 maxInvalidPeerPackets = DTLS_RECEIVEFROM_MAX_INVALID_PEER;
#else
const word32 maxInvalidPeerPackets = 10;
#endif
if (nxCtx == NULL || nxCtx->nxUdpSocket == NULL) {
WOLFSSL_MSG("NetX Recv NULL parameters");
return WOLFSSL_CBIO_ERR_GENERAL;
}
if (sz < 0)
return WOLFSSL_CBIO_ERR_GENERAL;
usingNonblock = wolfSSL_dtls_get_using_nonblock(ssl);
/* Don't use ssl->options.handShakeDone since it is true even if
* we are in the process of renegotiation. */
doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
doDtlsTimeout =
doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
(ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
}
#endif /* WOLFSSL_DTLS13 */
do {
if (nxCtx->nxPacket == NULL) {
/* Compute wait ticks from the DTLS retransmit timeout while a
* handshake/RTX timer is active, otherwise honor nxWait. */
if (!usingNonblock) {
dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
if (!doDtlsTimeout)
dtls_timeout = 0;
#ifdef WOLFSSL_DTLS13
if (dtls_timeout > 0 && wolfSSL_dtls13_use_quick_timeout(ssl) &&
IsAtLeastTLSv1_3(ssl->version)) {
if (dtls_timeout > 4)
dtls_timeout /= 4;
else
dtls_timeout = 1;
}
#endif /* WOLFSSL_DTLS13 */
waitOption = (dtls_timeout > 0)
? (ULONG)dtls_timeout * NX_IP_PERIODIC_RATE
: nxCtx->nxWait;
}
else {
waitOption = NX_NO_WAIT; /* non-blocking */
}
status = nx_udp_socket_receive(nxCtx->nxUdpSocket, &nxCtx->nxPacket,
waitOption);
if (status != NX_SUCCESS) {
if (status == NX_NO_PACKET) {
/* Normal receive timeout - allow DTLS to retransmit */
WOLFSSL_MSG("NetX Recv timeout");
return usingNonblock
? WOLFSSL_CBIO_ERR_WANT_READ
: WOLFSSL_CBIO_ERR_TIMEOUT;
}
WOLFSSL_MSG("NetX Recv receive error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
status = nxd_udp_source_extract(nxCtx->nxPacket, &srcIp, &srcPort);
if (status != NX_SUCCESS) {
NetX_ResetPacket(nxCtx);
WOLFSSL_MSG("NetX Recv source extract error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
if (nxCtx->nxPort != 0 &&
(nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V4 ||
nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V6)) {
if ((USHORT)srcPort != nxCtx->nxPort ||
!NetX_PeerAddrEqual(&srcIp, &nxCtx->nxdIp)) {
WOLFSSL_MSG("NetX Recv ignored packet from invalid peer");
NetX_ResetPacket(nxCtx);
/* Intentional: bound discard only during handshake/RTX
* window (doDtlsTimeout). Post-handshake, spoofed-source
* packets loop until a valid one arrives. This matches
* the EmbedReceiveFrom behavior. */
if (doDtlsTimeout) {
invalidPeerPackets++;
if (invalidPeerPackets > maxInvalidPeerPackets) {
return usingNonblock
? WOLFSSL_CBIO_ERR_WANT_READ
: WOLFSSL_CBIO_ERR_TIMEOUT;
}
}
continue;
}
}
else {
/* No peer preset: accept first datagram and lock onto source. */
nxCtx->nxdIp = srcIp;
nxCtx->nxPort = (USHORT)srcPort;
}
}
status = nx_packet_length_get(nxCtx->nxPacket, &total);
if (status != NX_SUCCESS) {
NetX_ResetPacket(nxCtx);
WOLFSSL_MSG("NetX Recv length get error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
if (total == 0) {
WOLFSSL_MSG("Ignoring 0-length datagram");
NetX_ResetPacket(nxCtx);
/* Intentional: same discard-bound semantics as invalid-peer
* handling above and EmbedReceiveFrom: only bounded during
* handshake, loops post-handshake until a valid datagram
* arrives. */
if (doDtlsTimeout) {
invalidPeerPackets++;
if (invalidPeerPackets > maxInvalidPeerPackets) {
return usingNonblock
? WOLFSSL_CBIO_ERR_WANT_READ
: WOLFSSL_CBIO_ERR_TIMEOUT;
}
}
continue;
}
if (nxCtx->nxOffset > total) {
NetX_ResetPacket(nxCtx);
WOLFSSL_MSG("NetX Recv invalid packet offset");
return WOLFSSL_CBIO_ERR_GENERAL;
}
left = total - nxCtx->nxOffset;
status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
buf, sz, &copied);
if (status != NX_SUCCESS) {
NetX_ResetPacket(nxCtx);
WOLFSSL_MSG("NetX Recv data extract offset error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
/* DTLS datagram semantics: always release the full datagram after one
* read. If the caller's buffer (sz) is smaller than the datagram,
* the excess bytes are discarded here, matching EmbedReceiveFrom /
* recvfrom behavior. Partial-datagram retention would re-introduce
* TCP stream semantics and could mis-frame DTLS records. */
if (copied < left) {
WOLFSSL_MSG("NetX Recv datagram truncated, discarding remainder");
}
NetX_ResetPacket(nxCtx);
return (int)copied;
} while (1);
}
/* The NetX send callback for DTLS
* return : bytes sent, or error
*/
int NetX_SendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
{
NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
NX_PACKET* packet;
NX_PACKET_POOL* pool; /* shorthand */
UINT status;
(void)ssl;
if (nxCtx == NULL || nxCtx->nxUdpSocket == NULL) {
WOLFSSL_MSG("NetX Send NULL parameters");
return WOLFSSL_CBIO_ERR_GENERAL;
}
if (sz < 0)
return WOLFSSL_CBIO_ERR_GENERAL;
pool = nxCtx->nxUdpSocket->nx_udp_socket_ip_ptr->nx_ip_default_packet_pool;
status = nx_packet_allocate(pool, &packet, NX_UDP_PACKET,
nxCtx->nxWait);
if (status != NX_SUCCESS) {
WOLFSSL_MSG("NetX Send packet alloc error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
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;
}
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);
}
if (status != NX_SUCCESS) {
nx_packet_release(packet);
WOLFSSL_MSG("NetX Send socket send error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
return sz;
}
/* like set_fd, but for default NetX Duo UDP context */
void wolfSSL_SetIO_NetX_Dtls(WOLFSSL* ssl, NX_UDP_SOCKET* nxsocket,
NXD_ADDRESS nxdip, USHORT nxport,
ULONG waitoption)
{
if (ssl) {
ssl->nxCtx.nxUdpSocket = nxsocket;
ssl->nxCtx.nxdIp = nxdip;
ssl->nxCtx.nxPort = nxport;
ssl->nxCtx.nxWait = waitoption;
}
}
#endif /* WOLFSSL_DTLS && WOLFSSL_NETX_DUO */
#endif /* HAVE_NETX */
+7 -1
View File
@@ -5793,10 +5793,16 @@ typedef struct DtlsMsg {
/* NETX I/O Callback default */
typedef struct NetX_Ctx {
NX_TCP_SOCKET* nxSocket; /* send/recv socket handle */
NX_TCP_SOCKET* nxTcpSocket; /* send/recv tcp socket handle */
NX_PACKET* nxPacket; /* incoming packet handle for short reads */
ULONG nxOffset; /* offset already read from nxPacket */
ULONG nxWait; /* wait option flag */
/* WOLFSSL_NETX_DUO: requires ThreadX NetX Duo (NXD_ADDRESS, nxd_udp_socket_send) */
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_NETX_DUO)
NX_UDP_SOCKET* nxUdpSocket; /* send/recv udp socket handle */
NXD_ADDRESS nxdIp; /* destination IP address for udp send */
USHORT nxPort; /* destination port for udp send */
#endif /* WOLFSSL_DTLS && WOLFSSL_NETX_DUO */
} NetX_Ctx;
#endif
+9 -1
View File
@@ -791,9 +791,17 @@ WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
#ifdef HAVE_NETX
WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx);
WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx);
WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket,
ULONG waitoption);
/* WOLFSSL_NETX_DUO: requires ThreadX NetX Duo (NXD_ADDRESS, nxd_udp_socket_send) */
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_NETX_DUO)
WOLFSSL_LOCAL int NetX_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx);
WOLFSSL_LOCAL int NetX_SendTo(WOLFSSL *ssl, char *buf, int sz, void *ctx);
WOLFSSL_API void wolfSSL_SetIO_NetX_Dtls(WOLFSSL* ssl, NX_UDP_SOCKET* nxsocket,
NXD_ADDRESS nxdip,
USHORT nxport,
ULONG waitoption);
#endif /* WOLFSSL_DTLS && WOLFSSL_NETX_DUO */
#endif /* HAVE_NETX */
#ifdef MICRIUM