1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * lws-api-test-async-dns
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Written in 2019 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 * This api test confirms various kinds of async dns apis
10d4afb5ceSopenharmony_ci */
11d4afb5ceSopenharmony_ci
12d4afb5ceSopenharmony_ci#include <libwebsockets.h>
13d4afb5ceSopenharmony_ci#include <signal.h>
14d4afb5ceSopenharmony_ci
15d4afb5ceSopenharmony_cistatic int interrupted, dtest, ok, fail, _exp = 26;
16d4afb5ceSopenharmony_cistruct lws_context *context;
17d4afb5ceSopenharmony_ci
18d4afb5ceSopenharmony_ci/*
19d4afb5ceSopenharmony_ci * These are used to test the apis to parse and print ipv4 / ipv6 literal
20d4afb5ceSopenharmony_ci * address strings for various cases.
21d4afb5ceSopenharmony_ci *
22d4afb5ceSopenharmony_ci * Expected error cases are not used to test the ip data -> string api.
23d4afb5ceSopenharmony_ci */
24d4afb5ceSopenharmony_ci
25d4afb5ceSopenharmony_cistatic const struct ipparser_tests {
26d4afb5ceSopenharmony_ci	const char	*test;
27d4afb5ceSopenharmony_ci	int		rlen;
28d4afb5ceSopenharmony_ci	const char	*emit_test;
29d4afb5ceSopenharmony_ci	int		emit_len;
30d4afb5ceSopenharmony_ci	uint8_t		b[16];
31d4afb5ceSopenharmony_ci} ipt[] = {
32d4afb5ceSopenharmony_ci	{ "2001:db8:85a3:0:0:8a2e:370:7334", 16,
33d4afb5ceSopenharmony_ci	  "2001:db8:85a3::8a2e:370:7334", 28,
34d4afb5ceSopenharmony_ci		{ 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00,
35d4afb5ceSopenharmony_ci		  0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 } },
36d4afb5ceSopenharmony_ci
37d4afb5ceSopenharmony_ci	{ "2001:db8:85a3::8a2e:370:7334", 16,
38d4afb5ceSopenharmony_ci	  "2001:db8:85a3::8a2e:370:7334", 28,
39d4afb5ceSopenharmony_ci		{ 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00,
40d4afb5ceSopenharmony_ci		  0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 } },
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_ci	{ "::1", 16, "::1", 3,
43d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
44d4afb5ceSopenharmony_ci
45d4afb5ceSopenharmony_ci	{ "::",  16, "::", 2,
46d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
47d4afb5ceSopenharmony_ci
48d4afb5ceSopenharmony_ci	{ "::ffff:192.0.2.128", 16,  "::ffff:192.0.2.128", 18,
49d4afb5ceSopenharmony_ci		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50d4afb5ceSopenharmony_ci		  0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x02, 0x80 } },
51d4afb5ceSopenharmony_ci
52d4afb5ceSopenharmony_ci	{ "cats", -1, "", 0,
53d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
54d4afb5ceSopenharmony_ci
55d4afb5ceSopenharmony_ci	{ "onevalid.bogus.warmcat.com", -1, "", 0,
56d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
57d4afb5ceSopenharmony_ci
58d4afb5ceSopenharmony_ci	{ "1.cat.dog.com", -1, "", 0,
59d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
60d4afb5ceSopenharmony_ci
61d4afb5ceSopenharmony_ci	{ ":::1", -8, "", 0,
62d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
63d4afb5ceSopenharmony_ci
64d4afb5ceSopenharmony_ci	{ "0:0::0:1", 16, "::1", 3,
65d4afb5ceSopenharmony_ci			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
66d4afb5ceSopenharmony_ci
67d4afb5ceSopenharmony_ci	{ "1.2.3.4", 4, "1.2.3.4", 7, { 1, 2, 3, 4 } },
68d4afb5ceSopenharmony_ci};
69d4afb5ceSopenharmony_ci
70d4afb5ceSopenharmony_cistatic const struct async_dns_tests {
71d4afb5ceSopenharmony_ci	const char *dns_name;
72d4afb5ceSopenharmony_ci	int recordtype;
73d4afb5ceSopenharmony_ci	int addrlen;
74d4afb5ceSopenharmony_ci	uint8_t ads[16];
75d4afb5ceSopenharmony_ci} adt[] = {
76d4afb5ceSopenharmony_ci	{ "warmcat.com", LWS_ADNS_RECORD_A, 4,
77d4afb5ceSopenharmony_ci		{ 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
78d4afb5ceSopenharmony_ci	{ "libwebsockets.org", LWS_ADNS_RECORD_A, 4,
79d4afb5ceSopenharmony_ci		{ 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
80d4afb5ceSopenharmony_ci	{ "doesntexist", LWS_ADNS_RECORD_A, 0,
81d4afb5ceSopenharmony_ci		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
82d4afb5ceSopenharmony_ci	{ "localhost", LWS_ADNS_RECORD_A, 4,
83d4afb5ceSopenharmony_ci		{ 127, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
84d4afb5ceSopenharmony_ci	{ "ipv4only.warmcat.com", LWS_ADNS_RECORD_A, 4,
85d4afb5ceSopenharmony_ci		{ 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
86d4afb5ceSopenharmony_ci	{ "onevalid.bogus.warmcat.com", LWS_ADNS_RECORD_A, 4,
87d4afb5ceSopenharmony_ci		{ 46, 105, 127, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
88d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6)
89d4afb5ceSopenharmony_ci	{ "warmcat.com", LWS_ADNS_RECORD_AAAA, 16, /* check ipv6 */
90d4afb5ceSopenharmony_ci		{ 0x20, 0x01, 0x41, 0xd0, 0x00, 0x02, 0xee, 0x93,
91d4afb5ceSopenharmony_ci				0, 0, 0, 0, 0, 0, 0, 1, } },
92d4afb5ceSopenharmony_ci	{ "ipv6only.warmcat.com", LWS_ADNS_RECORD_AAAA, 16, /* check ipv6 */
93d4afb5ceSopenharmony_ci		{ 0x20, 0x01, 0x41, 0xd0, 0x00, 0x02, 0xee, 0x93,
94d4afb5ceSopenharmony_ci				0, 0, 0, 0, 0, 0, 0, 1, } },
95d4afb5ceSopenharmony_ci#endif
96d4afb5ceSopenharmony_ci};
97d4afb5ceSopenharmony_ci
98d4afb5ceSopenharmony_cistatic lws_sorted_usec_list_t sul;
99d4afb5ceSopenharmony_ci
100d4afb5ceSopenharmony_cistruct lws *
101d4afb5ceSopenharmony_cicb1(struct lws *wsi_unused, const char *ads, const struct addrinfo *a, int n,
102d4afb5ceSopenharmony_ci    void *opaque);
103d4afb5ceSopenharmony_ci
104d4afb5ceSopenharmony_cistatic void
105d4afb5ceSopenharmony_cinext_test_cb(lws_sorted_usec_list_t *sul)
106d4afb5ceSopenharmony_ci{
107d4afb5ceSopenharmony_ci	int m;
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci	lwsl_notice("%s: querying %s\n", __func__, adt[dtest].dns_name);
110d4afb5ceSopenharmony_ci
111d4afb5ceSopenharmony_ci	m = lws_async_dns_query(context, 0,
112d4afb5ceSopenharmony_ci				adt[dtest].dns_name,
113d4afb5ceSopenharmony_ci				(adns_query_type_t)adt[dtest].recordtype, cb1, NULL,
114d4afb5ceSopenharmony_ci				context);
115d4afb5ceSopenharmony_ci	if (m != LADNS_RET_CONTINUING && m != LADNS_RET_FOUND && m != LADNS_RET_FAILED_WSI_CLOSED) {
116d4afb5ceSopenharmony_ci		lwsl_err("%s: adns 1: %s failed: %d\n", __func__, adt[dtest].dns_name, m);
117d4afb5ceSopenharmony_ci		interrupted = 1;
118d4afb5ceSopenharmony_ci	}
119d4afb5ceSopenharmony_ci}
120d4afb5ceSopenharmony_ci
121d4afb5ceSopenharmony_cistruct lws *
122d4afb5ceSopenharmony_cicb1(struct lws *wsi_unused, const char *ads, const struct addrinfo *a, int n,
123d4afb5ceSopenharmony_ci    void *opaque)
124d4afb5ceSopenharmony_ci{
125d4afb5ceSopenharmony_ci	const struct addrinfo *ac = a;
126d4afb5ceSopenharmony_ci	int ctr = 0, alen;
127d4afb5ceSopenharmony_ci	uint8_t *addr;
128d4afb5ceSopenharmony_ci	char buf[64];
129d4afb5ceSopenharmony_ci
130d4afb5ceSopenharmony_ci	dtest++;
131d4afb5ceSopenharmony_ci
132d4afb5ceSopenharmony_ci	if (!ac)
133d4afb5ceSopenharmony_ci		lwsl_warn("%s: no results\n", __func__);
134d4afb5ceSopenharmony_ci
135d4afb5ceSopenharmony_ci	/* dump the results */
136d4afb5ceSopenharmony_ci
137d4afb5ceSopenharmony_ci	while (ac) {
138d4afb5ceSopenharmony_ci		if (ac->ai_family == AF_INET) {
139d4afb5ceSopenharmony_ci			addr = (uint8_t *)&(((struct sockaddr_in *)
140d4afb5ceSopenharmony_ci					ac->ai_addr)->sin_addr.s_addr);
141d4afb5ceSopenharmony_ci			alen = 4;
142d4afb5ceSopenharmony_ci		} else {
143d4afb5ceSopenharmony_ci			addr = (uint8_t *)&(((struct sockaddr_in6 *)
144d4afb5ceSopenharmony_ci					ac->ai_addr)->sin6_addr.s6_addr);
145d4afb5ceSopenharmony_ci			alen = 16;
146d4afb5ceSopenharmony_ci		}
147d4afb5ceSopenharmony_ci		strcpy(buf, "unknown");
148d4afb5ceSopenharmony_ci		lws_write_numeric_address(addr, alen, buf, sizeof(buf));
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ci		lwsl_warn("%s: %d: %s %d %s\n", __func__, ctr++, ads, alen, buf);
151d4afb5ceSopenharmony_ci
152d4afb5ceSopenharmony_ci		ac = ac->ai_next;
153d4afb5ceSopenharmony_ci	}
154d4afb5ceSopenharmony_ci
155d4afb5ceSopenharmony_ci	ac = a;
156d4afb5ceSopenharmony_ci	while (ac) {
157d4afb5ceSopenharmony_ci		if (ac->ai_family == AF_INET) {
158d4afb5ceSopenharmony_ci			addr = (uint8_t *)&(((struct sockaddr_in *)
159d4afb5ceSopenharmony_ci					ac->ai_addr)->sin_addr.s_addr);
160d4afb5ceSopenharmony_ci			alen = 4;
161d4afb5ceSopenharmony_ci		} else {
162d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6)
163d4afb5ceSopenharmony_ci			addr = (uint8_t *)&(((struct sockaddr_in6 *)
164d4afb5ceSopenharmony_ci					ac->ai_addr)->sin6_addr.s6_addr);
165d4afb5ceSopenharmony_ci			alen = 16;
166d4afb5ceSopenharmony_ci#else
167d4afb5ceSopenharmony_ci			goto again;
168d4afb5ceSopenharmony_ci#endif
169d4afb5ceSopenharmony_ci		}
170d4afb5ceSopenharmony_ci		if (alen == adt[dtest - 1].addrlen &&
171d4afb5ceSopenharmony_ci		    !memcmp(adt[dtest - 1].ads, addr, (unsigned int)alen)) {
172d4afb5ceSopenharmony_ci			ok++;
173d4afb5ceSopenharmony_ci			goto next;
174d4afb5ceSopenharmony_ci		}
175d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_IPV6)
176d4afb5ceSopenharmony_ciagain:
177d4afb5ceSopenharmony_ci#endif
178d4afb5ceSopenharmony_ci		ac = ac->ai_next;
179d4afb5ceSopenharmony_ci	}
180d4afb5ceSopenharmony_ci
181d4afb5ceSopenharmony_ci	/* testing for NXDOMAIN? */
182d4afb5ceSopenharmony_ci
183d4afb5ceSopenharmony_ci	if (!a && !adt[dtest - 1].addrlen) {
184d4afb5ceSopenharmony_ci		ok++;
185d4afb5ceSopenharmony_ci		goto next;
186d4afb5ceSopenharmony_ci	}
187d4afb5ceSopenharmony_ci
188d4afb5ceSopenharmony_ci	lwsl_err("%s: dns test %d: no match\n", __func__, dtest);
189d4afb5ceSopenharmony_ci	fail++;
190d4afb5ceSopenharmony_ci
191d4afb5ceSopenharmony_cinext:
192d4afb5ceSopenharmony_ci	lws_async_dns_freeaddrinfo(&a);
193d4afb5ceSopenharmony_ci	if (dtest == (int)LWS_ARRAY_SIZE(adt))
194d4afb5ceSopenharmony_ci		interrupted = 1;
195d4afb5ceSopenharmony_ci	else
196d4afb5ceSopenharmony_ci		lws_sul_schedule(context, 0, &sul, next_test_cb, 1);
197d4afb5ceSopenharmony_ci
198d4afb5ceSopenharmony_ci	return NULL;
199d4afb5ceSopenharmony_ci}
200d4afb5ceSopenharmony_ci
201d4afb5ceSopenharmony_cistatic lws_sorted_usec_list_t sul_l;
202d4afb5ceSopenharmony_ci
203d4afb5ceSopenharmony_cistruct lws *
204d4afb5ceSopenharmony_cicb_loop(struct lws *wsi_unused, const char *ads, const struct addrinfo *a, int n,
205d4afb5ceSopenharmony_ci		void *opaque)
206d4afb5ceSopenharmony_ci{
207d4afb5ceSopenharmony_ci	if (!a) {
208d4afb5ceSopenharmony_ci		lwsl_err("%s: no results\n", __func__);
209d4afb5ceSopenharmony_ci		return NULL;
210d4afb5ceSopenharmony_ci	}
211d4afb5ceSopenharmony_ci
212d4afb5ceSopenharmony_ci	lwsl_notice("%s: addrinfo %p\n", __func__, a);\
213d4afb5ceSopenharmony_ci	lws_async_dns_freeaddrinfo(&a);
214d4afb5ceSopenharmony_ci
215d4afb5ceSopenharmony_ci	return NULL;
216d4afb5ceSopenharmony_ci}
217d4afb5ceSopenharmony_ci
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_cistatic void
220d4afb5ceSopenharmony_cisul_retry_l(struct lws_sorted_usec_list *sul)
221d4afb5ceSopenharmony_ci{
222d4afb5ceSopenharmony_ci	int m;
223d4afb5ceSopenharmony_ci
224d4afb5ceSopenharmony_ci	lwsl_user("%s: starting new query\n", __func__);
225d4afb5ceSopenharmony_ci
226d4afb5ceSopenharmony_ci	m = lws_async_dns_query(context, 0, "warmcat.com",
227d4afb5ceSopenharmony_ci				    (adns_query_type_t)LWS_ADNS_RECORD_A,
228d4afb5ceSopenharmony_ci				    cb_loop, NULL, context);
229d4afb5ceSopenharmony_ci	switch (m) {
230d4afb5ceSopenharmony_ci	case LADNS_RET_FAILED_WSI_CLOSED:
231d4afb5ceSopenharmony_ci		lwsl_warn("%s: LADNS_RET_FAILED_WSI_CLOSED "
232d4afb5ceSopenharmony_ci			  "(== from cache / success in this test)\n", __func__);
233d4afb5ceSopenharmony_ci		break;
234d4afb5ceSopenharmony_ci	case LADNS_RET_NXDOMAIN:
235d4afb5ceSopenharmony_ci		lwsl_warn("%s: LADNS_RET_NXDOMAIN\n", __func__);
236d4afb5ceSopenharmony_ci		break;
237d4afb5ceSopenharmony_ci	case LADNS_RET_TIMEDOUT:
238d4afb5ceSopenharmony_ci		lwsl_warn("%s: LADNS_RET_TIMEDOUT\n", __func__);
239d4afb5ceSopenharmony_ci		break;
240d4afb5ceSopenharmony_ci	case LADNS_RET_FAILED:
241d4afb5ceSopenharmony_ci		lwsl_warn("%s: LADNS_RET_FAILED\n", __func__);
242d4afb5ceSopenharmony_ci		break;
243d4afb5ceSopenharmony_ci	case LADNS_RET_FOUND:
244d4afb5ceSopenharmony_ci		lwsl_warn("%s: LADNS_RET_FOUND\n", __func__);
245d4afb5ceSopenharmony_ci		break;
246d4afb5ceSopenharmony_ci	case LADNS_RET_CONTINUING:
247d4afb5ceSopenharmony_ci		lwsl_warn("%s: LADNS_RET_CONTINUING\n", __func__);
248d4afb5ceSopenharmony_ci		break;
249d4afb5ceSopenharmony_ci	}
250d4afb5ceSopenharmony_ci
251d4afb5ceSopenharmony_ci	lws_sul_schedule(context, 0, &sul_l, sul_retry_l, 5 * LWS_US_PER_SEC);
252d4afb5ceSopenharmony_ci}
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_civoid sigint_handler(int sig)
255d4afb5ceSopenharmony_ci{
256d4afb5ceSopenharmony_ci	interrupted = 1;
257d4afb5ceSopenharmony_ci}
258d4afb5ceSopenharmony_ci
259d4afb5ceSopenharmony_ciint
260d4afb5ceSopenharmony_cimain(int argc, const char **argv)
261d4afb5ceSopenharmony_ci{
262d4afb5ceSopenharmony_ci	int n = 1, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
263d4afb5ceSopenharmony_ci	struct lws_context_creation_info info;
264d4afb5ceSopenharmony_ci	const char *p;
265d4afb5ceSopenharmony_ci
266d4afb5ceSopenharmony_ci	/* the normal lws init */
267d4afb5ceSopenharmony_ci
268d4afb5ceSopenharmony_ci	signal(SIGINT, sigint_handler);
269d4afb5ceSopenharmony_ci
270d4afb5ceSopenharmony_ci	if ((p = lws_cmdline_option(argc, argv, "-d")))
271d4afb5ceSopenharmony_ci		logs = atoi(p);
272d4afb5ceSopenharmony_ci
273d4afb5ceSopenharmony_ci	lws_set_log_level(logs, NULL);
274d4afb5ceSopenharmony_ci	lwsl_user("LWS API selftest: Async DNS\n");
275d4afb5ceSopenharmony_ci
276d4afb5ceSopenharmony_ci	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
277d4afb5ceSopenharmony_ci	info.port = CONTEXT_PORT_NO_LISTEN;
278d4afb5ceSopenharmony_ci	info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
279d4afb5ceSopenharmony_ci
280d4afb5ceSopenharmony_ci	context = lws_create_context(&info);
281d4afb5ceSopenharmony_ci	if (!context) {
282d4afb5ceSopenharmony_ci		lwsl_err("lws init failed\n");
283d4afb5ceSopenharmony_ci		return 1;
284d4afb5ceSopenharmony_ci	}
285d4afb5ceSopenharmony_ci
286d4afb5ceSopenharmony_ci	if (lws_cmdline_option(argc, argv, "-l")) {
287d4afb5ceSopenharmony_ci		lws_sul_schedule(context, 0, &sul_l, sul_retry_l, LWS_US_PER_SEC);
288d4afb5ceSopenharmony_ci		goto evloop;
289d4afb5ceSopenharmony_ci	}
290d4afb5ceSopenharmony_ci
291d4afb5ceSopenharmony_ci
292d4afb5ceSopenharmony_ci	/* ip address parser tests */
293d4afb5ceSopenharmony_ci
294d4afb5ceSopenharmony_ci	for (n = 0; n < (int)LWS_ARRAY_SIZE(ipt); n++) {
295d4afb5ceSopenharmony_ci		uint8_t u[16];
296d4afb5ceSopenharmony_ci		int m = lws_parse_numeric_address(ipt[n].test, u, sizeof(u));
297d4afb5ceSopenharmony_ci
298d4afb5ceSopenharmony_ci		if (m != ipt[n].rlen) {
299d4afb5ceSopenharmony_ci			lwsl_err("%s: fail %s ret %d\n",
300d4afb5ceSopenharmony_ci					__func__, ipt[n].test, m);
301d4afb5ceSopenharmony_ci			fail++;
302d4afb5ceSopenharmony_ci			continue;
303d4afb5ceSopenharmony_ci		}
304d4afb5ceSopenharmony_ci
305d4afb5ceSopenharmony_ci		if (m > 0) {
306d4afb5ceSopenharmony_ci			if (memcmp(ipt[n].b, u, (unsigned int)m)) {
307d4afb5ceSopenharmony_ci				lwsl_err("%s: fail %s compare\n", __func__,
308d4afb5ceSopenharmony_ci						ipt[n].test);
309d4afb5ceSopenharmony_ci				lwsl_hexdump_notice(u, (unsigned int)m);
310d4afb5ceSopenharmony_ci				fail++;
311d4afb5ceSopenharmony_ci				continue;
312d4afb5ceSopenharmony_ci			}
313d4afb5ceSopenharmony_ci		}
314d4afb5ceSopenharmony_ci		ok++;
315d4afb5ceSopenharmony_ci	}
316d4afb5ceSopenharmony_ci
317d4afb5ceSopenharmony_ci	/* ip address formatter tests */
318d4afb5ceSopenharmony_ci
319d4afb5ceSopenharmony_ci	for (n = 0; n < (int)LWS_ARRAY_SIZE(ipt); n++) {
320d4afb5ceSopenharmony_ci		char buf[64];
321d4afb5ceSopenharmony_ci		int m;
322d4afb5ceSopenharmony_ci
323d4afb5ceSopenharmony_ci		/* don't attempt to reverse the ones that are meant to fail */
324d4afb5ceSopenharmony_ci		if (ipt[n].rlen < 0)
325d4afb5ceSopenharmony_ci			continue;
326d4afb5ceSopenharmony_ci
327d4afb5ceSopenharmony_ci		m = lws_write_numeric_address(ipt[n].b, ipt[n].rlen, buf,
328d4afb5ceSopenharmony_ci						sizeof(buf));
329d4afb5ceSopenharmony_ci		if (m != ipt[n].emit_len) {
330d4afb5ceSopenharmony_ci			lwsl_err("%s: fail %s ret %d\n",
331d4afb5ceSopenharmony_ci					__func__, ipt[n].emit_test, m);
332d4afb5ceSopenharmony_ci			fail++;
333d4afb5ceSopenharmony_ci			continue;
334d4afb5ceSopenharmony_ci		}
335d4afb5ceSopenharmony_ci
336d4afb5ceSopenharmony_ci		if (m > 0) {
337d4afb5ceSopenharmony_ci			if (strcmp(ipt[n].emit_test, buf)) {
338d4afb5ceSopenharmony_ci				lwsl_err("%s: fail %s compare\n", __func__,
339d4afb5ceSopenharmony_ci						ipt[n].test);
340d4afb5ceSopenharmony_ci				lwsl_hexdump_notice(buf, (unsigned int)m);
341d4afb5ceSopenharmony_ci				fail++;
342d4afb5ceSopenharmony_ci				continue;
343d4afb5ceSopenharmony_ci			}
344d4afb5ceSopenharmony_ci		}
345d4afb5ceSopenharmony_ci		ok++;
346d4afb5ceSopenharmony_ci	}
347d4afb5ceSopenharmony_ci
348d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_IPV6)
349d4afb5ceSopenharmony_ci	_exp -= 2;
350d4afb5ceSopenharmony_ci#endif
351d4afb5ceSopenharmony_ci
352d4afb5ceSopenharmony_ci	/* kick off the async dns tests */
353d4afb5ceSopenharmony_ci
354d4afb5ceSopenharmony_ci	lws_sul_schedule(context, 0, &sul, next_test_cb, 1);
355d4afb5ceSopenharmony_ci
356d4afb5ceSopenharmony_cievloop:
357d4afb5ceSopenharmony_ci	/* the usual lws event loop */
358d4afb5ceSopenharmony_ci
359d4afb5ceSopenharmony_ci	n = 1;
360d4afb5ceSopenharmony_ci	while (n >= 0 && !interrupted)
361d4afb5ceSopenharmony_ci		n = lws_service(context, 0);
362d4afb5ceSopenharmony_ci
363d4afb5ceSopenharmony_ci	lws_context_destroy(context);
364d4afb5ceSopenharmony_ci
365d4afb5ceSopenharmony_ci	if (fail || ok != _exp)
366d4afb5ceSopenharmony_ci		lwsl_user("Completed: PASS: %d / %d, FAIL: %d\n", ok, _exp,
367d4afb5ceSopenharmony_ci				fail);
368d4afb5ceSopenharmony_ci	else
369d4afb5ceSopenharmony_ci		lwsl_user("Completed: ALL PASS: %d / %d\n", ok, _exp);
370d4afb5ceSopenharmony_ci
371d4afb5ceSopenharmony_ci	return !(ok == _exp && !fail);
372d4afb5ceSopenharmony_ci}
373