xref: /aosp_15_r20/external/libwebsockets/lib/system/fault-injection/fault-injection.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * lws System Fault Injection
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2019 - 2021 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker static lws_fi_priv_t *
lws_fi_lookup(const lws_fi_ctx_t * fic,const char * name)30*1c60b9acSAndroid Build Coastguard Worker lws_fi_lookup(const lws_fi_ctx_t *fic, const char *name)
31*1c60b9acSAndroid Build Coastguard Worker {
32*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll(struct lws_dll2 *, p, fic->fi_owner.head) {
33*1c60b9acSAndroid Build Coastguard Worker 		lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker 		if (!strcmp(pv->fi.name, name))
36*1c60b9acSAndroid Build Coastguard Worker 			return pv;
37*1c60b9acSAndroid Build Coastguard Worker 
38*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll(p);
39*1c60b9acSAndroid Build Coastguard Worker 
40*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
41*1c60b9acSAndroid Build Coastguard Worker }
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker int
lws_fi(const lws_fi_ctx_t * fic,const char * name)44*1c60b9acSAndroid Build Coastguard Worker lws_fi(const lws_fi_ctx_t *fic, const char *name)
45*1c60b9acSAndroid Build Coastguard Worker {
46*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_priv_t *pv;
47*1c60b9acSAndroid Build Coastguard Worker 	int n;
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker 	pv = lws_fi_lookup(fic, name);
50*1c60b9acSAndroid Build Coastguard Worker 
51*1c60b9acSAndroid Build Coastguard Worker 	if (!pv)
52*1c60b9acSAndroid Build Coastguard Worker 		return 0;
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	switch (pv->fi.type) {
55*1c60b9acSAndroid Build Coastguard Worker 	case LWSFI_ALWAYS:
56*1c60b9acSAndroid Build Coastguard Worker 		goto inject;
57*1c60b9acSAndroid Build Coastguard Worker 
58*1c60b9acSAndroid Build Coastguard Worker 	case LWSFI_DETERMINISTIC:
59*1c60b9acSAndroid Build Coastguard Worker 		pv->fi.times++;
60*1c60b9acSAndroid Build Coastguard Worker 		if (pv->fi.times >= pv->fi.pre)
61*1c60b9acSAndroid Build Coastguard Worker 			if (pv->fi.times < pv->fi.pre + pv->fi.count)
62*1c60b9acSAndroid Build Coastguard Worker 				goto inject;
63*1c60b9acSAndroid Build Coastguard Worker 		return 0;
64*1c60b9acSAndroid Build Coastguard Worker 
65*1c60b9acSAndroid Build Coastguard Worker 	case LWSFI_PROBABILISTIC:
66*1c60b9acSAndroid Build Coastguard Worker 		if (lws_xos_percent((lws_xos_t *)&fic->xos, (int)pv->fi.pre))
67*1c60b9acSAndroid Build Coastguard Worker 			goto inject;
68*1c60b9acSAndroid Build Coastguard Worker 		return 0;
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker 	case LWSFI_PATTERN:
71*1c60b9acSAndroid Build Coastguard Worker 	case LWSFI_PATTERN_ALLOC:
72*1c60b9acSAndroid Build Coastguard Worker 		n = (int)((pv->fi.times++) % pv->fi.count);
73*1c60b9acSAndroid Build Coastguard Worker 		if (pv->fi.pattern[n >> 3] & (1 << (n & 7)))
74*1c60b9acSAndroid Build Coastguard Worker 			goto inject;
75*1c60b9acSAndroid Build Coastguard Worker 
76*1c60b9acSAndroid Build Coastguard Worker 		return 0;
77*1c60b9acSAndroid Build Coastguard Worker 
78*1c60b9acSAndroid Build Coastguard Worker 	default:
79*1c60b9acSAndroid Build Coastguard Worker 		return 0;
80*1c60b9acSAndroid Build Coastguard Worker 	}
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker 	return 0;
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker inject:
85*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("%s: Injecting fault %s->%s\n", __func__,
86*1c60b9acSAndroid Build Coastguard Worker 			fic->name ? fic->name : "unk", pv->fi.name);
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	return 1;
89*1c60b9acSAndroid Build Coastguard Worker }
90*1c60b9acSAndroid Build Coastguard Worker 
91*1c60b9acSAndroid Build Coastguard Worker int
lws_fi_range(const lws_fi_ctx_t * fic,const char * name,uint64_t * result)92*1c60b9acSAndroid Build Coastguard Worker lws_fi_range(const lws_fi_ctx_t *fic, const char *name, uint64_t *result)
93*1c60b9acSAndroid Build Coastguard Worker {
94*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_priv_t *pv;
95*1c60b9acSAndroid Build Coastguard Worker 	uint64_t d;
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker 	pv = lws_fi_lookup(fic, name);
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker 	if (!pv)
100*1c60b9acSAndroid Build Coastguard Worker 		return 1;
101*1c60b9acSAndroid Build Coastguard Worker 
102*1c60b9acSAndroid Build Coastguard Worker 	if (pv->fi.type != LWSFI_RANGE) {
103*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: fault %s is not a 123..456 range\n",
104*1c60b9acSAndroid Build Coastguard Worker 			 __func__, name);
105*1c60b9acSAndroid Build Coastguard Worker 		return 1;
106*1c60b9acSAndroid Build Coastguard Worker 	}
107*1c60b9acSAndroid Build Coastguard Worker 
108*1c60b9acSAndroid Build Coastguard Worker 	d = pv->fi.count - pv->fi.pre;
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 	*result = pv->fi.pre + (lws_xos((lws_xos_t *)&fic->xos) % d);
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 	return 0;
113*1c60b9acSAndroid Build Coastguard Worker }
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_wsi_fi(struct lws * wsi,const char * name)116*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_wsi_fi(struct lws *wsi, const char *name)
117*1c60b9acSAndroid Build Coastguard Worker {
118*1c60b9acSAndroid Build Coastguard Worker 	return lws_fi(&wsi->fic, name);
119*1c60b9acSAndroid Build Coastguard Worker }
120*1c60b9acSAndroid Build Coastguard Worker 
121*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_context_fi(struct lws_context * ctx,const char * name)122*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_context_fi(struct lws_context *ctx, const char *name)
123*1c60b9acSAndroid Build Coastguard Worker {
124*1c60b9acSAndroid Build Coastguard Worker 	return lws_fi(&ctx->fic, name);
125*1c60b9acSAndroid Build Coastguard Worker }
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS)
128*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_ss_fi(struct lws_ss_handle * h,const char * name)129*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_ss_fi(struct lws_ss_handle *h, const char *name)
130*1c60b9acSAndroid Build Coastguard Worker {
131*1c60b9acSAndroid Build Coastguard Worker 	return lws_fi(&h->fic, name);
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker 
134*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
135*1c60b9acSAndroid Build Coastguard Worker int
_lws_fi_user_sspc_fi(struct lws_sspc_handle * h,const char * name)136*1c60b9acSAndroid Build Coastguard Worker _lws_fi_user_sspc_fi(struct lws_sspc_handle *h, const char *name)
137*1c60b9acSAndroid Build Coastguard Worker {
138*1c60b9acSAndroid Build Coastguard Worker 	return lws_fi(&h->fic, name);
139*1c60b9acSAndroid Build Coastguard Worker }
140*1c60b9acSAndroid Build Coastguard Worker #endif
141*1c60b9acSAndroid Build Coastguard Worker #endif
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker int
lws_fi_add(lws_fi_ctx_t * fic,const lws_fi_t * fi)144*1c60b9acSAndroid Build Coastguard Worker lws_fi_add(lws_fi_ctx_t *fic, const lws_fi_t *fi)
145*1c60b9acSAndroid Build Coastguard Worker {
146*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_priv_t *pv;
147*1c60b9acSAndroid Build Coastguard Worker 	size_t n = strlen(fi->name);
148*1c60b9acSAndroid Build Coastguard Worker 
149*1c60b9acSAndroid Build Coastguard Worker 	pv = lws_malloc(sizeof(*pv) + n + 1, __func__);
150*1c60b9acSAndroid Build Coastguard Worker 	if (!pv)
151*1c60b9acSAndroid Build Coastguard Worker 		return 1;
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_clear(&pv->list);
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker 	memcpy(&pv->fi, fi, sizeof(*fi));
156*1c60b9acSAndroid Build Coastguard Worker 	pv->fi.name = (const char *)&pv[1];
157*1c60b9acSAndroid Build Coastguard Worker 	memcpy(&pv[1], fi->name, n + 1);
158*1c60b9acSAndroid Build Coastguard Worker 
159*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_add_tail(&pv->list, &fic->fi_owner);
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker 	return 0;
162*1c60b9acSAndroid Build Coastguard Worker }
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_remove(lws_fi_ctx_t * fic,const char * name)165*1c60b9acSAndroid Build Coastguard Worker lws_fi_remove(lws_fi_ctx_t *fic, const char *name)
166*1c60b9acSAndroid Build Coastguard Worker {
167*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_priv_t *pv = lws_fi_lookup(fic, name);
168*1c60b9acSAndroid Build Coastguard Worker 
169*1c60b9acSAndroid Build Coastguard Worker 	if (!pv)
170*1c60b9acSAndroid Build Coastguard Worker 		return;
171*1c60b9acSAndroid Build Coastguard Worker 
172*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&pv->list);
173*1c60b9acSAndroid Build Coastguard Worker 	lws_free(pv);
174*1c60b9acSAndroid Build Coastguard Worker }
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_import(lws_fi_ctx_t * fic_dest,const lws_fi_ctx_t * fic_src)177*1c60b9acSAndroid Build Coastguard Worker lws_fi_import(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src)
178*1c60b9acSAndroid Build Coastguard Worker {
179*1c60b9acSAndroid Build Coastguard Worker 
180*1c60b9acSAndroid Build Coastguard Worker 	/* inherit the PRNG seed for our context from source guy too */
181*1c60b9acSAndroid Build Coastguard Worker 	lws_xos_init(&fic_dest->xos, lws_xos((lws_xos_t *)&fic_src->xos));
182*1c60b9acSAndroid Build Coastguard Worker 
183*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
184*1c60b9acSAndroid Build Coastguard Worker 				   fic_src->fi_owner.head) {
185*1c60b9acSAndroid Build Coastguard Worker 		lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
186*1c60b9acSAndroid Build Coastguard Worker 
187*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_remove(&pv->list);
188*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_add_tail(&pv->list, &fic_dest->fi_owner);
189*1c60b9acSAndroid Build Coastguard Worker 
190*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
191*1c60b9acSAndroid Build Coastguard Worker }
192*1c60b9acSAndroid Build Coastguard Worker 
193*1c60b9acSAndroid Build Coastguard Worker static void
do_inherit(lws_fi_ctx_t * fic_dest,lws_fi_t * pfi,size_t trim)194*1c60b9acSAndroid Build Coastguard Worker do_inherit(lws_fi_ctx_t *fic_dest, lws_fi_t *pfi, size_t trim)
195*1c60b9acSAndroid Build Coastguard Worker {
196*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_t fi = *pfi;
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker 	fi.name += trim;
199*1c60b9acSAndroid Build Coastguard Worker 
200*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s: %s inherited as %s\n", __func__, fic_dest->name,
201*1c60b9acSAndroid Build Coastguard Worker 		  pfi->name, fi.name);
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 	if (fi.type == LWSFI_PATTERN_ALLOC) {
204*1c60b9acSAndroid Build Coastguard Worker 		fi.pattern = lws_malloc((size_t)((fi.count >> 3) + 1), __func__);
205*1c60b9acSAndroid Build Coastguard Worker 		if (!fi.pattern)
206*1c60b9acSAndroid Build Coastguard Worker 			return;
207*1c60b9acSAndroid Build Coastguard Worker 		memcpy((uint8_t *)fi.pattern, pfi->pattern,
208*1c60b9acSAndroid Build Coastguard Worker 		       (size_t)((fi.count >> 3) + 1));
209*1c60b9acSAndroid Build Coastguard Worker 	}
210*1c60b9acSAndroid Build Coastguard Worker 
211*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_add(fic_dest, &fi);
212*1c60b9acSAndroid Build Coastguard Worker }
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_inherit_copy(lws_fi_ctx_t * fic_dest,const lws_fi_ctx_t * fic_src,const char * scope,const char * value)215*1c60b9acSAndroid Build Coastguard Worker lws_fi_inherit_copy(lws_fi_ctx_t *fic_dest, const lws_fi_ctx_t *fic_src,
216*1c60b9acSAndroid Build Coastguard Worker 		    const char *scope, const char *value)
217*1c60b9acSAndroid Build Coastguard Worker {
218*1c60b9acSAndroid Build Coastguard Worker 	size_t sl = 0, vl = 0;
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 	if (scope)
221*1c60b9acSAndroid Build Coastguard Worker 		sl = strlen(scope);
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker 	if (value)
224*1c60b9acSAndroid Build Coastguard Worker 		vl = strlen(value);
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
227*1c60b9acSAndroid Build Coastguard Worker 				   fic_src->fi_owner.head) {
228*1c60b9acSAndroid Build Coastguard Worker 		lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
229*1c60b9acSAndroid Build Coastguard Worker 		size_t nl = strlen(pv->fi.name);
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker 		if (!scope)
232*1c60b9acSAndroid Build Coastguard Worker 			do_inherit(fic_dest, &pv->fi, 0);
233*1c60b9acSAndroid Build Coastguard Worker 		else
234*1c60b9acSAndroid Build Coastguard Worker 			if (nl > sl + 2 &&
235*1c60b9acSAndroid Build Coastguard Worker 			    !strncmp(pv->fi.name, scope, sl) &&
236*1c60b9acSAndroid Build Coastguard Worker 			    pv->fi.name[sl] == '/')
237*1c60b9acSAndroid Build Coastguard Worker 				do_inherit(fic_dest, &pv->fi, sl + 1);
238*1c60b9acSAndroid Build Coastguard Worker 			else {
239*1c60b9acSAndroid Build Coastguard Worker 				if (value && nl > sl + vl + 2 &&
240*1c60b9acSAndroid Build Coastguard Worker 				    pv->fi.name[sl] == '=' &&
241*1c60b9acSAndroid Build Coastguard Worker 				    !strncmp(pv->fi.name + sl + 1, value, vl) &&
242*1c60b9acSAndroid Build Coastguard Worker 				    pv->fi.name[sl + 1 + vl] == '/')
243*1c60b9acSAndroid Build Coastguard Worker 					do_inherit(fic_dest, &pv->fi, sl + vl + 2);
244*1c60b9acSAndroid Build Coastguard Worker 			}
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_destroy(const lws_fi_ctx_t * fic)250*1c60b9acSAndroid Build Coastguard Worker lws_fi_destroy(const lws_fi_ctx_t *fic)
251*1c60b9acSAndroid Build Coastguard Worker {
252*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
253*1c60b9acSAndroid Build Coastguard Worker 				   fic->fi_owner.head) {
254*1c60b9acSAndroid Build Coastguard Worker 		lws_fi_priv_t *pv = lws_container_of(p, lws_fi_priv_t, list);
255*1c60b9acSAndroid Build Coastguard Worker 
256*1c60b9acSAndroid Build Coastguard Worker 		if (pv->fi.type == LWSFI_PATTERN_ALLOC && pv->fi.pattern) {
257*1c60b9acSAndroid Build Coastguard Worker 			lws_free((void *)pv->fi.pattern);
258*1c60b9acSAndroid Build Coastguard Worker 			pv->fi.pattern = NULL;
259*1c60b9acSAndroid Build Coastguard Worker 		}
260*1c60b9acSAndroid Build Coastguard Worker 
261*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_remove(&pv->list);
262*1c60b9acSAndroid Build Coastguard Worker 		lws_free(pv);
263*1c60b9acSAndroid Build Coastguard Worker 
264*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, p1);
265*1c60b9acSAndroid Build Coastguard Worker }
266*1c60b9acSAndroid Build Coastguard Worker 
267*1c60b9acSAndroid Build Coastguard Worker /*
268*1c60b9acSAndroid Build Coastguard Worker  * We want to support these kinds of qualifier
269*1c60b9acSAndroid Build Coastguard Worker  *
270*1c60b9acSAndroid Build Coastguard Worker  * myfault            true always
271*1c60b9acSAndroid Build Coastguard Worker  * myfault(10%)       true 10% of the time
272*1c60b9acSAndroid Build Coastguard Worker  * myfault(....X X)   true when X
273*1c60b9acSAndroid Build Coastguard Worker  * myfault2(20..3000)  pick a number between 20 and 3000
274*1c60b9acSAndroid Build Coastguard Worker  */
275*1c60b9acSAndroid Build Coastguard Worker 
276*1c60b9acSAndroid Build Coastguard Worker enum {
277*1c60b9acSAndroid Build Coastguard Worker 	PARSE_NAME,
278*1c60b9acSAndroid Build Coastguard Worker 	PARSE_WHEN,
279*1c60b9acSAndroid Build Coastguard Worker 	PARSE_PC,
280*1c60b9acSAndroid Build Coastguard Worker 	PARSE_ENDBR,
281*1c60b9acSAndroid Build Coastguard Worker 	PARSE_COMMA
282*1c60b9acSAndroid Build Coastguard Worker };
283*1c60b9acSAndroid Build Coastguard Worker 
284*1c60b9acSAndroid Build Coastguard Worker void
lws_fi_deserialize(lws_fi_ctx_t * fic,const char * sers)285*1c60b9acSAndroid Build Coastguard Worker lws_fi_deserialize(lws_fi_ctx_t *fic, const char *sers)
286*1c60b9acSAndroid Build Coastguard Worker {
287*1c60b9acSAndroid Build Coastguard Worker 	int state = PARSE_NAME, m;
288*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tokenize ts;
289*1c60b9acSAndroid Build Coastguard Worker 	lws_fi_t fi;
290*1c60b9acSAndroid Build Coastguard Worker 	char nm[64];
291*1c60b9acSAndroid Build Coastguard Worker 
292*1c60b9acSAndroid Build Coastguard Worker 	/*
293*1c60b9acSAndroid Build Coastguard Worker 	 * Go through the comma-separated list of faults
294*1c60b9acSAndroid Build Coastguard Worker 	 * creating them and adding to the lws_context info
295*1c60b9acSAndroid Build Coastguard Worker 	 */
296*1c60b9acSAndroid Build Coastguard Worker 
297*1c60b9acSAndroid Build Coastguard Worker 	lws_tokenize_init(&ts, sers, LWS_TOKENIZE_F_DOT_NONTERM |
298*1c60b9acSAndroid Build Coastguard Worker 				     LWS_TOKENIZE_F_NO_INTEGERS |
299*1c60b9acSAndroid Build Coastguard Worker 				     LWS_TOKENIZE_F_NO_FLOATS |
300*1c60b9acSAndroid Build Coastguard Worker 				     LWS_TOKENIZE_F_EQUALS_NONTERM |
301*1c60b9acSAndroid Build Coastguard Worker 				     LWS_TOKENIZE_F_SLASH_NONTERM |
302*1c60b9acSAndroid Build Coastguard Worker 				     LWS_TOKENIZE_F_MINUS_NONTERM);
303*1c60b9acSAndroid Build Coastguard Worker 	ts.len = (unsigned int)strlen(sers);
304*1c60b9acSAndroid Build Coastguard Worker 	if (ts.len < 1 || ts.len > 10240)
305*1c60b9acSAndroid Build Coastguard Worker 		return;
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	do {
308*1c60b9acSAndroid Build Coastguard Worker 		ts.e = (int8_t)lws_tokenize(&ts);
309*1c60b9acSAndroid Build Coastguard Worker 		switch (ts.e) {
310*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_TOKEN:
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 			if (state == PARSE_NAME) {
313*1c60b9acSAndroid Build Coastguard Worker 				/*
314*1c60b9acSAndroid Build Coastguard Worker 				 * One fault to inject looks like, eg,
315*1c60b9acSAndroid Build Coastguard Worker 				 *
316*1c60b9acSAndroid Build Coastguard Worker 				 *   vh=xxx/listenskt
317*1c60b9acSAndroid Build Coastguard Worker 				 */
318*1c60b9acSAndroid Build Coastguard Worker 
319*1c60b9acSAndroid Build Coastguard Worker 				memset(&fi, 0, sizeof(fi));
320*1c60b9acSAndroid Build Coastguard Worker 
321*1c60b9acSAndroid Build Coastguard Worker 				lws_strnncpy(nm, ts.token, ts.token_len,
322*1c60b9acSAndroid Build Coastguard Worker 					     sizeof(nm));
323*1c60b9acSAndroid Build Coastguard Worker 				fi.name = nm;
324*1c60b9acSAndroid Build Coastguard Worker 				fi.type = LWSFI_ALWAYS;
325*1c60b9acSAndroid Build Coastguard Worker 
326*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: name %.*s\n", __func__,
327*1c60b9acSAndroid Build Coastguard Worker 					    (int)ts.token_len, ts.token);
328*1c60b9acSAndroid Build Coastguard Worker 
329*1c60b9acSAndroid Build Coastguard Worker 				/* added later, potentially after (when) */
330*1c60b9acSAndroid Build Coastguard Worker 				break;
331*1c60b9acSAndroid Build Coastguard Worker 			}
332*1c60b9acSAndroid Build Coastguard Worker 			if (state == PARSE_WHEN) {
333*1c60b9acSAndroid Build Coastguard Worker 				/* it's either numeric (then % or ..num2), or
334*1c60b9acSAndroid Build Coastguard Worker 				 * .X pattern */
335*1c60b9acSAndroid Build Coastguard Worker 
336*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: when\n", __func__);
337*1c60b9acSAndroid Build Coastguard Worker 
338*1c60b9acSAndroid Build Coastguard Worker 				if (*ts.token == '.' || *ts.token == 'X') {
339*1c60b9acSAndroid Build Coastguard Worker 					uint8_t *pat;
340*1c60b9acSAndroid Build Coastguard Worker 					size_t n;
341*1c60b9acSAndroid Build Coastguard Worker 
342*1c60b9acSAndroid Build Coastguard Worker 					/*
343*1c60b9acSAndroid Build Coastguard Worker 					 * pattern... we need to allocate it
344*1c60b9acSAndroid Build Coastguard Worker 					 */
345*1c60b9acSAndroid Build Coastguard Worker 					fi.type = LWSFI_PATTERN_ALLOC;
346*1c60b9acSAndroid Build Coastguard Worker 					pat = lws_zalloc((ts.token_len >> 3) + 1,
347*1c60b9acSAndroid Build Coastguard Worker 							 __func__);
348*1c60b9acSAndroid Build Coastguard Worker 					if (!pat)
349*1c60b9acSAndroid Build Coastguard Worker 						return;
350*1c60b9acSAndroid Build Coastguard Worker 					fi.pattern = pat;
351*1c60b9acSAndroid Build Coastguard Worker 					fi.count = (uint64_t)ts.token_len;
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 					for (n = 0; n < ts.token_len; n++)
354*1c60b9acSAndroid Build Coastguard Worker 						if (ts.token[n] == 'X')
355*1c60b9acSAndroid Build Coastguard Worker 							pat[n >> 3] = (uint8_t)(
356*1c60b9acSAndroid Build Coastguard Worker 								pat[n >> 3] |
357*1c60b9acSAndroid Build Coastguard Worker 								(1 << (n & 7)));
358*1c60b9acSAndroid Build Coastguard Worker 
359*1c60b9acSAndroid Build Coastguard Worker 					lwsl_hexdump_notice(pat,
360*1c60b9acSAndroid Build Coastguard Worker 						       (ts.token_len >> 3) + 1);
361*1c60b9acSAndroid Build Coastguard Worker 
362*1c60b9acSAndroid Build Coastguard Worker 					state = PARSE_ENDBR;
363*1c60b9acSAndroid Build Coastguard Worker 					break;
364*1c60b9acSAndroid Build Coastguard Worker 				}
365*1c60b9acSAndroid Build Coastguard Worker 
366*1c60b9acSAndroid Build Coastguard Worker 				fi.pre = (uint64_t)atoll(ts.token);
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker 				for (m = 0; m < (int)ts.token_len - 1; m++)
369*1c60b9acSAndroid Build Coastguard Worker 					if (ts.token[m] < '0' ||
370*1c60b9acSAndroid Build Coastguard Worker 					    ts.token[m] > '9')
371*1c60b9acSAndroid Build Coastguard Worker 						break;
372*1c60b9acSAndroid Build Coastguard Worker 
373*1c60b9acSAndroid Build Coastguard Worker 				/*
374*1c60b9acSAndroid Build Coastguard Worker 				 * We can understand num% or num..num
375*1c60b9acSAndroid Build Coastguard Worker 				 */
376*1c60b9acSAndroid Build Coastguard Worker 
377*1c60b9acSAndroid Build Coastguard Worker 				if (m != (int)ts.token_len &&
378*1c60b9acSAndroid Build Coastguard Worker 				    ts.token[m] == '.' &&
379*1c60b9acSAndroid Build Coastguard Worker 				    ts.token[m + 1] == '.') {
380*1c60b9acSAndroid Build Coastguard Worker 					fi.count = (uint64_t)atoll(
381*1c60b9acSAndroid Build Coastguard Worker 						&ts.token[m + 2]);
382*1c60b9acSAndroid Build Coastguard Worker 					fi.type = LWSFI_RANGE;
383*1c60b9acSAndroid Build Coastguard Worker 					state = PARSE_ENDBR;
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker 					if (fi.pre >= fi.count) {
386*1c60b9acSAndroid Build Coastguard Worker 						lwsl_err("%s: range must have "
387*1c60b9acSAndroid Build Coastguard Worker 							 "smaller first!\n",
388*1c60b9acSAndroid Build Coastguard Worker 							 __func__);
389*1c60b9acSAndroid Build Coastguard Worker 					}
390*1c60b9acSAndroid Build Coastguard Worker 
391*1c60b9acSAndroid Build Coastguard Worker 					lwsl_notice("%s: range %llx .."
392*1c60b9acSAndroid Build Coastguard Worker 						    "%llx\n", __func__,
393*1c60b9acSAndroid Build Coastguard Worker 						    (unsigned long long)fi.pre,
394*1c60b9acSAndroid Build Coastguard Worker 						    (unsigned long long)fi.count);
395*1c60b9acSAndroid Build Coastguard Worker 					break;
396*1c60b9acSAndroid Build Coastguard Worker 				}
397*1c60b9acSAndroid Build Coastguard Worker 
398*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: prob %d%%\n", __func__,
399*1c60b9acSAndroid Build Coastguard Worker 					    (int)fi.pre);
400*1c60b9acSAndroid Build Coastguard Worker 				fi.type = LWSFI_PROBABILISTIC;
401*1c60b9acSAndroid Build Coastguard Worker 				state = PARSE_PC;
402*1c60b9acSAndroid Build Coastguard Worker 				break;
403*1c60b9acSAndroid Build Coastguard Worker 			}
404*1c60b9acSAndroid Build Coastguard Worker 			break;
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_DELIMITER:
407*1c60b9acSAndroid Build Coastguard Worker 			if (*ts.token == ',') {
408*1c60b9acSAndroid Build Coastguard Worker 				lws_fi_add(fic, &fi);
409*1c60b9acSAndroid Build Coastguard Worker 				state = PARSE_NAME;
410*1c60b9acSAndroid Build Coastguard Worker 				break;
411*1c60b9acSAndroid Build Coastguard Worker 			}
412*1c60b9acSAndroid Build Coastguard Worker 			if (*ts.token == '(') {
413*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: (\n", __func__);
414*1c60b9acSAndroid Build Coastguard Worker 				if (state != PARSE_NAME) {
415*1c60b9acSAndroid Build Coastguard Worker 					lwsl_err("%s: misplaced (\n", __func__);
416*1c60b9acSAndroid Build Coastguard Worker 					return;
417*1c60b9acSAndroid Build Coastguard Worker 				}
418*1c60b9acSAndroid Build Coastguard Worker 				state = PARSE_WHEN;
419*1c60b9acSAndroid Build Coastguard Worker 				break;
420*1c60b9acSAndroid Build Coastguard Worker 			}
421*1c60b9acSAndroid Build Coastguard Worker 			if (*ts.token == ')') {
422*1c60b9acSAndroid Build Coastguard Worker 				if (state != PARSE_ENDBR) {
423*1c60b9acSAndroid Build Coastguard Worker 					lwsl_err("%s: misplaced )\n", __func__);
424*1c60b9acSAndroid Build Coastguard Worker 					return;
425*1c60b9acSAndroid Build Coastguard Worker 				}
426*1c60b9acSAndroid Build Coastguard Worker 				state = PARSE_NAME;
427*1c60b9acSAndroid Build Coastguard Worker 				break;
428*1c60b9acSAndroid Build Coastguard Worker 			}
429*1c60b9acSAndroid Build Coastguard Worker 			if (*ts.token == '%') {
430*1c60b9acSAndroid Build Coastguard Worker 				if (state != PARSE_PC) {
431*1c60b9acSAndroid Build Coastguard Worker 					lwsl_err("%s: misplaced %%\n", __func__);
432*1c60b9acSAndroid Build Coastguard Worker 					return;
433*1c60b9acSAndroid Build Coastguard Worker 				}
434*1c60b9acSAndroid Build Coastguard Worker 				state = PARSE_ENDBR;
435*1c60b9acSAndroid Build Coastguard Worker 				break;
436*1c60b9acSAndroid Build Coastguard Worker 			}
437*1c60b9acSAndroid Build Coastguard Worker 			break;
438*1c60b9acSAndroid Build Coastguard Worker 
439*1c60b9acSAndroid Build Coastguard Worker 		case LWS_TOKZE_ENDED:
440*1c60b9acSAndroid Build Coastguard Worker 			lws_fi_add(fic, &fi);
441*1c60b9acSAndroid Build Coastguard Worker 			return;
442*1c60b9acSAndroid Build Coastguard Worker 
443*1c60b9acSAndroid Build Coastguard Worker 		default:
444*1c60b9acSAndroid Build Coastguard Worker 			return;
445*1c60b9acSAndroid Build Coastguard Worker 		}
446*1c60b9acSAndroid Build Coastguard Worker 	} while (ts.e > 0);
447*1c60b9acSAndroid Build Coastguard Worker }
448