1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * lws-minimal-secure-streams-policy2c
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Written in 2010-2021 by Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0
7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication.
8d4afb5ceSopenharmony_ci *
9d4afb5ceSopenharmony_ci *
10d4afb5ceSopenharmony_ci * This reads policy JSON on stdin and emits it as compileable
11d4afb5ceSopenharmony_ci * C structs.
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * It's useful if your platform is too space-constrained for a
14d4afb5ceSopenharmony_ci * JSON policy and needs to build a static policy in C via
15d4afb5ceSopenharmony_ci * LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY... this way you can
16d4afb5ceSopenharmony_ci * still create and maintain the JSON policy but implement it directly
17d4afb5ceSopenharmony_ci * as C structs in your code.
18d4afb5ceSopenharmony_ci */
19d4afb5ceSopenharmony_ci
20d4afb5ceSopenharmony_ci#include <libwebsockets.h>
21d4afb5ceSopenharmony_ci#include <string.h>
22d4afb5ceSopenharmony_ci#include <signal.h>
23d4afb5ceSopenharmony_ci#include <stdio.h>
24d4afb5ceSopenharmony_ci#include <assert.h>
25d4afb5ceSopenharmony_ci
26d4afb5ceSopenharmony_cistatic int interrupted, bad = 1;
27d4afb5ceSopenharmony_ci
28d4afb5ceSopenharmony_ci
29d4afb5ceSopenharmony_cistatic void
30d4afb5ceSopenharmony_cisigint_handler(int sig)
31d4afb5ceSopenharmony_ci{
32d4afb5ceSopenharmony_ci	interrupted = 1;
33d4afb5ceSopenharmony_ci}
34d4afb5ceSopenharmony_ci
35d4afb5ceSopenharmony_cistruct aggstr {
36d4afb5ceSopenharmony_ci	struct aggstr *next;
37d4afb5ceSopenharmony_ci
38d4afb5ceSopenharmony_ci	const char *orig;
39d4afb5ceSopenharmony_ci	size_t offset;
40d4afb5ceSopenharmony_ci};
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_cistatic struct aggstr *rbomap,	/* retry / backoff object map */
43d4afb5ceSopenharmony_ci		     *trustmap, /* trust store map */
44d4afb5ceSopenharmony_ci		     *certmap;	/* x.509 cert map */
45d4afb5ceSopenharmony_cistatic size_t last_offset;
46d4afb5ceSopenharmony_ci
47d4afb5ceSopenharmony_ci
48d4afb5ceSopenharmony_ci
49d4afb5ceSopenharmony_cistatic const char *
50d4afb5ceSopenharmony_cipurify_csymbol(const char *in, char *temp, size_t templen)
51d4afb5ceSopenharmony_ci{
52d4afb5ceSopenharmony_ci	const char *otemp = temp;
53d4afb5ceSopenharmony_ci
54d4afb5ceSopenharmony_ci	assert (strlen(in) < templen);
55d4afb5ceSopenharmony_ci
56d4afb5ceSopenharmony_ci	while (*in) {
57d4afb5ceSopenharmony_ci		if ((*in >= 'a' && *in <= 'z') || (*in >= 'A' && *in <= 'Z') ||
58d4afb5ceSopenharmony_ci		    (*in >= '0' && *in <= '9'))
59d4afb5ceSopenharmony_ci			*temp++ = *in;
60d4afb5ceSopenharmony_ci		else
61d4afb5ceSopenharmony_ci			*temp++ = '_';
62d4afb5ceSopenharmony_ci
63d4afb5ceSopenharmony_ci		in++;
64d4afb5ceSopenharmony_ci	}
65d4afb5ceSopenharmony_ci
66d4afb5ceSopenharmony_ci	*temp = '\0';
67d4afb5ceSopenharmony_ci
68d4afb5ceSopenharmony_ci	return otemp;
69d4afb5ceSopenharmony_ci}
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ciint main(int argc, const char **argv)
72d4afb5ceSopenharmony_ci{
73d4afb5ceSopenharmony_ci	const lws_ss_policy_t *pol, *lastpol = NULL;
74d4afb5ceSopenharmony_ci	struct lws_context_creation_info info;
75d4afb5ceSopenharmony_ci	size_t json_size = 0, est = 0;
76d4afb5ceSopenharmony_ci	struct lws_context *context;
77d4afb5ceSopenharmony_ci	const lws_ss_auth_t *auth;
78d4afb5ceSopenharmony_ci	char prev[128], curr[128];
79d4afb5ceSopenharmony_ci	int unique_rbo = 0, m, n;
80d4afb5ceSopenharmony_ci	char buf[64], buf1[64];
81d4afb5ceSopenharmony_ci	lws_ss_metadata_t *md;
82d4afb5ceSopenharmony_ci	struct aggstr *a, *a1;
83d4afb5ceSopenharmony_ci
84d4afb5ceSopenharmony_ci	signal(SIGINT, sigint_handler);
85d4afb5ceSopenharmony_ci
86d4afb5ceSopenharmony_ci	memset(&info, 0, sizeof info);
87d4afb5ceSopenharmony_ci	lws_cmdline_option_handle_builtin(argc, argv, &info);
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ci	lwsl_user("LWS secure streams policy2c [-d<verb>]\n");
90d4afb5ceSopenharmony_ci
91d4afb5ceSopenharmony_ci	info.fd_limit_per_thread = 1 + 6 + 1;
92d4afb5ceSopenharmony_ci	info.port = CONTEXT_PORT_NO_LISTEN;
93d4afb5ceSopenharmony_ci
94d4afb5ceSopenharmony_ci	info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
95d4afb5ceSopenharmony_ci		       LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
96d4afb5ceSopenharmony_ci
97d4afb5ceSopenharmony_ci	/* create the context */
98d4afb5ceSopenharmony_ci
99d4afb5ceSopenharmony_ci	context = lws_create_context(&info);
100d4afb5ceSopenharmony_ci	if (!context) {
101d4afb5ceSopenharmony_ci		lwsl_err("lws init failed\n");
102d4afb5ceSopenharmony_ci		return 1;
103d4afb5ceSopenharmony_ci	}
104d4afb5ceSopenharmony_ci
105d4afb5ceSopenharmony_ci	lws_ss_policy_parse_begin(context, 0);
106d4afb5ceSopenharmony_ci
107d4afb5ceSopenharmony_ci	printf("/*\n * Autogenerated from the following JSON policy\n */\n\n#if 0\n");
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci	do {
110d4afb5ceSopenharmony_ci		int m, n = (int)read(0, buf, sizeof(buf));
111d4afb5ceSopenharmony_ci
112d4afb5ceSopenharmony_ci		if (n < 1)
113d4afb5ceSopenharmony_ci			break;
114d4afb5ceSopenharmony_ci
115d4afb5ceSopenharmony_ci		m = lws_ss_policy_parse(context, (uint8_t *)buf, (size_t)n);
116d4afb5ceSopenharmony_ci
117d4afb5ceSopenharmony_ci		printf("%.*s", n, buf);
118d4afb5ceSopenharmony_ci		json_size += (unsigned int)n;
119d4afb5ceSopenharmony_ci
120d4afb5ceSopenharmony_ci		if (m < 0 && m != LEJP_CONTINUE) {
121d4afb5ceSopenharmony_ci			lwsl_err("%s: policy parse failed... lws has WITH_ROLEs"
122d4afb5ceSopenharmony_ci				 "for what's in the JSON?\n", __func__);
123d4afb5ceSopenharmony_ci			goto bail;
124d4afb5ceSopenharmony_ci		}
125d4afb5ceSopenharmony_ci	} while (1);
126d4afb5ceSopenharmony_ci
127d4afb5ceSopenharmony_ci	printf("\n\n Original JSON size: %zu\n#endif\n\n", json_size);
128d4afb5ceSopenharmony_ci
129d4afb5ceSopenharmony_ci	lwsl_notice("%s: parsed JSON\n", __func__);
130d4afb5ceSopenharmony_ci
131d4afb5ceSopenharmony_ci	/*
132d4afb5ceSopenharmony_ci	 * Well, this is fun, isn't it... we have parsed the JSON into in-memory
133d4afb5ceSopenharmony_ci	 * policy objects, and it has set the context policy pointer to the head
134d4afb5ceSopenharmony_ci	 * of those but has not set the new policy (which would free the x.509).
135d4afb5ceSopenharmony_ci	 *
136d4afb5ceSopenharmony_ci	 * We want to walk the streamtype list first discovering unique objects
137d4afb5ceSopenharmony_ci	 * and strings referenced there and emitting them compactly as C data,
138d4afb5ceSopenharmony_ci	 * and then second to emit the streamtype linked-list referring to those
139d4afb5ceSopenharmony_ci	 * objects.
140d4afb5ceSopenharmony_ci	 *
141d4afb5ceSopenharmony_ci	 * For const strings, we aggregate them and avoid generating extra
142d4afb5ceSopenharmony_ci	 * pointers by encoding the reference as &_lws_ss_staticpol_str[xxx]
143d4afb5ceSopenharmony_ci	 * where xxx is the fixed offset in the aggregated monster-string.  When
144d4afb5ceSopenharmony_ci	 * doing that, we keep a map of original pointers to offsets.
145d4afb5ceSopenharmony_ci	 *
146d4afb5ceSopenharmony_ci	 * Although we want to minimize memory used by the emitted C, we don't
147d4afb5ceSopenharmony_ci	 * have to sweat memory during this conversion since it's happening on a
148d4afb5ceSopenharmony_ci	 * PC
149d4afb5ceSopenharmony_ci	 */
150d4afb5ceSopenharmony_ci
151d4afb5ceSopenharmony_ci	pol = lws_ss_policy_get(context);
152d4afb5ceSopenharmony_ci
153d4afb5ceSopenharmony_ci	while (pol) {
154d4afb5ceSopenharmony_ci
155d4afb5ceSopenharmony_ci		/*
156d4afb5ceSopenharmony_ci		 * Walk the metadata list gathering strings and issuing the
157d4afb5ceSopenharmony_ci		 * C struct
158d4afb5ceSopenharmony_ci		 */
159d4afb5ceSopenharmony_ci
160d4afb5ceSopenharmony_ci		md = pol->metadata;
161d4afb5ceSopenharmony_ci
162d4afb5ceSopenharmony_ci		if (md) {
163d4afb5ceSopenharmony_ci			int idx = 0;
164d4afb5ceSopenharmony_ci
165d4afb5ceSopenharmony_ci			printf("\nstatic const lws_ss_metadata_t ");
166d4afb5ceSopenharmony_ci
167d4afb5ceSopenharmony_ci			prev[0] = '\0';
168d4afb5ceSopenharmony_ci			md = pol->metadata;
169d4afb5ceSopenharmony_ci			while (md) {
170d4afb5ceSopenharmony_ci
171d4afb5ceSopenharmony_ci				est += sizeof(lws_ss_metadata_t);
172d4afb5ceSopenharmony_ci
173d4afb5ceSopenharmony_ci				lws_snprintf(curr, sizeof(curr), "_md_%s_%s",
174d4afb5ceSopenharmony_ci					purify_csymbol(pol->streamtype, buf,
175d4afb5ceSopenharmony_ci						       sizeof(buf)),
176d4afb5ceSopenharmony_ci					purify_csymbol(md->name, buf1,
177d4afb5ceSopenharmony_ci						       sizeof(buf1)));
178d4afb5ceSopenharmony_ci
179d4afb5ceSopenharmony_ci				printf("%s = {\n", curr);
180d4afb5ceSopenharmony_ci				if (prev[0])
181d4afb5ceSopenharmony_ci					printf("\t.next = (void *)&%s, \n", prev);
182d4afb5ceSopenharmony_ci
183d4afb5ceSopenharmony_ci				printf("\t.name = \"%s\",\n", (const char *)md->name);
184d4afb5ceSopenharmony_ci				if (md->value__may_own_heap) {
185d4afb5ceSopenharmony_ci					printf("\t.value__may_own_heap = (void *)\"%s\",\n",
186d4afb5ceSopenharmony_ci							(const char *)md->value__may_own_heap);
187d4afb5ceSopenharmony_ci					printf("\t.value_length = 0x%x,\n",
188d4afb5ceSopenharmony_ci						(unsigned int)strlen(
189d4afb5ceSopenharmony_ci							(const char *)md->value__may_own_heap));
190d4afb5ceSopenharmony_ci				}
191d4afb5ceSopenharmony_ci
192d4afb5ceSopenharmony_ci				printf("\t.length = %d,\n", idx++); // md->length);
193d4afb5ceSopenharmony_ci				printf("\t.value_is_http_token = 0x%x,\n",
194d4afb5ceSopenharmony_ci					(unsigned int)md->value_is_http_token);
195d4afb5ceSopenharmony_ci				printf("}");
196d4afb5ceSopenharmony_ci				if (md->next)
197d4afb5ceSopenharmony_ci					printf(",\n");
198d4afb5ceSopenharmony_ci
199d4afb5ceSopenharmony_ci				lws_strncpy(prev, curr, sizeof(prev));
200d4afb5ceSopenharmony_ci
201d4afb5ceSopenharmony_ci				md = md->next;
202d4afb5ceSopenharmony_ci			}
203d4afb5ceSopenharmony_ci
204d4afb5ceSopenharmony_ci			printf(";\n\n");
205d4afb5ceSopenharmony_ci		}
206d4afb5ceSopenharmony_ci
207d4afb5ceSopenharmony_ci		/*
208d4afb5ceSopenharmony_ci		 * Create unique retry policies... have we seen this guy?
209d4afb5ceSopenharmony_ci		 */
210d4afb5ceSopenharmony_ci
211d4afb5ceSopenharmony_ci		if (pol->retry_bo) {
212d4afb5ceSopenharmony_ci			a = rbomap;
213d4afb5ceSopenharmony_ci			while (a) {
214d4afb5ceSopenharmony_ci				if (a->orig == (const char *)pol->retry_bo)
215d4afb5ceSopenharmony_ci					break;
216d4afb5ceSopenharmony_ci
217d4afb5ceSopenharmony_ci				a = a->next;
218d4afb5ceSopenharmony_ci			}
219d4afb5ceSopenharmony_ci
220d4afb5ceSopenharmony_ci			if (!a) {
221d4afb5ceSopenharmony_ci
222d4afb5ceSopenharmony_ci				/* We haven't seen it before and need to create it */
223d4afb5ceSopenharmony_ci
224d4afb5ceSopenharmony_ci				a = malloc(sizeof(*a));
225d4afb5ceSopenharmony_ci				if (!a)
226d4afb5ceSopenharmony_ci					goto bail;
227d4afb5ceSopenharmony_ci				a->next = rbomap;
228d4afb5ceSopenharmony_ci				a->offset = (unsigned int)unique_rbo++;
229d4afb5ceSopenharmony_ci				a->orig = (const char *)pol->retry_bo;
230d4afb5ceSopenharmony_ci				rbomap = a;
231d4afb5ceSopenharmony_ci
232d4afb5ceSopenharmony_ci				printf("static const uint32_t _rbo_bo_%zu[] = {\n",
233d4afb5ceSopenharmony_ci					a->offset);
234d4afb5ceSopenharmony_ci				for (n = 0; n < pol->retry_bo->retry_ms_table_count; n++)
235d4afb5ceSopenharmony_ci					printf(" %u, ", (unsigned int)
236d4afb5ceSopenharmony_ci					       pol->retry_bo->retry_ms_table[n]);
237d4afb5ceSopenharmony_ci
238d4afb5ceSopenharmony_ci				est += sizeof(uint32_t) *
239d4afb5ceSopenharmony_ci					pol->retry_bo->retry_ms_table_count;
240d4afb5ceSopenharmony_ci
241d4afb5ceSopenharmony_ci				printf("\n};\nstatic const "
242d4afb5ceSopenharmony_ci				       "lws_retry_bo_t _rbo_%zu = {\n", a->offset);
243d4afb5ceSopenharmony_ci
244d4afb5ceSopenharmony_ci				printf("\t.retry_ms_table = _rbo_bo_%zu,\n",
245d4afb5ceSopenharmony_ci					a->offset);
246d4afb5ceSopenharmony_ci				printf("\t.retry_ms_table_count = %u,\n",
247d4afb5ceSopenharmony_ci					pol->retry_bo->retry_ms_table_count);
248d4afb5ceSopenharmony_ci				printf("\t.conceal_count = %u,\n",
249d4afb5ceSopenharmony_ci					pol->retry_bo->conceal_count);
250d4afb5ceSopenharmony_ci				printf("\t.secs_since_valid_ping = %u,\n",
251d4afb5ceSopenharmony_ci					pol->retry_bo->secs_since_valid_ping);
252d4afb5ceSopenharmony_ci				printf("\t.secs_since_valid_hangup = %u,\n",
253d4afb5ceSopenharmony_ci					pol->retry_bo->secs_since_valid_hangup);
254d4afb5ceSopenharmony_ci				printf("\t.jitter_percent = %u,\n",
255d4afb5ceSopenharmony_ci					pol->retry_bo->jitter_percent);
256d4afb5ceSopenharmony_ci				printf("};\n");
257d4afb5ceSopenharmony_ci
258d4afb5ceSopenharmony_ci				est += sizeof(lws_retry_bo_t);
259d4afb5ceSopenharmony_ci			}
260d4afb5ceSopenharmony_ci		}
261d4afb5ceSopenharmony_ci
262d4afb5ceSopenharmony_ci		/*
263d4afb5ceSopenharmony_ci		 * How about his trust store, it's new to us?
264d4afb5ceSopenharmony_ci		 */
265d4afb5ceSopenharmony_ci
266d4afb5ceSopenharmony_ci		if (pol->trust.store) {
267d4afb5ceSopenharmony_ci			a = trustmap;
268d4afb5ceSopenharmony_ci			while (a) {
269d4afb5ceSopenharmony_ci				if (a->orig == (const char *)pol->trust.store)
270d4afb5ceSopenharmony_ci					break;
271d4afb5ceSopenharmony_ci
272d4afb5ceSopenharmony_ci				a = a->next;
273d4afb5ceSopenharmony_ci			}
274d4afb5ceSopenharmony_ci
275d4afb5ceSopenharmony_ci			if (!a) {
276d4afb5ceSopenharmony_ci
277d4afb5ceSopenharmony_ci				/* it's new to us... */
278d4afb5ceSopenharmony_ci
279d4afb5ceSopenharmony_ci				a = malloc(sizeof(*a));
280d4afb5ceSopenharmony_ci				if (!a)
281d4afb5ceSopenharmony_ci					goto bail;
282d4afb5ceSopenharmony_ci				a->next = trustmap;
283d4afb5ceSopenharmony_ci				a->offset = 0; /* don't care, just track seen */
284d4afb5ceSopenharmony_ci				a->orig = (const char *)pol->trust.store;
285d4afb5ceSopenharmony_ci				trustmap = a;
286d4afb5ceSopenharmony_ci
287d4afb5ceSopenharmony_ci				/*
288d4afb5ceSopenharmony_ci				 * Have a look through his x.509 stack...
289d4afb5ceSopenharmony_ci				 * any that're new to us?
290d4afb5ceSopenharmony_ci				 */
291d4afb5ceSopenharmony_ci
292d4afb5ceSopenharmony_ci				for (n = 0; n < pol->trust.store->count; n++) {
293d4afb5ceSopenharmony_ci					if (!pol->trust.store->ssx509[n])
294d4afb5ceSopenharmony_ci						continue;
295d4afb5ceSopenharmony_ci					a1 = certmap;
296d4afb5ceSopenharmony_ci					while (a1) {
297d4afb5ceSopenharmony_ci						if (a1->orig == (const char *)pol->trust.store->ssx509[n])
298d4afb5ceSopenharmony_ci							break;
299d4afb5ceSopenharmony_ci						a1 = a1->next;
300d4afb5ceSopenharmony_ci					}
301d4afb5ceSopenharmony_ci
302d4afb5ceSopenharmony_ci					if (!a1) {
303d4afb5ceSopenharmony_ci						/*
304d4afb5ceSopenharmony_ci						 * This x.509 cert is new to us...
305d4afb5ceSopenharmony_ci						 * let's capture the DER
306d4afb5ceSopenharmony_ci						 */
307d4afb5ceSopenharmony_ci
308d4afb5ceSopenharmony_ci						a1 = malloc(sizeof(*a1));
309d4afb5ceSopenharmony_ci						if (!a1)
310d4afb5ceSopenharmony_ci							goto bail;
311d4afb5ceSopenharmony_ci						a1->next = certmap;
312d4afb5ceSopenharmony_ci						a1->offset = 0; /* don't care, just track seen */
313d4afb5ceSopenharmony_ci						a1->orig = (const char *)pol->trust.store->ssx509[n];
314d4afb5ceSopenharmony_ci						certmap = a1;
315d4afb5ceSopenharmony_ci
316d4afb5ceSopenharmony_ci						printf("static const uint8_t _ss_der_%s[] = {\n",
317d4afb5ceSopenharmony_ci							purify_csymbol(pol->trust.store->ssx509[n]->vhost_name,
318d4afb5ceSopenharmony_ci									buf, sizeof(buf)));
319d4afb5ceSopenharmony_ci
320d4afb5ceSopenharmony_ci						for (m = 0; m < (int)pol->trust.store->ssx509[n]->ca_der_len; m++) {
321d4afb5ceSopenharmony_ci							if ((m & 7) == 0)
322d4afb5ceSopenharmony_ci								printf("\t/* 0x%3x */ ", m);
323d4afb5ceSopenharmony_ci
324d4afb5ceSopenharmony_ci							printf("0x%02X, ", pol->trust.store->ssx509[n]->ca_der[m]);
325d4afb5ceSopenharmony_ci							if ((m & 7) == 7)
326d4afb5ceSopenharmony_ci								printf("\n");
327d4afb5ceSopenharmony_ci						}
328d4afb5ceSopenharmony_ci
329d4afb5ceSopenharmony_ci						printf("\n};\nstatic const lws_ss_x509_t _ss_x509_%s = {\n",
330d4afb5ceSopenharmony_ci								purify_csymbol(pol->trust.store->ssx509[n]->vhost_name,
331d4afb5ceSopenharmony_ci								buf, sizeof(buf)));
332d4afb5ceSopenharmony_ci						printf("\t.vhost_name = \"%s\",\n", pol->trust.store->ssx509[n]->vhost_name);
333d4afb5ceSopenharmony_ci						printf("\t.ca_der = _ss_der_%s,\n",
334d4afb5ceSopenharmony_ci							purify_csymbol(pol->trust.store->ssx509[n]->vhost_name,
335d4afb5ceSopenharmony_ci								buf, sizeof(buf)));
336d4afb5ceSopenharmony_ci						printf("\t.ca_der_len = %zu,\n", pol->trust.store->ssx509[n]->ca_der_len);
337d4afb5ceSopenharmony_ci						printf("};\n");
338d4afb5ceSopenharmony_ci
339d4afb5ceSopenharmony_ci						est += sizeof(lws_ss_x509_t) + pol->trust.store->ssx509[n]->ca_der_len;
340d4afb5ceSopenharmony_ci					}
341d4afb5ceSopenharmony_ci
342d4afb5ceSopenharmony_ci				}
343d4afb5ceSopenharmony_ci
344d4afb5ceSopenharmony_ci
345d4afb5ceSopenharmony_ci				printf("static const lws_ss_trust_store_t _ss_ts_%s = {\n",
346d4afb5ceSopenharmony_ci					purify_csymbol(pol->trust.store->name,
347d4afb5ceSopenharmony_ci							buf, sizeof(buf)));
348d4afb5ceSopenharmony_ci
349d4afb5ceSopenharmony_ci				printf("\t.name = \"%s\",\n", pol->trust.store->name);
350d4afb5ceSopenharmony_ci				printf("\t.count = %d,\n", pol->trust.store->count);
351d4afb5ceSopenharmony_ci				printf("\t.ssx509 = {\n");
352d4afb5ceSopenharmony_ci
353d4afb5ceSopenharmony_ci				for (n = pol->trust.store->count - 1; n >= 0 ; n--)
354d4afb5ceSopenharmony_ci					printf("\t\t&_ss_x509_%s,\n",
355d4afb5ceSopenharmony_ci						pol->trust.store->ssx509[n]->vhost_name);
356d4afb5ceSopenharmony_ci
357d4afb5ceSopenharmony_ci				printf("\t}\n};\n");
358d4afb5ceSopenharmony_ci
359d4afb5ceSopenharmony_ci				est += sizeof(lws_ss_trust_store_t);
360d4afb5ceSopenharmony_ci
361d4afb5ceSopenharmony_ci			}
362d4afb5ceSopenharmony_ci		}
363d4afb5ceSopenharmony_ci
364d4afb5ceSopenharmony_ci		pol = pol->next;
365d4afb5ceSopenharmony_ci	}
366d4afb5ceSopenharmony_ci
367d4afb5ceSopenharmony_ci
368d4afb5ceSopenharmony_ci	/* dump any streamtype's http resp map */
369d4afb5ceSopenharmony_ci
370d4afb5ceSopenharmony_ci	pol = lws_ss_policy_get(context);
371d4afb5ceSopenharmony_ci	m = 0;
372d4afb5ceSopenharmony_ci
373d4afb5ceSopenharmony_ci	while (pol) {
374d4afb5ceSopenharmony_ci
375d4afb5ceSopenharmony_ci		lws_snprintf(curr, sizeof(curr), "_ssp_%s",
376d4afb5ceSopenharmony_ci			purify_csymbol(pol->streamtype, buf, sizeof(buf)));
377d4afb5ceSopenharmony_ci
378d4afb5ceSopenharmony_ci		/* if relevant, dump http resp map */
379d4afb5ceSopenharmony_ci
380d4afb5ceSopenharmony_ci		switch (pol->protocol) {
381d4afb5ceSopenharmony_ci		case LWSSSP_H1:
382d4afb5ceSopenharmony_ci		case LWSSSP_H2:
383d4afb5ceSopenharmony_ci		case LWSSSP_WS:
384d4afb5ceSopenharmony_ci
385d4afb5ceSopenharmony_ci			if (!pol->u.http.count_respmap)
386d4afb5ceSopenharmony_ci				break;
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci			if (!m)
389d4afb5ceSopenharmony_ci				printf("\nstatic const lws_ss_http_respmap_t ");
390d4afb5ceSopenharmony_ci			else
391d4afb5ceSopenharmony_ci				printf(",\n");
392d4afb5ceSopenharmony_ci			m++;
393d4afb5ceSopenharmony_ci
394d4afb5ceSopenharmony_ci			printf("%s_http_respmap[] = {\n", curr);
395d4afb5ceSopenharmony_ci			for (n = 0; n < pol->u.http.count_respmap; n++) {
396d4afb5ceSopenharmony_ci				printf("\t{ %d, 0x%x },\n",
397d4afb5ceSopenharmony_ci						pol->u.http.respmap[n].resp,
398d4afb5ceSopenharmony_ci						pol->u.http.respmap[n].state);
399d4afb5ceSopenharmony_ci
400d4afb5ceSopenharmony_ci				est += sizeof(lws_ss_http_respmap_t);
401d4afb5ceSopenharmony_ci			}
402d4afb5ceSopenharmony_ci			printf("}");
403d4afb5ceSopenharmony_ci			break;
404d4afb5ceSopenharmony_ci		}
405d4afb5ceSopenharmony_ci
406d4afb5ceSopenharmony_ci		pol = pol->next;
407d4afb5ceSopenharmony_ci	}
408d4afb5ceSopenharmony_ci
409d4afb5ceSopenharmony_ci	if (m)
410d4afb5ceSopenharmony_ci		printf(";\n");
411d4afb5ceSopenharmony_ci
412d4afb5ceSopenharmony_ci	/*
413d4afb5ceSopenharmony_ci	 * The auth map
414d4afb5ceSopenharmony_ci	 */
415d4afb5ceSopenharmony_ci
416d4afb5ceSopenharmony_ci	auth = lws_ss_auth_get(context);
417d4afb5ceSopenharmony_ci	if (auth)
418d4afb5ceSopenharmony_ci		printf("\nstatic const lws_ss_auth_t ");
419d4afb5ceSopenharmony_ci	prev[0] = '\0';
420d4afb5ceSopenharmony_ci
421d4afb5ceSopenharmony_ci	while (auth) {
422d4afb5ceSopenharmony_ci		lws_snprintf(curr, sizeof(curr), "_ssau_%s",
423d4afb5ceSopenharmony_ci			purify_csymbol(auth->name, buf, sizeof(buf)));
424d4afb5ceSopenharmony_ci
425d4afb5ceSopenharmony_ci		printf("%s = {\n", curr);
426d4afb5ceSopenharmony_ci		if (prev[0])
427d4afb5ceSopenharmony_ci			printf("\t.next = (void *)&%s,\n", prev);
428d4afb5ceSopenharmony_ci
429d4afb5ceSopenharmony_ci		printf("\t.name = \"%s\",\n", auth->name);
430d4afb5ceSopenharmony_ci		printf("\t.type= \"%s\",\n", auth->type);
431d4afb5ceSopenharmony_ci		printf("\t.streamtype = \"%s\",\n", auth->streamtype);
432d4afb5ceSopenharmony_ci		printf("\t.blob_index = %d,\n", auth->blob_index);
433d4afb5ceSopenharmony_ci		printf("}");
434d4afb5ceSopenharmony_ci		if (auth->next)
435d4afb5ceSopenharmony_ci			printf(",");
436d4afb5ceSopenharmony_ci		else
437d4afb5ceSopenharmony_ci			printf(";");
438d4afb5ceSopenharmony_ci		printf("\n");
439d4afb5ceSopenharmony_ci
440d4afb5ceSopenharmony_ci		lws_strncpy(prev, curr, sizeof(prev));
441d4afb5ceSopenharmony_ci
442d4afb5ceSopenharmony_ci		auth = auth->next;
443d4afb5ceSopenharmony_ci	}
444d4afb5ceSopenharmony_ci
445d4afb5ceSopenharmony_ci	if (lws_ss_auth_get(context))
446d4afb5ceSopenharmony_ci		printf("\n");
447d4afb5ceSopenharmony_ci
448d4afb5ceSopenharmony_ci	/*
449d4afb5ceSopenharmony_ci	 * The streamtypes
450d4afb5ceSopenharmony_ci	 */
451d4afb5ceSopenharmony_ci
452d4afb5ceSopenharmony_ci	pol = lws_ss_policy_get(context);
453d4afb5ceSopenharmony_ci
454d4afb5ceSopenharmony_ci	printf("\nstatic const lws_ss_policy_t ");
455d4afb5ceSopenharmony_ci	prev[0] = '\0';
456d4afb5ceSopenharmony_ci
457d4afb5ceSopenharmony_ci	while (pol) {
458d4afb5ceSopenharmony_ci
459d4afb5ceSopenharmony_ci		est += sizeof(*pol);
460d4afb5ceSopenharmony_ci
461d4afb5ceSopenharmony_ci		lws_snprintf(curr, sizeof(curr), "_ssp_%s",
462d4afb5ceSopenharmony_ci			purify_csymbol(pol->streamtype, buf, sizeof(buf)));
463d4afb5ceSopenharmony_ci
464d4afb5ceSopenharmony_ci		printf("%s = {\n", curr);
465d4afb5ceSopenharmony_ci
466d4afb5ceSopenharmony_ci		if (prev[0])
467d4afb5ceSopenharmony_ci			printf("\t.next = (void *)&%s,\n", prev);
468d4afb5ceSopenharmony_ci
469d4afb5ceSopenharmony_ci		printf("\t.streamtype = \"%s\",\n", pol->streamtype);
470d4afb5ceSopenharmony_ci		if (pol->endpoint)
471d4afb5ceSopenharmony_ci			printf("\t.endpoint = \"%s\",\n", pol->endpoint);
472d4afb5ceSopenharmony_ci		if (pol->rideshare_streamtype)
473d4afb5ceSopenharmony_ci			printf("\t.rideshare_streamtype = \"%s\",\n",
474d4afb5ceSopenharmony_ci				pol->rideshare_streamtype);
475d4afb5ceSopenharmony_ci		if (pol->payload_fmt)
476d4afb5ceSopenharmony_ci			printf("\t.payload_fmt = \"%s\",\n",
477d4afb5ceSopenharmony_ci				pol->payload_fmt);
478d4afb5ceSopenharmony_ci		if (pol->socks5_proxy)
479d4afb5ceSopenharmony_ci			printf("\t.socks5_proxy = \"%s\",\n",
480d4afb5ceSopenharmony_ci				pol->socks5_proxy);
481d4afb5ceSopenharmony_ci
482d4afb5ceSopenharmony_ci		if (pol->auth)
483d4afb5ceSopenharmony_ci			printf("\t.auth = &_ssau_%s,\n",
484d4afb5ceSopenharmony_ci			       purify_csymbol(pol->auth->name, buf, sizeof(buf)));
485d4afb5ceSopenharmony_ci
486d4afb5ceSopenharmony_ci		{
487d4afb5ceSopenharmony_ci			lws_ss_metadata_t *nv = pol->metadata, *last = NULL;
488d4afb5ceSopenharmony_ci
489d4afb5ceSopenharmony_ci			while (nv) {
490d4afb5ceSopenharmony_ci				last = nv;
491d4afb5ceSopenharmony_ci				nv = nv->next;
492d4afb5ceSopenharmony_ci			}
493d4afb5ceSopenharmony_ci			if (pol->metadata)
494d4afb5ceSopenharmony_ci				printf("\t.metadata = (void *)&_md_%s_%s,\n",
495d4afb5ceSopenharmony_ci					purify_csymbol(pol->streamtype, buf, sizeof(buf)),
496d4afb5ceSopenharmony_ci					purify_csymbol(last->name, buf1, sizeof(buf1)));
497d4afb5ceSopenharmony_ci		}
498d4afb5ceSopenharmony_ci
499d4afb5ceSopenharmony_ci
500d4afb5ceSopenharmony_ci		switch (pol->protocol) {
501d4afb5ceSopenharmony_ci		case LWSSSP_H1:
502d4afb5ceSopenharmony_ci		case LWSSSP_H2:
503d4afb5ceSopenharmony_ci		case LWSSSP_WS:
504d4afb5ceSopenharmony_ci
505d4afb5ceSopenharmony_ci			printf("\t.u = {\n\t\t.http = {\n");
506d4afb5ceSopenharmony_ci
507d4afb5ceSopenharmony_ci			if (pol->u.http.method)
508d4afb5ceSopenharmony_ci				printf("\t\t\t.method = \"%s\",\n",
509d4afb5ceSopenharmony_ci					pol->u.http.method);
510d4afb5ceSopenharmony_ci			if (pol->u.http.url)
511d4afb5ceSopenharmony_ci				printf("\t\t\t.url = \"%s\",\n",
512d4afb5ceSopenharmony_ci					pol->u.http.url);
513d4afb5ceSopenharmony_ci			if (pol->u.http.multipart_name)
514d4afb5ceSopenharmony_ci				printf("\t\t\t.multipart_name = \"%s\",\n",
515d4afb5ceSopenharmony_ci					pol->u.http.multipart_name);
516d4afb5ceSopenharmony_ci			if (pol->u.http.multipart_filename)
517d4afb5ceSopenharmony_ci				printf("\t\t\t.multipart_filename = \"%s\",\n",
518d4afb5ceSopenharmony_ci					pol->u.http.multipart_filename);
519d4afb5ceSopenharmony_ci			if (pol->u.http.multipart_content_type)
520d4afb5ceSopenharmony_ci				printf("\t\t\t.multipart_content_type = \"%s\",\n",
521d4afb5ceSopenharmony_ci					pol->u.http.multipart_content_type);
522d4afb5ceSopenharmony_ci			if (pol->u.http.auth_preamble)
523d4afb5ceSopenharmony_ci				printf("\t\t\t.auth_preamble = \"%s\",\n",
524d4afb5ceSopenharmony_ci					pol->u.http.auth_preamble);
525d4afb5ceSopenharmony_ci
526d4afb5ceSopenharmony_ci			if (pol->u.http.respmap) {
527d4afb5ceSopenharmony_ci				printf("\t\t\t.respmap = (void *)&%s_http_respmap,\n",
528d4afb5ceSopenharmony_ci						curr);
529d4afb5ceSopenharmony_ci				printf("\t\t\t.count_respmap = %d,\n",
530d4afb5ceSopenharmony_ci						pol->u.http.count_respmap);
531d4afb5ceSopenharmony_ci			}
532d4afb5ceSopenharmony_ci
533d4afb5ceSopenharmony_ci			if (pol->u.http.blob_header[0]) {
534d4afb5ceSopenharmony_ci				printf("\t\t\t.blob_header = {\n");
535d4afb5ceSopenharmony_ci				for (n = 0; n < (int)LWS_ARRAY_SIZE(pol->u.http.blob_header); n++)
536d4afb5ceSopenharmony_ci					if (pol->u.http.blob_header[n])
537d4afb5ceSopenharmony_ci						printf("\t\t\t\t\"%s\",\n",
538d4afb5ceSopenharmony_ci							pol->u.http.blob_header[n]);
539d4afb5ceSopenharmony_ci
540d4afb5ceSopenharmony_ci				printf("\t\t\t},\n");
541d4afb5ceSopenharmony_ci			}
542d4afb5ceSopenharmony_ci
543d4afb5ceSopenharmony_ci			if (pol->protocol == LWSSSP_WS) {
544d4afb5ceSopenharmony_ci				printf("\t\t\t.u = {\n\t\t\t\t.ws = {\n");
545d4afb5ceSopenharmony_ci				if (pol->u.http.u.ws.subprotocol)
546d4afb5ceSopenharmony_ci					printf("\t\t\t\t\t.subprotocol = \"%s\",\n",
547d4afb5ceSopenharmony_ci						pol->u.http.u.ws.subprotocol);
548d4afb5ceSopenharmony_ci				printf("\t\t\t\t\t.binary = %u\n", pol->u.http.u.ws.binary);
549d4afb5ceSopenharmony_ci				printf("\t\t\t\t}\n\t\t\t},\n");
550d4afb5ceSopenharmony_ci			}
551d4afb5ceSopenharmony_ci
552d4afb5ceSopenharmony_ci			if (pol->u.http.resp_expect)
553d4afb5ceSopenharmony_ci				printf("\t\t\t.resp_expect = %u,\n", pol->u.http.resp_expect);
554d4afb5ceSopenharmony_ci			if (pol->u.http.fail_redirect)
555d4afb5ceSopenharmony_ci				printf("\t\t\t.fail_redirect = %u,\n", pol->u.http.fail_redirect);
556d4afb5ceSopenharmony_ci
557d4afb5ceSopenharmony_ci			printf("\t\t}\n\t},\n");
558d4afb5ceSopenharmony_ci
559d4afb5ceSopenharmony_ci			break;
560d4afb5ceSopenharmony_ci		case LWSSSP_MQTT:
561d4afb5ceSopenharmony_ci
562d4afb5ceSopenharmony_ci			printf("\t.u = {\n\t\t.mqtt = {\n");
563d4afb5ceSopenharmony_ci
564d4afb5ceSopenharmony_ci			if (pol->u.mqtt.topic)
565d4afb5ceSopenharmony_ci				printf("\t\t\t.topic = \"%s\",\n",
566d4afb5ceSopenharmony_ci					pol->u.mqtt.topic);
567d4afb5ceSopenharmony_ci			if (pol->u.mqtt.subscribe)
568d4afb5ceSopenharmony_ci				printf("\t\t\t.subscribe = \"%s\",\n",
569d4afb5ceSopenharmony_ci					pol->u.mqtt.subscribe);
570d4afb5ceSopenharmony_ci			if (pol->u.mqtt.will_topic)
571d4afb5ceSopenharmony_ci				printf("\t\t\t.will_topic = \"%s\",\n",
572d4afb5ceSopenharmony_ci					pol->u.mqtt.will_topic);
573d4afb5ceSopenharmony_ci			if (pol->u.mqtt.will_message)
574d4afb5ceSopenharmony_ci				printf("\t\t\t.will_message = \"%s\",\n",
575d4afb5ceSopenharmony_ci					pol->u.mqtt.will_message);
576d4afb5ceSopenharmony_ci			if (pol->u.mqtt.will_qos)
577d4afb5ceSopenharmony_ci				printf("\t\t\t.will_qos = %u,\n",
578d4afb5ceSopenharmony_ci					pol->u.mqtt.will_qos);
579d4afb5ceSopenharmony_ci			if (pol->u.mqtt.will_retain)
580d4afb5ceSopenharmony_ci				printf("\t\t\t.will_retain = %u,\n",
581d4afb5ceSopenharmony_ci					pol->u.mqtt.will_retain);
582d4afb5ceSopenharmony_ci			if (pol->u.mqtt.birth_topic)
583d4afb5ceSopenharmony_ci				printf("\t\t\t.birth_topic = \"%s\",\n",
584d4afb5ceSopenharmony_ci					pol->u.mqtt.birth_topic);
585d4afb5ceSopenharmony_ci			if (pol->u.mqtt.birth_message)
586d4afb5ceSopenharmony_ci				printf("\t\t\t.birth_message = \"%s\",\n",
587d4afb5ceSopenharmony_ci					pol->u.mqtt.birth_message);
588d4afb5ceSopenharmony_ci			if (pol->u.mqtt.birth_qos)
589d4afb5ceSopenharmony_ci				printf("\t\t\t.birth_qos = %u,\n",
590d4afb5ceSopenharmony_ci					pol->u.mqtt.birth_qos);
591d4afb5ceSopenharmony_ci			if (pol->u.mqtt.birth_retain)
592d4afb5ceSopenharmony_ci				printf("\t\t\t.birth_retain = %u,\n",
593d4afb5ceSopenharmony_ci					pol->u.mqtt.birth_retain);
594d4afb5ceSopenharmony_ci			if (pol->u.mqtt.keep_alive)
595d4afb5ceSopenharmony_ci				printf("\t\t\t.keep_alive = %u,\n",
596d4afb5ceSopenharmony_ci					pol->u.mqtt.keep_alive);
597d4afb5ceSopenharmony_ci			if (pol->u.mqtt.qos)
598d4afb5ceSopenharmony_ci				printf("\t\t\t.qos = %u,\n",
599d4afb5ceSopenharmony_ci					pol->u.mqtt.qos);
600d4afb5ceSopenharmony_ci			if (pol->u.mqtt.clean_start)
601d4afb5ceSopenharmony_ci				printf("\t\t\t.clean_start = %u,\n",
602d4afb5ceSopenharmony_ci					pol->u.mqtt.clean_start);
603d4afb5ceSopenharmony_ci			if (pol->u.mqtt.aws_iot)
604d4afb5ceSopenharmony_ci				printf("\t\t\t.aws_iot = %u,\n",
605d4afb5ceSopenharmony_ci					pol->u.mqtt.aws_iot);
606d4afb5ceSopenharmony_ci			if (pol->u.mqtt.retain)
607d4afb5ceSopenharmony_ci				printf("\t\t\t.retain = %u,\n",
608d4afb5ceSopenharmony_ci					pol->u.mqtt.retain);
609d4afb5ceSopenharmony_ci			printf("\t\t}\n\t},\n");
610d4afb5ceSopenharmony_ci
611d4afb5ceSopenharmony_ci			break;
612d4afb5ceSopenharmony_ci		default:
613d4afb5ceSopenharmony_ci			lwsl_err("%s: unknown ss protocol index %d\n", __func__,
614d4afb5ceSopenharmony_ci					pol->protocol);
615d4afb5ceSopenharmony_ci			goto bail;
616d4afb5ceSopenharmony_ci		}
617d4afb5ceSopenharmony_ci
618d4afb5ceSopenharmony_ci#if 0
619d4afb5ceSopenharmony_ci		const lws_ss_trust_store_t *trust_store; /**< CA certs needed for conn
620d4afb5ceSopenharmony_ci		       validation, only set between policy parsing and vhost creation */
621d4afb5ceSopenharmony_ci#endif
622d4afb5ceSopenharmony_ci
623d4afb5ceSopenharmony_ci		if (pol->retry_bo) {
624d4afb5ceSopenharmony_ci			a = rbomap;
625d4afb5ceSopenharmony_ci			while (a) {
626d4afb5ceSopenharmony_ci				if (a->orig == (const char *)pol->retry_bo)
627d4afb5ceSopenharmony_ci					break;
628d4afb5ceSopenharmony_ci
629d4afb5ceSopenharmony_ci				a = a->next;
630d4afb5ceSopenharmony_ci			}
631d4afb5ceSopenharmony_ci			if (!a)
632d4afb5ceSopenharmony_ci				goto bail;
633d4afb5ceSopenharmony_ci
634d4afb5ceSopenharmony_ci			printf("\t.retry_bo = &_rbo_%zu,\n", a->offset);
635d4afb5ceSopenharmony_ci		}
636d4afb5ceSopenharmony_ci
637d4afb5ceSopenharmony_ci		if (pol->timeout_ms)
638d4afb5ceSopenharmony_ci			printf("\t.timeout_ms = %u,\n", pol->timeout_ms);
639d4afb5ceSopenharmony_ci		if (pol->flags)
640d4afb5ceSopenharmony_ci			printf("\t.flags = 0x%x,\n", pol->flags);
641d4afb5ceSopenharmony_ci		if (pol->flags)
642d4afb5ceSopenharmony_ci			printf("\t.priority = 0x%x,\n", (unsigned int)pol->priority);
643d4afb5ceSopenharmony_ci		if (pol->port)
644d4afb5ceSopenharmony_ci			printf("\t.port = %u,\n", pol->port);
645d4afb5ceSopenharmony_ci		if (pol->metadata_count)
646d4afb5ceSopenharmony_ci			printf("\t.metadata_count = %u,\n", pol->metadata_count);
647d4afb5ceSopenharmony_ci		printf("\t.protocol = %u,\n", pol->protocol);
648d4afb5ceSopenharmony_ci		if (pol->client_cert)
649d4afb5ceSopenharmony_ci			printf("\t.client_cert = %u,\n", pol->client_cert);
650d4afb5ceSopenharmony_ci
651d4afb5ceSopenharmony_ci		if (pol->trust.store)
652d4afb5ceSopenharmony_ci			printf("\t.trust = {.store = &_ss_ts_%s},\n",
653d4afb5ceSopenharmony_ci				purify_csymbol(pol->trust.store->name,
654d4afb5ceSopenharmony_ci							buf, sizeof(buf)));
655d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4)
656d4afb5ceSopenharmony_ci		if (pol->aws_region)
657d4afb5ceSopenharmony_ci			printf("\t.aws_region= \"%s\",\n", pol->aws_region);
658d4afb5ceSopenharmony_ci		if (pol->aws_service)
659d4afb5ceSopenharmony_ci			printf("\t.aws_service= \"%s\",\n", pol->aws_service);
660d4afb5ceSopenharmony_ci
661d4afb5ceSopenharmony_ci#endif
662d4afb5ceSopenharmony_ci
663d4afb5ceSopenharmony_ci
664d4afb5ceSopenharmony_ci		printf("}");
665d4afb5ceSopenharmony_ci		if (pol->next)
666d4afb5ceSopenharmony_ci			printf(",\n");
667d4afb5ceSopenharmony_ci
668d4afb5ceSopenharmony_ci		lws_strncpy(prev, curr, sizeof(prev));
669d4afb5ceSopenharmony_ci
670d4afb5ceSopenharmony_ci		lastpol = pol;
671d4afb5ceSopenharmony_ci
672d4afb5ceSopenharmony_ci		pol = pol->next;
673d4afb5ceSopenharmony_ci	}
674d4afb5ceSopenharmony_ci
675d4afb5ceSopenharmony_ci	printf(";\n");
676d4afb5ceSopenharmony_ci	if (lastpol)
677d4afb5ceSopenharmony_ci		printf("#define _ss_static_policy_entry _ssp_%s\n",
678d4afb5ceSopenharmony_ci			purify_csymbol(lastpol->streamtype, buf, sizeof(buf)));
679d4afb5ceSopenharmony_ci
680d4afb5ceSopenharmony_ci	est += last_offset;
681d4afb5ceSopenharmony_ci
682d4afb5ceSopenharmony_ci	printf("/* estimated footprint %zu (when sizeof void * = %zu) */\n",
683d4afb5ceSopenharmony_ci			est, sizeof(void *));
684d4afb5ceSopenharmony_ci
685d4afb5ceSopenharmony_ci	lws_ss_policy_parse_abandon(context);
686d4afb5ceSopenharmony_ci	bad = 0;
687d4afb5ceSopenharmony_ci
688d4afb5ceSopenharmony_cibail:
689d4afb5ceSopenharmony_ci
690d4afb5ceSopenharmony_ci
691d4afb5ceSopenharmony_ci	lws_context_destroy(context);
692d4afb5ceSopenharmony_ci
693d4afb5ceSopenharmony_ci	lwsl_user("Completed: %s\n", bad ? "failed" : "OK");
694d4afb5ceSopenharmony_ci
695d4afb5ceSopenharmony_ci	return bad;
696d4afb5ceSopenharmony_ci}
697