zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/README.txt b/ap/lib/libwolfssl/install/share/doc/wolfssl/README.txt
new file mode 100644
index 0000000..efaed1b
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/README.txt
@@ -0,0 +1,8 @@
+The wolfSSL manual is available at:
+http://www.wolfssl.com/documentation/wolfSSL-Manual.pdf
+
+The wolfSSL API guide is available at:
+https://www.wolfssl.com/doxygen/wolfssl_API.html
+
+The wolfCrypt API guide is available at:
+https://www.wolfssl.com/doxygen/wolfcrypt_API.html
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/client.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/client.c
new file mode 100644
index 0000000..6772c82
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/client.c
@@ -0,0 +1,4018 @@
+/* client.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+        #include <config.h>
+#endif
+
+#ifndef WOLFSSL_USER_SETTINGS
+        #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+
+#include <wolfssl/ssl.h>
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+#include <wolfsentry/wolfsentry.h>
+#if !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
+static const char *wolfsentry_config_path = NULL;
+#endif
+#endif /* WOLFSSL_WOLFSENTRY_HOOKS */
+
+#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+        #include <stdio.h>
+        #include <string.h>
+        #include "rl_fs.h"
+        #include "rl_net.h"
+#endif
+
+#include <wolfssl/test.h>
+
+#include <examples/client/client.h>
+#include <wolfssl/error-ssl.h>
+
+#ifndef NO_WOLFSSL_CLIENT
+
+#ifdef NO_FILESYSTEM
+#ifdef NO_RSA
+#error currently the example only tries to load in a RSA buffer
+#endif
+#undef USE_CERT_BUFFERS_256
+#define USE_CERT_BUFFERS_256
+#undef USE_CERT_BUFFERS_2048
+#define USE_CERT_BUFFERS_2048
+#include <wolfssl/certs_test.h>
+#endif
+
+#ifdef USE_FAST_MATH
+    /* included to inspect the size of FP_MAX_BITS */
+    /* need integer.h header to make sure right math version used */
+    #include <wolfssl/wolfcrypt/integer.h>
+#endif
+#ifdef HAVE_ECC
+    #include <wolfssl/wolfcrypt/ecc.h>
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    static int devId = INVALID_DEVID;
+#endif
+
+#define DEFAULT_TIMEOUT_SEC 2
+#ifndef MAX_NON_BLOCK_SEC
+#define MAX_NON_BLOCK_SEC   10
+#endif
+
+#define OCSP_STAPLING 1
+#define OCSP_STAPLINGV2 2
+#define OCSP_STAPLINGV2_MULTI 3
+#define OCSP_STAPLING_OPT_MAX OCSP_STAPLINGV2_MULTI
+
+#ifdef WOLFSSL_ALT_TEST_STRINGS
+    #define TEST_STR_TERM "\n"
+#else
+    #define TEST_STR_TERM
+#endif
+
+static const char kHelloMsg[] = "hello wolfssl!" TEST_STR_TERM;
+#ifndef NO_SESSION_CACHE
+static const char kResumeMsg[] = "resuming wolfssl!" TEST_STR_TERM;
+#endif
+
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_EARLY_DATA)
+    static const char kEarlyMsg[] = "A drop of info" TEST_STR_TERM;
+#endif
+static const char kHttpGetMsg[] = "GET /index.html HTTP/1.0\r\n\r\n";
+
+/* Write needs to be largest of the above strings (29) */
+#define CLI_MSG_SZ      32
+/* Read needs to be at least sizeof server.c `webServerMsg` (226) */
+#define CLI_REPLY_SZ    256
+
+#if defined(XSLEEP_US) && defined(NO_MAIN_DRIVER)
+    /* This is to force the server's thread to get a chance to
+     * execute before continuing the resume in non-blocking
+     * DTLS test cases. */
+    #define TEST_DELAY() XSLEEP_US(10000)
+#else
+    #define TEST_DELAY() XSLEEP_MS(1000)
+#endif
+
+/* Note on using port 0: the client standalone example doesn't utilize the
+ * port 0 port sharing; that is used by (1) the server in external control
+ * test mode and (2) the testsuite which uses this code and sets up the correct
+ * port numbers when the internal thread using the server code using port 0. */
+
+static int lng_index = 0;
+#ifdef WOLFSSL_CALLBACKS
+    WOLFSSL_TIMEVAL timeoutConnect;
+    static int handShakeCB(HandShakeInfo* info)
+    {
+        (void)info;
+        return 0;
+    }
+
+    static int timeoutCB(TimeoutInfo* info)
+    {
+        (void)info;
+        return 0;
+    }
+
+#endif
+
+#ifdef HAVE_SESSION_TICKET
+    static int sessionTicketCB(WOLFSSL* ssl,
+                        const unsigned char* ticket, int ticketSz,
+                        void* ctx)
+    {
+        (void)ssl;
+        (void)ticket;
+        printf("Session Ticket CB: ticketSz = %d, ctx = %s\n",
+               ticketSz, (char*)ctx);
+        return 0;
+    }
+#endif
+
+static int NonBlockingSSL_Connect(WOLFSSL* ssl)
+{
+    int ret;
+    int error;
+    SOCKET_T sockfd;
+    int select_ret = 0;
+    int elapsedSec = 0;
+
+#ifndef WOLFSSL_CALLBACKS
+    ret = wolfSSL_connect(ssl);
+#else
+    ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeoutConnect);
+#endif
+    error = wolfSSL_get_error(ssl, 0);
+    sockfd = (SOCKET_T)wolfSSL_get_fd(ssl);
+
+    while (ret != WOLFSSL_SUCCESS &&
+        (error == WOLFSSL_ERROR_WANT_READ || error == WOLFSSL_ERROR_WANT_WRITE
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            || error == WC_PENDING_E
+        #endif
+        #ifdef WOLFSSL_NONBLOCK_OCSP
+            || error == OCSP_WANT_READ
+        #endif
+    )) {
+        int currTimeout = 1;
+
+        if (error == WOLFSSL_ERROR_WANT_READ)
+            printf("... client would read block\n");
+        else if (error == WOLFSSL_ERROR_WANT_WRITE)
+            printf("... client would write block\n");
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+        if (error == WC_PENDING_E) {
+            ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            if (ret < 0) break;
+        }
+        else
+#endif
+        {
+            if (error == WOLFSSL_ERROR_WANT_WRITE) {
+                select_ret = tcp_select_tx(sockfd, currTimeout);
+
+            }
+            else
+            {
+            #ifdef WOLFSSL_DTLS
+                currTimeout = wolfSSL_dtls_get_current_timeout(ssl);
+            #endif
+                select_ret = tcp_select(sockfd, currTimeout);
+            }
+        }
+
+        if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_SEND_READY)
+            || (select_ret == TEST_ERROR_READY)
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            || error == WC_PENDING_E
+        #endif
+        ) {
+        #ifndef WOLFSSL_CALLBACKS
+            ret = wolfSSL_connect(ssl);
+        #else
+            ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB,
+                                                                timeoutConnect);
+        #endif
+            error = wolfSSL_get_error(ssl, 0);
+            elapsedSec = 0; /* reset elapsed */
+        }
+        else if (select_ret == TEST_TIMEOUT && !wolfSSL_dtls(ssl)) {
+            error = WOLFSSL_ERROR_WANT_READ;
+
+            elapsedSec += currTimeout;
+            if (elapsedSec > MAX_NON_BLOCK_SEC) {
+                printf("Nonblocking connect timeout\n");
+                error = WOLFSSL_FATAL_ERROR;
+            }
+        }
+#ifdef WOLFSSL_DTLS
+        else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) &&
+                                        wolfSSL_dtls_got_timeout(ssl) >= 0) {
+            error = WOLFSSL_ERROR_WANT_READ;
+        }
+#endif
+        else {
+            error = WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return ret;
+}
+
+
+static void ShowCiphers(void)
+{
+    static char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE];
+
+    int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
+
+    if (ret == WOLFSSL_SUCCESS)
+        printf("%s\n", ciphers);
+}
+
+/* Shows which versions are valid */
+static void ShowVersions(void)
+{
+#ifndef NO_OLD_TLS
+    #ifdef WOLFSSL_ALLOW_SSLV3
+        printf("0:");
+    #endif
+    #ifdef WOLFSSL_ALLOW_TLSV10
+        printf("1:");
+    #endif
+    printf("2:");
+#endif /* NO_OLD_TLS */
+#ifndef WOLFSSL_NO_TLS12
+    printf("3:");
+#endif
+#ifdef WOLFSSL_TLS13
+    printf("4:");
+#endif
+    printf("d(downgrade):");
+#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+    printf("e(either):");
+#endif
+    printf("\n");
+}
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+#define MAX_GROUP_NUMBER 4
+static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
+                        int useX448, int setGroups)
+{
+    int ret;
+    int groups[MAX_GROUP_NUMBER] = {0};
+    int count = 0;
+
+    (void)useX25519;
+    (void)useX448;
+
+    WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+    if (onlyKeyShare == 0 || onlyKeyShare == 2) {
+        if (useX25519) {
+    #ifdef HAVE_CURVE25519
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_X25519;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve x25519");
+            } while (ret == WC_PENDING_E);
+    #endif
+        }
+        else if (useX448) {
+    #ifdef HAVE_CURVE448
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_X448;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve x448");
+            } while (ret == WC_PENDING_E);
+    #endif
+        }
+        else {
+    #ifdef HAVE_ECC
+        #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_SECP256R1;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve secp256r1");
+            } while (ret == WC_PENDING_E);
+        #endif
+    #endif
+        }
+    }
+    if (onlyKeyShare == 0 || onlyKeyShare == 1) {
+    #ifdef HAVE_FFDHE_2048
+        do {
+            ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048);
+            if (ret == WOLFSSL_SUCCESS)
+                groups[count++] = WOLFSSL_FFDHE_2048;
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            else if (ret == WC_PENDING_E)
+                wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+        #endif
+            else
+                err_sys("unable to use DH 2048-bit parameters");
+        } while (ret == WC_PENDING_E);
+    #endif
+    }
+    if (count >= MAX_GROUP_NUMBER)
+        err_sys("example group array size error");
+    if (setGroups && count > 0) {
+        if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS)
+            err_sys("unable to set groups");
+    }
+    WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+}
+#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */
+
+#ifdef WOLFSSL_EARLY_DATA
+static void EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg,
+                      int msgSz, char* buffer)
+{
+    int err;
+    int ret;
+
+    do {
+        err = 0; /* reset error */
+        ret = wolfSSL_write_early_data(ssl, msg, msgSz, &msgSz);
+        if (ret <= 0) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+    if (ret != msgSz) {
+        printf("SSL_write_early_data msg error %d, %s\n", err,
+                                         wolfSSL_ERR_error_string(err, buffer));
+        wolfSSL_free(ssl); ssl = NULL;
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("SSL_write_early_data failed");
+    }
+    do {
+        err = 0; /* reset error */
+        ret = wolfSSL_write_early_data(ssl, msg, msgSz, &msgSz);
+        if (ret <= 0) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+    if (ret != msgSz) {
+        printf("SSL_write_early_data msg error %d, %s\n", err,
+                                         wolfSSL_ERR_error_string(err, buffer));
+        wolfSSL_free(ssl);
+        wolfSSL_CTX_free(ctx);
+        err_sys("SSL_write_early_data failed");
+    }
+}
+#endif
+
+/* Measures average time to create, connect and disconnect a connection (TPS).
+Benchmark = number of connections. */
+static const char* client_bench_conmsg[][5] = {
+    /* English */
+    {
+        "wolfSSL_resume  avg took:", "milliseconds\n",
+        "wolfSSL_connect avg took:", "milliseconds\n",
+        NULL
+    },
+    #ifndef NO_MULTIBYTE_PRINT
+    /* Japanese */
+    {
+        "wolfSSL_resume  平均時間:", "ミリ秒\n",
+        "wolfSSL_connect 平均時間:", "ミリ秒\n",
+    }
+    #endif
+};
+
+static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
+    int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519,
+    int useX448, int helloRetry, int onlyKeyShare, int version, int earlyData)
+{
+    /* time passed in number of connects give average */
+    int times = benchmark, skip = times * 0.1;
+    int loops = resumeSession ? 2 : 1;
+    int i = 0, err, ret;
+#ifndef NO_SESSION_CACHE
+    WOLFSSL_SESSION* benchSession = NULL;
+#endif
+#ifdef WOLFSSL_TLS13
+    byte reply[CLI_REPLY_SZ];
+#endif
+    const char** words = client_bench_conmsg[lng_index];
+
+    (void)resumeSession;
+    (void)useX25519;
+    (void)useX448;
+    (void)helloRetry;
+    (void)onlyKeyShare;
+    (void)version;
+    (void)earlyData;
+
+    while (loops--) {
+    #ifndef NO_SESSION_CACHE
+        int benchResume = resumeSession && loops == 0;
+    #endif
+        double start = current_time(1), avg;
+
+        for (i = 0; i < times; i++) {
+            SOCKET_T sockfd;
+            WOLFSSL* ssl;
+
+            if (i == skip)
+                start = current_time(1);
+
+            ssl = wolfSSL_new(ctx);
+            if (ssl == NULL)
+                err_sys("unable to get SSL object");
+
+        #ifndef NO_SESSION_CACHE
+            if (benchResume)
+                wolfSSL_set_session(ssl, benchSession);
+        #endif
+        #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+            else if (version >= 4) {
+                if (!helloRetry)
+                    SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1);
+                else
+                    wolfSSL_NoKeyShares(ssl);
+            }
+        #endif
+
+            tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
+
+            if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
+                err_sys("error in setting fd");
+            }
+
+    #if defined(WOLFSSL_TLS13) && !defined(NO_SESSION_CACHE) && \
+                                                     defined(WOLFSSL_EARLY_DATA)
+            if (version >= 4 && benchResume && earlyData) {
+                char buffer[WOLFSSL_MAX_ERROR_SZ];
+                EarlyData(ctx, ssl, kEarlyMsg, sizeof(kEarlyMsg)-1, buffer);
+            }
+    #endif
+            do {
+                err = 0; /* reset error */
+                ret = wolfSSL_connect(ssl);
+#ifdef WOLFSSL_EARLY_DATA
+                EarlyDataStatus(ssl);
+#endif
+                if (ret != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+            if (ret != WOLFSSL_SUCCESS) {
+                err_sys("SSL_connect failed");
+            }
+
+    #ifdef WOLFSSL_TLS13
+        #ifndef NO_SESSION_CACHE
+            if (version >= 4 && resumeSession && !benchResume)
+        #else
+            if (version >= 4 && resumeSession)
+        #endif
+            {
+                /* no null term */
+                if (wolfSSL_write(ssl, kHttpGetMsg, sizeof(kHttpGetMsg)-1) <= 0)
+                    err_sys("SSL_write failed");
+
+                if (wolfSSL_read(ssl, reply, sizeof(reply)-1) <= 0)
+                    err_sys("SSL_read failed");
+            }
+    #endif
+
+
+            wolfSSL_shutdown(ssl);
+    #ifndef NO_SESSION_CACHE
+            if (i == (times-1) && resumeSession) {
+                benchSession = wolfSSL_get_session(ssl);
+            }
+    #endif
+            wolfSSL_free(ssl); ssl = NULL;
+            CloseSocket(sockfd);
+        }
+        avg = current_time(0) - start;
+        avg /= (times - skip);
+        avg *= 1000;   /* milliseconds */
+    #ifndef NO_SESSION_CACHE
+        if (benchResume)
+            printf("%s %8.3f %s\n", words[0],avg, words[1]);
+        else
+    #endif
+            printf("%s %8.3f %s\n", words[2],avg, words[3]);
+
+        WOLFSSL_TIME(times);
+    }
+
+    return EXIT_SUCCESS;
+}
+
+/* Measures throughput in mbps. Throughput = number of bytes */
+static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
+    int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519,
+    int useX448, int exitWithRet, int version, int onlyKeyShare)
+{
+    double start, conn_time = 0, tx_time = 0, rx_time = 0;
+    SOCKET_T sockfd;
+    WOLFSSL* ssl;
+    int ret = 0, err = 0;
+
+    start = current_time(1);
+    ssl = wolfSSL_new(ctx);
+    if (ssl == NULL)
+        err_sys("unable to get SSL object");
+
+    tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
+    if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
+        err_sys("error in setting fd");
+    }
+
+    (void)useX25519;
+    (void)useX448;
+    (void)version;
+    (void)onlyKeyShare;
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+    if (version >= 4) {
+        SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1);
+    }
+#endif
+
+    do {
+        err = 0; /* reset error */
+        ret = wolfSSL_connect(ssl);
+        if (ret != WOLFSSL_SUCCESS) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+    if (ret == WOLFSSL_SUCCESS) {
+        /* Perform throughput test */
+        char *tx_buffer, *rx_buffer;
+
+        /* Record connection time */
+        conn_time = current_time(0) - start;
+
+        /* Allocate TX/RX buffers */
+        tx_buffer = (char*)XMALLOC(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        rx_buffer = (char*)XMALLOC(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (tx_buffer && rx_buffer) {
+            WC_RNG rng;
+
+            /* Startup the RNG */
+        #if !defined(HAVE_FIPS) && defined(WOLFSSL_ASYNC_CRYPT)
+            ret = wc_InitRng_ex(&rng, NULL, devId);
+        #else
+            ret = wc_InitRng(&rng);
+        #endif
+            if (ret == 0) {
+                size_t xfer_bytes;
+
+                /* Generate random data to send */
+                ret = wc_RNG_GenerateBlock(&rng, (byte*)tx_buffer, block);
+                wc_FreeRng(&rng);
+                if(ret != 0) {
+                    err_sys("wc_RNG_GenerateBlock failed");
+                }
+
+                /* Perform TX and RX of bytes */
+                xfer_bytes = 0;
+                while (throughput > xfer_bytes) {
+                    int len, rx_pos, select_ret;
+
+                    /* Determine packet size */
+                    len = min(block, (int)(throughput - xfer_bytes));
+
+                    /* Perform TX */
+                    start = current_time(1);
+                    do {
+                        err = 0; /* reset error */
+                        ret = wolfSSL_write(ssl, tx_buffer, len);
+                        if (ret <= 0) {
+                            err = wolfSSL_get_error(ssl, 0);
+                        #ifdef WOLFSSL_ASYNC_CRYPT
+                            if (err == WC_PENDING_E) {
+                                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                                if (ret < 0) break;
+                            }
+                        #endif
+                        }
+                    } while (err == WC_PENDING_E);
+                    if (ret != len) {
+                        printf("SSL_write bench error %d!\n", err);
+                        if (!exitWithRet)
+                            err_sys("SSL_write failed");
+                        goto doExit;
+                    }
+                    tx_time += current_time(0) - start;
+
+                    /* Perform RX */
+                    select_ret = tcp_select(sockfd, DEFAULT_TIMEOUT_SEC);
+                    if (select_ret == TEST_RECV_READY) {
+                        start = current_time(1);
+                        rx_pos = 0;
+                        while (rx_pos < len) {
+                            ret = wolfSSL_read(ssl, &rx_buffer[rx_pos],
+                                                                len - rx_pos);
+                            if (ret <= 0) {
+                                err = wolfSSL_get_error(ssl, 0);
+                            #ifdef WOLFSSL_ASYNC_CRYPT
+                                if (err == WC_PENDING_E) {
+                                    ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                                    if (ret < 0) break;
+                                }
+                                else
+                            #endif
+                                if (err != WOLFSSL_ERROR_WANT_READ) {
+                                    printf("SSL_read bench error %d\n", err);
+                                    err_sys("SSL_read failed");
+                                }
+                            }
+                            else {
+                                rx_pos += ret;
+                            }
+                        }
+                        rx_time += current_time(0) - start;
+                    }
+
+                    /* Compare TX and RX buffers */
+                    if (XMEMCMP(tx_buffer, rx_buffer, len) != 0) {
+                        free(tx_buffer);
+                        tx_buffer = NULL;
+                        free(rx_buffer);
+                        rx_buffer = NULL;
+                        err_sys("Compare TX and RX buffers failed");
+                    }
+
+                    /* Update overall position */
+                    xfer_bytes += len;
+                }
+            }
+            else {
+                err_sys("wc_InitRng failed");
+            }
+            (void)rng; /* for WC_NO_RNG case */
+        }
+        else {
+            err_sys("Client buffer malloc failed");
+        }
+doExit:
+        if (tx_buffer) XFREE(tx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (rx_buffer) XFREE(rx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+    else {
+        err_sys("wolfSSL_connect failed");
+    }
+
+    wolfSSL_shutdown(ssl);
+    wolfSSL_free(ssl); ssl = NULL;
+    CloseSocket(sockfd);
+
+    if (exitWithRet)
+        return err;
+
+    printf(
+#if !defined(__MINGW32__)
+        "wolfSSL Client Benchmark %zu bytes\n"
+#else
+        "wolfSSL Client Benchmark %d bytes\n"
+#endif
+        "\tConnect %8.3f ms\n"
+        "\tTX      %8.3f ms (%8.3f MBps)\n"
+        "\tRX      %8.3f ms (%8.3f MBps)\n",
+#if !defined(__MINGW32__)
+        throughput,
+#else
+        (int)throughput,
+#endif
+        conn_time * 1000,
+        tx_time * 1000, throughput / tx_time / 1024 / 1024,
+        rx_time * 1000, throughput / rx_time / 1024 / 1024
+    );
+
+    return EXIT_SUCCESS;
+}
+
+const char* starttlsCmd[6] = {
+    "220",
+    "EHLO mail.example.com\r\n",
+    "250",
+    "STARTTLS\r\n",
+    "220",
+    "QUIT\r\n",
+};
+
+/* Initiates the STARTTLS command sequence over TCP */
+static int StartTLS_Init(SOCKET_T* sockfd)
+{
+    char tmpBuf[256];
+
+    if (sockfd == NULL)
+        return BAD_FUNC_ARG;
+
+    /* S: 220 <host> SMTP service ready */
+    XMEMSET(tmpBuf, 0, sizeof(tmpBuf));
+    if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0)
+        err_sys("failed to read STARTTLS command\n");
+
+    if (!XSTRNCMP(tmpBuf, starttlsCmd[0], XSTRLEN(starttlsCmd[0]))) {
+        printf("%s\n", tmpBuf);
+    } else {
+        err_sys("incorrect STARTTLS command received");
+    }
+
+    /* C: EHLO mail.example.com */
+    if (send(*sockfd, starttlsCmd[1], (int)XSTRLEN(starttlsCmd[1]), 0) !=
+              (int)XSTRLEN(starttlsCmd[1]))
+        err_sys("failed to send STARTTLS EHLO command\n");
+
+    /* S: 250 <host> offers a warm hug of welcome */
+    XMEMSET(tmpBuf, 0, sizeof(tmpBuf));
+    if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0)
+        err_sys("failed to read STARTTLS command\n");
+
+    if (!XSTRNCMP(tmpBuf, starttlsCmd[2], XSTRLEN(starttlsCmd[2]))) {
+        printf("%s\n", tmpBuf);
+    } else {
+        err_sys("incorrect STARTTLS command received");
+    }
+
+    /* C: STARTTLS */
+    if (send(*sockfd, starttlsCmd[3], (int)XSTRLEN(starttlsCmd[3]), 0) !=
+              (int)XSTRLEN(starttlsCmd[3])) {
+        err_sys("failed to send STARTTLS command\n");
+    }
+
+    /* S: 220 Go ahead */
+    XMEMSET(tmpBuf, 0, sizeof(tmpBuf));
+    if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0)
+        err_sys("failed to read STARTTLS command\n");
+    tmpBuf[sizeof(tmpBuf)-1] = '\0';
+    if (!XSTRNCMP(tmpBuf, starttlsCmd[4], XSTRLEN(starttlsCmd[4]))) {
+        printf("%s\n", tmpBuf);
+    } else {
+        err_sys("incorrect STARTTLS command received, expected 220");
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+/* Closes down the SMTP connection */
+static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown)
+{
+    int ret, err = 0;
+    char tmpBuf[256];
+
+    if (ssl == NULL)
+        return BAD_FUNC_ARG;
+
+    printf("\nwolfSSL client shutting down SMTP connection\n");
+
+    XMEMSET(tmpBuf, 0, sizeof(tmpBuf));
+
+    /* C: QUIT */
+    do {
+        ret = wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5]));
+        if (ret < 0) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+    if (ret != (int)XSTRLEN(starttlsCmd[5])) {
+        err_sys("failed to send SMTP QUIT command\n");
+    }
+
+    /* S: 221 2.0.0 Service closing transmission channel */
+    do {
+        ret = wolfSSL_read(ssl, tmpBuf, sizeof(tmpBuf)-1);
+        if (ret < 0) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+    if (ret < 0) {
+        err_sys("failed to read SMTP closing down response\n");
+    }
+    tmpBuf[ret] = 0; /* null terminate message */
+    printf("%s\n", tmpBuf);
+
+    ret = wolfSSL_shutdown(ssl);
+    if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) {
+        if (tcp_select(wolfSSL_get_fd(ssl), DEFAULT_TIMEOUT_SEC) ==
+                TEST_RECV_READY) {
+            ret = wolfSSL_shutdown(ssl);    /* bidirectional shutdown */
+            if (ret == WOLFSSL_SUCCESS)
+                printf("Bidirectional shutdown complete\n");
+        }
+        if (ret != WOLFSSL_SUCCESS)
+            printf("Bidirectional shutdown failed\n");
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+
+static int ClientWrite(WOLFSSL* ssl, const char* msg, int msgSz, const char* str,
+    int exitWithRet)
+{
+    int ret, err;
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+
+    do {
+        err = 0; /* reset error */
+        ret = wolfSSL_write(ssl, msg, msgSz);
+        if (ret <= 0) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WOLFSSL_ERROR_WANT_WRITE ||
+             err == WOLFSSL_ERROR_WANT_READ
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || err == WC_PENDING_E
+    #endif
+    );
+    if (ret != msgSz) {
+        printf("SSL_write%s msg error %d, %s\n", str, err,
+                                        wolfSSL_ERR_error_string(err, buffer));
+        if (!exitWithRet) {
+            err_sys("SSL_write failed");
+        }
+    }
+
+    return err;
+}
+
+static int ClientRead(WOLFSSL* ssl, char* reply, int replyLen, int mustRead,
+                      const char* str, int exitWithRet)
+{
+    int ret, err;
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+    double start = current_time(1), elapsed;
+
+    do {
+        err = 0; /* reset error */
+        ret = wolfSSL_read(ssl, reply, replyLen);
+        if (ret <= 0) {
+            err = wolfSSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+            else
+        #endif
+            if (err != WOLFSSL_ERROR_WANT_READ) {
+                printf("SSL_read reply error %d, %s\n", err,
+                                         wolfSSL_ERR_error_string(err, buffer));
+                if (!exitWithRet) {
+                    err_sys("SSL_read failed");
+                }
+                else {
+                    break;
+                }
+            }
+        }
+
+        if (mustRead && err == WOLFSSL_ERROR_WANT_READ) {
+            elapsed = current_time(0) - start;
+            if (elapsed > MAX_NON_BLOCK_SEC) {
+                printf("Nonblocking read timeout\n");
+                ret = WOLFSSL_FATAL_ERROR;
+                break;
+            }
+        }
+    } while ((mustRead && err == WOLFSSL_ERROR_WANT_READ)
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        || err == WC_PENDING_E
+    #endif
+    );
+    if (ret > 0) {
+        reply[ret] = 0; /* null terminate */
+        printf("%s%s\n", str, reply);
+    }
+
+    return err;
+}
+
+
+/* when adding new option, please follow the steps below: */
+/*  1. add new option message in English section          */
+/*  2. increase the number of the second column           */
+/*  3. increase the array dimension                       */
+/*  4. add the same message into Japanese section         */
+/*     (will be translated later)                         */
+/*  5. add printf() into suitable position of Usage()     */
+static const char* client_usage_msg[][69] = {
+    /* English */
+    {
+        " NOTE: All files relative to wolfSSL home dir\n",          /* 0 */
+        "Max RSA key size in bits for build is set at : ",          /* 1 */
+#ifdef NO_RSA
+        "RSA not supported\n",                                      /* 2 */
+#elif defined(WOLFSSL_SP_MATH) /* case of SP math only */
+#ifdef WOLFSSL_SP_4096
+        "4096\n",                                                   /* 2 */
+#elif !defined(WOLFSSL_SP_NO_3072)
+        "3072\n",                                                   /* 2 */
+#elif !defined(WOLFSSL_SP_NO_2048)
+        "2048\n",                                                   /* 2 */
+#else
+        "0\n",                                                      /* 2 */
+#endif
+#elif defined(USE_FAST_MATH)
+#else
+        "INFINITE\n",                                               /* 2 */
+#endif
+        "-? <num>    Help, print this usage\n"
+        "            0: English, 1: Japanese\n"
+        "--help      Help, in English\n",                           /* 3 */
+        "-h <host>   Host to connect to, default",                  /* 4 */
+        "-p <num>    Port to connect on, not 0, default",           /* 5 */
+
+#ifndef WOLFSSL_TLS13
+        "-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default", /* 6 */
+        "-V          Prints valid ssl version numbers"
+                                             ", SSLv3(0) - TLS1.2(3)\n", /* 7 */
+#else
+        "-v <num>    SSL version [0-4], SSLv3(0) - TLS1.3(4)), default", /* 6 */
+        "-V          Prints valid ssl version numbers,"
+                                            " SSLv3(0) - TLS1.3(4)\n",   /* 7 */
+#endif
+        "-l <str>    Cipher suite list (: delimited)\n",                /* 8 */
+#ifndef NO_CERTS
+        "-c <file>   Certificate file,           default",              /* 9 */
+        "-k <file>   Key file,                   default",              /* 10 */
+        "-A <file>   Certificate Authority file, default",              /* 11 */
+#endif
+#ifndef NO_DH
+        "-Z <num>    Minimum DH key bits,        default",              /* 12 */
+#endif
+        "-b <num>    Benchmark <num> connections and print stats\n",    /* 13 */
+#ifdef HAVE_ALPN
+        "-L <str>    Application-Layer Protocol"
+                                      " Negotiation ({C,F}:<list>)\n",  /* 14 */
+#endif
+        "-B <num>    Benchmark throughput"
+                                " using <num> bytes and print stats\n", /* 15 */
+#ifndef NO_PSK
+        "-s          Use pre Shared keys\n",                            /* 16 */
+#endif
+        "-d          Disable peer checks\n",                            /* 17 */
+        "-D          Override Date Errors example\n",                   /* 18 */
+        "-e          List Every cipher suite available, \n",            /* 19 */
+        "-g          Send server HTTP GET\n",                           /* 20 */
+        "-u          Use UDP DTLS,"
+                 " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n", /* 21 */
+#ifdef WOLFSSL_SCTP
+        "-G          Use SCTP DTLS,"
+                " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n",  /* 22 */
+#endif
+#ifndef NO_CERTS
+        "-m          Match domain name in cert\n",                      /* 23 */
+#endif
+        "-N          Use Non-blocking sockets\n",                       /* 24 */
+#ifndef NO_SESSION_CACHE
+        "-r          Resume session\n",                                 /* 25 */
+#endif
+        "-w          Wait for bidirectional shutdown\n",                /* 26 */
+        "-M <prot>   Use STARTTLS, using <prot> protocol (smtp)\n",     /* 27 */
+#ifdef HAVE_SECURE_RENEGOTIATION
+        "-R          Allow Secure Renegotiation\n",                     /* 28 */
+        "-i <str>    Force client Initiated Secure Renegotiation. If the\n"
+        "            string 'scr-app-data' is passed in as the value and\n"
+        "            Non-blocking sockets are enabled ('-N') then wolfSSL\n"
+        "            sends a test message during the secure renegotiation.\n"
+        "            The string parameter is optional.\n", /* 29 */
+#endif
+        "-f          Fewer packets/group messages\n",                   /* 30 */
+#ifndef NO_CERTS
+        "-x          Disable client cert/key loading\n",                /* 31 */
+#endif
+        "-X          Driven by eXternal test case\n",                   /* 32 */
+        "-j          Use verify callback override\n",                   /* 33 */
+#ifdef SHOW_SIZES
+        "-z          Print structure sizes\n",                          /* 34 */
+#endif
+#ifdef HAVE_SNI
+        "-S <str>    Use Host Name Indication\n",                       /* 35 */
+#endif
+#ifdef HAVE_MAX_FRAGMENT
+        "-F <num>    Use Maximum Fragment Length [1-6]\n",              /* 36 */
+#endif
+#ifdef HAVE_TRUNCATED_HMAC
+        "-T          Use Truncated HMAC\n",                             /* 37 */
+#endif
+#ifdef HAVE_EXTENDED_MASTER
+        "-n          Disable Extended Master Secret\n",                 /* 38 */
+#endif
+#ifdef HAVE_OCSP
+        "-o          Perform OCSP lookup on peer certificate\n",        /* 39 */
+        "-O <url>    Perform OCSP lookup using <url> as responder\n",   /* 40 */
+#endif
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        "-W <num>    Use OCSP Stapling (1 v1, 2 v2, 3 v2 multi)\n",     /* 41 */
+        "            With 'm' at end indicates MUST staple\n",          /* 42 */
+#endif
+#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+        "-U          Atomic User Record Layer Callbacks\n",             /* 43 */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+        "-P          Public Key Callbacks\n",                           /* 44 */
+#endif
+#ifdef HAVE_ANON
+        "-a          Anonymous client\n",                               /* 45 */
+#endif
+#ifdef HAVE_CRL
+        "-C          Disable CRL\n",                                    /* 46 */
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+        "-E <file>   Path to load trusted peer cert\n",                 /* 47 */
+#endif
+#ifdef HAVE_WNR
+        "-q <file>   Whitewood config file,      defaults\n",           /* 48 */
+#endif
+        "-H <arg>    Internal tests"
+            " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 49 */
+        "                            loadSSL, disallowETM]\n",          /* 50 */
+#ifdef WOLFSSL_TLS13
+        "-J          Use HelloRetryRequest to choose group for KE\n",   /* 51 */
+        "-K          Key Exchange for PSK not using (EC)DHE\n",         /* 52 */
+        "-I          Update keys and IVs before sending data\n",        /* 53 */
+#ifndef NO_DH
+        "-y          Key Share with FFDHE named groups only\n",         /* 54 */
+#endif
+#ifdef HAVE_ECC
+        "-Y          Key Share with ECC named groups only\n",           /* 55 */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef HAVE_CURVE25519
+        "-t          Use X25519 for key exchange\n",                    /* 56 */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        "-Q          Support requesting certificate post-handshake\n",  /* 57 */
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+        "-0          Early data sent to server (0-RTT handshake)\n",    /* 58 */
+#endif
+#ifdef WOLFSSL_MULTICAST
+        "-3 <grpid>  Multicast, grpid < 256\n",                         /* 59 */
+#endif
+        "-1 <num>    Display a result by specified language.\n"
+                               "            0: English, 1: Japanese\n", /* 60 */
+#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+        "-2          Disable DH Prime check\n",                         /* 61 */
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+        "-4          Use resumption for renegotiation\n",               /* 62 */
+#endif
+#ifdef HAVE_TRUSTED_CA
+        "-5          Use Trusted CA Key Indication\n",                  /* 63 */
+#endif
+        "-6          Simulate WANT_WRITE errors on every other IO send\n",
+#ifdef HAVE_CURVE448
+        "-8          Use X448 for key exchange\n",                      /* 66 */
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        "-9          Use hash dir look up for certificate loading\n"
+        "            loading from <wolfSSL home>/certs folder\n"
+        "            files in the folder would have the form \"hash.N\" file name\n"
+        "            e.g symbolic link to the file at certs folder\n"
+        "            ln -s ca-cert.pem  `openssl x509 -in ca-cert.pem -hash -noout`.0\n",
+                                                                       /* 67 */
+#endif
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \
+    !defined(WOLFSENTRY_NO_JSON)
+        "--wolfsentry-config <file>    Path for JSON wolfSentry config\n",
+                                                                       /* 68 */
+#endif
+#ifndef WOLFSSL_TLS13
+        "-7          Set minimum downgrade protocol version [0-3] "
+        " SSLv3(0) - TLS1.2(3)\n",
+#else
+        "-7          Set minimum downgrade protocol version [0-4] "
+        " SSLv3(0) - TLS1.3(4)\n",                           /* 69 */
+#endif
+        NULL,
+    },
+#ifndef NO_MULTIBYTE_PRINT
+    /* Japanese */
+        {
+        " 注意 : 全てのファイルは wolfSSL ホーム・ディレクトリからの相対です。"
+                                                               "\n",     /* 0 */
+        "RSAの最大ビットは次のように設定されています: ",                 /* 1 */
+#ifdef NO_RSA
+        "RSAはサポートされていません。\n",                               /* 2 */
+#elif defined(WOLFSSL_SP_MATH) /* case of SP math only */
+#ifndef WOLFSSL_SP_NO_3072
+        "3072\n",                                                        /* 2 */
+#elif !defined(WOLFSSL_SP_NO_2048)
+        "2048\n",                                                        /* 2 */
+#else
+        "0\n",                                                           /* 2 */
+#endif
+#elif defined(USE_FAST_MATH)
+#else
+        "無限\n",                                                        /* 2 */
+#endif
+        "-? <num>    ヘルプ, 使い方を表示\n"
+        "            0: 英語、 1: 日本語\n"
+        "--ヘルプ     使い方を表示, 日本語で\n",                          /* 3 */
+        "-h <host>   接続先ホスト, 既定値",                              /* 4 */
+        "-p <num>    接続先ポート, 0は無効, 既定値",                     /* 5 */
+
+#ifndef WOLFSSL_TLS13
+        "-v <num>    SSL バージョン [0-3], SSLv3(0) - TLS1.2(3)),"
+                                                              " 既定値", /* 6 */
+        "-V          有効な ssl バージョン番号を出力, SSLv3(0) -"
+                                                 " TLS1.2(3)\n",         /* 7 */
+#else
+        "-v <num>    SSL バージョン [0-4], SSLv3(0) - TLS1.3(4)),"
+                                                    " 既定値",           /* 6 */
+        "-V          有効な ssl バージョン番号を出力, SSLv3(0) -"
+                                                 " TLS1.3(4)\n",         /* 7 */
+#endif
+        "-l <str>    暗号スイートリスト (区切り文字 :)\n",               /* 8 */
+#ifndef NO_CERTS
+        "-c <file>   証明書ファイル,  既定値",                           /* 9 */
+        "-k <file>   鍵ファイル,      既定値",                          /* 10 */
+        "-A <file>   認証局ファイル,  既定値",                          /* 11 */
+#endif
+#ifndef NO_DH
+        "-Z <num>    最小 DH 鍵 ビット, 既定値",                        /* 12 */
+#endif
+        "-b <num>    ベンチマーク <num> 接続及び結果出力する\n",        /* 13 */
+#ifdef HAVE_ALPN
+        "-L <str>    アプリケーション層プロトコルネゴシエーションを行う"
+                                                 " ({C,F}:<list>)\n",   /* 14 */
+#endif
+        "-B <num>    <num> バイトを用いてのベンチマーク・スループット測定"
+                                                  "と結果を出力する\n", /* 15 */
+#ifndef NO_PSK
+        "-s          事前共有鍵を使用する\n",                           /* 16 */
+#endif
+        "-d          ピア確認を無効とする\n",                           /* 17 */
+        "-D          日付エラー用コールバック例の上書きを行う\n",       /* 18 */
+        "-e          利用可能な全ての暗号スイートをリスト, \n",         /* 19 */
+        "-g          サーバーへ HTTP GET を送信\n",                     /* 20 */
+        "-u          UDP DTLSを使用する。-v 2 を追加指定すると"
+               " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n",    /* 21 */
+#ifdef WOLFSSL_SCTP
+        "-G          SCTP DTLSを使用する。-v 2 を追加指定すると"
+                " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n",   /* 22 */
+#endif
+#ifndef NO_CERTS
+        "-m          証明書内のドメイン名一致を確認する\n",             /* 23 */
+#endif
+        "-N          ノンブロッキング・ソケットを使用する\n",           /* 24 */
+#ifndef NO_SESSION_CACHE
+        "-r          セッションを継続する\n",                           /* 25 */
+#endif
+        "-w          双方向シャットダウンを待つ\n",                     /* 26 */
+        "-M <prot>   STARTTLSを使用する, <prot>プロトコル(smtp)を"
+                                              "使用する\n",             /* 27 */
+#ifdef HAVE_SECURE_RENEGOTIATION
+        "-R          セキュアな再ネゴシエーションを許可する\n",         /* 28 */
+        "-i <str>    クライアント主導のネゴシエーションを強制する\n",   /* 29 */
+#endif
+        "-f          より少ないパケット/グループメッセージを使用する\n",/* 30 */
+#ifndef NO_CERTS
+        "-x          クライアントの証明書/鍵のロードを無効する\n",      /* 31 */
+#endif
+        "-X          外部テスト・ケースにより動作する\n",               /* 32 */
+        "-j          コールバック・オーバーライドの検証を使用する\n",   /* 33 */
+#ifdef SHOW_SIZES
+        "-z          構造体のサイズを表示する\n",                       /* 34 */
+#endif
+#ifdef HAVE_SNI
+        "-S <str>    ホスト名表示を使用する\n",                         /* 35 */
+#endif
+#ifdef HAVE_MAX_FRAGMENT
+        "-F <num>    最大フラグメント長[1-6]を設定する\n",              /* 36 */
+#endif
+#ifdef HAVE_TRUNCATED_HMAC
+        "-T          Truncated HMACを使用する\n",                       /* 37 */
+#endif
+#ifdef HAVE_EXTENDED_MASTER
+        "-n          マスターシークレット拡張を無効にする\n",           /* 38 */
+#endif
+#ifdef HAVE_OCSP
+        "-o          OCSPルックアップをピア証明書で実施する\n",         /* 39 */
+        "-O <url>    OCSPルックアップを、<url>を使用し"
+                                   "応答者として実施する\n",            /* 40 */
+#endif
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        "-W <num>    OCSP Staplingを使用する"
+                                         " (1 v1, 2 v2, 3 v2 multi)\n", /* 41 */
+        "            With 'm' at end indicates MUST staple\n",          /* 42 */
+#endif
+#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+        "-U          アトミック・ユーザー記録の"
+                                           "コールバックを利用する\n",  /* 43 */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+        "-P          公開鍵コールバック\n",                             /* 44 */
+#endif
+#ifdef HAVE_ANON
+        "-a          匿名クライアント\n",                               /* 45 */
+#endif
+#ifdef HAVE_CRL
+        "-C          CRLを無効\n",                                      /* 46 */
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+        "-E <file>   信頼出来るピアの証明書ロードの為のパス\n",         /* 47 */
+#endif
+#ifdef HAVE_WNR
+        "-q <file>   Whitewood コンフィグファイル,      既定値\n",      /* 48 */
+#endif
+        "-H <arg>    内部テスト"
+            " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 49 */
+        "                            loadSSL, disallowETM]\n",          /* 50 */
+#ifdef WOLFSSL_TLS13
+        "-J          HelloRetryRequestをKEのグループ選択に使用する\n",  /* 51 */
+        "-K          鍵交換にPSKを使用、(EC)DHEは使用しない\n",         /* 52 */
+        "-I          データ送信前に、鍵とIVを更新する\n",               /* 53 */
+#ifndef NO_DH
+        "-y          FFDHE名前付きグループとの鍵共有のみ\n",            /* 54 */
+#endif
+#ifdef HAVE_ECC
+        "-Y          ECC名前付きグループとの鍵共有のみ\n",              /* 55 */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef HAVE_CURVE25519
+        "-t          X25519を鍵交換に使用する\n",                       /* 56 */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        "-Q          ポストハンドシェークの証明要求をサポートする\n",   /* 57 */
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+        "-0          Early data をサーバーへ送信する"
+                            "(0-RTTハンドシェイク)\n",                /* 58 */
+#endif
+#ifdef WOLFSSL_MULTICAST
+        "-3 <grpid>  マルチキャスト, grpid < 256\n",                    /* 59 */
+#endif
+        "-1 <num>    指定された言語で結果を表示します。\n"
+                                   "            0: 英語、 1: 日本語\n", /* 60 */
+#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+        "-2          DHプライム番号チェックを無効にする\n",             /* 61 */
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+        "-4          再交渉に再開を使用\n",                             /* 62 */
+#endif
+#ifdef HAVE_TRUSTED_CA
+        "-5          信頼できる認証局の鍵表示を使用する\n",             /* 63 */
+#endif
+        "-6          WANT_WRITE エラーを全てのIO 送信でシュミレートします\n",
+#ifdef HAVE_CURVE448
+        "-8          Use X448 for key exchange\n",                      /* 66 */
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        "-9          証明書の読み込みに hash dir 機能を使用する\n"
+        "            <wolfSSL home>/certs フォルダーからロードします\n"
+        "            フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n"
+        "            以下の例ではca-cert.pemにシンボリックリンクを設定します\n"
+        "            ln -s ca-cert.pem  `openssl x509 -in ca-cert.pem -hash -noout`.0\n",
+                                                                        /* 67 */
+#endif
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \
+    !defined(WOLFSENTRY_NO_JSON)
+        "--wolfsentry-config <file>    wolfSentry コンフィグファイル\n",
+                                                                      /* 68 */
+#endif
+#ifndef WOLFSSL_TLS13
+        "-7          最小ダウングレード可能なプロトコルバージョンを設定します [0-3] "
+        " SSLv3(0) - TLS1.2(3)\n",
+#else
+        "-7          最小ダウングレード可能なプロトコルバージョンを設定します [0-4] "
+        " SSLv3(0) - TLS1.3(4)\n",                            /* 69 */
+#endif
+        NULL,
+    },
+#endif
+
+};
+
+static void Usage(void)
+{
+    int msgid = 0;
+    const char** msg = client_usage_msg[lng_index];
+
+    printf("%s%s%s", "wolfSSL client ",    LIBWOLFSSL_VERSION_STRING,
+           msg[msgid]);
+
+    /* print out so that scripts can know what the max supported key size is */
+    printf("%s", msg[++msgid]);
+#ifdef NO_RSA
+    printf("%s", msg[++msgid]);
+#elif defined(WOLFSSL_SP_MATH) /* case of SP math only */
+    #ifndef WOLFSSL_SP_NO_3072
+        printf("%s", msg[++msgid]);
+    #elif !defined(WOLFSSL_SP_NO_2048)
+        printf("%s", msg[++msgid]);
+    #else
+        printf("%s", msg[++msgid]);
+    #endif
+#elif defined(USE_FAST_MATH)
+    #if !defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_SP_MATH)
+    printf("%d\n", FP_MAX_BITS/2);
+    #else
+    printf("%d\n", SP_INT_MAX_BITS/2);
+    #endif
+#else
+    /* normal math has unlimited max size */
+    printf("%s", msg[++msgid]);
+#endif
+
+    printf("%s", msg[++msgid]); /* ? */
+    printf("%s %s\n", msg[++msgid], wolfSSLIP);   /* -h */
+    printf("%s %d\n", msg[++msgid], wolfSSLPort); /* -p */
+#ifndef WOLFSSL_TLS13
+    printf("%s %d\n", msg[++msgid], CLIENT_DEFAULT_VERSION); /* -v */
+    printf("%s", msg[++msgid]); /* -V */
+#else
+    printf("%s %d\n", msg[++msgid], CLIENT_DEFAULT_VERSION); /* -v */
+    printf("%s", msg[++msgid]);                              /* -V */
+#endif
+    printf("%s", msg[++msgid]); /* -l */
+#ifndef NO_CERTS
+    printf("%s %s\n", msg[++msgid], cliCertFile); /* -c */
+    printf("%s %s\n", msg[++msgid], cliKeyFile);  /* -k */
+    printf("%s %s\n", msg[++msgid], caCertFile);  /* -A */
+#endif
+#ifndef NO_DH
+    printf("%s %d\n", msg[++msgid], DEFAULT_MIN_DHKEY_BITS);
+#endif
+    printf("%s", msg[++msgid]); /* -b */
+#ifdef HAVE_ALPN
+    printf("%s", msg[++msgid]); /* -L <str> */
+#endif
+    printf("%s", msg[++msgid]); /* -B <num> */
+#ifndef NO_PSK
+    printf("%s", msg[++msgid]); /* -s */
+#endif
+    printf("%s", msg[++msgid]); /* -d */
+    printf("%s", msg[++msgid]); /* -D */
+    printf("%s", msg[++msgid]); /* -e */
+    printf("%s", msg[++msgid]); /* -g */
+    printf("%s", msg[++msgid]); /* -u */
+#ifdef WOLFSSL_SCTP
+    printf("%s", msg[++msgid]); /* -G */
+#endif
+#ifndef NO_CERTS
+    printf("%s", msg[++msgid]); /* -m */
+#endif
+    printf("%s", msg[++msgid]); /* -N */
+#ifndef NO_SESSION_CACHE
+    printf("%s", msg[++msgid]); /* -r */
+#endif
+    printf("%s", msg[++msgid]); /* -w */
+    printf("%s", msg[++msgid]); /* -M */
+#ifdef HAVE_SECURE_RENEGOTIATION
+    printf("%s", msg[++msgid]); /* -R */
+    printf("%s", msg[++msgid]); /* -i */
+#endif
+    printf("%s", msg[++msgid]); /* -f */
+#ifndef NO_CERTS
+    printf("%s", msg[++msgid]); /* -x */
+#endif
+    printf("%s", msg[++msgid]); /* -X */
+    printf("%s", msg[++msgid]); /* -j */
+#ifdef SHOW_SIZES
+    printf("%s", msg[++msgid]); /* -z */
+#endif
+#ifdef HAVE_SNI
+    printf("%s", msg[++msgid]); /* -S */
+#endif
+#ifdef HAVE_MAX_FRAGMENT
+    printf("%s", msg[++msgid]); /* -F */
+#endif
+#ifdef HAVE_TRUNCATED_HMAC
+    printf("%s", msg[++msgid]); /* -T */
+#endif
+#ifdef HAVE_EXTENDED_MASTER
+    printf("%s", msg[++msgid]); /* -n */
+#endif
+#ifdef HAVE_OCSP
+    printf("%s", msg[++msgid]); /* -o */
+    printf("%s", msg[++msgid]); /* -O */
+#endif
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    printf("%s", msg[++msgid]); /* -W */
+    printf("%s", msg[++msgid]); /* note for -W */
+#endif
+#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+    printf("%s", msg[++msgid]); /* -U */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    printf("%s", msg[++msgid]); /* -P */
+#endif
+#ifdef HAVE_ANON
+    printf("%s", msg[++msgid]); /* -a */
+#endif
+#ifdef HAVE_CRL
+    printf("%s", msg[++msgid]); /* -C */
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    printf("%s", msg[++msgid]); /* -E */
+#endif
+#ifdef HAVE_WNR
+    printf("%s %s\n", msg[++msgid], wnrConfig); /* -q */
+#endif
+    printf("%s", msg[++msgid]);                /* -H  */
+    printf("%s", msg[++msgid]);                /* more -H options  */
+#ifdef WOLFSSL_TLS13
+    printf("%s", msg[++msgid]); /* -J */
+    printf("%s", msg[++msgid]); /* -K */
+    printf("%s", msg[++msgid]); /* -I */
+#ifndef NO_DH
+    printf("%s", msg[++msgid]); /* -y */
+#endif
+#ifdef HAVE_ECC
+    printf("%s", msg[++msgid]); /* -Y */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef HAVE_CURVE25519
+    printf("%s", msg[++msgid]); /* -t */
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    printf("%s", msg[++msgid]); /* -Q */
+#endif
+#ifdef WOLFSSL_EARLY_DATA
+    printf("%s", msg[++msgid]); /* -0 */
+#endif
+#ifdef WOLFSSL_MULTICAST
+    printf("%s", msg[++msgid]); /* -3 */
+#endif
+    printf("%s", msg[++msgid]);  /* -1 */
+#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+    printf("%s", msg[++msgid]);  /* -2 */
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+    printf("%s", msg[++msgid]);  /* -4 */
+#endif
+#ifdef HAVE_TRUSTED_CA
+    printf("%s", msg[++msgid]);  /* -5 */
+#endif
+    printf("%s", msg[++msgid]);  /* -6 */
+#ifdef HAVE_CURVE448
+    printf("%s", msg[++msgid]); /* -8 */
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+    printf("%s", msg[++msgid]); /* -9 */
+#endif
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \
+    !defined(WOLFSENTRY_NO_JSON)
+    printf("%s", msg[++msgid]); /* --wolfsentry-config */
+#endif
+    printf("%s", msg[++msgid]); /* -7 */
+}
+
+THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
+{
+    SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID;
+
+    wolfSSL_method_func method = NULL;
+    WOLFSSL_CTX*     ctx     = 0;
+    WOLFSSL*         ssl     = 0;
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+    wolfsentry_errcode_t wolfsentry_ret;
+#endif
+
+    WOLFSSL*         sslResume = 0;
+    WOLFSSL_SESSION* session = 0;
+    byte*            flatSession = NULL;
+    int              flatSessionSz = 0;
+
+    char msg[CLI_MSG_SZ];
+    int  msgSz = 0;
+    char reply[CLI_REPLY_SZ];
+
+    word16 port   = wolfSSLPort;
+    char* host   = (char*)wolfSSLIP;
+    const char* domain = "localhost";  /* can't default to www.wolfssl.com
+                                          because can't tell if we're really
+                                          going there to detect old chacha-poly
+                                       */
+#ifndef WOLFSSL_VXWORKS
+    int    ch;
+    static const struct mygetopt_long_config long_options[] = {
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \
+    !defined(WOLFSENTRY_NO_JSON)
+        { "wolfsentry-config", 1, 256 },
+#endif
+        { "help", 0, 257 },
+        { "ヘルプ", 0, 258 },
+        { 0, 0, 0 }
+    };
+#endif
+    int    version = CLIENT_INVALID_VERSION;
+    int    minVersion = CLIENT_INVALID_VERSION;
+    int    usePsk   = 0;
+    int    useAnon  = 0;
+    int    sendGET  = 0;
+    int    benchmark = 0;
+    int    block = TEST_BUFFER_SIZE;
+    size_t throughput = 0;
+    int    doDTLS    = 0;
+    int    dtlsUDP   = 0;
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+    int    dtlsMTU = 0;
+#endif
+    int    dtlsSCTP  = 0;
+    int    doMcast   = 0;
+    int    matchName = 0;
+    int    doPeerCheck = 1;
+    int    nonBlocking = 0;
+    int    simulateWantWrite = 0;
+    int    resumeSession = 0;
+    int    wc_shutdown   = 0;
+    int    disableCRL    = 0;
+    int    externalTest  = 0;
+    int    ret;
+    int    err           = 0;
+    int    scr           = 0;    /* allow secure renegotiation */
+    int    forceScr      = 0;    /* force client initiated scr */
+    int    scrAppData    = 0;
+    int    resumeScr     = 0;    /* use resumption for renegotiation */
+#ifndef WOLFSSL_NO_CLIENT_AUTH
+    int    useClientCert = 1;
+#else
+    int    useClientCert = 0;
+#endif
+    int    fewerPackets  = 0;
+    int    atomicUser    = 0;
+#ifdef HAVE_PK_CALLBACKS
+    int    pkCallbacks   = 0;
+    PkCbInfo pkCbInfo;
+#endif
+    int    minDhKeyBits  = DEFAULT_MIN_DHKEY_BITS;
+    char*  alpnList = NULL;
+    unsigned char alpn_opt = 0;
+    char*  cipherList = NULL;
+    int    useDefCipherList = 0;
+    const char* verifyCert;
+    const char* ourCert;
+    const char* ourKey;
+
+    int   doSTARTTLS    = 0;
+    char* starttlsProt = NULL;
+    int   useVerifyCb = 0;
+    int   useSupCurve = 0;
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    const char* trustCert  = NULL;
+#endif
+
+#ifdef HAVE_SNI
+    char*  sniHostName = NULL;
+#endif
+#ifdef HAVE_TRUSTED_CA
+    int trustedCaKeyId = 0;
+#endif
+#ifdef HAVE_MAX_FRAGMENT
+    byte maxFragment = 0;
+#endif
+#ifdef HAVE_TRUNCATED_HMAC
+    byte truncatedHMAC = 0;
+#endif
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    byte statusRequest = 0;
+    byte mustStaple = 0;
+#endif
+#ifdef HAVE_EXTENDED_MASTER
+    byte disableExtMasterSecret = 0;
+#endif
+    int helloRetry = 0;
+    int onlyKeyShare = 0;
+#ifdef WOLFSSL_TLS13
+    int noPskDheKe = 0;
+    int postHandAuth = 0;
+#endif
+    int updateKeysIVs = 0;
+    int earlyData = 0;
+#ifdef WOLFSSL_MULTICAST
+    byte mcastID = 0;
+#endif
+#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+    int doDhKeyCheck = 1;
+#endif
+
+#ifdef HAVE_OCSP
+    int    useOcsp  = 0;
+    char*  ocspUrl  = NULL;
+#endif
+    int useX25519 = 0;
+    int useX448 = 0;
+    int exitWithRet = 0;
+    int loadCertKeyIntoSSLObj = 0;
+
+#ifdef HAVE_ENCRYPT_THEN_MAC
+    int disallowETM = 0;
+#endif
+
+#ifdef HAVE_WNR
+    const char* wnrConfigFile = wnrConfig;
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+    int useCertFolder = 0;
+#endif
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+
+    int     argc = ((func_args*)args)->argc;
+    char**  argv = ((func_args*)args)->argv;
+
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
+        || defined(SESSION_CERTS)
+        /* big enough to handle most cases including session certs */
+        byte memory[320000];
+    #else
+        byte memory[80000];
+    #endif
+    byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */
+    WOLFSSL_MEM_CONN_STATS ssl_stats;
+    #ifdef DEBUG_WOLFSSL
+        WOLFSSL_MEM_STATS mem_stats;
+    #endif
+    WOLFSSL_HEAP_HINT *heap = NULL;
+#endif
+
+    ((func_args*)args)->return_code = -1; /* error state */
+
+#ifndef NO_RSA
+    verifyCert = caCertFile;
+    ourCert    = cliCertFile;
+    ourKey     = cliKeyFile;
+#else
+    #ifdef HAVE_ECC
+        verifyCert = caEccCertFile;
+        ourCert    = cliEccCertFile;
+        ourKey     = cliEccKeyFile;
+    #elif defined(HAVE_ED25519)
+        verifyCert = caEdCertFile;
+        ourCert    = cliEdCertFile;
+        ourKey     = cliEdKeyFile;
+    #elif defined(HAVE_ED448)
+        verifyCert = caEd448CertFile;
+        ourCert    = cliEd448CertFile;
+        ourKey     = cliEd448KeyFile;
+    #else
+        verifyCert = NULL;
+        ourCert    = NULL;
+        ourKey     = NULL;
+    #endif
+#endif
+
+    (void)session;
+    (void)flatSession;
+    (void)flatSessionSz;
+    (void)sslResume;
+    (void)atomicUser;
+    (void)scr;
+    (void)forceScr;
+    (void)scrAppData;
+    (void)resumeScr;
+    (void)ourKey;
+    (void)ourCert;
+    (void)verifyCert;
+    (void)useClientCert;
+    (void)disableCRL;
+    (void)minDhKeyBits;
+    (void)alpnList;
+    (void)alpn_opt;
+    (void)updateKeysIVs;
+    (void)earlyData;
+    (void)useX25519;
+    (void)useX448;
+    (void)helloRetry;
+    (void)onlyKeyShare;
+    (void)useSupCurve;
+    (void)loadCertKeyIntoSSLObj;
+
+    StackTrap();
+
+    /* Reinitialize the global myVerifyAction. */
+    myVerifyAction = VERIFY_OVERRIDE_ERROR;
+
+#ifndef WOLFSSL_VXWORKS
+    /* Not used: All used */
+    while ((ch = mygetopt_long(argc, argv, "?:"
+            "ab:c:defgh:i;jk:l:mnop:q:rstu;v:wxyz"
+            "A:B:CDE:F:GH:IJKL:M:NO:PQRS:TUVW:XYZ:"
+            "01:23:4567:89"
+            "@#", long_options, 0)) != -1) {
+        switch (ch) {
+            case '?' :
+                if(myoptarg!=NULL) {
+                    lng_index = atoi(myoptarg);
+                    if(lng_index<0||lng_index>1){
+                        lng_index = 0;
+                    }
+                }
+                Usage();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 257 :
+                lng_index = 0;
+                Usage();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 258 :
+                lng_index = 1;
+                Usage();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 'g' :
+                sendGET = 1;
+                break;
+
+            case 'd' :
+                doPeerCheck = 0;
+                break;
+
+            case 'e' :
+                ShowCiphers();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 'D' :
+                myVerifyAction = VERIFY_OVERRIDE_DATE_ERR;
+                break;
+
+            case 'C' :
+                #ifdef HAVE_CRL
+                    disableCRL = 1;
+                #endif
+                break;
+
+            case 'u' :
+                doDTLS = 1;
+                dtlsUDP = 1;
+            #if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+                dtlsMTU = atoi(myoptarg);
+            #endif
+                break;
+
+            case 'G' :
+            #ifdef WOLFSSL_SCTP
+                doDTLS = 1;
+                dtlsSCTP = 1;
+            #endif
+                break;
+
+            case 's' :
+                usePsk = 1;
+                break;
+
+            #ifdef WOLFSSL_TRUST_PEER_CERT
+            case 'E' :
+                trustCert = myoptarg;
+                break;
+            #endif
+
+            case 'm' :
+                matchName = 1;
+                break;
+
+            case 'x' :
+                useClientCert = 0;
+                break;
+
+            case 'X' :
+                externalTest = 1;
+                break;
+
+            case 'f' :
+                fewerPackets = 1;
+                break;
+
+            case 'U' :
+            #if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+                atomicUser = 1;
+            #endif
+                break;
+
+            case 'P' :
+            #ifdef HAVE_PK_CALLBACKS
+                pkCallbacks = 1;
+            #endif
+                break;
+
+            case 'h' :
+                host   = myoptarg;
+                domain = myoptarg;
+                break;
+
+            case 'p' :
+                port = (word16)atoi(myoptarg);
+                #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
+                    if (port == 0)
+                        err_sys("port number cannot be 0");
+                #endif
+                break;
+
+            case 'v' :
+                if (myoptarg[0] == 'd') {
+                    version = CLIENT_DOWNGRADE_VERSION;
+                    break;
+                }
+            #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+                else if (myoptarg[0] == 'e') {
+                    version = EITHER_DOWNGRADE_VERSION;
+                #ifndef NO_CERTS
+                    loadCertKeyIntoSSLObj = 1;
+                #endif
+                    break;
+                }
+            #endif
+                version = atoi(myoptarg);
+                if (version < 0 || version > 4) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'V' :
+                ShowVersions();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 'l' :
+                cipherList = myoptarg;
+                break;
+
+            case 'H' :
+                if (XSTRNCMP(myoptarg, "defCipherList", 13) == 0) {
+                    printf("Using default cipher list for testing\n");
+                    useDefCipherList = 1;
+                }
+                else if (XSTRNCMP(myoptarg, "exitWithRet", 11) == 0) {
+                    printf("Skip exit() for testing\n");
+                    exitWithRet = 1;
+                }
+                else if (XSTRNCMP(myoptarg, "verifyFail", 10) == 0) {
+                    printf("Verify should fail\n");
+                    myVerifyAction = VERIFY_FORCE_FAIL;
+                }
+                else if (XSTRNCMP(myoptarg, "verifyInfo", 10) == 0) {
+                    printf("Verify should not override error\n");
+                    myVerifyAction = VERIFY_USE_PREVERFIY;
+                }
+                else if (XSTRNCMP(myoptarg, "useSupCurve", 11) == 0) {
+                    printf("Attempting to test use supported curve\n");
+                #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
+                    useSupCurve = 1;
+                #else
+                    printf("Supported curves not compiled in!\n");
+                #endif
+                }
+                else if (XSTRNCMP(myoptarg, "loadSSL", 7) == 0) {
+                    printf("Load cert/key into wolfSSL object\n");
+                #ifndef NO_CERTS
+                    loadCertKeyIntoSSLObj = 1;
+                #else
+                    printf("Certs turned off with NO_CERTS!\n");
+                #endif
+                }
+                else if (XSTRNCMP(myoptarg, "disallowETM", 7) == 0) {
+                    printf("Disallow Encrypt-Then-MAC\n");
+                #ifdef HAVE_ENCRYPT_THEN_MAC
+                    disallowETM = 1;
+                #endif
+                }
+                else {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'A' :
+                verifyCert = myoptarg;
+                break;
+
+            case 'c' :
+                ourCert = myoptarg;
+                break;
+
+            case 'k' :
+                ourKey = myoptarg;
+                break;
+
+            case 'Z' :
+                #ifndef NO_DH
+                    minDhKeyBits = atoi(myoptarg);
+                    if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+                #endif
+                break;
+
+            case 'b' :
+                benchmark = atoi(myoptarg);
+                if (benchmark < 0 || benchmark > 1000000) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'B' :
+                throughput = atol(myoptarg);
+                for (; *myoptarg != '\0'; myoptarg++) {
+                    if (*myoptarg == ',') {
+                        block = atoi(myoptarg + 1);
+                        break;
+                    }
+                }
+                if (throughput == 0 || block <= 0) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'N' :
+                nonBlocking = 1;
+                break;
+
+            case 'r' :
+                resumeSession = 1;
+                break;
+
+            case 'w' :
+                wc_shutdown = 1;
+                break;
+
+            case 'R' :
+                #ifdef HAVE_SECURE_RENEGOTIATION
+                    scr = 1;
+                #endif
+                break;
+
+            case 'i' :
+                #ifdef HAVE_SECURE_RENEGOTIATION
+                    scr      = 1;
+                    forceScr = 1;
+                    if (XSTRNCMP(myoptarg, "scr-app-data", 12) == 0) {
+                        scrAppData = 1;
+                    }
+                #endif
+                break;
+
+            case 'z' :
+                #ifndef WOLFSSL_LEANPSK
+                    wolfSSL_GetObjectSize();
+                #endif
+                break;
+
+            case 'S' :
+                if (XSTRNCMP(myoptarg, "check", 5) == 0) {
+                #ifdef HAVE_SNI
+                    printf("SNI is: ON\n");
+                #else
+                    printf("SNI is: OFF\n");
+                #endif
+                    XEXIT_T(EXIT_SUCCESS);
+                }
+                #ifdef HAVE_SNI
+                    sniHostName = myoptarg;
+                #endif
+                break;
+
+            case 'F' :
+                #ifdef HAVE_MAX_FRAGMENT
+                    maxFragment = atoi(myoptarg);
+                    if (maxFragment < WOLFSSL_MFL_MIN ||
+                                               maxFragment > WOLFSSL_MFL_MAX) {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+                #endif
+                break;
+
+            case 'T' :
+                #ifdef HAVE_TRUNCATED_HMAC
+                    truncatedHMAC = 1;
+                #endif
+                break;
+
+            case 'n' :
+                #ifdef HAVE_EXTENDED_MASTER
+                    disableExtMasterSecret = 1;
+                #endif
+                break;
+
+            case 'W' :
+                #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+                 || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+                {
+                    word32 myoptargSz;
+
+                    statusRequest = atoi(myoptarg);
+                    if (statusRequest > OCSP_STAPLING_OPT_MAX) {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+
+                    myoptargSz = (word32)XSTRLEN(myoptarg);
+                    if (myoptargSz > 0 &&
+                            XTOUPPER(myoptarg[myoptargSz-1]) == 'M') {
+                        mustStaple = 1;
+                    }
+                }
+                #endif
+                break;
+
+            case 'o' :
+                #ifdef HAVE_OCSP
+                    useOcsp = 1;
+                #endif
+                break;
+
+            case 'O' :
+                #ifdef HAVE_OCSP
+                    useOcsp = 1;
+                    ocspUrl = myoptarg;
+                #endif
+                break;
+
+            case 'a' :
+                #ifdef HAVE_ANON
+                    useAnon = 1;
+                #endif
+                break;
+
+            case 'L' :
+                #ifdef HAVE_ALPN
+                    alpnList = myoptarg;
+
+                    if (alpnList[0] == 'C' && alpnList[1] == ':')
+                        alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
+                    else if (alpnList[0] == 'F' && alpnList[1] == ':')
+                        alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
+                    else {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+
+                    alpnList += 2;
+
+                #endif
+                break;
+
+            case 'M' :
+                doSTARTTLS = 1;
+                starttlsProt = myoptarg;
+
+                if (XSTRNCMP(starttlsProt, "smtp", 4) != 0) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+
+                break;
+
+            case 'q' :
+                #ifdef HAVE_WNR
+                    wnrConfigFile = myoptarg;
+                #endif
+                break;
+
+            case 'J' :
+                #ifdef WOLFSSL_TLS13
+                    helloRetry = 1;
+                #endif
+                break;
+
+            case 'K' :
+                #ifdef WOLFSSL_TLS13
+                    noPskDheKe = 1;
+                #endif
+                break;
+
+            case 'I' :
+                #ifdef WOLFSSL_TLS13
+                    updateKeysIVs = 1;
+                #endif
+                break;
+
+            case 'y' :
+                #if defined(WOLFSSL_TLS13) && \
+                               defined(HAVE_SUPPORTED_CURVES) && !defined(NO_DH)
+                    onlyKeyShare = 1;
+                #endif
+                break;
+
+            case 'Y' :
+                #if defined(WOLFSSL_TLS13) && \
+                             defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_ECC)
+                    onlyKeyShare = 2;
+                #endif
+                break;
+
+            case 'j' :
+                useVerifyCb = 1;
+                break;
+
+            case 't' :
+                #ifdef HAVE_CURVE25519
+                    useX25519 = 1;
+                    #ifdef HAVE_ECC
+                    useSupCurve = 1;
+                        #if defined(WOLFSSL_TLS13) && \
+                                                  defined(HAVE_SUPPORTED_CURVES)
+                        onlyKeyShare = 2;
+                        #endif
+                    #endif
+                #endif
+                break;
+
+            case 'Q' :
+                #if defined(WOLFSSL_TLS13) && \
+                                            defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+                    postHandAuth = 1;
+                #endif
+                break;
+
+            case '0' :
+            #ifdef WOLFSSL_EARLY_DATA
+                earlyData = 1;
+            #endif
+                break;
+
+            case '1' :
+                lng_index = atoi(myoptarg);
+                if(lng_index<0||lng_index>1){
+                      lng_index = 0;
+                }
+                break;
+
+            case '2' :
+               #if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+                   !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+                    doDhKeyCheck = 0;
+                #endif
+                break;
+
+            case '3' :
+                #ifdef WOLFSSL_MULTICAST
+                    doMcast = 1;
+                    mcastID = (byte)(atoi(myoptarg) & 0xFF);
+                #endif
+                break;
+
+            case '4' :
+                #ifdef HAVE_SECURE_RENEGOTIATION
+                    scr       = 1;
+                    forceScr  = 1;
+                    resumeScr = 1;
+                #endif
+                break;
+
+            case '5' :
+            #ifdef HAVE_TRUSTED_CA
+                trustedCaKeyId = 1;
+            #endif /* HAVE_TRUSTED_CA */
+                break;
+
+            case '6' :
+                nonBlocking = 1;
+                simulateWantWrite = 1;
+                break;
+            case '7' :
+                minVersion = atoi(myoptarg);
+                if (minVersion < 0 || minVersion > 4) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+            case '8' :
+                #ifdef HAVE_CURVE448
+                    useX448 = 1;
+                    #ifdef HAVE_ECC
+                    useSupCurve = 1;
+                        #if defined(WOLFSSL_TLS13) && \
+                                                  defined(HAVE_SUPPORTED_CURVES)
+                        onlyKeyShare = 2;
+                        #endif
+                    #endif
+                #endif
+                break;
+            case '9' :
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+                    useCertFolder = 1;
+#endif
+                    break;
+            case '@' :
+            {
+#ifdef HAVE_WC_INTROSPECTION
+                const char *conf_args = wolfSSL_configure_args();
+                if (conf_args) {
+                    puts(conf_args);
+                    XEXIT_T(EXIT_SUCCESS);
+                } else {
+                    fputs("configure args not compiled in.\n",stderr);
+                    XEXIT_T(MY_EX_USAGE);
+                }
+#else
+                fputs("compiled without BUILD_INTROSPECTION.\n",stderr);
+                XEXIT_T(MY_EX_USAGE);
+#endif
+            }
+
+            case '#' :
+            {
+#ifdef HAVE_WC_INTROSPECTION
+                const char *cflags = wolfSSL_global_cflags();
+                if (cflags) {
+                    puts(cflags);
+                    XEXIT_T(EXIT_SUCCESS);
+                } else {
+                    fputs("CFLAGS not compiled in.\n",stderr);
+                    XEXIT_T(MY_EX_USAGE);
+                }
+#else
+                fputs("compiled without BUILD_INTROSPECTION.\n",stderr);
+                XEXIT_T(MY_EX_USAGE);
+#endif
+            }
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+            case 256:
+#if !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
+                wolfsentry_config_path = myoptarg;
+#endif
+                break;
+#endif
+
+            default:
+                Usage();
+                XEXIT_T(MY_EX_USAGE);
+        }
+    }
+
+    myoptind = 0;      /* reset for test cases */
+#endif /* !WOLFSSL_VXWORKS */
+
+    if (externalTest) {
+        /* detect build cases that wouldn't allow test against wolfssl.com */
+        int done = 0;
+
+        #ifdef NO_RSA
+            done += 1; /* require RSA for external tests */
+        #endif
+
+        if (!XSTRNCMP(domain, "www.globalsign.com", 14)) {
+        /* www.globalsign.com does not respond to ipv6 ocsp requests */
+        #if defined(TEST_IPV6) && defined(HAVE_OCSP)
+            done += 1;
+        #endif
+
+        /* www.globalsign.com has limited supported cipher suites */
+        #if defined(NO_AES) && defined(HAVE_OCSP)
+            done += 1;
+        #endif
+
+        /* www.globalsign.com only supports static RSA or ECDHE with AES */
+        /* We cannot expect users to have on static RSA so test for ECC only
+         * as some users will most likely be on 32-bit systems where ECC
+         * is not enabled by default */
+        #if defined(HAVE_OCSP) && !defined(HAVE_ECC)
+            done += 1;
+        #endif
+        }
+
+        #ifndef NO_PSK
+        if (usePsk) {
+            done += 1; /* don't perform external tests if PSK is enabled */
+        }
+        #endif
+
+        #ifdef NO_SHA
+            done += 1;  /* external cert chain most likely has SHA */
+        #endif
+
+        #if !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \
+            || ( defined(HAVE_ECC) && !defined(HAVE_SUPPORTED_CURVES) \
+                  && !defined(WOLFSSL_STATIC_RSA) )
+            /* google needs ECDHE+Supported Curves or static RSA */
+            if (!XSTRNCMP(domain, "www.google.com", 14))
+                done += 1;
+        #endif
+
+        #if !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA)
+            /* wolfssl needs ECDHE or static RSA */
+            if (!XSTRNCMP(domain, "www.wolfssl.com", 15))
+                done += 1;
+        #endif
+
+        #if !defined(WOLFSSL_SHA384)
+            if (!XSTRNCMP(domain, "www.wolfssl.com", 15)) {
+                /* wolfssl need sha384 for cert chain verify */
+                done += 1;
+            }
+        #endif
+
+        #if !defined(HAVE_AESGCM) && defined(NO_AES) && \
+            !(defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
+            /* need at least one of these for external tests */
+            done += 1;
+        #endif
+
+        #if defined(HAVE_QSH)
+            /*currently google server rejects client hello with QSH extension.*/
+            done += 1;
+        #endif
+
+        /* For the external test, if we disable AES, GoDaddy will reject the
+         * connection. They only currently support AES suites, RC4 and 3DES
+         * suites. With AES disabled we only offer PolyChacha suites. */
+        #if defined(NO_AES) && !defined(HAVE_AESGCM)
+            if (!XSTRNCMP(domain, "www.wolfssl.com", 15)) {
+                done += 1;
+            }
+        #endif
+
+        if (done) {
+            printf("external test can't be run in this mode\n");
+
+            ((func_args*)args)->return_code = 0;
+            XEXIT_T(EXIT_SUCCESS);
+        }
+    }
+
+    /* sort out DTLS versus TLS versions */
+    if (version == CLIENT_INVALID_VERSION) {
+        if (doDTLS)
+            version = CLIENT_DTLS_DEFAULT_VERSION;
+        else
+            version = CLIENT_DEFAULT_VERSION;
+    }
+    else {
+        if (doDTLS) {
+            if (version == 3)
+                version = -2;
+        #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+            else if (version == EITHER_DOWNGRADE_VERSION)
+                version = -3;
+        #endif
+            else
+                version = -1;
+        }
+    }
+
+#ifdef HAVE_WNR
+    if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0)
+        err_sys("can't load whitewood net random config file");
+#endif
+
+    switch (version) {
+#ifndef NO_OLD_TLS
+    #ifdef WOLFSSL_ALLOW_SSLV3
+        case 0:
+            method = wolfSSLv3_client_method_ex;
+            break;
+    #endif
+
+    #ifndef NO_TLS
+        #ifdef WOLFSSL_ALLOW_TLSV10
+        case 1:
+            method = wolfTLSv1_client_method_ex;
+            break;
+        #endif
+
+        case 2:
+            method = wolfTLSv1_1_client_method_ex;
+            break;
+    #endif /* !NO_TLS */
+#endif /* !NO_OLD_TLS */
+
+#ifndef NO_TLS
+    #ifndef WOLFSSL_NO_TLS12
+        case 3:
+            method = wolfTLSv1_2_client_method_ex;
+            break;
+    #endif
+
+    #ifdef WOLFSSL_TLS13
+        case 4:
+            method = wolfTLSv1_3_client_method_ex;
+            break;
+    #endif
+
+        case CLIENT_DOWNGRADE_VERSION:
+            method = wolfSSLv23_client_method_ex;
+            break;
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+        case EITHER_DOWNGRADE_VERSION:
+            method = wolfSSLv23_method_ex;
+            break;
+    #endif
+#endif /* NO_TLS */
+
+#ifdef WOLFSSL_DTLS
+        #ifndef NO_OLD_TLS
+        case -1:
+            method = wolfDTLSv1_client_method_ex;
+            break;
+        #endif
+
+    #ifndef WOLFSSL_NO_TLS12
+        case -2:
+            method = wolfDTLSv1_2_client_method_ex;
+            break;
+    #endif
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+        case -3:
+            method = wolfDTLSv1_2_method_ex;
+            break;
+    #endif
+#endif
+
+        default:
+            err_sys("Bad SSL version");
+            break;
+    }
+
+    if (method == NULL)
+        err_sys("unable to get method");
+
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    #ifdef DEBUG_WOLFSSL
+    /* print off helper buffer sizes for use with static memory
+     * printing to stderr in case of debug mode turned on */
+    fprintf(stderr, "static memory management size = %d\n",
+            wolfSSL_MemoryPaddingSz());
+    fprintf(stderr, "calculated optimum general buffer size = %d\n",
+            wolfSSL_StaticBufferSz(memory, sizeof(memory), 0));
+    fprintf(stderr, "calculated optimum IO buffer size      = %d\n",
+            wolfSSL_StaticBufferSz(memoryIO, sizeof(memoryIO),
+                                                  WOLFMEM_IO_POOL_FIXED));
+    #endif /* DEBUG_WOLFSSL */
+
+    if (wc_LoadStaticMemory(&heap, memory, sizeof(memory), WOLFMEM_GENERAL, 1)
+            != 0) {
+        err_sys("unable to load static memory");
+    }
+
+    ctx = wolfSSL_CTX_new_ex(method(heap), heap);
+    if (ctx == NULL)
+        err_sys("unable to get ctx");
+
+    if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO),
+           WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1) != WOLFSSL_SUCCESS) {
+        err_sys("unable to load static memory");
+    }
+#else
+    if (method != NULL) {
+        ctx = wolfSSL_CTX_new(method(NULL));
+        if (ctx == NULL)
+            err_sys("unable to get ctx");
+    }
+#endif
+    if (minVersion != CLIENT_INVALID_VERSION) {
+        wolfSSL_CTX_SetMinVersion(ctx, minVersion);
+    }
+    if (simulateWantWrite) {
+    #ifdef USE_WOLFSSL_IO
+        wolfSSL_CTX_SetIOSend(ctx, SimulateWantWriteIOSendCb);
+    #endif
+    }
+
+#ifdef SINGLE_THREADED
+    if (wolfSSL_CTX_new_rng(ctx) != WOLFSSL_SUCCESS) {
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("Single Threaded new rng at CTX failed");
+    }
+#endif
+
+
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+    if (wolfsentry_setup(&wolfsentry, wolfsentry_config_path,
+                                     WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT) < 0) {
+        err_sys("unable to initialize wolfSentry");
+    }
+
+    if (wolfSSL_CTX_set_ConnectFilter(
+            ctx,
+            (NetworkFilterCallback_t)wolfSentry_NetworkFilterCallback,
+            wolfsentry) < 0) {
+        err_sys("unable to install wolfSentry_NetworkFilterCallback");
+    }
+#endif
+
+    if (cipherList && !useDefCipherList) {
+        if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("client can't set cipher list 1");
+        }
+    }
+
+#ifdef WOLFSSL_LEANPSK
+    if (!usePsk) {
+        usePsk = 1;
+    }
+#endif
+
+#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
+                                                            !defined(HAVE_ED448)
+    if (!usePsk) {
+        usePsk = 1;
+    }
+#endif
+
+    if (fewerPackets)
+        wolfSSL_CTX_set_group_messages(ctx);
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+    if (dtlsMTU)
+        wolfSSL_CTX_dtls_set_mtu(ctx, dtlsMTU);
+#endif
+
+#ifndef NO_DH
+    if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits)
+            != WOLFSSL_SUCCESS) {
+        err_sys("Error setting minimum DH key size");
+    }
+#endif
+
+    if (usePsk) {
+#ifndef NO_PSK
+        const char *defaultCipherList = cipherList;
+
+        wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
+#ifdef WOLFSSL_TLS13
+    #if !defined(WOLFSSL_PSK_TLS13_CB) && !defined(WOLFSSL_PSK_ONE_ID)
+        wolfSSL_CTX_set_psk_client_cs_callback(ctx, my_psk_client_cs_cb);
+    #else
+        wolfSSL_CTX_set_psk_client_tls13_callback(ctx, my_psk_client_tls13_cb);
+    #endif
+#endif
+        if (defaultCipherList == NULL) {
+        #if defined(HAVE_AESGCM) && !defined(NO_DH)
+            #ifdef WOLFSSL_TLS13
+                defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                    ":DHE-PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+            #else
+                defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
+            #endif
+        #elif defined(HAVE_AESGCM) && defined(WOLFSSL_TLS13)
+                defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                    ":PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+        #elif defined(HAVE_NULL_CIPHER)
+                defaultCipherList = "PSK-NULL-SHA256";
+        #else
+                defaultCipherList = "PSK-AES128-CBC-SHA256";
+        #endif
+            if (wolfSSL_CTX_set_cipher_list(ctx, defaultCipherList)
+                                                            !=WOLFSSL_SUCCESS) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("client can't set cipher list 2");
+            }
+        }
+        wolfSSL_CTX_set_psk_callback_ctx(ctx, (void*)defaultCipherList);
+#endif
+        if (useClientCert) {
+            useClientCert = 0;
+        }
+    }
+
+    if (useAnon) {
+#ifdef HAVE_ANON
+        if (cipherList == NULL || (cipherList && useDefCipherList)) {
+            const char* defaultCipherList;
+            wolfSSL_CTX_allow_anon_cipher(ctx);
+            defaultCipherList = "ADH-AES256-GCM-SHA384:"
+                                "ADH-AES128-SHA";
+            if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList)
+                                                           != WOLFSSL_SUCCESS) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("client can't set cipher list 4");
+            }
+        }
+#endif
+        if (useClientCert) {
+            useClientCert = 0;
+        }
+    }
+
+#ifdef WOLFSSL_SCTP
+    if (dtlsSCTP)
+        wolfSSL_CTX_dtls_set_sctp(ctx);
+#endif
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
+#endif
+
+#ifdef WOLFSSL_SNIFFER
+    if (cipherList == NULL && version < 4) {
+        /* static RSA or ECC cipher suites */
+        const char* staticCipherList = "AES128-SHA:ECDH-ECDSA-AES128-SHA";
+        if (wolfSSL_CTX_set_cipher_list(ctx, staticCipherList) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("client can't set cipher list 3");
+        }
+    }
+#endif
+
+#ifdef HAVE_OCSP
+    if (useOcsp) {
+    #if defined(HAVE_IO_TIMEOUT) && defined(HAVE_HTTP_CLIENT)
+        wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC);
+    #endif
+
+        if (ocspUrl != NULL) {
+            wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
+            wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE
+                                                    | WOLFSSL_OCSP_URL_OVERRIDE);
+        }
+        else {
+            wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_CHECKALL);
+        }
+
+    #ifdef WOLFSSL_NONBLOCK_OCSP
+        wolfSSL_CTX_SetOCSP_Cb(ctx, OCSPIOCb, OCSPRespFreeCb, NULL);
+    #endif
+    }
+#endif
+
+#ifdef USER_CA_CB
+    wolfSSL_CTX_SetCACb(ctx, CaCb);
+#endif
+
+#if defined(HAVE_EXT_CACHE) && !defined(NO_SESSION_CACHE)
+    wolfSSL_CTX_sess_set_get_cb(ctx, mySessGetCb);
+    wolfSSL_CTX_sess_set_new_cb(ctx, mySessNewCb);
+    wolfSSL_CTX_sess_set_remove_cb(ctx, mySessRemCb);
+#endif
+
+#ifndef NO_CERTS
+    if (useClientCert && !loadCertKeyIntoSSLObj){
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_use_certificate_chain_buffer(ctx, client_cert_der_2048,
+            sizeof_client_cert_der_2048) != WOLFSSL_SUCCESS)
+            err_sys("can't load client cert buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert)
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load client cert file, check file and run from"
+                    " wolfSSL home dir");
+        }
+    #else
+        load_buffer(ctx, ourCert, WOLFSSL_CERT_CHAIN);
+    #endif
+    }
+
+    #ifdef HAVE_PK_CALLBACKS
+        pkCbInfo.ourKey = ourKey;
+    #endif
+    if (useClientCert && !loadCertKeyIntoSSLObj
+    #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY)
+        && !pkCallbacks
+    #endif
+    ) {
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, client_key_der_2048,
+            sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
+            err_sys("can't load client private key buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM)
+                                         != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load client private key file, check file and run "
+                    "from wolfSSL home dir");
+        }
+    #else
+        load_buffer(ctx, ourKey, WOLFSSL_KEY);
+    #endif
+    }
+
+    if (!usePsk && !useAnon && !useVerifyCb && myVerifyAction != VERIFY_FORCE_FAIL) {
+    #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        if (useCertFolder) {
+            WOLFSSL_X509_STORE      *store;
+            WOLFSSL_X509_LOOKUP     *lookup;
+            
+            store = wolfSSL_CTX_get_cert_store(ctx);
+            if (store == NULL) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("can't get WOLFSSL_X509_STORE");
+            }
+            lookup = wolfSSL_X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+            if (lookup == NULL) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("can't add lookup");
+            }
+            if (wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, caCertFolder,
+                            X509_FILETYPE_PEM, NULL) != WOLFSSL_SUCCESS) {
+                err_sys("X509_LOOKUP_ctrl w/ L_ADD_DIR failed");
+            }
+        } else {
+    #endif
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,
+            sizeof_ca_cert_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load ca buffer, Please run from wolfSSL home dir");
+        }
+    #elif !defined(TEST_LOAD_BUFFER)
+        unsigned int verify_flags = 0;
+    #ifdef TEST_BEFORE_DATE
+        verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY;
+    #endif
+        if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0, verify_flags)
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load ca file, Please run from wolfSSL home dir");
+        }
+    #else
+        load_buffer(ctx, verifyCert, WOLFSSL_CA);
+    #endif  /* !NO_FILESYSTEM */
+
+    #ifdef HAVE_ECC
+        /* load ecc verify too, echoserver uses it by default w/ ecc */
+        #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_load_verify_buffer(ctx, ca_ecc_cert_der_256,
+                sizeof_ca_ecc_cert_der_256, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load ecc ca buffer");
+        }
+        #elif !defined(TEST_LOAD_BUFFER)
+        if (wolfSSL_CTX_load_verify_locations_ex(ctx, eccCertFile, 0, verify_flags)
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load ecc ca file, Please run from wolfSSL home dir");
+        }
+        #else
+        load_buffer(ctx, eccCertFile, WOLFSSL_CA);
+        #endif /* !TEST_LOAD_BUFFER */
+    #endif /* HAVE_ECC */
+    #if defined(WOLFSSL_TRUST_PEER_CERT) && !defined(NO_FILESYSTEM)
+        if (trustCert) {
+            if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert,
+                                    WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("can't load trusted peer cert file");
+            }
+        }
+    #endif /* WOLFSSL_TRUST_PEER_CERT && !NO_FILESYSTEM */
+    #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+    }
+    #endif
+    }
+    if (useVerifyCb || myVerifyAction == VERIFY_FORCE_FAIL ||
+            myVerifyAction == VERIFY_USE_PREVERFIY) {
+        wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
+    }
+    else if (!usePsk && !useAnon && doPeerCheck == 0) {
+        wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0);
+    }
+    else if (!usePsk && !useAnon && myVerifyAction == VERIFY_OVERRIDE_DATE_ERR) {
+        wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
+    }
+#endif /* !NO_CERTS */
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevOpen(&devId);
+    if (ret < 0) {
+        printf("Async device open failed\nRunning without async\n");
+    }
+    wolfSSL_CTX_SetDevId(ctx, devId);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef HAVE_SNI
+    if (sniHostName) {
+        if (wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, sniHostName,
+                    (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("UseSNI failed");
+        }
+    }
+#endif
+#ifdef HAVE_MAX_FRAGMENT
+    if (maxFragment)
+        if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("UseMaxFragment failed");
+        }
+#endif
+#ifdef HAVE_TRUNCATED_HMAC
+    if (truncatedHMAC)
+        if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("UseTruncatedHMAC failed");
+        }
+#endif
+#ifdef HAVE_SESSION_TICKET
+    if (wolfSSL_CTX_UseSessionTicket(ctx) != WOLFSSL_SUCCESS) {
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("UseSessionTicket failed");
+    }
+#endif
+#ifdef HAVE_EXTENDED_MASTER
+    if (disableExtMasterSecret)
+        if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("DisableExtendedMasterSecret failed");
+        }
+#endif
+#if defined(HAVE_SUPPORTED_CURVES)
+    #if defined(HAVE_CURVE25519)
+    if (useX25519) {
+        if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_X25519)
+                                                           != WOLFSSL_SUCCESS) {
+            err_sys("unable to support X25519");
+        }
+    }
+    #endif /* HAVE_CURVE25519 */
+    #if defined(HAVE_CURVE448)
+    if (useX448) {
+        if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_X448)
+                                                           != WOLFSSL_SUCCESS) {
+            err_sys("unable to support X448");
+        }
+    }
+    #endif /* HAVE_CURVE448 */
+    #ifdef HAVE_ECC
+    if (useSupCurve) {
+        #if !defined(NO_ECC_SECP) && \
+            (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES))
+        if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP384R1)
+                                                           != WOLFSSL_SUCCESS) {
+            err_sys("unable to support secp384r1");
+        }
+        #endif
+        #if !defined(NO_ECC_SECP) && \
+            (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES))
+        if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_ECC_SECP256R1)
+                                                           != WOLFSSL_SUCCESS) {
+            err_sys("unable to support secp256r1");
+        }
+        #endif
+    }
+    #endif /* HAVE_ECC */
+    #ifdef HAVE_FFDHE_2048
+    if (useSupCurve) {
+        if (wolfSSL_CTX_UseSupportedCurve(ctx, WOLFSSL_FFDHE_2048)
+                                                           != WOLFSSL_SUCCESS) {
+            err_sys("unable to support FFDHE 2048");
+        }
+    }
+    #endif
+#endif /* HAVE_SUPPORTED_CURVES */
+
+#ifdef WOLFSSL_TLS13
+    if (noPskDheKe)
+        wolfSSL_CTX_no_dhe_psk(ctx);
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+    if (postHandAuth)
+        wolfSSL_CTX_allow_post_handshake_auth(ctx);
+#endif
+
+    if (benchmark) {
+        ((func_args*)args)->return_code =
+            ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP,
+                                       benchmark, resumeSession, useX25519,
+                                       useX448, helloRetry, onlyKeyShare,
+                                       version, earlyData);
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        XEXIT_T(EXIT_SUCCESS);
+    }
+
+    if (throughput) {
+        ((func_args*)args)->return_code =
+            ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP,
+                                      block, throughput, useX25519, useX448,
+                                      exitWithRet, version, onlyKeyShare);
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        if (!exitWithRet)
+            XEXIT_T(EXIT_SUCCESS);
+        else
+            goto exit;
+    }
+
+    #if defined(WOLFSSL_MDK_ARM)
+    wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0);
+    #endif
+
+    #if defined(OPENSSL_EXTRA)
+    if (wolfSSL_CTX_get_read_ahead(ctx) != 0) {
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("bad read ahead default value");
+    }
+    if (wolfSSL_CTX_set_read_ahead(ctx, 1) != WOLFSSL_SUCCESS) {
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("error setting read ahead value");
+    }
+    #endif
+
+#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
+        fprintf(stderr, "Before creating SSL\n");
+        if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
+            err_sys("ctx not using static memory");
+        if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */
+            err_sys("error printing out memory stats");
+#endif
+
+    if (doMcast) {
+#ifdef WOLFSSL_MULTICAST
+        wolfSSL_CTX_mcast_set_member_id(ctx, mcastID);
+        if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256")
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("Couldn't set multicast cipher list.");
+        }
+#endif
+    }
+
+#ifdef HAVE_PK_CALLBACKS
+    if (pkCallbacks)
+        SetupPkCallbacks(ctx);
+#endif
+
+    ssl = wolfSSL_new(ctx);
+    if (ssl == NULL) {
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("unable to get SSL object");
+    }
+
+#ifndef NO_PSK
+    if (usePsk) {
+    #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && defined(TEST_PSK_USE_SESSION)
+        SSL_set_psk_use_session_callback(ssl, my_psk_use_session_cb);
+    #endif
+    }
+#endif
+
+#ifndef NO_CERTS
+    if (useClientCert && loadCertKeyIntoSSLObj){
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_use_certificate_buffer(ssl, client_cert_der_2048,
+            sizeof_client_cert_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load client cert buffer");
+        }
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (wolfSSL_use_certificate_chain_file(ssl, ourCert)
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load client cert file, check file and run from"
+                    " wolfSSL home dir");
+        }
+    #else
+        load_ssl_buffer(ssl, ourCert, WOLFSSL_CERT_CHAIN);
+    #endif
+    }
+
+    if (loadCertKeyIntoSSLObj
+    #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY)
+        && !pkCallbacks
+    #endif
+    ) {
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, client_key_der_2048,
+            sizeof_client_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
+            err_sys("can't load client private key buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (wolfSSL_use_PrivateKey_file(ssl, ourKey, WOLFSSL_FILETYPE_PEM)
+                                         != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load client private key file, check file and run "
+                    "from wolfSSL home dir");
+        }
+    #else
+        load_ssl_buffer(ssl, ourKey, WOLFSSL_KEY);
+    #endif
+    }
+#endif /* !NO_CERTS */
+
+#ifdef OPENSSL_EXTRA
+    wolfSSL_KeepArrays(ssl);
+#endif
+
+#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
+    fprintf(stderr, "After creating SSL\n");
+    if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
+        err_sys("ctx not using static memory");
+    if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */
+            err_sys("error printing out memory stats");
+#endif
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+    if (!helloRetry && version >= 4) {
+        SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 0);
+    }
+    else {
+        wolfSSL_NoKeyShares(ssl);
+    }
+#endif
+
+    if (doMcast) {
+#ifdef WOLFSSL_MULTICAST
+        /* DTLS multicast secret for testing only */
+        #define CLI_SRV_RANDOM_SZ 32     /* RAN_LEN (see internal.h) */
+        #define PMS_SZ            512    /* ENCRYPT_LEN (see internal.h) */
+        byte pms[PMS_SZ];                /* pre master secret */
+        byte cr[CLI_SRV_RANDOM_SZ];      /* client random */
+        byte sr[CLI_SRV_RANDOM_SZ];      /* server random */
+        const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */
+
+        XMEMSET(pms, 0x23, sizeof(pms));
+        XMEMSET(cr, 0xA5, sizeof(cr));
+        XMEMSET(sr, 0x5A, sizeof(sr));
+
+        if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite)
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("unable to set mcast secret");
+        }
+#endif
+    }
+
+    #ifdef HAVE_SESSION_TICKET
+    wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session");
+    #endif
+
+#ifdef HAVE_TRUSTED_CA
+    if (trustedCaKeyId) {
+        if (wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_PRE_AGREED,
+                    NULL, 0) != WOLFSSL_SUCCESS) {
+            err_sys("UseTrustedCA failed");
+        }
+    }
+#endif
+#ifdef HAVE_ALPN
+    if (alpnList != NULL) {
+       printf("ALPN accepted protocols list : %s\n", alpnList);
+       wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
+    }
+#endif
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    if (statusRequest) {
+        if (version == 4 &&
+            (statusRequest == OCSP_STAPLINGV2 || \
+             statusRequest == OCSP_STAPLINGV2_MULTI)) {
+            err_sys("Cannot use OCSP Stapling V2 with TLSv1.3");
+        }
+
+        if (wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS)
+            err_sys("can't enable OCSP Stapling Certificate Manager");
+        if (mustStaple) {
+            if (wolfSSL_CTX_EnableOCSPMustStaple(ctx) != WOLFSSL_SUCCESS)
+                err_sys("can't enable OCSP Must Staple");
+        }
+
+        switch (statusRequest) {
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
+            case OCSP_STAPLING:
+                if (wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP,
+                               WOLFSSL_CSR_OCSP_USE_NONCE) != WOLFSSL_SUCCESS) {
+                    wolfSSL_free(ssl); ssl = NULL;
+                    wolfSSL_CTX_free(ctx); ctx = NULL;
+                    err_sys("UseCertificateStatusRequest failed");
+                }
+            break;
+        #endif
+        #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
+            case OCSP_STAPLINGV2:
+                if (wolfSSL_UseOCSPStaplingV2(ssl,
+                    WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE)
+                                                           != WOLFSSL_SUCCESS) {
+                    wolfSSL_free(ssl); ssl = NULL;
+                    wolfSSL_CTX_free(ctx); ctx = NULL;
+                    err_sys("UseCertificateStatusRequest failed");
+                }
+            break;
+            case OCSP_STAPLINGV2_MULTI:
+                if (wolfSSL_UseOCSPStaplingV2(ssl,
+                    WOLFSSL_CSR2_OCSP_MULTI, 0)
+                                                           != WOLFSSL_SUCCESS) {
+                    wolfSSL_free(ssl); ssl = NULL;
+                    wolfSSL_CTX_free(ctx); ctx = NULL;
+                    err_sys("UseCertificateStatusRequest failed");
+                }
+            break;
+        #endif
+            default:
+                err_sys("Invalid OCSP Stapling option");
+        }
+
+        wolfSSL_CTX_EnableOCSP(ctx, 0);
+    }
+#endif
+
+#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+    !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+    if (!doDhKeyCheck)
+        wolfSSL_SetEnableDhKeyTest(ssl, 0);
+#endif
+
+#ifdef HAVE_ENCRYPT_THEN_MAC
+    if (disallowETM)
+        wolfSSL_AllowEncryptThenMac(ssl, 0);
+#endif
+
+
+    tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
+    if (wolfSSL_set_fd(ssl, sockfd) != WOLFSSL_SUCCESS) {
+        wolfSSL_free(ssl); ssl = NULL;
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("error in setting fd");
+    }
+
+    /* STARTTLS */
+    if (doSTARTTLS) {
+        if (StartTLS_Init(&sockfd) != WOLFSSL_SUCCESS) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("error during STARTTLS protocol");
+        }
+    }
+
+#ifdef HAVE_CRL
+    if (disableCRL == 0 && !useVerifyCb) {
+    #if defined(HAVE_IO_TIMEOUT) && defined(HAVE_HTTP_CLIENT)
+        wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC);
+    #endif
+
+        if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != WOLFSSL_SUCCESS) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't enable crl check");
+        }
+        if (wolfSSL_LoadCRL(ssl, crlPemDir, WOLFSSL_FILETYPE_PEM, 0)
+                                                           != WOLFSSL_SUCCESS) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't load crl, check crlfile and date validity");
+        }
+        if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't set crl callback");
+        }
+    }
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (scr) {
+        if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("can't enable secure renegotiation");
+        }
+    }
+#endif
+#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+    if (atomicUser)
+        SetupAtomicUser(ctx, ssl);
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    if (pkCallbacks)
+        SetupPkCallbackContexts(ssl, &pkCbInfo);
+#endif
+    if (matchName && doPeerCheck)
+        wolfSSL_check_domain_name(ssl, domain);
+#ifndef WOLFSSL_CALLBACKS
+    if (nonBlocking) {
+#ifdef WOLFSSL_DTLS
+        if (doDTLS) {
+            wolfSSL_dtls_set_using_nonblock(ssl, 1);
+        }
+#endif
+        tcp_set_nonblocking(&sockfd);
+        ret = NonBlockingSSL_Connect(ssl);
+    }
+    else {
+#ifdef WOLFSSL_EARLY_DATA
+        if (usePsk && earlyData)
+            EarlyData(ctx, ssl, kEarlyMsg, sizeof(kEarlyMsg)-1, buffer);
+#endif
+        do {
+            err = 0; /* reset error */
+            ret = wolfSSL_connect(ssl);
+            if (ret != WOLFSSL_SUCCESS) {
+                err = wolfSSL_get_error(ssl, 0);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (err == WC_PENDING_E) {
+                    ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                    if (ret < 0) break;
+                }
+            #endif
+            }
+        } while (err == WC_PENDING_E);
+    }
+#else
+    timeoutConnect.tv_sec  = DEFAULT_TIMEOUT_SEC;
+    timeoutConnect.tv_usec = 0;
+    ret = NonBlockingSSL_Connect(ssl);  /* will keep retrying on timeout */
+#endif
+    if (ret != WOLFSSL_SUCCESS) {
+        err = wolfSSL_get_error(ssl, 0);
+        printf("wolfSSL_connect error %d, %s\n", err,
+            wolfSSL_ERR_error_string(err, buffer));
+
+        /* cleanup */
+        wolfSSL_free(ssl); ssl = NULL;
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        CloseSocket(sockfd);
+
+        if (!exitWithRet)
+            err_sys("wolfSSL_connect failed");
+        /* see note at top of README */
+        /* if you're getting an error here  */
+
+        ((func_args*)args)->return_code = err;
+        goto exit;
+    }
+
+    showPeerEx(ssl, lng_index);
+
+    /* if the caller requested a particular cipher, check here that either
+     * a canonical name of the established cipher matches the requested
+     * cipher name, or the requested cipher name is marked as an alias
+     * that matches the established cipher.
+     */
+    if (cipherList && !useDefCipherList && (! XSTRSTR(cipherList, ":"))) {
+        WOLFSSL_CIPHER* established_cipher = wolfSSL_get_current_cipher(ssl);
+        byte requested_cipherSuite0, requested_cipherSuite;
+        int requested_cipherFlags;
+        if (established_cipher &&
+            /* don't test for pseudo-ciphers like "ALL" and "DEFAULT". */
+            (wolfSSL_get_cipher_suite_from_name(cipherList,
+                                                &requested_cipherSuite0,
+                                                &requested_cipherSuite,
+                                                &requested_cipherFlags) == 0)) {
+            word32 established_cipher_id =
+                wolfSSL_CIPHER_get_id(established_cipher);
+            byte established_cipherSuite0 = (established_cipher_id >> 8) & 0xff;
+            byte established_cipherSuite = established_cipher_id & 0xff;
+            const char *established_cipher_name =
+                wolfSSL_get_cipher_name_from_suite(established_cipherSuite0,
+                                                   established_cipherSuite);
+            const char *established_cipher_name_iana =
+                wolfSSL_get_cipher_name_iana_from_suite(established_cipherSuite0,
+                                                        established_cipherSuite);
+
+            if (established_cipher_name == NULL)
+                err_sys("error looking up name of established cipher");
+
+            if (strcmp(cipherList, established_cipher_name) &&
+                ((established_cipher_name_iana == NULL) ||
+                 strcmp(cipherList, established_cipher_name_iana))) {
+                if (! (requested_cipherFlags & WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS))
+                    err_sys("Unexpected mismatch between names of requested and established ciphers.");
+                else if ((requested_cipherSuite0 != established_cipherSuite0) ||
+                         (requested_cipherSuite != established_cipherSuite))
+                    err_sys("Mismatch between IDs of requested and established ciphers.");
+            }
+        }
+    }
+
+#if defined(HAVE_OCSP) && !defined(NO_ASN_TIME)
+#ifdef HAVE_STRFTIME
+    {
+        struct tm tm;
+        char date[32];
+        ret = wolfSSL_get_ocsp_producedDate_tm(ssl, &tm);
+        if ((ret == 0) && (strftime(date, sizeof date, "%Y-%m-%d %H:%M:%S %z", &tm) > 0))
+            printf("OCSP response timestamp: %s\n", date);
+    }
+#else
+    {
+        byte date[MAX_DATE_SIZE];
+        int asn_date_format;
+        ret = wolfSSL_get_ocsp_producedDate(ssl, date, sizeof date, &asn_date_format);
+        if (ret == 0)
+            printf("OCSP response timestamp: %s (ASN.1 type %d)\n", (char *)date, asn_date_format);
+    }
+#endif
+#endif
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_SECRET_CALLBACK)
+    printf("Session timeout set to %ld seconds\n", wolfSSL_get_timeout(ssl));
+    {
+        byte*  rnd;
+        byte*  pt;
+        size_t size;
+
+        /* get size of buffer then print */
+        size = wolfSSL_get_client_random(NULL, NULL, 0);
+        if (size == 0) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("error getting client random buffer size");
+        }
+
+        rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (rnd == NULL) {
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("error creating client random buffer");
+        }
+
+        size = wolfSSL_get_client_random(ssl, rnd, size);
+        if (size == 0) {
+            XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            wolfSSL_free(ssl); ssl = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("error getting client random buffer");
+        }
+
+        printf("Client Random : ");
+        for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt);
+        printf("\n");
+        XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    }
+#endif
+
+#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \
+                             defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \
+                             defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH)))
+#if !defined(NO_SESSION_CACHE) && \
+    (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \
+        !defined(NO_FILESYSTEM)
+    #ifndef NO_BIO
+    /* print out session to stdout */
+    {
+        WOLFSSL_BIO* bio = wolfSSL_BIO_new_fp(stdout, BIO_NOCLOSE);
+        if (bio != NULL) {
+            if (wolfSSL_SESSION_print(bio, wolfSSL_get_session(ssl)) !=
+                    WOLFSSL_SUCCESS) {
+                wolfSSL_BIO_printf(bio, "BIO error printing session\n");
+            }
+        }
+        wolfSSL_BIO_free(bio);
+    }
+    #endif /* !NO_BIO */
+#endif
+#endif
+
+    if (doSTARTTLS && starttlsProt != NULL) {
+        if (XSTRNCMP(starttlsProt, "smtp", 4) == 0) {
+            if (SMTP_Shutdown(ssl, wc_shutdown) != WOLFSSL_SUCCESS) {
+                wolfSSL_free(ssl); ssl = NULL;
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("error closing STARTTLS connection");
+            }
+        }
+
+        wolfSSL_free(ssl); ssl = NULL;
+        CloseSocket(sockfd);
+
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+
+        ((func_args*)args)->return_code = 0;
+        return 0;
+    }
+
+#ifdef HAVE_ALPN
+    if (alpnList != NULL) {
+        char *protocol_name = NULL;
+        word16 protocol_nameSz = 0;
+
+        err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
+        if (err == WOLFSSL_SUCCESS)
+            printf("Received ALPN protocol : %s (%d)\n",
+                   protocol_name, protocol_nameSz);
+        else if (err == WOLFSSL_ALPN_NOT_FOUND)
+            printf("No ALPN response received (no match with server)\n");
+        else
+            printf("Getting ALPN protocol name failed\n");
+    }
+#endif
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (scr && forceScr) {
+        if (nonBlocking) {
+            if (!resumeScr) {
+                if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(ssl, 0);
+                    if (err == WOLFSSL_ERROR_WANT_READ ||
+                            err == WOLFSSL_ERROR_WANT_WRITE) {
+                        if (scrAppData) {
+                            ret = ClientWrite(ssl,
+                                    "msg sent during renegotiation",
+                             sizeof("msg sent during renegotiation") - 1,
+                                    "", 1);
+                        }
+                        else {
+                            ret = 0;
+                        }
+                        if (ret != 0) {
+                            ret = WOLFSSL_FAILURE;
+                        }
+                        else {
+                            do {
+                                if (err == APP_DATA_READY) {
+                                    if ((ret = wolfSSL_read(ssl, reply,
+                                            sizeof(reply)-1)) < 0) {
+                                        err_sys("APP DATA should be present "
+                                                "but error returned");
+                                    }
+                                    printf("Received message during "
+                                           "renegotiation: %s\n", reply);
+                                }
+                                err = 0;
+                                if ((ret = wolfSSL_connect(ssl))
+                                        != WOLFSSL_SUCCESS) {
+                                    err = wolfSSL_get_error(ssl, ret);
+                                }
+                            } while (ret != WOLFSSL_SUCCESS &&
+                                    (err == WOLFSSL_ERROR_WANT_READ ||
+                                        err == WOLFSSL_ERROR_WANT_WRITE ||
+                                        err == APP_DATA_READY));
+                        }
+
+                        if (ret != WOLFSSL_SUCCESS) {
+                            err = wolfSSL_get_error(ssl, 0);
+                            printf("wolfSSL_Rehandshake error %d, %s\n", err,
+                                wolfSSL_ERR_error_string(err, buffer));
+                            wolfSSL_free(ssl); ssl = NULL;
+                            wolfSSL_CTX_free(ctx); ctx = NULL;
+                            err_sys("non-blocking wolfSSL_Rehandshake failed");
+                        }
+                        printf("NON-BLOCKING RENEGOTIATION SUCCESSFUL\n");
+                    }
+                    else {
+                        printf("wolfSSL_Rehandshake error %d, %s\n", err,
+                            wolfSSL_ERR_error_string(err, buffer));
+                        wolfSSL_free(ssl); ssl = NULL;
+                        wolfSSL_CTX_free(ctx); ctx = NULL;
+                        err_sys("non-blocking wolfSSL_Rehandshake failed");
+                    }
+                }
+            }
+            else {
+                printf("not doing secure resumption with non-blocking");
+            }
+        } else {
+            if (!resumeScr) {
+                printf("Beginning secure renegotiation.\n");
+                if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(ssl, 0);
+#ifdef WOLFSSL_ASYNC_CRYPT
+                    while (err == WC_PENDING_E) {
+                        err = 0;
+                        ret = wolfSSL_negotiate(ssl);
+                        if (ret != WOLFSSL_SUCCESS) {
+                            err = wolfSSL_get_error(ssl, 0);
+                            if (err == WC_PENDING_E) {
+                                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                                if (ret < 0) break;
+                            }
+                        }
+                    }
+#endif
+                    if (ret != WOLFSSL_SUCCESS) {
+                        printf("err = %d, %s\n", err,
+                                        wolfSSL_ERR_error_string(err, buffer));
+                        wolfSSL_free(ssl); ssl = NULL;
+                        wolfSSL_CTX_free(ctx); ctx = NULL;
+                        err_sys("wolfSSL_Rehandshake failed");
+                    }
+                }
+                else {
+                    printf("RENEGOTIATION SUCCESSFUL\n");
+                }
+            }
+            else {
+                printf("Beginning secure resumption.\n");
+                if ((ret = wolfSSL_SecureResume(ssl)) != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(ssl, 0);
+#ifdef WOLFSSL_ASYNC_CRYPT
+                    while (err == WC_PENDING_E) {
+                        err = 0;
+                        ret = wolfSSL_negotiate(ssl);
+                        if (ret != WOLFSSL_SUCCESS) {
+                            err = wolfSSL_get_error(ssl, 0);
+                            if (err == WC_PENDING_E) {
+                                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                                if (ret < 0) break;
+                            }
+                        }
+                    }
+#endif
+                    if (ret != WOLFSSL_SUCCESS) {
+                        printf("err = %d, %s\n", err,
+                                        wolfSSL_ERR_error_string(err, buffer));
+                        wolfSSL_free(ssl); ssl = NULL;
+                        wolfSSL_CTX_free(ctx); ctx = NULL;
+                        err_sys("wolfSSL_SecureResume failed");
+                    }
+                }
+                else {
+                    printf("SECURE RESUMPTION SUCCESSFUL\n");
+                }
+            }
+        }
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+    XMEMSET(msg, 0, sizeof(msg));
+    if (sendGET) {
+        printf("SSL connect ok, sending GET...\n");
+
+        msgSz = (int)XSTRLEN(kHttpGetMsg);
+        XMEMCPY(msg, kHttpGetMsg, msgSz);
+    }
+    else {
+        msgSz = (int)XSTRLEN(kHelloMsg);
+        XMEMCPY(msg, kHelloMsg, msgSz);
+    }
+
+/* allow some time for exporting the session */
+#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+    TEST_DELAY();
+#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+#ifdef WOLFSSL_TLS13
+    if (updateKeysIVs)
+        wolfSSL_update_keys(ssl);
+#endif
+
+    err = ClientWrite(ssl, msg, msgSz, "", exitWithRet);
+    if (exitWithRet && (err != 0)) {
+        ((func_args*)args)->return_code = err;
+        wolfSSL_free(ssl); ssl = NULL;
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        goto exit;
+    }
+
+    err = ClientRead(ssl, reply, sizeof(reply)-1, 1, "", exitWithRet);
+    if (exitWithRet && (err != 0)) {
+        ((func_args*)args)->return_code = err;
+        wolfSSL_free(ssl); ssl = NULL;
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        goto exit;
+    }
+
+#if defined(WOLFSSL_TLS13)
+    if (updateKeysIVs || postHandAuth)
+        (void)ClientWrite(ssl, msg, msgSz, "", 0);
+#endif
+
+#ifndef NO_SESSION_CACHE
+    if (resumeSession) {
+        session = wolfSSL_get_session(ssl);
+    }
+#endif
+
+#if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \
+        defined(HAVE_EXT_CACHE))
+    if (session != NULL && resumeSession) {
+        flatSessionSz = wolfSSL_i2d_SSL_SESSION(session, NULL);
+        if (flatSessionSz != 0) {
+            int checkSz = wolfSSL_i2d_SSL_SESSION(session, &flatSession);
+            if (flatSession == NULL)
+                err_sys("error creating flattened session buffer");
+            if (checkSz != flatSessionSz) {
+                XFREE(flatSession, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                err_sys("flat session size check failure");
+            }
+        }
+    }
+#endif
+
+    if (dtlsUDP == 0) {           /* don't send alert after "break" command */
+        ret = wolfSSL_shutdown(ssl);
+        if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) {
+            if (tcp_select(sockfd, DEFAULT_TIMEOUT_SEC) == TEST_RECV_READY) {
+                ret = wolfSSL_shutdown(ssl); /* bidirectional shutdown */
+                if (ret == WOLFSSL_SUCCESS)
+                    printf("Bidirectional shutdown complete\n");
+            }
+            if (ret != WOLFSSL_SUCCESS)
+                printf("Bidirectional shutdown failed\n");
+        }
+    }
+#if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY)
+    if (atomicUser)
+        FreeAtomicUser(ssl);
+#endif
+
+    /* display collected statistics */
+#ifdef WOLFSSL_STATIC_MEMORY
+    if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1)
+        err_sys("static memory was not used with ssl");
+
+    fprintf(stderr, "\nprint off SSL memory stats\n");
+    fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n");
+    fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem);
+    fprintf(stderr, "current memory in use  = %d\n", ssl_stats.curMem);
+    fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc);
+    fprintf(stderr, "current connection allocs = %d\n", ssl_stats.curAlloc);
+    fprintf(stderr, "total connection allocs   = %d\n", ssl_stats.totalAlloc);
+    fprintf(stderr, "total connection frees    = %d\n\n", ssl_stats.totalFr);
+#endif
+
+    wolfSSL_free(ssl); ssl = NULL;
+    CloseSocket(sockfd);
+
+#ifndef NO_SESSION_CACHE
+    if (resumeSession) {
+        sslResume = wolfSSL_new(ctx);
+        if (sslResume == NULL) {
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("unable to get SSL object");
+        }
+
+#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+    !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+        if (!doDhKeyCheck)
+            wolfSSL_SetEnableDhKeyTest(sslResume, 0);
+#endif
+
+        if (dtlsUDP) {
+            TEST_DELAY();
+        }
+        tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume);
+        if (wolfSSL_set_fd(sslResume, sockfd) != WOLFSSL_SUCCESS) {
+            wolfSSL_free(sslResume); sslResume = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("error in setting fd");
+        }
+#ifdef HAVE_ALPN
+        if (alpnList != NULL) {
+            printf("ALPN accepted protocols list : %s\n", alpnList);
+            wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList),
+                            alpn_opt);
+        }
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+        if (scr) {
+            if (wolfSSL_UseSecureRenegotiation(sslResume) != WOLFSSL_SUCCESS) {
+                wolfSSL_free(sslResume); sslResume = NULL;
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("can't enable secure renegotiation");
+            }
+        }
+#endif
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE)
+        if (flatSession) {
+            const byte* constFlatSession = flatSession;
+            session = wolfSSL_d2i_SSL_SESSION(NULL,
+                    &constFlatSession, flatSessionSz);
+        }
+#endif
+
+        wolfSSL_set_session(sslResume, session);
+
+#if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE)
+        if (flatSession) {
+            XFREE(flatSession, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            wolfSSL_SESSION_free(session);
+        }
+#endif
+#ifdef HAVE_SESSION_TICKET
+        wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB,
+                                    (void*)"resumed session");
+#endif
+
+#ifndef WOLFSSL_CALLBACKS
+        if (nonBlocking) {
+#ifdef WOLFSSL_DTLS
+            if (doDTLS) {
+                wolfSSL_dtls_set_using_nonblock(sslResume, 1);
+            }
+#endif
+            tcp_set_nonblocking(&sockfd);
+            ret = NonBlockingSSL_Connect(sslResume);
+        }
+        else {
+    #ifdef WOLFSSL_EARLY_DATA
+        #ifndef HAVE_SESSION_TICKET
+            if (!usePsk) {
+            }
+            else
+        #endif
+            if (earlyData) {
+                EarlyData(ctx, sslResume, kEarlyMsg, sizeof(kEarlyMsg)-1, buffer);
+            }
+    #endif
+            do {
+                err = 0; /* reset error */
+                ret = wolfSSL_connect(sslResume);
+                if (ret != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(sslResume, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(sslResume,
+                                                    WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+        }
+#else
+        timeoutConnect.tv_sec  = DEFAULT_TIMEOUT_SEC;
+        timeoutConnect.tv_usec = 0;
+        ret = NonBlockingSSL_Connect(sslResume);  /* will keep retrying on timeout */
+#endif
+        if (ret != WOLFSSL_SUCCESS) {
+            printf("wolfSSL_connect resume error %d, %s\n", err,
+                wolfSSL_ERR_error_string(err, buffer));
+            wolfSSL_free(sslResume); sslResume = NULL;
+            wolfSSL_CTX_free(ctx); ctx = NULL;
+            err_sys("wolfSSL_connect resume failed");
+        }
+
+        showPeerEx(sslResume, lng_index);
+
+        if (wolfSSL_session_reused(sslResume))
+            printf("reused session id\n");
+        else
+            printf("didn't reuse session id!!!\n");
+
+#ifdef HAVE_ALPN
+        if (alpnList != NULL) {
+            char *protocol_name = NULL;
+            word16 protocol_nameSz = 0;
+
+            printf("Sending ALPN accepted list : %s\n", alpnList);
+            err = wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name,
+                                           &protocol_nameSz);
+            if (err == WOLFSSL_SUCCESS)
+                printf("Received ALPN protocol : %s (%d)\n",
+                       protocol_name, protocol_nameSz);
+            else if (err == WOLFSSL_ALPN_NOT_FOUND)
+                printf("Not received ALPN response (no match with server)\n");
+            else
+                printf("Getting ALPN protocol name failed\n");
+        }
+#endif
+
+    /* allow some time for exporting the session */
+    #ifdef WOLFSSL_SESSION_EXPORT_DEBUG
+        TEST_DELAY();
+    #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+    if (scr && forceScr) {
+        if (nonBlocking) {
+            printf("not doing secure renegotiation on example with"
+                   " nonblocking yet\n");
+        } else {
+            if (!resumeScr) {
+                printf("Beginning secure renegotiation.\n");
+                if (wolfSSL_Rehandshake(sslResume) != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(sslResume, 0);
+                    printf("err = %d, %s\n", err,
+                                    wolfSSL_ERR_error_string(err, buffer));
+                    wolfSSL_free(sslResume); sslResume = NULL;
+                    wolfSSL_CTX_free(ctx); ctx = NULL;
+                    err_sys("wolfSSL_Rehandshake failed");
+                }
+                else {
+                    printf("RENEGOTIATION SUCCESSFUL\n");
+                }
+            }
+            else {
+                printf("Beginning secure resumption.\n");
+                if (wolfSSL_SecureResume(sslResume) != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(sslResume, 0);
+                    printf("err = %d, %s\n", err,
+                                    wolfSSL_ERR_error_string(err, buffer));
+                    wolfSSL_free(sslResume); sslResume = NULL;
+                    wolfSSL_CTX_free(ctx); ctx = NULL;
+                    err_sys("wolfSSL_SecureResume failed");
+                }
+                else {
+                    printf("SECURE RESUMPTION SUCCESSFUL\n");
+                }
+            }
+        }
+    }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+        XMEMSET(msg, 0, sizeof(msg));
+        if (sendGET) {
+            msgSz = (int)XSTRLEN(kHttpGetMsg);
+            XMEMCPY(msg, kHttpGetMsg, msgSz);
+        }
+        else {
+            msgSz = (int)XSTRLEN(kResumeMsg);
+            XMEMCPY(msg, kResumeMsg, msgSz);
+        }
+        (void)ClientWrite(sslResume, msg, msgSz, " resume", 0);
+
+        (void)ClientRead(sslResume, reply, sizeof(reply)-1, sendGET,
+                         "Server resume: ", 0);
+
+        ret = wolfSSL_shutdown(sslResume);
+        if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE)
+            wolfSSL_shutdown(sslResume);    /* bidirectional shutdown */
+
+        /* display collected statistics */
+    #ifdef WOLFSSL_STATIC_MEMORY
+        if (wolfSSL_is_static_memory(sslResume, &ssl_stats) != 1)
+            err_sys("static memory was not used with ssl");
+
+        fprintf(stderr, "\nprint off SSLresume memory stats\n");
+        fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n");
+        fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem);
+        fprintf(stderr, "current memory in use  = %d\n", ssl_stats.curMem);
+        fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc);
+        fprintf(stderr, "current connection allocs = %d\n", ssl_stats.curAlloc);
+        fprintf(stderr, "total connection allocs   = %d\n", ssl_stats.totalAlloc);
+        fprintf(stderr, "total connection frees    = %d\n\n", ssl_stats.totalFr);
+    #endif
+
+        wolfSSL_free(sslResume); sslResume = NULL;
+        CloseSocket(sockfd);
+    }
+#endif /* !NO_SESSION_CACHE */
+
+    wolfSSL_CTX_free(ctx); ctx = NULL;
+
+    ((func_args*)args)->return_code = 0;
+
+exit:
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+    wolfsentry_ret = wolfsentry_shutdown(&wolfsentry);
+    if (wolfsentry_ret < 0) {
+        fprintf(stderr,
+                "wolfsentry_shutdown() returned " WOLFSENTRY_ERROR_FMT "\n",
+                WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret));
+    }
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wolfAsync_DevClose(&devId);
+#endif
+
+#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \
+                                         && defined(HAVE_STACK_SIZE)
+    wc_ecc_fp_free();  /* free per thread cache */
+#endif
+
+    /* There are use cases  when these assignments are not read. To avoid
+     * potential confusion those warnings have been handled here.
+     */
+    (void) useClientCert;
+    (void) verifyCert;
+    (void) ourCert;
+    (void) ourKey;
+    (void) useVerifyCb;
+
+#if !defined(WOLFSSL_TIRTOS)
+    return 0;
+#endif
+}
+
+#endif /* !NO_WOLFSSL_CLIENT */
+
+
+/* so overall tests can pull in test function */
+#ifndef NO_MAIN_DRIVER
+
+    int main(int argc, char** argv)
+    {
+        func_args args;
+
+
+        StartTCP();
+
+        args.argc = argc;
+        args.argv = argv;
+        args.return_code = 0;
+
+#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL) && !defined(STACK_TRAP)
+        wolfSSL_Debugging_ON();
+#endif
+        wolfSSL_Init();
+        ChangeToWolfRoot();
+
+#ifndef NO_WOLFSSL_CLIENT
+#ifdef HAVE_STACK_SIZE
+        StackSizeCheck(&args, client_test);
+#else
+        client_test(&args);
+#endif
+#else
+        printf("Client not compiled in!\n");
+#endif
+        wolfSSL_Cleanup();
+
+#ifdef HAVE_WNR
+    if (wc_FreeNetRandom() < 0)
+        err_sys("Failed to free netRandom context");
+#endif /* HAVE_WNR */
+
+        return args.return_code;
+    }
+
+    int myoptind = 0;
+    char* myoptarg = NULL;
+
+#endif /* NO_MAIN_DRIVER */
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/echoclient.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/echoclient.c
new file mode 100644
index 0000000..105b024
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/echoclient.c
@@ -0,0 +1,409 @@
+/* echoclient.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <cyassl/ctaocrypt/settings.h>
+/* let's use cyassl layer AND cyassl openssl layer */
+#include <cyassl/ssl.h>
+#include <cyassl/openssl/ssl.h>
+#ifdef CYASSL_DTLS
+    #include <cyassl/error-ssl.h>
+#endif
+
+#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+        #include <stdio.h>
+        #include <string.h>
+        #include "cmsis_os.h"
+        #include "rl_fs.h"
+        #include "rl_net.h"
+        #include "wolfssl_MDK_ARM.h"
+#endif
+
+#include <cyassl/test.h>
+
+#include <examples/echoclient/echoclient.h>
+
+#ifndef NO_WOLFSSL_CLIENT
+
+
+#ifdef NO_FILESYSTEM
+#ifdef NO_RSA
+#error currently the example only tries to load in a RSA buffer
+#endif
+#undef USE_CERT_BUFFERS_2048
+#define USE_CERT_BUFFERS_2048
+#include <wolfssl/certs_test.h>
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    static int devId = INVALID_DEVID;
+#endif
+
+
+void echoclient_test(void* args)
+{
+    SOCKET_T sockfd = 0;
+
+    FILE* fin   = stdin  ;
+    FILE* fout = stdout;
+
+#ifndef WOLFSSL_MDK_SHELL
+    int inCreated  = 0;
+    int outCreated = 0;
+#endif
+
+    char msg[1024];
+    char reply[1024+1];
+
+    SSL_METHOD* method = 0;
+    SSL_CTX*    ctx    = 0;
+    SSL*        ssl    = 0;
+
+    int ret = 0, err = 0;
+    int doDTLS = 0;
+    int doPSK = 0;
+    int sendSz;
+#ifndef WOLFSSL_MDK_SHELL
+    int argc    = 0;
+    char** argv = 0;
+#endif
+    word16 port;
+    char buffer[CYASSL_MAX_ERROR_SZ];
+
+    ((func_args*)args)->return_code = -1; /* error state */
+
+#ifndef WOLFSSL_MDK_SHELL
+    argc = ((func_args*)args)->argc;
+    argv = ((func_args*)args)->argv;
+
+    if (argc >= 2) {
+        fin  = fopen(argv[1], "r");
+        inCreated = 1;
+    }
+    if (argc >= 3) {
+        fout = fopen(argv[2], "w");
+        outCreated = 1;
+    }
+#endif
+
+    if (!fin)  err_sys("can't open input file");
+    if (!fout) err_sys("can't open output file");
+
+#ifdef CYASSL_DTLS
+    doDTLS  = 1;
+#endif
+
+#ifdef CYASSL_LEANPSK
+    doPSK = 1;
+#endif
+#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
+                                                            !defined(HAVE_ED448)
+    doPSK = 1;
+#endif
+    (void)doPSK;
+
+#if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_SHELL)
+    port = ((func_args*)args)->signal->port;
+#else
+    port = yasslPort;
+#endif
+
+#if defined(CYASSL_DTLS)
+    method  = DTLSv1_2_client_method();
+#elif !defined(NO_TLS)
+    #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SNIFFER)
+    method = CyaTLSv1_2_client_method();
+    #else
+    method = CyaSSLv23_client_method();
+    #endif
+#elif defined(WOLFSSL_ALLOW_SSLV3)
+    method = SSLv3_client_method();
+#else
+    #error "no valid client method type"
+#endif
+    ctx    = SSL_CTX_new(method);
+
+#ifndef NO_FILESYSTEM
+    #ifndef NO_RSA
+    if (SSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS)
+        err_sys("can't load ca file, Please run from wolfSSL home dir");
+    #endif
+    #ifdef HAVE_ECC
+        if (SSL_CTX_load_verify_locations(ctx, caEccCertFile, 0) != WOLFSSL_SUCCESS)
+            err_sys("can't load ca file, Please run from wolfSSL home dir");
+    #elif defined(HAVE_ED25519)
+        if (SSL_CTX_load_verify_locations(ctx, caEdCertFile, 0) != WOLFSSL_SUCCESS)
+            err_sys("can't load ca file, Please run from wolfSSL home dir");
+    #elif defined(HAVE_ED448)
+        if (SSL_CTX_load_verify_locations(ctx, caEd448CertFile, 0) != WOLFSSL_SUCCESS)
+            err_sys("can't load ca file, Please run from wolfSSL home dir");
+    #endif
+#elif !defined(NO_CERTS)
+    if (!doPSK)
+        if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,
+            sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
+            err_sys("can't load ca buffer");
+#endif
+
+#if defined(CYASSL_SNIFFER)
+    /* Only set if not running testsuite */
+    if (XSTRSTR(argv[0], "testsuite") != 0) {
+        /* don't use EDH, can't sniff tmp keys */
+        SSL_CTX_set_cipher_list(ctx, "AES256-SHA");
+    }
+#endif
+#ifndef NO_PSK
+    if (doPSK) {
+        const char *defaultCipherList;
+
+        CyaSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
+        #ifdef HAVE_NULL_CIPHER
+            defaultCipherList = "PSK-NULL-SHA256";
+        #elif defined(HAVE_AESGCM) && !defined(NO_DH)
+            #ifdef WOLFSSL_TLS13
+            defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                ":DHE-PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+            #else
+            defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
+            #endif
+        #elif defined(HAVE_AESGCM) && defined(WOLFSSL_TLS13)
+            defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                ":DHE-PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+        #else
+            defaultCipherList = "PSK-AES128-CBC-SHA256";
+        #endif
+        if (CyaSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=WOLFSSL_SUCCESS)
+            err_sys("client can't set cipher list 2");
+        wolfSSL_CTX_set_psk_callback_ctx(ctx, (void*)defaultCipherList);
+    }
+#endif
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
+#endif
+
+#if defined(WOLFSSL_MDK_ARM)
+    CyaSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, 0);
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevOpen(&devId);
+    if (ret < 0) {
+        printf("Async device open failed\nRunning without async\n");
+    }
+    wolfSSL_CTX_SetDevId(ctx, devId);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    ssl = SSL_new(ctx);
+    tcp_connect(&sockfd, yasslIP, port, doDTLS, 0, ssl);
+
+    SSL_set_fd(ssl, sockfd);
+#if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER)
+    /* let echoserver bind first, TODO: add Windows signal like pthreads does */
+    Sleep(100);
+#endif
+
+    do {
+        err = 0; /* Reset error */
+        ret = SSL_connect(ssl);
+        if (ret != WOLFSSL_SUCCESS) {
+            err = SSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("SSL_connect error %d, %s\n", err,
+            ERR_error_string(err, buffer));
+        err_sys("SSL_connect failed");
+    }
+
+    while (fgets(msg, sizeof(msg), fin) != 0) {
+
+        sendSz = (int)XSTRLEN(msg);
+
+        do {
+            err = 0; /* reset error */
+            ret = SSL_write(ssl, msg, sendSz);
+            if (ret <= 0) {
+                err = SSL_get_error(ssl, 0);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (err == WC_PENDING_E) {
+                    ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                    if (ret < 0) break;
+                }
+            #endif
+            }
+        } while (err == WC_PENDING_E);
+        if (ret != sendSz) {
+            printf("SSL_write msg error %d, %s\n", err,
+                ERR_error_string(err, buffer));
+            err_sys("SSL_write failed");
+        }
+
+        if (strncmp(msg, "quit", 4) == 0) {
+            fputs("sending server shutdown command: quit!\n", fout);
+            break;
+        }
+
+        if (strncmp(msg, "break", 5) == 0) {
+            fputs("sending server session close: break!\n", fout);
+            break;
+        }
+
+    #ifndef WOLFSSL_MDK_SHELL
+        while (sendSz)
+    #endif
+        {
+            do {
+                err = 0; /* reset error */
+                ret = SSL_read(ssl, reply, sizeof(reply)-1);
+                if (ret <= 0) {
+                    err = SSL_get_error(ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+            if (ret > 0) {
+                reply[ret] = 0;
+                fputs(reply, fout);
+                fflush(fout) ;
+                sendSz -= ret;
+            }
+#ifdef CYASSL_DTLS
+            else if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) {
+                /* This condition is OK. The packet should be dropped
+                 * silently when there is a decrypt or MAC error on
+                 * a DTLS record. */
+                sendSz = 0;
+            }
+#endif
+            else {
+                printf("SSL_read msg error %d, %s\n", err,
+                    ERR_error_string(err, buffer));
+                err_sys("SSL_read failed");
+
+            #ifndef WOLFSSL_MDK_SHELL
+                break;
+            #endif
+            }
+        }
+    }
+
+
+#ifdef CYASSL_DTLS
+    strncpy(msg, "break", 6);
+    sendSz = (int)strlen(msg);
+    /* try to tell server done */
+    do {
+        err = 0; /* reset error */
+        ret = SSL_write(ssl, msg, sendSz);
+        if (ret <= 0) {
+            err = SSL_get_error(ssl, 0);
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+    } while (err == WC_PENDING_E);
+#else
+    SSL_shutdown(ssl);
+#endif
+
+    SSL_free(ssl);
+    SSL_CTX_free(ctx);
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wolfAsync_DevClose(&devId);
+#endif
+
+    fflush(fout);
+#ifndef WOLFSSL_MDK_SHELL
+    if (inCreated)  fclose(fin);
+    if (outCreated) fclose(fout);
+#endif
+
+    CloseSocket(sockfd);
+    ((func_args*)args)->return_code = 0;
+}
+
+#endif /* !NO_WOLFSSL_CLIENT */
+
+/* so overall tests can pull in test function */
+#ifndef NO_MAIN_DRIVER
+
+    int main(int argc, char** argv)
+    {
+        func_args args;
+
+#ifdef HAVE_WNR
+        if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0)
+            err_sys("Whitewood netRandom global config failed");
+#endif
+
+        StartTCP();
+
+        args.argc = argc;
+        args.argv = argv;
+        args.return_code = 0;
+
+        CyaSSL_Init();
+#if defined(DEBUG_CYASSL) && !defined(WOLFSSL_MDK_SHELL)
+        CyaSSL_Debugging_ON();
+#endif
+#ifndef CYASSL_TIRTOS
+        ChangeToWolfRoot();
+#endif
+#ifndef NO_WOLFSSL_CLIENT
+        echoclient_test(&args);
+#endif
+
+        CyaSSL_Cleanup();
+
+#ifdef HAVE_WNR
+        if (wc_FreeNetRandom() < 0)
+            err_sys("Failed to free netRandom context");
+#endif /* HAVE_WNR */
+
+        return args.return_code;
+    }
+
+#endif /* NO_MAIN_DRIVER */
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/echoserver.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/echoserver.c
new file mode 100644
index 0000000..fc36a26
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/echoserver.c
@@ -0,0 +1,576 @@
+/* echoserver.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <cyassl/ssl.h> /* name change portability layer */
+#include <cyassl/ctaocrypt/settings.h>
+#ifdef HAVE_ECC
+    #include <cyassl/ctaocrypt/ecc.h>   /* ecc_fp_free */
+#endif
+
+#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+        #include <stdio.h>
+        #include <string.h>
+        #include "cmsis_os.h"
+        #include "rl_fs.h"
+        #include "rl_net.h"
+        #include "wolfssl_MDK_ARM.h"
+#endif
+
+#include <cyassl/ssl.h>
+#include <cyassl/test.h>
+
+#ifndef NO_MAIN_DRIVER
+    #define ECHO_OUT
+#endif
+
+#include "examples/echoserver/echoserver.h"
+
+#ifndef NO_WOLFSSL_SERVER
+
+#ifdef NO_FILESYSTEM
+#ifdef NO_RSA
+#error currently the example only tries to load in a RSA buffer
+#endif
+#undef USE_CERT_BUFFERS_2048
+#define USE_CERT_BUFFERS_2048
+#include <wolfssl/certs_test.h>
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    static int devId = INVALID_DEVID;
+#endif
+
+#define SVR_COMMAND_SIZE 256
+
+static void SignalReady(void* args, word16 port)
+{
+#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
+    /* signal ready to tcp_accept */
+    func_args* server_args = (func_args*)args;
+    tcp_ready* ready = server_args->signal;
+    pthread_mutex_lock(&ready->mutex);
+    ready->ready = 1;
+    ready->port = port;
+    pthread_cond_signal(&ready->cond);
+    pthread_mutex_unlock(&ready->mutex);
+#endif
+    (void)args;
+    (void)port;
+}
+
+
+THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
+{
+    SOCKET_T       sockfd = 0;
+    CYASSL_METHOD* method = 0;
+    CYASSL_CTX*    ctx    = 0;
+
+    int    ret = 0;
+    int    doDTLS = 0;
+    int    doPSK;
+    int    outCreated = 0;
+    int    shutDown = 0;
+    int    useAnyAddr = 0;
+    word16 port;
+    int    argc = ((func_args*)args)->argc;
+    char** argv = ((func_args*)args)->argv;
+    char   buffer[CYASSL_MAX_ERROR_SZ];
+
+#ifdef ECHO_OUT
+    FILE* fout = stdout;
+    if (argc >= 2) {
+        fout = fopen(argv[1], "w");
+        outCreated = 1;
+    }
+    if (!fout) err_sys("can't open output file");
+#endif
+    (void)outCreated;
+    (void)argc;
+    (void)argv;
+
+    ((func_args*)args)->return_code = -1; /* error state */
+
+#ifdef CYASSL_DTLS
+    doDTLS  = 1;
+#endif
+
+#if (defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
+                                !defined(HAVE_ED448)) || defined(CYASSL_LEANPSK)
+    doPSK = 1;
+#else
+    doPSK = 0;
+#endif
+
+#if defined(NO_MAIN_DRIVER) && !defined(CYASSL_SNIFFER) && \
+     !defined(WOLFSSL_MDK_SHELL) && !defined(CYASSL_TIRTOS) && \
+     !defined(USE_WINDOWS_API)
+    /* Let tcp_listen assign port */
+    port = 0;
+#else
+    /* Use default port */
+    port = wolfSSLPort;
+#endif
+
+#if defined(USE_ANY_ADDR)
+    useAnyAddr = 1;
+#endif
+
+#ifdef CYASSL_TIRTOS
+    fdOpenSession(Task_self());
+#endif
+
+    tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0);
+
+#if defined(CYASSL_DTLS)
+    method  = CyaDTLSv1_2_server_method();
+#elif !defined(NO_TLS)
+    #if (defined(WOLFSSL_TLS13) && defined(WOLFSSL_SNIFFER)) || \
+        defined(HAVE_NTRU)
+    method = CyaTLSv1_2_server_method();
+    #else
+    method = CyaSSLv23_server_method();
+    #endif
+#elif defined(WOLFSSL_ALLOW_SSLV3)
+    method = CyaSSLv3_server_method();
+#else
+    #error "no valid server method built in"
+#endif
+    ctx    = CyaSSL_CTX_new(method);
+    /* CyaSSL_CTX_set_session_cache_mode(ctx, WOLFSSL_SESS_CACHE_OFF); */
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    CyaSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
+#endif
+
+#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
+    ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
+    if (TicketInit() != 0)
+        err_sys("unable to setup Session Ticket Key context");
+    wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
+#endif
+
+#ifndef NO_FILESYSTEM
+    if (doPSK == 0) {
+    #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA)
+        /* ntru */
+        if (CyaSSL_CTX_use_certificate_file(ctx, ntruCertFile, WOLFSSL_FILETYPE_PEM)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load ntru cert file, "
+                    "Please run from wolfSSL home dir");
+
+        if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ntruKeyFile)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load ntru key file, "
+                    "Please run from wolfSSL home dir");
+    #elif defined(HAVE_ECC) && !defined(CYASSL_SNIFFER)
+        /* ecc */
+        if (CyaSSL_CTX_use_certificate_file(ctx, eccCertFile, WOLFSSL_FILETYPE_PEM)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server cert file, "
+                    "Please run from wolfSSL home dir");
+
+        if (CyaSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, WOLFSSL_FILETYPE_PEM)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server key file, "
+                    "Please run from wolfSSL home dir");
+    #elif defined(HAVE_ED25519) && !defined(CYASSL_SNIFFER)
+        /* ed25519 */
+        if (CyaSSL_CTX_use_certificate_chain_file(ctx, edCertFile)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server cert file, "
+                    "Please run from wolfSSL home dir");
+
+        if (CyaSSL_CTX_use_PrivateKey_file(ctx, edKeyFile, WOLFSSL_FILETYPE_PEM)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server key file, "
+                    "Please run from wolfSSL home dir");
+    #elif defined(HAVE_ED448) && !defined(CYASSL_SNIFFER)
+        /* ed448 */
+        if (CyaSSL_CTX_use_certificate_chain_file(ctx, ed448CertFile)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server cert file, "
+                    "Please run from wolfSSL home dir");
+
+        if (CyaSSL_CTX_use_PrivateKey_file(ctx, ed448KeyFile,
+                WOLFSSL_FILETYPE_PEM) != WOLFSSL_SUCCESS)
+            err_sys("can't load server key file, "
+                    "Please run from wolfSSL home dir");
+    #elif defined(NO_CERTS)
+        /* do nothing, just don't load cert files */
+    #else
+        /* normal */
+        if (CyaSSL_CTX_use_certificate_file(ctx, svrCertFile, WOLFSSL_FILETYPE_PEM)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server cert file, "
+                    "Please run from wolfSSL home dir");
+
+        if (CyaSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, WOLFSSL_FILETYPE_PEM)
+                != WOLFSSL_SUCCESS)
+            err_sys("can't load server key file, "
+                    "Please run from wolfSSL home dir");
+    #endif
+    } /* doPSK */
+#elif !defined(NO_CERTS)
+    if (!doPSK) {
+        if (CyaSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048,
+            sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1)
+            != WOLFSSL_SUCCESS)
+            err_sys("can't load server cert buffer");
+
+        if (CyaSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048,
+            sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1)
+            != WOLFSSL_SUCCESS)
+            err_sys("can't load server key buffer");
+    }
+#endif
+
+#if defined(CYASSL_SNIFFER)
+    /* Only set if not running testsuite */
+    if (XSTRSTR(argv[0], "testsuite") != 0) {
+        /* don't use EDH, can't sniff tmp keys */
+        CyaSSL_CTX_set_cipher_list(ctx, "AES256-SHA");
+    }
+#endif
+
+    if (doPSK) {
+#ifndef NO_PSK
+        const char *defaultCipherList;
+
+        CyaSSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);
+        CyaSSL_CTX_use_psk_identity_hint(ctx, "cyassl server");
+        #ifdef HAVE_NULL_CIPHER
+            defaultCipherList = "PSK-NULL-SHA256";
+        #elif defined(HAVE_AESGCM) && !defined(NO_DH)
+            #ifdef WOLFSSL_TLS13
+            defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                ":DHE-PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+            #else
+            defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
+            #endif
+        #elif defined(HAVE_AESGCM) && defined(WOLFSSL_TLS13)
+            defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                ":PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+        #else
+            defaultCipherList = "PSK-AES128-CBC-SHA256";
+        #endif
+        if (CyaSSL_CTX_set_cipher_list(ctx, defaultCipherList) != WOLFSSL_SUCCESS)
+            err_sys("server can't set cipher list 2");
+        wolfSSL_CTX_set_psk_callback_ctx(ctx, (void*)defaultCipherList);
+#endif
+    }
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevOpen(&devId);
+    if (ret < 0) {
+        printf("Async device open failed\nRunning without async\n");
+    }
+    wolfSSL_CTX_SetDevId(ctx, devId);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+    SignalReady(args, port);
+
+    while (!shutDown) {
+        CYASSL* ssl = NULL;
+        CYASSL* write_ssl = NULL;   /* may have separate w/ HAVE_WRITE_DUP */
+        char    command[SVR_COMMAND_SIZE+1];
+        int     echoSz = 0;
+        int     clientfd;
+        int     firstRead = 1;
+        int     gotFirstG = 0;
+        int     err = 0;
+        SOCKADDR_IN_T client;
+        socklen_t     client_len = sizeof(client);
+#ifndef CYASSL_DTLS
+        clientfd = accept(sockfd, (struct sockaddr*)&client,
+                         (ACCEPT_THIRD_T)&client_len);
+#else
+        clientfd = sockfd;
+        {
+            /* For DTLS, peek at the next datagram so we can get the client's
+             * address and set it into the ssl object later to generate the
+             * cookie. */
+            int n;
+            byte b[1500];
+            n = (int)recvfrom(clientfd, (char*)b, sizeof(b), MSG_PEEK,
+                              (struct sockaddr*)&client, &client_len);
+            if (n <= 0)
+                err_sys("recvfrom failed");
+        }
+#endif
+        if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) err_sys("tcp accept failed");
+
+        ssl = CyaSSL_new(ctx);
+        if (ssl == NULL) err_sys("SSL_new failed");
+        CyaSSL_set_fd(ssl, clientfd);
+        #ifdef CYASSL_DTLS
+            wolfSSL_dtls_set_peer(ssl, &client, client_len);
+        #endif
+        #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN)
+            CyaSSL_SetTmpDH_file(ssl, dhParamFile, WOLFSSL_FILETYPE_PEM);
+        #elif !defined(NO_DH)
+            SetDH(ssl);  /* will repick suites with DHE, higher than PSK */
+        #endif
+
+        do {
+            err = 0; /* Reset error */
+            ret = CyaSSL_accept(ssl);
+            if (ret != WOLFSSL_SUCCESS) {
+                err = CyaSSL_get_error(ssl, 0);
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                if (err == WC_PENDING_E) {
+                    ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                    if (ret < 0) break;
+                }
+            #endif
+            }
+        } while (err == WC_PENDING_E);
+        if (ret != WOLFSSL_SUCCESS) {
+            printf("SSL_accept error = %d, %s\n", err,
+                CyaSSL_ERR_error_string(err, buffer));
+            printf("SSL_accept failed\n");
+            CyaSSL_free(ssl);
+            CloseSocket(clientfd);
+            continue;
+        }
+#if defined(PEER_INFO)
+        showPeer(ssl);
+#endif
+
+#ifdef HAVE_WRITE_DUP
+        write_ssl = wolfSSL_write_dup(ssl);
+        if (write_ssl == NULL) {
+            printf("wolfSSL_write_dup failed\n");
+            CyaSSL_free(ssl);
+            CloseSocket(clientfd);
+            continue;
+        }
+#else
+        write_ssl = ssl;
+#endif
+
+        while (1) {
+            do {
+                err = 0; /* reset error */
+                ret = CyaSSL_read(ssl, command, sizeof(command)-1);
+                if (ret <= 0) {
+                    err = CyaSSL_get_error(ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+            if (ret <= 0) {
+                if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_ZERO_RETURN){
+                    printf("SSL_read echo error %d, %s!\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                }
+                break;
+            }
+
+            echoSz = ret;
+
+            if (firstRead == 1) {
+                firstRead = 0;  /* browser may send 1 byte 'G' to start */
+                if (echoSz == 1 && command[0] == 'G') {
+                    gotFirstG = 1;
+                    continue;
+                }
+            }
+            else if (gotFirstG == 1 && strncmp(command, "ET /", 4) == 0) {
+                strncpy(command, "GET", 4);
+                /* fall through to normal GET */
+            }
+
+            if ( strncmp(command, "quit", 4) == 0) {
+                printf("client sent quit command: shutting down!\n");
+                shutDown = 1;
+                break;
+            }
+            if ( strncmp(command, "break", 5) == 0) {
+                printf("client sent break command: closing session!\n");
+                break;
+            }
+#ifdef PRINT_SESSION_STATS
+            if ( strncmp(command, "printstats", 10) == 0) {
+                CyaSSL_PrintSessionStats();
+                break;
+            }
+#endif
+            if (strncmp(command, "GET", 3) == 0) {
+                const char resp[] =
+                    "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"
+                    "<html><body BGCOLOR=\"#ffffff\"><pre>\r\n"
+                    "greetings from wolfSSL\r\n</pre></body></html>\r\n\r\n";
+
+                echoSz = (int)strlen(resp) + 1;
+                if (echoSz > (int)sizeof(command)) {
+                    /* Internal error. */
+                    err_sys("HTTP response greater than buffer.");
+                }
+                strncpy(command, resp, sizeof(command));
+
+                do {
+                    err = 0; /* reset error */
+                    ret = CyaSSL_write(write_ssl, command, echoSz);
+                    if (ret <= 0) {
+                        err = CyaSSL_get_error(write_ssl, 0);
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        if (err == WC_PENDING_E) {
+                            ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW);
+                            if (ret < 0) break;
+                        }
+                    #endif
+                    }
+                } while (err == WC_PENDING_E);
+                if (ret != echoSz) {
+                    printf("SSL_write get error = %d, %s\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                    err_sys("SSL_write get failed");
+                }
+                break;
+            }
+            command[echoSz] = 0;
+
+        #ifdef ECHO_OUT
+            fputs(command, fout);
+        #endif
+
+            do {
+                err = 0; /* reset error */
+                ret = CyaSSL_write(write_ssl, command, echoSz);
+                if (ret <= 0) {
+                    err = CyaSSL_get_error(write_ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+
+            if (ret != echoSz) {
+                printf("SSL_write echo error = %d, %s\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                err_sys("SSL_write echo failed");
+            }
+        }
+#ifndef CYASSL_DTLS
+        CyaSSL_shutdown(ssl);
+#endif
+#ifdef HAVE_WRITE_DUP
+        CyaSSL_free(write_ssl);
+#endif
+        CyaSSL_free(ssl);
+        CloseSocket(clientfd);
+#ifdef CYASSL_DTLS
+        tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0);
+        SignalReady(args, port);
+#endif
+    }
+
+    CloseSocket(sockfd);
+    CyaSSL_CTX_free(ctx);
+
+#ifdef ECHO_OUT
+    if (outCreated)
+        fclose(fout);
+#endif
+
+    ((func_args*)args)->return_code = 0;
+
+#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \
+                            && defined(HAVE_THREAD_LS)
+    ecc_fp_free();  /* free per thread cache */
+#endif
+
+#ifdef CYASSL_TIRTOS
+    fdCloseSession(Task_self());
+#endif
+
+#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
+    ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
+    TicketCleanup();
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wolfAsync_DevClose(&devId);
+#endif
+
+#ifndef CYASSL_TIRTOS
+    return 0;
+#endif
+}
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+
+/* so overall tests can pull in test function */
+#ifndef NO_MAIN_DRIVER
+
+    int main(int argc, char** argv)
+    {
+        func_args args;
+
+#ifdef HAVE_WNR
+        if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0)
+            err_sys("Whitewood netRandom global config failed");
+#endif
+
+        StartTCP();
+
+        args.argc = argc;
+        args.argv = argv;
+        args.return_code = 0;
+
+        CyaSSL_Init();
+#if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL)
+        CyaSSL_Debugging_ON();
+#endif
+        ChangeToWolfRoot();
+#ifndef NO_WOLFSSL_SERVER
+        echoserver_test(&args);
+#endif
+        CyaSSL_Cleanup();
+
+#ifdef HAVE_WNR
+        if (wc_FreeNetRandom() < 0)
+            err_sys("Failed to free netRandom context");
+#endif /* HAVE_WNR */
+
+        return args.return_code;
+    }
+
+#endif /* NO_MAIN_DRIVER */
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-client-dtls.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-client-dtls.c
new file mode 100644
index 0000000..8022e50
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-client-dtls.c
@@ -0,0 +1,130 @@
+/* sctp-client-dtls.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/* wolfssl */
+#ifndef WOLFSSL_USER_SETTINGS
+    #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/ssl.h>
+
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+/* sctp */
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+/* std */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define cacert "./certs/ca-cert.pem"
+
+static int err_sys(const char* msg)
+{
+    perror(msg);
+    exit(EXIT_FAILURE);
+}
+#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */
+
+int main()
+{
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+    int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
+
+    if (sd < 0)
+        err_sys("sctp socket error");
+
+    struct sockaddr_in sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sin_family = AF_INET;
+    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sa.sin_port = htons(12345);
+
+    int ret = connect(sd, (struct sockaddr*)&sa, sizeof(sa));
+    if (ret < 0)
+        err_sys("sctp connect error");
+
+    const char* response = "hello there";
+    char buffer[80];
+
+    WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method());
+    if (ctx == NULL)
+        err_sys("ctx new dtls client failed");
+
+    ret = wolfSSL_CTX_dtls_set_sctp(ctx);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("set sctp mode failed");
+
+    ret = wolfSSL_CTX_load_verify_locations(ctx, cacert, NULL);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("ca cert error");
+
+    WOLFSSL* ssl = wolfSSL_new(ctx);
+    if (ssl == NULL)
+        err_sys("ssl new dtls client failed");
+
+    wolfSSL_set_fd(ssl, sd);
+
+    ret = wolfSSL_connect(ssl);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("ssl connect failed");
+
+    printf("TLS version is %s\n", wolfSSL_get_version(ssl));
+    printf("Cipher Suite is %s\n",
+           wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)));
+
+    wolfSSL_write(ssl, response, (int)strlen(response));
+    int got = wolfSSL_read(ssl, buffer, sizeof(buffer));
+    if (got > 0) {
+        buffer[got] = 0;
+        printf("server said: %s\n", buffer);
+    }
+
+    unsigned char bigBuf[4096];
+    unsigned int i;
+
+    for (i = 0; i < (int)sizeof(bigBuf); i++)
+        bigBuf[i] = (unsigned char)(i & 0xFF);
+    wolfSSL_write(ssl, bigBuf, sizeof(bigBuf));
+    memset(bigBuf, 0, sizeof(bigBuf));
+
+    wolfSSL_read(ssl, bigBuf, sizeof(bigBuf));
+    for (i = 0; i < sizeof(bigBuf); i++) {
+        if (bigBuf[i] != (unsigned char)(i & 0xFF)) {
+            printf("big message check fail\n");
+            break;
+        }
+    }
+
+    wolfSSL_shutdown(ssl);
+    wolfSSL_free(ssl);
+    wolfSSL_CTX_free(ctx);
+
+    close(sd);
+#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */
+
+    return 0;
+}
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-client.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-client.c
new file mode 100644
index 0000000..9a55cd2
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-client.c
@@ -0,0 +1,72 @@
+/* sctp-client.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef WOLFSSL_USER_SETTINGS
+    #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_SCTP
+
+/* sctp */
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+/* std */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#endif /* WOLFSSL_SCTP */
+
+int main()
+{
+#ifdef WOLFSSL_SCTP
+    int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
+
+    if (sd < 0)
+        perror("sctp socket error");
+
+    struct sockaddr_in sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sin_family = AF_INET;
+    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sa.sin_port = htons(12345);
+
+    int ret = connect(sd, (struct sockaddr*)&sa, sizeof(sa));
+    if (ret < 0)
+        perror("sctp connect error");
+
+    const char* msg = "hello sctp";
+    char buffer[80];
+
+    send(sd, msg, strlen(msg), 0);
+    int got = (int)recv(sd, buffer, sizeof(buffer), 0);
+    if (got > 0) {
+        buffer[got] = 0;
+        printf("server said: %s\n", buffer);
+    }
+
+    close(sd);
+#endif /* WOLFSSL_SCTP */
+    return 0;
+}
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-server-dtls.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-server-dtls.c
new file mode 100644
index 0000000..5d14ca8
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-server-dtls.c
@@ -0,0 +1,128 @@
+/* sctp-server-dtls.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+/* wolfssl */
+#ifndef WOLFSSL_USER_SETTINGS
+    #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/ssl.h>
+
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+/* sctp */
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/* std */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#define key "./certs/server-key.pem"
+#define cert "./certs/server-cert.pem"
+
+static int err_sys(const char* msg)
+{
+    perror(msg);
+    exit(EXIT_FAILURE);
+}
+#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */
+
+int main()
+{
+#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
+    int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
+
+    if (sd < 0)
+        err_sys("sctp socket error");
+
+    struct sockaddr_in sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sin_family = AF_INET;
+    sa.sin_addr.s_addr = htonl(INADDR_ANY);
+    sa.sin_port = htons(12345);
+
+    int ret = bind(sd, (struct sockaddr*)&sa, sizeof(sa));
+    if (ret < 0)
+        err_sys("sctp bind error");
+
+    listen(sd, 3);
+
+    int client_sd = accept(sd, NULL, NULL);
+    if (client_sd < 0)
+        err_sys("sctp accept error");
+
+    const char* response = "well hello to you";
+    char buffer[80];
+
+    WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method());
+    if (ctx == NULL)
+        err_sys("ctx new dtls server failed");
+
+    ret = wolfSSL_CTX_dtls_set_sctp(ctx);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("set sctp mode failed");
+
+    ret = wolfSSL_CTX_use_PrivateKey_file(ctx, key, WOLFSSL_FILETYPE_PEM);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("use private key error");
+
+    ret = wolfSSL_CTX_use_certificate_file(ctx, cert, WOLFSSL_FILETYPE_PEM);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("use cert error");
+
+    WOLFSSL* ssl = wolfSSL_new(ctx);
+    if (ssl == NULL)
+        err_sys("ssl new dtls server failed");
+
+    wolfSSL_set_fd(ssl, client_sd);
+
+    ret = wolfSSL_accept(ssl);
+    if (ret != WOLFSSL_SUCCESS)
+        err_sys("ssl accept failed");
+
+    printf("TLS version is %s\n", wolfSSL_get_version(ssl));
+    printf("Cipher Suite is %s\n",
+           wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)));
+
+    int got = wolfSSL_read(ssl, buffer, sizeof(buffer));
+    if (got > 0) {
+        buffer[got] = 0;
+        printf("client said: %s\n", buffer);
+    }
+    wolfSSL_write(ssl, response, (int)strlen(response));
+
+    unsigned char bigBuf[4096];
+
+    wolfSSL_read(ssl, bigBuf, sizeof(bigBuf));
+    wolfSSL_write(ssl, bigBuf, sizeof(bigBuf));
+
+    wolfSSL_shutdown(ssl);
+    wolfSSL_free(ssl);
+    wolfSSL_CTX_free(ctx);
+
+    close(sd);
+#endif /* WOLFSSL_SCTP && WOLFSSL_DTLS */
+    return 0;
+}
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-server.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-server.c
new file mode 100644
index 0000000..75034ca
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/sctp-server.c
@@ -0,0 +1,77 @@
+/* sctp-server.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#ifndef WOLFSSL_USER_SETTINGS
+    #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_SCTP
+/* sctp */
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/* std */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#endif /* WOLFSSL_SCTP */
+
+int main()
+{
+#ifdef WOLFSSL_SCTP
+    int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
+
+    if (sd < 0)
+        perror("sctp socket error");
+
+    struct sockaddr_in sa;
+    memset(&sa, 0, sizeof(sa));
+    sa.sin_family = AF_INET;
+    sa.sin_addr.s_addr = htonl(INADDR_ANY);
+    sa.sin_port = htons(12345);
+
+    int ret = bind(sd, (struct sockaddr*)&sa, sizeof(sa));
+    if (ret < 0)
+        perror("sctp bind error");
+
+    listen(sd, 3);
+
+    int client_sd = accept(sd, NULL, NULL);
+    if (client_sd < 0)
+        perror("sctp accept error");
+
+    const char* response = "hi there";
+    char buffer[80];
+
+    int got = (int)recv(client_sd, buffer, sizeof(buffer), 0);
+    if (got > 0) {
+        buffer[got] = 0;
+        printf("client said: %s\n", buffer);
+    }
+    send(client_sd, response, strlen(response), 0);
+
+
+    close(sd);
+#endif /* WOLFSSL_SCTP */
+    return 0;
+}
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/server.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/server.c
new file mode 100644
index 0000000..c787c2c
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/server.c
@@ -0,0 +1,3164 @@
+/* server.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#ifndef WOLFSSL_USER_SETTINGS
+    #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+
+#include <wolfssl/ssl.h> /* name change portability layer */
+
+#ifdef HAVE_ECC
+    #include <wolfssl/wolfcrypt/ecc.h>   /* wc_ecc_fp_free */
+#endif
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+#include <wolfsentry/wolfsentry.h>
+#if !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
+static const char *wolfsentry_config_path = NULL;
+#endif
+#endif /* WOLFSSL_WOLFSENTRY_HOOKS */
+
+#if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
+        #include <stdio.h>
+        #include <string.h>
+        #include "rl_fs.h"
+        #include "rl_net.h"
+#endif
+
+#ifdef NO_FILESYSTEM
+    #ifdef NO_RSA
+    #error currently the example only tries to load in a RSA buffer
+    #endif
+    #undef USE_CERT_BUFFERS_2048
+    #define USE_CERT_BUFFERS_2048
+    #include <wolfssl/certs_test.h>
+#endif
+
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/test.h>
+#include <wolfssl/error-ssl.h>
+
+#include "examples/server/server.h"
+
+#ifndef NO_WOLFSSL_SERVER
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    static int devId = INVALID_DEVID;
+#endif
+
+#define DEFAULT_TIMEOUT_SEC 2
+
+/* Note on using port 0: if the server uses port 0 to bind an ephemeral port
+ * number and is using the ready file for scripted testing, the code in
+ * test.h will write the actual port number into the ready file for use
+ * by the client. */
+
+#ifndef WOLFSSL_ALT_TEST_STRINGS
+static const char kReplyMsg[] = "I hear you fa shizzle!";
+#else
+static const char kReplyMsg[] = "I hear you fa shizzle!\n";
+#endif
+
+static const char kHttpServerMsg[] =
+    "HTTP/1.1 200 OK\r\n"
+    "Content-Type: text/html\r\n"
+    "Connection: close\r\n"
+    "Content-Length: 141\r\n"
+    "\r\n"
+    "<html>\r\n"
+    "<head>\r\n"
+    "<title>Welcome to wolfSSL!</title>\r\n"
+    "</head>\r\n"
+    "<body>\r\n"
+    "<p>wolfSSL has successfully performed handshake!</p>\r\n"
+    "</body>\r\n"
+    "</html>\r\n";
+
+/* Read needs to be largest of the client.c message strings (29) */
+#define SRV_READ_SZ    32
+
+
+int runWithErrors = 0; /* Used with -x flag to run err_sys vs. print errors */
+int catastrophic = 0; /* Use with -x flag to still exit when an error is
+                      * considered catastrophic EG the servers own cert failing
+                      * to load would be catastrophic since there would be no
+                      * cert to send to clients attempting to connect. The
+                      * server should error out completely in that case
+                      */
+static int lng_index = 0;
+
+#ifdef WOLFSSL_CALLBACKS
+    #if !defined(NO_OLD_TIMEVAL_NAME)
+        Timeval srvTo;
+    #else
+        WOLFSSL_TIMEVAL srvTo;
+    #endif
+    static int srvHandShakeCB(HandShakeInfo* info)
+    {
+        (void)info;
+        return 0;
+    }
+
+    static int srvTimeoutCB(TimeoutInfo* info)
+    {
+        (void)info;
+        return 0;
+    }
+
+#endif
+
+#ifndef NO_HANDSHAKE_DONE_CB
+    static int myHsDoneCb(WOLFSSL* ssl, void* user_ctx)
+    {
+        (void)user_ctx;
+        (void)ssl;
+
+        /* printf("Notified HandShake done\n"); */
+
+        /* return negative number to end TLS connection now */
+        return 0;
+    }
+#endif
+
+static void err_sys_ex(int out, const char* msg)
+{
+    if (out == 1) { /* if server is running w/ -x flag, print error w/o exit */
+        printf("wolfSSL error: %s\n", msg);
+        printf("Continuing server execution...\n\n");
+    } else {
+        err_sys(msg);
+    }
+}
+
+
+#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO)
+
+/* Translates return codes returned from
+ * send() and recv() if need be.
+ */
+static WC_INLINE int TranslateReturnCode(int old, int 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;
+    }
+#endif
+
+    return old;
+}
+
+static WC_INLINE int wolfSSL_LastError(void)
+{
+#ifdef USE_WINDOWS_API
+    return WSAGetLastError();
+#elif defined(EBSNET)
+    return xn_getlasterror();
+#else
+    return errno;
+#endif
+}
+
+/* wolfSSL Sock Addr */
+struct WOLFSSL_TEST_SOCKADDR {
+    unsigned int  sz; /* sockaddr size */
+    SOCKADDR_IN_T sa; /* pointer to the sockaddr_in or sockaddr_in6 */
+};
+
+typedef struct WOLFSSL_TEST_DTLS_CTX {
+    struct WOLFSSL_TEST_SOCKADDR peer;
+    int rfd;
+    int wfd;
+    int failOnce;
+    word32 blockSeq;
+} WOLFSSL_TEST_DTLS_CTX;
+
+
+static WC_INLINE int PeekSeq(const char* buf, word32* seq)
+{
+    const char* c = buf + 3;
+
+    if ((c[0] | c[1] | c[2] | c[3]) == 0) {
+        *seq = (c[4] << 24) | (c[5] << 16) | (c[6] << 8) | c[7];
+        return 1;
+    }
+
+    return 0;
+}
+
+
+/* The send embedded callback
+ *  return : nb bytes sent, or error
+ */
+static int TestEmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+    WOLFSSL_TEST_DTLS_CTX* dtlsCtx = (WOLFSSL_TEST_DTLS_CTX*)ctx;
+    int sd = dtlsCtx->wfd;
+    int sent;
+    int err;
+
+    (void)ssl;
+
+    WOLFSSL_ENTER("TestEmbedSendTo()");
+
+    if (dtlsCtx->failOnce) {
+        word32 seq = 0;
+
+        if (PeekSeq(buf, &seq) && seq == dtlsCtx->blockSeq) {
+            dtlsCtx->failOnce = 0;
+            WOLFSSL_MSG("Forcing WANT_WRITE");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+    }
+
+    sent = (int)sendto(sd, buf, sz, 0, (const SOCKADDR*)&dtlsCtx->peer.sa,
+                                                             dtlsCtx->peer.sz);
+
+    sent = TranslateReturnCode(sent, sd);
+
+    if (sent < 0) {
+        err = wolfSSL_LastError();
+        WOLFSSL_MSG("Embed Send To error");
+
+        if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
+            WOLFSSL_MSG("\tWould Block");
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+        else if (err == SOCKET_ECONNRESET) {
+            WOLFSSL_MSG("\tConnection reset");
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (err == SOCKET_EINTR) {
+            WOLFSSL_MSG("\tSocket interrupted");
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (err == SOCKET_EPIPE) {
+            WOLFSSL_MSG("\tSocket EPIPE");
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            WOLFSSL_MSG("\tGeneral error");
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return sent;
+}
+#endif /* WOLFSSL_DTLS && USE_WOLFSSL_IO */
+
+static int NonBlockingSSL_Accept(SSL* ssl)
+{
+#ifndef WOLFSSL_CALLBACKS
+    int ret = SSL_accept(ssl);
+#else
+    int ret = wolfSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo);
+#endif
+    int error = SSL_get_error(ssl, 0);
+    SOCKET_T sockfd = (SOCKET_T)SSL_get_fd(ssl);
+    int select_ret = 0;
+
+    while (ret != WOLFSSL_SUCCESS &&
+        (error == WOLFSSL_ERROR_WANT_READ || error == WOLFSSL_ERROR_WANT_WRITE
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            || error == WC_PENDING_E
+        #endif
+    )) {
+        int currTimeout = 1;
+
+        if (error == WOLFSSL_ERROR_WANT_READ) {
+            /* printf("... server would read block\n"); */
+        }
+        else if (error == WOLFSSL_ERROR_WANT_WRITE) {
+            /* printf("... server would write block\n"); */
+        }
+
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        if (error == WC_PENDING_E) {
+            ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            if (ret < 0) break;
+        }
+        else
+    #endif
+        {
+            if (error == WOLFSSL_ERROR_WANT_WRITE)
+            {
+                select_ret = tcp_select_tx(sockfd, currTimeout);
+            }
+            else {
+            #ifdef WOLFSSL_DTLS
+                currTimeout = wolfSSL_dtls_get_current_timeout(ssl);
+            #endif
+                select_ret = tcp_select(sockfd, currTimeout);
+            }
+        }
+
+        if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_SEND_READY)
+            || (select_ret == TEST_ERROR_READY)
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            || error == WC_PENDING_E
+        #endif
+        ) {
+            #ifndef WOLFSSL_CALLBACKS
+                ret = SSL_accept(ssl);
+            #else
+                ret = wolfSSL_accept_ex(ssl,
+                                    srvHandShakeCB, srvTimeoutCB, srvTo);
+            #endif
+            error = SSL_get_error(ssl, 0);
+        }
+        else if (select_ret == TEST_TIMEOUT && !wolfSSL_dtls(ssl)) {
+            error = WOLFSSL_ERROR_WANT_READ;
+        }
+    #ifdef WOLFSSL_DTLS
+        else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) &&
+                                        wolfSSL_dtls_got_timeout(ssl) >= 0) {
+            error = WOLFSSL_ERROR_WANT_READ;
+        }
+    #endif
+        else {
+            error = WOLFSSL_FATAL_ERROR;
+        }
+    }
+
+    return ret;
+}
+
+/* Echo number of bytes specified by -B arg */
+int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block,
+                   size_t throughput)
+{
+    int ret = 0, err;
+    double start = 0, rx_time = 0, tx_time = 0;
+    int select_ret, len, rx_pos;
+    size_t xfer_bytes = 0;
+    char* buffer;
+
+    buffer = (char*)malloc(block);
+    if (!buffer) {
+        err_sys_ex(runWithErrors, "Server buffer malloc failed");
+    }
+
+    while ((echoData && throughput == 0) ||
+          (!echoData && xfer_bytes < throughput))
+    {
+        select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */
+        if (select_ret == TEST_RECV_READY) {
+
+            if (throughput)
+                len = min(block, (int)(throughput - xfer_bytes));
+            else
+                len = block;
+            rx_pos = 0;
+
+            if (throughput) {
+                start = current_time(1);
+            }
+
+            /* Read data */
+            while (rx_pos < len) {
+                ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos);
+                if (ret < 0) {
+                    err = SSL_get_error(ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                    else
+                #endif
+                    if (err != WOLFSSL_ERROR_WANT_READ &&
+                                             err != WOLFSSL_ERROR_ZERO_RETURN &&
+                                             err != APP_DATA_READY) {
+                        printf("SSL_read echo error %d\n", err);
+                        err_sys_ex(runWithErrors, "SSL_read failed");
+                        break;
+                    }
+                    if (err == WOLFSSL_ERROR_ZERO_RETURN) {
+                        free(buffer);
+                        return WOLFSSL_ERROR_ZERO_RETURN;
+                    }
+                }
+                else {
+                    rx_pos += ret;
+                    if (!throughput)
+                        break;
+                }
+            }
+            if (throughput) {
+                rx_time += current_time(0) - start;
+                start = current_time(1);
+            }
+
+            /* Write data */
+            do {
+                err = 0; /* reset error */
+                ret = SSL_write(ssl, buffer, min(len, rx_pos));
+                if (ret <= 0) {
+                    err = SSL_get_error(ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+            if (ret != (int)min(len, rx_pos)) {
+                printf("SSL_write echo error %d\n", err);
+                err_sys_ex(runWithErrors, "SSL_write failed");
+            }
+
+            if (throughput) {
+                tx_time += current_time(0) - start;
+            }
+
+            xfer_bytes += len;
+        }
+    }
+
+    free(buffer);
+
+    if (throughput) {
+        printf(
+        #if !defined(__MINGW32__)
+            "wolfSSL Server Benchmark %zu bytes\n"
+        #else
+            "wolfSSL Server Benchmark %d bytes\n"
+        #endif
+            "\tRX      %8.3f ms (%8.3f MBps)\n"
+            "\tTX      %8.3f ms (%8.3f MBps)\n",
+    #if !defined(__MINGW32__)
+            throughput,
+    #else
+            (int)throughput,
+    #endif
+            rx_time * 1000, throughput / rx_time / 1024 / 1024,
+            tx_time * 1000, throughput / tx_time / 1024 / 1024
+        );
+    }
+
+    return 0;
+}
+
+static void ServerRead(WOLFSSL* ssl, char* input, int inputLen)
+{
+    int ret, err;
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+
+    /* Read data */
+    do {
+        err = 0; /* reset error */
+        ret = SSL_read(ssl, input, inputLen);
+        if (ret < 0) {
+            err = SSL_get_error(ssl, ret);
+
+        #ifdef HAVE_SECURE_RENEGOTIATION
+            if (err == APP_DATA_READY) {
+                /* If we receive a message during renegotiation
+                 * then just print it. We return the message sent
+                 * after the renegotiation. */
+                ret = SSL_read(ssl, input, inputLen);
+                if (ret >= 0) {
+                    /* null terminate message */
+                    input[ret] = '\0';
+                    printf("Client message received during "
+                           "secure renegotiation: %s\n", input);
+                    err = WOLFSSL_ERROR_WANT_READ;
+                }
+                else {
+                    err = SSL_get_error(ssl, ret);
+                }
+            }
+        #endif
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+            else
+        #endif
+        #ifdef WOLFSSL_DTLS
+            if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) {
+                printf("Dropped client's message due to a bad MAC\n");
+            }
+            else
+        #endif
+            if (err != WOLFSSL_ERROR_WANT_READ
+        #ifdef HAVE_SECURE_RENEGOTIATION
+                    && err != APP_DATA_READY
+        #endif
+            ) {
+                printf("SSL_read input error %d, %s\n", err,
+                                                 ERR_error_string(err, buffer));
+                err_sys_ex(runWithErrors, "SSL_read failed");
+            }
+        }
+        else if (SSL_get_error(ssl, 0) == 0 &&
+                            tcp_select(SSL_get_fd(ssl), 0) == TEST_RECV_READY) {
+                err = WOLFSSL_ERROR_WANT_READ;
+        }
+    } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_READ);
+    if (ret > 0) {
+        /* null terminate message */
+        input[ret] = '\0';
+        printf("Client message: %s\n", input);
+    }
+}
+
+static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen)
+{
+    int ret, err;
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+    int len;
+
+#ifdef OPENSSL_ALL
+    /* Fuzz testing expects reply split over two msgs when TLSv1.0 or below */
+    if (wolfSSL_GetVersion(ssl) <= WOLFSSL_TLSV1)
+         len = outputLen / 2;
+    else
+#endif
+        len = outputLen;
+
+    do {
+        err = 0; /* reset error */
+        ret = SSL_write(ssl, output, len);
+        if (ret <= 0) {
+            err = SSL_get_error(ssl, 0);
+
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            if (err == WC_PENDING_E) {
+                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                if (ret < 0) break;
+            }
+        #endif
+        }
+        else if (ret != outputLen) {
+            output += ret;
+            len = (outputLen -= ret);
+            err = WOLFSSL_ERROR_WANT_WRITE;
+        }
+    } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_WRITE);
+    if (ret != outputLen) {
+        printf("SSL_write msg error %d, %s\n", err,
+                                                 ERR_error_string(err, buffer));
+        err_sys_ex(runWithErrors, "SSL_write failed");
+    }
+}
+
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+#define MAX_GROUP_NUMBER 4
+static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
+                        int useX448)
+{
+    int ret;
+    int groups[MAX_GROUP_NUMBER] = {0};
+    int count = 0;
+
+    (void)useX25519;
+    (void)useX448;
+
+    WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+    if (onlyKeyShare == 2) {
+        if (useX25519) {
+    #ifdef HAVE_CURVE25519
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_X25519;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve x25519");
+            } while (ret == WC_PENDING_E);
+    #endif
+        }
+        else if (useX448) {
+    #ifdef HAVE_CURVE448
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_X448;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve x448");
+            } while (ret == WC_PENDING_E);
+    #endif
+        }
+        else {
+    #ifdef HAVE_ECC
+        #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_SECP256R1;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve secp256r1");
+            } while (ret == WC_PENDING_E);
+        #endif
+    #endif
+        }
+    }
+    if (onlyKeyShare == 1) {
+    #ifdef HAVE_FFDHE_2048
+        do {
+            ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048);
+            if (ret == WOLFSSL_SUCCESS)
+                groups[count++] = WOLFSSL_FFDHE_2048;
+        #ifdef WOLFSSL_ASYNC_CRYPT
+            else if (ret == WC_PENDING_E)
+                wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+        #endif
+            else
+                err_sys("unable to use DH 2048-bit parameters");
+        } while (ret == WC_PENDING_E);
+    #endif
+    }
+    if (count >= MAX_GROUP_NUMBER)
+        err_sys("example group array size error");
+    if (count > 0) {
+        if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS)
+            err_sys("unable to set groups");
+    }
+    WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
+}
+#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */
+
+
+/* when adding new option, please follow the steps below: */
+/*  1. add new option message in English section          */
+/*  2. increase the number of the second column           */
+/*  3. increase the array dimension                       */
+/*  4. add the same message into Japanese section         */
+/*     (will be translated later)                         */
+/*  5. add printf() into suitable position of Usage()     */
+static const char* server_usage_msg[][59] = {
+    /* English */
+    {
+        " NOTE: All files relative to wolfSSL home dir\n",               /* 0 */
+        "-? <num>    Help, print this usage\n"
+        "            0: English, 1: Japanese\n"
+        "--help      Help, in English\n",                                /* 1 */
+        "-p <num>    Port to listen on, not 0, default",                 /* 2 */
+#ifndef WOLFSSL_TLS13
+        "-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default", /* 3 */
+#else
+        "-v <num>    SSL version [0-4], SSLv3(0) - TLS1.3(4)), default", /* 3 */
+#endif
+        "-l <str>    Cipher suite list (: delimited)\n",                 /* 4 */
+        "-c <file>   Certificate file,           default",               /* 5 */
+        "-k <file>   Key file,                   default",               /* 6 */
+        "-A <file>   Certificate Authority file, default",               /* 7 */
+        "-R <file>   Create Ready file for external monitor"
+                                                     " default none\n",  /* 8 */
+#ifndef NO_DH
+        "-D <file>   Diffie-Hellman Params file, default",               /* 9 */
+        "-Z <num>    Minimum DH key bits,        default",              /* 10 */
+#endif
+#ifdef HAVE_ALPN
+        "-L <str>    Application-Layer Protocol Negotiation"
+                                                  " ({C,F}:<list>)\n",  /* 11 */
+#endif
+        "-d          Disable client cert check\n",                      /* 12 */
+        "-b          Bind to any interface instead of localhost only\n",/* 13 */
+        "-s          Use pre Shared keys\n",                            /* 14 */
+        "-u          Use UDP DTLS,"
+           " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n",       /* 15 */
+#ifdef WOLFSSL_SCTP
+        "-G          Use SCTP DTLS,"
+           " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n",       /* 16 */
+#endif
+        "-f          Fewer packets/group messages\n",                   /* 17 */
+        "-r          Allow one client Resumption\n",                    /* 18 */
+        "-N          Use Non-blocking sockets\n",                       /* 19 */
+        "-S <str>    Use Host Name Indication\n",                       /* 20 */
+        "-w          Wait for bidirectional shutdown\n",                /* 21 */
+#ifdef HAVE_OCSP
+        "-o          Perform OCSP lookup on peer certificate\n",        /* 22 */
+        "-O <url>    Perform OCSP lookup using <url> as responder\n",   /* 23 */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+        "-P          Public Key Callbacks\n",                           /* 24 */
+#endif
+#ifdef HAVE_ANON
+        "-a          Anonymous server\n",                               /* 25 */
+#endif
+#ifndef NO_PSK
+        "-I          Do not send PSK identity hint\n",                  /* 26 */
+#endif
+        "-x          Print server errors but do not close connection\n",/* 27 */
+        "-i          Loop indefinitely (allow repeated connections)\n", /* 28 */
+        "-e          Echo data mode (return raw bytes received)\n",     /* 29 */
+#ifdef HAVE_NTRU
+        "-n          Use NTRU key (needed for NTRU suites)\n",          /* 30 */
+#endif
+        "-B <num>    Benchmark throughput"
+                            " using <num> bytes and print stats\n",     /* 31 */
+#ifdef HAVE_CRL
+        "-V          Disable CRL\n",                                    /* 32 */
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+        "-E <file>   Path to load trusted peer cert\n",                 /* 33 */
+#endif
+#ifdef HAVE_WNR
+        "-q <file>   Whitewood config file,      default",              /* 34 */
+#endif
+        "-g          Return basic HTML web page\n",                     /* 35 */
+        "-C <num>    The number of connections to accept, default: 1\n",/* 36 */
+        "-H <arg>    Internal tests"
+            " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */
+        "                            loadSSL, disallowETM]\n",          /* 38 */
+#ifdef WOLFSSL_TLS13
+        "-U          Update keys and IVs before sending\n",             /* 39 */
+        "-K          Key Exchange for PSK not using (EC)DHE\n",         /* 40 */
+#ifndef NO_DH
+        "-y          Pre-generate Key Share using FFDHE_2048 only\n",   /* 41 */
+#endif
+#ifdef HAVE_ECC
+        "-Y          Pre-generate Key Share using P-256 only \n",       /* 42 */
+#endif
+#ifdef HAVE_CURVE25519
+        "-t          Pre-generate Key share using Curve25519 only\n",   /* 43 */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef HAVE_SESSION_TICKET
+#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS)
+        "-T          Do not generate session ticket\n",                 /* 44 */
+#else
+        "-T [aon]    Do not generate session ticket\n",                 /* 44 */
+        "            No option affects TLS 1.3 only, 'a' affects all"
+            " protocol versions,\n",                                    /* 45 */
+        "            'o' affects TLS 1.2 and below only\n",             /* 46 */
+        "            'n' affects TLS 1.3 only\n",                       /* 47 */
+#endif
+#endif
+#ifdef WOLFSSL_TLS13
+        "-F          Send alert if no mutual authentication\n",         /* 48 */
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+        "-Q          Request certificate from client post-handshake\n", /* 49 */
+#endif
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+        "-J          Server sends Cookie Extension containing state\n", /* 50 */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef WOLFSSL_EARLY_DATA
+        "-0          Early data read from client (0-RTT handshake)\n",  /* 51 */
+#endif
+#ifdef WOLFSSL_MULTICAST
+        "-3 <grpid>  Multicast, grpid < 256\n",                         /* 52 */
+#endif
+        "-1 <num>    Display a result by specified language."
+                             "\n            0: English, 1: Japanese\n", /* 53 */
+#ifdef HAVE_TRUSTED_CA
+        "-5          Use Trusted CA Key Indication\n",                  /* 54 */
+#endif
+        "-6          Simulate WANT_WRITE errors on every other IO send\n",
+                                                                        /* 55 */
+#ifdef HAVE_CURVE448
+        "-8          Pre-generate Key share using Curve448 only\n",     /* 56 */
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        "-9          Use hash dir look up for certificate loading\n"
+        "            loading from <wolfSSL home>/certs folder\n"
+        "            files in the folder would have the form \"hash.N\" file name\n"
+        "            e.g symbolic link to the file at certs folder\n"
+        "            ln -s client-ca.pem  `openssl x509 -in client-ca.pem -hash -noout`.0\n",
+                                                                       /* 57 */
+#endif
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
+        "--wolfsentry-config <file>    Path for JSON wolfSentry config\n",
+                                                                       /* 58 */
+#endif
+
+#ifndef WOLFSSL_TLS13
+        "-7          Set minimum downgrade protocol version [0-3] "
+        " SSLv3(0) - TLS1.2(3)\n",
+#else
+        "-7          Set minimum downgrade protocol version [0-4] "
+        " SSLv3(0) - TLS1.3(4)\n",                           /* 59 */
+#endif
+        NULL,
+    },
+#ifndef NO_MULTIBYTE_PRINT
+    /* Japanese */
+    {
+        " 注意 : 全てのファイルは"
+        " wolfSSL ホーム・ディレクトリからの相対です。\n",               /* 0 */
+        "-? <num>    ヘルプ, 使い方を表示\n"
+        "            0: 英語、 1: 日本語\n"
+        "--ヘルプ     使い方を表示, 日本語で\n",                         /* 1 */
+        "-p <num>    接続先ポート, 0は無効, 既定値",                     /* 2 */
+#ifndef WOLFSSL_TLS13
+        "-v <num>    SSL バージョン [0-3], SSLv3(0) - TLS1.2(3)),"
+                                                            " 既定値",   /* 3 */
+#else
+        "-v <num>    SSL バージョン [0-4], SSLv3(0) - TLS1.3(4)),"
+                                                            " 既定値",   /* 3 */
+#endif
+        "-l <str>    暗号スイートリスト (区切り文字 :)\n",               /* 4 */
+        "-c <file>   証明書ファイル,  既定値",                           /* 5 */
+        "-k <file>   鍵ファイル,      既定値",                           /* 6 */
+        "-A <file>   認証局ファイル,  既定値",                           /* 7 */
+        "-R <file>   外部モニタ用の準備完了ファイルを作成する。"
+                                                      "既定値  なし\n",  /* 8 */
+#ifndef NO_DH
+        "-D <file>   ディフィー・ヘルマンのパラメータファイル,"
+                                                     " 既定値",          /* 9 */
+        "-Z <num>    最小 DH 鍵 ビット, 既定値",                        /* 10 */
+#endif
+#ifdef HAVE_ALPN
+        "-L <str>    アプリケーション層プロトコルネゴシエーションを行う"
+                                                  " ({C,F}:<list>)\n",  /* 11 */
+#endif
+        "-d          クライアント認証を無効とする\n",                   /* 12 */
+        "-b          ローカルホスト以外のインターフェースへも"
+                                                "バインドする\n",       /* 13 */
+        "-s          事前共有鍵を使用する\n",                           /* 14 */
+        "-u          UDP DTLSを使用する。-v 2 を追加指定すると"
+             " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n",      /* 15 */
+#ifdef WOLFSSL_SCTP
+        "-G          SCTP DTLSを使用する。-v 2 を追加指定すると"
+              " DTLSv1, -v 3 を追加指定すると DTLSv1.2 (既定値)\n",     /* 16 */
+#endif
+        "-f          より少ないパケット/グループメッセージを使用する\n",/* 17 */
+        "-r          クライアントの再開を許可する\n",                   /* 18 */
+        "-N          ノンブロッキング・ソケットを使用する\n",           /* 19 */
+        "-S <str>    ホスト名表示を使用する\n",                         /* 20 */
+        "-w          双方向シャットダウンを待つ\n",                     /* 21 */
+#ifdef HAVE_OCSP
+        "-o          OCSPルックアップをピア証明書で実施する\n",         /* 22 */
+        "-O <url>    OCSPルックアップを、"
+                        "<url>を使用し応答者として実施する\n",          /* 23 */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+        "-P          公開鍵コールバック\n",                             /* 24 */
+#endif
+#ifdef HAVE_ANON
+        "-a          匿名サーバー\n",                                   /* 25 */
+#endif
+#ifndef NO_PSK
+        "-I          PSKアイデンティティのヒントを送信しない\n",        /* 26 */
+#endif
+        "-x          サーバーエラーを出力するが接続を切断しない\n",     /* 27 */
+        "-i          無期限にループする(繰り返し接続を許可)\n",         /* 28 */
+        "-e          エコー・データモード"
+                                   "(受け取ったバイトデータを返す)\n",  /* 29 */
+#ifdef HAVE_NTRU
+        "-n          NTRU鍵を使用する(NTRUスイートに必要)\n",           /* 30 */
+#endif
+        "-B <num>    <num> バイトを用いてのベンチマーク・スループット"
+                                          "測定と結果を出力する\n",     /* 31 */
+#ifdef HAVE_CRL
+        "-V          CRLを無効とする\n",                                /* 32 */
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+        "-E <file>   信頼出来るピアの証明書ロードの為のパス\n\n",       /* 33 */
+#endif
+#ifdef HAVE_WNR
+        "-q <file>   Whitewood コンフィグファイル,      既定値",        /* 34 */
+#endif
+        "-g          基本的な Web ページを返す\n",                      /* 35 */
+        "-C <num>    アクセプト可能な接続数を指定する。既定値: 1\n",    /* 36 */
+        "-H <arg>    内部テスト"
+            " [defCipherList, exitWithRet, verifyFail, useSupCurve,\n", /* 37 */
+        "                            loadSSL, disallowETM]\n",          /* 38 */
+#ifdef WOLFSSL_TLS13
+        "-U          データ送信前に、鍵とIVを更新する\n",               /* 39 */
+        "-K          鍵交換にPSKを使用、(EC)DHEは使用しない\n",         /* 40 */
+#ifndef NO_DH
+        "-y          FFDHE_2048のみを使用して鍵共有を事前生成する\n",   /* 41 */
+#endif
+#ifdef HAVE_ECC
+        "-Y          P-256のみを使用したキー共有の事前生成\n",          /* 42 */
+#endif
+#ifdef HAVE_CURVE25519
+        "-t          Curve25519のみを使用して鍵共有を事前生成する\n",   /* 43 */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS)
+        "-T          セッションチケットを生成しない\n",                 /* 44 */
+#else
+        "-T [aon]    セッションチケットを生成しない\n",                 /* 44 */
+        "            No option affects TLS 1.3 only, 'a' affects all"
+            " protocol versions,\n",                                    /* 45 */
+        "            'o' affects TLS 1.2 and below only\n",             /* 46 */
+        "            'n' affects TLS 1.3 only\n",                       /* 47 */
+#endif
+#ifdef WOLFSSL_TLS13
+        "-F          Send alert if no mutual authentication\n",         /* 48 */
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+        "-Q          クライアントのポストハンドシェイクから"
+                                              "証明書を要求する\n",     /* 49 */
+#endif
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+        "-J          サーバーの状態を含むTLS Cookie 拡張を送信する\n",  /* 50 */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef WOLFSSL_EARLY_DATA
+        "-0          クライアントからの Early Data 読み取り"
+                                      "(0-RTTハンドシェイク)\n",      /* 51 */
+#endif
+#ifdef WOLFSSL_MULTICAST
+        "-3 <grpid>  マルチキャスト, grpid < 256\n",                    /* 52 */
+#endif
+        "-1 <num>    指定された言語で結果を表示します。"
+                                 "\n            0: 英語、 1: 日本語\n", /* 53 */
+#ifdef HAVE_TRUSTED_CA
+        "-5          信頼できる認証局の鍵表示を使用する\n",             /* 54 */
+#endif
+        "-6          Simulate WANT_WRITE errors on every other IO send\n",
+                                                                        /* 55 */
+#ifdef HAVE_CURVE448
+        "-8          Pre-generate Key share using Curve448 only\n",     /* 56 */
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        "-9          証明書の読み込みに hash dir 機能を使用する\n"
+        "            <wolfSSL home>/certs フォルダーからロードします\n"
+        "            フォルダー中のファイルは、\"hash.N\"[N:0-9]名である必要があります\n"
+        "            以下の例ではca-cert.pemにシンボリックリンクを設定します\n"
+        "            ln -s client-ca.pem  `openssl x509 -in client-ca.pem -hash -noout`.0\n",
+                                                                        /* 57 */
+#endif
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
+        "--wolfsentry-config <file>    wolfSentry コンフィグファイル\n",
+                                                                       /* 58 */
+#endif
+#ifndef WOLFSSL_TLS13
+        "-7          最小ダウングレード可能なプロトコルバージョンを設定します [0-3] "
+        " SSLv3(0) - TLS1.2(3)\n",
+#else
+        "-7          最小ダウングレード可能なプロトコルバージョンを設定します [0-4] "
+        " SSLv3(0) - TLS1.3(4)\n",                            /* 59 */
+#endif
+        NULL,
+    },
+#endif
+};
+
+static void Usage(void)
+{
+    int msgId = 0;
+    const char** msg = server_usage_msg[lng_index];
+
+    printf("%s%s%s", "server ", LIBWOLFSSL_VERSION_STRING,
+           msg[msgId]);
+    printf("%s", msg[++msgId]);                     /* ? */
+    printf("%s %d\n", msg[++msgId], wolfSSLPort);   /* -p */
+#ifndef WOLFSSL_TLS13
+    printf("%s %d\n", msg[++msgId], SERVER_DEFAULT_VERSION); /* -v */
+#else
+    printf("%s %d\n", msg[++msgId], SERVER_DEFAULT_VERSION); /* -v */
+#endif
+    printf("%s", msg[++msgId]);     /* -l */
+    printf("%s %s\n", msg[++msgId], svrCertFile);    /* -c */
+    printf("%s %s\n", msg[++msgId], svrKeyFile);     /* -k */
+    printf("%s %s\n", msg[++msgId], cliCertFile);    /* -A */
+    printf("%s", msg[++msgId]);     /* -R */
+#ifndef NO_DH
+    printf("%s %s\n", msg[++msgId], dhParamFile);           /* -D */
+    printf("%s %d\n", msg[++msgId], DEFAULT_MIN_DHKEY_BITS);/* -Z */
+#endif
+#ifdef HAVE_ALPN
+    printf("%s", msg[++msgId]);     /* -L */
+#endif
+    printf("%s", msg[++msgId]);     /* -d */
+    printf("%s", msg[++msgId]);     /* -b */
+    printf("%s", msg[++msgId]);     /* -s */
+    printf("%s", msg[++msgId]);     /* -u */
+#ifdef WOLFSSL_SCTP
+    printf("%s", msg[++msgId]);     /* -G */
+#endif
+    printf("%s", msg[++msgId]);     /* -f */
+    printf("%s", msg[++msgId]);     /* -r */
+    printf("%s", msg[++msgId]);     /* -N */
+    printf("%s", msg[++msgId]);     /* -S */
+    printf("%s", msg[++msgId]);     /* -w */
+#ifdef HAVE_SECURE_RENEGOTIATION
+    printf("-M          Allow Secure Renegotiation\n");
+    printf("-m          Force Server Initiated Secure Renegotiation\n");
+#endif /* HAVE_SECURE_RENEGOTIATION */
+#ifdef HAVE_OCSP
+    printf("%s", msg[++msgId]);     /* -o */
+    printf("%s", msg[++msgId]);     /* -O */
+#endif
+#ifdef HAVE_PK_CALLBACKS
+    printf("%s", msg[++msgId]);     /* -P */
+#endif
+#ifdef HAVE_ANON
+    printf("%s", msg[++msgId]);     /* -a */
+#endif
+#ifndef NO_PSK
+    printf("%s", msg[++msgId]);     /* -I */
+#endif
+    printf("%s", msg[++msgId]);     /* -x */
+    printf("%s", msg[++msgId]);     /* -i */
+    printf("%s", msg[++msgId]);     /* -e */
+#ifdef HAVE_NTRU
+    printf("%s", msg[++msgId]);     /* -n */
+#endif
+    printf("%s", msg[++msgId]);     /* -B */
+#ifdef HAVE_CRL
+    printf("%s", msg[++msgId]);     /* -V */
+#endif
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    printf("%s", msg[++msgId]);     /* -E */
+#endif
+#ifdef HAVE_WNR
+    printf("%s %s\n", msg[++msgId], wnrConfig);  /* -q */
+#endif
+    printf("%s", msg[++msgId]);     /* -g */
+    printf("%s", msg[++msgId]);     /* -C */
+    printf("%s", msg[++msgId]);     /* -H */
+    printf("%s", msg[++msgId]);     /* more -H options */
+#ifdef WOLFSSL_TLS13
+    printf("%s", msg[++msgId]);     /* -U */
+    printf("%s", msg[++msgId]);     /* -K */
+#ifndef NO_DH
+    printf("%s", msg[++msgId]);     /* -y */
+#endif
+#ifdef HAVE_ECC
+    printf("%s", msg[++msgId]);     /* -Y */
+#endif
+#ifdef HAVE_CURVE25519
+    printf("%s", msg[++msgId]);     /* -t */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef HAVE_SESSION_TICKET
+    printf("%s", msg[++msgId]);     /* -T */
+    #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
+    printf("%s", msg[++msgId]);     /* -T */
+    printf("%s", msg[++msgId]);     /* -T */
+    printf("%s", msg[++msgId]);     /* -T */
+    #endif
+#endif
+#ifdef WOLFSSL_TLS13
+    printf("%s", msg[++msgId]);     /* -F */
+#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
+    printf("%s", msg[++msgId]);     /* -Q */
+#endif
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+    printf("%s", msg[++msgId]);     /* -J */
+#endif
+#endif /* WOLFSSL_TLS13 */
+#ifdef WOLFSSL_EARLY_DATA
+    printf("%s", msg[++msgId]);     /* -0 */
+#endif
+#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+    printf("-2          Disable DH Prime check\n");
+#endif
+#ifdef WOLFSSL_DTLS
+    printf("-4 <seq>    DTLS fake would-block for message seq\n");
+#endif
+#ifdef WOLFSSL_MULTICAST
+    printf("%s", msg[++msgId]);     /* -3 */
+#endif
+    printf("%s", msg[++msgId]);     /* -1 */
+#ifdef HAVE_TRUSTED_CA
+    printf("%s", msg[++msgId]);     /* -5 */
+#endif /* HAVE_TRUSTED_CA */
+    printf("%s", msg[++msgId]);     /* -6 */
+#ifdef HAVE_CURVE448
+    printf("%s", msg[++msgId]);     /* -8 */
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+    printf("%s", msg[++msgId]); /* -9 */
+#endif
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \
+    !defined(WOLFSENTRY_NO_JSON)
+    printf("%s", msg[++msgId]); /* --wolfsentry-config */
+#endif
+    printf("%s", msg[++msgId]); /* -7 */
+}
+
+THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
+{
+    SOCKET_T sockfd   = WOLFSSL_SOCKET_INVALID;
+    SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID;
+    SOCKADDR_IN_T client_addr;
+    socklen_t client_len;
+
+    wolfSSL_method_func method = NULL;
+    SSL_CTX*    ctx    = 0;
+    SSL*        ssl    = 0;
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+    wolfsentry_errcode_t wolfsentry_ret;
+#endif
+    int    minVersion = SERVER_INVALID_VERSION;
+    int    useWebServerMsg = 0;
+    char   input[SRV_READ_SZ];
+#ifndef WOLFSSL_VXWORKS
+    int    ch;
+    static const struct mygetopt_long_config long_options[] = {
+#if defined(WOLFSSL_WOLFSENTRY_HOOKS) && !defined(NO_FILESYSTEM) && \
+    !defined(WOLFSENTRY_NO_JSON)
+        { "wolfsentry-config", 1, 256 },
+#endif
+        { "help", 0, 257 },
+        { "ヘルプ", 0, 258 },
+        { 0, 0, 0 }
+    };
+#endif
+    int    version = SERVER_DEFAULT_VERSION;
+#ifndef WOLFSSL_NO_CLIENT_AUTH
+    int    doCliCertCheck = 1;
+#else
+    int    doCliCertCheck = 0;
+#endif
+#ifdef HAVE_CRL
+    int    disableCRL = 0;
+#endif
+    int    useAnyAddr = 0;
+    word16 port = wolfSSLPort;
+    int    usePsk = 0;
+    int    usePskPlus = 0;
+    int    useAnon = 0;
+    int    doDTLS = 0;
+    int    dtlsUDP = 0;
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                               defined(WOLFSSL_DTLS)
+    int    dtlsMTU = 0;
+#endif
+    int    dtlsSCTP = 0;
+    int    doMcast = 0;
+#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO)
+    int    doBlockSeq = 0;
+    WOLFSSL_TEST_DTLS_CTX dtlsCtx;
+#endif
+    int    needDH = 0;
+    int    useNtruKey   = 0;
+    int    nonBlocking  = 0;
+    int    simulateWantWrite = 0;
+    int    fewerPackets = 0;
+#ifdef HAVE_PK_CALLBACKS
+    int    pkCallbacks  = 0;
+    PkCbInfo pkCbInfo;
+#endif
+    int    wc_shutdown     = 0;
+    int    resume = 0;
+    int    resumeCount = 0;
+    int    loops = 1;
+    int    cnt = 0;
+    int    echoData = 0;
+    int    block = TEST_BUFFER_SIZE;
+    size_t throughput = 0;
+    int    minDhKeyBits  = DEFAULT_MIN_DHKEY_BITS;
+    short  minRsaKeyBits = DEFAULT_MIN_RSAKEY_BITS;
+    short  minEccKeyBits = DEFAULT_MIN_ECCKEY_BITS;
+    int    doListen = 1;
+    int    crlFlags = 0;
+    int    ret;
+    int    err = 0;
+    char*  serverReadyFile = NULL;
+    char*  alpnList = NULL;
+    unsigned char alpn_opt = 0;
+    char*  cipherList = NULL;
+    int    useDefCipherList = 0;
+    const char* verifyCert;
+    const char* ourCert;
+    const char* ourKey;
+    const char* ourDhParam = dhParamFile;
+    tcp_ready*  readySignal = NULL;
+    int    argc = ((func_args*)args)->argc;
+    char** argv = ((func_args*)args)->argv;
+
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    const char* trustCert  = NULL;
+#endif
+
+#ifndef NO_PSK
+    int sendPskIdentityHint = 1;
+#endif
+
+#ifdef HAVE_SNI
+    char*  sniHostName = NULL;
+#endif
+
+#ifdef HAVE_TRUSTED_CA
+    int trustedCaKeyId = 0;
+#endif /* HAVE_TRUSTED_CA */
+
+#ifdef HAVE_OCSP
+    int    useOcsp  = 0;
+    char*  ocspUrl  = NULL;
+#endif
+
+#ifdef HAVE_WNR
+    const char* wnrConfigFile = wnrConfig;
+#endif
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
+#ifdef WOLFSSL_TLS13
+    int noPskDheKe = 0;
+#endif
+    int updateKeysIVs = 0;
+#ifndef NO_CERTS
+    int mutualAuth = 0;
+#endif
+    int postHandAuth = 0;
+#ifdef WOLFSSL_EARLY_DATA
+    int earlyData = 0;
+#endif
+#ifdef HAVE_SECURE_RENEGOTIATION
+    int scr = 0;
+    int forceScr = 0;
+#endif /* HAVE_SECURE_RENEGOTIATION */
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+    int hrrCookie = 0;
+#endif
+    byte mcastID = 0;
+#if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+    !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+    int doDhKeyCheck = 1;
+#endif
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
+        || defined(SESSION_CERTS)
+        /* big enough to handle most cases including session certs */
+        byte memory[239936];
+    #else
+        byte memory[80000];
+    #endif
+    byte memoryIO[34500]; /* max for IO buffer (TLS packet can be 16k) */
+    WOLFSSL_MEM_CONN_STATS ssl_stats;
+    #ifdef DEBUG_WOLFSSL
+        WOLFSSL_MEM_STATS mem_stats;
+    #endif
+#endif
+#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+    int onlyKeyShare = 0;
+#endif
+#if defined(HAVE_SESSION_TICKET)
+#ifdef WOLFSSL_TLS13
+    int noTicketTls13 = 0;
+#endif
+#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
+    int noTicketTls12 = 0;
+#endif
+#endif
+    int useX25519 = 0;
+    int useX448 = 0;
+    int exitWithRet = 0;
+    int loadCertKeyIntoSSLObj = 0;
+
+#ifdef HAVE_ENCRYPT_THEN_MAC
+    int disallowETM = 0;
+#endif
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+    int useCertFolder = 0;
+#endif
+
+    ((func_args*)args)->return_code = -1; /* error state */
+
+#ifndef NO_RSA
+    verifyCert = cliCertFile;
+    ourCert    = svrCertFile;
+    ourKey     = svrKeyFile;
+#else
+    #ifdef HAVE_ECC
+        verifyCert = cliEccCertFile;
+        ourCert    = eccCertFile;
+        ourKey     = eccKeyFile;
+    #elif defined(HAVE_ED25519)
+        verifyCert = cliEdCertFile;
+        ourCert    = edCertFile;
+        ourKey     = edKeyFile;
+    #elif defined(HAVE_ED448)
+        verifyCert = cliEd448CertFile;
+        ourCert    = ed448CertFile;
+        ourKey     = ed448KeyFile;
+    #else
+        verifyCert = NULL;
+        ourCert    = NULL;
+        ourKey     = NULL;
+    #endif
+#endif
+
+    (void)needDH;
+    (void)ourKey;
+    (void)ourCert;
+    (void)ourDhParam;
+    (void)verifyCert;
+    (void)useNtruKey;
+    (void)doCliCertCheck;
+    (void)minDhKeyBits;
+    (void)minRsaKeyBits;
+    (void)minEccKeyBits;
+    (void)alpnList;
+    (void)alpn_opt;
+    (void)crlFlags;
+    (void)readySignal;
+    (void)updateKeysIVs;
+#ifndef NO_CERTS
+    (void)mutualAuth;
+#endif
+    (void)postHandAuth;
+    (void)mcastID;
+    (void)loadCertKeyIntoSSLObj;
+    (void)nonBlocking;
+
+#ifdef WOLFSSL_TIRTOS
+    fdOpenSession(Task_self());
+#endif
+
+#ifdef WOLFSSL_VXWORKS
+    useAnyAddr = 1;
+#else
+
+    /* Reinitialize the global myVerifyAction. */
+    myVerifyAction = VERIFY_OVERRIDE_ERROR;
+
+    /* Not Used: h, z, W, X, 7 */
+    while ((ch = mygetopt_long(argc, argv, "?:"
+                "abc:defgijk:l:mnop:q:rstu;v:wxy"
+                "A:B:C:D:E:FGH:IJKL:MNO:PQR:S:T;UVYZ:"
+                "01:23:4:5689"
+                "@#", long_options, 0)) != -1) {
+        switch (ch) {
+            case '?' :
+                if(myoptarg!=NULL) {
+                    lng_index = atoi(myoptarg);
+                    if(lng_index<0||lng_index>1){
+                        lng_index = 0;
+                    }
+                }
+                Usage();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 257 :
+                lng_index = 0;
+                Usage();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 258 :
+                lng_index = 1;
+                Usage();
+                XEXIT_T(EXIT_SUCCESS);
+
+            case 'x' :
+                runWithErrors = 1;
+                break;
+
+            case 'd' :
+                doCliCertCheck = 0;
+                break;
+
+            case 'V' :
+                #ifdef HAVE_CRL
+                    disableCRL = 1;
+                #endif
+                break;
+
+            case 'b' :
+                useAnyAddr = 1;
+                break;
+
+            case 's' :
+                usePsk = 1;
+                break;
+
+            case 'j' :
+                usePskPlus = 1;
+                break;
+
+            case 'n' :
+                useNtruKey = 1;
+                break;
+
+            case 'u' :
+                doDTLS  = 1;
+                dtlsUDP = 1;
+            #if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+                dtlsMTU = atoi(myoptarg);
+            #endif
+                break;
+
+            case 'G' :
+            #ifdef WOLFSSL_SCTP
+                doDTLS  = 1;
+                dtlsSCTP = 1;
+            #endif
+                break;
+
+            case 'f' :
+                fewerPackets = 1;
+                break;
+
+            case 'R' :
+                serverReadyFile = myoptarg;
+                break;
+
+            case 'r' :
+                #ifndef NO_SESSION_CACHE
+                    resume = 1;
+                #endif
+                break;
+
+            case 'P' :
+            #ifdef HAVE_PK_CALLBACKS
+                pkCallbacks = 1;
+            #endif
+                break;
+
+            case 'p' :
+                port = (word16)atoi(myoptarg);
+                break;
+
+            case 'w' :
+                wc_shutdown = 1;
+                break;
+
+            case 'v' :
+                if (myoptarg[0] == 'd') {
+                    version = SERVER_DOWNGRADE_VERSION;
+                    break;
+                }
+            #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+                else if (myoptarg[0] == 'e') {
+                    version = EITHER_DOWNGRADE_VERSION;
+                #ifndef NO_CERTS
+                    loadCertKeyIntoSSLObj = 1;
+                #endif
+                    break;
+                }
+            #endif
+                version = atoi(myoptarg);
+                if (version < 0 || version > 4) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'l' :
+                cipherList = myoptarg;
+                break;
+
+            case 'H' :
+                if (XSTRNCMP(myoptarg, "defCipherList", 13) == 0) {
+                    printf("Using default cipher list for testing\n");
+                    useDefCipherList = 1;
+                }
+                else if (XSTRNCMP(myoptarg, "exitWithRet", 11) == 0) {
+                    printf("Skip exit() for testing\n");
+                    exitWithRet = 1;
+                }
+                else if (XSTRNCMP(myoptarg, "verifyFail", 10) == 0) {
+                    printf("Verify should fail\n");
+                    myVerifyAction = VERIFY_FORCE_FAIL;
+                }
+                else if (XSTRNCMP(myoptarg, "verifyInfo", 10) == 0) {
+                    printf("Verify should use preverify (just show info)\n");
+                    myVerifyAction = VERIFY_USE_PREVERFIY;
+                }
+                else if (XSTRNCMP(myoptarg, "loadSSL", 7) == 0) {
+                    printf("Also load cert/key into wolfSSL object\n");
+                #ifndef NO_CERTS
+                    loadCertKeyIntoSSLObj = 2;
+                #endif
+                }
+                else if (XSTRNCMP(myoptarg, "loadSSLOnly", 11) == 0) {
+                    printf("Only load cert/key into wolfSSL object\n");
+                #ifndef NO_CERTS
+                    loadCertKeyIntoSSLObj = 1;
+                #endif
+                }
+                else if (XSTRNCMP(myoptarg, "disallowETM", 11) == 0) {
+                    printf("Disallow Encrypt-Then-MAC\n");
+                #ifdef HAVE_ENCRYPT_THEN_MAC
+                    disallowETM = 1;
+                #endif
+                }
+                else if (XSTRNCMP(myoptarg, "overrideDateErr", 15) == 0) {
+                #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+                    myVerifyAction = VERIFY_OVERRIDE_DATE_ERR;
+                #endif
+                }
+                else {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'A' :
+                verifyCert = myoptarg;
+                break;
+
+            case 'c' :
+                ourCert = myoptarg;
+                break;
+
+            case 'k' :
+                ourKey = myoptarg;
+                break;
+
+            case 'D' :
+                #ifndef NO_DH
+                    ourDhParam = myoptarg;
+                #endif
+                break;
+
+            case 'Z' :
+                #ifndef NO_DH
+                    minDhKeyBits = atoi(myoptarg);
+                    if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+                #endif
+                break;
+
+            case 'N':
+                nonBlocking = 1;
+                break;
+
+            case 'S' :
+                #ifdef HAVE_SNI
+                    sniHostName = myoptarg;
+                #endif
+                break;
+
+            case 'o' :
+                #ifdef HAVE_OCSP
+                    useOcsp = 1;
+                #endif
+                break;
+
+            case 'O' :
+                #ifdef HAVE_OCSP
+                    useOcsp = 1;
+                    ocspUrl = myoptarg;
+                #endif
+                break;
+
+            case 'a' :
+                #ifdef HAVE_ANON
+                    useAnon = 1;
+                #endif
+                break;
+            case 'I':
+                #ifndef NO_PSK
+                    sendPskIdentityHint = 0;
+                #endif
+                break;
+
+            case 'L' :
+                #ifdef HAVE_ALPN
+                    alpnList = myoptarg;
+
+                    if (alpnList[0] == 'C' && alpnList[1] == ':')
+                        alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
+                    else if (alpnList[0] == 'F' && alpnList[1] == ':')
+                        alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
+                    else {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+
+                    alpnList += 2;
+
+                #endif
+                break;
+
+            case 'i' :
+                loops = -1;
+                break;
+
+            case 'C' :
+                loops = atoi(myoptarg);
+                if (loops <= 0) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            case 'e' :
+                echoData = 1;
+                break;
+
+            case 'B':
+                throughput = atol(myoptarg);
+                for (; *myoptarg != '\0'; myoptarg++) {
+                    if (*myoptarg == ',') {
+                        block = atoi(myoptarg + 1);
+                        break;
+                    }
+                }
+                if (throughput == 0 || block <= 0) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+
+            #ifdef WOLFSSL_TRUST_PEER_CERT
+            case 'E' :
+                 trustCert = myoptarg;
+                break;
+            #endif
+
+            case 'q' :
+                #ifdef HAVE_WNR
+                    wnrConfigFile = myoptarg;
+                #endif
+                break;
+
+            case 'g' :
+                useWebServerMsg = 1;
+                break;
+
+            case 'y' :
+                #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) \
+                    && !defined(NO_DH)
+                    onlyKeyShare = 1;
+                #endif
+                break;
+
+            case 'Y' :
+                #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) \
+                    && defined(HAVE_ECC)
+                    onlyKeyShare = 2;
+                #endif
+                break;
+
+            case 't' :
+                #ifdef HAVE_CURVE25519
+                    useX25519 = 1;
+                    #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+                        onlyKeyShare = 2;
+                    #endif
+                #endif
+                break;
+
+            case 'K' :
+                #ifdef WOLFSSL_TLS13
+                    noPskDheKe = 1;
+                #endif
+                break;
+
+            case 'T' :
+                #if defined(HAVE_SESSION_TICKET)
+                    if (XSTRLEN(myoptarg) == 0) {
+                    #if defined(WOLFSSL_TLS13)
+                        noTicketTls13 = 1;
+                    #endif
+                    }
+                #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
+                    else if (XSTRNCMP(myoptarg, "a", 2) == 0) {
+                        noTicketTls12 = 1;
+                    #if defined(WOLFSSL_TLS13)
+                        noTicketTls13 = 1;
+                    #endif
+                    }
+                    else if (XSTRNCMP(myoptarg, "o", 2) == 0) {
+                        noTicketTls12 = 1;
+                    }
+                    else if (XSTRNCMP(myoptarg, "n", 2) == 0) {
+                    #if defined(WOLFSSL_TLS13)
+                        noTicketTls13 = 1;
+                    #endif
+                    }
+                #endif
+                    else {
+                        Usage();
+                        XEXIT_T(MY_EX_USAGE);
+                    }
+                #endif
+                break;
+
+            case 'U' :
+                #ifdef WOLFSSL_TLS13
+                    updateKeysIVs = 1;
+                #endif
+                break;
+
+        #ifndef NO_CERTS
+            case 'F' :
+                mutualAuth = 1;
+                break;
+        #endif
+
+            case 'Q' :
+            #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+                postHandAuth = 1;
+                doCliCertCheck = 0;
+            #endif
+                break;
+
+            case 'J' :
+            #ifdef WOLFSSL_SEND_HRR_COOKIE
+                hrrCookie = 1;
+            #endif
+                break;
+
+            case 'M' :
+            #ifdef HAVE_SECURE_RENEGOTIATION
+                scr = 1;
+            #endif /* HAVE_SECURE_RENEGOTIATION */
+                break;
+
+            case 'm' :
+            #ifdef HAVE_SECURE_RENEGOTIATION
+                scr = 1;
+                forceScr = 1;
+            #endif /* HAVE_SECURE_RENEGOTIATION */
+                break;
+
+            case '0' :
+            #ifdef WOLFSSL_EARLY_DATA
+                earlyData = 1;
+            #endif
+                break;
+
+            case '1' :
+                lng_index = atoi(myoptarg);
+                if(lng_index<0||lng_index>1){
+                    lng_index = 0;
+                }
+                break;
+
+            case '2' :
+               #if !defined(NO_DH) && !defined(HAVE_FIPS) && \
+                   !defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
+                    doDhKeyCheck = 0;
+                #endif
+                break;
+
+            case '3' :
+                #ifdef WOLFSSL_MULTICAST
+                    doMcast = 1;
+                    mcastID = (byte)(atoi(myoptarg) & 0xFF);
+                #endif
+                break;
+
+            case '4' :
+                #if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO)
+                    XMEMSET(&dtlsCtx, 0, sizeof(dtlsCtx));
+                    doBlockSeq = 1;
+                    dtlsCtx.blockSeq = atoi(myoptarg);
+                #endif
+                    break;
+
+            case '5' :
+            #ifdef HAVE_TRUSTED_CA
+                trustedCaKeyId = 1;
+            #endif /* HAVE_TRUSTED_CA */
+                break;
+
+            case '6' :
+                nonBlocking = 1;
+                simulateWantWrite = 1;
+                break;
+            case '7' :
+                minVersion = atoi(myoptarg);
+                if (minVersion < 0 || minVersion > 4) {
+                    Usage();
+                    XEXIT_T(MY_EX_USAGE);
+                }
+                break;
+            case '8' :
+                #ifdef HAVE_CURVE448
+                    useX448 = 1;
+                    #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+                        onlyKeyShare = 2;
+                    #endif
+                #endif
+                break;
+            case '9' :
+#if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+                    useCertFolder = 1;
+                    break;
+#endif
+            case '@' :
+            {
+#ifdef HAVE_WC_INTROSPECTION
+                const char *conf_args = wolfSSL_configure_args();
+                if (conf_args) {
+                    puts(conf_args);
+                    XEXIT_T(EXIT_SUCCESS);
+                } else {
+                    fputs("configure args not compiled in.\n",stderr);
+                    XEXIT_T(MY_EX_USAGE);
+                }
+#else
+                fputs("compiled without BUILD_INTROSPECTION.\n",stderr);
+                XEXIT_T(MY_EX_USAGE);
+#endif
+            }
+
+            case '#' :
+            {
+#ifdef HAVE_WC_INTROSPECTION
+                const char *cflags = wolfSSL_global_cflags();
+                if (cflags) {
+                    puts(cflags);
+                    XEXIT_T(EXIT_SUCCESS);
+                } else {
+                    fputs("CFLAGS not compiled in.\n",stderr);
+                    XEXIT_T(MY_EX_USAGE);
+                }
+#else
+                fputs("compiled without BUILD_INTROSPECTION.\n",stderr);
+                XEXIT_T(MY_EX_USAGE);
+#endif
+            }
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+            case 256:
+#if !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
+                wolfsentry_config_path = myoptarg;
+#endif
+                break;
+#endif
+
+            default:
+                Usage();
+                XEXIT_T(MY_EX_USAGE);
+        }
+    }
+
+    myoptind = 0;      /* reset for test cases */
+#endif /* !WOLFSSL_VXWORKS */
+
+    /* Can only use DTLS over UDP or SCTP, can't do both. */
+    if (dtlsUDP && dtlsSCTP) {
+        err_sys_ex(runWithErrors, "Cannot use DTLS with both UDP and SCTP.");
+    }
+
+    /* sort out DTLS versus TLS versions */
+    if (version == CLIENT_INVALID_VERSION) {
+        if (doDTLS)
+            version = CLIENT_DTLS_DEFAULT_VERSION;
+        else
+            version = CLIENT_DEFAULT_VERSION;
+    }
+    else {
+        if (doDTLS) {
+            if (version == 3)
+                version = -2;
+        #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+            else if (version == EITHER_DOWNGRADE_VERSION)
+                version = -3;
+        #endif
+            else
+                version = -1;
+        }
+    }
+
+#ifdef HAVE_WNR
+    if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0)
+        err_sys_ex(runWithErrors, "can't load whitewood net random config "
+                   "file");
+#endif
+
+    switch (version) {
+#ifndef NO_OLD_TLS
+    #ifdef WOLFSSL_ALLOW_SSLV3
+        case 0:
+            method = wolfSSLv3_server_method_ex;
+            break;
+    #endif
+
+    #ifndef NO_TLS
+        #ifdef WOLFSSL_ALLOW_TLSV10
+        case 1:
+            method = wolfTLSv1_server_method_ex;
+            break;
+        #endif
+
+        case 2:
+            method = wolfTLSv1_1_server_method_ex;
+            break;
+    #endif /* !NO_TLS */
+#endif /* !NO_OLD_TLS */
+
+#ifndef NO_TLS
+    #ifndef WOLFSSL_NO_TLS12
+        case 3:
+            method = wolfTLSv1_2_server_method_ex;
+            break;
+    #endif
+
+    #ifdef WOLFSSL_TLS13
+        case 4:
+            method = wolfTLSv1_3_server_method_ex;
+            break;
+    #endif
+
+        case SERVER_DOWNGRADE_VERSION:
+            method = wolfSSLv23_server_method_ex;
+            break;
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+        case EITHER_DOWNGRADE_VERSION:
+            method = wolfSSLv23_method_ex;
+            break;
+    #endif
+#endif /* NO_TLS */
+
+#ifdef WOLFSSL_DTLS
+    #ifndef NO_OLD_TLS
+        case -1:
+            method = wolfDTLSv1_server_method_ex;
+            break;
+    #endif
+
+    #ifndef WOLFSSL_NO_TLS12
+        case -2:
+            method = wolfDTLSv1_2_server_method_ex;
+            break;
+    #endif
+    #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
+        case -3:
+            method = wolfDTLSv1_2_method_ex;
+            break;
+    #endif
+#endif
+
+        default:
+            err_sys_ex(runWithErrors, "Bad SSL version");
+    }
+
+    if (method == NULL)
+        err_sys_ex(runWithErrors, "unable to get method");
+
+#ifdef WOLFSSL_STATIC_MEMORY
+    #ifdef DEBUG_WOLFSSL
+    /* print off helper buffer sizes for use with static memory
+     * printing to stderr in case of debug mode turned on */
+    fprintf(stderr, "static memory management size = %d\n",
+            wolfSSL_MemoryPaddingSz());
+    fprintf(stderr, "calculated optimum general buffer size = %d\n",
+            wolfSSL_StaticBufferSz(memory, sizeof(memory), 0));
+    fprintf(stderr, "calculated optimum IO buffer size      = %d\n",
+            wolfSSL_StaticBufferSz(memoryIO, sizeof(memoryIO),
+                                                  WOLFMEM_IO_POOL_FIXED));
+    #endif /* DEBUG_WOLFSSL */
+
+    if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory),0,1)
+            != WOLFSSL_SUCCESS)
+        err_sys_ex(catastrophic, "unable to load static memory and create ctx");
+
+    /* load in a buffer for IO */
+    if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO),
+                                 WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1)
+            != WOLFSSL_SUCCESS)
+        err_sys_ex(catastrophic, "unable to load static memory and create ctx");
+#else
+    if (method != NULL) {
+        ctx = SSL_CTX_new(method(NULL));
+    }
+#endif /* WOLFSSL_STATIC_MEMORY */
+    if (ctx == NULL)
+        err_sys_ex(catastrophic, "unable to get ctx");
+    
+    if (minVersion != SERVER_INVALID_VERSION) {
+        wolfSSL_CTX_SetMinVersion(ctx, minVersion);
+    }
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+    if (wolfsentry_setup(&wolfsentry, wolfsentry_config_path,
+                                      WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN) < 0) {
+        err_sys("unable to initialize wolfSentry");
+    }
+
+    if (wolfSSL_CTX_set_AcceptFilter(
+            ctx,
+            (NetworkFilterCallback_t)wolfSentry_NetworkFilterCallback,
+            wolfsentry) < 0) {
+        err_sys_ex(catastrophic,
+                   "unable to install wolfSentry_NetworkFilterCallback");
+    }
+#endif
+
+    if (simulateWantWrite)
+    {
+    #ifdef USE_WOLFSSL_IO
+        wolfSSL_CTX_SetIOSend(ctx, SimulateWantWriteIOSendCb);
+    #endif
+    }
+
+#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
+    ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
+    if (TicketInit() != 0)
+        err_sys_ex(catastrophic, "unable to setup Session Ticket Key context");
+    wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
+#endif
+
+#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_STATIC_EPHEMERAL)
+    /* used for testing only to set a static/fixed ephemeral key 
+        for use with the sniffer */
+#if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && \
+        (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES))
+    ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_ECDH,
+        "./certs/statickeys/ecc-secp256r1.pem", 0, WOLFSSL_FILETYPE_PEM);
+    if (ret != 0) {
+        err_sys_ex(runWithErrors, "error loading static ECDH key");
+    }
+    {
+        const byte* key = NULL;
+        word32 keySz = 0;
+        /* example for getting pointer to loaded static ephemeral key */
+        wolfSSL_CTX_get_ephemeral_key(ctx, WC_PK_TYPE_ECDH, &key, &keySz);
+        (void)key;
+        (void)keySz;
+    }
+#endif
+#ifndef NO_DH
+    ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_DH,
+        "./certs/statickeys/dh-ffdhe2048.pem", 0, WOLFSSL_FILETYPE_PEM);
+    if (ret != 0) {
+        err_sys_ex(runWithErrors, "error loading static DH key");
+    }
+#endif
+#endif /* WOLFSSL_SNIFFER && WOLFSSL_STATIC_EPHEMERAL */
+
+    if (cipherList && !useDefCipherList) {
+        if (SSL_CTX_set_cipher_list(ctx, cipherList) != WOLFSSL_SUCCESS)
+            err_sys_ex(runWithErrors, "server can't set custom cipher list");
+    }
+
+#ifdef WOLFSSL_LEANPSK
+    if (!usePsk) {
+        usePsk = 1;
+    }
+#endif
+
+#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \
+                                                            !defined(HAVE_ED448)
+    if (!usePsk) {
+        usePsk = 1;
+    }
+#endif
+
+    if (fewerPackets)
+        wolfSSL_CTX_set_group_messages(ctx);
+#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
+                                                           defined(WOLFSSL_DTLS)
+    if (dtlsMTU)
+        wolfSSL_CTX_dtls_set_mtu(ctx, dtlsMTU);
+#endif
+
+#ifdef WOLFSSL_SCTP
+    if (dtlsSCTP)
+        wolfSSL_CTX_dtls_set_sctp(ctx);
+#endif
+
+#ifdef WOLFSSL_ENCRYPTED_KEYS
+    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
+#endif
+
+#if !defined(NO_CERTS)
+    if ((!usePsk || usePskPlus) && !useAnon && !(loadCertKeyIntoSSLObj == 1)) {
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_use_certificate_chain_buffer(ctx, server_cert_der_2048,
+            sizeof_server_cert_der_2048) != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server cert buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (SSL_CTX_use_certificate_chain_file(ctx, ourCert)
+                                         != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server cert file, check file "
+                       "and run from wolfSSL home dir");
+    #else
+        /* loads cert chain file using buffer API */
+        load_buffer(ctx, ourCert, WOLFSSL_CERT_CHAIN);
+    #endif
+    }
+#endif
+
+#ifndef NO_DH
+    if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits)
+        != WOLFSSL_SUCCESS) {
+        err_sys_ex(runWithErrors, "Error setting minimum DH key size");
+    }
+#endif
+#ifndef NO_RSA
+    if (wolfSSL_CTX_SetMinRsaKey_Sz(ctx, minRsaKeyBits) != WOLFSSL_SUCCESS){
+        err_sys_ex(runWithErrors, "Error setting minimum RSA key size");
+    }
+#endif
+#ifdef HAVE_ECC
+    if (wolfSSL_CTX_SetMinEccKey_Sz(ctx, minEccKeyBits) != WOLFSSL_SUCCESS){
+        err_sys_ex(runWithErrors, "Error setting minimum ECC key size");
+    }
+#endif
+
+#ifdef HAVE_NTRU
+    if (useNtruKey) {
+        if (wolfSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
+                                != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load ntru key file, "
+                    "Please run from wolfSSL home dir");
+    }
+#endif
+#if !defined(NO_CERTS)
+    #ifdef HAVE_PK_CALLBACKS
+        pkCbInfo.ourKey = ourKey;
+    #endif
+    if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon
+        && !(loadCertKeyIntoSSLObj == 1)
+    #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY)
+        && !pkCallbacks
+    #endif /* HAVE_PK_CALLBACKS && TEST_PK_PRIVKEY */
+    ) {
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048,
+            sizeof_server_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server private key buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, WOLFSSL_FILETYPE_PEM)
+                                         != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server private key file, "
+                       "check file and run from wolfSSL home dir");
+    #else
+        /* loads private key file using buffer API */
+        load_buffer(ctx, ourKey, WOLFSSL_KEY);
+    #endif
+    }
+#endif
+
+    if (usePsk || usePskPlus) {
+#ifndef NO_PSK
+        const char *defaultCipherList = cipherList;
+
+        SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);
+    #ifdef WOLFSSL_TLS13
+        wolfSSL_CTX_set_psk_server_tls13_callback(ctx, my_psk_server_tls13_cb);
+    #endif
+        if (sendPskIdentityHint == 1)
+            SSL_CTX_use_psk_identity_hint(ctx, "cyassl server");
+
+        if (defaultCipherList == NULL && !usePskPlus) {
+        #if defined(HAVE_AESGCM) && !defined(NO_DH)
+            #ifdef WOLFSSL_TLS13
+                defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                    ":DHE-PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+            #else
+                defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
+            #endif
+                needDH = 1;
+        #elif defined(HAVE_AESGCM) && defined(WOLFSSL_TLS13)
+                defaultCipherList = "TLS13-AES128-GCM-SHA256"
+                #ifndef WOLFSSL_NO_TLS12
+                                    ":PSK-AES128-GCM-SHA256"
+                #endif
+                ;
+        #elif defined(HAVE_NULL_CIPHER)
+                defaultCipherList = "PSK-NULL-SHA256";
+        #else
+                defaultCipherList = "PSK-AES128-CBC-SHA256";
+        #endif
+            if (SSL_CTX_set_cipher_list(ctx, defaultCipherList)
+                != WOLFSSL_SUCCESS)
+                err_sys_ex(runWithErrors, "server can't set cipher list 2");
+        }
+        wolfSSL_CTX_set_psk_callback_ctx(ctx, (void*)defaultCipherList);
+#endif /* !NO_PSK */
+    }
+#ifndef NO_CERTS
+    if (mutualAuth)
+        wolfSSL_CTX_mutual_auth(ctx, 1);
+#endif
+
+
+#ifdef HAVE_ECC
+    /* Use ECDHE key size that matches long term key.
+     * Zero means use ctx->privateKeySz.
+     * Default ECDHE_SIZE is 32 bytes
+     */
+    if (wolfSSL_CTX_SetTmpEC_DHE_Sz(ctx, 0) != WOLFSSL_SUCCESS){
+        err_sys_ex(runWithErrors, "Error setting ECDHE size");
+    }
+#endif
+
+    if (useAnon) {
+#ifdef HAVE_ANON
+        wolfSSL_CTX_allow_anon_cipher(ctx);
+        if (cipherList == NULL || (cipherList && useDefCipherList)) {
+            const char* defaultCipherList;
+            defaultCipherList = "ADH-AES256-GCM-SHA384:"
+                                "ADH-AES128-SHA";
+            if (SSL_CTX_set_cipher_list(ctx, defaultCipherList)
+                                                            != WOLFSSL_SUCCESS)
+                err_sys_ex(runWithErrors, "server can't set cipher list 4");
+        }
+#endif
+    }
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+    /* if not using PSK, verify peer with certs
+       if using PSK Plus then verify peer certs except PSK suites */
+    if (doCliCertCheck && (usePsk == 0 || usePskPlus) && useAnon == 0) {
+        unsigned int verify_flags = 0;
+        SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER |
+                            (usePskPlus ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK :
+                                WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT),
+                  (myVerifyAction == VERIFY_OVERRIDE_DATE_ERR ||
+                   myVerifyAction == VERIFY_FORCE_FAIL) ? myVerify : NULL);
+
+    #ifdef TEST_BEFORE_DATE
+        verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY;
+    #endif
+    #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+    !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        if (useCertFolder) {
+            WOLFSSL_X509_STORE      *store;
+            WOLFSSL_X509_LOOKUP     *lookup;
+            
+            store = wolfSSL_CTX_get_cert_store(ctx);
+            if (store == NULL) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("can't get WOLFSSL_X509_STORE");
+            }
+            lookup = wolfSSL_X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+            if (lookup == NULL) {
+                wolfSSL_CTX_free(ctx); ctx = NULL;
+                err_sys("can't add lookup");
+            }
+            if (wolfSSL_X509_LOOKUP_ctrl(lookup, WOLFSSL_X509_L_ADD_DIR, caCertFolder,
+                            X509_FILETYPE_PEM, NULL) != WOLFSSL_SUCCESS) {
+                err_sys("X509_LOOKUP_ctrl w/ L_ADD_DIR failed");
+            }
+        } else {
+    #endif
+        if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0,
+            verify_flags) != WOLFSSL_SUCCESS) {
+            err_sys_ex(catastrophic,
+                       "can't load ca file, Please run from wolfSSL home dir");
+        }
+        #ifdef WOLFSSL_TRUST_PEER_CERT
+        if (trustCert) {
+            if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert,
+                                                   WOLFSSL_FILETYPE_PEM))
+                                                   != WOLFSSL_SUCCESS) {
+                err_sys_ex(runWithErrors, "can't load trusted peer cert file");
+            }
+        }
+        #endif /* WOLFSSL_TRUST_PEER_CERT */
+    #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
+        (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
+        !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
+        }
+    #endif
+   }
+#endif
+
+#ifdef WOLFSSL_SNIFFER
+    if (cipherList == NULL && version < 4) {
+        /* static RSA or static ECC cipher suites */
+        const char* staticCipherList = "AES128-SHA:ECDH-ECDSA-AES128-SHA";
+        if (SSL_CTX_set_cipher_list(ctx, staticCipherList) != WOLFSSL_SUCCESS) {
+            err_sys_ex(runWithErrors, "server can't set cipher list 3");
+        }
+    }
+#endif
+
+#ifdef HAVE_SNI
+    if (sniHostName)
+        if (wolfSSL_CTX_UseSNI(ctx, WOLFSSL_SNI_HOST_NAME, sniHostName,
+                    (word16) XSTRLEN(sniHostName)) != WOLFSSL_SUCCESS)
+            err_sys_ex(runWithErrors, "UseSNI failed");
+#endif
+
+#ifdef USE_WINDOWS_API
+    if (port == 0) {
+        /* Generate random port for testing */
+        port = GetRandomPort();
+    }
+#endif /* USE_WINDOWS_API */
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    ret = wolfAsync_DevOpen(&devId);
+    if (ret < 0) {
+        printf("Async device open failed\nRunning without async\n");
+    }
+    wolfSSL_CTX_SetDevId(ctx, devId);
+#endif /* WOLFSSL_ASYNC_CRYPT */
+
+#ifdef WOLFSSL_TLS13
+    if (noPskDheKe)
+        wolfSSL_CTX_no_dhe_psk(ctx);
+#endif
+#ifdef HAVE_SESSION_TICKET
+#ifdef WOLFSSL_TLS13
+    if (noTicketTls13)
+        wolfSSL_CTX_no_ticket_TLSv13(ctx);
+#endif
+#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
+    if (noTicketTls12)
+        wolfSSL_CTX_NoTicketTLSv12(ctx);
+#endif
+#endif
+
+    while (1) {
+        /* allow resume option */
+        if (resumeCount > 1) {
+            if (dtlsUDP == 0) {
+                client_len = sizeof client_addr;
+                clientfd = accept(sockfd, (struct sockaddr*)&client_addr,
+                                 (ACCEPT_THIRD_T)&client_len);
+            }
+            else {
+                tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP);
+                clientfd = sockfd;
+            }
+            if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) {
+                err_sys_ex(runWithErrors, "tcp accept failed");
+            }
+        }
+#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
+        fprintf(stderr, "Before creating SSL\n");
+        if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
+            err_sys_ex(runWithErrors, "ctx not using static memory");
+        if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */
+            err_sys_ex(runWithErrors, "error printing out memory stats");
+#endif
+
+    if (doMcast) {
+#ifdef WOLFSSL_MULTICAST
+        wolfSSL_CTX_mcast_set_member_id(ctx, mcastID);
+        if (wolfSSL_CTX_set_cipher_list(ctx, "WDM-NULL-SHA256")
+            != WOLFSSL_SUCCESS)
+            err_sys("Couldn't set multicast cipher list.");
+#endif
+    }
+
+    if (doDTLS && dtlsUDP) {
+#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO)
+        if (doBlockSeq) {
+            wolfSSL_CTX_SetIOSend(ctx, TestEmbedSendTo);
+        }
+#endif
+    }
+
+#ifdef HAVE_PK_CALLBACKS
+        if (pkCallbacks)
+            SetupPkCallbacks(ctx);
+#endif
+
+        ssl = SSL_new(ctx);
+        if (ssl == NULL)
+            err_sys_ex(catastrophic, "unable to create an SSL object");
+        #ifdef OPENSSL_EXTRA
+        wolfSSL_KeepArrays(ssl);
+        #endif
+
+    /* Support for loading private key and cert using WOLFSSL object */
+#if !defined(NO_CERTS)
+    if ((!usePsk || usePskPlus) && !useAnon && loadCertKeyIntoSSLObj) {
+    #ifdef NO_FILESYSTEM
+        if (wolfSSL_use_certificate_chain_buffer(ssl, server_cert_der_2048,
+            sizeof_server_cert_der_2048) != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server cert buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (SSL_use_certificate_chain_file(ssl, ourCert)
+                                         != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server cert file, check file "
+                       "and run from wolfSSL home dir");
+    #else
+        /* loads cert chain file using buffer API */
+        load_ssl_buffer(ssl, ourCert, WOLFSSL_CERT_CHAIN);
+    #endif
+    }
+
+    if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon &&
+        loadCertKeyIntoSSLObj
+    #if defined(HAVE_PK_CALLBACKS) && defined(TEST_PK_PRIVKEY)
+        && !pkCallbacks
+    #endif /* HAVE_PK_CALLBACKS && TEST_PK_PRIVKEY */
+    ) {
+    #if defined(NO_FILESYSTEM)
+        if (wolfSSL_use_PrivateKey_buffer(ssl, server_key_der_2048,
+            sizeof_server_key_der_2048, SSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server private key buffer");
+    #elif !defined(TEST_LOAD_BUFFER)
+        if (SSL_use_PrivateKey_file(ssl, ourKey, WOLFSSL_FILETYPE_PEM)
+                                         != WOLFSSL_SUCCESS)
+            err_sys_ex(catastrophic, "can't load server private key file, check"
+                       "file and run from wolfSSL home dir");
+    #else
+        /* loads private key file using buffer API */
+        load_ssl_buffer(ssl, ourKey, WOLFSSL_KEY);
+    #endif
+    }
+#endif /* !NO_CERTS */
+
+#ifdef WOLFSSL_SEND_HRR_COOKIE
+        if (hrrCookie && wolfSSL_send_hrr_cookie(ssl, NULL, 0)
+            != WOLFSSL_SUCCESS) {
+            err_sys("unable to set use of cookie with HRR msg");
+        }
+#endif
+
+#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
+        fprintf(stderr, "After creating SSL\n");
+        if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
+            err_sys_ex(runWithErrors, "ctx not using static memory");
+        if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */
+            err_sys_ex(runWithErrors, "error printing out memory stats");
+#endif
+
+    if (doMcast) {
+#ifdef WOLFSSL_MULTICAST
+        /* DTLS multicast secret for testing only */
+        #define CLI_SRV_RANDOM_SZ 32     /* RAN_LEN (see internal.h) */
+        #define PMS_SZ            512    /* ENCRYPT_LEN (see internal.h) */
+        byte pms[PMS_SZ];                /* pre master secret */
+        byte cr[CLI_SRV_RANDOM_SZ];      /* client random */
+        byte sr[CLI_SRV_RANDOM_SZ];      /* server random */
+        const byte suite[2] = {0, 0xfe}; /* WDM_WITH_NULL_SHA256 */
+
+        XMEMSET(pms, 0x23, sizeof(pms));
+        XMEMSET(cr, 0xA5, sizeof(cr));
+        XMEMSET(sr, 0x5A, sizeof(sr));
+
+        if (wolfSSL_set_secret(ssl, 1, pms, sizeof(pms), cr, sr, suite)
+                != WOLFSSL_SUCCESS) {
+            err_sys("unable to set mcast secret");
+        }
+#endif
+    }
+
+#ifdef HAVE_SECURE_RENEGOTIATION
+        if (scr) {
+            if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) {
+                err_sys_ex(runWithErrors, "can't enable secure renegotiation");
+            }
+        }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
+    #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+        if (postHandAuth) {
+            unsigned int verify_flags = 0;
+
+            SSL_set_verify(ssl, WOLFSSL_VERIFY_PEER |
+                                ((usePskPlus) ? WOLFSSL_VERIFY_FAIL_EXCEPT_PSK :
+                                WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0);
+
+        #ifdef TEST_BEFORE_DATE
+            verify_flags |= WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY;
+        #endif
+
+            if (wolfSSL_CTX_load_verify_locations_ex(ctx, verifyCert, 0,
+                                                     verify_flags)
+                                                     != WOLFSSL_SUCCESS) {
+                err_sys_ex(runWithErrors, "can't load ca file, Please run from "
+                                          "wolfSSL home dir");
+            }
+            #ifdef WOLFSSL_TRUST_PEER_CERT
+            if (trustCert) {
+                if ((ret = wolfSSL_trust_peer_cert(ssl, trustCert,
+                                    WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
+                    err_sys_ex(runWithErrors, "can't load trusted peer cert "
+                                              "file");
+                }
+            }
+            #endif /* WOLFSSL_TRUST_PEER_CERT */
+       }
+    #endif
+#endif
+
+
+#ifndef NO_HANDSHAKE_DONE_CB
+        wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL);
+#endif
+#ifdef HAVE_CRL
+    if (!disableCRL) {
+#ifdef HAVE_CRL_MONITOR
+        crlFlags = WOLFSSL_CRL_MONITOR | WOLFSSL_CRL_START_MON;
+#endif
+        if (wolfSSL_EnableCRL(ssl, 0) != WOLFSSL_SUCCESS)
+            err_sys_ex(runWithErrors, "unable to enable CRL");
+        if (wolfSSL_LoadCRL(ssl, crlPemDir, WOLFSSL_FILETYPE_PEM, crlFlags)
+                            != WOLFSSL_SUCCESS)
+            err_sys_ex(runWithErrors, "unable to load CRL");
+        if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != WOLFSSL_SUCCESS)
+            err_sys_ex(runWithErrors, "unable to set CRL callback url");
+    }
+#endif
+#ifdef HAVE_OCSP
+        if (useOcsp) {
+            if (ocspUrl != NULL) {
+                wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
+                wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE
+                                                   | WOLFSSL_OCSP_URL_OVERRIDE);
+            }
+            else
+                wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
+        }
+#ifndef NO_RSA
+    /* All the OSCP Stapling test certs are RSA. */
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+    || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+        { /* scope start */
+            const char* ca1 = "certs/ocsp/intermediate1-ca-cert.pem";
+            const char* ca2 = "certs/ocsp/intermediate2-ca-cert.pem";
+            const char* ca3 = "certs/ocsp/intermediate3-ca-cert.pem";
+            int fails = 0;
+
+            if (wolfSSL_CTX_EnableOCSPStapling(ctx) != WOLFSSL_SUCCESS) {
+                err_sys_ex(catastrophic, "can't enable OCSP Stapling "
+                           "Certificate Manager");
+            }
+            if (SSL_CTX_load_verify_locations(ctx, ca1, 0) != WOLFSSL_SUCCESS) {
+                fails++;
+                err_sys_ex(runWithErrors, "can't load ca file, Please run from "
+                           "wolfSSL home dir");
+            }
+            if (SSL_CTX_load_verify_locations(ctx, ca2, 0) != WOLFSSL_SUCCESS) {
+                fails++;
+                err_sys_ex(runWithErrors, "can't load ca file, Please run from "
+                           "wolfSSL home dir");
+            }
+            if (SSL_CTX_load_verify_locations(ctx, ca3, 0) != WOLFSSL_SUCCESS) {
+                fails++;
+                err_sys_ex(runWithErrors, "can't load ca file, Please run from "
+                           "wolfSSL home dir");
+            }
+            if (fails > 2) {
+                err_sys_ex(catastrophic, "Failed to load any intermediates for "
+                           "OCSP stapling test");
+            }
+        } /* scope end */
+#endif /* HAVE_CERTIFICATE_STATUS_REQUEST HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
+#endif /* NO_RSA */
+#endif /* HAVE_OCSP */
+
+#ifdef HAVE_PK_CALLBACKS
+        if (pkCallbacks)
+            SetupPkCallbackContexts(ssl, &pkCbInfo);
+#endif
+
+    #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
+        if (version >= 4) {
+            SetKeyShare(ssl, onlyKeyShare, useX25519, useX448);   
+        }
+    #endif
+
+    #ifdef HAVE_ENCRYPT_THEN_MAC
+        if (disallowETM)
+            wolfSSL_AllowEncryptThenMac(ssl, 0);
+    #endif
+
+
+        /* do accept */
+        readySignal = ((func_args*)args)->signal;
+        if (readySignal) {
+            readySignal->srfName = serverReadyFile;
+        }
+
+        client_len = sizeof client_addr;
+        tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr,
+                   dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen,
+                   &client_addr, &client_len);
+
+        doListen = 0; /* Don't listen next time */
+
+        if (port == 0) {
+            port = readySignal->port;
+        }
+
+        if (SSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) {
+            err_sys_ex(catastrophic, "error in setting fd");
+        }
+
+#ifdef HAVE_TRUSTED_CA
+        if (trustedCaKeyId) {
+            if (wolfSSL_UseTrustedCA(ssl, WOLFSSL_TRUSTED_CA_PRE_AGREED,
+                        NULL, 0) != WOLFSSL_SUCCESS) {
+                err_sys_ex(runWithErrors, "UseTrustedCA failed");
+            }
+        }
+#endif /* HAVE_TRUSTED_CA */
+
+#ifdef HAVE_ALPN
+        if (alpnList != NULL) {
+            printf("ALPN accepted protocols list : %s\n", alpnList);
+            wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
+        }
+#endif
+
+#if defined(WOLFSSL_DTLS) && defined(USE_WOLFSSL_IO)
+        if (doDTLS && dtlsUDP) {
+            byte          b[1500];
+            int           n;
+
+            client_len = sizeof client_addr;
+
+            /* For DTLS, peek at the next datagram so we can get the client's
+             * address and set it into the ssl object later to generate the
+             * cookie. */
+            n = (int)recvfrom(clientfd, (char*)b, sizeof(b), MSG_PEEK,
+                              (struct sockaddr*)&client_addr, &client_len);
+            if (n <= 0)
+                err_sys_ex(runWithErrors, "recvfrom failed");
+
+            if (doBlockSeq) {
+                XMEMCPY(&dtlsCtx.peer.sa, &client_addr, client_len);
+                dtlsCtx.peer.sz = client_len;
+                dtlsCtx.wfd = clientfd;
+                dtlsCtx.failOnce = 1;
+
+                wolfSSL_SetIOWriteCtx(ssl, &dtlsCtx);
+            }
+            else {
+                wolfSSL_dtls_set_peer(ssl, &client_addr, client_len);
+            }
+        }
+#endif
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+        {
+            SOCKADDR_IN_T local_addr;
+            socklen_t local_len = sizeof(local_addr);
+            getsockname(clientfd, (struct sockaddr *)&local_addr,
+                        (socklen_t *)&local_len);
+
+            if (((struct sockaddr *)&client_addr)->sa_family !=
+                ((struct sockaddr *)&local_addr)->sa_family)
+                err_sys_ex(catastrophic,
+                           "client_addr.sa_family != local_addr.sa_family");
+
+            if (wolfsentry_store_endpoints(
+                    ssl, &client_addr, &local_addr,
+                    dtlsUDP ? IPPROTO_UDP : IPPROTO_TCP,
+                    WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN, NULL) != WOLFSSL_SUCCESS)
+                err_sys_ex(catastrophic,
+                           "error in wolfsentry_store_endpoints()");
+        }
+#endif /* WOLFSSL_WOLFSENTRY_HOOKS */
+
+        if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL
+                                                               || needDH == 1) {
+            #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN)
+                wolfSSL_SetTmpDH_file(ssl, ourDhParam, WOLFSSL_FILETYPE_PEM);
+            #elif !defined(NO_DH)
+                SetDH(ssl);  /* repick suites with DHE, higher priority than
+                              * PSK */
+            #endif
+#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \
+    !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
+            if (!doDhKeyCheck)
+                wolfSSL_SetEnableDhKeyTest(ssl, 0);
+#endif
+        }
+
+#ifndef WOLFSSL_CALLBACKS
+        if (nonBlocking) {
+            #ifdef WOLFSSL_DTLS
+            if (doDTLS) {
+                wolfSSL_dtls_set_using_nonblock(ssl, 1);
+            }
+            #endif
+            tcp_set_nonblocking(&clientfd);
+
+            ret = NonBlockingSSL_Accept(ssl);
+        }
+        else {
+    #ifdef WOLFSSL_EARLY_DATA
+            if (earlyData) {
+                do {
+                    int len;
+                    err = 0; /* reset error */
+                    ret = wolfSSL_read_early_data(ssl, input, sizeof(input)-1,
+                                                                          &len);
+                    if (ret != WOLFSSL_SUCCESS) {
+                        err = SSL_get_error(ssl, 0);
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        if (err == WC_PENDING_E) {
+                            ret = wolfSSL_AsyncPoll(ssl,
+                                                    WOLF_POLL_FLAG_CHECK_HW);
+                            if (ret < 0) break;
+                        }
+                    #endif
+                    }
+                    if (ret > 0) {
+                        input[ret] = 0; /* null terminate message */
+                        printf("Early Data Client message: %s\n", input);
+                    }
+                } while (err == WC_PENDING_E || ret > 0);
+            }
+    #endif
+            do {
+                err = 0; /* reset error */
+                ret = SSL_accept(ssl);
+#ifdef WOLFSSL_EARLY_DATA
+                EarlyDataStatus(ssl);
+#endif
+                if (ret != WOLFSSL_SUCCESS) {
+                    err = SSL_get_error(ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
+        }
+#else
+        ret = NonBlockingSSL_Accept(ssl);
+#endif
+        if (ret != WOLFSSL_SUCCESS) {
+            err = SSL_get_error(ssl, 0);
+            printf("SSL_accept error %d, %s\n", err,
+                                                ERR_error_string(err, buffer));
+            if (!exitWithRet) {
+                err_sys_ex(runWithErrors, "SSL_accept failed");
+            } else {
+                /* cleanup */
+                SSL_free(ssl); ssl = NULL;
+                SSL_CTX_free(ctx); ctx = NULL;
+                CloseSocket(clientfd);
+                CloseSocket(sockfd);
+                ((func_args*)args)->return_code = err;
+                goto exit;
+            }
+        }
+
+        showPeerEx(ssl, lng_index);
+        if (SSL_state(ssl) != 0) {
+            err_sys_ex(runWithErrors, "SSL in error state");
+        }
+
+        /* if the caller requested a particular cipher, check here that either
+         * a canonical name of the established cipher matches the requested
+         * cipher name, or the requested cipher name is marked as an alias
+         * that matches the established cipher.
+         */
+        if (cipherList && !useDefCipherList && (! XSTRSTR(cipherList, ":"))) {
+            WOLFSSL_CIPHER* established_cipher = wolfSSL_get_current_cipher(ssl);
+            byte requested_cipherSuite0, requested_cipherSuite;
+            int requested_cipherFlags;
+            if (established_cipher &&
+                /* don't test for pseudo-ciphers like "ALL" and "DEFAULT". */
+                (wolfSSL_get_cipher_suite_from_name(cipherList,
+                                                    &requested_cipherSuite0,
+                                                    &requested_cipherSuite,
+                                                    &requested_cipherFlags) == 0)) {
+                word32 established_cipher_id = wolfSSL_CIPHER_get_id(established_cipher);
+                byte established_cipherSuite0 = (established_cipher_id >> 8) & 0xff;
+                byte established_cipherSuite = established_cipher_id & 0xff;
+                const char *established_cipher_name =
+                    wolfSSL_get_cipher_name_from_suite(established_cipherSuite0,
+                                                       established_cipherSuite);
+                const char *established_cipher_name_iana =
+                    wolfSSL_get_cipher_name_iana_from_suite(established_cipherSuite0,
+                                                            established_cipherSuite);
+
+                if (established_cipher_name == NULL)
+                    err_sys_ex(catastrophic, "error looking up name of established cipher");
+
+                if (strcmp(cipherList, established_cipher_name) &&
+                    ((established_cipher_name_iana == NULL) ||
+                     strcmp(cipherList, established_cipher_name_iana))) {
+                    if (! (requested_cipherFlags & WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS))
+                        err_sys_ex(
+                            catastrophic,
+                            "Unexpected mismatch between names of requested and established ciphers.");
+                    else if ((requested_cipherSuite0 != established_cipherSuite0) ||
+                             (requested_cipherSuite != established_cipherSuite))
+                        err_sys_ex(
+                            catastrophic,
+                            "Mismatch between IDs of requested and established ciphers.");
+                }
+            }
+        }
+
+#if defined(OPENSSL_EXTRA) || defined(HAVE_SECRET_CALLBACK)
+    {
+        byte*  rnd = NULL;
+        byte*  pt;
+        size_t size;
+
+        /* get size of buffer then print */
+        size = wolfSSL_get_server_random(NULL, NULL, 0);
+        if (size == 0) {
+            err_sys_ex(runWithErrors, "error getting server random buffer "
+                       "size");
+        }
+        else {
+            rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        }
+
+        if (rnd == NULL) {
+            err_sys_ex(runWithErrors, "error creating server random buffer");
+        }
+
+        size = wolfSSL_get_server_random(ssl, rnd, size);
+        if (size == 0) {
+            if (rnd) {
+                XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                rnd = NULL;
+            }
+            err_sys_ex(runWithErrors, "error getting server random buffer");
+        }
+
+        if (rnd) {
+            printf("Server Random : ");
+            for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt);
+            printf("\n");
+
+            XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            rnd = NULL;
+        }
+    }
+#endif
+
+#ifdef HAVE_ALPN
+        if (alpnList != NULL) {
+            char *protocol_name = NULL, *list = NULL;
+            word16 protocol_nameSz = 0, listSz = 0;
+
+            err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name,
+                                           &protocol_nameSz);
+            if (err == WOLFSSL_SUCCESS)
+                printf("Sent ALPN protocol : %s (%d)\n",
+                       protocol_name, protocol_nameSz);
+            else if (err == WOLFSSL_ALPN_NOT_FOUND)
+                printf("No ALPN response sent (no match)\n");
+            else
+                printf("Getting ALPN protocol name failed\n");
+
+            err = wolfSSL_ALPN_GetPeerProtocol(ssl, &list, &listSz);
+            if (err == WOLFSSL_SUCCESS)
+                printf("List of protocol names sent by Client: %s (%d)\n",
+                       list, listSz);
+            else
+                printf("Get list of client's protocol name failed\n");
+
+            free(list);
+        }
+#endif
+
+        if (echoData == 0 && throughput == 0) {
+            ServerRead(ssl, input, sizeof(input)-1);
+            err = SSL_get_error(ssl, 0);
+        }
+
+#if defined(HAVE_SECURE_RENEGOTIATION) && \
+    defined(HAVE_SERVER_RENEGOTIATION_INFO)
+        if (scr && forceScr) {
+            if (nonBlocking) {
+                if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) {
+                    err = wolfSSL_get_error(ssl, 0);
+                    if (err == WOLFSSL_ERROR_WANT_READ ||
+                            err == WOLFSSL_ERROR_WANT_WRITE) {
+                        do {
+                            if (err == APP_DATA_READY) {
+                                if ((ret = wolfSSL_read(ssl, input, sizeof(input)-1)) < 0) {
+                                    err_sys("APP DATA should be present but error returned");
+                                }
+                                printf("Received message: %s\n", input);
+                            }
+                            err = 0;
+                            if ((ret = wolfSSL_accept(ssl)) != WOLFSSL_SUCCESS) {
+                                err = wolfSSL_get_error(ssl, ret);
+                            }
+                        } while (ret != WOLFSSL_SUCCESS &&
+                                (err == WOLFSSL_ERROR_WANT_READ ||
+                                        err == WOLFSSL_ERROR_WANT_WRITE ||
+                                        err == APP_DATA_READY));
+
+                        if (ret != WOLFSSL_SUCCESS) {
+                            err = wolfSSL_get_error(ssl, 0);
+                            printf("wolfSSL_Rehandshake error %d, %s\n", err,
+                                wolfSSL_ERR_error_string(err, buffer));
+                            wolfSSL_free(ssl); ssl = NULL;
+                            wolfSSL_CTX_free(ctx); ctx = NULL;
+                            err_sys("non-blocking wolfSSL_Rehandshake failed");
+                        }
+                        printf("NON-BLOCKING RENEGOTIATION SUCCESSFUL\n");
+                    }
+                    else {
+                        printf("wolfSSL_Rehandshake error %d, %s\n", err,
+                            wolfSSL_ERR_error_string(err, buffer));
+                        wolfSSL_free(ssl); ssl = NULL;
+                        wolfSSL_CTX_free(ctx); ctx = NULL;
+                        err_sys("non-blocking wolfSSL_Rehandshake failed");
+                    }
+                }
+            } else {
+                if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) {
+#ifdef WOLFSSL_ASYNC_CRYPT
+                    err = wolfSSL_get_error(ssl, 0);
+                    while (err == WC_PENDING_E) {
+                        err = 0;
+                        ret = wolfSSL_negotiate(ssl);
+                        if (ret != WOLFSSL_SUCCESS) {
+                            err = wolfSSL_get_error(ssl, 0);
+                            if (err == WC_PENDING_E) {
+                                ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+                                if (ret < 0) break;
+                            }
+                        }
+                    }
+                    if (ret != WOLFSSL_SUCCESS)
+#endif
+                        printf("not doing secure renegotiation\n");
+                }
+                else {
+                    printf("RENEGOTIATION SUCCESSFUL\n");
+                }
+            }
+        }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
+        if (err == 0 && echoData == 0 && throughput == 0) {
+            const char* write_msg;
+            int write_msg_sz;
+
+#ifdef WOLFSSL_TLS13
+            if (updateKeysIVs)
+                wolfSSL_update_keys(ssl);
+#endif
+#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
+            if (postHandAuth)
+                wolfSSL_request_certificate(ssl);
+#endif
+
+            /* Write data */
+            if (!useWebServerMsg) {
+                write_msg = kReplyMsg;
+                write_msg_sz = (int)XSTRLEN(kReplyMsg);
+            }
+            else {
+                write_msg = kHttpServerMsg;
+                write_msg_sz = (int)XSTRLEN(kHttpServerMsg);
+            }
+            ServerWrite(ssl, write_msg, write_msg_sz);
+
+#ifdef WOLFSSL_TLS13
+            if (updateKeysIVs || postHandAuth)
+                ServerRead(ssl, input, sizeof(input)-1);
+#endif
+        }
+        else if (err == 0 || err == WOLFSSL_ERROR_ZERO_RETURN) {
+            err = ServerEchoData(ssl, clientfd, echoData, block, throughput);
+            if (err != 0) {
+                SSL_free(ssl); ssl = NULL;
+                SSL_CTX_free(ctx); ctx = NULL;
+                CloseSocket(clientfd);
+                CloseSocket(sockfd);
+                ((func_args*)args)->return_code = err;
+                goto exit;
+            }
+        }
+
+#if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX)
+        os_dly_wait(500) ;
+#elif defined (WOLFSSL_TIRTOS)
+        Task_yield();
+#endif
+
+        if (dtlsUDP == 0) {
+            ret = SSL_shutdown(ssl);
+            if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) {
+                ret = SSL_shutdown(ssl); /* bidirectional shutdown */
+                if (ret == WOLFSSL_SUCCESS)
+                    printf("Bidirectional shutdown complete\n");
+            }
+        }
+
+        /* display collected statistics */
+#ifdef WOLFSSL_STATIC_MEMORY
+        if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1)
+            err_sys_ex(runWithErrors, "static memory was not used with ssl");
+
+        fprintf(stderr, "\nprint off SSL memory stats\n");
+        fprintf(stderr, "*** This is memory state before wolfSSL_free is "
+                "called\n");
+        fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem);
+        fprintf(stderr, "current memory in use  = %d\n", ssl_stats.curMem);
+        fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc);
+        fprintf(stderr, "current connection allocs = %d\n",ssl_stats.curAlloc);
+        fprintf(stderr, "total connection allocs   = %d\n",
+                ssl_stats.totalAlloc);
+        fprintf(stderr, "total connection frees    = %d\n\n",
+                ssl_stats.totalFr);
+
+#endif
+        SSL_free(ssl); ssl = NULL;
+
+        CloseSocket(clientfd);
+
+        if (resume == 1 && resumeCount == 0) {
+            resumeCount++;           /* only do one resume for testing */
+            continue;
+        }
+        resumeCount = 0;
+
+        cnt++;
+        if (loops > 0 && --loops == 0) {
+            break;  /* out of while loop, done with normal and resume option */
+        }
+    } /* while(1) */
+
+    WOLFSSL_TIME(cnt);
+    (void)cnt;
+
+#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
+ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
+    wolfSSL_CTX_DisableOCSPStapling(ctx);
+#endif
+
+    CloseSocket(sockfd);
+    SSL_CTX_free(ctx); ctx = NULL;
+
+    ((func_args*)args)->return_code = 0;
+
+exit:
+
+#ifdef WOLFSSL_WOLFSENTRY_HOOKS
+    wolfsentry_ret = wolfsentry_shutdown(&wolfsentry);
+    if (wolfsentry_ret < 0) {
+        fprintf(stderr,
+                "wolfsentry_shutdown() returned " WOLFSENTRY_ERROR_FMT "\n",
+                WOLFSENTRY_ERROR_FMT_ARGS(wolfsentry_ret));
+    }
+#endif
+
+#if defined(HAVE_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) \
+                      && (defined(NO_MAIN_DRIVER) || defined(HAVE_STACK_SIZE))
+    wc_ecc_fp_free();  /* free per thread cache */
+#endif
+
+#ifdef WOLFSSL_TIRTOS
+    fdCloseSession(Task_self());
+#endif
+
+#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \
+    ((defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) || defined(HAVE_AESGCM))
+    TicketCleanup();
+#endif
+
+#ifdef WOLFSSL_ASYNC_CRYPT
+    wolfAsync_DevClose(&devId);
+#endif
+
+    /* There are use cases  when these assignments are not read. To avoid
+     * potential confusion those warnings have been handled here.
+     */
+    (void) ourKey;
+    (void) verifyCert;
+    (void) doCliCertCheck;
+    (void) useNtruKey;
+    (void) ourDhParam;
+    (void) ourCert;
+    (void) useX25519;
+    (void) useX448;
+#ifdef HAVE_SECURE_RENEGOTIATION
+    (void) forceScr;
+#endif
+#ifndef WOLFSSL_TIRTOS
+    return 0;
+#endif
+}
+
+#endif /* !NO_WOLFSSL_SERVER */
+
+
+/* so overall tests can pull in test function */
+#ifndef NO_MAIN_DRIVER
+
+    int main(int argc, char** argv)
+    {
+        func_args args;
+        tcp_ready ready;
+
+        StartTCP();
+
+        args.argc = argc;
+        args.argv = argv;
+        args.signal = &ready;
+        args.return_code = 0;
+        InitTcpReady(&ready);
+
+#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL)
+        wolfSSL_Debugging_ON();
+#endif
+        wolfSSL_Init();
+        ChangeToWolfRoot();
+
+#ifndef NO_WOLFSSL_SERVER
+#ifdef HAVE_STACK_SIZE
+        StackSizeCheck(&args, server_test);
+#else
+        server_test(&args);
+#endif
+#else
+        printf("Server not compiled in!\n");
+#endif
+
+        wolfSSL_Cleanup();
+        FreeTcpReady(&ready);
+
+#ifdef HAVE_WNR
+    if (wc_FreeNetRandom() < 0)
+        err_sys_ex(runWithErrors, "Failed to free netRandom context");
+#endif /* HAVE_WNR */
+
+        return args.return_code;
+    }
+
+    int myoptind = 0;
+    char* myoptarg = NULL;
+
+#endif /* NO_MAIN_DRIVER */
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/example/tls_bench.c b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/tls_bench.c
new file mode 100644
index 0000000..fcbdd66
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/example/tls_bench.c
@@ -0,0 +1,1953 @@
+/* tls_bench.c
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+
+/*
+Example gcc build statement
+gcc -lwolfssl -lpthread -o tls_bench tls_bench.c
+./tls_bench
+
+Or
+
+#include <examples/benchmark/tls_bench.h>
+bench_tls(args);
+*/
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+#ifndef WOLFSSL_USER_SETTINGS
+    #include <wolfssl/options.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/ssl.h>
+#include <wolfssl/wolfcrypt/hash.h> /* WC_MAX_DIGEST_SIZE */
+#include <wolfssl/test.h>
+#include <wolfssl/wolfio.h>
+#include <examples/benchmark/tls_bench.h>
+
+/* force certificate test buffers to be included via headers */
+#undef  USE_CERT_BUFFERS_2048
+#define USE_CERT_BUFFERS_2048
+#undef  USE_CERT_BUFFERS_256
+#define USE_CERT_BUFFERS_256
+#include <wolfssl/certs_test.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
+
+/* For testing no pthread support */
+#if 0
+    #undef HAVE_PTHREAD
+#endif
+
+/* PTHREAD requires server and client enabled */
+#if defined(HAVE_PTHREAD) && (defined(NO_WOLFSSL_CLIENT) || defined(NO_WOLFSSL_SERVER))
+    #undef HAVE_PTHREAD
+#endif
+
+#ifdef HAVE_PTHREAD
+    #include <pthread.h>
+#endif
+
+#if 0
+#define BENCH_USE_NONBLOCK
+#endif
+
+/* Defaults for configuration parameters */
+#define BENCH_DEFAULT_HOST  "localhost"
+#define BENCH_DEFAULT_PORT  11112
+#define NUM_THREAD_PAIRS    1 /* Thread pairs of server/client */
+#ifndef BENCH_RUNTIME_SEC
+    #ifdef BENCH_EMBEDDED
+        #define BENCH_RUNTIME_SEC   15
+    #else
+        #define BENCH_RUNTIME_SEC   1
+    #endif
+#endif
+/* TLS packet size */
+#ifndef TEST_PACKET_SIZE
+    #ifdef BENCH_EMBEDDED
+        #define TEST_PACKET_SIZE    (2 * 1024)
+    #else
+        #define TEST_PACKET_SIZE    (16 * 1024)
+    #endif
+#endif
+/* Total bytes to benchmark per connection */
+#ifndef TEST_MAX_SIZE
+    #ifdef BENCH_EMBEDDED
+        #define TEST_MAX_SIZE       (16 * 1024)
+    #else
+        #define TEST_MAX_SIZE       (128 * 1024)
+    #endif
+#endif
+
+#ifdef WOLFSSL_DTLS
+    #ifdef BENCH_EMBEDDED
+        /* WOLFSSL_MAX_MTU in internal.h */
+        #define TEST_DTLS_PACKET_SIZE   (1500)
+    #else
+        /* MAX_UDP_SIZE in interna.h */
+        #define TEST_DTLS_PACKET_SIZE   (8092)
+    #endif
+#endif
+
+/* In memory transfer buffer maximum size */
+/* Must be large enough to handle max TLS packet size plus max TLS header MAX_MSG_EXTRA */
+#define MEM_BUFFER_SZ       (TEST_PACKET_SIZE + 38 + WC_MAX_DIGEST_SIZE)
+#define SHOW_VERBOSE        0 /* Default output is tab delimited format */
+
+#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \
+    !defined(WOLFCRYPT_ONLY) && defined(USE_WOLFSSL_IO)
+
+/* shutdown message - nice signal to server, we are done */
+static const char* kShutdown = "shutdown";
+
+#ifndef NO_WOLFSSL_CLIENT
+PEDANTIC_EXTENSION static const char* kTestStr =
+"Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n"
+"polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n"
+"marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n"
+"plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\n"
+"selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\n"
+"small batch meggings kogi dolore food truck bespoke gastropub.\n"
+"\n"
+"Terry richardson adipisicing actually typewriter tumblr, twee whatever\n"
+"four loko you probably haven't heard of them high life. Messenger bag\n"
+"whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\n"
+"et, banksy ullamco messenger bag umami pariatur direct trade forage.\n"
+"Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\n"
+"food truck next level, tousled irony non semiotics PBR ethical anim cred\n"
+"readymade. Mumblecore brunch lomo odd future, portland organic terry\n"
+"richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\n"
+"mixtape polaroid, pork belly readymade organic cray typewriter helvetica\n"
+"four loko whatever street art yr farm-to-table.\n"
+"\n"
+"Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\n"
+"pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\n"
+"et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\n"
+"nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\n"
+"seitan fingerstache kale chips. Terry richardson artisan williamsburg,\n"
+"eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\n"
+"readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\n"
+"ethnic art party qui letterpress nisi proident jean shorts mlkshk\n"
+"locavore.\n"
+"\n"
+"Narwhal flexitarian letterpress, do gluten-free voluptate next level\n"
+"banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\n"
+"cillum pickled velit, YOLO officia you probably haven't heard of them\n"
+"trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\n"
+"small batch american apparel. Put a bird on it cosby sweater before they\n"
+"sold out pork belly kogi hella. Street art mollit sustainable polaroid,\n"
+"DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\n"
+"Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\n"
+"excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\n"
+"neutra PBR selvage.\n"
+"\n"
+"Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\n"
+"next level jean shorts exercitation. Hashtag keytar whatever, nihil\n"
+"authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\n"
+"wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\n"
+"tattooed. Labore high life commodo, meggings raw denim fingerstache pug\n"
+"trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\n"
+"incididunt flannel sustainable helvetica pork belly pug banksy you\n"
+"probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\n"
+"mollit magna, sriracha sartorial helvetica.\n"
+"\n"
+"Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\n"
+"ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\n"
+"of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\n"
+"reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\n"
+"skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\n"
+"organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\n"
+"Veniam sunt food truck leggings, sint vinyl fap.\n"
+"\n"
+"Hella dolore pork belly, truffaut carles you probably haven't heard of\n"
+"them PBR helvetica in sapiente. Fashion axe ugh bushwick american\n"
+"apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\n"
+"flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\n"
+"letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\n"
+"Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\n"
+"delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\n"
+"magna pop-up literally. Swag thundercats ennui shoreditch vegan\n"
+"pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\n"
+"\n"
+"Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\n"
+"meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\n"
+"dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\n"
+"locavore kale chips. Sriracha swag thundercats, chillwave disrupt\n"
+"tousled beard mollit mustache leggings portland next level. Nihil esse\n"
+"est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\n"
+"swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n"
+"bag dolor terry richardson sapiente.\n";
+#endif
+
+#if !defined(NO_DH)
+
+#define MIN_DHKEY_BITS      1024
+
+#if !defined(NO_WOLFSSL_SERVER)
+/* dh2048 p */
+static const unsigned char dhp[] =
+{
+    0xb0, 0xa1, 0x08, 0x06, 0x9c, 0x08, 0x13, 0xba, 0x59, 0x06, 0x3c, 0xbc, 0x30,
+    0xd5, 0xf5, 0x00, 0xc1, 0x4f, 0x44, 0xa7, 0xd6, 0xef, 0x4a, 0xc6, 0x25, 0x27,
+    0x1c, 0xe8, 0xd2, 0x96, 0x53, 0x0a, 0x5c, 0x91, 0xdd, 0xa2, 0xc2, 0x94, 0x84,
+    0xbf, 0x7d, 0xb2, 0x44, 0x9f, 0x9b, 0xd2, 0xc1, 0x8a, 0xc5, 0xbe, 0x72, 0x5c,
+    0xa7, 0xe7, 0x91, 0xe6, 0xd4, 0x9f, 0x73, 0x07, 0x85, 0x5b, 0x66, 0x48, 0xc7,
+    0x70, 0xfa, 0xb4, 0xee, 0x02, 0xc9, 0x3d, 0x9a, 0x4a, 0xda, 0x3d, 0xc1, 0x46,
+    0x3e, 0x19, 0x69, 0xd1, 0x17, 0x46, 0x07, 0xa3, 0x4d, 0x9f, 0x2b, 0x96, 0x17,
+    0x39, 0x6d, 0x30, 0x8d, 0x2a, 0xf3, 0x94, 0xd3, 0x75, 0xcf, 0xa0, 0x75, 0xe6,
+    0xf2, 0x92, 0x1f, 0x1a, 0x70, 0x05, 0xaa, 0x04, 0x83, 0x57, 0x30, 0xfb, 0xda,
+    0x76, 0x93, 0x38, 0x50, 0xe8, 0x27, 0xfd, 0x63, 0xee, 0x3c, 0xe5, 0xb7, 0xc8,
+    0x09, 0xae, 0x6f, 0x50, 0x35, 0x8e, 0x84, 0xce, 0x4a, 0x00, 0xe9, 0x12, 0x7e,
+    0x5a, 0x31, 0xd7, 0x33, 0xfc, 0x21, 0x13, 0x76, 0xcc, 0x16, 0x30, 0xdb, 0x0c,
+    0xfc, 0xc5, 0x62, 0xa7, 0x35, 0xb8, 0xef, 0xb7, 0xb0, 0xac, 0xc0, 0x36, 0xf6,
+    0xd9, 0xc9, 0x46, 0x48, 0xf9, 0x40, 0x90, 0x00, 0x2b, 0x1b, 0xaa, 0x6c, 0xe3,
+    0x1a, 0xc3, 0x0b, 0x03, 0x9e, 0x1b, 0xc2, 0x46, 0xe4, 0x48, 0x4e, 0x22, 0x73,
+    0x6f, 0xc3, 0x5f, 0xd4, 0x9a, 0xd6, 0x30, 0x07, 0x48, 0xd6, 0x8c, 0x90, 0xab,
+    0xd4, 0xf6, 0xf1, 0xe3, 0x48, 0xd3, 0x58, 0x4b, 0xa6, 0xb9, 0xcd, 0x29, 0xbf,
+    0x68, 0x1f, 0x08, 0x4b, 0x63, 0x86, 0x2f, 0x5c, 0x6b, 0xd6, 0xb6, 0x06, 0x65,
+    0xf7, 0xa6, 0xdc, 0x00, 0x67, 0x6b, 0xbb, 0xc3, 0xa9, 0x41, 0x83, 0xfb, 0xc7,
+    0xfa, 0xc8, 0xe2, 0x1e, 0x7e, 0xaf, 0x00, 0x3f, 0x93
+};
+
+/* dh2048 g */
+static const unsigned char dhg[] =
+{
+    0x02,
+};
+#endif /* !NO_WOLFSSL_SERVER */
+#endif /* !NO_DH */
+
+#ifdef HAVE_PTHREAD
+typedef struct {
+    unsigned char buf[MEM_BUFFER_SZ];
+    int write_bytes;
+    int write_idx;
+    int read_bytes;
+    int read_idx;
+
+    pthread_t tid;
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+
+    int done;
+} memBuf_t;
+#endif
+
+typedef struct {
+    double connTime;
+    double rxTime;
+    double txTime;
+    int connCount;
+    int rxTotal;
+    int txTotal;
+} stats_t;
+
+typedef struct {
+    int shutdown;
+    int sockFd;
+    int ret;
+} side_t;
+
+typedef struct {
+    const char* cipher;
+    const char* host;
+    word32 port;
+    int packetSize; /* The data payload size in the packet */
+    int maxSize;
+    int runTimeSec;
+    int showPeerInfo;
+    int showVerbose;
+#ifndef NO_WOLFSSL_SERVER
+    int listenFd;
+#endif
+#ifdef WOLFSSL_DTLS
+    int doDTLS;
+    struct sockaddr_in serverAddr;
+    struct sockaddr_in clientAddr;
+#ifdef HAVE_PTHREAD
+    int serverReady;
+    int clientOrserverOnly;
+    pthread_mutex_t dtls_mutex;
+    pthread_cond_t dtls_cond;
+#endif
+#endif
+    side_t client;
+    side_t server;
+
+#ifdef HAVE_PTHREAD
+    int useLocalMem;
+
+    /* client messages to server in memory */
+    memBuf_t to_server;
+
+    /* server messages to client in memory */
+    memBuf_t to_client;
+#endif
+
+    /* server */
+    stats_t server_stats;
+
+    /* client */
+    stats_t client_stats;
+} info_t;
+
+/* Global vars for argument parsing */
+int myoptind = 0;
+char* myoptarg = NULL;
+
+#ifdef WOLFSSL_DTLS
+int DoneHandShake = 0;
+#endif
+
+static double gettime_secs(int reset)
+{
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    (void)reset;
+
+    return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
+}
+
+
+#ifdef HAVE_PTHREAD
+/* server send callback */
+static int ServerMemSend(info_t* info, char* buf, int sz)
+{
+    pthread_mutex_lock(&info->to_client.mutex);
+
+#ifndef BENCH_USE_NONBLOCK
+    /* check for overflow */
+    if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) {
+        pthread_mutex_unlock(&info->to_client.mutex);
+        printf("ServerMemSend overflow\n");
+        return -1;
+    }
+#else
+    if (info->to_client.write_idx + sz > MEM_BUFFER_SZ)
+        sz = MEM_BUFFER_SZ - info->to_client.write_idx;
+#endif
+
+    XMEMCPY(&info->to_client.buf[info->to_client.write_idx], buf, sz);
+    info->to_client.write_idx += sz;
+    info->to_client.write_bytes += sz;
+
+    pthread_cond_signal(&info->to_client.cond);
+    pthread_mutex_unlock(&info->to_client.mutex);
+
+#ifdef BENCH_USE_NONBLOCK
+    if (sz == 0)
+        return WOLFSSL_CBIO_ERR_WANT_WRITE;
+#endif
+    return sz;
+}
+
+/* server recv callback */
+static int ServerMemRecv(info_t* info, char* buf, int sz)
+{
+    pthread_mutex_lock(&info->to_server.mutex);
+
+#ifndef BENCH_USE_NONBLOCK
+    while (info->to_server.write_idx - info->to_server.read_idx < sz && !info->to_client.done)
+        pthread_cond_wait(&info->to_server.cond, &info->to_server.mutex);
+#else
+    if (info->to_server.write_idx - info->to_server.read_idx < sz)
+        sz = info->to_server.write_idx - info->to_server.read_idx;
+#endif
+
+    XMEMCPY(buf, &info->to_server.buf[info->to_server.read_idx], sz);
+    info->to_server.read_idx += sz;
+    info->to_server.read_bytes += sz;
+
+    /* if the rx has caught up with pending then reset buffer positions */
+    if (info->to_server.read_bytes == info->to_server.write_bytes) {
+        info->to_server.read_bytes = info->to_server.read_idx = 0;
+        info->to_server.write_bytes = info->to_server.write_idx = 0;
+    }
+
+    pthread_mutex_unlock(&info->to_server.mutex);
+
+    if (info->to_client.done != 0)
+        return -1;
+
+#ifdef BENCH_USE_NONBLOCK
+    if (sz == 0)
+        return WOLFSSL_CBIO_ERR_WANT_READ;
+#endif
+    return sz;
+}
+
+/* client send callback */
+static int ClientMemSend(info_t* info, char* buf, int sz)
+{
+    pthread_mutex_lock(&info->to_server.mutex);
+
+#ifndef BENCH_USE_NONBLOCK
+    /* check for overflow */
+    if (info->to_client.write_idx + sz > MEM_BUFFER_SZ) {
+        printf("ClientMemSend overflow %d %d %d\n", info->to_client.write_idx, sz, MEM_BUFFER_SZ);
+        pthread_mutex_unlock(&info->to_server.mutex);
+        return -1;
+    }
+#else
+    if (info->to_server.write_idx + sz > MEM_BUFFER_SZ)
+        sz = MEM_BUFFER_SZ - info->to_server.write_idx;
+#endif
+
+    XMEMCPY(&info->to_server.buf[info->to_server.write_idx], buf, sz);
+    info->to_server.write_idx += sz;
+    info->to_server.write_bytes += sz;
+
+    pthread_cond_signal(&info->to_server.cond);
+    pthread_mutex_unlock(&info->to_server.mutex);
+
+#ifdef BENCH_USE_NONBLOCK
+    if (sz == 0)
+        return WOLFSSL_CBIO_ERR_WANT_WRITE;
+#endif
+    return sz;
+}
+
+/* client recv callback */
+static int ClientMemRecv(info_t* info, char* buf, int sz)
+{
+    pthread_mutex_lock(&info->to_client.mutex);
+
+#ifndef BENCH_USE_NONBLOCK
+    while (info->to_client.write_idx - info->to_client.read_idx < sz)
+        pthread_cond_wait(&info->to_client.cond, &info->to_client.mutex);
+#else
+    if (info->to_client.write_idx - info->to_client.read_idx < sz)
+        sz = info->to_client.write_idx - info->to_client.read_idx;
+#endif
+
+    XMEMCPY(buf, &info->to_client.buf[info->to_client.read_idx], sz);
+    info->to_client.read_idx += sz;
+    info->to_client.read_bytes += sz;
+
+    /* if the rx has caught up with pending then reset buffer positions */
+    if (info->to_client.read_bytes == info->to_client.write_bytes) {
+        info->to_client.read_bytes = info->to_client.read_idx = 0;
+        info->to_client.write_bytes = info->to_client.write_idx = 0;
+    }
+
+    pthread_mutex_unlock(&info->to_client.mutex);
+
+#ifdef BENCH_USE_NONBLOCK
+    if (sz == 0)
+        return WOLFSSL_CBIO_ERR_WANT_READ;
+#endif
+    return sz;
+}
+#endif /* HAVE_PTHREAD */
+
+static int SocketRecv(int sockFd, char* buf, int sz)
+{
+    int recvd = (int)recv(sockFd, buf, sz, 0);
+    if (recvd == -1) {
+        switch (errno) {
+    #if EAGAIN != SOCKET_EWOULDBLOCK
+        case EAGAIN: /* EAGAIN == EWOULDBLOCK on some systems, but not others */
+    #endif
+        case SOCKET_EWOULDBLOCK:
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        case SOCKET_ECONNRESET:
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        case SOCKET_EINTR:
+            return WOLFSSL_CBIO_ERR_ISR;
+        case SOCKET_ECONNREFUSED: /* DTLS case */
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        case SOCKET_ECONNABORTED:
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        default:
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else if (recvd == 0) {
+        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+    }
+    return recvd;
+}
+
+static int SocketSend(int sockFd, char* buf, int sz)
+{
+    int sent = (int)send(sockFd, buf, sz, 0);
+    if (sent == -1) {
+        switch (errno) {
+    #if EAGAIN != SOCKET_EWOULDBLOCK
+        case EAGAIN: /* EAGAIN == EWOULDBLOCK on some systems, but not others */
+    #endif
+        case SOCKET_EWOULDBLOCK:
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        case SOCKET_ECONNRESET:
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        case SOCKET_EINTR:
+            return WOLFSSL_CBIO_ERR_ISR;
+        case SOCKET_EPIPE:
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        default:
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else if (sent == 0) {
+        return 0;
+    }
+    return sent;
+}
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+static int ReceiveFrom(WOLFSSL *ssl, int sd, char *buf, int sz)
+{
+    int recvd;
+    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
+    struct sockaddr peer;
+    socklen_t peerSz = 0;
+
+    if (DoneHandShake) dtls_timeout = 0;
+
+    if (!wolfSSL_get_using_nonblock(ssl)) {
+        struct timeval timeout;
+        XMEMSET(&timeout, 0, sizeof(timeout));
+        timeout.tv_sec = dtls_timeout;
+
+        if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
+                       sizeof(timeout)) != 0) {
+                printf("setsockopt rcvtimeo failed\n");
+        }
+    }
+
+    recvd = (int)recvfrom(sd, buf, sz, 0, (SOCKADDR*)&peer, &peerSz);
+
+    if (recvd < 0) {
+
+        if (errno == SOCKET_EWOULDBLOCK || errno == SOCKET_EAGAIN) {
+            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
+                return WOLFSSL_CBIO_ERR_WANT_READ;
+            }
+            else {
+                return WOLFSSL_CBIO_ERR_TIMEOUT;
+            }
+        }
+        else if (errno == SOCKET_ECONNRESET) {
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (errno == SOCKET_EINTR) {
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (errno == SOCKET_ECONNREFUSED) {
+            return WOLFSSL_CBIO_ERR_WANT_READ;
+        }
+        else {
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+    else {
+        if (recvd == 0) {
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+    }
+
+    return recvd;
+}
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_CLIENT)
+static int SendTo(int sd, char *buf, int sz, const struct sockaddr *peer,
+                  socklen_t peerSz)
+{
+    int sent;
+
+    sent = (int)sendto(sd, buf, sz, 0, peer, peerSz);
+
+    if (sent < 0) {
+        if (errno == SOCKET_EWOULDBLOCK || errno == SOCKET_EAGAIN) {
+            return WOLFSSL_CBIO_ERR_WANT_WRITE;
+        }
+        else if (errno == SOCKET_ECONNRESET) {
+            return WOLFSSL_CBIO_ERR_CONN_RST;
+        }
+        else if (errno == SOCKET_EINTR) {
+            return WOLFSSL_CBIO_ERR_ISR;
+        }
+        else if (errno == SOCKET_EPIPE) {
+            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
+        }
+        else {
+            return WOLFSSL_CBIO_ERR_GENERAL;
+        }
+    }
+
+    return sent;
+}
+
+static int myDoneHsCb(WOLFSSL* ssl, void* user_ctx)
+{
+    (void) ssl;
+    (void) user_ctx;
+
+    DoneHandShake = 1;
+    return 1;
+}
+#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_CLIENT */
+
+#ifndef NO_WOLFSSL_SERVER
+static int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    info_t* info = (info_t*)ctx;
+    (void)ssl;
+#ifdef HAVE_PTHREAD
+    if (info->useLocalMem)
+        return ServerMemSend(info, buf, sz);
+#endif
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_CLIENT)
+    if (info->doDTLS) {
+        return SendTo(info->server.sockFd, buf, sz,
+            (const struct sockaddr*)&info->clientAddr, sizeof(info->clientAddr));
+    } else
+#endif
+        return SocketSend(info->server.sockFd, buf, sz);
+}
+static int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    info_t* info = (info_t*)ctx;
+    (void)ssl;
+#ifdef HAVE_PTHREAD
+    if (info->useLocalMem)
+        return ServerMemRecv(info, buf, sz);
+#endif
+#ifdef WOLFSSL_DTLS
+    if (info->doDTLS) {
+        return ReceiveFrom(ssl, info->server.sockFd, buf, sz);
+    } else
+#endif
+        return SocketRecv(info->server.sockFd, buf, sz);
+}
+#endif /* !NO_WOLFSSL_SERVER */
+
+#ifndef NO_WOLFSSL_CLIENT
+static int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    info_t* info = (info_t*)ctx;
+    (void)ssl;
+#ifdef HAVE_PTHREAD
+    if (info->useLocalMem)
+        return ClientMemSend(info, buf, sz);
+#endif
+#ifdef WOLFSSL_DTLS
+    if (info->doDTLS) {
+        return SendTo(info->client.sockFd, buf, sz,
+            (const struct sockaddr*)&info->serverAddr, sizeof(info->serverAddr));
+    } else
+#endif
+        return SocketSend(info->client.sockFd, buf, sz);
+}
+static int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
+{
+    info_t* info = (info_t*)ctx;
+    (void)ssl;
+#ifdef HAVE_PTHREAD
+    if (info->useLocalMem)
+        return ClientMemRecv(info, buf, sz);
+#endif
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+    if (info->doDTLS) {
+        return ReceiveFrom(ssl, info->client.sockFd, buf, sz);
+    } else
+#endif
+        return SocketRecv(info->client.sockFd, buf, sz);
+}
+#endif /* !NO_WOLFSSL_CLIENT */
+
+static void CloseAndCleanupSocket(int* sockFd)
+{
+    if (*sockFd != -1) {
+        close(*sockFd);
+        *sockFd = -1;
+    }
+#ifdef WOLFSSL_DTLS
+    DoneHandShake = 0;
+#endif
+}
+
+#ifdef BENCH_USE_NONBLOCK
+static int SetSocketNonBlocking(int sockFd)
+{
+    int flags = fcntl(sockFd, F_GETFL, 0);
+    if (flags < 0) {
+        printf("fcntl get failed\n");
+        return -1;
+    }
+    flags = fcntl(sockFd, F_SETFL, flags | O_NONBLOCK);
+    if (flags < 0) {
+        printf("fcntl set failed\n");
+        return -1;
+    }
+    return 0;
+}
+#endif
+
+#ifndef NO_WOLFSSL_CLIENT
+static int SetupSocketAndConnect(info_t* info, const char* host,
+    word32 port)
+{
+    struct sockaddr_in servAddr;
+    struct hostent* entry;
+
+    /* Setup server address */
+    XMEMSET(&servAddr, 0, sizeof(servAddr));
+    servAddr.sin_family = AF_INET;
+    servAddr.sin_port = htons(port);
+
+    /* Resolve host */
+    entry = gethostbyname(host);
+    if (entry) {
+        XMEMCPY(&servAddr.sin_addr.s_addr, entry->h_addr_list[0],
+            entry->h_length);
+    }
+    else {
+        servAddr.sin_addr.s_addr = inet_addr(host);
+    }
+
+#ifdef WOLFSSL_DTLS
+    if (info->doDTLS) {
+        /* Create the SOCK_DGRAM socket type is implemented on the User
+        *  Datagram Protocol/Internet Protocol(UDP/IP protocol).*/
+        if ((info->client.sockFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+            printf("ERROR: failed to create the SOCK_DGRAM socket\n");
+            return -1;
+        }
+        XMEMCPY(&info->serverAddr, &servAddr, sizeof(servAddr));
+    } else {
+#endif
+    /* Create a socket that uses an Internet IPv4 address,
+     * Sets the socket to be stream based (TCP),
+     * 0 means choose the default protocol. */
+    if ((info->client.sockFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+        printf("ERROR: failed to create the socket\n");
+        return -1;
+    }
+
+    /* Connect to the server */
+    if (connect(info->client.sockFd, (struct sockaddr*)&servAddr,
+                                                    sizeof(servAddr)) == -1) {
+        printf("ERROR: failed to connect\n");
+        return -1;
+    }
+#ifdef WOLFSSL_DTLS
+    }
+#endif
+
+#ifdef BENCH_USE_NONBLOCK
+    if (SetSocketNonBlocking(info->client.sockFd) != 0) {
+        return -1;
+    }
+#endif
+
+    if (info->showVerbose) {
+        printf("Connected to %s on port %d\n", host, port);
+    }
+
+    return 0;
+}
+
+static int bench_tls_client(info_t* info)
+{
+    byte *writeBuf = NULL, *readBuf = NULL;
+    double start, total = 0;
+    int ret, readBufSz;
+    WOLFSSL_CTX* cli_ctx = NULL;
+    WOLFSSL* cli_ssl = NULL;
+    int haveShownPeerInfo = 0;
+    int tls13 = XSTRNCMP(info->cipher, "TLS13", 5) == 0;
+    int total_sz;
+
+    total = gettime_secs(0);
+
+    /* set up client */
+#ifdef WOLFSSL_DTLS
+    if(info->doDTLS) {
+        if (tls13) return WOLFSSL_SUCCESS;
+        cli_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method());
+    } else
+#endif
+#ifdef WOLFSSL_TLS13
+    if (tls13)
+        cli_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+#endif
+    if (!tls13)
+#ifdef WOLFSSL_DTLS
+        if(!info->doDTLS)
+#endif
+#if !defined(WOLFSSL_TLS13)
+        cli_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
+#elif !defined(WOLFSSL_NO_TLS12)
+        cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
+#endif
+
+    if (cli_ctx == NULL) {
+        printf("error creating ctx\n");
+        ret = MEMORY_E; goto exit;
+    }
+
+#ifndef NO_CERTS
+#ifdef HAVE_ECC
+    if (XSTRSTR(info->cipher, "ECDSA")) {
+        ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_ecc_cert_der_256,
+            sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
+    }
+    else
+#endif
+    {
+        ret = wolfSSL_CTX_load_verify_buffer(cli_ctx, ca_cert_der_2048,
+            sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1);
+    }
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("error loading CA\n");
+        goto exit;
+    }
+#endif
+
+    wolfSSL_CTX_SetIOSend(cli_ctx, ClientSend);
+    wolfSSL_CTX_SetIORecv(cli_ctx, ClientRecv);
+
+    /* set cipher suite */
+    ret = wolfSSL_CTX_set_cipher_list(cli_ctx, info->cipher);
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("error setting cipher suite\n");
+        goto exit;
+    }
+
+#ifndef NO_DH
+    ret = wolfSSL_CTX_SetMinDhKey_Sz(cli_ctx, MIN_DHKEY_BITS);
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("Error setting minimum DH key size\n");
+        goto exit;
+    }
+#endif
+
+    /* Allocate and initialize a packet sized buffer */
+    writeBuf = (unsigned char*)XMALLOC(info->packetSize, NULL,
+        DYNAMIC_TYPE_TMP_BUFFER);
+    if (writeBuf == NULL) {
+        printf("failed to allocate write memory\n");
+        ret = MEMORY_E; goto exit;
+    }
+
+    /* Allocate read buffer */
+    readBufSz = info->packetSize;
+    readBuf = (unsigned char*)XMALLOC(readBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (readBuf == NULL) {
+        printf("failed to allocate read memory\n");
+        ret = MEMORY_E; goto exit;
+    }
+
+    /* BENCHMARK CONNECTIONS LOOP */
+    while (!info->client.shutdown) {
+        int writeSz = info->packetSize;
+    #ifdef BENCH_USE_NONBLOCK
+        int err;
+    #endif
+
+    #ifdef HAVE_PTHREAD
+        if (!info->useLocalMem)
+    #endif
+        {
+            /* Setup socket and connection */
+            ret = SetupSocketAndConnect(info, info->host, info->port);
+            if (ret != 0) goto exit;
+        }
+
+        cli_ssl = wolfSSL_new(cli_ctx);
+        if (cli_ssl == NULL) {
+            printf("error creating client object\n");
+            goto exit;
+        }
+
+#ifdef WOLFSSL_DTLS
+        if (info->doDTLS) {
+            ret = wolfSSL_dtls_set_peer(cli_ssl, &info->serverAddr,
+                                                    sizeof(info->serverAddr));
+            if (ret != WOLFSSL_SUCCESS) {
+                printf("error setting dtls peer\n");
+                goto exit;
+            }
+            ret = wolfSSL_SetHsDoneCb(cli_ssl, myDoneHsCb, NULL);
+            if (ret != WOLFSSL_SUCCESS) {
+                printf("error handshake done callback\n");
+                goto exit;
+            }
+        }
+#endif
+        wolfSSL_SetIOReadCtx(cli_ssl, info);
+        wolfSSL_SetIOWriteCtx(cli_ssl, info);
+
+#if defined(HAVE_PTHREAD) && defined(WOLFSSL_DTLS)
+        /* synchronize with server */
+        if (info->doDTLS && !info->clientOrserverOnly) {
+            pthread_mutex_lock(&info->dtls_mutex);
+            if (info->serverReady != 1) {
+                pthread_cond_wait(&info->dtls_cond, &info->dtls_mutex);
+            }
+            /* for next loop */
+            info->serverReady = 0;
+            pthread_mutex_unlock(&info->dtls_mutex);
+        }
+#endif
+        /* perform connect */
+        start = gettime_secs(1);
+    #ifndef BENCH_USE_NONBLOCK
+        ret = wolfSSL_connect(cli_ssl);
+    #else
+        do
+        {
+            ret = wolfSSL_connect(cli_ssl);
+            err = wolfSSL_get_error(cli_ssl, ret);
+        }
+        while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
+    #endif
+        start = gettime_secs(0) - start;
+        if (ret != WOLFSSL_SUCCESS) {
+            printf("error connecting client\n");
+            ret = wolfSSL_get_error(cli_ssl, ret);
+            goto exit;
+        }
+        info->client_stats.connTime += start;
+        info->client_stats.connCount++;
+
+        if ((info->showPeerInfo) && (!haveShownPeerInfo)) {
+            haveShownPeerInfo = 1;
+            showPeer(cli_ssl);
+        }
+
+        /* check for run time completion and issue shutdown */
+        if (gettime_secs(0) - total >= info->runTimeSec) {
+            info->client.shutdown = 1;
+
+            writeSz = (int)XSTRLEN(kShutdown) + 1;
+            XMEMCPY(writeBuf, kShutdown, writeSz); /* include null term */
+            if (info->showVerbose) {
+                printf("Sending shutdown\n");
+            }
+
+            ret = wolfSSL_write(cli_ssl, writeBuf, writeSz);
+            if (ret < 0) {
+                printf("error on client write\n");
+                ret = wolfSSL_get_error(cli_ssl, ret);
+                goto exit;
+            }
+        }
+        else {
+            XMEMSET(writeBuf, 0, info->packetSize);
+            XSTRNCPY((char*)writeBuf, kTestStr, info->packetSize);
+        }
+
+        /* write / read echo loop */
+        ret = 0;
+        total_sz = 0;
+        while (ret == 0 && total_sz < info->maxSize && !info->client.shutdown) {
+            /* write test message to server */
+            start = gettime_secs(1);
+        #ifndef BENCH_USE_NONBLOCK
+            ret = wolfSSL_write(cli_ssl, writeBuf, writeSz);
+        #else
+            do {
+                ret = wolfSSL_write(cli_ssl, writeBuf, writeSz);
+                err = wolfSSL_get_error(cli_ssl, ret);
+            }
+            while (err == WOLFSSL_ERROR_WANT_WRITE);
+        #endif
+            info->client_stats.txTime += gettime_secs(0) - start;
+            if (ret < 0) {
+                printf("error on client write\n");
+                ret = wolfSSL_get_error(cli_ssl, ret);
+                goto exit;
+            }
+            info->client_stats.txTotal += ret;
+            total_sz += ret;
+
+            /* read echo of message from server */
+            XMEMSET(readBuf, 0, readBufSz);
+            start = gettime_secs(1);
+        #ifndef BENCH_USE_NONBLOCK
+            ret = wolfSSL_read(cli_ssl, readBuf, readBufSz);
+        #else
+            do {
+                ret = wolfSSL_read(cli_ssl, readBuf, readBufSz);
+                err = wolfSSL_get_error(cli_ssl, ret);
+            }
+            while (err == WOLFSSL_ERROR_WANT_READ);
+        #endif
+            info->client_stats.rxTime += gettime_secs(0) - start;
+            if (ret < 0) {
+                printf("error on client read\n");
+                ret = wolfSSL_get_error(cli_ssl, ret);
+                goto exit;
+            }
+            info->client_stats.rxTotal += ret;
+            ret = 0; /* reset return code */
+
+            /* validate echo */
+            if (XMEMCMP((char*)writeBuf, (char*)readBuf, writeSz) != 0) {
+                printf("echo check failed!\n");
+                ret = wolfSSL_get_error(cli_ssl, ret);
+                goto exit;
+            }
+        }
+
+        CloseAndCleanupSocket(&info->client.sockFd);
+
+        wolfSSL_free(cli_ssl);
+        cli_ssl = NULL;
+    }
+
+exit:
+
+    if (ret != 0 && ret != WOLFSSL_SUCCESS) {
+        printf("Client Error: %d (%s)\n", ret,
+            wolfSSL_ERR_reason_error_string(ret));
+    }
+
+    /* clean up */
+    CloseAndCleanupSocket(&info->client.sockFd);
+    if (cli_ssl != NULL)
+        wolfSSL_free(cli_ssl);
+    if (cli_ctx != NULL)
+        wolfSSL_CTX_free(cli_ctx);
+    XFREE(readBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(writeBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    info->client.ret = ret;
+
+    return ret;
+}
+
+#ifdef HAVE_PTHREAD
+static void* client_thread(void* args)
+{
+    int ret;
+    info_t* info = (info_t*)args;
+
+    ret = bench_tls_client(info);
+
+    pthread_cond_signal(&info->to_server.cond);
+    info->to_client.done = 1;
+    info->client.ret = ret;
+
+    return NULL;
+}
+#endif /* HAVE_PTHREAD */
+#endif /* !NO_WOLFSSL_CLIENT */
+
+
+#ifndef NO_WOLFSSL_SERVER
+static int SetupSocketAndListen(int* listenFd, word32 port, int doDTLS)
+{
+    struct sockaddr_in servAddr;
+#if defined(_MSC_VER) || defined(__MINGW32__)
+    char optval = 1;
+#else
+    int optval = 1;
+#endif
+#ifndef WOLFSSL_DTLS
+    (void) doDTLS;
+#endif
+    /* Setup server address */
+    XMEMSET(&servAddr, 0, sizeof(servAddr));
+    servAddr.sin_family = AF_INET;
+    servAddr.sin_port = htons(port);
+    servAddr.sin_addr.s_addr = INADDR_ANY;
+
+#ifdef WOLFSSL_DTLS
+    if (doDTLS) {
+        /* Create a socket that is implemented on the User Datagram Protocol/
+        * Interet Protocol(UDP/IP protocol). */
+        if((*listenFd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+            printf("ERROR: failed to create the socket\n");
+            return -1;
+        }
+    } else
+#endif
+    /* Create a socket that uses an Internet IPv4 address,
+     * Sets the socket to be stream based (TCP),
+     * 0 means choose the default protocol. */
+    if ((*listenFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+        printf("ERROR: failed to create the socket\n");
+        return -1;
+    }
+
+    /* allow reuse */
+    if (setsockopt(*listenFd, SOL_SOCKET, SO_REUSEADDR,
+                &optval, sizeof(optval)) == -1) {
+        printf("setsockopt SO_REUSEADDR failed\n");
+        return -1;
+    }
+
+    /* Connect to the server */
+    if (bind(*listenFd, (struct sockaddr*)&servAddr,
+                                                    sizeof(servAddr)) == -1) {
+        printf("ERROR: failed to bind\n");
+        return -1;
+    }
+#ifdef WOLFSSL_DTLS
+    if (!doDTLS)
+#endif
+    if (listen(*listenFd, 5) != 0) {
+        printf("ERROR: failed to listen\n");
+        return -1;
+    }
+
+#ifdef BENCH_USE_NONBLOCK
+    if (SetSocketNonBlocking(*listenFd) != 0) {
+        return -1;
+    }
+#endif
+
+    return 0;
+}
+
+static int SocketWaitClient(info_t* info)
+{
+    int connd;
+    struct sockaddr_in clientAddr;
+    socklen_t size = sizeof(clientAddr);
+#ifdef WOLFSSL_DTLS
+    char msg[64];
+
+    if (info->doDTLS) {
+#ifdef HAVE_PTHREAD
+        if (!info->clientOrserverOnly) {
+            pthread_mutex_lock(&info->dtls_mutex);
+            info->serverReady = 1;
+            pthread_cond_signal(&info->dtls_cond);
+            pthread_mutex_unlock(&info->dtls_mutex);
+        }
+#endif
+        connd = (int)recvfrom(info->listenFd, (char *)msg, sizeof(msg),
+            MSG_PEEK, (struct sockaddr*)&clientAddr, &size);
+        if (connd < -1) {
+            printf("ERROR: failed to accept the connection\n");
+            return -1;
+        }
+        XMEMCPY(&info->clientAddr, &clientAddr, sizeof(clientAddr));
+        info->server.sockFd = info->listenFd;
+    } else {
+#endif
+    if ((connd = accept(info->listenFd, (struct sockaddr*)&clientAddr, &size)) == -1) {
+        if (errno == SOCKET_EWOULDBLOCK)
+            return -2;
+        printf("ERROR: failed to accept the connection\n");
+        return -1;
+    }
+    info->server.sockFd = connd;
+#ifdef WOLFSSL_DTLS
+    }
+#endif
+
+    if (info->showVerbose) {
+        printf("Got client %d\n", connd);
+    }
+
+    return 0;
+}
+static void CloseAndCleanupListenSocket(int* listenFd)
+{
+    if (*listenFd != -1) {
+        close(*listenFd);
+        *listenFd = -1;
+    }
+}
+
+static int bench_tls_server(info_t* info)
+{
+    byte *readBuf = NULL;
+    double start;
+    int ret, len = 0, readBufSz;
+    WOLFSSL_CTX* srv_ctx = NULL;
+    WOLFSSL* srv_ssl = NULL;
+    int tls13 = XSTRNCMP(info->cipher, "TLS13", 5) == 0;
+    int total_sz;
+
+    /* set up server */
+#ifdef WOLFSSL_DTLS
+    if(info->doDTLS) {
+        if(tls13) return WOLFSSL_SUCCESS;
+        srv_ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method());
+    } else {
+#endif
+#ifdef WOLFSSL_TLS13
+    if (tls13)
+        srv_ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method());
+#endif
+    if (!tls13)
+        srv_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method());
+#ifdef WOLFSSL_DTLS
+    }
+#endif
+    if (srv_ctx == NULL) {
+        printf("error creating server ctx\n");
+        ret = MEMORY_E; goto exit;
+    }
+
+#ifndef NO_CERTS
+#ifdef HAVE_ECC
+    if (XSTRSTR(info->cipher, "ECDSA")) {
+        ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, ecc_key_der_256,
+            sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
+    }
+    else
+#endif
+    {
+        ret = wolfSSL_CTX_use_PrivateKey_buffer(srv_ctx, server_key_der_2048,
+            sizeof_server_key_der_2048, WOLFSSL_FILETYPE_ASN1);
+    }
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("error loading server key\n");
+        goto exit;
+    }
+
+#ifdef HAVE_ECC
+    if (XSTRSTR(info->cipher, "ECDSA")) {
+        ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, serv_ecc_der_256,
+            sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
+    }
+    else
+#endif
+    {
+        ret = wolfSSL_CTX_use_certificate_buffer(srv_ctx, server_cert_der_2048,
+            sizeof_server_cert_der_2048, WOLFSSL_FILETYPE_ASN1);
+    }
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("error loading server cert\n");
+        goto exit;
+    }
+#endif /* !NO_CERTS */
+
+    wolfSSL_CTX_SetIOSend(srv_ctx, ServerSend);
+    wolfSSL_CTX_SetIORecv(srv_ctx, ServerRecv);
+
+    /* set cipher suite */
+    ret = wolfSSL_CTX_set_cipher_list(srv_ctx, info->cipher);
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("error setting cipher suite\n");
+        goto exit;
+    }
+
+#ifndef NO_DH
+    ret = wolfSSL_CTX_SetMinDhKey_Sz(srv_ctx, MIN_DHKEY_BITS);
+    if (ret != WOLFSSL_SUCCESS) {
+        printf("Error setting minimum DH key size\n");
+        goto exit;
+    }
+#endif
+
+    /* Allocate read buffer */
+    readBufSz = info->packetSize;
+    readBuf = (unsigned char*)XMALLOC(readBufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (readBuf == NULL) {
+        printf("failed to allocate read memory\n");
+        ret = MEMORY_E; goto exit;
+    }
+
+    /* BENCHMARK CONNECTIONS LOOP */
+    while (!info->server.shutdown) {
+    #ifdef BENCH_USE_NONBLOCK
+        int err;
+    #endif
+
+    #ifdef HAVE_PTHREAD
+        if (!info->useLocalMem)
+    #endif
+        {
+            /* Accept client connections */
+            ret = SocketWaitClient(info);
+        #ifdef BENCH_USE_NONBLOCK
+            if (ret == -2) {
+                XSLEEP_MS(0);
+                continue;
+            }
+        #endif
+            if (ret != 0) {
+                goto exit;
+            }
+        }
+
+        srv_ssl = wolfSSL_new(srv_ctx);
+        if (srv_ssl == NULL) {
+            printf("error creating server object\n");
+            ret = MEMORY_E; goto exit;
+        }
+#ifdef WOLFSSL_DTLS
+        if (info->doDTLS) {
+            ret = wolfSSL_dtls_set_peer(srv_ssl, &info->clientAddr,
+                        sizeof(info->clientAddr));
+            if (ret != WOLFSSL_SUCCESS) {
+                printf("error setting dtls peer\n");
+                goto exit;
+            }
+        }
+#endif
+
+        wolfSSL_SetIOReadCtx(srv_ssl, info);
+        wolfSSL_SetIOWriteCtx(srv_ssl, info);
+    #ifndef NO_DH
+        wolfSSL_SetTmpDH(srv_ssl, dhp, sizeof(dhp), dhg, sizeof(dhg));
+    #endif
+
+        /* accept TLS connection */
+        start = gettime_secs(1);
+    #ifndef BENCH_USE_NONBLOCK
+        ret = wolfSSL_accept(srv_ssl);
+    #else
+        do {
+            ret = wolfSSL_accept(srv_ssl);
+            err = wolfSSL_get_error(srv_ssl, ret);
+        }
+        while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
+    #endif
+        start = gettime_secs(0) - start;
+        if (ret != WOLFSSL_SUCCESS) {
+            printf("error on server accept\n");
+            ret = wolfSSL_get_error(srv_ssl, ret);
+            goto exit;
+        }
+
+        info->server_stats.connTime += start;
+        info->server_stats.connCount++;
+
+        /* echo loop */
+        ret = 0;
+        total_sz = 0;
+        while (ret == 0 && total_sz < info->maxSize) {
+            double rxTime;
+
+            /* read message from client */
+            XMEMSET(readBuf, 0, readBufSz);
+            start = gettime_secs(1);
+        #ifndef BENCH_USE_NONBLOCK
+            ret = wolfSSL_read(srv_ssl, readBuf, readBufSz);
+        #else
+            do {
+                ret = wolfSSL_read(srv_ssl, readBuf, readBufSz);
+                err = wolfSSL_get_error(srv_ssl, ret);
+            }
+            while (err == WOLFSSL_ERROR_WANT_READ);
+        #endif
+            rxTime = gettime_secs(0) - start;
+
+            /* shutdown signals, no more connections for this cipher */
+            if (XSTRSTR((const char*)readBuf, kShutdown) != NULL) {
+                info->server.shutdown = 1;
+                if (info->showVerbose) {
+                    printf("Server shutdown done\n");
+                }
+                ret = 0; /* success */
+                break;
+            }
+
+            info->server_stats.rxTime += rxTime;
+            if (ret < 0) {
+                printf("error on server read\n");
+                ret = wolfSSL_get_error(srv_ssl, ret);
+                goto exit;
+            }
+            info->server_stats.rxTotal += ret;
+            len = ret;
+            total_sz += ret;
+
+            /* write message back to client */
+            start = gettime_secs(1);
+        #ifndef BENCH_USE_NONBLOCK
+            ret = wolfSSL_write(srv_ssl, readBuf, len);
+        #else
+            do {
+                ret = wolfSSL_write(srv_ssl, readBuf, len);
+                err = wolfSSL_get_error(srv_ssl, ret);
+            }
+            while (err == WOLFSSL_ERROR_WANT_WRITE);
+        #endif
+            info->server_stats.txTime += gettime_secs(0) - start;
+            if (ret < 0) {
+                printf("error on server write\n");
+                ret = wolfSSL_get_error(srv_ssl, ret);
+                goto exit;
+            }
+            info->server_stats.txTotal += ret;
+            ret = 0; /* reset return code */
+        }
+
+        CloseAndCleanupSocket(&info->server.sockFd);
+
+        wolfSSL_free(srv_ssl);
+        srv_ssl = NULL;
+#ifdef WOLFSSL_DTLS
+        if (info->doDTLS) {
+            SetupSocketAndListen(&info->listenFd, info->port, info->doDTLS);
+        }
+#endif
+
+    }
+
+exit:
+
+    if (ret != 0 && ret != WOLFSSL_SUCCESS) {
+        printf("Server Error: %d (%s)\n", ret,
+            wolfSSL_ERR_reason_error_string(ret));
+    }
+
+    /* clean up */
+    CloseAndCleanupSocket(&info->server.sockFd);
+    if (srv_ssl != NULL)
+        wolfSSL_free(srv_ssl);
+    if (srv_ctx != NULL)
+        wolfSSL_CTX_free(srv_ctx);
+    XFREE(readBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    info->server.ret = ret;
+
+    return ret;
+}
+
+#ifdef HAVE_PTHREAD
+static void* server_thread(void* args)
+{
+    int ret = 0;
+    info_t* info = (info_t*)args;
+
+    if (!info->useLocalMem) {
+        /* Setup TLS server listener */
+#ifdef WOLFSSL_DTLS
+        ret = SetupSocketAndListen(&info->listenFd, info->port, info->doDTLS);
+#else
+        ret = SetupSocketAndListen(&info->listenFd, info->port, 0);
+#endif
+    }
+    if (ret == 0) {
+        ret = bench_tls_server(info);
+
+        if (!info->useLocalMem) {
+            CloseAndCleanupListenSocket(&info->listenFd);
+        }
+    }
+
+    pthread_cond_signal(&info->to_client.cond);
+    info->to_server.done = 1;
+    info->server.ret = ret;
+
+    return NULL;
+}
+#endif /* HAVE_PTHREAD */
+#endif /* !NO_WOLFSSL_SERVER */
+
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
+static void print_stats(stats_t* wcStat, const char* desc, const char* cipher, int verbose)
+{
+    const char* formatStr;
+
+    if (verbose) {
+        formatStr = "wolfSSL %s Benchmark on %s:\n"
+               "\tTotal       : %9d bytes\n"
+               "\tNum Conns   : %9d\n"
+               "\tRx Total    : %9.3f ms\n"
+               "\tTx Total    : %9.3f ms\n"
+               "\tRx          : %9.3f MB/s\n"
+               "\tTx          : %9.3f MB/s\n"
+               "\tConnect     : %9.3f ms\n"
+               "\tConnect Avg : %9.3f ms\n";
+    }
+    else {
+        formatStr = "%-6s  %-33s  %11d  %9d  %9.3f  %9.3f  %9.3f  %9.3f  %17.3f  %15.3f\n";
+    }
+
+    printf(formatStr,
+           desc,
+           cipher,
+           wcStat->txTotal + wcStat->rxTotal,
+           wcStat->connCount,
+           wcStat->rxTime * 1000,
+           wcStat->txTime * 1000,
+           wcStat->rxTotal / wcStat->rxTime / 1024 / 1024,
+           wcStat->txTotal / wcStat->txTime / 1024 / 1024,
+           wcStat->connTime * 1000,
+           wcStat->connTime * 1000 / wcStat->connCount);
+}
+
+static void Usage(void)
+{
+    printf("tls_bench "    LIBWOLFSSL_VERSION_STRING
+           " NOTE: All files relative to wolfSSL home dir\n");
+    printf("-?          Help, print this usage\n");
+    printf("-c          Run as client only, no threading and uses sockets\n");
+    printf("-s          Run as server only, no threading and uses sockets\n");
+    printf("-h          Host (default %s)\n", BENCH_DEFAULT_HOST);
+    printf("-P          Port (default %d)\n", BENCH_DEFAULT_PORT);
+    printf("-e          List Every cipher suite available\n");
+    printf("-i          Show peer info\n");
+    printf("-l <str>    Cipher suite list (: delimited)\n");
+    printf("-t <num>    Time <num> (seconds) to run each test (default %d)\n", BENCH_RUNTIME_SEC);
+    printf("-p <num>    The packet size <num> in bytes [1-16kB] (default %d)\n", TEST_PACKET_SIZE);
+#ifdef WOLFSSL_DTLS
+    printf("            In the case of DTLS, [1-8kB] (default %d)\n", TEST_DTLS_PACKET_SIZE);
+#endif
+    printf("-S <num>    The total size <num> in bytes (default %d)\n", TEST_MAX_SIZE);
+    printf("-v          Show verbose output\n");
+#ifdef DEBUG_WOLFSSL
+    printf("-d          Enable debug messages\n");
+#endif
+#ifdef HAVE_PTHREAD
+    printf("-T <num>    Number of threaded server/client pairs (default %d)\n", NUM_THREAD_PAIRS);
+    printf("-m          Use local memory, not socket\n");
+#endif
+#ifdef WOLFSSL_DTLS
+    printf("-u          Use DTLS\n");
+#endif
+}
+
+static void ShowCiphers(void)
+{
+    char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE];
+
+    int ret = wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers));
+
+    if (ret == WOLFSSL_SUCCESS)
+        printf("%s\n", ciphers);
+}
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+int bench_tls(void* args)
+{
+    int ret = 0;
+    info_t *theadInfo = NULL, *info;
+    stats_t cli_comb, srv_comb;
+    int i;
+    char *cipher, *next_cipher, *ciphers = NULL;
+    int     argc = 0;
+    char**  argv = NULL;
+    int    ch;
+
+    /* Vars configured by command line arguments */
+    int argRuntimeSec = BENCH_RUNTIME_SEC;
+    char *argCipherList = NULL;
+    int argTestPacketSize = TEST_PACKET_SIZE;
+    int argTestMaxSize = TEST_MAX_SIZE;
+    int argThreadPairs = NUM_THREAD_PAIRS;
+    int argShowVerbose = SHOW_VERBOSE;
+    int argClientOnly = 0;
+    int argServerOnly = 0;
+    const char* argHost = BENCH_DEFAULT_HOST;
+    int argPort = BENCH_DEFAULT_PORT;
+    int argShowPeerInfo = 0;
+#ifdef HAVE_PTHREAD
+    int doShutdown;
+#endif
+#if !defined(NO_WOLFSSL_SERVER) || defined(HAVE_PTHREAD)
+    int argLocalMem = 0;
+    int listenFd = -1;
+#endif
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+    int option_p = 0;
+#endif
+#ifdef WOLFSSL_DTLS
+    int doDTLS = 0;
+#endif
+    if (args != NULL) {
+        argc = ((func_args*)args)->argc;
+        argv = ((func_args*)args)->argv;
+        ((func_args*)args)->return_code = -1; /* error state */
+    }
+
+    /* Initialize wolfSSL */
+    wolfSSL_Init();
+
+    /* Parse command line arguments */
+    while ((ch = mygetopt(argc, argv, "?" "udeil:p:t:vT:sch:P:mS:")) != -1) {
+        switch (ch) {
+            case '?' :
+                Usage();
+                goto exit;
+
+            case 's':
+                argServerOnly = 1;
+                break;
+
+            case 'c':
+                argClientOnly = 1;
+                break;
+
+            case 'h':
+                argHost = myoptarg;
+                break;
+
+            case 'P':
+                argPort = atoi(myoptarg);
+                break;
+
+            case 'd' :
+            #ifdef DEBUG_WOLFSSL
+                wolfSSL_Debugging_ON();
+            #endif
+                break;
+
+            case 'e' :
+                ShowCiphers();
+                goto exit;
+
+            case 'i' :
+                argShowPeerInfo = 1;
+                break;
+
+            case 'l' :
+                argCipherList = myoptarg;
+                break;
+
+            case 'p' :
+                argTestPacketSize = atoi(myoptarg);
+                if (argTestPacketSize > (16 * 1024)) {
+                    printf("Invalid packet size %d\n", argTestPacketSize);
+                    Usage();
+                    ret = MY_EX_USAGE; goto exit;
+                }
+            #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+                option_p = 1;
+            #endif
+                break;
+
+            case 'S' :
+                argTestMaxSize = atoi(myoptarg);
+                break;
+
+            case 't' :
+                argRuntimeSec = atoi(myoptarg);
+                break;
+
+            case 'v' :
+                argShowVerbose = 1;
+                break;
+
+            case 'T' :
+            #ifdef HAVE_PTHREAD
+                argThreadPairs = atoi(myoptarg);
+            #endif
+                break;
+
+            case 'm':
+            #ifdef HAVE_PTHREAD
+                argLocalMem = 1;
+            #endif
+                break;
+            case 'u':
+            #ifdef WOLFSSL_DTLS
+                doDTLS = 1;
+                #ifdef BENCH_USE_NONBLOCK
+                    printf("tls_bench hasn't yet supported DTLS "
+                       "non-blocking mode.\n");
+                    Usage();
+                    ret = MY_EX_USAGE; goto exit;
+                #endif
+            #endif
+                break;
+            default:
+                Usage();
+                ret = MY_EX_USAGE; goto exit;
+        }
+    }
+
+    /* reset for test cases */
+    myoptind = 0;
+
+    if (argCipherList != NULL) {
+        /* Use the list from CL argument */
+        cipher = argCipherList;
+    }
+    else {
+        /* Run for each cipher */
+        ciphers = (char*)XMALLOC(WOLFSSL_CIPHER_LIST_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (ciphers == NULL) {
+            goto exit;
+        }
+        wolfSSL_get_ciphers(ciphers, WOLFSSL_CIPHER_LIST_MAX_SIZE);
+        cipher = ciphers;
+    }
+
+    /* for server or client side only, only 1 thread is allowed */
+    if (argServerOnly || argClientOnly) {
+        argThreadPairs = 1;
+    }
+#ifndef HAVE_PTHREAD
+    else {
+        printf("Threading is not enabled, so please use -s or -c to indicate side\n");
+        Usage();
+        ret = MY_EX_USAGE; goto exit;
+    }
+#endif
+
+    /* Allocate test info array */
+    theadInfo = (info_t*)XMALLOC(sizeof(info_t) * argThreadPairs, NULL,
+        DYNAMIC_TYPE_TMP_BUFFER);
+    if (theadInfo == NULL) {
+        ret = MEMORY_E; goto exit;
+    }
+    XMEMSET(theadInfo, 0, sizeof(info_t) * argThreadPairs);
+
+#ifndef NO_WOLFSSL_SERVER
+    /* Use same listen socket to avoid timing issues between client and server */
+    if (argServerOnly && !argLocalMem) {
+        /* Setup TLS server listener */
+#ifdef WOLFSSL_DTLS
+        ret = SetupSocketAndListen(&listenFd, argPort, doDTLS);
+#else
+        ret = SetupSocketAndListen(&listenFd, argPort, 0);
+#endif
+        if (ret != 0) goto exit;
+    }
+#endif
+
+#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
+    if (doDTLS) {
+        if (argLocalMem) {
+            printf("tls_bench hasn't yet supported DTLS with local memory.\n");
+            ret = MY_EX_USAGE; goto exit;
+        }
+        if (option_p && argTestPacketSize > TEST_DTLS_PACKET_SIZE){
+            printf("Invalid packet size %d\n", argTestPacketSize);
+            Usage();
+            ret = MY_EX_USAGE; goto exit;
+        } else {
+            /* argTestPacketSize would be default for tcp packet */
+            if (argTestPacketSize >= TEST_PACKET_SIZE)
+                argTestPacketSize = TEST_DTLS_PACKET_SIZE;
+        }
+    }
+#endif
+    printf("Running TLS Benchmarks...\n");
+
+    /* parse by : */
+    while ((cipher != NULL) && (cipher[0] != '\0')) {
+        next_cipher = strchr(cipher, ':');
+        if (next_cipher != NULL) {
+            cipher[next_cipher - cipher] = '\0';
+        }
+
+        if (argShowVerbose) {
+            printf("Cipher: %s\n", cipher);
+        }
+
+        for (i=0; i<argThreadPairs; i++) {
+            info = &theadInfo[i];
+            XMEMSET(info, 0, sizeof(info_t));
+
+            info->host = argHost;
+            info->port = argPort + i; /* threads must have separate ports */
+            info->cipher = cipher;
+            info->packetSize = argTestPacketSize;
+
+            info->runTimeSec = argRuntimeSec;
+            info->maxSize = argTestMaxSize;
+            info->showPeerInfo = argShowPeerInfo;
+            info->showVerbose = argShowVerbose;
+        #ifndef NO_WOLFSSL_SERVER
+            info->listenFd = listenFd;
+        #endif
+            info->client.sockFd = -1;
+            info->server.sockFd = -1;
+
+        #ifdef WOLFSSL_DTLS
+            info->doDTLS = doDTLS;
+        #ifdef HAVE_PTHREAD
+            info->serverReady = 0;
+            if (argServerOnly || argClientOnly) {
+                info->clientOrserverOnly = 1;
+            }
+        #endif
+        #endif
+            if (argClientOnly) {
+            #ifndef NO_WOLFSSL_CLIENT
+                ret = bench_tls_client(info);
+            #endif
+            }
+            else if (argServerOnly) {
+            #ifndef NO_WOLFSSL_SERVER
+                ret = bench_tls_server(info);
+            #endif
+            }
+            else {
+            #ifdef HAVE_PTHREAD
+                info->useLocalMem = argLocalMem;
+                pthread_mutex_init(&info->to_server.mutex, NULL);
+                pthread_mutex_init(&info->to_client.mutex, NULL);
+            #ifdef WOLFSSL_DTLS
+                pthread_mutex_init(&info->dtls_mutex, NULL);
+                pthread_cond_init(&info->dtls_cond, NULL);
+            #endif
+                pthread_cond_init(&info->to_server.cond, NULL);
+                pthread_cond_init(&info->to_client.cond, NULL);
+
+                pthread_create(&info->to_server.tid, NULL, server_thread, info);
+                pthread_create(&info->to_client.tid, NULL, client_thread, info);
+
+                /* State that we won't be joining this thread */
+                pthread_detach(info->to_server.tid);
+                pthread_detach(info->to_client.tid);
+            #endif
+            }
+        }
+
+    #ifdef HAVE_PTHREAD
+        /* For threading, wait for completion */
+        if (!argClientOnly && !argServerOnly) {
+            /* Wait until threads are marked done */
+            do {
+                doShutdown = 1;
+
+                for (i = 0; i < argThreadPairs; ++i) {
+                    info = &theadInfo[i];
+                    if (!info->to_client.done || !info->to_server.done) {
+                        doShutdown = 0;
+                        XSLEEP_MS(1000); /* Allow other threads to run */
+                    }
+
+                }
+            } while (!doShutdown);
+            if (argShowVerbose) {
+                printf("Shutdown complete\n");
+            }
+        }
+    #endif /* HAVE_PTHREAD */
+
+        if (argShowVerbose) {
+            /* print results */
+            for (i = 0; i < argThreadPairs; ++i) {
+                info = &theadInfo[i];
+
+                printf("\nThread %d\n", i);
+            #ifndef NO_WOLFSSL_SERVER
+                if (!argClientOnly)
+                    print_stats(&info->server_stats, "Server", info->cipher, 1);
+            #endif
+            #ifndef NO_WOLFSSL_CLIENT
+                if (!argServerOnly)
+                    print_stats(&info->client_stats, "Client", info->cipher, 1);
+            #endif
+            }
+        }
+
+        /* print combined results for more than one thread */
+        XMEMSET(&cli_comb, 0, sizeof(cli_comb));
+        XMEMSET(&srv_comb, 0, sizeof(srv_comb));
+
+        for (i = 0; i < argThreadPairs; ++i) {
+            info = &theadInfo[i];
+
+            cli_comb.connCount += info->client_stats.connCount;
+            srv_comb.connCount += info->server_stats.connCount;
+
+            cli_comb.connTime += info->client_stats.connTime;
+            srv_comb.connTime += info->server_stats.connTime;
+
+            cli_comb.rxTotal += info->client_stats.rxTotal;
+            srv_comb.rxTotal += info->server_stats.rxTotal;
+
+            cli_comb.rxTime += info->client_stats.rxTime;
+            srv_comb.rxTime += info->server_stats.rxTime;
+
+            cli_comb.txTotal += info->client_stats.txTotal;
+            srv_comb.txTotal += info->server_stats.txTotal;
+
+            cli_comb.txTime += info->client_stats.txTime;
+            srv_comb.txTime += info->server_stats.txTime;
+        }
+
+        if (argShowVerbose) {
+            printf("Totals for %d Threads\n", argThreadPairs);
+        }
+        else {
+            printf("%-6s  %-33s  %11s  %9s  %9s  %9s  %9s  %9s  %17s  %15s\n",
+                "Side", "Cipher", "Total Bytes", "Num Conns", "Rx ms", "Tx ms",
+                "Rx MB/s", "Tx MB/s", "Connect Total ms", "Connect Avg ms");
+        #ifndef NO_WOLFSSL_SERVER
+            if (!argClientOnly)
+                print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0);
+        #endif
+        #ifndef NO_WOLFSSL_CLIENT
+            if (!argServerOnly)
+                print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0);
+        #endif
+        }
+
+        /* target next cipher */
+        cipher = (next_cipher != NULL) ? (next_cipher + 1) : NULL;
+    } /* while */
+
+exit:
+
+#ifndef NO_WOLFSSL_SERVER
+    if (argServerOnly && !argLocalMem) {
+        /* Close server listener */
+        CloseAndCleanupListenSocket(&listenFd);
+    }
+#endif
+
+    /* Cleanup the wolfSSL environment */
+    wolfSSL_Cleanup();
+
+    /* Free theadInfo array */
+    XFREE(theadInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* Free cipher list */
+    XFREE(ciphers, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+
+    /* Return reporting a success */
+    if (args)
+        ((func_args*)args)->return_code = ret;
+
+    return ret;
+}
+#endif /* (!NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER) && !WOLFCRYPT_ONLY && USE_WOLFSSL_IO */
+
+#ifndef NO_MAIN_DRIVER
+
+int main(int argc, char** argv)
+{
+    func_args args;
+
+    args.argc = argc;
+    args.argv = argv;
+    args.return_code = 0;
+
+#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \
+    !defined(WOLFCRYPT_ONLY) && defined(USE_WOLFSSL_IO)
+    bench_tls(&args);
+#endif
+
+    return args.return_code;
+}
+
+#endif /* !NO_MAIN_DRIVER */
diff --git a/ap/lib/libwolfssl/install/share/doc/wolfssl/taoCert.txt b/ap/lib/libwolfssl/install/share/doc/wolfssl/taoCert.txt
new file mode 100644
index 0000000..0973def
--- /dev/null
+++ b/ap/lib/libwolfssl/install/share/doc/wolfssl/taoCert.txt
@@ -0,0 +1,176 @@
+
+***** Create a self signed cert ************
+
+1) openssl genrsa 1024 > client-key.pem
+
+2) openssl req -new -x509 -nodes -sha1 -days 1000 -key client-key.pem > client-cert.pem
+
+3) note md5 would be -md5
+
+-- adding metadata to beginning
+
+3) openssl x509 -in client-cert.pem -text > tmp.pem
+
+4) mv tmp.pem client-cert.pem
+
+
+***** Create a CA, signing authority **********
+
+same as self signed, use ca prefix instead of client
+
+
+***** Create a cert signed by CA **************
+
+1) openssl req -newkey rsa:1024 -sha1 -days 1000 -nodes -keyout server-key.pem > server-req.pem
+
+* note if using existing key do: -new -key keyName
+
+2) copy ca-key.pem ca-cert.srl   (why ????)
+
+3) openssl x509 -req -in server-req.pem -days 1000 -sha1 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
+
+
+***** Adding Subject Key ID and Authentication Key ID extensions to a cert *****
+
+Create a config file for OpenSSL with the example contents:
+
+    [skidakid]
+    subjectKeyIdentifier=hash
+    authorityKeyIdentifier=keyid
+
+Add to the openssl command for creating a cert signed by a CA step 3 the
+following options:
+
+    -extfile <file.cnf> -extensions skidakid
+
+anywhere before the redirect. This will add the cert's public key hash as the
+Subject Key Identifier, and the signer's SKID as the Authentication Key ID.
+
+
+***** To create a dsa cert ********************
+
+1) openssl dsaparam 512 > dsa512.param       # creates group params
+
+2) openssl gendsa dsa512.param > dsa512.pem  # creates private key
+
+3) openssl req -new -x509 -nodes -days 1000 -key dsa512.pem > dsa-cert.pem 
+
+
+
+
+***** To convert from PEM to DER **************
+
+a) openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
+
+to convert rsa private PEM to DER :
+
+b) openssl rsa -in key.pem -outform DER -out key.der
+
+
+**** To encrypt rsa key already in pem **********
+
+a) openssl rsa <server-key.pem.bak -des >server-keyEnc.pem
+
+note location of des, pass = yassl123
+
+
+*** To make a public key from a private key ******
+
+
+openssl rsa -in 1024rsa.priv -pubout -out 1024rsa.pub
+
+
+**** To convert to pkcs8 *******
+
+openssl pkcs8 -nocrypt -topk8 -in server-key.pem -out server-keyPkcs8.pem
+
+
+**** To convert to pkcs8 encrypted *******
+
+openssl pkcs8 -topk8 -in server-key.pem -out server-keyPkcs8Enc.pem
+
+passwd: yassl123
+
+to use PKCS#5 v2 instead of v1.5 which is default add
+
+-v2 des3       # file Pkcs8Enc2
+
+to use PKCS#12 instead use -v1 witch a 12 algo like
+
+-v1 PBE-SHA1-3DES   # file Pkcs8Enc12 , see man pkcs8 for more info
+-v1 PBE-SHA1-RC4-128   # no longer file Pkcs8Enc12, arc4 now off by default
+
+
+**** To convert from pkcs8 to traditional ****
+
+openssl pkcs8 -nocrypt -in server-keyPkcs8.pem -out server-key.pem
+
+
+*** DH parameters ***
+
+openssl dhparam 2048 > dh2048.param
+
+to add metadata
+
+openssl dhparam -in dh2048.param -text > dh2048.pem
+
+**** ECC ******
+
+1) make a key
+
+    to see types available do
+        openssl ecparam -list_curves
+
+    make a new key
+        openssl ecparam -genkey -text -name secp256r1 -out ecc-key.pem
+
+    convert to compressed
+        openssl ec -in ecc-key.pem -conv_form compressed -out ecc-key-comp.pem 
+
+*** CRL ***
+
+1) create a crl
+
+a) openssl ca -gencrl -crldays 120 -out crl.pem -keyfile ./ca-key.pem -cert ./ca-cert.pem
+
+Error No ./CA root/index.txt so:
+
+b) touch ./CA root/index.txt
+
+a) again
+
+Error No ./CA root/crlnumber so:
+
+c) touch ./CA root/crlnumber
+
+a) again
+
+Error unable to load CRL number
+
+d) add '01' to crlnumber file
+
+a) again
+
+2)  view crl file
+
+openssl crl -in crl.pem -text
+
+3) revoke
+
+openssl ca -revoke server-cert.pem -keyfile ./ca-key.pem -cert ./ca-cert.pem
+
+Then regenerate crl with a)
+
+4) verify
+
+openssl verify -CAfile ./ca-cert.pem  ./server-cert.pem
+
+OK
+
+Make file with both ca and crl
+
+cat ca-cert.pem crl.pem > ca-crl.pem
+
+openssl verify -CAfile ./ca-crl.pem -crl_check ./ca-cert.pem
+
+revoked