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