1d4afb5ceSopenharmony_ci#include <libwebsockets.h> 2d4afb5ceSopenharmony_ci#include <string.h> 3d4afb5ceSopenharmony_ci#include <signal.h> 4d4afb5ceSopenharmony_ci#if defined(WIN32) 5d4afb5ceSopenharmony_ci#define HAVE_STRUCT_TIMESPEC 6d4afb5ceSopenharmony_ci#if defined(pid_t) 7d4afb5ceSopenharmony_ci#undef pid_t 8d4afb5ceSopenharmony_ci#endif 9d4afb5ceSopenharmony_ci#endif 10d4afb5ceSopenharmony_ci 11d4afb5ceSopenharmony_cistatic int nclients = 11; 12d4afb5ceSopenharmony_ciunsigned char msg[LWS_PRE+128]; 13d4afb5ceSopenharmony_cistatic int message_delay = 500000; // microseconds 14d4afb5ceSopenharmony_cistatic int connection_delay = 100000; // microseconds 15d4afb5ceSopenharmony_cistatic struct lws_context *context; 16d4afb5ceSopenharmony_cistatic const char *server_address = "localhost", *pro = "lws-minimal"; 17d4afb5ceSopenharmony_cistatic int interrupted = 0, port = 7681, ssl_connection = 0; 18d4afb5ceSopenharmony_ci 19d4afb5ceSopenharmony_cistatic int connect_client() 20d4afb5ceSopenharmony_ci{ 21d4afb5ceSopenharmony_ci struct lws_client_connect_info i; 22d4afb5ceSopenharmony_ci 23d4afb5ceSopenharmony_ci memset(&i, 0, sizeof(i)); 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci i.context = context; 26d4afb5ceSopenharmony_ci i.port = port; 27d4afb5ceSopenharmony_ci i.address = server_address; 28d4afb5ceSopenharmony_ci i.path = "/"; 29d4afb5ceSopenharmony_ci i.host = i.address; 30d4afb5ceSopenharmony_ci i.origin = i.address; 31d4afb5ceSopenharmony_ci i.ssl_connection = ssl_connection; 32d4afb5ceSopenharmony_ci i.protocol = pro; 33d4afb5ceSopenharmony_ci i.local_protocol_name = pro; 34d4afb5ceSopenharmony_ci 35d4afb5ceSopenharmony_ci //usleep(connection_delay); 36d4afb5ceSopenharmony_ci lwsl_notice("%s: connection %s:%d\n", __func__, i.address, i.port); 37d4afb5ceSopenharmony_ci if (!lws_client_connect_via_info(&i)) return 1; 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci return 0; 40d4afb5ceSopenharmony_ci} 41d4afb5ceSopenharmony_ci 42d4afb5ceSopenharmony_cistatic int 43d4afb5ceSopenharmony_cicallback(struct lws *wsi, enum lws_callback_reasons reason, 44d4afb5ceSopenharmony_ci void *user, void *in, size_t len) 45d4afb5ceSopenharmony_ci{ 46d4afb5ceSopenharmony_ci int m= 0, n = 0; 47d4afb5ceSopenharmony_ci short r; 48d4afb5ceSopenharmony_ci#if defined(_DEBUG) && !defined(LWS_WITH_NO_LOGS) 49d4afb5ceSopenharmony_ci size_t remain; 50d4afb5ceSopenharmony_ci int first = 0, final = 0; 51d4afb5ceSopenharmony_ci#endif 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci //lwsl_notice("callback called with reason %d\n", reason); 54d4afb5ceSopenharmony_ci switch (reason) { 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci case LWS_CALLBACK_PROTOCOL_INIT: 57d4afb5ceSopenharmony_ci for (n = 0; n < nclients; n++) 58d4afb5ceSopenharmony_ci connect_client(); 59d4afb5ceSopenharmony_ci break; 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 62d4afb5ceSopenharmony_ci lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : 63d4afb5ceSopenharmony_ci "(null)"); 64d4afb5ceSopenharmony_ci if(--nclients == 0) interrupted = 1; 65d4afb5ceSopenharmony_ci break; 66d4afb5ceSopenharmony_ci 67d4afb5ceSopenharmony_ci /* --- client callbacks --- */ 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_ESTABLISHED: 70d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 71d4afb5ceSopenharmony_ci lwsl_user("%s: established connection, wsi = %p\n", 72d4afb5ceSopenharmony_ci __func__, wsi); 73d4afb5ceSopenharmony_ci break; 74d4afb5ceSopenharmony_ci 75d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CLOSED: 76d4afb5ceSopenharmony_ci lwsl_user("%s: CLOSED\n", __func__); 77d4afb5ceSopenharmony_ci if(--nclients == 0) interrupted = 1; 78d4afb5ceSopenharmony_ci break; 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_WRITEABLE: 81d4afb5ceSopenharmony_ci 82d4afb5ceSopenharmony_ci m = lws_write(wsi, msg + LWS_PRE, 128, LWS_WRITE_TEXT); 83d4afb5ceSopenharmony_ci if (m < 128) { 84d4afb5ceSopenharmony_ci lwsl_err("sending message failed: %d < %d\n", m, n); 85d4afb5ceSopenharmony_ci return -1; 86d4afb5ceSopenharmony_ci } 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci /* 89d4afb5ceSopenharmony_ci * Schedule the timer after minimum message delay plus the 90d4afb5ceSopenharmony_ci * random number of centiseconds. 91d4afb5ceSopenharmony_ci */ 92d4afb5ceSopenharmony_ci if (lws_get_random(lws_get_context(wsi), &r, 2) == 2) { 93d4afb5ceSopenharmony_ci n = message_delay + 10000*(r % 100); 94d4afb5ceSopenharmony_ci lwsl_debug("set timer on %d usecs\n", n); 95d4afb5ceSopenharmony_ci lws_set_timer_usecs(wsi, n); 96d4afb5ceSopenharmony_ci } 97d4afb5ceSopenharmony_ci break; 98d4afb5ceSopenharmony_ci 99d4afb5ceSopenharmony_ci case LWS_CALLBACK_TIMER: 100d4afb5ceSopenharmony_ci // Let the main loop know we want to send another message to the 101d4afb5ceSopenharmony_ci // server 102d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 103d4afb5ceSopenharmony_ci break; 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_RECEIVE: 106d4afb5ceSopenharmony_ci#if defined(_DEBUG) && !defined(LWS_WITH_NO_LOGS) 107d4afb5ceSopenharmony_ci first = lws_is_first_fragment(wsi); 108d4afb5ceSopenharmony_ci final = lws_is_final_fragment(wsi); 109d4afb5ceSopenharmony_ci remain = lws_remaining_packet_payload(wsi); 110d4afb5ceSopenharmony_ci lwsl_debug("LWS_CALLBACK_RECEIVE: len = %lu, first = %d, " 111d4afb5ceSopenharmony_ci "final = %d, remains = %lu\n", 112d4afb5ceSopenharmony_ci (unsigned long)len, first, final, 113d4afb5ceSopenharmony_ci (unsigned long)remain); 114d4afb5ceSopenharmony_ci#endif 115d4afb5ceSopenharmony_ci break; 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: 118d4afb5ceSopenharmony_ci lwsl_notice("server initiated connection close: len = %lu, " 119d4afb5ceSopenharmony_ci "in = %s\n", (unsigned long)len, (char*)in); 120d4afb5ceSopenharmony_ci return 0; 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci default: 123d4afb5ceSopenharmony_ci break; 124d4afb5ceSopenharmony_ci } 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 127d4afb5ceSopenharmony_ci} 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_cistatic const struct lws_protocols protocols[] = { 130d4afb5ceSopenharmony_ci { "spam-rx-tx", callback, 4096, 4096, 0, NULL, 0 }, 131d4afb5ceSopenharmony_ci LWS_PROTOCOL_LIST_TERM 132d4afb5ceSopenharmony_ci}; 133d4afb5ceSopenharmony_ci 134d4afb5ceSopenharmony_cistatic void 135d4afb5ceSopenharmony_cisigint_handler(int sig) 136d4afb5ceSopenharmony_ci{ 137d4afb5ceSopenharmony_ci interrupted = 1; 138d4afb5ceSopenharmony_ci} 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 141d4afb5ceSopenharmony_ci{ 142d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 143d4afb5ceSopenharmony_ci const char *p; 144d4afb5ceSopenharmony_ci int n = 0, logs = 145d4afb5ceSopenharmony_ci LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; 146d4afb5ceSopenharmony_ci#ifndef WIN32 147d4afb5ceSopenharmony_ci srandom((unsigned int)time(0)); 148d4afb5ceSopenharmony_ci#endif 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci memset(msg, 'x', sizeof(msg)); 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ci signal(SIGINT, sigint_handler); 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_ci if (lws_cmdline_option(argc, argv, "-d")) 155d4afb5ceSopenharmony_ci logs |= LLL_INFO | LLL_DEBUG; 156d4afb5ceSopenharmony_ci 157d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 158d4afb5ceSopenharmony_ci 159d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 160d4afb5ceSopenharmony_ci info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; 161d4afb5ceSopenharmony_ci info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */ 162d4afb5ceSopenharmony_ci info.protocols = protocols; 163d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL) 164d4afb5ceSopenharmony_ci /* 165d4afb5ceSopenharmony_ci * OpenSSL uses the system trust store. mbedTLS has to be told which 166d4afb5ceSopenharmony_ci * CA to trust explicitly. 167d4afb5ceSopenharmony_ci */ 168d4afb5ceSopenharmony_ci info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; 169d4afb5ceSopenharmony_ci#endif 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-h"))) { 172d4afb5ceSopenharmony_ci server_address = p; 173d4afb5ceSopenharmony_ci } 174d4afb5ceSopenharmony_ci 175d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-s"))) { 176d4afb5ceSopenharmony_ci ssl_connection |= 177d4afb5ceSopenharmony_ci LCCSCF_USE_SSL | 178d4afb5ceSopenharmony_ci LCCSCF_ALLOW_SELFSIGNED | 179d4afb5ceSopenharmony_ci LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; 180d4afb5ceSopenharmony_ci } 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-p"))) { 183d4afb5ceSopenharmony_ci port = atoi(p); 184d4afb5ceSopenharmony_ci if (port > 65535 || port < 0) 185d4afb5ceSopenharmony_ci return 1; 186d4afb5ceSopenharmony_ci } 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-n"))) { 189d4afb5ceSopenharmony_ci n = atoi(p); 190d4afb5ceSopenharmony_ci if (n < 1) 191d4afb5ceSopenharmony_ci n = 1; 192d4afb5ceSopenharmony_ci if (n > LWS_MAX_SMP) 193d4afb5ceSopenharmony_ci n = LWS_MAX_SMP; 194d4afb5ceSopenharmony_ci if (n < nclients) 195d4afb5ceSopenharmony_ci nclients = n; 196d4afb5ceSopenharmony_ci lwsl_notice("Start test clients: %d\n", nclients); 197d4afb5ceSopenharmony_ci } 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-c"))) { 200d4afb5ceSopenharmony_ci connection_delay = atoi(p); 201d4afb5ceSopenharmony_ci lwsl_notice("Connection delay: %d\n", connection_delay); 202d4afb5ceSopenharmony_ci } 203d4afb5ceSopenharmony_ci 204d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-m"))) { 205d4afb5ceSopenharmony_ci message_delay = atoi(p); 206d4afb5ceSopenharmony_ci lwsl_notice("Message delay: %d\n", connection_delay); 207d4afb5ceSopenharmony_ci } 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci info.fd_limit_per_thread = (unsigned int)(1 + nclients + 1); 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci context = lws_create_context(&info); 212d4afb5ceSopenharmony_ci if (!context) { 213d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 214d4afb5ceSopenharmony_ci return 1; 215d4afb5ceSopenharmony_ci } 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci while (n >= 0 && !interrupted) 218d4afb5ceSopenharmony_ci n = lws_service(context, 0); 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci lwsl_notice("%s: exiting service loop. n = %d, interrupted = %d\n", 221d4afb5ceSopenharmony_ci __func__, n, interrupted); 222d4afb5ceSopenharmony_ci 223d4afb5ceSopenharmony_ci lws_context_destroy(context); 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci return 0; 226d4afb5ceSopenharmony_ci} 227