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