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