1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci */
24d4afb5ceSopenharmony_ci
25d4afb5ceSopenharmony_ci#include "private-lib-core.h"
26d4afb5ceSopenharmony_ci
27d4afb5ceSopenharmony_ci#ifndef LWS_BUILD_HASH
28d4afb5ceSopenharmony_ci#define LWS_BUILD_HASH "unknown-build-hash"
29d4afb5ceSopenharmony_ci#endif
30d4afb5ceSopenharmony_ci
31d4afb5ceSopenharmony_cistatic const char *library_version = LWS_LIBRARY_VERSION;
32d4afb5ceSopenharmony_ci
33d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS)
34d4afb5ceSopenharmony_ciextern const char *mbedtls_client_preload_filepath;
35d4afb5ceSopenharmony_ci#endif
36d4afb5ceSopenharmony_ci
37d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_SYS_RESOURCE_H)
38d4afb5ceSopenharmony_ci/* for setrlimit */
39d4afb5ceSopenharmony_ci#include <sys/resource.h>
40d4afb5ceSopenharmony_ci#endif
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
43d4afb5ceSopenharmony_ci/* in ms */
44d4afb5ceSopenharmony_cistatic uint32_t default_backoff_table[] = { 1000, 3000, 9000, 17000 };
45d4afb5ceSopenharmony_ci#endif
46d4afb5ceSopenharmony_ci
47d4afb5ceSopenharmony_ci/**
48d4afb5ceSopenharmony_ci * lws_get_library_version: get version and git hash library built from
49d4afb5ceSopenharmony_ci *
50d4afb5ceSopenharmony_ci *	returns a const char * to a string like "1.1 178d78c"
51d4afb5ceSopenharmony_ci *	representing the library version followed by the git head hash it
52d4afb5ceSopenharmony_ci *	was built from
53d4afb5ceSopenharmony_ci */
54d4afb5ceSopenharmony_ciconst char *
55d4afb5ceSopenharmony_cilws_get_library_version(void)
56d4afb5ceSopenharmony_ci{
57d4afb5ceSopenharmony_ci	return library_version;
58d4afb5ceSopenharmony_ci}
59d4afb5ceSopenharmony_ci
60d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
61d4afb5ceSopenharmony_ci
62d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
63d4afb5ceSopenharmony_ci
64d4afb5ceSopenharmony_cistatic const char * system_state_names[] = {
65d4afb5ceSopenharmony_ci	"undef",
66d4afb5ceSopenharmony_ci	"CONTEXT_CREATED",
67d4afb5ceSopenharmony_ci	"INITIALIZED",
68d4afb5ceSopenharmony_ci	"IFACE_COLDPLUG",
69d4afb5ceSopenharmony_ci	"DHCP",
70d4afb5ceSopenharmony_ci	"CPD_PRE_TIME",
71d4afb5ceSopenharmony_ci	"TIME_VALID",
72d4afb5ceSopenharmony_ci	"CPD_POST_TIME",
73d4afb5ceSopenharmony_ci	"POLICY_VALID",
74d4afb5ceSopenharmony_ci	"REGISTERED",
75d4afb5ceSopenharmony_ci	"AUTH1",
76d4afb5ceSopenharmony_ci	"AUTH2",
77d4afb5ceSopenharmony_ci	"OPERATIONAL",
78d4afb5ceSopenharmony_ci	"POLICY_INVALID",
79d4afb5ceSopenharmony_ci	"DESTROYING"
80d4afb5ceSopenharmony_ci};
81d4afb5ceSopenharmony_ci
82d4afb5ceSopenharmony_ci
83d4afb5ceSopenharmony_ci/*
84d4afb5ceSopenharmony_ci * Handle provoking protocol init when we pass through the right system state
85d4afb5ceSopenharmony_ci */
86d4afb5ceSopenharmony_ci
87d4afb5ceSopenharmony_cistatic int
88d4afb5ceSopenharmony_cilws_state_notify_protocol_init(struct lws_state_manager *mgr,
89d4afb5ceSopenharmony_ci			       struct lws_state_notify_link *link, int current,
90d4afb5ceSopenharmony_ci			       int target)
91d4afb5ceSopenharmony_ci{
92d4afb5ceSopenharmony_ci	struct lws_context *context = lws_container_of(mgr, struct lws_context,
93d4afb5ceSopenharmony_ci						       mgr_system);
94d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS) && \
95d4afb5ceSopenharmony_ci    defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM)
96d4afb5ceSopenharmony_ci	lws_system_blob_t *ab0, *ab1;
97d4afb5ceSopenharmony_ci#endif
98d4afb5ceSopenharmony_ci	int n;
99d4afb5ceSopenharmony_ci
100d4afb5ceSopenharmony_ci	/*
101d4afb5ceSopenharmony_ci	 * Deal with any attachments that were waiting for the right state
102d4afb5ceSopenharmony_ci	 * to come along
103d4afb5ceSopenharmony_ci	 */
104d4afb5ceSopenharmony_ci
105d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++)
106d4afb5ceSopenharmony_ci		lws_system_do_attach(&context->pt[n]);
107d4afb5ceSopenharmony_ci
108d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT)
109d4afb5ceSopenharmony_ci	if (target == LWS_SYSTATE_DHCP) {
110d4afb5ceSopenharmony_ci		/*
111d4afb5ceSopenharmony_ci		 * Don't let it past here until at least one iface has been
112d4afb5ceSopenharmony_ci		 * configured for operation with DHCP
113d4afb5ceSopenharmony_ci		 */
114d4afb5ceSopenharmony_ci
115d4afb5ceSopenharmony_ci		if (!lws_dhcpc_status(context, NULL))
116d4afb5ceSopenharmony_ci			return 1;
117d4afb5ceSopenharmony_ci	}
118d4afb5ceSopenharmony_ci#endif
119d4afb5ceSopenharmony_ci
120d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_NTPCLIENT)
121d4afb5ceSopenharmony_ci	if (target == LWS_SYSTATE_TIME_VALID &&
122d4afb5ceSopenharmony_ci	    lws_now_secs() < 1594017754) /* 06:42 Mon Jul 6 2020 UTC */ {
123d4afb5ceSopenharmony_ci		lws_ntpc_trigger(context);
124d4afb5ceSopenharmony_ci
125d4afb5ceSopenharmony_ci		return 1;
126d4afb5ceSopenharmony_ci	}
127d4afb5ceSopenharmony_ci#endif
128d4afb5ceSopenharmony_ci
129d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETLINK)
130d4afb5ceSopenharmony_ci	/*
131d4afb5ceSopenharmony_ci	 * If we're going to use netlink routing data for DNS, we have to
132d4afb5ceSopenharmony_ci	 * wait to collect it asynchronously from the platform first.  Netlink
133d4afb5ceSopenharmony_ci	 * role init starts a ctx sul for 350ms (reset to 100ms each time some
134d4afb5ceSopenharmony_ci	 * new netlink data comes) that sets nl_initial_done and tries to move
135d4afb5ceSopenharmony_ci	 * us to OPERATIONAL
136d4afb5ceSopenharmony_ci	 */
137d4afb5ceSopenharmony_ci
138d4afb5ceSopenharmony_ci	if (target == LWS_SYSTATE_IFACE_COLDPLUG &&
139d4afb5ceSopenharmony_ci	    context->netlink &&
140d4afb5ceSopenharmony_ci	    !context->nl_initial_done) {
141d4afb5ceSopenharmony_ci		lwsl_cx_info(context, "waiting for netlink coldplug");
142d4afb5ceSopenharmony_ci
143d4afb5ceSopenharmony_ci		return 1;
144d4afb5ceSopenharmony_ci	}
145d4afb5ceSopenharmony_ci#endif
146d4afb5ceSopenharmony_ci
147d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS) && \
148d4afb5ceSopenharmony_ci    defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM)
149d4afb5ceSopenharmony_ci	/*
150d4afb5ceSopenharmony_ci	 * Skip this if we are running something without the policy for it
151d4afb5ceSopenharmony_ci	 *
152d4afb5ceSopenharmony_ci	 * If root token is empty, skip too.
153d4afb5ceSopenharmony_ci	 */
154d4afb5ceSopenharmony_ci
155d4afb5ceSopenharmony_ci	ab0 = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 0);
156d4afb5ceSopenharmony_ci	ab1 = lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 1);
157d4afb5ceSopenharmony_ci
158d4afb5ceSopenharmony_ci	if (target == LWS_SYSTATE_AUTH1 &&
159d4afb5ceSopenharmony_ci	    context->pss_policies && ab0 && ab1 &&
160d4afb5ceSopenharmony_ci	    !lws_system_blob_get_size(ab0) &&
161d4afb5ceSopenharmony_ci	    lws_system_blob_get_size(ab1)) {
162d4afb5ceSopenharmony_ci		lwsl_cx_info(context,
163d4afb5ceSopenharmony_ci			     "AUTH1 state triggering api.amazon.com auth");
164d4afb5ceSopenharmony_ci		/*
165d4afb5ceSopenharmony_ci		 * Start trying to acquire it if it's not already in progress
166d4afb5ceSopenharmony_ci		 * returns nonzero if we determine it's not needed
167d4afb5ceSopenharmony_ci		 */
168d4afb5ceSopenharmony_ci		if (!lws_ss_sys_auth_api_amazon_com(context))
169d4afb5ceSopenharmony_ci			return 1;
170d4afb5ceSopenharmony_ci	}
171d4afb5ceSopenharmony_ci#endif
172d4afb5ceSopenharmony_ci
173d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
174d4afb5ceSopenharmony_ci#if defined(LWS_WITH_DRIVERS)
175d4afb5ceSopenharmony_ci	/*
176d4afb5ceSopenharmony_ci	 * See if we should do the SS Captive Portal Detection
177d4afb5ceSopenharmony_ci	 */
178d4afb5ceSopenharmony_ci	if (target == LWS_SYSTATE_CPD_PRE_TIME) {
179d4afb5ceSopenharmony_ci		if (lws_system_cpd_state_get(context) == LWS_CPD_INTERNET_OK)
180d4afb5ceSopenharmony_ci			return 0; /* allow it */
181d4afb5ceSopenharmony_ci
182d4afb5ceSopenharmony_ci		/*
183d4afb5ceSopenharmony_ci		 * Don't allow it to move past here until we get an IP and
184d4afb5ceSopenharmony_ci		 * CPD passes, driven by SMD
185d4afb5ceSopenharmony_ci		 */
186d4afb5ceSopenharmony_ci
187d4afb5ceSopenharmony_ci		return 1;
188d4afb5ceSopenharmony_ci	}
189d4afb5ceSopenharmony_ci#endif
190d4afb5ceSopenharmony_ci
191d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
192d4afb5ceSopenharmony_ci	/*
193d4afb5ceSopenharmony_ci	 * Skip this if we are running something without the policy for it
194d4afb5ceSopenharmony_ci	 */
195d4afb5ceSopenharmony_ci	if (target == LWS_SYSTATE_POLICY_VALID &&
196d4afb5ceSopenharmony_ci	    context->pss_policies && !context->policy_updated) {
197d4afb5ceSopenharmony_ci
198d4afb5ceSopenharmony_ci		if (context->hss_fetch_policy)
199d4afb5ceSopenharmony_ci			return 1;
200d4afb5ceSopenharmony_ci
201d4afb5ceSopenharmony_ci		lwsl_cx_debug(context, "starting policy fetch");
202d4afb5ceSopenharmony_ci		/*
203d4afb5ceSopenharmony_ci		 * Start trying to acquire it if it's not already in progress
204d4afb5ceSopenharmony_ci		 * returns nonzero if we determine it's not needed
205d4afb5ceSopenharmony_ci		 */
206d4afb5ceSopenharmony_ci		if (!lws_ss_sys_fetch_policy(context))
207d4afb5ceSopenharmony_ci			/* we have it */
208d4afb5ceSopenharmony_ci			return 0;
209d4afb5ceSopenharmony_ci
210d4afb5ceSopenharmony_ci		/* deny while we fetch it */
211d4afb5ceSopenharmony_ci
212d4afb5ceSopenharmony_ci		return 1;
213d4afb5ceSopenharmony_ci	}
214d4afb5ceSopenharmony_ci#endif
215d4afb5ceSopenharmony_ci#endif
216d4afb5ceSopenharmony_ci
217d4afb5ceSopenharmony_ci	/* protocol part */
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_ci	if (context->protocol_init_done)
220d4afb5ceSopenharmony_ci		return 0;
221d4afb5ceSopenharmony_ci
222d4afb5ceSopenharmony_ci	if (target != LWS_SYSTATE_POLICY_VALID)
223d4afb5ceSopenharmony_ci		return 0;
224d4afb5ceSopenharmony_ci
225d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "doing protocol init on POLICY_VALID\n");
226d4afb5ceSopenharmony_ci
227d4afb5ceSopenharmony_ci	return lws_protocol_init(context);
228d4afb5ceSopenharmony_ci}
229d4afb5ceSopenharmony_ci
230d4afb5ceSopenharmony_cistatic void
231d4afb5ceSopenharmony_cilws_context_creation_completion_cb(lws_sorted_usec_list_t *sul)
232d4afb5ceSopenharmony_ci{
233d4afb5ceSopenharmony_ci	struct lws_context *context = lws_container_of(sul, struct lws_context,
234d4afb5ceSopenharmony_ci						       sul_system_state);
235d4afb5ceSopenharmony_ci
236d4afb5ceSopenharmony_ci	/* if nothing is there to intercept anything, go all the way */
237d4afb5ceSopenharmony_ci	lws_state_transition_steps(&context->mgr_system,
238d4afb5ceSopenharmony_ci				   LWS_SYSTATE_OPERATIONAL);
239d4afb5ceSopenharmony_ci}
240d4afb5ceSopenharmony_ci#endif /* WITH_SYS_STATE */
241d4afb5ceSopenharmony_ci
242d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
243d4afb5ceSopenharmony_cistatic int
244d4afb5ceSopenharmony_cilws_system_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,
245d4afb5ceSopenharmony_ci		  void *buf, size_t len)
246d4afb5ceSopenharmony_ci{
247d4afb5ceSopenharmony_ci	struct lws_context *cx = (struct lws_context *)opaque;
248d4afb5ceSopenharmony_ci
249d4afb5ceSopenharmony_ci	if (_class != LWSSMDCL_NETWORK)
250d4afb5ceSopenharmony_ci		return 0;
251d4afb5ceSopenharmony_ci
252d4afb5ceSopenharmony_ci	/* something external requested CPD check */
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_ci	if (!lws_json_simple_strcmp(buf, len, "\"trigger\":", "cpdcheck"))
255d4afb5ceSopenharmony_ci		lws_system_cpd_start(cx);
256d4afb5ceSopenharmony_ci	else
257d4afb5ceSopenharmony_ci		/*
258d4afb5ceSopenharmony_ci		 * IP acquisition on any interface triggers captive portal
259d4afb5ceSopenharmony_ci		 * check on default route
260d4afb5ceSopenharmony_ci		 */
261d4afb5ceSopenharmony_ci		if (!lws_json_simple_strcmp(buf, len, "\"type\":", "ipacq"))
262d4afb5ceSopenharmony_ci			lws_system_cpd_start(cx);
263d4afb5ceSopenharmony_ci
264d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_NTPCLIENT)
265d4afb5ceSopenharmony_ci	/*
266d4afb5ceSopenharmony_ci	 * Captive portal detect showing internet workable triggers NTP Client
267d4afb5ceSopenharmony_ci	 */
268d4afb5ceSopenharmony_ci	if (!lws_json_simple_strcmp(buf, len, "\"type\":", "cps") &&
269d4afb5ceSopenharmony_ci	    !lws_json_simple_strcmp(buf, len, "\"result\":", "OK") &&
270d4afb5ceSopenharmony_ci	    lws_now_secs() < 1594017754) /* 06:42 Mon Jul 6 2020 UTC */
271d4afb5ceSopenharmony_ci		lws_ntpc_trigger(cx);
272d4afb5ceSopenharmony_ci#endif
273d4afb5ceSopenharmony_ci
274d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT) && 0
275d4afb5ceSopenharmony_ci	/*
276d4afb5ceSopenharmony_ci	 * Any network interface linkup triggers DHCP
277d4afb5ceSopenharmony_ci	 */
278d4afb5ceSopenharmony_ci	if (!lws_json_simple_strcmp(buf, len, "\"type\":", "linkup"))
279d4afb5ceSopenharmony_ci		lws_ntpc_trigger(cx);
280d4afb5ceSopenharmony_ci
281d4afb5ceSopenharmony_ci#endif
282d4afb5ceSopenharmony_ci
283d4afb5ceSopenharmony_ci#if defined(LWS_WITH_DRIVERS) && defined(LWS_WITH_NETWORK)
284d4afb5ceSopenharmony_ci	lws_netdev_smd_cb(opaque, _class, timestamp, buf, len);
285d4afb5ceSopenharmony_ci#endif
286d4afb5ceSopenharmony_ci
287d4afb5ceSopenharmony_ci	return 0;
288d4afb5ceSopenharmony_ci}
289d4afb5ceSopenharmony_ci#endif
290d4afb5ceSopenharmony_ci
291d4afb5ceSopenharmony_ci
292d4afb5ceSopenharmony_ci
293d4afb5ceSopenharmony_ci#endif /* NETWORK */
294d4afb5ceSopenharmony_ci
295d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_NO_LOGS)
296d4afb5ceSopenharmony_ci
297d4afb5ceSopenharmony_cistatic const char * const opts_str =
298d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
299d4afb5ceSopenharmony_ci			"NET "
300d4afb5ceSopenharmony_ci#else
301d4afb5ceSopenharmony_ci			"NoNET "
302d4afb5ceSopenharmony_ci#endif
303d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
304d4afb5ceSopenharmony_ci			"CLI "
305d4afb5ceSopenharmony_ci#endif
306d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
307d4afb5ceSopenharmony_ci			"SRV "
308d4afb5ceSopenharmony_ci#endif
309d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1)
310d4afb5ceSopenharmony_ci			"H1 "
311d4afb5ceSopenharmony_ci#endif
312d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2)
313d4afb5ceSopenharmony_ci			"H2 "
314d4afb5ceSopenharmony_ci#endif
315d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS)
316d4afb5ceSopenharmony_ci			"WS "
317d4afb5ceSopenharmony_ci#endif
318d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_MQTT)
319d4afb5ceSopenharmony_ci			"MQTT "
320d4afb5ceSopenharmony_ci#endif
321d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS) && !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
322d4afb5ceSopenharmony_ci			"SS-JSON-POL "
323d4afb5ceSopenharmony_ci#endif
324d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS) && defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
325d4afb5ceSopenharmony_ci			"SS-STATIC-POL "
326d4afb5ceSopenharmony_ci#endif
327d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
328d4afb5ceSopenharmony_ci			"SSPROX "
329d4afb5ceSopenharmony_ci#endif
330d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON)
331d4afb5ceSopenharmony_ci			"ConMon "
332d4afb5ceSopenharmony_ci#endif
333d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION)
334d4afb5ceSopenharmony_ci			"FLTINJ "
335d4afb5ceSopenharmony_ci#endif
336d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
337d4afb5ceSopenharmony_ci			"ASYNC_DNS "
338d4afb5ceSopenharmony_ci#endif
339d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_NTPCLIENT)
340d4afb5ceSopenharmony_ci			"NTPCLIENT "
341d4afb5ceSopenharmony_ci#endif
342d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT)
343d4afb5ceSopenharmony_ci			"DHCP_CLIENT "
344d4afb5ceSopenharmony_ci#endif
345d4afb5ceSopenharmony_ci;
346d4afb5ceSopenharmony_ci
347d4afb5ceSopenharmony_ci#endif
348d4afb5ceSopenharmony_ci
349d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
350d4afb5ceSopenharmony_cistatic const struct lws_evlib_map {
351d4afb5ceSopenharmony_ci	uint64_t	flag;
352d4afb5ceSopenharmony_ci	const char	*name;
353d4afb5ceSopenharmony_ci} map[] = {
354d4afb5ceSopenharmony_ci	{ LWS_SERVER_OPTION_LIBUV,    "evlib_uv" },
355d4afb5ceSopenharmony_ci	{ LWS_SERVER_OPTION_LIBEVENT, "evlib_event" },
356d4afb5ceSopenharmony_ci	{ LWS_SERVER_OPTION_GLIB,     "evlib_glib" },
357d4afb5ceSopenharmony_ci	{ LWS_SERVER_OPTION_LIBEV,    "evlib_ev" },
358d4afb5ceSopenharmony_ci	{ LWS_SERVER_OPTION_SDEVENT,  "evlib_sd" },
359d4afb5ceSopenharmony_ci	{ LWS_SERVER_OPTION_ULOOP,    "evlib_uloop" },
360d4afb5ceSopenharmony_ci};
361d4afb5ceSopenharmony_cistatic const char * const dlist[] = {
362d4afb5ceSopenharmony_ci	".",				/* Priority 1: plugins in cwd */
363d4afb5ceSopenharmony_ci	LWS_INSTALL_LIBDIR,		/* Priority 2: plugins in install dir */
364d4afb5ceSopenharmony_ci	NULL
365d4afb5ceSopenharmony_ci};
366d4afb5ceSopenharmony_ci#endif
367d4afb5ceSopenharmony_ci
368d4afb5ceSopenharmony_cistruct lws_context *
369d4afb5ceSopenharmony_cilws_create_context(const struct lws_context_creation_info *info)
370d4afb5ceSopenharmony_ci{
371d4afb5ceSopenharmony_ci	struct lws_context *context = NULL;
372d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_NO_LOGS)
373d4afb5ceSopenharmony_ci	const char *s = "IPv6-absent";
374d4afb5ceSopenharmony_ci#endif
375d4afb5ceSopenharmony_ci#if defined(LWS_WITH_FILE_OPS)
376d4afb5ceSopenharmony_ci	struct lws_plat_file_ops *prev;
377d4afb5ceSopenharmony_ci#endif
378d4afb5ceSopenharmony_ci#ifndef LWS_NO_DAEMONIZE
379d4afb5ceSopenharmony_ci	pid_t pid_daemon = get_daemonize_pid();
380d4afb5ceSopenharmony_ci#endif
381d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
382d4afb5ceSopenharmony_ci	const lws_plugin_evlib_t *plev = NULL;
383d4afb5ceSopenharmony_ci	unsigned short count_threads = 1;
384d4afb5ceSopenharmony_ci	uint8_t *u;
385d4afb5ceSopenharmony_ci	uint16_t us_wait_resolution = 0;
386d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
387d4afb5ceSopenharmony_ci	struct lws_cache_creation_info ci;
388d4afb5ceSopenharmony_ci#endif
389d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS)
390d4afb5ceSopenharmony_ci	char mbedtls_version[32];
391d4afb5ceSopenharmony_ci#endif
392d4afb5ceSopenharmony_ci
393d4afb5ceSopenharmony_ci#if defined(__ANDROID__)
394d4afb5ceSopenharmony_ci	struct rlimit rt;
395d4afb5ceSopenharmony_ci#endif
396d4afb5ceSopenharmony_ci	size_t
397d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS)
398d4afb5ceSopenharmony_ci		/* smaller default, can set in info->pt_serv_buf_size */
399d4afb5ceSopenharmony_ci		s1 = 2048,
400d4afb5ceSopenharmony_ci#else
401d4afb5ceSopenharmony_ci		s1 = 4096,
402d4afb5ceSopenharmony_ci#endif
403d4afb5ceSopenharmony_ci		size = sizeof(struct lws_context);
404d4afb5ceSopenharmony_ci#endif
405d4afb5ceSopenharmony_ci
406d4afb5ceSopenharmony_ci	int n;
407d4afb5ceSopenharmony_ci	unsigned int lpf = info->fd_limit_per_thread;
408d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
409d4afb5ceSopenharmony_ci	struct lws_plugin		*evlib_plugin_list = NULL;
410d4afb5ceSopenharmony_ci#if defined(_DEBUG) && !defined(LWS_WITH_NO_LOGS)
411d4afb5ceSopenharmony_ci	char		*ld_env;
412d4afb5ceSopenharmony_ci#endif
413d4afb5ceSopenharmony_ci#endif
414d4afb5ceSopenharmony_ci#if defined(LWS_WITH_LIBUV)
415d4afb5ceSopenharmony_ci	char fatal_exit_defer = 0;
416d4afb5ceSopenharmony_ci#endif
417d4afb5ceSopenharmony_ci
418d4afb5ceSopenharmony_ci
419d4afb5ceSopenharmony_ci	if (lws_fi(&info->fic, "ctx_createfail1"))
420d4afb5ceSopenharmony_ci		goto early_bail;
421d4afb5ceSopenharmony_ci
422d4afb5ceSopenharmony_ci	if (lpf) {
423d4afb5ceSopenharmony_ci		lpf+= 2;
424d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
425d4afb5ceSopenharmony_ci		lpf++;
426d4afb5ceSopenharmony_ci#endif
427d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_NTPCLIENT)
428d4afb5ceSopenharmony_ci		lpf++;
429d4afb5ceSopenharmony_ci#endif
430d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT)
431d4afb5ceSopenharmony_ci		lpf++;
432d4afb5ceSopenharmony_ci#endif
433d4afb5ceSopenharmony_ci	}
434d4afb5ceSopenharmony_ci
435d4afb5ceSopenharmony_ci#if defined(LWS_WITH_IPV6) && !defined(LWS_WITH_NO_LOGS)
436d4afb5ceSopenharmony_ci	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6))
437d4afb5ceSopenharmony_ci		s = "IPV6-on";
438d4afb5ceSopenharmony_ci	else
439d4afb5ceSopenharmony_ci		s = "IPV6-off";
440d4afb5ceSopenharmony_ci#endif
441d4afb5ceSopenharmony_ci
442d4afb5ceSopenharmony_ci	if (lws_plat_context_early_init())
443d4afb5ceSopenharmony_ci		goto early_bail;
444d4afb5ceSopenharmony_ci
445d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
446d4afb5ceSopenharmony_ci	if (info->count_threads)
447d4afb5ceSopenharmony_ci		count_threads = (unsigned short)info->count_threads;
448d4afb5ceSopenharmony_ci
449d4afb5ceSopenharmony_ci	if (count_threads > LWS_MAX_SMP)
450d4afb5ceSopenharmony_ci		count_threads = LWS_MAX_SMP;
451d4afb5ceSopenharmony_ci
452d4afb5ceSopenharmony_ci	if (info->pt_serv_buf_size)
453d4afb5ceSopenharmony_ci		s1 = info->pt_serv_buf_size;
454d4afb5ceSopenharmony_ci
455d4afb5ceSopenharmony_ci	/* pt fakewsi and the pt serv buf allocations ride after the context */
456d4afb5ceSopenharmony_ci	size += count_threads * s1;
457d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS)
458d4afb5ceSopenharmony_ci	size += (count_threads * sizeof(struct lws));
459d4afb5ceSopenharmony_ci#endif
460d4afb5ceSopenharmony_ci
461d4afb5ceSopenharmony_ci	if (info->event_lib_custom) {
462d4afb5ceSopenharmony_ci		plev = info->event_lib_custom;
463d4afb5ceSopenharmony_ci		us_wait_resolution = 0;
464d4afb5ceSopenharmony_ci	}
465d4afb5ceSopenharmony_ci#if defined(LWS_WITH_POLL)
466d4afb5ceSopenharmony_ci	else {
467d4afb5ceSopenharmony_ci		extern const lws_plugin_evlib_t evlib_poll;
468d4afb5ceSopenharmony_ci		plev = &evlib_poll;
469d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS)
470d4afb5ceSopenharmony_ci		/*
471d4afb5ceSopenharmony_ci		 * ... freertos has us-resolution select()...
472d4afb5ceSopenharmony_ci		 * others are to ms-resolution poll()
473d4afb5ceSopenharmony_ci		 */
474d4afb5ceSopenharmony_ci		us_wait_resolution = 1000;
475d4afb5ceSopenharmony_ci#endif
476d4afb5ceSopenharmony_ci	}
477d4afb5ceSopenharmony_ci#endif
478d4afb5ceSopenharmony_ci
479d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
480d4afb5ceSopenharmony_ci
481d4afb5ceSopenharmony_ci	/*
482d4afb5ceSopenharmony_ci	 * New style dynamically loaded event lib support
483d4afb5ceSopenharmony_ci	 *
484d4afb5ceSopenharmony_ci	 * We have to pick and load the event lib plugin before we allocate
485d4afb5ceSopenharmony_ci	 * the context object, so we can overallocate it correctly
486d4afb5ceSopenharmony_ci	 */
487d4afb5ceSopenharmony_ci
488d4afb5ceSopenharmony_ci#if defined(_DEBUG) && !defined(LWS_WITH_NO_LOGS)
489d4afb5ceSopenharmony_ci	ld_env = getenv("LD_LIBRARY_PATH");
490d4afb5ceSopenharmony_ci	lwsl_info("%s: ev lib path %s, '%s'\n", __func__,
491d4afb5ceSopenharmony_ci			LWS_INSTALL_LIBDIR, ld_env);
492d4afb5ceSopenharmony_ci#endif
493d4afb5ceSopenharmony_ci
494d4afb5ceSopenharmony_ci	for (n = 0; n < (int)LWS_ARRAY_SIZE(map); n++) {
495d4afb5ceSopenharmony_ci		char ok = 0;
496d4afb5ceSopenharmony_ci
497d4afb5ceSopenharmony_ci		if (!lws_check_opt(info->options, map[n].flag))
498d4afb5ceSopenharmony_ci			continue;
499d4afb5ceSopenharmony_ci
500d4afb5ceSopenharmony_ci		if (!lws_plugins_init(&evlib_plugin_list,
501d4afb5ceSopenharmony_ci				     dlist, "lws_evlib_plugin",
502d4afb5ceSopenharmony_ci				     map[n].name, NULL, NULL))
503d4afb5ceSopenharmony_ci			ok = 1;
504d4afb5ceSopenharmony_ci
505d4afb5ceSopenharmony_ci		if (!ok || lws_fi(&info->fic, "ctx_createfail_plugin_init")) {
506d4afb5ceSopenharmony_ci			lwsl_err("%s: failed to load %s\n", __func__,
507d4afb5ceSopenharmony_ci					map[n].name);
508d4afb5ceSopenharmony_ci			goto bail;
509d4afb5ceSopenharmony_ci		}
510d4afb5ceSopenharmony_ci
511d4afb5ceSopenharmony_ci#if defined(LWS_WITH_LIBUV)
512d4afb5ceSopenharmony_ci		if (!n) /* libuv */
513d4afb5ceSopenharmony_ci			fatal_exit_defer = !!info->foreign_loops;
514d4afb5ceSopenharmony_ci#endif
515d4afb5ceSopenharmony_ci
516d4afb5ceSopenharmony_ci		if (!evlib_plugin_list ||
517d4afb5ceSopenharmony_ci		    lws_fi(&info->fic, "ctx_createfail_evlib_plugin")) {
518d4afb5ceSopenharmony_ci			lwsl_err("%s: unable to load evlib plugin %s\n",
519d4afb5ceSopenharmony_ci					__func__, map[n].name);
520d4afb5ceSopenharmony_ci
521d4afb5ceSopenharmony_ci			goto bail;
522d4afb5ceSopenharmony_ci		}
523d4afb5ceSopenharmony_ci		plev = (const lws_plugin_evlib_t *)evlib_plugin_list->hdr;
524d4afb5ceSopenharmony_ci		break;
525d4afb5ceSopenharmony_ci	}
526d4afb5ceSopenharmony_ci#else
527d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVENT_LIBS)
528d4afb5ceSopenharmony_ci	/*
529d4afb5ceSopenharmony_ci	 * set the context event loops ops struct
530d4afb5ceSopenharmony_ci	 *
531d4afb5ceSopenharmony_ci	 * after this, all event_loop actions use the generic ops
532d4afb5ceSopenharmony_ci	 */
533d4afb5ceSopenharmony_ci
534d4afb5ceSopenharmony_ci	/*
535d4afb5ceSopenharmony_ci	 * oldstyle built-in event lib support
536d4afb5ceSopenharmony_ci	 *
537d4afb5ceSopenharmony_ci	 * We have composed them into the libwebsockets lib itself, we can
538d4afb5ceSopenharmony_ci	 * just pick the ops we want and done
539d4afb5ceSopenharmony_ci	 */
540d4afb5ceSopenharmony_ci
541d4afb5ceSopenharmony_ci#if defined(LWS_WITH_LIBUV)
542d4afb5ceSopenharmony_ci	if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) {
543d4afb5ceSopenharmony_ci		extern const lws_plugin_evlib_t evlib_uv;
544d4afb5ceSopenharmony_ci		plev = &evlib_uv;
545d4afb5ceSopenharmony_ci		fatal_exit_defer = !!info->foreign_loops;
546d4afb5ceSopenharmony_ci		us_wait_resolution = 0;
547d4afb5ceSopenharmony_ci	}
548d4afb5ceSopenharmony_ci#endif
549d4afb5ceSopenharmony_ci
550d4afb5ceSopenharmony_ci#if defined(LWS_WITH_LIBEVENT)
551d4afb5ceSopenharmony_ci	if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT)) {
552d4afb5ceSopenharmony_ci		extern const lws_plugin_evlib_t evlib_event;
553d4afb5ceSopenharmony_ci		plev = &evlib_event;
554d4afb5ceSopenharmony_ci		us_wait_resolution = 0;
555d4afb5ceSopenharmony_ci	}
556d4afb5ceSopenharmony_ci#endif
557d4afb5ceSopenharmony_ci
558d4afb5ceSopenharmony_ci#if defined(LWS_WITH_GLIB)
559d4afb5ceSopenharmony_ci	if (lws_check_opt(info->options, LWS_SERVER_OPTION_GLIB)) {
560d4afb5ceSopenharmony_ci		extern const lws_plugin_evlib_t evlib_glib;
561d4afb5ceSopenharmony_ci		plev = &evlib_glib;
562d4afb5ceSopenharmony_ci		us_wait_resolution = 0;
563d4afb5ceSopenharmony_ci	}
564d4afb5ceSopenharmony_ci#endif
565d4afb5ceSopenharmony_ci
566d4afb5ceSopenharmony_ci#if defined(LWS_WITH_LIBEV)
567d4afb5ceSopenharmony_ci	if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV)) {
568d4afb5ceSopenharmony_ci		extern const lws_plugin_evlib_t evlib_ev;
569d4afb5ceSopenharmony_ci		plev = &evlib_ev;
570d4afb5ceSopenharmony_ci		us_wait_resolution = 0;
571d4afb5ceSopenharmony_ci	}
572d4afb5ceSopenharmony_ci#endif
573d4afb5ceSopenharmony_ci
574d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SDEVENT)
575d4afb5ceSopenharmony_ci    if (lws_check_opt(info->options, LWS_SERVER_OPTION_SDEVENT)) {
576d4afb5ceSopenharmony_ci        extern const lws_plugin_evlib_t evlib_sd;
577d4afb5ceSopenharmony_ci        plev = &evlib_sd;
578d4afb5ceSopenharmony_ci        us_wait_resolution = 0;
579d4afb5ceSopenharmony_ci    }
580d4afb5ceSopenharmony_ci#endif
581d4afb5ceSopenharmony_ci
582d4afb5ceSopenharmony_ci#if defined(LWS_WITH_ULOOP)
583d4afb5ceSopenharmony_ci    if (lws_check_opt(info->options, LWS_SERVER_OPTION_ULOOP)) {
584d4afb5ceSopenharmony_ci        extern const lws_plugin_evlib_t evlib_uloop;
585d4afb5ceSopenharmony_ci        plev = &evlib_uloop;
586d4afb5ceSopenharmony_ci        us_wait_resolution = 0;
587d4afb5ceSopenharmony_ci    }
588d4afb5ceSopenharmony_ci#endif
589d4afb5ceSopenharmony_ci
590d4afb5ceSopenharmony_ci#endif /* with event libs */
591d4afb5ceSopenharmony_ci
592d4afb5ceSopenharmony_ci#endif /* not with ev plugins */
593d4afb5ceSopenharmony_ci
594d4afb5ceSopenharmony_ci	if (!plev || lws_fi(&info->fic, "ctx_createfail_evlib_sel"))
595d4afb5ceSopenharmony_ci		goto fail_event_libs;
596d4afb5ceSopenharmony_ci
597d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
598d4afb5ceSopenharmony_ci	size += (size_t)plev->ops->evlib_size_ctx /* the ctx evlib priv */ +
599d4afb5ceSopenharmony_ci		(count_threads * (size_t)plev->ops->evlib_size_pt) /* the pt evlib priv */;
600d4afb5ceSopenharmony_ci#endif
601d4afb5ceSopenharmony_ci
602d4afb5ceSopenharmony_ci	context = lws_zalloc(size, "context");
603d4afb5ceSopenharmony_ci	if (!context || lws_fi(&info->fic, "ctx_createfail_oom_ctx")) {
604d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION)
605d4afb5ceSopenharmony_ci		lws_free(context);
606d4afb5ceSopenharmony_ci#endif
607d4afb5ceSopenharmony_ci		lwsl_err("OOM");
608d4afb5ceSopenharmony_ci		goto early_bail;
609d4afb5ceSopenharmony_ci	}
610d4afb5ceSopenharmony_ci
611d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
612d4afb5ceSopenharmony_ci   // NOTE: we need to init this fields because they may be used in logger when context destroying
613d4afb5ceSopenharmony_ci	context->mgr_system.state_names = system_state_names;
614d4afb5ceSopenharmony_ci	context->mgr_system.context = context;
615d4afb5ceSopenharmony_ci#endif
616d4afb5ceSopenharmony_ci
617d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
618d4afb5ceSopenharmony_ci	context->event_loop_ops = plev->ops;
619d4afb5ceSopenharmony_ci	context->us_wait_resolution = us_wait_resolution;
620d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS_JIT_TRUST)
621d4afb5ceSopenharmony_ci	{
622d4afb5ceSopenharmony_ci		struct lws_cache_creation_info ci;
623d4afb5ceSopenharmony_ci
624d4afb5ceSopenharmony_ci		memset(&ci, 0, sizeof(ci));
625d4afb5ceSopenharmony_ci		ci.cx = context;
626d4afb5ceSopenharmony_ci		ci.ops = &lws_cache_ops_heap;
627d4afb5ceSopenharmony_ci		ci.name = "jitt";
628d4afb5ceSopenharmony_ci		ci.max_footprint = info->jitt_cache_max_footprint;
629d4afb5ceSopenharmony_ci		context->trust_cache = lws_cache_create(&ci);
630d4afb5ceSopenharmony_ci	}
631d4afb5ceSopenharmony_ci#endif
632d4afb5ceSopenharmony_ci#endif
633d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVENT_LIBS)
634d4afb5ceSopenharmony_ci	/* at the very end */
635d4afb5ceSopenharmony_ci	context->evlib_ctx = (uint8_t *)context + size -
636d4afb5ceSopenharmony_ci					plev->ops->evlib_size_ctx;
637d4afb5ceSopenharmony_ci#endif
638d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
639d4afb5ceSopenharmony_ci	context->evlib_plugin_list = evlib_plugin_list;
640d4afb5ceSopenharmony_ci#endif
641d4afb5ceSopenharmony_ci
642d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS)
643d4afb5ceSopenharmony_ci	context->uid = info->uid;
644d4afb5ceSopenharmony_ci	context->gid = info->gid;
645d4afb5ceSopenharmony_ci	context->username = info->username;
646d4afb5ceSopenharmony_ci	context->groupname = info->groupname;
647d4afb5ceSopenharmony_ci#endif
648d4afb5ceSopenharmony_ci	context->name			= info->vhost_name;
649d4afb5ceSopenharmony_ci	if (info->log_cx)
650d4afb5ceSopenharmony_ci		context->log_cx = info->log_cx;
651d4afb5ceSopenharmony_ci	else
652d4afb5ceSopenharmony_ci		context->log_cx = &log_cx;
653d4afb5ceSopenharmony_ci	lwsl_refcount_cx(context->log_cx, 1);
654d4afb5ceSopenharmony_ci
655d4afb5ceSopenharmony_ci	context->system_ops = info->system_ops;
656d4afb5ceSopenharmony_ci	context->pt_serv_buf_size = (unsigned int)s1;
657d4afb5ceSopenharmony_ci	context->protocols_copy = info->protocols;
658d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS_JIT_TRUST)
659d4afb5ceSopenharmony_ci	context->vh_idle_grace_ms = info->vh_idle_grace_ms ?
660d4afb5ceSopenharmony_ci			info->vh_idle_grace_ms : 5000;
661d4afb5ceSopenharmony_ci#endif
662d4afb5ceSopenharmony_ci
663d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION)
664d4afb5ceSopenharmony_ci	context->fic.name = "ctx";
665d4afb5ceSopenharmony_ci	if (info->fic.fi_owner.count)
666d4afb5ceSopenharmony_ci		/*
667d4afb5ceSopenharmony_ci		 * This moves all the lws_fi_t from info->fi to the context fi,
668d4afb5ceSopenharmony_ci		 * leaving it empty, so no injection added to default vhost
669d4afb5ceSopenharmony_ci		 */
670d4afb5ceSopenharmony_ci		lws_fi_import(&context->fic, &info->fic);
671d4afb5ceSopenharmony_ci#endif
672d4afb5ceSopenharmony_ci
673d4afb5ceSopenharmony_ci
674d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
675d4afb5ceSopenharmony_ci	context->smd_ttl_us = info->smd_ttl_us ? info->smd_ttl_us :
676d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS)
677d4afb5ceSopenharmony_ci			5000000;
678d4afb5ceSopenharmony_ci#else
679d4afb5ceSopenharmony_ci			2000000;
680d4afb5ceSopenharmony_ci#endif
681d4afb5ceSopenharmony_ci	context->smd_queue_depth = (uint16_t)(info->smd_queue_depth ?
682d4afb5ceSopenharmony_ci						info->smd_queue_depth :
683d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS)
684d4afb5ceSopenharmony_ci						20);
685d4afb5ceSopenharmony_ci#else
686d4afb5ceSopenharmony_ci						40);
687d4afb5ceSopenharmony_ci#endif
688d4afb5ceSopenharmony_ci#endif
689d4afb5ceSopenharmony_ci
690d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
691d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI].tag_prefix = "wsi";
692d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_VHOST].tag_prefix = "vh";
693d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_SERVER].tag_prefix = "wsisrv"; /* adopted */
694d4afb5ceSopenharmony_ci
695d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
696d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_MUX].tag_prefix = "mux"; /* a mux child wsi */
697d4afb5ceSopenharmony_ci#endif
698d4afb5ceSopenharmony_ci
699d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
700d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_CLIENT].tag_prefix = "wsicli";
701d4afb5ceSopenharmony_ci#endif
702d4afb5ceSopenharmony_ci
703d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
704d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
705d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_SS_CLIENT].tag_prefix = "SScli";
706d4afb5ceSopenharmony_ci#endif
707d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
708d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_SS_SERVER].tag_prefix = "SSsrv";
709d4afb5ceSopenharmony_ci#endif
710d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
711d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_SS_CLIENT].tag_prefix = "wsiSScli";
712d4afb5ceSopenharmony_ci#endif
713d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
714d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_SS_SERVER].tag_prefix = "wsiSSsrv";
715d4afb5ceSopenharmony_ci#endif
716d4afb5ceSopenharmony_ci#endif
717d4afb5ceSopenharmony_ci#endif
718d4afb5ceSopenharmony_ci
719d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
720d4afb5ceSopenharmony_ci	/*
721d4afb5ceSopenharmony_ci	 * If we're not using secure streams, we can still pass in a linked-
722d4afb5ceSopenharmony_ci	 * list of metrics policies
723d4afb5ceSopenharmony_ci	 */
724d4afb5ceSopenharmony_ci	context->metrics_policies = info->metrics_policies;
725d4afb5ceSopenharmony_ci	context->metrics_prefix = info->metrics_prefix;
726d4afb5ceSopenharmony_ci
727d4afb5ceSopenharmony_ci	context->mt_service = lws_metric_create(context,
728d4afb5ceSopenharmony_ci					LWSMTFL_REPORT_DUTY_WALLCLOCK_US |
729d4afb5ceSopenharmony_ci					LWSMTFL_REPORT_ONLY_GO, "cpu.svc");
730d4afb5ceSopenharmony_ci
731d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
732d4afb5ceSopenharmony_ci
733d4afb5ceSopenharmony_ci	context->mt_conn_dns = lws_metric_create(context,
734d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_MEAN |
735d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
736d4afb5ceSopenharmony_ci						 "n.cn.dns");
737d4afb5ceSopenharmony_ci	context->mt_conn_tcp = lws_metric_create(context,
738d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_MEAN |
739d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
740d4afb5ceSopenharmony_ci						 "n.cn.tcp");
741d4afb5ceSopenharmony_ci	context->mt_conn_tls = lws_metric_create(context,
742d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_MEAN |
743d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
744d4afb5ceSopenharmony_ci						 "n.cn.tls");
745d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
746d4afb5ceSopenharmony_ci	context->mt_http_txn = lws_metric_create(context,
747d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_MEAN |
748d4afb5ceSopenharmony_ci						 LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
749d4afb5ceSopenharmony_ci						 "n.http.txn");
750d4afb5ceSopenharmony_ci#endif
751d4afb5ceSopenharmony_ci
752d4afb5ceSopenharmony_ci	context->mth_conn_failures = lws_metric_create(context,
753d4afb5ceSopenharmony_ci					LWSMTFL_REPORT_HIST, "n.cn.failures");
754d4afb5ceSopenharmony_ci
755d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
756d4afb5ceSopenharmony_ci	context->mt_adns_cache = lws_metric_create(context,
757d4afb5ceSopenharmony_ci						   LWSMTFL_REPORT_MEAN |
758d4afb5ceSopenharmony_ci						   LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
759d4afb5ceSopenharmony_ci						   "n.cn.adns");
760d4afb5ceSopenharmony_ci#endif
761d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
762d4afb5ceSopenharmony_ci	context->mth_ss_conn = lws_metric_create(context, LWSMTFL_REPORT_HIST,
763d4afb5ceSopenharmony_ci						 "n.ss.conn");
764d4afb5ceSopenharmony_ci#endif
765d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
766d4afb5ceSopenharmony_ci	context->mt_ss_cliprox_conn = lws_metric_create(context,
767d4afb5ceSopenharmony_ci			LWSMTFL_REPORT_HIST,
768d4afb5ceSopenharmony_ci							"n.ss.cliprox.conn");
769d4afb5ceSopenharmony_ci	context->mt_ss_cliprox_paylat = lws_metric_create(context,
770d4afb5ceSopenharmony_ci							  LWSMTFL_REPORT_MEAN |
771d4afb5ceSopenharmony_ci							  LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
772d4afb5ceSopenharmony_ci							  "n.ss.cliprox.paylat");
773d4afb5ceSopenharmony_ci	context->mt_ss_proxcli_paylat = lws_metric_create(context,
774d4afb5ceSopenharmony_ci							  LWSMTFL_REPORT_MEAN |
775d4afb5ceSopenharmony_ci							  LWSMTFL_REPORT_DUTY_WALLCLOCK_US,
776d4afb5ceSopenharmony_ci							  "n.ss.proxcli.paylat");
777d4afb5ceSopenharmony_ci#endif
778d4afb5ceSopenharmony_ci
779d4afb5ceSopenharmony_ci#endif /* network + metrics + client */
780d4afb5ceSopenharmony_ci
781d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
782d4afb5ceSopenharmony_ci	context->mth_srv = lws_metric_create(context,
783d4afb5ceSopenharmony_ci					     LWSMTFL_REPORT_HIST, "n.srv");
784d4afb5ceSopenharmony_ci#endif /* network + metrics + server */
785d4afb5ceSopenharmony_ci
786d4afb5ceSopenharmony_ci#endif /* network + metrics */
787d4afb5ceSopenharmony_ci
788d4afb5ceSopenharmony_ci#endif /* network */
789d4afb5ceSopenharmony_ci
790d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS)
791d4afb5ceSopenharmony_ci	mbedtls_version_get_string(mbedtls_version);
792d4afb5ceSopenharmony_ci#endif
793d4afb5ceSopenharmony_ci
794d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS)
795d4afb5ceSopenharmony_ci	lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s);
796d4afb5ceSopenharmony_ci#else
797d4afb5ceSopenharmony_ci	lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s);
798d4afb5ceSopenharmony_ci#endif
799d4afb5ceSopenharmony_ci
800d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
801d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "Event loop: %s", plev->ops->name);
802d4afb5ceSopenharmony_ci#endif
803d4afb5ceSopenharmony_ci
804d4afb5ceSopenharmony_ci	/*
805d4afb5ceSopenharmony_ci	 * Proxy group
806d4afb5ceSopenharmony_ci	 */
807d4afb5ceSopenharmony_ci
808d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)
809d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
810d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_SSP_CLIENT].tag_prefix = "SSPcli";
811d4afb5ceSopenharmony_ci#endif
812d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
813d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_SSP_ONWARD].tag_prefix = "SSPonw";
814d4afb5ceSopenharmony_ci#endif
815d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
816d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_SSP_CLIENT].tag_prefix = "wsiSSPcli";
817d4afb5ceSopenharmony_ci#endif
818d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
819d4afb5ceSopenharmony_ci	context->lcg[LWSLCG_WSI_SSP_ONWARD].tag_prefix = "wsiSSPonw";
820d4afb5ceSopenharmony_ci#endif
821d4afb5ceSopenharmony_ci#endif
822d4afb5ceSopenharmony_ci
823d4afb5ceSopenharmony_ci
824d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
825d4afb5ceSopenharmony_ci	/* directly use the user-provided policy object list */
826d4afb5ceSopenharmony_ci	context->pss_policies = info->pss_policies;
827d4afb5ceSopenharmony_ci#endif
828d4afb5ceSopenharmony_ci
829d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) && defined(LWS_WITH_CLIENT)
830d4afb5ceSopenharmony_ci	context->ss_proxy_bind = info->ss_proxy_bind;
831d4afb5ceSopenharmony_ci	context->ss_proxy_port = info->ss_proxy_port;
832d4afb5ceSopenharmony_ci	context->ss_proxy_address = info->ss_proxy_address;
833d4afb5ceSopenharmony_ci	if (context->ss_proxy_bind && context->ss_proxy_address)
834d4afb5ceSopenharmony_ci		lwsl_cx_notice(context, "ss proxy bind '%s', port %d, ads '%s'",
835d4afb5ceSopenharmony_ci			context->ss_proxy_bind, context->ss_proxy_port,
836d4afb5ceSopenharmony_ci			context->ss_proxy_address);
837d4afb5ceSopenharmony_ci#endif
838d4afb5ceSopenharmony_ci
839d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
840d4afb5ceSopenharmony_ci	context->undestroyed_threads = count_threads;
841d4afb5ceSopenharmony_ci	context->count_threads = count_threads;
842d4afb5ceSopenharmony_ci
843d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) && defined(LWS_WITHOUT_EXTENSIONS)
844d4afb5ceSopenharmony_ci        if (info->extensions)
845d4afb5ceSopenharmony_ci                lwsl_cx_warn(context, "WITHOUT_EXTENSIONS but exts ptr set");
846d4afb5ceSopenharmony_ci#endif
847d4afb5ceSopenharmony_ci#endif /* network */
848d4afb5ceSopenharmony_ci
849d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
850d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
851d4afb5ceSopenharmony_ci	context->pss_policies_json = info->pss_policies_json;
852d4afb5ceSopenharmony_ci#endif
853d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SSPLUGINS)
854d4afb5ceSopenharmony_ci	context->pss_plugins = info->pss_plugins;
855d4afb5ceSopenharmony_ci#endif
856d4afb5ceSopenharmony_ci#endif
857d4afb5ceSopenharmony_ci
858d4afb5ceSopenharmony_ci	/* if he gave us names, set the uid / gid */
859d4afb5ceSopenharmony_ci	if (lws_plat_drop_app_privileges(context, 0) ||
860d4afb5ceSopenharmony_ci	    lws_fi(&context->fic, "ctx_createfail_privdrop"))
861d4afb5ceSopenharmony_ci		goto free_context_fail2;
862d4afb5ceSopenharmony_ci
863d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
864d4afb5ceSopenharmony_ci#if defined(LWS_WITH_MBEDTLS)
865d4afb5ceSopenharmony_ci	context->tls_ops = &tls_ops_mbedtls;
866d4afb5ceSopenharmony_ci
867d4afb5ceSopenharmony_ci	mbedtls_client_preload_filepath = info->mbedtls_client_preload_filepath;
868d4afb5ceSopenharmony_ci#else
869d4afb5ceSopenharmony_ci	context->tls_ops = &tls_ops_openssl;
870d4afb5ceSopenharmony_ci#endif
871d4afb5ceSopenharmony_ci#endif
872d4afb5ceSopenharmony_ci
873d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1
874d4afb5ceSopenharmony_ci	lws_mutex_refcount_init(&context->mr);
875d4afb5ceSopenharmony_ci#endif
876d4afb5ceSopenharmony_ci
877d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS)
878d4afb5ceSopenharmony_ci#if defined(LWS_AMAZON_RTOS)
879d4afb5ceSopenharmony_ci	context->last_free_heap = xPortGetFreeHeapSize();
880d4afb5ceSopenharmony_ci#else
881d4afb5ceSopenharmony_ci	context->last_free_heap = esp_get_free_heap_size();
882d4afb5ceSopenharmony_ci#endif
883d4afb5ceSopenharmony_ci#endif
884d4afb5ceSopenharmony_ci
885d4afb5ceSopenharmony_ci#if defined(LWS_WITH_FILE_OPS)
886d4afb5ceSopenharmony_ci	/* default to just the platform fops implementation */
887d4afb5ceSopenharmony_ci
888d4afb5ceSopenharmony_ci	context->fops_platform.LWS_FOP_OPEN	= _lws_plat_file_open;
889d4afb5ceSopenharmony_ci	context->fops_platform.LWS_FOP_CLOSE	= _lws_plat_file_close;
890d4afb5ceSopenharmony_ci	context->fops_platform.LWS_FOP_SEEK_CUR	= _lws_plat_file_seek_cur;
891d4afb5ceSopenharmony_ci	context->fops_platform.LWS_FOP_READ	= _lws_plat_file_read;
892d4afb5ceSopenharmony_ci	context->fops_platform.LWS_FOP_WRITE	= _lws_plat_file_write;
893d4afb5ceSopenharmony_ci	context->fops_platform.fi[0].sig	= NULL;
894d4afb5ceSopenharmony_ci
895d4afb5ceSopenharmony_ci	/*
896d4afb5ceSopenharmony_ci	 *  arrange a linear linked-list of fops starting from context->fops
897d4afb5ceSopenharmony_ci	 *
898d4afb5ceSopenharmony_ci	 * platform fops
899d4afb5ceSopenharmony_ci	 * [ -> fops_zip (copied into context so .next settable) ]
900d4afb5ceSopenharmony_ci	 * [ -> info->fops ]
901d4afb5ceSopenharmony_ci	 */
902d4afb5ceSopenharmony_ci
903d4afb5ceSopenharmony_ci	context->fops = &context->fops_platform;
904d4afb5ceSopenharmony_ci	prev = (struct lws_plat_file_ops *)context->fops;
905d4afb5ceSopenharmony_ci
906d4afb5ceSopenharmony_ci#if defined(LWS_WITH_ZIP_FOPS)
907d4afb5ceSopenharmony_ci	/* make a soft copy so we can set .next */
908d4afb5ceSopenharmony_ci	context->fops_zip = fops_zip;
909d4afb5ceSopenharmony_ci	prev->next = &context->fops_zip;
910d4afb5ceSopenharmony_ci	prev = (struct lws_plat_file_ops *)prev->next;
911d4afb5ceSopenharmony_ci#endif
912d4afb5ceSopenharmony_ci
913d4afb5ceSopenharmony_ci	/* if user provided fops, tack them on the end of the list */
914d4afb5ceSopenharmony_ci	if (info->fops)
915d4afb5ceSopenharmony_ci		prev->next = info->fops;
916d4afb5ceSopenharmony_ci#endif
917d4afb5ceSopenharmony_ci
918d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
919d4afb5ceSopenharmony_ci	context->reject_service_keywords = info->reject_service_keywords;
920d4afb5ceSopenharmony_ci#endif
921d4afb5ceSopenharmony_ci	if (info->external_baggage_free_on_destroy)
922d4afb5ceSopenharmony_ci		context->external_baggage_free_on_destroy =
923d4afb5ceSopenharmony_ci			info->external_baggage_free_on_destroy;
924d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
925d4afb5ceSopenharmony_ci	context->time_up = lws_now_usecs();
926d4afb5ceSopenharmony_ci#endif
927d4afb5ceSopenharmony_ci	context->pcontext_finalize = info->pcontext;
928d4afb5ceSopenharmony_ci
929d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
930d4afb5ceSopenharmony_ci	context->simultaneous_ssl_restriction =
931d4afb5ceSopenharmony_ci			info->simultaneous_ssl_restriction;
932d4afb5ceSopenharmony_ci	context->simultaneous_ssl_handshake_restriction =
933d4afb5ceSopenharmony_ci			info->simultaneous_ssl_handshake_restriction;
934d4afb5ceSopenharmony_ci#endif
935d4afb5ceSopenharmony_ci
936d4afb5ceSopenharmony_ci	context->options = info->options;
937d4afb5ceSopenharmony_ci
938d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) && !defined(WIN32)
939d4afb5ceSopenharmony_ci	/*
940d4afb5ceSopenharmony_ci	 * If asked, try to set the rlimit / ulimit for process sockets / files.
941d4afb5ceSopenharmony_ci	 * We read the effective limit in a moment, so we will find out the
942d4afb5ceSopenharmony_ci	 * real limit according to system constraints then.
943d4afb5ceSopenharmony_ci	 */
944d4afb5ceSopenharmony_ci	if (info->rlimit_nofile) {
945d4afb5ceSopenharmony_ci		struct rlimit rl;
946d4afb5ceSopenharmony_ci
947d4afb5ceSopenharmony_ci		rl.rlim_cur = (unsigned int)info->rlimit_nofile;
948d4afb5ceSopenharmony_ci		rl.rlim_max = (unsigned int)info->rlimit_nofile;
949d4afb5ceSopenharmony_ci		setrlimit(RLIMIT_NOFILE, &rl);
950d4afb5ceSopenharmony_ci	}
951d4afb5ceSopenharmony_ci#endif
952d4afb5ceSopenharmony_ci
953d4afb5ceSopenharmony_ci#ifndef LWS_NO_DAEMONIZE
954d4afb5ceSopenharmony_ci	if (pid_daemon) {
955d4afb5ceSopenharmony_ci		context->started_with_parent = pid_daemon;
956d4afb5ceSopenharmony_ci		lwsl_cx_info(context, " Started with daemon pid %u",
957d4afb5ceSopenharmony_ci				(unsigned int)pid_daemon);
958d4afb5ceSopenharmony_ci	}
959d4afb5ceSopenharmony_ci#endif
960d4afb5ceSopenharmony_ci#if defined(__ANDROID__)
961d4afb5ceSopenharmony_ci	n = getrlimit(RLIMIT_NOFILE, &rt);
962d4afb5ceSopenharmony_ci	if (n == -1) {
963d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "Get RLIMIT_NOFILE failed!");
964d4afb5ceSopenharmony_ci
965d4afb5ceSopenharmony_ci		goto free_context_fail2;
966d4afb5ceSopenharmony_ci	}
967d4afb5ceSopenharmony_ci	context->max_fds = (unsigned int)rt.rlim_cur;
968d4afb5ceSopenharmony_ci#else
969d4afb5ceSopenharmony_ci#if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS) || defined(LWS_ESP_PLATFORM)
970d4afb5ceSopenharmony_ci	context->max_fds = getdtablesize();
971d4afb5ceSopenharmony_ci#else
972d4afb5ceSopenharmony_ci	{
973d4afb5ceSopenharmony_ci		long l = sysconf(_SC_OPEN_MAX);
974d4afb5ceSopenharmony_ci
975d4afb5ceSopenharmony_ci		context->max_fds = 2560;
976d4afb5ceSopenharmony_ci
977d4afb5ceSopenharmony_ci		if (l > 10000000)
978d4afb5ceSopenharmony_ci			lwsl_cx_warn(context, "unreasonable ulimit -n workaround");
979d4afb5ceSopenharmony_ci		else
980d4afb5ceSopenharmony_ci			if (l != -1l)
981d4afb5ceSopenharmony_ci				context->max_fds = (unsigned int)l;
982d4afb5ceSopenharmony_ci	}
983d4afb5ceSopenharmony_ci#endif
984d4afb5ceSopenharmony_ci	if ((int)context->max_fds < 0 ||
985d4afb5ceSopenharmony_ci	     lws_fi(&context->fic, "ctx_createfail_maxfds")) {
986d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "problem getting process max files");
987d4afb5ceSopenharmony_ci
988d4afb5ceSopenharmony_ci		goto free_context_fail2;
989d4afb5ceSopenharmony_ci	}
990d4afb5ceSopenharmony_ci#endif
991d4afb5ceSopenharmony_ci
992d4afb5ceSopenharmony_ci	/*
993d4afb5ceSopenharmony_ci	 * deal with any max_fds override, if it's reducing (setting it to
994d4afb5ceSopenharmony_ci	 * more than ulimit -n is meaningless).  The platform init will
995d4afb5ceSopenharmony_ci	 * figure out what if this is something it can deal with.
996d4afb5ceSopenharmony_ci	 */
997d4afb5ceSopenharmony_ci	if (info->fd_limit_per_thread) {
998d4afb5ceSopenharmony_ci		unsigned int mf = lpf * context->count_threads;
999d4afb5ceSopenharmony_ci
1000d4afb5ceSopenharmony_ci		if (mf < context->max_fds) {
1001d4afb5ceSopenharmony_ci			context->max_fds_unrelated_to_ulimit = 1;
1002d4afb5ceSopenharmony_ci			context->max_fds = mf;
1003d4afb5ceSopenharmony_ci		}
1004d4afb5ceSopenharmony_ci	}
1005d4afb5ceSopenharmony_ci
1006d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1007d4afb5ceSopenharmony_ci	context->token_limits = info->token_limits;
1008d4afb5ceSopenharmony_ci#endif
1009d4afb5ceSopenharmony_ci
1010d4afb5ceSopenharmony_ci
1011d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK)
1012d4afb5ceSopenharmony_ci	time(&context->tls.last_cert_check_s);
1013d4afb5ceSopenharmony_ci	if (info->alpn)
1014d4afb5ceSopenharmony_ci		context->tls.alpn_default = info->alpn;
1015d4afb5ceSopenharmony_ci	else {
1016d4afb5ceSopenharmony_ci		char *p = context->tls.alpn_discovered, first = 1;
1017d4afb5ceSopenharmony_ci
1018d4afb5ceSopenharmony_ci		LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
1019d4afb5ceSopenharmony_ci			if (ar->alpn) {
1020d4afb5ceSopenharmony_ci				if (!first)
1021d4afb5ceSopenharmony_ci					*p++ = ',';
1022d4afb5ceSopenharmony_ci				p += lws_snprintf(p, (unsigned int)(
1023d4afb5ceSopenharmony_ci					(context->tls.alpn_discovered +
1024d4afb5ceSopenharmony_ci					sizeof(context->tls.alpn_discovered) -
1025d4afb5ceSopenharmony_ci					2) - p), "%s", ar->alpn);
1026d4afb5ceSopenharmony_ci				first = 0;
1027d4afb5ceSopenharmony_ci			}
1028d4afb5ceSopenharmony_ci		} LWS_FOR_EVERY_AVAILABLE_ROLE_END;
1029d4afb5ceSopenharmony_ci
1030d4afb5ceSopenharmony_ci		context->tls.alpn_default = context->tls.alpn_discovered;
1031d4afb5ceSopenharmony_ci	}
1032d4afb5ceSopenharmony_ci
1033d4afb5ceSopenharmony_ci#endif
1034d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1035d4afb5ceSopenharmony_ci	if (info->timeout_secs)
1036d4afb5ceSopenharmony_ci		context->timeout_secs = info->timeout_secs;
1037d4afb5ceSopenharmony_ci	else
1038d4afb5ceSopenharmony_ci#endif
1039d4afb5ceSopenharmony_ci		context->timeout_secs = 15;
1040d4afb5ceSopenharmony_ci
1041d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1042d4afb5ceSopenharmony_ci	if (info->max_http_header_data)
1043d4afb5ceSopenharmony_ci		context->max_http_header_data = info->max_http_header_data;
1044d4afb5ceSopenharmony_ci	else
1045d4afb5ceSopenharmony_ci		if (info->max_http_header_data2)
1046d4afb5ceSopenharmony_ci			context->max_http_header_data =
1047d4afb5ceSopenharmony_ci					(unsigned short)info->max_http_header_data2;
1048d4afb5ceSopenharmony_ci		else
1049d4afb5ceSopenharmony_ci			context->max_http_header_data = LWS_DEF_HEADER_LEN;
1050d4afb5ceSopenharmony_ci
1051d4afb5ceSopenharmony_ci	if (info->max_http_header_pool)
1052d4afb5ceSopenharmony_ci		context->max_http_header_pool = info->max_http_header_pool;
1053d4afb5ceSopenharmony_ci	else
1054d4afb5ceSopenharmony_ci		if (info->max_http_header_pool2)
1055d4afb5ceSopenharmony_ci			context->max_http_header_pool =
1056d4afb5ceSopenharmony_ci					(unsigned short)info->max_http_header_pool2;
1057d4afb5ceSopenharmony_ci		else
1058d4afb5ceSopenharmony_ci			context->max_http_header_pool = context->max_fds;
1059d4afb5ceSopenharmony_ci#endif
1060d4afb5ceSopenharmony_ci
1061d4afb5ceSopenharmony_ci	if (info->fd_limit_per_thread)
1062d4afb5ceSopenharmony_ci		context->fd_limit_per_thread = lpf;
1063d4afb5ceSopenharmony_ci	else
1064d4afb5ceSopenharmony_ci		if (context->count_threads)
1065d4afb5ceSopenharmony_ci			context->fd_limit_per_thread = context->max_fds /
1066d4afb5ceSopenharmony_ci							context->count_threads;
1067d4afb5ceSopenharmony_ci
1068d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
1069d4afb5ceSopenharmony_ci	lws_mutex_init(context->smd.lock_messages);
1070d4afb5ceSopenharmony_ci	lws_mutex_init(context->smd.lock_peers);
1071d4afb5ceSopenharmony_ci
1072d4afb5ceSopenharmony_ci	/* lws_system smd participant */
1073d4afb5ceSopenharmony_ci
1074d4afb5ceSopenharmony_ci	if (!lws_smd_register(context, context, 0, LWSSMDCL_NETWORK,
1075d4afb5ceSopenharmony_ci			      lws_system_smd_cb)) {
1076d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "early smd register failed");
1077d4afb5ceSopenharmony_ci	}
1078d4afb5ceSopenharmony_ci
1079d4afb5ceSopenharmony_ci	/* user smd participant */
1080d4afb5ceSopenharmony_ci
1081d4afb5ceSopenharmony_ci	if (info->early_smd_cb &&
1082d4afb5ceSopenharmony_ci	    !lws_smd_register(context, info->early_smd_opaque, 0,
1083d4afb5ceSopenharmony_ci			      info->early_smd_class_filter,
1084d4afb5ceSopenharmony_ci			      info->early_smd_cb)) {
1085d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "early smd register failed");
1086d4afb5ceSopenharmony_ci	}
1087d4afb5ceSopenharmony_ci#endif
1088d4afb5ceSopenharmony_ci
1089d4afb5ceSopenharmony_ci	n = 0;
1090d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1091d4afb5ceSopenharmony_ci
1092d4afb5ceSopenharmony_ci	context->default_retry.retry_ms_table = default_backoff_table;
1093d4afb5ceSopenharmony_ci	context->default_retry.conceal_count =
1094d4afb5ceSopenharmony_ci			context->default_retry.retry_ms_table_count =
1095d4afb5ceSopenharmony_ci					LWS_ARRAY_SIZE(default_backoff_table);
1096d4afb5ceSopenharmony_ci	context->default_retry.jitter_percent = 20;
1097d4afb5ceSopenharmony_ci	context->default_retry.secs_since_valid_ping = 300;
1098d4afb5ceSopenharmony_ci	context->default_retry.secs_since_valid_hangup = 310;
1099d4afb5ceSopenharmony_ci
1100d4afb5ceSopenharmony_ci	if (info->retry_and_idle_policy &&
1101d4afb5ceSopenharmony_ci	    info->retry_and_idle_policy->secs_since_valid_ping) {
1102d4afb5ceSopenharmony_ci		context->default_retry.secs_since_valid_ping =
1103d4afb5ceSopenharmony_ci				info->retry_and_idle_policy->secs_since_valid_ping;
1104d4afb5ceSopenharmony_ci		context->default_retry.secs_since_valid_hangup =
1105d4afb5ceSopenharmony_ci				info->retry_and_idle_policy->secs_since_valid_hangup;
1106d4afb5ceSopenharmony_ci	}
1107d4afb5ceSopenharmony_ci
1108d4afb5ceSopenharmony_ci	/*
1109d4afb5ceSopenharmony_ci	 * Allocate the per-thread storage for scratchpad buffers,
1110d4afb5ceSopenharmony_ci	 * and header data pool
1111d4afb5ceSopenharmony_ci	 */
1112d4afb5ceSopenharmony_ci	u = (uint8_t *)&context[1];
1113d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++) {
1114d4afb5ceSopenharmony_ci		context->pt[n].serv_buf = u;
1115d4afb5ceSopenharmony_ci		u += context->pt_serv_buf_size;
1116d4afb5ceSopenharmony_ci
1117d4afb5ceSopenharmony_ci		context->pt[n].context = context;
1118d4afb5ceSopenharmony_ci		context->pt[n].tid = (uint8_t)n;
1119d4afb5ceSopenharmony_ci
1120d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS)
1121d4afb5ceSopenharmony_ci		/*
1122d4afb5ceSopenharmony_ci		 * We overallocated for a fakewsi (can't compose it in the
1123d4afb5ceSopenharmony_ci		 * pt because size isn't known at that time).  point to it
1124d4afb5ceSopenharmony_ci		 * and zero it down.  Fakewsis are needed to make callbacks work
1125d4afb5ceSopenharmony_ci		 * when the source of the callback is not actually from a wsi
1126d4afb5ceSopenharmony_ci		 * context.
1127d4afb5ceSopenharmony_ci		 */
1128d4afb5ceSopenharmony_ci		context->pt[n].fake_wsi = (struct lws *)u;
1129d4afb5ceSopenharmony_ci		u += sizeof(struct lws);
1130d4afb5ceSopenharmony_ci
1131d4afb5ceSopenharmony_ci		memset(context->pt[n].fake_wsi, 0, sizeof(struct lws));
1132d4afb5ceSopenharmony_ci#endif
1133d4afb5ceSopenharmony_ci
1134d4afb5ceSopenharmony_ci		context->pt[n].evlib_pt = u;
1135d4afb5ceSopenharmony_ci		u += plev->ops->evlib_size_pt;
1136d4afb5ceSopenharmony_ci
1137d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1138d4afb5ceSopenharmony_ci		context->pt[n].http.ah_list = NULL;
1139d4afb5ceSopenharmony_ci		context->pt[n].http.ah_pool_length = 0;
1140d4afb5ceSopenharmony_ci#endif
1141d4afb5ceSopenharmony_ci		lws_pt_mutex_init(&context->pt[n]);
1142d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SEQUENCER)
1143d4afb5ceSopenharmony_ci		lws_seq_pt_init(&context->pt[n]);
1144d4afb5ceSopenharmony_ci#endif
1145d4afb5ceSopenharmony_ci
1146d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CGI)
1147d4afb5ceSopenharmony_ci		if (lws_rops_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy))
1148d4afb5ceSopenharmony_ci			(lws_rops_func_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)).
1149d4afb5ceSopenharmony_ci				pt_init_destroy(context, info,
1150d4afb5ceSopenharmony_ci						&context->pt[n], 0);
1151d4afb5ceSopenharmony_ci#endif
1152d4afb5ceSopenharmony_ci	}
1153d4afb5ceSopenharmony_ci
1154d4afb5ceSopenharmony_ci	if (!info->ka_interval && info->ka_time > 0) {
1155d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "info->ka_interval can't be 0 if ka_time used");
1156d4afb5ceSopenharmony_ci		goto free_context_fail;
1157d4afb5ceSopenharmony_ci	}
1158d4afb5ceSopenharmony_ci
1159d4afb5ceSopenharmony_ci#if defined(LWS_WITH_PEER_LIMITS)
1160d4afb5ceSopenharmony_ci	/* scale the peer hash table according to the max fds for the process,
1161d4afb5ceSopenharmony_ci	 * so that the max list depth averages 16.  Eg, 1024 fd -> 64,
1162d4afb5ceSopenharmony_ci	 * 102400 fd -> 6400
1163d4afb5ceSopenharmony_ci	 */
1164d4afb5ceSopenharmony_ci
1165d4afb5ceSopenharmony_ci	context->pl_hash_elements =
1166d4afb5ceSopenharmony_ci		(context->count_threads * context->fd_limit_per_thread) / 16;
1167d4afb5ceSopenharmony_ci	context->pl_hash_table = lws_zalloc(sizeof(struct lws_peer *) *
1168d4afb5ceSopenharmony_ci			context->pl_hash_elements, "peer limits hash table");
1169d4afb5ceSopenharmony_ci
1170d4afb5ceSopenharmony_ci	context->ip_limit_ah = info->ip_limit_ah;
1171d4afb5ceSopenharmony_ci	context->ip_limit_wsi = info->ip_limit_wsi;
1172d4afb5ceSopenharmony_ci	context->pl_notify_cb = info->pl_notify_cb;
1173d4afb5ceSopenharmony_ci#endif
1174d4afb5ceSopenharmony_ci
1175d4afb5ceSopenharmony_ci	/*
1176d4afb5ceSopenharmony_ci	 * fds table contains pollfd structs for as many pollfds as we can
1177d4afb5ceSopenharmony_ci	 * handle... spread across as many service threads as we have going
1178d4afb5ceSopenharmony_ci	 */
1179d4afb5ceSopenharmony_ci	n = (int)(sizeof(struct lws_pollfd) * context->count_threads *
1180d4afb5ceSopenharmony_ci	    context->fd_limit_per_thread);
1181d4afb5ceSopenharmony_ci	context->pt[0].fds = lws_zalloc((unsigned int)n, "fds table");
1182d4afb5ceSopenharmony_ci	if (context->pt[0].fds == NULL ||
1183d4afb5ceSopenharmony_ci	    lws_fi(&context->fic, "ctx_createfail_oom_fds")) {
1184d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION)
1185d4afb5ceSopenharmony_ci		lws_free(context->pt[0].fds);
1186d4afb5ceSopenharmony_ci#endif
1187d4afb5ceSopenharmony_ci		lwsl_cx_err(context, "OOM allocating %d fds\n", context->max_fds);
1188d4afb5ceSopenharmony_ci		goto free_context_fail;
1189d4afb5ceSopenharmony_ci	}
1190d4afb5ceSopenharmony_ci#endif
1191d4afb5ceSopenharmony_ci
1192d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "ctx: %5luB (%ld ctx + pt(%ld thr x %d)), "
1193d4afb5ceSopenharmony_ci		  "pt-fds: %d, fdmap: %d",
1194d4afb5ceSopenharmony_ci		  (long)sizeof(struct lws_context) +
1195d4afb5ceSopenharmony_ci		  (context->count_threads * context->pt_serv_buf_size),
1196d4afb5ceSopenharmony_ci		  (long)sizeof(struct lws_context),
1197d4afb5ceSopenharmony_ci		  (long)context->count_threads,
1198d4afb5ceSopenharmony_ci		  context->pt_serv_buf_size,
1199d4afb5ceSopenharmony_ci		  context->fd_limit_per_thread, n);
1200d4afb5ceSopenharmony_ci
1201d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1202d4afb5ceSopenharmony_ci	lwsl_cx_info(context, " http: ah_data: %u, ah: %lu, max count %u",
1203d4afb5ceSopenharmony_ci		    context->max_http_header_data,
1204d4afb5ceSopenharmony_ci		    (long)sizeof(struct allocated_headers),
1205d4afb5ceSopenharmony_ci		    context->max_http_header_pool);
1206d4afb5ceSopenharmony_ci#endif
1207d4afb5ceSopenharmony_ci
1208d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
1209d4afb5ceSopenharmony_ci	if (info->server_string) {
1210d4afb5ceSopenharmony_ci		context->server_string = info->server_string;
1211d4afb5ceSopenharmony_ci		context->server_string_len = (short)
1212d4afb5ceSopenharmony_ci				strlen(context->server_string);
1213d4afb5ceSopenharmony_ci	}
1214d4afb5ceSopenharmony_ci#endif
1215d4afb5ceSopenharmony_ci
1216d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1
1217d4afb5ceSopenharmony_ci	/* each thread serves his own chunk of fds */
1218d4afb5ceSopenharmony_ci	for (n = 1; n < (int)context->count_threads; n++)
1219d4afb5ceSopenharmony_ci		context->pt[n].fds = context->pt[n - 1].fds +
1220d4afb5ceSopenharmony_ci				     context->fd_limit_per_thread;
1221d4afb5ceSopenharmony_ci#endif
1222d4afb5ceSopenharmony_ci
1223d4afb5ceSopenharmony_ci
1224d4afb5ceSopenharmony_ci	/*
1225d4afb5ceSopenharmony_ci	 * Past here, we may have added handles to the event lib
1226d4afb5ceSopenharmony_ci	 * loop and if libuv,  have to take care about how to unpick them...
1227d4afb5ceSopenharmony_ci	 */
1228d4afb5ceSopenharmony_ci
1229d4afb5ceSopenharmony_ci	if (lws_plat_init(context, info) ||
1230d4afb5ceSopenharmony_ci	    lws_fi(&context->fic, "ctx_createfail_plat_init"))
1231d4afb5ceSopenharmony_ci		goto bail_libuv_aware;
1232d4afb5ceSopenharmony_ci
1233d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1234d4afb5ceSopenharmony_ci
1235d4afb5ceSopenharmony_ci	if (lws_fi(&context->fic, "ctx_createfail_evlib_init"))
1236d4afb5ceSopenharmony_ci		goto bail_libuv_aware;
1237d4afb5ceSopenharmony_ci
1238d4afb5ceSopenharmony_ci	if (context->event_loop_ops->init_context)
1239d4afb5ceSopenharmony_ci		if (context->event_loop_ops->init_context(context, info))
1240d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1241d4afb5ceSopenharmony_ci
1242d4afb5ceSopenharmony_ci	if (lws_fi(&context->fic, "ctx_createfail_evlib_pt"))
1243d4afb5ceSopenharmony_ci		goto bail_libuv_aware;
1244d4afb5ceSopenharmony_ci
1245d4afb5ceSopenharmony_ci	if (context->event_loop_ops->init_pt)
1246d4afb5ceSopenharmony_ci		for (n = 0; n < context->count_threads; n++) {
1247d4afb5ceSopenharmony_ci			void *lp = NULL;
1248d4afb5ceSopenharmony_ci
1249d4afb5ceSopenharmony_ci			if (info->foreign_loops)
1250d4afb5ceSopenharmony_ci				lp = info->foreign_loops[n];
1251d4afb5ceSopenharmony_ci
1252d4afb5ceSopenharmony_ci			if (context->event_loop_ops->init_pt(context, lp, n))
1253d4afb5ceSopenharmony_ci				goto bail_libuv_aware;
1254d4afb5ceSopenharmony_ci		}
1255d4afb5ceSopenharmony_ci
1256d4afb5ceSopenharmony_ci	lws_context_lock(context, __func__);
1257d4afb5ceSopenharmony_ci	n = __lws_create_event_pipes(context);
1258d4afb5ceSopenharmony_ci	lws_context_unlock(context);
1259d4afb5ceSopenharmony_ci	if (n)
1260d4afb5ceSopenharmony_ci		goto bail_libuv_aware;
1261d4afb5ceSopenharmony_ci
1262d4afb5ceSopenharmony_ci	for (n = 0; n < context->count_threads; n++) {
1263d4afb5ceSopenharmony_ci		LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
1264d4afb5ceSopenharmony_ci			if (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy))
1265d4afb5ceSopenharmony_ci				(lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)).
1266d4afb5ceSopenharmony_ci					pt_init_destroy(context, info,
1267d4afb5ceSopenharmony_ci							&context->pt[n], 0);
1268d4afb5ceSopenharmony_ci		} LWS_FOR_EVERY_AVAILABLE_ROLE_END;
1269d4afb5ceSopenharmony_ci	}
1270d4afb5ceSopenharmony_ci#endif
1271d4afb5ceSopenharmony_ci
1272d4afb5ceSopenharmony_ci	lws_context_init_ssl_library(context, info);
1273d4afb5ceSopenharmony_ci
1274d4afb5ceSopenharmony_ci	context->user_space = info->user;
1275d4afb5ceSopenharmony_ci
1276d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
1277d4afb5ceSopenharmony_ci	strcpy(context->canonical_hostname, "unknown");
1278d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1279d4afb5ceSopenharmony_ci	lws_server_get_canonical_hostname(context, info);
1280d4afb5ceSopenharmony_ci#endif
1281d4afb5ceSopenharmony_ci#endif
1282d4afb5ceSopenharmony_ci
1283d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
1284d4afb5ceSopenharmony_ci	memcpy(context->caps, info->caps, sizeof(context->caps));
1285d4afb5ceSopenharmony_ci	context->count_caps = info->count_caps;
1286d4afb5ceSopenharmony_ci#endif
1287d4afb5ceSopenharmony_ci
1288d4afb5ceSopenharmony_ci
1289d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1290d4afb5ceSopenharmony_ci
1291d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS) || defined(LWS_WITH_SYS_NTPCLIENT) || \
1292d4afb5ceSopenharmony_ci	defined(LWS_WITH_SYS_DHCP_CLIENT)
1293d4afb5ceSopenharmony_ci	{
1294d4afb5ceSopenharmony_ci		/*
1295d4afb5ceSopenharmony_ci		 * system vhost
1296d4afb5ceSopenharmony_ci		 */
1297d4afb5ceSopenharmony_ci
1298d4afb5ceSopenharmony_ci		struct lws_context_creation_info ii;
1299d4afb5ceSopenharmony_ci		const struct lws_protocols *pp[4];
1300d4afb5ceSopenharmony_ci		struct lws_vhost *vh;
1301d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
1302d4afb5ceSopenharmony_ci		extern const struct lws_protocols lws_async_dns_protocol;
1303d4afb5ceSopenharmony_ci#endif
1304d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_NTPCLIENT)
1305d4afb5ceSopenharmony_ci		extern const struct lws_protocols lws_system_protocol_ntpc;
1306d4afb5ceSopenharmony_ci#endif
1307d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT)
1308d4afb5ceSopenharmony_ci		extern const struct lws_protocols lws_system_protocol_dhcpc4;
1309d4afb5ceSopenharmony_ci#endif
1310d4afb5ceSopenharmony_ci
1311d4afb5ceSopenharmony_ci		n = 0;
1312d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
1313d4afb5ceSopenharmony_ci		pp[n++] = &lws_async_dns_protocol;
1314d4afb5ceSopenharmony_ci#endif
1315d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_NTPCLIENT)
1316d4afb5ceSopenharmony_ci		pp[n++] = &lws_system_protocol_ntpc;
1317d4afb5ceSopenharmony_ci#endif
1318d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT)
1319d4afb5ceSopenharmony_ci		pp[n++] = &lws_system_protocol_dhcpc4;
1320d4afb5ceSopenharmony_ci#endif
1321d4afb5ceSopenharmony_ci		pp[n] = NULL;
1322d4afb5ceSopenharmony_ci
1323d4afb5ceSopenharmony_ci		memset(&ii, 0, sizeof(ii));
1324d4afb5ceSopenharmony_ci		ii.vhost_name = "system";
1325d4afb5ceSopenharmony_ci		ii.pprotocols = pp;
1326d4afb5ceSopenharmony_ci		ii.port = CONTEXT_PORT_NO_LISTEN;
1327d4afb5ceSopenharmony_ci
1328d4afb5ceSopenharmony_ci		if (lws_fi(&context->fic, "ctx_createfail_sys_vh"))
1329d4afb5ceSopenharmony_ci			vh = NULL;
1330d4afb5ceSopenharmony_ci		else
1331d4afb5ceSopenharmony_ci			vh = lws_create_vhost(context, &ii);
1332d4afb5ceSopenharmony_ci		if (!vh) {
1333d4afb5ceSopenharmony_ci			lwsl_cx_err(context, "failed to create system vhost");
1334d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1335d4afb5ceSopenharmony_ci		}
1336d4afb5ceSopenharmony_ci
1337d4afb5ceSopenharmony_ci		context->vhost_system = vh;
1338d4afb5ceSopenharmony_ci
1339d4afb5ceSopenharmony_ci		if (lws_protocol_init_vhost(vh, NULL) ||
1340d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_sys_vh_init")) {
1341d4afb5ceSopenharmony_ci			lwsl_cx_err(context, "failed to init system vhost");
1342d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1343d4afb5ceSopenharmony_ci		}
1344d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
1345d4afb5ceSopenharmony_ci		lws_async_dns_init(context);
1346d4afb5ceSopenharmony_ci			//goto bail_libuv_aware;
1347d4afb5ceSopenharmony_ci#endif
1348d4afb5ceSopenharmony_ci	}
1349d4afb5ceSopenharmony_ci
1350d4afb5ceSopenharmony_ci#endif
1351d4afb5ceSopenharmony_ci
1352d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
1353d4afb5ceSopenharmony_ci	/*
1354d4afb5ceSopenharmony_ci	 * init the lws_state mgr for the system state
1355d4afb5ceSopenharmony_ci	 */
1356d4afb5ceSopenharmony_ci
1357d4afb5ceSopenharmony_ci	context->mgr_system.name		= "system";
1358d4afb5ceSopenharmony_ci	context->mgr_system.state		= LWS_SYSTATE_CONTEXT_CREATED;
1359d4afb5ceSopenharmony_ci	context->mgr_system.parent		= context;
1360d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
1361d4afb5ceSopenharmony_ci	context->mgr_system.smd_class		= LWSSMDCL_SYSTEM_STATE;
1362d4afb5ceSopenharmony_ci#endif
1363d4afb5ceSopenharmony_ci
1364d4afb5ceSopenharmony_ci	context->protocols_notify.name		= "prot_init";
1365d4afb5ceSopenharmony_ci	context->protocols_notify.notify_cb	= lws_state_notify_protocol_init;
1366d4afb5ceSopenharmony_ci
1367d4afb5ceSopenharmony_ci	lws_state_reg_notifier(&context->mgr_system, &context->protocols_notify);
1368d4afb5ceSopenharmony_ci
1369d4afb5ceSopenharmony_ci	/*
1370d4afb5ceSopenharmony_ci	 * insert user notifiers here so they can participate with vetoing us
1371d4afb5ceSopenharmony_ci	 * trying to jump straight to operational, or at least observe us
1372d4afb5ceSopenharmony_ci	 * reaching 'operational', before we returned from context creation.
1373d4afb5ceSopenharmony_ci	 */
1374d4afb5ceSopenharmony_ci
1375d4afb5ceSopenharmony_ci	lws_state_reg_notifier_list(&context->mgr_system,
1376d4afb5ceSopenharmony_ci				    info->register_notifier_list);
1377d4afb5ceSopenharmony_ci#endif
1378d4afb5ceSopenharmony_ci
1379d4afb5ceSopenharmony_ci	/*
1380d4afb5ceSopenharmony_ci	 * if he's not saying he'll make his own vhosts later then act
1381d4afb5ceSopenharmony_ci	 * compatibly and make a default vhost using the data in the info
1382d4afb5ceSopenharmony_ci	 */
1383d4afb5ceSopenharmony_ci	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) {
1384d4afb5ceSopenharmony_ci		if (!lws_create_vhost(context, info) ||
1385d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_def_vh")) {
1386d4afb5ceSopenharmony_ci			lwsl_cx_err(context, "Failed to create default vhost");
1387d4afb5ceSopenharmony_ci
1388d4afb5ceSopenharmony_ci#if defined(LWS_WITH_PEER_LIMITS)
1389d4afb5ceSopenharmony_ci			lws_free_set_NULL(context->pl_hash_table);
1390d4afb5ceSopenharmony_ci#endif
1391d4afb5ceSopenharmony_ci			goto bail;
1392d4afb5ceSopenharmony_ci		}
1393d4afb5ceSopenharmony_ci	}
1394d4afb5ceSopenharmony_ci
1395d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
1396d4afb5ceSopenharmony_ci	if (info->http_nsc_filepath) {
1397d4afb5ceSopenharmony_ci		memset(&ci, 0, sizeof(ci));
1398d4afb5ceSopenharmony_ci
1399d4afb5ceSopenharmony_ci		ci.cx			   = context;
1400d4afb5ceSopenharmony_ci		ci.ops			   = &lws_cache_ops_nscookiejar;
1401d4afb5ceSopenharmony_ci		ci.name			   = "NSC";
1402d4afb5ceSopenharmony_ci		ci.u.nscookiejar.filepath  = info->http_nsc_filepath;
1403d4afb5ceSopenharmony_ci
1404d4afb5ceSopenharmony_ci		context->nsc = lws_cache_create(&ci);
1405d4afb5ceSopenharmony_ci		if (!context->nsc)
1406d4afb5ceSopenharmony_ci			goto bail;
1407d4afb5ceSopenharmony_ci
1408d4afb5ceSopenharmony_ci		ci.ops			  = &lws_cache_ops_heap;
1409d4afb5ceSopenharmony_ci		ci.name			  = "L1";
1410d4afb5ceSopenharmony_ci		ci.parent		  = context->nsc;
1411d4afb5ceSopenharmony_ci		ci.max_footprint	  = info->http_nsc_heap_max_footprint;
1412d4afb5ceSopenharmony_ci		ci.max_items		  = info->http_nsc_heap_max_items;
1413d4afb5ceSopenharmony_ci		ci.max_payload		  = info->http_nsc_heap_max_payload;
1414d4afb5ceSopenharmony_ci
1415d4afb5ceSopenharmony_ci		context->l1 = lws_cache_create(&ci);
1416d4afb5ceSopenharmony_ci		if (!context->l1) {
1417d4afb5ceSopenharmony_ci			lwsl_cx_err(context, "Failed to init cookiejar");
1418d4afb5ceSopenharmony_ci			goto bail;
1419d4afb5ceSopenharmony_ci		}
1420d4afb5ceSopenharmony_ci	}
1421d4afb5ceSopenharmony_ci#endif
1422d4afb5ceSopenharmony_ci
1423d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
1424d4afb5ceSopenharmony_ci
1425d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
1426d4afb5ceSopenharmony_ci	if (context->pss_policies_json) {
1427d4afb5ceSopenharmony_ci		/*
1428d4afb5ceSopenharmony_ci		 * You must create your context with the explicit vhosts flag
1429d4afb5ceSopenharmony_ci		 * in order to use secure streams
1430d4afb5ceSopenharmony_ci		 */
1431d4afb5ceSopenharmony_ci		assert(lws_check_opt(info->options,
1432d4afb5ceSopenharmony_ci		       LWS_SERVER_OPTION_EXPLICIT_VHOSTS));
1433d4afb5ceSopenharmony_ci
1434d4afb5ceSopenharmony_ci		if (lws_ss_policy_parse_begin(context, 0) ||
1435d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_ss_pol1")) {
1436d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION)
1437d4afb5ceSopenharmony_ci			lws_ss_policy_parse_abandon(context);
1438d4afb5ceSopenharmony_ci#endif
1439d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1440d4afb5ceSopenharmony_ci		}
1441d4afb5ceSopenharmony_ci
1442d4afb5ceSopenharmony_ci		n = lws_ss_policy_parse(context,
1443d4afb5ceSopenharmony_ci					(uint8_t *)context->pss_policies_json,
1444d4afb5ceSopenharmony_ci					strlen(context->pss_policies_json));
1445d4afb5ceSopenharmony_ci		if ((n != LEJP_CONTINUE && n < 0) ||
1446d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_ss_pol2")) {
1447d4afb5ceSopenharmony_ci			lws_ss_policy_parse_abandon(context);
1448d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1449d4afb5ceSopenharmony_ci		}
1450d4afb5ceSopenharmony_ci
1451d4afb5ceSopenharmony_ci		if (lws_ss_policy_set(context, "hardcoded") ||
1452d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_ss_pol3")) {
1453d4afb5ceSopenharmony_ci			lwsl_cx_err(context, "policy set failed");
1454d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1455d4afb5ceSopenharmony_ci		}
1456d4afb5ceSopenharmony_ci	}
1457d4afb5ceSopenharmony_ci#else
1458d4afb5ceSopenharmony_ci	if (context->pss_policies) {
1459d4afb5ceSopenharmony_ci		/* user code set the policy objects directly, no parsing step */
1460d4afb5ceSopenharmony_ci
1461d4afb5ceSopenharmony_ci		if (lws_ss_policy_set(context, "hardcoded") ||
1462d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_ss_pol3")) {
1463d4afb5ceSopenharmony_ci			lwsl_cx_err(context, "policy set failed");
1464d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1465d4afb5ceSopenharmony_ci		}
1466d4afb5ceSopenharmony_ci	}
1467d4afb5ceSopenharmony_ci#endif
1468d4afb5ceSopenharmony_ci#endif
1469d4afb5ceSopenharmony_ci
1470d4afb5ceSopenharmony_ci	lws_context_init_extensions(info, context);
1471d4afb5ceSopenharmony_ci
1472d4afb5ceSopenharmony_ci	lwsl_cx_info(context, " mem: per-conn:        %5lu bytes + protocol rx buf",
1473d4afb5ceSopenharmony_ci		    (unsigned long)sizeof(struct lws));
1474d4afb5ceSopenharmony_ci
1475d4afb5ceSopenharmony_ci	/*
1476d4afb5ceSopenharmony_ci	 * drop any root privs for this process
1477d4afb5ceSopenharmony_ci	 * to listen on port < 1023 we would have needed root, but now we are
1478d4afb5ceSopenharmony_ci	 * listening, we don't want the power for anything else
1479d4afb5ceSopenharmony_ci	 */
1480d4afb5ceSopenharmony_ci	if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
1481d4afb5ceSopenharmony_ci		if (lws_plat_drop_app_privileges(context, 1) ||
1482d4afb5ceSopenharmony_ci		    lws_fi(&context->fic, "ctx_createfail_privdrop"))
1483d4afb5ceSopenharmony_ci			goto bail_libuv_aware;
1484d4afb5ceSopenharmony_ci
1485d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
1486d4afb5ceSopenharmony_ci	/*
1487d4afb5ceSopenharmony_ci	 * We want to move on the syste, state as far as it can go towards
1488d4afb5ceSopenharmony_ci	 * OPERATIONAL now.  But we have to return from here first so the user
1489d4afb5ceSopenharmony_ci	 * code that called us can set its copy of context, which it may be
1490d4afb5ceSopenharmony_ci	 * relying on to perform operations triggered by the state change.
1491d4afb5ceSopenharmony_ci	 *
1492d4afb5ceSopenharmony_ci	 * We set up a sul to come back immediately and do the state change.
1493d4afb5ceSopenharmony_ci	 */
1494d4afb5ceSopenharmony_ci
1495d4afb5ceSopenharmony_ci	lws_sul_schedule(context, 0, &context->sul_system_state,
1496d4afb5ceSopenharmony_ci			 lws_context_creation_completion_cb, 1);
1497d4afb5ceSopenharmony_ci#endif
1498d4afb5ceSopenharmony_ci
1499d4afb5ceSopenharmony_ci	/* expedite post-context init (eg, protocols) */
1500d4afb5ceSopenharmony_ci	lws_cancel_service(context);
1501d4afb5ceSopenharmony_ci#endif
1502d4afb5ceSopenharmony_ci
1503d4afb5ceSopenharmony_ci	return context;
1504d4afb5ceSopenharmony_ci
1505d4afb5ceSopenharmony_ciearly_bail:
1506d4afb5ceSopenharmony_ci	lws_fi_destroy(&info->fic);
1507d4afb5ceSopenharmony_ci
1508d4afb5ceSopenharmony_ci	return NULL;
1509d4afb5ceSopenharmony_ci
1510d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1511d4afb5ceSopenharmony_cibail:
1512d4afb5ceSopenharmony_ci	lws_fi_destroy(&info->fic);
1513d4afb5ceSopenharmony_ci	lws_context_destroy(context);
1514d4afb5ceSopenharmony_ci
1515d4afb5ceSopenharmony_ci	return NULL;
1516d4afb5ceSopenharmony_ci#endif
1517d4afb5ceSopenharmony_ci
1518d4afb5ceSopenharmony_cibail_libuv_aware:
1519d4afb5ceSopenharmony_ci	lws_context_destroy(context);
1520d4afb5ceSopenharmony_ci#if defined(LWS_WITH_LIBUV)
1521d4afb5ceSopenharmony_ci	return fatal_exit_defer ? context : NULL;
1522d4afb5ceSopenharmony_ci#else
1523d4afb5ceSopenharmony_ci	return NULL;
1524d4afb5ceSopenharmony_ci#endif
1525d4afb5ceSopenharmony_ci
1526d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1527d4afb5ceSopenharmony_cifail_event_libs:
1528d4afb5ceSopenharmony_ci	if (context)
1529d4afb5ceSopenharmony_ci	lwsl_cx_err(context, "Requested event library support not configured");
1530d4afb5ceSopenharmony_ci#endif
1531d4afb5ceSopenharmony_ci
1532d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1533d4afb5ceSopenharmony_cifree_context_fail:
1534d4afb5ceSopenharmony_ci	if (context) {
1535d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
1536d4afb5ceSopenharmony_ci		_lws_smd_destroy(context);
1537d4afb5ceSopenharmony_ci#endif
1538d4afb5ceSopenharmony_ci	}
1539d4afb5ceSopenharmony_ci#endif
1540d4afb5ceSopenharmony_cifree_context_fail2:
1541d4afb5ceSopenharmony_ci	if (context) {
1542d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
1543d4afb5ceSopenharmony_ci		lws_metrics_destroy(context);
1544d4afb5ceSopenharmony_ci#endif
1545d4afb5ceSopenharmony_ci		lws_fi_destroy(&context->fic);
1546d4afb5ceSopenharmony_ci	}
1547d4afb5ceSopenharmony_ci	lws_fi_destroy(&info->fic);
1548d4afb5ceSopenharmony_ci	if (context) {
1549d4afb5ceSopenharmony_ci		lwsl_refcount_cx(context->log_cx, -1);
1550d4afb5ceSopenharmony_ci		lws_free(context);
1551d4afb5ceSopenharmony_ci	}
1552d4afb5ceSopenharmony_ci
1553d4afb5ceSopenharmony_ci	return NULL;
1554d4afb5ceSopenharmony_ci}
1555d4afb5ceSopenharmony_ci
1556d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1557d4afb5ceSopenharmony_ciint
1558d4afb5ceSopenharmony_cilws_system_cpd_start(struct lws_context *cx)
1559d4afb5ceSopenharmony_ci{
1560d4afb5ceSopenharmony_ci	cx->captive_portal_detect = LWS_CPD_UNKNOWN;
1561d4afb5ceSopenharmony_ci
1562d4afb5ceSopenharmony_ci	/* if there's a platform implementation, use it */
1563d4afb5ceSopenharmony_ci
1564d4afb5ceSopenharmony_ci	if (lws_system_get_ops(cx) &&
1565d4afb5ceSopenharmony_ci	    lws_system_get_ops(cx)->captive_portal_detect_request)
1566d4afb5ceSopenharmony_ci		return lws_system_get_ops(cx)->captive_portal_detect_request(cx);
1567d4afb5ceSopenharmony_ci
1568d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
1569d4afb5ceSopenharmony_ci	/*
1570d4afb5ceSopenharmony_ci	 * Otherwise try to use SS "captive_portal_detect" if that's enabled
1571d4afb5ceSopenharmony_ci	 */
1572d4afb5ceSopenharmony_ci	return lws_ss_sys_cpd(cx);
1573d4afb5ceSopenharmony_ci#else
1574d4afb5ceSopenharmony_ci	return 0;
1575d4afb5ceSopenharmony_ci#endif
1576d4afb5ceSopenharmony_ci}
1577d4afb5ceSopenharmony_ci
1578d4afb5ceSopenharmony_cistatic void
1579d4afb5ceSopenharmony_cilws_system_deferred_cb(lws_sorted_usec_list_t *sul)
1580d4afb5ceSopenharmony_ci{
1581d4afb5ceSopenharmony_ci	struct lws_context *cx =
1582d4afb5ceSopenharmony_ci		     lws_container_of(sul, struct lws_context, sul_cpd_defer);
1583d4afb5ceSopenharmony_ci
1584d4afb5ceSopenharmony_ci	lws_system_cpd_start(cx);
1585d4afb5ceSopenharmony_ci}
1586d4afb5ceSopenharmony_ci
1587d4afb5ceSopenharmony_civoid
1588d4afb5ceSopenharmony_cilws_system_cpd_start_defer(struct lws_context *cx, lws_usec_t defer_us)
1589d4afb5ceSopenharmony_ci{
1590d4afb5ceSopenharmony_ci	lws_sul_schedule(cx, 0, &cx->sul_cpd_defer,
1591d4afb5ceSopenharmony_ci			 lws_system_deferred_cb, defer_us);
1592d4afb5ceSopenharmony_ci}
1593d4afb5ceSopenharmony_ci
1594d4afb5ceSopenharmony_ci#if (defined(LWS_WITH_SYS_STATE) && defined(LWS_WITH_SYS_SMD)) || !defined(LWS_WITH_NO_LOGS)
1595d4afb5ceSopenharmony_cistatic const char *cname[] = { "Unknown", "OK", "Captive", "No internet" };
1596d4afb5ceSopenharmony_ci#endif
1597d4afb5ceSopenharmony_ci
1598d4afb5ceSopenharmony_civoid
1599d4afb5ceSopenharmony_cilws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result)
1600d4afb5ceSopenharmony_ci{
1601d4afb5ceSopenharmony_ci	if (cx->captive_portal_detect != LWS_CPD_UNKNOWN)
1602d4afb5ceSopenharmony_ci		return;
1603d4afb5ceSopenharmony_ci
1604d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_NO_LOGS)
1605d4afb5ceSopenharmony_ci	lwsl_cx_notice(cx, "setting CPD result %s", cname[result]);
1606d4afb5ceSopenharmony_ci#endif
1607d4afb5ceSopenharmony_ci
1608d4afb5ceSopenharmony_ci	cx->captive_portal_detect = (uint8_t)result;
1609d4afb5ceSopenharmony_ci
1610d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
1611d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
1612d4afb5ceSopenharmony_ci	lws_smd_msg_printf(cx, LWSSMDCL_NETWORK,
1613d4afb5ceSopenharmony_ci			   "{\"type\":\"cpd\",\"result\":\"%s\"}",
1614d4afb5ceSopenharmony_ci			   cname[cx->captive_portal_detect]);
1615d4afb5ceSopenharmony_ci#endif
1616d4afb5ceSopenharmony_ci
1617d4afb5ceSopenharmony_ci	/* if nothing is there to intercept anything, go all the way */
1618d4afb5ceSopenharmony_ci	if (cx->mgr_system.state != LWS_SYSTATE_POLICY_INVALID)
1619d4afb5ceSopenharmony_ci		lws_state_transition_steps(&cx->mgr_system,
1620d4afb5ceSopenharmony_ci					   LWS_SYSTATE_OPERATIONAL);
1621d4afb5ceSopenharmony_ci#endif
1622d4afb5ceSopenharmony_ci}
1623d4afb5ceSopenharmony_ci
1624d4afb5ceSopenharmony_cilws_cpd_result_t
1625d4afb5ceSopenharmony_cilws_system_cpd_state_get(struct lws_context *cx)
1626d4afb5ceSopenharmony_ci{
1627d4afb5ceSopenharmony_ci	return (lws_cpd_result_t)cx->captive_portal_detect;
1628d4afb5ceSopenharmony_ci}
1629d4afb5ceSopenharmony_ci
1630d4afb5ceSopenharmony_ci#endif
1631d4afb5ceSopenharmony_ci
1632d4afb5ceSopenharmony_ciint
1633d4afb5ceSopenharmony_cilws_context_is_deprecated(struct lws_context *cx)
1634d4afb5ceSopenharmony_ci{
1635d4afb5ceSopenharmony_ci	return cx->deprecated;
1636d4afb5ceSopenharmony_ci}
1637d4afb5ceSopenharmony_ci
1638d4afb5ceSopenharmony_ci/*
1639d4afb5ceSopenharmony_ci * When using an event loop, the context destruction is in three separate
1640d4afb5ceSopenharmony_ci * parts.  This is to cover both internal and foreign event loops cleanly.
1641d4afb5ceSopenharmony_ci *
1642d4afb5ceSopenharmony_ci *  - lws_context_destroy() simply starts a soft close of all wsi and
1643d4afb5ceSopenharmony_ci *     related allocations.  The event loop continues.
1644d4afb5ceSopenharmony_ci *
1645d4afb5ceSopenharmony_ci *     As the closes complete in the event loop, reference counting is used
1646d4afb5ceSopenharmony_ci *     to determine when everything is closed.  It then calls
1647d4afb5ceSopenharmony_ci *     lws_context_destroy2().
1648d4afb5ceSopenharmony_ci *
1649d4afb5ceSopenharmony_ci *  - lws_context_destroy2() cleans up the rest of the higher-level logical
1650d4afb5ceSopenharmony_ci *     lws pieces like vhosts.  If the loop was foreign, it then proceeds to
1651d4afb5ceSopenharmony_ci *     lws_context_destroy3().  If it the loop is internal, it stops the
1652d4afb5ceSopenharmony_ci *     internal loops and waits for lws_context_destroy() to be called again
1653d4afb5ceSopenharmony_ci *     outside the event loop (since we cannot destroy the loop from
1654d4afb5ceSopenharmony_ci *     within the loop).  That will cause lws_context_destroy3() to run
1655d4afb5ceSopenharmony_ci *     directly.
1656d4afb5ceSopenharmony_ci *
1657d4afb5ceSopenharmony_ci *  - lws_context_destroy3() destroys any internal event loops and then
1658d4afb5ceSopenharmony_ci *     destroys the context itself, setting what was info.pcontext to NULL.
1659d4afb5ceSopenharmony_ci */
1660d4afb5ceSopenharmony_ci
1661d4afb5ceSopenharmony_ci
1662d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1663d4afb5ceSopenharmony_cistatic void
1664d4afb5ceSopenharmony_cilws_pt_destroy(struct lws_context_per_thread *pt)
1665d4afb5ceSopenharmony_ci{
1666d4afb5ceSopenharmony_ci	volatile struct lws_foreign_thread_pollfd *ftp, *next;
1667d4afb5ceSopenharmony_ci	volatile struct lws_context_per_thread *vpt;
1668d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CGI)
1669d4afb5ceSopenharmony_ci	lws_ctx_t ctx = pt->context;
1670d4afb5ceSopenharmony_ci
1671d4afb5ceSopenharmony_ci		if (lws_rops_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy))
1672d4afb5ceSopenharmony_ci			(lws_rops_func_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy)).
1673d4afb5ceSopenharmony_ci				pt_init_destroy(ctx, NULL, pt, 1);
1674d4afb5ceSopenharmony_ci#endif
1675d4afb5ceSopenharmony_ci	vpt = (volatile struct lws_context_per_thread *)pt;
1676d4afb5ceSopenharmony_ci	ftp = vpt->foreign_pfd_list;
1677d4afb5ceSopenharmony_ci	while (ftp) {
1678d4afb5ceSopenharmony_ci		next = ftp->next;
1679d4afb5ceSopenharmony_ci		lws_free((void *)ftp);
1680d4afb5ceSopenharmony_ci		ftp = next;
1681d4afb5ceSopenharmony_ci	}
1682d4afb5ceSopenharmony_ci	vpt->foreign_pfd_list = NULL;
1683d4afb5ceSopenharmony_ci
1684d4afb5ceSopenharmony_ci	lws_pt_lock(pt, __func__);
1685d4afb5ceSopenharmony_ci
1686d4afb5ceSopenharmony_ci	if (pt->pipe_wsi) {
1687d4afb5ceSopenharmony_ci		lws_destroy_event_pipe(pt->pipe_wsi);
1688d4afb5ceSopenharmony_ci		pt->pipe_wsi = NULL;
1689d4afb5ceSopenharmony_ci	}
1690d4afb5ceSopenharmony_ci
1691d4afb5ceSopenharmony_ci	if ((pt->dummy_pipe_fds[0] || pt->dummy_pipe_fds[1])
1692d4afb5ceSopenharmony_ci#if !defined(WIN32)
1693d4afb5ceSopenharmony_ci	    && ((int)pt->dummy_pipe_fds[0] != -1 || (int)pt->dummy_pipe_fds[1] != -1)
1694d4afb5ceSopenharmony_ci#endif
1695d4afb5ceSopenharmony_ci	) {
1696d4afb5ceSopenharmony_ci		struct lws wsi;
1697d4afb5ceSopenharmony_ci
1698d4afb5ceSopenharmony_ci		memset(&wsi, 0, sizeof(wsi));
1699d4afb5ceSopenharmony_ci		wsi.a.context = pt->context;
1700d4afb5ceSopenharmony_ci		wsi.tsi = (char)pt->tid;
1701d4afb5ceSopenharmony_ci		lws_plat_pipe_close(&wsi);
1702d4afb5ceSopenharmony_ci	}
1703d4afb5ceSopenharmony_ci
1704d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS)
1705d4afb5ceSopenharmony_ci	lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll);
1706d4afb5ceSopenharmony_ci
1707d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) && defined(LWS_WITH_CLIENT)
1708d4afb5ceSopenharmony_ci	lws_dll2_foreach_safe(&pt->ss_client_owner, NULL, lws_sspc_destroy_dll);
1709d4afb5ceSopenharmony_ci#endif
1710d4afb5ceSopenharmony_ci
1711d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SEQUENCER)
1712d4afb5ceSopenharmony_ci	lws_seq_destroy_all_on_pt(pt);
1713d4afb5ceSopenharmony_ci#endif
1714d4afb5ceSopenharmony_ci
1715d4afb5ceSopenharmony_ci
1716d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
1717d4afb5ceSopenharmony_ci		while (pt->http.ah_list)
1718d4afb5ceSopenharmony_ci			_lws_destroy_ah(pt, pt->http.ah_list);
1719d4afb5ceSopenharmony_ci#endif
1720d4afb5ceSopenharmony_ci
1721d4afb5ceSopenharmony_ci#endif
1722d4afb5ceSopenharmony_ci
1723d4afb5ceSopenharmony_ci	lws_pt_unlock(pt);
1724d4afb5ceSopenharmony_ci	pt->pipe_wsi = NULL;
1725d4afb5ceSopenharmony_ci
1726d4afb5ceSopenharmony_ci}
1727d4afb5ceSopenharmony_ci#endif
1728d4afb5ceSopenharmony_ci
1729d4afb5ceSopenharmony_ci/*
1730d4afb5ceSopenharmony_ci * Context destruction is now a state machine that's aware of SMP pts and
1731d4afb5ceSopenharmony_ci * various event lib approaches.
1732d4afb5ceSopenharmony_ci *
1733d4afb5ceSopenharmony_ci * lws_context_destroy() expects to be called at the end of the user code's
1734d4afb5ceSopenharmony_ci * usage of it.  But it can also be called non-finally, as a way to stop
1735d4afb5ceSopenharmony_ci * service and exit the outer user service loop, and then complete in the
1736d4afb5ceSopenharmony_ci * final call.
1737d4afb5ceSopenharmony_ci *
1738d4afb5ceSopenharmony_ci * For libuv, with async close, it must decide by refcounting the hamdles on
1739d4afb5ceSopenharmony_ci * the loop if it has extricated itself from the loop and can be destroyed.
1740d4afb5ceSopenharmony_ci *
1741d4afb5ceSopenharmony_ci * The various entry states for the staged destroy
1742d4afb5ceSopenharmony_ci *
1743d4afb5ceSopenharmony_ci * LWSCD_NO_DESTROY: begin destroy process
1744d4afb5ceSopenharmony_ci * 	- mark context as starting destroy process
1745d4afb5ceSopenharmony_ci * 	- start vhost destroy
1746d4afb5ceSopenharmony_ci * 	- stop any further user protocol service
1747d4afb5ceSopenharmony_ci *
1748d4afb5ceSopenharmony_ci * LWSCD_PT_WAS_DEFERRED: come back here if any pt inside service
1749d4afb5ceSopenharmony_ci * 	- Check for pts that are inside service loop, mark deferral needed if so
1750d4afb5ceSopenharmony_ci * 	- If not, close all wsi on the pt loop and start logical pt destroy
1751d4afb5ceSopenharmony_ci * 	- If any deferred, set state to LWSCD_PT_WAS_DEFERRED and exit
1752d4afb5ceSopenharmony_ci *
1753d4afb5ceSopenharmony_ci * LWSCD_PT_WAIT_ALL_DESTROYED: come back here for async loop / pt closes
1754d4afb5ceSopenharmony_ci * 	- exit if any pt not marked as unused, or destroyed
1755d4afb5ceSopenharmony_ci * 	- if all pt down, call into evlib to advance context destroy
1756d4afb5ceSopenharmony_ci * 	- finalize vhost destruction
1757d4afb5ceSopenharmony_ci * 	- finalize pt destruction
1758d4afb5ceSopenharmony_ci *	- if foreign loops, set state to LWSCD_FINALIZATION and exit
1759d4afb5ceSopenharmony_ci *
1760d4afb5ceSopenharmony_ci * LWSCD_FINALIZATION: come back here at final lws_destroy_context() call
1761d4afb5ceSopenharmony_ci *	- destroy sundries
1762d4afb5ceSopenharmony_ci *	- destroy and free the actual context
1763d4afb5ceSopenharmony_ci */
1764d4afb5ceSopenharmony_ci
1765d4afb5ceSopenharmony_civoid
1766d4afb5ceSopenharmony_cilws_context_destroy(struct lws_context *context)
1767d4afb5ceSopenharmony_ci{
1768d4afb5ceSopenharmony_ci	struct lws_context **pcontext_finalize;
1769d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1770d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt;
1771d4afb5ceSopenharmony_ci	struct lws_vhost *vh = NULL, *vh1;
1772d4afb5ceSopenharmony_ci	int alive = 0, deferred_pt = 0;
1773d4afb5ceSopenharmony_ci#endif
1774d4afb5ceSopenharmony_ci#if defined(LWS_WITH_PEER_LIMITS)
1775d4afb5ceSopenharmony_ci	uint32_t nu;
1776d4afb5ceSopenharmony_ci#endif
1777d4afb5ceSopenharmony_ci	int n;
1778d4afb5ceSopenharmony_ci
1779d4afb5ceSopenharmony_ci	if (!context || context->inside_context_destroy)
1780d4afb5ceSopenharmony_ci		return;
1781d4afb5ceSopenharmony_ci
1782d4afb5ceSopenharmony_ci	pcontext_finalize = context->pcontext_finalize;
1783d4afb5ceSopenharmony_ci
1784d4afb5ceSopenharmony_ci	lws_context_lock(context, __func__);
1785d4afb5ceSopenharmony_ci	context->inside_context_destroy = 1;
1786d4afb5ceSopenharmony_ci
1787d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "destroy_state %d", context->destroy_state);
1788d4afb5ceSopenharmony_ci
1789d4afb5ceSopenharmony_ci	switch (context->destroy_state) {
1790d4afb5ceSopenharmony_ci	case LWSCD_NO_DESTROY:
1791d4afb5ceSopenharmony_ci		/*
1792d4afb5ceSopenharmony_ci		 * We're getting started
1793d4afb5ceSopenharmony_ci		 */
1794d4afb5ceSopenharmony_ci
1795d4afb5ceSopenharmony_ci		lwsl_cx_info(context, "starting context destroy flow");
1796d4afb5ceSopenharmony_ci		context->being_destroyed = 1;
1797d4afb5ceSopenharmony_ci
1798d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1799d4afb5ceSopenharmony_ci
1800d4afb5ceSopenharmony_ci		/*
1801d4afb5ceSopenharmony_ci		 * Close any vhost listen wsi
1802d4afb5ceSopenharmony_ci		 *
1803d4afb5ceSopenharmony_ci		 * inform all the protocols that they are done and will have no
1804d4afb5ceSopenharmony_ci		 * more callbacks.
1805d4afb5ceSopenharmony_ci		 *
1806d4afb5ceSopenharmony_ci		 * We can't free things until after the event loop shuts down.
1807d4afb5ceSopenharmony_ci		 */
1808d4afb5ceSopenharmony_ci
1809d4afb5ceSopenharmony_ci		if (context->protocol_init_done)
1810d4afb5ceSopenharmony_ci			vh = context->vhost_list;
1811d4afb5ceSopenharmony_ci
1812d4afb5ceSopenharmony_ci		while (vh) {
1813d4afb5ceSopenharmony_ci			lwsl_vhost_info(vh, "start close");
1814d4afb5ceSopenharmony_ci			vh1 = vh->vhost_next;
1815d4afb5ceSopenharmony_ci			lws_vhost_destroy1(vh);
1816d4afb5ceSopenharmony_ci			vh = vh1;
1817d4afb5ceSopenharmony_ci		}
1818d4afb5ceSopenharmony_ci#endif
1819d4afb5ceSopenharmony_ci
1820d4afb5ceSopenharmony_ci		lws_plat_context_early_destroy(context);
1821d4afb5ceSopenharmony_ci
1822d4afb5ceSopenharmony_ci		context->service_no_longer_possible = 1;
1823d4afb5ceSopenharmony_ci		context->requested_stop_internal_loops = 1;
1824d4afb5ceSopenharmony_ci
1825d4afb5ceSopenharmony_ci		/* fallthru */
1826d4afb5ceSopenharmony_ci
1827d4afb5ceSopenharmony_ci	case LWSCD_PT_WAS_DEFERRED:
1828d4afb5ceSopenharmony_ci
1829d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1830d4afb5ceSopenharmony_ci
1831d4afb5ceSopenharmony_ci		/*
1832d4afb5ceSopenharmony_ci		 * We want to mark the pts as their destruction having been
1833d4afb5ceSopenharmony_ci		 * initiated, so they will reject any new wsi, and iterate all
1834d4afb5ceSopenharmony_ci		 * existing pt wsi starting to close them.
1835d4afb5ceSopenharmony_ci		 *
1836d4afb5ceSopenharmony_ci		 * If the event loop has async close, we have to return after
1837d4afb5ceSopenharmony_ci		 * this and try again when all the loops stop after all the
1838d4afb5ceSopenharmony_ci		 * refcounted wsi are gone.
1839d4afb5ceSopenharmony_ci		 */
1840d4afb5ceSopenharmony_ci
1841d4afb5ceSopenharmony_ci		pt = context->pt;
1842d4afb5ceSopenharmony_ci		for (n = 0; n < context->count_threads; n++) {
1843d4afb5ceSopenharmony_ci			lws_pt_lock(pt, __func__);
1844d4afb5ceSopenharmony_ci
1845d4afb5ceSopenharmony_ci			/* evlib will realize it needs to destroy pt */
1846d4afb5ceSopenharmony_ci			pt->destroy_self = 1;
1847d4afb5ceSopenharmony_ci
1848d4afb5ceSopenharmony_ci			if (pt->inside_lws_service) {
1849d4afb5ceSopenharmony_ci				pt->event_loop_pt_unused = 1;
1850d4afb5ceSopenharmony_ci				deferred_pt = 1;
1851d4afb5ceSopenharmony_ci				goto next;
1852d4afb5ceSopenharmony_ci			}
1853d4afb5ceSopenharmony_ci
1854d4afb5ceSopenharmony_ci			/*
1855d4afb5ceSopenharmony_ci			 * Close every handle in the fds
1856d4afb5ceSopenharmony_ci			 */
1857d4afb5ceSopenharmony_ci
1858d4afb5ceSopenharmony_ci			while (pt->fds_count) {
1859d4afb5ceSopenharmony_ci				struct lws *wsi = wsi_from_fd(context,
1860d4afb5ceSopenharmony_ci							      pt->fds[0].fd);
1861d4afb5ceSopenharmony_ci
1862d4afb5ceSopenharmony_ci				if (wsi) {
1863d4afb5ceSopenharmony_ci
1864d4afb5ceSopenharmony_ci					lwsl_cx_debug(context,
1865d4afb5ceSopenharmony_ci						"pt %d: closing wsi %p: role %s",
1866d4afb5ceSopenharmony_ci						n, wsi, wsi->role_ops->name);
1867d4afb5ceSopenharmony_ci
1868d4afb5ceSopenharmony_ci					lws_close_free_wsi(wsi,
1869d4afb5ceSopenharmony_ci						LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY,
1870d4afb5ceSopenharmony_ci						"ctx destroy"
1871d4afb5ceSopenharmony_ci						/* no protocol close */);
1872d4afb5ceSopenharmony_ci
1873d4afb5ceSopenharmony_ci					if (pt->pipe_wsi == wsi)
1874d4afb5ceSopenharmony_ci						pt->pipe_wsi = NULL;
1875d4afb5ceSopenharmony_ci				}
1876d4afb5ceSopenharmony_ci			}
1877d4afb5ceSopenharmony_ci
1878d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CGI)
1879d4afb5ceSopenharmony_ci			(lws_rops_func_fidx(&role_ops_cgi,
1880d4afb5ceSopenharmony_ci					    LWS_ROPS_pt_init_destroy)).
1881d4afb5ceSopenharmony_ci					    pt_init_destroy(context, NULL,
1882d4afb5ceSopenharmony_ci							    pt, 1);
1883d4afb5ceSopenharmony_ci#endif
1884d4afb5ceSopenharmony_ci
1885d4afb5ceSopenharmony_ci			/*
1886d4afb5ceSopenharmony_ci			 * This closes handles that belong to the evlib pt
1887d4afb5ceSopenharmony_ci			 * footprint, eg, timers, idle
1888d4afb5ceSopenharmony_ci			 */
1889d4afb5ceSopenharmony_ci
1890d4afb5ceSopenharmony_ci			if (context->event_loop_ops->destroy_pt) {
1891d4afb5ceSopenharmony_ci				lwsl_cx_info(context,
1892d4afb5ceSopenharmony_ci					     "calling evlib destroy_pt %d\n", n);
1893d4afb5ceSopenharmony_ci				context->event_loop_ops->destroy_pt(context, n);
1894d4afb5ceSopenharmony_ci			}
1895d4afb5ceSopenharmony_ci
1896d4afb5ceSopenharmony_cinext:
1897d4afb5ceSopenharmony_ci			lws_pt_unlock(pt);
1898d4afb5ceSopenharmony_ci
1899d4afb5ceSopenharmony_ci			pt++;
1900d4afb5ceSopenharmony_ci		}
1901d4afb5ceSopenharmony_ci
1902d4afb5ceSopenharmony_ci		if (deferred_pt) {
1903d4afb5ceSopenharmony_ci			context->destroy_state = LWSCD_PT_WAS_DEFERRED;
1904d4afb5ceSopenharmony_ci			lwsl_cx_notice(context, "destroy from inside service");
1905d4afb5ceSopenharmony_ci			lws_cancel_service(context);
1906d4afb5ceSopenharmony_ci			goto bail;
1907d4afb5ceSopenharmony_ci		}
1908d4afb5ceSopenharmony_ci#endif
1909d4afb5ceSopenharmony_ci		context->destroy_state = LWSCD_PT_WAIT_ALL_DESTROYED;
1910d4afb5ceSopenharmony_ci
1911d4afb5ceSopenharmony_ci		/*
1912d4afb5ceSopenharmony_ci		 * We have different needs depending if foreign loop or not.
1913d4afb5ceSopenharmony_ci		 *
1914d4afb5ceSopenharmony_ci		 * 1) If foreign loop, we really want to advance the
1915d4afb5ceSopenharmony_ci		 *    destroy_context() past here, and block only for libuv-
1916d4afb5ceSopenharmony_ci		 *    style async close completion.
1917d4afb5ceSopenharmony_ci		 *
1918d4afb5ceSopenharmony_ci		 * 2a) If poll, and we exited by ourselves and are calling a
1919d4afb5ceSopenharmony_ci		 *     final destroy_context() outside of any service already,
1920d4afb5ceSopenharmony_ci		 *     we want to advance all the way in one step.
1921d4afb5ceSopenharmony_ci		 *
1922d4afb5ceSopenharmony_ci		 * 2b) If poll, and we are reacting to a SIGINT, service
1923d4afb5ceSopenharmony_ci		 *     thread(s) may be in poll wait or servicing.  We can't
1924d4afb5ceSopenharmony_ci		 *     advance the destroy_context() to the point it's freeing
1925d4afb5ceSopenharmony_ci		 *     things; we have to leave that for the final
1926d4afb5ceSopenharmony_ci		 *     destroy_context() after the service thread(s) are
1927d4afb5ceSopenharmony_ci		 *     finished calling for service.
1928d4afb5ceSopenharmony_ci		 */
1929d4afb5ceSopenharmony_ci
1930d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1931d4afb5ceSopenharmony_ci		if (context->event_loop_ops->destroy_context1) {
1932d4afb5ceSopenharmony_ci			lwsl_cx_info(context, "do evlib destroy_context1 and wait");
1933d4afb5ceSopenharmony_ci			context->event_loop_ops->destroy_context1(context);
1934d4afb5ceSopenharmony_ci
1935d4afb5ceSopenharmony_ci			goto bail;
1936d4afb5ceSopenharmony_ci		}
1937d4afb5ceSopenharmony_ci
1938d4afb5ceSopenharmony_ci		/*
1939d4afb5ceSopenharmony_ci		 * ...if the more typical sync close, we can clean up the pts
1940d4afb5ceSopenharmony_ci		 * now ourselves...
1941d4afb5ceSopenharmony_ci		 */
1942d4afb5ceSopenharmony_ci
1943d4afb5ceSopenharmony_ci		lwsl_cx_info(context, "manually destroying pts");
1944d4afb5ceSopenharmony_ci
1945d4afb5ceSopenharmony_ci		pt = context->pt;
1946d4afb5ceSopenharmony_ci		for (n = 0; n < context->count_threads; n++, pt++) {
1947d4afb5ceSopenharmony_ci			pt->event_loop_pt_unused = 1;
1948d4afb5ceSopenharmony_ci			lws_pt_destroy(pt);
1949d4afb5ceSopenharmony_ci		}
1950d4afb5ceSopenharmony_ci#endif
1951d4afb5ceSopenharmony_ci		/* fallthru */
1952d4afb5ceSopenharmony_ci
1953d4afb5ceSopenharmony_ci	case LWSCD_PT_WAIT_ALL_DESTROYED:
1954d4afb5ceSopenharmony_ci
1955d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1956d4afb5ceSopenharmony_ci
1957d4afb5ceSopenharmony_ci		for (n = 0; n < context->count_threads; n++)
1958d4afb5ceSopenharmony_ci			if (!context->pt[n].is_destroyed &&
1959d4afb5ceSopenharmony_ci			    !context->pt[n].event_loop_pt_unused)
1960d4afb5ceSopenharmony_ci				alive++;
1961d4afb5ceSopenharmony_ci
1962d4afb5ceSopenharmony_ci		lwsl_cx_info(context, "PT_WAIT_ALL_DESTROYED: %d alive", alive);
1963d4afb5ceSopenharmony_ci
1964d4afb5ceSopenharmony_ci		if (alive)
1965d4afb5ceSopenharmony_ci			break;
1966d4afb5ceSopenharmony_ci
1967d4afb5ceSopenharmony_ci		/*
1968d4afb5ceSopenharmony_ci		 * With foreign loops, removing all our fds from the loop
1969d4afb5ceSopenharmony_ci		 * means there are no more ways for the foreign loop to give
1970d4afb5ceSopenharmony_ci		 * us any further CPU once we leave here... so we must make
1971d4afb5ceSopenharmony_ci		 * sure related service threads are exiting so we can pick up
1972d4afb5ceSopenharmony_ci		 * again at the original app thread and do the context
1973d4afb5ceSopenharmony_ci		 * destroy completion
1974d4afb5ceSopenharmony_ci		 */
1975d4afb5ceSopenharmony_ci
1976d4afb5ceSopenharmony_ci		/*
1977d4afb5ceSopenharmony_ci		 * evlib specific loop destroy?
1978d4afb5ceSopenharmony_ci		 */
1979d4afb5ceSopenharmony_ci		if (context->event_loop_ops->destroy_context2)
1980d4afb5ceSopenharmony_ci			/*
1981d4afb5ceSopenharmony_ci			 * He returns nonzero to indicate the evlib must
1982d4afb5ceSopenharmony_ci			 * continue around the loop before destroy of it is
1983d4afb5ceSopenharmony_ci			 * completed so it can be freed
1984d4afb5ceSopenharmony_ci			 */
1985d4afb5ceSopenharmony_ci			context->event_loop_ops->destroy_context2(context);
1986d4afb5ceSopenharmony_ci		context->requested_stop_internal_loops = 1;
1987d4afb5ceSopenharmony_ci#endif
1988d4afb5ceSopenharmony_ci
1989d4afb5ceSopenharmony_ci		/*
1990d4afb5ceSopenharmony_ci		 * Every pt and wsi that may depend on the logical vhosts
1991d4afb5ceSopenharmony_ci		 * is destroyed.  We can remove the logical vhosts.
1992d4afb5ceSopenharmony_ci		 */
1993d4afb5ceSopenharmony_ci
1994d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE) && defined(LWS_WITH_NETWORK)
1995d4afb5ceSopenharmony_ci	lws_state_transition(&context->mgr_system, LWS_SYSTATE_POLICY_INVALID);
1996d4afb5ceSopenharmony_ci#endif
1997d4afb5ceSopenharmony_ci
1998d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
1999d4afb5ceSopenharmony_ci		/*
2000d4afb5ceSopenharmony_ci		 * free all the per-vhost allocations
2001d4afb5ceSopenharmony_ci		 */
2002d4afb5ceSopenharmony_ci
2003d4afb5ceSopenharmony_ci		vh = context->vhost_list;
2004d4afb5ceSopenharmony_ci		while (vh) {
2005d4afb5ceSopenharmony_ci			vh1 = vh->vhost_next;
2006d4afb5ceSopenharmony_ci		//	lwsl_vhost_debug(vh, "vh %s destroy2", vh->name);
2007d4afb5ceSopenharmony_ci			__lws_vhost_destroy2(vh);
2008d4afb5ceSopenharmony_ci			vh = vh1;
2009d4afb5ceSopenharmony_ci		}
2010d4afb5ceSopenharmony_ci
2011d4afb5ceSopenharmony_ci		/* remove ourselves from the pending destruction list */
2012d4afb5ceSopenharmony_ci
2013d4afb5ceSopenharmony_ci		while (context->vhost_pending_destruction_list)
2014d4afb5ceSopenharmony_ci			/* removes itself from list */
2015d4afb5ceSopenharmony_ci			__lws_vhost_destroy2(context->vhost_pending_destruction_list);
2016d4afb5ceSopenharmony_ci#endif
2017d4afb5ceSopenharmony_ci
2018d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
2019d4afb5ceSopenharmony_ci		lws_ssl_context_destroy(context);
2020d4afb5ceSopenharmony_ci#endif
2021d4afb5ceSopenharmony_ci		lws_plat_context_late_destroy(context);
2022d4afb5ceSopenharmony_ci
2023d4afb5ceSopenharmony_ci#if defined(LWS_WITH_PEER_LIMITS)
2024d4afb5ceSopenharmony_ci		if (context->pl_hash_table)
2025d4afb5ceSopenharmony_ci			for (nu = 0; nu < context->pl_hash_elements; nu++)	{
2026d4afb5ceSopenharmony_ci				if (!context->pl_hash_table[nu])
2027d4afb5ceSopenharmony_ci					continue;
2028d4afb5ceSopenharmony_ci				lws_start_foreach_llp(struct lws_peer **, peer,
2029d4afb5ceSopenharmony_ci						      context->pl_hash_table[nu]) {
2030d4afb5ceSopenharmony_ci					struct lws_peer *df = *peer;
2031d4afb5ceSopenharmony_ci					*peer = df->next;
2032d4afb5ceSopenharmony_ci					lws_free(df);
2033d4afb5ceSopenharmony_ci					continue;
2034d4afb5ceSopenharmony_ci				} lws_end_foreach_llp(peer, next);
2035d4afb5ceSopenharmony_ci			}
2036d4afb5ceSopenharmony_ci		lws_free(context->pl_hash_table);
2037d4afb5ceSopenharmony_ci#endif
2038d4afb5ceSopenharmony_ci
2039d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
2040d4afb5ceSopenharmony_ci
2041d4afb5ceSopenharmony_ci		for (n = 0; n < context->count_threads; n++) {
2042d4afb5ceSopenharmony_ci			struct lws_context_per_thread *pt = &context->pt[n];
2043d4afb5ceSopenharmony_ci
2044d4afb5ceSopenharmony_ci			(void)pt;
2045d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SEQUENCER)
2046d4afb5ceSopenharmony_ci			lws_seq_destroy_all_on_pt(pt);
2047d4afb5ceSopenharmony_ci#endif
2048d4afb5ceSopenharmony_ci			LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
2049d4afb5ceSopenharmony_ci				if (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy))
2050d4afb5ceSopenharmony_ci					(lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)).
2051d4afb5ceSopenharmony_ci						pt_init_destroy(context, NULL, pt, 1);
2052d4afb5ceSopenharmony_ci			} LWS_FOR_EVERY_AVAILABLE_ROLE_END;
2053d4afb5ceSopenharmony_ci
2054d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CGI)
2055d4afb5ceSopenharmony_ci			lws_rops_func_fidx(&role_ops_cgi,
2056d4afb5ceSopenharmony_ci					   LWS_ROPS_pt_init_destroy).
2057d4afb5ceSopenharmony_ci					        pt_init_destroy(context, NULL,
2058d4afb5ceSopenharmony_ci					        		pt, 1);
2059d4afb5ceSopenharmony_ci#endif
2060d4afb5ceSopenharmony_ci
2061d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
2062d4afb5ceSopenharmony_ci			while (pt->http.ah_list)
2063d4afb5ceSopenharmony_ci				_lws_destroy_ah(pt, pt->http.ah_list);
2064d4afb5ceSopenharmony_ci#endif
2065d4afb5ceSopenharmony_ci			lwsl_cx_info(context, "pt destroy %d", n);
2066d4afb5ceSopenharmony_ci			lws_pt_destroy(pt);
2067d4afb5ceSopenharmony_ci		}
2068d4afb5ceSopenharmony_ci#endif /* NETWORK */
2069d4afb5ceSopenharmony_ci
2070d4afb5ceSopenharmony_ci		context->destroy_state = LWSCD_FINALIZATION;
2071d4afb5ceSopenharmony_ci
2072d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
2073d4afb5ceSopenharmony_ci
2074d4afb5ceSopenharmony_ci		if (context->pt[0].event_loop_foreign &&
2075d4afb5ceSopenharmony_ci		    context->event_loop_ops->destroy_context1) {
2076d4afb5ceSopenharmony_ci
2077d4afb5ceSopenharmony_ci			lwsl_cx_info(context,
2078d4afb5ceSopenharmony_ci				    "leaving final context destruction"
2079d4afb5ceSopenharmony_ci					" for final call");
2080d4afb5ceSopenharmony_ci			goto bail;
2081d4afb5ceSopenharmony_ci		}
2082d4afb5ceSopenharmony_ci
2083d4afb5ceSopenharmony_ci		if (context->event_loop_ops->destroy_context1 &&
2084d4afb5ceSopenharmony_ci		    !context->pt[0].event_loop_foreign) {
2085d4afb5ceSopenharmony_ci			lwsl_cx_notice(context, "waiting for internal loop exit");
2086d4afb5ceSopenharmony_ci
2087d4afb5ceSopenharmony_ci			goto bail;
2088d4afb5ceSopenharmony_ci		}
2089d4afb5ceSopenharmony_ci#endif
2090d4afb5ceSopenharmony_ci		/* fallthru */
2091d4afb5ceSopenharmony_ci
2092d4afb5ceSopenharmony_ci	case LWSCD_FINALIZATION:
2093d4afb5ceSopenharmony_ci
2094d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
2095d4afb5ceSopenharmony_ci		lws_metrics_dump(context);
2096d4afb5ceSopenharmony_ci#endif
2097d4afb5ceSopenharmony_ci
2098d4afb5ceSopenharmony_ci		context->evlib_finalize_destroy_after_int_loops_stop = 1;
2099d4afb5ceSopenharmony_ci
2100d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
2101d4afb5ceSopenharmony_ci		if (context->event_loop_ops->destroy_context2)
2102d4afb5ceSopenharmony_ci			context->event_loop_ops->destroy_context2(context);
2103d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
2104d4afb5ceSopenharmony_ci		lws_state_transition_steps(&context->mgr_system,
2105d4afb5ceSopenharmony_ci					   LWS_SYSTATE_CONTEXT_DESTROYING);
2106d4afb5ceSopenharmony_ci#endif
2107d4afb5ceSopenharmony_ci		/*
2108d4afb5ceSopenharmony_ci		 * finalize destroy of pt and things hanging off it
2109d4afb5ceSopenharmony_ci		 */
2110d4afb5ceSopenharmony_ci
2111d4afb5ceSopenharmony_ci		for (n = 0; n < context->count_threads; n++) {
2112d4afb5ceSopenharmony_ci			struct lws_context_per_thread *pt = &context->pt[n];
2113d4afb5ceSopenharmony_ci
2114d4afb5ceSopenharmony_ci			/*
2115d4afb5ceSopenharmony_ci			 * Destroy the pt-roles
2116d4afb5ceSopenharmony_ci			 */
2117d4afb5ceSopenharmony_ci
2118d4afb5ceSopenharmony_ci			LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
2119d4afb5ceSopenharmony_ci				if (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy))
2120d4afb5ceSopenharmony_ci					(lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)).
2121d4afb5ceSopenharmony_ci							pt_init_destroy(context, NULL, pt, 1);
2122d4afb5ceSopenharmony_ci			} LWS_FOR_EVERY_AVAILABLE_ROLE_END;
2123d4afb5ceSopenharmony_ci
2124d4afb5ceSopenharmony_ci		#if defined(LWS_WITH_CGI)
2125d4afb5ceSopenharmony_ci			lws_rops_func_fidx(&role_ops_cgi, LWS_ROPS_pt_init_destroy).
2126d4afb5ceSopenharmony_ci						pt_init_destroy(context, NULL, pt, 1);
2127d4afb5ceSopenharmony_ci		#endif
2128d4afb5ceSopenharmony_ci
2129d4afb5ceSopenharmony_ci			lws_pt_mutex_destroy(pt);
2130d4afb5ceSopenharmony_ci			assert(!pt->is_destroyed);
2131d4afb5ceSopenharmony_ci			pt->destroy_self = 0;
2132d4afb5ceSopenharmony_ci			pt->is_destroyed = 1;
2133d4afb5ceSopenharmony_ci
2134d4afb5ceSopenharmony_ci			lwsl_cx_info(context, "pt %d fully destroyed",
2135d4afb5ceSopenharmony_ci					(int)(pt - pt->context->pt));
2136d4afb5ceSopenharmony_ci		}
2137d4afb5ceSopenharmony_ci
2138d4afb5ceSopenharmony_ci		/*
2139d4afb5ceSopenharmony_ci		 * wsis are gone, pts are gone, vhosts are gone.
2140d4afb5ceSopenharmony_ci		 *
2141d4afb5ceSopenharmony_ci		 * clean up the context and things hanging off it
2142d4afb5ceSopenharmony_ci		 */
2143d4afb5ceSopenharmony_ci
2144d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS_JIT_TRUST)
2145d4afb5ceSopenharmony_ci		lws_cache_destroy(&context->trust_cache);
2146d4afb5ceSopenharmony_ci		lws_tls_jit_trust_inflight_destroy_all(context);
2147d4afb5ceSopenharmony_ci#endif
2148d4afb5ceSopenharmony_ci
2149d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
2150d4afb5ceSopenharmony_ci		lws_cache_destroy(&context->nsc);
2151d4afb5ceSopenharmony_ci		lws_cache_destroy(&context->l1);
2152d4afb5ceSopenharmony_ci#endif
2153d4afb5ceSopenharmony_ci
2154d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_SMD)
2155d4afb5ceSopenharmony_ci		_lws_smd_destroy(context);
2156d4afb5ceSopenharmony_ci#endif
2157d4afb5ceSopenharmony_ci
2158d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_ASYNC_DNS)
2159d4afb5ceSopenharmony_ci		lws_async_dns_deinit(&context->async_dns);
2160d4afb5ceSopenharmony_ci#endif
2161d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_DHCP_CLIENT)
2162d4afb5ceSopenharmony_ci		lws_dhcpc_remove(context, NULL);
2163d4afb5ceSopenharmony_ci#endif
2164d4afb5ceSopenharmony_ci
2165d4afb5ceSopenharmony_ci		if (context->pt[0].fds)
2166d4afb5ceSopenharmony_ci			lws_free_set_NULL(context->pt[0].fds);
2167d4afb5ceSopenharmony_ci#endif
2168d4afb5ceSopenharmony_ci		lws_context_deinit_ssl_library(context);
2169d4afb5ceSopenharmony_ci
2170d4afb5ceSopenharmony_ci#if defined(LWS_WITH_DETAILED_LATENCIES)
2171d4afb5ceSopenharmony_ci		if (context->latencies_fd != -1)
2172d4afb5ceSopenharmony_ci			compatible_close(context->latencies_fd);
2173d4afb5ceSopenharmony_ci#endif
2174d4afb5ceSopenharmony_ci
2175d4afb5ceSopenharmony_ci		for (n = 0; n < LWS_SYSBLOB_TYPE_COUNT; n++)
2176d4afb5ceSopenharmony_ci			lws_system_blob_destroy(
2177d4afb5ceSopenharmony_ci					lws_system_get_blob(context, (lws_system_blob_item_t)n, 0));
2178d4afb5ceSopenharmony_ci
2179d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK) && defined(LWS_WITH_SECURE_STREAMS) && \
2180d4afb5ceSopenharmony_ci	!defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
2181d4afb5ceSopenharmony_ci
2182d4afb5ceSopenharmony_ci		while (context->server_der_list) {
2183d4afb5ceSopenharmony_ci			struct lws_ss_x509 *x = context->server_der_list;
2184d4afb5ceSopenharmony_ci
2185d4afb5ceSopenharmony_ci			context->server_der_list = x->next;
2186d4afb5ceSopenharmony_ci			lws_free((void *)x->ca_der);
2187d4afb5ceSopenharmony_ci		}
2188d4afb5ceSopenharmony_ci
2189d4afb5ceSopenharmony_ci		if (context->ac_policy)
2190d4afb5ceSopenharmony_ci			lwsac_free(&context->ac_policy);
2191d4afb5ceSopenharmony_ci#endif
2192d4afb5ceSopenharmony_ci
2193d4afb5ceSopenharmony_ci		/*
2194d4afb5ceSopenharmony_ci		 * Context lock is about to go away
2195d4afb5ceSopenharmony_ci		 */
2196d4afb5ceSopenharmony_ci
2197d4afb5ceSopenharmony_ci		lws_context_unlock(context);
2198d4afb5ceSopenharmony_ci
2199d4afb5ceSopenharmony_ci#if LWS_MAX_SMP > 1
2200d4afb5ceSopenharmony_ci		lws_mutex_refcount_destroy(&context->mr);
2201d4afb5ceSopenharmony_ci#endif
2202d4afb5ceSopenharmony_ci
2203d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_NETWORK)
2204d4afb5ceSopenharmony_ci		lws_metrics_destroy(context);
2205d4afb5ceSopenharmony_ci#endif
2206d4afb5ceSopenharmony_ci
2207d4afb5ceSopenharmony_ci		if (context->external_baggage_free_on_destroy)
2208d4afb5ceSopenharmony_ci			free(context->external_baggage_free_on_destroy);
2209d4afb5ceSopenharmony_ci
2210d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS)
2211d4afb5ceSopenharmony_ci#if defined(LWS_AMAZON_RTOS)
2212d4afb5ceSopenharmony_ci		context->last_free_heap = xPortGetFreeHeapSize();
2213d4afb5ceSopenharmony_ci#else
2214d4afb5ceSopenharmony_ci		context->last_free_heap = esp_get_free_heap_size();
2215d4afb5ceSopenharmony_ci#endif
2216d4afb5ceSopenharmony_ci#endif
2217d4afb5ceSopenharmony_ci
2218d4afb5ceSopenharmony_ci#if defined(LWS_WITH_EVLIB_PLUGINS) && defined(LWS_WITH_EVENT_LIBS)
2219d4afb5ceSopenharmony_ci		if (context->evlib_plugin_list)
2220d4afb5ceSopenharmony_ci			lws_plugins_destroy(&context->evlib_plugin_list,
2221d4afb5ceSopenharmony_ci					    NULL, NULL);
2222d4afb5ceSopenharmony_ci#endif
2223d4afb5ceSopenharmony_ci
2224d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_FAULT_INJECTION)
2225d4afb5ceSopenharmony_ci		lws_fi_destroy(&context->fic);
2226d4afb5ceSopenharmony_ci#endif
2227d4afb5ceSopenharmony_ci
2228d4afb5ceSopenharmony_ci		lwsl_refcount_cx(context->log_cx, -1);
2229d4afb5ceSopenharmony_ci
2230d4afb5ceSopenharmony_ci		lws_free(context);
2231d4afb5ceSopenharmony_ci
2232d4afb5ceSopenharmony_ci		if (pcontext_finalize)
2233d4afb5ceSopenharmony_ci			*pcontext_finalize = NULL;
2234d4afb5ceSopenharmony_ci
2235d4afb5ceSopenharmony_ci		return;
2236d4afb5ceSopenharmony_ci	}
2237d4afb5ceSopenharmony_ci
2238d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
2239d4afb5ceSopenharmony_cibail:
2240d4afb5ceSopenharmony_ci#endif
2241d4afb5ceSopenharmony_ci	lwsl_cx_info(context, "leaving");
2242d4afb5ceSopenharmony_ci	context->inside_context_destroy = 0;
2243d4afb5ceSopenharmony_ci	lws_context_unlock(context);
2244d4afb5ceSopenharmony_ci}
2245d4afb5ceSopenharmony_ci
2246d4afb5ceSopenharmony_ciint
2247d4afb5ceSopenharmony_cilws_context_is_being_destroyed(struct lws_context *context)
2248d4afb5ceSopenharmony_ci{
2249d4afb5ceSopenharmony_ci	return !!context->being_destroyed;
2250d4afb5ceSopenharmony_ci}
2251d4afb5ceSopenharmony_ci
2252d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_STATE)
2253d4afb5ceSopenharmony_cistruct lws_context *
2254d4afb5ceSopenharmony_cilws_system_context_from_system_mgr(lws_state_manager_t *mgr)
2255d4afb5ceSopenharmony_ci{
2256d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
2257d4afb5ceSopenharmony_ci	return mgr->context;
2258d4afb5ceSopenharmony_ci#else
2259d4afb5ceSopenharmony_ci	return NULL;
2260d4afb5ceSopenharmony_ci#endif
2261d4afb5ceSopenharmony_ci}
2262d4afb5ceSopenharmony_ci#endif
2263d4afb5ceSopenharmony_ci
2264d4afb5ceSopenharmony_civoid
2265d4afb5ceSopenharmony_cilws_log_prepend_context(struct lws_log_cx *cx, void *obj, char **p, char *e)
2266d4afb5ceSopenharmony_ci{
2267d4afb5ceSopenharmony_ci	struct lws_context *lcx = (struct lws_context *)obj;
2268d4afb5ceSopenharmony_ci
2269d4afb5ceSopenharmony_ci	if (lcx->name)
2270d4afb5ceSopenharmony_ci		*p += lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), "%s: ",
2271d4afb5ceSopenharmony_ci				   lcx->name);
2272d4afb5ceSopenharmony_ci}
2273d4afb5ceSopenharmony_ci
2274d4afb5ceSopenharmony_cistruct lws_log_cx *
2275d4afb5ceSopenharmony_cilwsl_context_get_cx(struct lws_context *cx)
2276d4afb5ceSopenharmony_ci{
2277d4afb5ceSopenharmony_ci	if (!cx)
2278d4afb5ceSopenharmony_ci		return NULL;
2279d4afb5ceSopenharmony_ci
2280d4afb5ceSopenharmony_ci	return cx->log_cx;
2281d4afb5ceSopenharmony_ci}
2282