1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws-minimal-ws-client-pmd-bulk
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Written in 2010-2019 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * This file is made available under the Creative Commons CC0 1.0
7*1c60b9acSAndroid Build Coastguard Worker  * Universal Public Domain Dedication.
8*1c60b9acSAndroid Build Coastguard Worker  *
9*1c60b9acSAndroid Build Coastguard Worker  * This demonstrates a ws client that sends bulk data in multiple
10*1c60b9acSAndroid Build Coastguard Worker  * ws fragments, in a way compatible with per-message deflate.
11*1c60b9acSAndroid Build Coastguard Worker  *
12*1c60b9acSAndroid Build Coastguard Worker  * It shows how to send huge messages without needing a lot of memory.
13*1c60b9acSAndroid Build Coastguard Worker  *
14*1c60b9acSAndroid Build Coastguard Worker  * Build and start the minimal-examples/ws-server/minmal-ws-server-pmd-bulk
15*1c60b9acSAndroid Build Coastguard Worker  * example first.  Running this sends a large message to the server and
16*1c60b9acSAndroid Build Coastguard Worker  * exits.
17*1c60b9acSAndroid Build Coastguard Worker  *
18*1c60b9acSAndroid Build Coastguard Worker  * If you give both sides the -n commandline option, it disables permessage-
19*1c60b9acSAndroid Build Coastguard Worker  * deflate compression extension.
20*1c60b9acSAndroid Build Coastguard Worker  */
21*1c60b9acSAndroid Build Coastguard Worker 
22*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
23*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
24*1c60b9acSAndroid Build Coastguard Worker #include <signal.h>
25*1c60b9acSAndroid Build Coastguard Worker 
26*1c60b9acSAndroid Build Coastguard Worker #define LWS_PLUGIN_STATIC
27*1c60b9acSAndroid Build Coastguard Worker #include "protocol_lws_minimal_pmd_bulk.c"
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker static struct lws_protocols protocols[] = {
30*1c60b9acSAndroid Build Coastguard Worker 	{ "http", lws_callback_http_dummy, 0, 0, 0, NULL, 0 },
31*1c60b9acSAndroid Build Coastguard Worker 	LWS_PLUGIN_PROTOCOL_MINIMAL_PMD_BULK,
32*1c60b9acSAndroid Build Coastguard Worker 	LWS_PROTOCOL_LIST_TERM
33*1c60b9acSAndroid Build Coastguard Worker };
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker static int interrupted, options;
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker /* pass pointers to shared vars to the protocol */
38*1c60b9acSAndroid Build Coastguard Worker 
39*1c60b9acSAndroid Build Coastguard Worker static const struct lws_protocol_vhost_options pvo_options = {
40*1c60b9acSAndroid Build Coastguard Worker 	NULL,
41*1c60b9acSAndroid Build Coastguard Worker 	NULL,
42*1c60b9acSAndroid Build Coastguard Worker 	"options",		/* pvo name */
43*1c60b9acSAndroid Build Coastguard Worker 	(void *)&options	/* pvo value */
44*1c60b9acSAndroid Build Coastguard Worker };
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker static const struct lws_protocol_vhost_options pvo_interrupted = {
47*1c60b9acSAndroid Build Coastguard Worker 	&pvo_options,
48*1c60b9acSAndroid Build Coastguard Worker 	NULL,
49*1c60b9acSAndroid Build Coastguard Worker 	"interrupted",		/* pvo name */
50*1c60b9acSAndroid Build Coastguard Worker 	(void *)&interrupted	/* pvo value */
51*1c60b9acSAndroid Build Coastguard Worker };
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker static const struct lws_protocol_vhost_options pvo = {
54*1c60b9acSAndroid Build Coastguard Worker 	NULL,		/* "next" pvo linked-list */
55*1c60b9acSAndroid Build Coastguard Worker 	&pvo_interrupted,	/* "child" pvo linked-list */
56*1c60b9acSAndroid Build Coastguard Worker 	"lws-minimal-pmd-bulk",	/* protocol name we belong to on this vhost */
57*1c60b9acSAndroid Build Coastguard Worker 	""		/* ignored */
58*1c60b9acSAndroid Build Coastguard Worker };
59*1c60b9acSAndroid Build Coastguard Worker static const struct lws_extension extensions[] = {
60*1c60b9acSAndroid Build Coastguard Worker 	{
61*1c60b9acSAndroid Build Coastguard Worker 		"permessage-deflate",
62*1c60b9acSAndroid Build Coastguard Worker 		lws_extension_callback_pm_deflate,
63*1c60b9acSAndroid Build Coastguard Worker 		"permessage-deflate"
64*1c60b9acSAndroid Build Coastguard Worker 		 "; client_no_context_takeover"
65*1c60b9acSAndroid Build Coastguard Worker 		 "; client_max_window_bits"
66*1c60b9acSAndroid Build Coastguard Worker 	},
67*1c60b9acSAndroid Build Coastguard Worker 	{ NULL, NULL, NULL /* terminator */ }
68*1c60b9acSAndroid Build Coastguard Worker };
69*1c60b9acSAndroid Build Coastguard Worker 
sigint_handler(int sig)70*1c60b9acSAndroid Build Coastguard Worker void sigint_handler(int sig)
71*1c60b9acSAndroid Build Coastguard Worker {
72*1c60b9acSAndroid Build Coastguard Worker 	interrupted = 1;
73*1c60b9acSAndroid Build Coastguard Worker }
74*1c60b9acSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)75*1c60b9acSAndroid Build Coastguard Worker int main(int argc, const char **argv)
76*1c60b9acSAndroid Build Coastguard Worker {
77*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_creation_info info;
78*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context;
79*1c60b9acSAndroid Build Coastguard Worker 	const char *p;
80*1c60b9acSAndroid Build Coastguard Worker 	int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
81*1c60b9acSAndroid Build Coastguard Worker 			/* for LLL_ verbosity above NOTICE to be built into lws,
82*1c60b9acSAndroid Build Coastguard Worker 			 * lws must have been configured and built with
83*1c60b9acSAndroid Build Coastguard Worker 			 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
84*1c60b9acSAndroid Build Coastguard Worker 			/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
85*1c60b9acSAndroid Build Coastguard Worker 			/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
86*1c60b9acSAndroid Build Coastguard Worker 			/* | LLL_DEBUG */;
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	signal(SIGINT, sigint_handler);
89*1c60b9acSAndroid Build Coastguard Worker 
90*1c60b9acSAndroid Build Coastguard Worker 	if ((p = lws_cmdline_option(argc, argv, "-d")))
91*1c60b9acSAndroid Build Coastguard Worker 		logs = atoi(p);
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	lws_set_log_level(logs, NULL);
94*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("LWS minimal ws client + permessage-deflate + multifragment bulk message\n");
95*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("   needs minimal-ws-server-pmd-bulk running to communicate with\n");
96*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("   %s [-n (no exts)] [-c (compressible)]\n", argv[0]);
97*1c60b9acSAndroid Build Coastguard Worker 
98*1c60b9acSAndroid Build Coastguard Worker 	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
99*1c60b9acSAndroid Build Coastguard Worker 	info.port = CONTEXT_PORT_NO_LISTEN;
100*1c60b9acSAndroid Build Coastguard Worker 	info.protocols = protocols;
101*1c60b9acSAndroid Build Coastguard Worker 	info.pvo = &pvo;
102*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_cmdline_option(argc, argv, "-n"))
103*1c60b9acSAndroid Build Coastguard Worker 		info.extensions = extensions;
104*1c60b9acSAndroid Build Coastguard Worker 	info.pt_serv_buf_size = 32 * 1024;
105*1c60b9acSAndroid Build Coastguard Worker 
106*1c60b9acSAndroid Build Coastguard Worker 	if (lws_cmdline_option(argc, argv, "-c"))
107*1c60b9acSAndroid Build Coastguard Worker 		options |= 1;
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 	/*
110*1c60b9acSAndroid Build Coastguard Worker 	 * since we know this lws context is only ever going to be used with
111*1c60b9acSAndroid Build Coastguard Worker 	 * one client wsis / fds / sockets at a time, let lws know it doesn't
112*1c60b9acSAndroid Build Coastguard Worker 	 * have to use the default allocations for fd tables up to ulimit -n.
113*1c60b9acSAndroid Build Coastguard Worker 	 * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
114*1c60b9acSAndroid Build Coastguard Worker 	 * will use.
115*1c60b9acSAndroid Build Coastguard Worker 	 */
116*1c60b9acSAndroid Build Coastguard Worker 	info.fd_limit_per_thread = 1 + 1 + 1;
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker 	context = lws_create_context(&info);
119*1c60b9acSAndroid Build Coastguard Worker 	if (!context) {
120*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("lws init failed\n");
121*1c60b9acSAndroid Build Coastguard Worker 		return 1;
122*1c60b9acSAndroid Build Coastguard Worker 	}
123*1c60b9acSAndroid Build Coastguard Worker 
124*1c60b9acSAndroid Build Coastguard Worker 	while (n >= 0 && !interrupted)
125*1c60b9acSAndroid Build Coastguard Worker 		n = lws_service(context, 0);
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker 	lws_context_destroy(context);
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 	lwsl_user("Completed %s\n", interrupted == 2 ? "OK" : "failed");
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker 	return interrupted != 2;
132*1c60b9acSAndroid Build Coastguard Worker }
133