1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2021 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 void
28 lws_tls_session_vh_destroy(struct lws_vhost *vh);
29 
30 const struct lws_role_ops *available_roles[] = {
31 #if defined(LWS_ROLE_H2)
32 	&role_ops_h2,
33 #endif
34 #if defined(LWS_ROLE_H1)
35 	&role_ops_h1,
36 #endif
37 #if defined(LWS_ROLE_WS)
38 	&role_ops_ws,
39 #endif
40 #if defined(LWS_ROLE_DBUS)
41 	&role_ops_dbus,
42 #endif
43 #if defined(LWS_ROLE_RAW_PROXY)
44 	&role_ops_raw_proxy,
45 #endif
46 #if defined(LWS_ROLE_MQTT) && defined(LWS_WITH_CLIENT)
47 	&role_ops_mqtt,
48 #endif
49 #if defined(LWS_WITH_NETLINK)
50 	&role_ops_netlink,
51 #endif
52 	NULL
53 };
54 
55 #if defined(LWS_WITH_ABSTRACT)
56 const struct lws_protocols *available_abstract_protocols[] = {
57 #if defined(LWS_ROLE_RAW)
58 	&protocol_abs_client_raw_skt,
59 #endif
60 	NULL
61 };
62 #endif
63 
64 #if defined(LWS_WITH_SECURE_STREAMS)
65 const struct lws_protocols *available_secstream_protocols[] = {
66 #if defined(LWS_ROLE_H1)
67 	&protocol_secstream_h1,
68 #endif
69 #if defined(LWS_ROLE_H2)
70 	&protocol_secstream_h2,
71 #endif
72 #if defined(LWS_ROLE_WS)
73 	&protocol_secstream_ws,
74 #endif
75 #if defined(LWS_ROLE_MQTT)
76 	&protocol_secstream_mqtt,
77 #endif
78 	&protocol_secstream_raw,
79 	NULL
80 };
81 #endif
82 
83 static const char * const mount_protocols[] = {
84 	"http://",
85 	"https://",
86 	"file://",
87 	"cgi://",
88 	">http://",
89 	">https://",
90 	"callback://"
91 };
92 
93 const struct lws_role_ops *
lws_role_by_name(const char * name)94 lws_role_by_name(const char *name)
95 {
96 	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
97 		if (!strcmp(ar->name, name))
98 			return ar;
99 	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
100 
101 	if (!strcmp(name, role_ops_raw_skt.name))
102 		return &role_ops_raw_skt;
103 
104 #if defined(LWS_ROLE_RAW_FILE)
105 	if (!strcmp(name, role_ops_raw_file.name))
106 		return &role_ops_raw_file;
107 #endif
108 
109 	return NULL;
110 }
111 
112 int
lws_role_call_alpn_negotiated(struct lws * wsi,const char * alpn)113 lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn)
114 {
115 #if defined(LWS_WITH_TLS)
116 	if (!alpn)
117 		return 0;
118 
119 #if !defined(LWS_ESP_PLATFORM)
120 	lwsl_info("%s: '%s'\n", __func__, alpn);
121 #endif
122 
123 	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
124 		if (ar->alpn && !strcmp(ar->alpn, alpn) &&
125 		    lws_rops_fidx(ar, LWS_ROPS_alpn_negotiated)) {
126 #if defined(LWS_WITH_SERVER)
127 			lws_metrics_tag_wsi_add(wsi, "upg", ar->name);
128 #endif
129 			return (lws_rops_func_fidx(ar, LWS_ROPS_alpn_negotiated)).
130 						   alpn_negotiated(wsi, alpn);
131 		}
132 	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
133 #endif
134 	return 0;
135 }
136 
137 int
lws_role_call_adoption_bind(struct lws * wsi,int type,const char * prot)138 lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot)
139 {
140 	int n;
141 
142 	/*
143 	 * if the vhost is told to bind accepted sockets to a given role,
144 	 * then look it up by name and try to bind to the specific role.
145 	 */
146 	if (lws_check_opt(wsi->a.vhost->options,
147 			  LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG) &&
148 	    wsi->a.vhost->listen_accept_role) {
149 		const struct lws_role_ops *role =
150 			lws_role_by_name(wsi->a.vhost->listen_accept_role);
151 
152 		if (!prot)
153 			prot = wsi->a.vhost->listen_accept_protocol;
154 
155 		if (!role)
156 			lwsl_err("%s: can't find role '%s'\n", __func__,
157 				  wsi->a.vhost->listen_accept_role);
158 
159 		if (!strcmp(wsi->a.vhost->listen_accept_role, "raw-proxy"))
160 			type |= LWS_ADOPT_FLAG_RAW_PROXY;
161 
162 		if (role && lws_rops_fidx(role, LWS_ROPS_adoption_bind)) {
163 			n = (lws_rops_func_fidx(role, LWS_ROPS_adoption_bind)).
164 						adoption_bind(wsi, type, prot);
165 			if (n < 0)
166 				return -1;
167 			if (n) /* did the bind */
168 				return 0;
169 		}
170 
171 		if (type & _LWS_ADOPT_FINISH) {
172 			lwsl_debug("%s: leaving bound to role %s\n", __func__,
173 				   wsi->role_ops->name);
174 			return 0;
175 		}
176 
177 		lwsl_warn("%s: adoption bind to role '%s', "
178 			  "protocol '%s', type 0x%x, failed\n", __func__,
179 			  wsi->a.vhost->listen_accept_role, prot, type);
180 	}
181 
182 	/*
183 	 * Otherwise ask each of the roles in order of preference if they
184 	 * want to bind to this accepted socket
185 	 */
186 
187 	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
188 		if (lws_rops_fidx(ar, LWS_ROPS_adoption_bind) &&
189 		    (lws_rops_func_fidx(ar, LWS_ROPS_adoption_bind)).
190 					    adoption_bind(wsi, type, prot))
191 			return 0;
192 	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
193 
194 	/* fall back to raw socket role if, eg, h1 not configured */
195 
196 	if (lws_rops_fidx(&role_ops_raw_skt, LWS_ROPS_adoption_bind) &&
197 	    (lws_rops_func_fidx(&role_ops_raw_skt, LWS_ROPS_adoption_bind)).
198 				    adoption_bind(wsi, type, prot))
199 		return 0;
200 
201 #if defined(LWS_ROLE_RAW_FILE)
202 
203 	lwsl_notice("%s: falling back to raw file role bind\n", __func__);
204 
205 	/* fall back to raw file role if, eg, h1 not configured */
206 
207 	if (lws_rops_fidx(&role_ops_raw_file, LWS_ROPS_adoption_bind) &&
208 	    (lws_rops_func_fidx(&role_ops_raw_file, LWS_ROPS_adoption_bind)).
209 				    adoption_bind(wsi, type, prot))
210 		return 0;
211 #endif
212 
213 	return 1;
214 }
215 
216 #if defined(LWS_WITH_CLIENT)
217 int
lws_role_call_client_bind(struct lws * wsi,const struct lws_client_connect_info * i)218 lws_role_call_client_bind(struct lws *wsi,
219 			  const struct lws_client_connect_info *i)
220 {
221 	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
222 		if (lws_rops_fidx(ar, LWS_ROPS_client_bind)) {
223 			int m = (lws_rops_func_fidx(ar, LWS_ROPS_client_bind)).
224 							client_bind(wsi, i);
225 
226 			if (m < 0)
227 				return m;
228 			if (m)
229 				return 0;
230 		}
231 	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
232 
233 	/* fall back to raw socket role if, eg, h1 not configured */
234 
235 	if (lws_rops_fidx(&role_ops_raw_skt, LWS_ROPS_client_bind) &&
236 	    (lws_rops_func_fidx(&role_ops_raw_skt, LWS_ROPS_client_bind)).
237 					client_bind(wsi, i))
238 		return 0;
239 
240 	return 1;
241 }
242 #endif
243 
244 void *
lws_protocol_vh_priv_zalloc(struct lws_vhost * vhost,const struct lws_protocols * prot,int size)245 lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost,
246 			    const struct lws_protocols *prot, int size)
247 {
248 	int n = 0;
249 
250 	if (!vhost || !prot)
251 		return NULL;
252 
253 	/* allocate the vh priv array only on demand */
254 	if (!vhost->protocol_vh_privs) {
255 		vhost->protocol_vh_privs = (void **)lws_zalloc(
256 				(size_t)vhost->count_protocols * sizeof(void *),
257 				"protocol_vh_privs");
258 		if (!vhost->protocol_vh_privs)
259 			return NULL;
260 	}
261 
262 	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
263 		n++;
264 
265 	if (n == vhost->count_protocols) {
266 		n = 0;
267 		while (n < vhost->count_protocols &&
268 		       strcmp(vhost->protocols[n].name, prot->name))
269 			n++;
270 
271 		if (n == vhost->count_protocols)
272 			return NULL;
273 	}
274 
275 	vhost->protocol_vh_privs[n] = lws_zalloc((size_t)size, "vh priv");
276 	return vhost->protocol_vh_privs[n];
277 }
278 
279 void *
lws_protocol_vh_priv_get(struct lws_vhost * vhost,const struct lws_protocols * prot)280 lws_protocol_vh_priv_get(struct lws_vhost *vhost,
281 			 const struct lws_protocols *prot)
282 {
283 	int n = 0;
284 
285 	if (!vhost || !vhost->protocol_vh_privs || !prot)
286 		return NULL;
287 
288 	while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
289 		n++;
290 
291 	if (n == vhost->count_protocols) {
292 		n = 0;
293 		while (n < vhost->count_protocols &&
294 		       strcmp(vhost->protocols[n].name, prot->name))
295 			n++;
296 
297 		if (n == vhost->count_protocols) {
298 			lwsl_err("%s: unknown protocol %p\n", __func__, prot);
299 			return NULL;
300 		}
301 	}
302 
303 	return vhost->protocol_vh_privs[n];
304 }
305 
306 void *
lws_vhd_find_by_pvo(struct lws_context * cx,const char * protname,const char * pvo_name,const char * pvo_value)307 lws_vhd_find_by_pvo(struct lws_context *cx, const char *protname,
308 		    const char *pvo_name, const char *pvo_value)
309 {
310 	struct lws_vhost *vh;
311 	int n;
312 
313 	/* let's go through all the vhosts */
314 
315 	vh = cx->vhost_list;
316 	while (vh) {
317 
318 		if (vh->protocol_vh_privs) {
319 
320 		for (n = 0; n < vh->count_protocols; n++) {
321 			const struct lws_protocol_vhost_options *pv;
322 
323 			if (strcmp(vh->protocols[n].name, protname))
324 				continue;
325 
326 			/* this vh has an instance of the required protocol */
327 
328 			pv = lws_pvo_search(vh->pvo, protname);
329 			if (!pv)
330 				continue;
331 
332 			pv = lws_pvo_search(pv->options, pvo_name);
333 			if (!pv)
334 				continue;
335 
336 			/* ... he also has a pvo of the right name... */
337 			if (!strcmp(pv->value, pvo_value))
338 				/*
339 				 * ... yes, the pvo has the right value too,
340 				 * return a pointer to this vhost-protocol
341 				 * private alloc (ie, its "vhd")
342 				 */
343 				return vh->protocol_vh_privs[n];
344 		}
345 		} else
346 			lwsl_notice("%s: no privs yet on %s\n", __func__, lws_vh_tag(vh));
347 		vh = vh->vhost_next;
348 	}
349 
350 	return NULL;
351 }
352 
353 const struct lws_protocol_vhost_options *
lws_vhost_protocol_options(struct lws_vhost * vh,const char * name)354 lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
355 {
356 	const struct lws_protocol_vhost_options *pvo = vh->pvo;
357 
358 	if (!name)
359 		return NULL;
360 
361 	while (pvo) {
362 		if (!strcmp(pvo->name, name))
363 			return pvo;
364 		pvo = pvo->next;
365 	}
366 
367 	return NULL;
368 }
369 
370 int
lws_protocol_init_vhost(struct lws_vhost * vh,int * any)371 lws_protocol_init_vhost(struct lws_vhost *vh, int *any)
372 {
373 	const struct lws_protocol_vhost_options *pvo, *pvo1;
374 	lws_fakewsi_def_plwsa(&vh->context->pt[0]);
375 	int n;
376 
377 	lws_fakewsi_prep_plwsa_ctx(vh->context);
378 
379 	plwsa->vhost = vh;
380 
381 	/* initialize supported protocols on this vhost */
382 
383 	for (n = 0; n < vh->count_protocols; n++) {
384 		plwsa->protocol = &vh->protocols[n];
385 		if (!vh->protocols[n].name)
386 			continue;
387 		pvo = lws_vhost_protocol_options(vh, vh->protocols[n].name);
388 		if (pvo) {
389 			/*
390 			 * linked list of options specific to
391 			 * vh + protocol
392 			 */
393 			pvo1 = pvo;
394 			pvo = pvo1->options;
395 
396 			while (pvo) {
397 				lwsl_debug(
398 					"    vhost \"%s\", "
399 					"protocol \"%s\", "
400 					"option \"%s\"\n",
401 						vh->name,
402 						vh->protocols[n].name,
403 						pvo->name);
404 
405 				if (!strcmp(pvo->name, "default")) {
406 					lwsl_info("Setting default "
407 					   "protocol for vh %s to %s\n",
408 					   vh->name,
409 					   vh->protocols[n].name);
410 					vh->default_protocol_index = (unsigned char)n;
411 				}
412 				if (!strcmp(pvo->name, "raw")) {
413 					lwsl_info("Setting raw "
414 					   "protocol for vh %s to %s\n",
415 					   vh->name,
416 					   vh->protocols[n].name);
417 					vh->raw_protocol_index = (unsigned char)n;
418 				}
419 				pvo = pvo->next;
420 			}
421 		} else
422 			lwsl_debug("%s: not instantiating %s.%s\n",
423 				   __func__, vh->name, vh->protocols[n].name);
424 
425 #if defined(LWS_WITH_TLS)
426 		if (any)
427 			*any |= !!vh->tls.ssl_ctx;
428 #endif
429 
430 		plwsa->vhost = vh;
431 		plwsa->protocol = &vh->protocols[n];
432 
433 		pvo = lws_vhost_protocol_options(vh, vh->protocols[n].name);
434 
435 		/*
436 		 * inform all the protocols that they are doing their
437 		 * one-time initialization if they want to.
438 		 *
439 		 * NOTE the fakewsi is garbage, except the key pointers that are
440 		 * prepared in case the protocol handler wants to touch them
441 		 */
442 
443 		if (pvo || !vh->pvo) {
444 			lwsl_info("%s: init %s.%s\n", __func__, vh->name,
445 					vh->protocols[n].name);
446 			if (vh->protocols[n].callback((struct lws *)plwsa,
447 				LWS_CALLBACK_PROTOCOL_INIT, NULL,
448 				(void *)(pvo ? pvo->options : NULL), 0)) {
449 				if (vh->protocol_vh_privs && vh->protocol_vh_privs[n]) {
450 					lws_free(vh->protocol_vh_privs[n]);
451 					vh->protocol_vh_privs[n] = NULL;
452 				}
453 			lwsl_err("%s: protocol %s failed init\n",
454 				 __func__, vh->protocols[n].name);
455 
456 				return 1;
457 			}
458 		}
459 	}
460 
461 	vh->created_vhost_protocols = 1;
462 
463 	return 0;
464 }
465 
466 /*
467  * inform every vhost that hasn't already done it, that
468  * his protocols are initializing
469  */
470 int
lws_protocol_init(struct lws_context * context)471 lws_protocol_init(struct lws_context *context)
472 {
473 	struct lws_vhost *vh = context->vhost_list;
474 	int any = 0, r = 0;
475 
476 	if (context->doing_protocol_init)
477 		return 0;
478 
479 	context->doing_protocol_init = 1;
480 
481 	lwsl_info("%s\n", __func__);
482 
483 	while (vh) {
484 
485 		/* only do the protocol init once for a given vhost */
486 		if (vh->created_vhost_protocols ||
487 		    (lws_check_opt(vh->options, LWS_SERVER_OPTION_SKIP_PROTOCOL_INIT)))
488 			goto next;
489 
490 		if (lws_protocol_init_vhost(vh, &any)) {
491 			lwsl_warn("%s: init vhost %s failed\n", __func__, vh->name);
492 			r = -1;
493 		}
494 next:
495 		vh = vh->vhost_next;
496 	}
497 
498 	context->doing_protocol_init = 0;
499 
500 	if (r)
501 		lwsl_warn("%s: some protocols did not init\n", __func__);
502 
503 	if (!context->protocol_init_done) {
504 
505 		context->protocol_init_done = 1;
506 		lws_finalize_startup(context);
507 
508 		return 0;
509 	}
510 
511 #if defined(LWS_WITH_SERVER)
512 	if (any) {
513 		lws_tls_check_all_cert_lifetimes(context);
514 	}
515 #endif
516 
517 	return 0;
518 }
519 
520 
521 /* list of supported protocols and callbacks */
522 
523 static const struct lws_protocols protocols_dummy[] = {
524 	/* first protocol must always be HTTP handler */
525 
526 	{
527 		"http-only",			/* name */
528 		lws_callback_http_dummy,	/* callback */
529 		0,				/* per_session_data_size */
530 		0,				/* rx_buffer_size */
531 		0,				/* id */
532 		NULL,				/* user */
533 		0				/* tx_packet_size */
534 	},
535 	/*
536 	 * the other protocols are provided by lws plugins
537 	 */
538 	{ NULL, NULL, 0, 0, 0, NULL, 0} /* terminator */
539 };
540 
541 
542 #ifdef LWS_PLAT_OPTEE
543 #undef LWS_HAVE_GETENV
544 #endif
545 
546 struct lws_vhost *
lws_create_vhost(struct lws_context * context,const struct lws_context_creation_info * info)547 lws_create_vhost(struct lws_context *context,
548 		 const struct lws_context_creation_info *info)
549 {
550 	struct lws_vhost *vh, **vh1 = &context->vhost_list;
551 	const struct lws_http_mount *mounts;
552 	const struct lws_protocols *pcols = info->protocols;
553 #ifdef LWS_WITH_PLUGINS
554 	struct lws_plugin *plugin = context->plugin_list;
555 #endif
556 	struct lws_protocols *lwsp;
557 	int m, f = !info->pvo, fx = 0, abs_pcol_count = 0, sec_pcol_count = 0;
558 	char buf[96];
559 	char *p;
560 #if defined(LWS_WITH_SYS_ASYNC_DNS)
561 	extern struct lws_protocols lws_async_dns_protocol;
562 #endif
563 	int n;
564 
565 	if (lws_fi(&info->fic, "vh_create_oom"))
566 		vh = NULL;
567 	else
568 		vh = lws_zalloc(sizeof(*vh)
569 #if defined(LWS_WITH_EVENT_LIBS)
570 			+ context->event_loop_ops->evlib_size_vh
571 #endif
572 			, __func__);
573 	if (!vh)
574 		goto early_bail;
575 
576 #if defined(LWS_WITH_EVENT_LIBS)
577 	vh->evlib_vh = (void *)&vh[1];
578 #endif
579 
580 #if LWS_MAX_SMP > 1
581 	lws_mutex_refcount_init(&vh->mr);
582 #endif
583 
584 	if (!pcols && !info->pprotocols)
585 		pcols = &protocols_dummy[0];
586 
587 	vh->context = context;
588 	if (!info->vhost_name)
589 		vh->name = "default";
590 	else
591 		vh->name = info->vhost_name;
592 	{
593 		char *end = buf + sizeof(buf) - 1;
594 		p = buf;
595 
596 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s", vh->name);
597 		if (info->iface)
598 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "|%s", info->iface);
599 		if (info->port && !(info->port & 0xffff))
600 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "|%u", info->port);
601 	}
602 
603 	__lws_lc_tag(&context->lcg[LWSLCG_VHOST], &vh->lc, "%s|%s|%d", buf,
604 			info->iface ? info->iface : "", info->port);
605 
606 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
607 	vh->fic.name = "vh";
608 	if (info->fic.fi_owner.count)
609 		/*
610 		 * This moves all the lws_fi_t from info->fi to the vhost fi,
611 		 * leaving it empty
612 		 */
613 		lws_fi_import(&vh->fic, &info->fic);
614 
615 	lws_fi_inherit_copy(&vh->fic, &context->fic, "vh", vh->name);
616 	if (lws_fi(&vh->fic, "vh_create_oom"))
617 		goto bail;
618 #endif
619 
620 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
621 	vh->http.error_document_404 = info->error_document_404;
622 #endif
623 
624 	if (lws_check_opt(info->options, LWS_SERVER_OPTION_ONLY_RAW))
625 		lwsl_info("%s set to only support RAW\n", vh->name);
626 
627 	vh->iface = info->iface;
628 #if !defined(LWS_PLAT_FREERTOS) && !defined(OPTEE_TA) && !defined(WIN32)
629 	vh->bind_iface = info->bind_iface;
630 #endif
631 #if defined(LWS_WITH_CLIENT)
632 	if (info->connect_timeout_secs)
633 		vh->connect_timeout_secs = (int)info->connect_timeout_secs;
634 	else
635 		vh->connect_timeout_secs = 20;
636 #endif
637 	/* apply the context default lws_retry */
638 
639 	if (info->retry_and_idle_policy)
640 		vh->retry_policy = info->retry_and_idle_policy;
641 	else
642 		vh->retry_policy = &context->default_retry;
643 
644 	/*
645 	 * let's figure out how many protocols the user is handing us, using the
646 	 * old or new way depending on what he gave us
647 	 */
648 
649 	if (!pcols)
650 		for (vh->count_protocols = 0;
651 			info->pprotocols[vh->count_protocols];
652 			vh->count_protocols++)
653 			;
654 	else
655 		for (vh->count_protocols = 0;
656 			pcols[vh->count_protocols].callback;
657 			vh->count_protocols++)
658 				;
659 
660 	vh->options = info->options;
661 	vh->pvo = info->pvo;
662 	vh->headers = info->headers;
663 	vh->user = info->user;
664 	vh->finalize = info->finalize;
665 	vh->finalize_arg = info->finalize_arg;
666 	vh->listen_accept_role = info->listen_accept_role;
667 	vh->listen_accept_protocol = info->listen_accept_protocol;
668 	vh->unix_socket_perms = info->unix_socket_perms;
669 
670 	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
671 	if (lws_rops_fidx(ar, LWS_ROPS_init_vhost) &&
672 	    (lws_rops_func_fidx(ar, LWS_ROPS_init_vhost)).init_vhost(vh, info))
673 		return NULL;
674 	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
675 
676 
677 	if (info->keepalive_timeout)
678 		vh->keepalive_timeout = info->keepalive_timeout;
679 	else
680 		vh->keepalive_timeout = 5;
681 
682 	if (info->timeout_secs_ah_idle)
683 		vh->timeout_secs_ah_idle = (int)info->timeout_secs_ah_idle;
684 	else
685 		vh->timeout_secs_ah_idle = 10;
686 
687 #if defined(LWS_WITH_TLS)
688 
689 	vh->tls.alpn = info->alpn;
690 	vh->tls.ssl_info_event_mask = info->ssl_info_event_mask;
691 
692 	if (info->ecdh_curve)
693 		lws_strncpy(vh->tls.ecdh_curve, info->ecdh_curve,
694 			    sizeof(vh->tls.ecdh_curve));
695 
696 	/* carefully allocate and take a copy of cert + key paths if present */
697 	n = 0;
698 	if (info->ssl_cert_filepath)
699 		n += (int)strlen(info->ssl_cert_filepath) + 1;
700 	if (info->ssl_private_key_filepath)
701 		n += (int)strlen(info->ssl_private_key_filepath) + 1;
702 
703 	if (n) {
704 		vh->tls.key_path = vh->tls.alloc_cert_path =
705 					lws_malloc((unsigned int)n, "vh paths");
706 		if (info->ssl_cert_filepath) {
707 			n = (int)strlen(info->ssl_cert_filepath) + 1;
708 			memcpy(vh->tls.alloc_cert_path,
709 			       info->ssl_cert_filepath, (unsigned int)n);
710 			vh->tls.key_path += n;
711 		}
712 		if (info->ssl_private_key_filepath)
713 			memcpy(vh->tls.key_path, info->ssl_private_key_filepath,
714 			       strlen(info->ssl_private_key_filepath) + 1);
715 	}
716 #endif
717 
718 #if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_ROLE_WS)
719 	fx = 1;
720 #endif
721 #if defined(LWS_WITH_ABSTRACT)
722 	abs_pcol_count = (int)LWS_ARRAY_SIZE(available_abstract_protocols) - 1;
723 #endif
724 #if defined(LWS_WITH_SECURE_STREAMS)
725 	sec_pcol_count = (int)LWS_ARRAY_SIZE(available_secstream_protocols) - 1;
726 #endif
727 
728 	/*
729 	 * give the vhost a unified list of protocols including:
730 	 *
731 	 * - internal, async_dns if enabled (first vhost only)
732 	 * - internal, abstracted ones
733 	 * - the ones that came from plugins
734 	 * - his user protocols
735 	 */
736 
737 	if (lws_fi(&vh->fic, "vh_create_pcols_oom"))
738 		lwsp = NULL;
739 	else
740 		lwsp = lws_zalloc(sizeof(struct lws_protocols) *
741 				((unsigned int)vh->count_protocols +
742 				   (unsigned int)abs_pcol_count +
743 				   (unsigned int)sec_pcol_count +
744 				   (unsigned int)context->plugin_protocol_count +
745 				   (unsigned int)fx + 1), "vh plugin table");
746 	if (!lwsp) {
747 		lwsl_err("OOM\n");
748 		goto bail;
749 	}
750 
751 	/*
752 	 * 1: user protocols (from pprotocols or protocols)
753 	 */
754 
755 	m = vh->count_protocols;
756 	if (!pcols) {
757 		for (n = 0; n < m; n++)
758 			memcpy(&lwsp[n], info->pprotocols[n], sizeof(lwsp[0]));
759 	} else
760 		memcpy(lwsp, pcols, sizeof(struct lws_protocols) * (unsigned int)m);
761 
762 	/*
763 	 * 2: abstract protocols
764 	 */
765 #if defined(LWS_WITH_ABSTRACT)
766 	for (n = 0; n < abs_pcol_count; n++) {
767 		memcpy(&lwsp[m++], available_abstract_protocols[n],
768 		       sizeof(*lwsp));
769 		vh->count_protocols++;
770 	}
771 #endif
772 	/*
773 	 * 3: async dns protocol (first vhost only)
774 	 */
775 #if defined(LWS_WITH_SYS_ASYNC_DNS)
776 	if (!context->vhost_list) {
777 		memcpy(&lwsp[m++], &lws_async_dns_protocol,
778 		       sizeof(struct lws_protocols));
779 		vh->count_protocols++;
780 	}
781 #endif
782 
783 #if defined(LWS_WITH_SECURE_STREAMS)
784 	for (n = 0; n < sec_pcol_count; n++) {
785 		memcpy(&lwsp[m++], available_secstream_protocols[n],
786 		       sizeof(*lwsp));
787 		vh->count_protocols++;
788 	}
789 #endif
790 
791 	/*
792 	 * 3: For compatibility, all protocols enabled on vhost if only
793 	 * the default vhost exists.  Otherwise only vhosts who ask
794 	 * for a protocol get it enabled.
795 	 */
796 
797 	if (context->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
798 		f = 0;
799 	(void)f;
800 #ifdef LWS_WITH_PLUGINS
801 	if (plugin) {
802 		while (plugin) {
803 			const lws_plugin_protocol_t *plpr =
804 				(const lws_plugin_protocol_t *)plugin->hdr;
805 
806 			for (n = 0; n < plpr->count_protocols; n++) {
807 				/*
808 				 * for compatibility's sake, no pvo implies
809 				 * allow all protocols
810 				 */
811 				if (f || lws_vhost_protocol_options(vh,
812 						plpr->protocols[n].name)) {
813 					memcpy(&lwsp[m],
814 					       &plpr->protocols[n],
815 					       sizeof(struct lws_protocols));
816 					m++;
817 					vh->count_protocols++;
818 				}
819 			}
820 			plugin = plugin->list;
821 		}
822 	}
823 #endif
824 
825 #if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_ROLE_WS)
826 	memcpy(&lwsp[m++], &lws_ws_proxy, sizeof(*lwsp));
827 	vh->count_protocols++;
828 #endif
829 
830 	vh->protocols = lwsp;
831 	vh->allocated_vhost_protocols = 1;
832 
833 	vh->same_vh_protocol_owner = (struct lws_dll2_owner *)
834 			lws_zalloc(sizeof(struct lws_dll2_owner) *
835 				   (unsigned int)vh->count_protocols, "same vh list");
836 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
837 	vh->http.mount_list = info->mounts;
838 #endif
839 
840 #if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_SERVER)
841 	{
842 		char *end = buf + sizeof(buf) - 1;
843 		p = buf;
844 
845 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "vh.%s", vh->name);
846 		if (info->iface)
847 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), ".%s", info->iface);
848 		if (info->port && !(info->port & 0xffff))
849 			p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), ".%u", info->port);
850 		p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), ".rx");
851 		vh->mt_traffic_rx = lws_metric_create(context, 0, buf);
852 		p[-2] = 't';
853 		vh->mt_traffic_tx = lws_metric_create(context, 0, buf);
854 	}
855 #endif
856 
857 #ifdef LWS_WITH_UNIX_SOCK
858 	if (LWS_UNIX_SOCK_ENABLED(vh)) {
859 		lwsl_info("Creating Vhost '%s' path \"%s\", %d protocols\n",
860 				vh->name, vh->iface, vh->count_protocols);
861 	} else
862 #endif
863 	{
864 		switch(info->port) {
865 		case CONTEXT_PORT_NO_LISTEN:
866 			strcpy(buf, "(serving disabled)");
867 			break;
868 		case CONTEXT_PORT_NO_LISTEN_SERVER:
869 			strcpy(buf, "(no listener)");
870 			break;
871 		default:
872 			lws_snprintf(buf, sizeof(buf), "port %u", info->port);
873 			break;
874 		}
875 		lwsl_info("Creating Vhost '%s' %s, %d protocols, IPv6 %s\n",
876 			    vh->name, buf, vh->count_protocols,
877 			    LWS_IPV6_ENABLED(vh) ? "on" : "off");
878 	}
879 	mounts = info->mounts;
880 	while (mounts) {
881 		(void)mount_protocols[0];
882 		lwsl_info("   mounting %s%s to %s\n",
883 			  mount_protocols[mounts->origin_protocol],
884 			  mounts->origin ? mounts->origin : "none",
885 			  mounts->mountpoint);
886 
887 		mounts = mounts->mount_next;
888 	}
889 
890 	vh->listen_port = info->port;
891 
892 #if defined(LWS_WITH_SOCKS5)
893 	vh->socks_proxy_port = 0;
894 	vh->socks_proxy_address[0] = '\0';
895 #endif
896 
897 #if defined(LWS_WITH_CLIENT) && defined(LWS_CLIENT_HTTP_PROXYING)
898 	/* either use proxy from info, or try get it from env var */
899 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
900 	vh->http.http_proxy_port = 0;
901 	vh->http.http_proxy_address[0] = '\0';
902 	/* http proxy */
903 	if (info->http_proxy_address) {
904 		/* override for backwards compatibility */
905 		if (info->http_proxy_port)
906 			vh->http.http_proxy_port = info->http_proxy_port;
907 		lws_set_proxy(vh, info->http_proxy_address);
908 	} else
909 #endif
910 	{
911 #ifdef LWS_HAVE_GETENV
912 #if defined(__COVERITY__)
913 		p = NULL;
914 #else
915 		p = getenv("http_proxy"); /* coverity[tainted_scalar] */
916 		if (p) {
917 			lws_strncpy(buf, p, sizeof(buf));
918 			lws_set_proxy(vh, buf);
919 		}
920 #endif
921 #endif
922 	}
923 #endif
924 #if defined(LWS_WITH_SOCKS5)
925 	lws_socks5c_ads_server(vh, info);
926 #endif
927 
928 	vh->ka_time = info->ka_time;
929 	vh->ka_interval = info->ka_interval;
930 	vh->ka_probes = info->ka_probes;
931 
932 	if (vh->options & LWS_SERVER_OPTION_STS)
933 		lwsl_notice("   STS enabled\n");
934 
935 #ifdef LWS_WITH_ACCESS_LOG
936 	if (info->log_filepath) {
937 		if (lws_fi(&vh->fic, "vh_create_access_log_open_fail"))
938 			vh->log_fd = (int)LWS_INVALID_FILE;
939 		else
940 			vh->log_fd = lws_open(info->log_filepath,
941 				  O_CREAT | O_APPEND | O_RDWR, 0600);
942 		if (vh->log_fd == (int)LWS_INVALID_FILE) {
943 			lwsl_err("unable to open log filepath %s\n",
944 				 info->log_filepath);
945 			goto bail;
946 		}
947 #ifndef WIN32
948 		if (context->uid != (uid_t)-1)
949 			if (chown(info->log_filepath, context->uid,
950 				  context->gid) == -1)
951 				lwsl_err("unable to chown log file %s\n",
952 						info->log_filepath);
953 #endif
954 	} else
955 		vh->log_fd = (int)LWS_INVALID_FILE;
956 #endif
957 	if (lws_fi(&vh->fic, "vh_create_ssl_srv") ||
958 	    lws_context_init_server_ssl(info, vh)) {
959 		lwsl_err("%s: lws_context_init_server_ssl failed\n", __func__);
960 		goto bail1;
961 	}
962 	if (lws_fi(&vh->fic, "vh_create_ssl_cli") ||
963 	    lws_context_init_client_ssl(info, vh)) {
964 		lwsl_err("%s: lws_context_init_client_ssl failed\n", __func__);
965 		goto bail1;
966 	}
967 #if defined(LWS_WITH_SERVER)
968 	lws_context_lock(context, __func__);
969 	if (lws_fi(&vh->fic, "vh_create_srv_init"))
970 		n = -1;
971 	else
972 		n = _lws_vhost_init_server(info, vh);
973 	lws_context_unlock(context);
974 	if (n < 0) {
975 		lwsl_err("init server failed\n");
976 		goto bail1;
977 	}
978 #endif
979 
980 #if defined(LWS_WITH_SYS_ASYNC_DNS)
981 	n = !!context->vhost_list;
982 #endif
983 
984 	while (1) {
985 		if (!(*vh1)) {
986 			*vh1 = vh;
987 			break;
988 		}
989 		vh1 = &(*vh1)->vhost_next;
990 	};
991 
992 #if defined(LWS_WITH_SYS_ASYNC_DNS)
993 	if (!n)
994 		lws_async_dns_init(context);
995 #endif
996 
997 	/* for the case we are adding a vhost much later, after server init */
998 
999 	if (context->protocol_init_done)
1000 		if (lws_fi(&vh->fic, "vh_create_protocol_init") ||
1001 		    lws_protocol_init(context)) {
1002 			lwsl_err("%s: lws_protocol_init failed\n", __func__);
1003 			goto bail1;
1004 		}
1005 
1006 	return vh;
1007 
1008 bail1:
1009 	lws_vhost_destroy(vh);
1010 
1011 	return NULL;
1012 
1013 bail:
1014 	__lws_lc_untag(&vh->lc);
1015 	lws_fi_destroy(&vh->fic);
1016 	lws_free(vh);
1017 
1018 early_bail:
1019 	lws_fi_destroy(&info->fic);
1020 
1021 	return NULL;
1022 }
1023 
1024 int
lws_init_vhost_client_ssl(const struct lws_context_creation_info * info,struct lws_vhost * vhost)1025 lws_init_vhost_client_ssl(const struct lws_context_creation_info *info,
1026 			  struct lws_vhost *vhost)
1027 {
1028 	struct lws_context_creation_info i;
1029 
1030 	memcpy(&i, info, sizeof(i));
1031 	i.port = CONTEXT_PORT_NO_LISTEN;
1032 
1033 	return lws_context_init_client_ssl(&i, vhost);
1034 }
1035 
1036 void
lws_cancel_service_pt(struct lws * wsi)1037 lws_cancel_service_pt(struct lws *wsi)
1038 {
1039 	lws_plat_pipe_signal(wsi->a.context, wsi->tsi);
1040 }
1041 
1042 void
lws_cancel_service(struct lws_context * context)1043 lws_cancel_service(struct lws_context *context)
1044 {
1045 	struct lws_context_per_thread *pt = &context->pt[0];
1046 	short m;
1047 
1048 	if (context->service_no_longer_possible)
1049 		return;
1050 
1051 	lwsl_debug("%s\n", __func__);
1052 
1053 	for (m = 0; m < context->count_threads; m++) {
1054 		if (pt->pipe_wsi)
1055 			lws_plat_pipe_signal(pt->context, m);
1056 		pt++;
1057 	}
1058 }
1059 
1060 int
__lws_create_event_pipes(struct lws_context * context)1061 __lws_create_event_pipes(struct lws_context *context)
1062 {
1063 	struct lws_context_per_thread *pt;
1064 	struct lws *wsi;
1065 	int n;
1066 
1067 	/*
1068 	 * Create the pt event pipes... these are unique in that they are
1069 	 * not bound to a vhost or protocol (both are NULL)
1070 	 */
1071 
1072 #if LWS_MAX_SMP > 1
1073 	for (n = 0; n < context->count_threads; n++) {
1074 #else
1075 	n = 0;
1076 	{
1077 #endif
1078 		pt = &context->pt[n];
1079 
1080 		if (pt->pipe_wsi)
1081 			return 0;
1082 
1083 		wsi = __lws_wsi_create_with_role(context, n, &role_ops_pipe);
1084 		if (!wsi)
1085 			return 1;
1086 
1087 		__lws_lc_tag(&context->lcg[LWSLCG_WSI], &wsi->lc, "pipe");
1088 
1089 		wsi->event_pipe = 1;
1090 		pt->pipe_wsi = wsi;
1091 
1092 		if (!lws_plat_pipe_create(wsi)) {
1093 			/*
1094 			 * platform code returns 0 if it actually created pipes
1095 			 * and initialized pt->dummy_pipe_fds[].  If it used
1096 			 * some other mechanism outside of signaling in the
1097 			 * normal event loop, we skip treating the pipe as
1098 			 * related to dummy_pipe_fds[], adding it to the fds,
1099 			 * etc.
1100 			 */
1101 
1102 			wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0];
1103 			lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd);
1104 
1105 			if (lws_wsi_inject_to_loop(pt, wsi))
1106 					goto bail;
1107 		}
1108 	}
1109 
1110 	return 0;
1111 
1112 bail:
1113 
1114 	return 1;
1115 }
1116 
1117 void
1118 lws_destroy_event_pipe(struct lws *wsi)
1119 {
1120 	int n;
1121 
1122 	lwsl_info("%s\n", __func__);
1123 
1124 	n = lws_wsi_extract_from_loop(wsi);
1125 	lws_plat_pipe_close(wsi);
1126 	if (!n)
1127 		lws_free(wsi);
1128 }
1129 
1130 /*
1131  * Start close process for any wsi bound to this vhost that belong to the
1132  * service thread we are called from.  Because of async event lib close, or
1133  * protocol staged close on wsi, latency with pts joining in closing their
1134  * wsi on the vhost, this may take some time.
1135  *
1136  * When the wsi count bound to the vhost (from all pts) drops to zero, the
1137  * vhost destruction will be finalized.
1138  */
1139 
1140 void
1141 __lws_vhost_destroy_pt_wsi_dieback_start(struct lws_vhost *vh)
1142 {
1143 #if LWS_MAX_SMP > 1
1144 	/* calling pt thread has done its wsi dieback */
1145 	int tsi = lws_pthread_self_to_tsi(vh->context);
1146 #else
1147 	int tsi = 0;
1148 #endif
1149 	struct lws_context *ctx = vh->context;
1150 	struct lws_context_per_thread *pt = &ctx->pt[tsi];
1151 	unsigned int n;
1152 
1153 #if LWS_MAX_SMP > 1
1154 	if (vh->close_flow_vs_tsi[lws_pthread_self_to_tsi(vh->context)])
1155 		/* this pt has already done its bit */
1156 		return;
1157 #endif
1158 
1159 #if defined(LWS_WITH_CLIENT)
1160 	/*
1161 	 * destroy any wsi that are associated with us but have no socket
1162 	 * (and will otherwise be missed for destruction)
1163 	 */
1164 	lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
1165 			      vh->vh_awaiting_socket_owner.head) {
1166 		struct lws *w =
1167 			lws_container_of(d, struct lws, vh_awaiting_socket);
1168 
1169 		if (w->tsi == tsi) {
1170 
1171 			lwsl_debug("%s: closing aso\n", __func__);
1172 			lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
1173 					   "awaiting skt");
1174 		}
1175 
1176 	} lws_end_foreach_dll_safe(d, d1);
1177 #endif
1178 
1179 	/*
1180 	 * Close any wsi on this pt bound to the vhost
1181 	 */
1182 
1183 	n = 0;
1184 	while (n < pt->fds_count) {
1185 		struct lws *wsi = wsi_from_fd(ctx, pt->fds[n].fd);
1186 
1187 		if (wsi && wsi->tsi == tsi && wsi->a.vhost == vh) {
1188 
1189 			lwsl_debug("%s: pt %d: closing wsi %p: role %s\n",
1190 					__func__, tsi, wsi, wsi->role_ops->name);
1191 
1192 			lws_wsi_close(wsi, LWS_TO_KILL_ASYNC);
1193 
1194 			if (pt->pipe_wsi == wsi)
1195 				pt->pipe_wsi = NULL;
1196 		}
1197 		n++;
1198 	}
1199 
1200 #if LWS_MAX_SMP > 1
1201 	/* calling pt thread has done its wsi dieback */
1202 	vh->close_flow_vs_tsi[lws_pthread_self_to_tsi(vh->context)] = 1;
1203 #endif
1204 }
1205 
1206 
1207 /*
1208  * Mark the vhost as being destroyed, so things trying to use it abort.
1209  *
1210  * Dispose of the listen socket.
1211  */
1212 
1213 void
1214 lws_vhost_destroy1(struct lws_vhost *vh)
1215 {
1216 	struct lws_context *context = vh->context;
1217 
1218 	lwsl_info("%s\n", __func__);
1219 
1220 	lws_context_lock(context, "vhost destroy 1"); /* ---------- context { */
1221 
1222 	if (vh->being_destroyed)
1223 		goto out;
1224 
1225 	lws_vhost_lock(vh); /* -------------- vh { */
1226 
1227 #if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_WITH_TLS)
1228 	lws_tls_session_vh_destroy(vh);
1229 #endif
1230 
1231 	vh->being_destroyed = 1;
1232 	lws_dll2_add_tail(&vh->vh_being_destroyed_list,
1233 			  &context->owner_vh_being_destroyed);
1234 
1235 #if defined(LWS_WITH_NETWORK)
1236 	/*
1237 	 * PHASE 1: take down or reassign any listen wsi
1238 	 *
1239 	 * Are there other vhosts that are piggybacking on our listen socket?
1240 	 * If so we need to hand the listen socket off to one of the others
1241 	 * so it will remain open.
1242 	 *
1243 	 * If not, close the listen socket now.
1244 	 *
1245 	 * Either way the listen socket response to the vhost close is
1246 	 * immediately performed.
1247 	 */
1248 
1249 	if (vh->lserv_wsi) {
1250 		lws_start_foreach_ll(struct lws_vhost *, v,
1251 				     context->vhost_list) {
1252 			if (v != vh &&
1253 			    !v->being_destroyed &&
1254 			    v->listen_port == vh->listen_port &&
1255 			    ((!v->iface && !vh->iface) ||
1256 			    (v->iface && vh->iface &&
1257 			    !strcmp(v->iface, vh->iface)))) {
1258 				/*
1259 				 * this can only be a listen wsi, which is
1260 				 * restricted... it has no protocol or other
1261 				 * bindings or states.  So we can simply
1262 				 * swap it to a vhost that has the same
1263 				 * iface + port, but is not closing.
1264 				 */
1265 
1266 				lwsl_notice("%s: listen skt migrate %s -> %s\n",
1267 					    __func__, lws_vh_tag(vh),
1268 					    lws_vh_tag(v));
1269 
1270 				assert(v->lserv_wsi == NULL);
1271 				v->lserv_wsi = vh->lserv_wsi;
1272 
1273 				if (v->lserv_wsi) {
1274 					/* req cx + vh lock */
1275 					/*
1276 					 * If the vhost sees it's being destroyed and
1277 					 * in the unbind the number of wsis bound to
1278 					 * it falls to zero, it will destroy the
1279 					 * vhost opportunistically before we can
1280 					 * complete the transfer.  Add a fake wsi
1281 					 * bind temporarily to disallow this...
1282 					 */
1283 					v->count_bound_wsi++;
1284 					__lws_vhost_unbind_wsi(vh->lserv_wsi);
1285 					lws_vhost_bind_wsi(v, v->lserv_wsi);
1286 
1287 					/*
1288 					 * ... remove the fake wsi bind
1289 					 */
1290 					v->count_bound_wsi--;
1291 
1292 					vh->lserv_wsi = NULL;
1293 				}
1294 
1295 				break;
1296 			}
1297 		} lws_end_foreach_ll(v, vhost_next);
1298 
1299 		if (vh->lserv_wsi) {
1300 			/*
1301 			 * we didn't pass it off to another vhost on the same
1302 			 * listen port... let's close it next time around the
1303 			 * event loop without waiting for the logical destroy
1304 			 * of the vhost itself
1305 			 */
1306 			lws_set_timeout(vh->lserv_wsi, 1, LWS_TO_KILL_ASYNC);
1307 			vh->lserv_wsi = NULL;
1308 		}
1309 	}
1310 #endif
1311 
1312 	lws_vhost_unlock(vh); /* } vh -------------- */
1313 
1314 out:
1315 	lws_context_unlock(context); /* --------------------------- context { */
1316 }
1317 
1318 #if defined(LWS_WITH_ABSTRACT)
1319 static int
1320 destroy_ais(struct lws_dll2 *d, void *user)
1321 {
1322 	lws_abs_t *ai = lws_container_of(d, lws_abs_t, abstract_instances);
1323 
1324 	lws_abs_destroy_instance(&ai);
1325 
1326 	return 0;
1327 }
1328 #endif
1329 
1330 /*
1331  * Either start close or destroy any wsi on the vhost that belong to this pt,
1332  * if SMP mark the vh that we have done it for
1333  *
1334  * Must not have lock on vh
1335  */
1336 
1337 void
1338 __lws_vhost_destroy2(struct lws_vhost *vh)
1339 {
1340 	const struct lws_protocols *protocol = NULL;
1341 	struct lws_context *context = vh->context;
1342 	struct lws wsi;
1343 	int n;
1344 
1345 	vh->being_destroyed = 0;
1346 
1347 	// lwsl_info("%s: %s\n", __func__, vh->name);
1348 
1349 #if defined(LWS_WITH_DEPRECATED_THINGS)
1350 	/*
1351 	 * destroy any pending timed events
1352 	 */
1353 
1354 	while (vh->timed_vh_protocol_list)
1355 		__lws_timed_callback_remove(vh, vh->timed_vh_protocol_list);
1356 #endif
1357 	/*
1358 	 * let the protocols destroy the per-vhost protocol objects
1359 	 */
1360 
1361 	memset(&wsi, 0, sizeof(wsi));
1362 	wsi.a.context = vh->context;
1363 	wsi.a.vhost = vh; /* not a real bound wsi */
1364 	protocol = vh->protocols;
1365 	if (protocol && vh->created_vhost_protocols) {
1366 		n = 0;
1367 		while (n < vh->count_protocols) {
1368 			wsi.a.protocol = protocol;
1369 
1370 			lwsl_debug("%s: protocol destroy\n", __func__);
1371 
1372 			if (protocol->callback)
1373 				protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY,
1374 					   NULL, NULL, 0);
1375 			protocol++;
1376 			n++;
1377 		}
1378 	}
1379 
1380 	/*
1381 	 * remove vhost from context list of vhosts
1382 	 */
1383 
1384 	lws_start_foreach_llp(struct lws_vhost **, pv, context->vhost_list) {
1385 		if (*pv == vh) {
1386 			*pv = vh->vhost_next;
1387 			break;
1388 		}
1389 	} lws_end_foreach_llp(pv, vhost_next);
1390 
1391 	/* add ourselves to the pending destruction list */
1392 
1393 	if (vh->context->vhost_pending_destruction_list != vh) {
1394 		vh->vhost_next = vh->context->vhost_pending_destruction_list;
1395 		vh->context->vhost_pending_destruction_list = vh;
1396 	}
1397 
1398 	//lwsl_debug("%s: do dfl '%s'\n", __func__, vh->name);
1399 
1400 	/* remove ourselves from the pending destruction list */
1401 
1402 	lws_start_foreach_llp(struct lws_vhost **, pv,
1403 			      context->vhost_pending_destruction_list) {
1404 		if ((*pv) == vh) {
1405 			*pv = (*pv)->vhost_next;
1406 			break;
1407 		}
1408 	} lws_end_foreach_llp(pv, vhost_next);
1409 
1410 	/*
1411 	 * Free all the allocations associated with the vhost
1412 	 */
1413 
1414 	protocol = vh->protocols;
1415 	if (protocol) {
1416 		n = 0;
1417 		while (n < vh->count_protocols) {
1418 			if (vh->protocol_vh_privs &&
1419 			    vh->protocol_vh_privs[n]) {
1420 				lws_free(vh->protocol_vh_privs[n]);
1421 				vh->protocol_vh_privs[n] = NULL;
1422 			}
1423 			protocol++;
1424 			n++;
1425 		}
1426 	}
1427 	if (vh->protocol_vh_privs)
1428 		lws_free(vh->protocol_vh_privs);
1429 	lws_ssl_SSL_CTX_destroy(vh);
1430 	lws_free(vh->same_vh_protocol_owner);
1431 
1432 	if (
1433 #if defined(LWS_WITH_PLUGINS)
1434 		context->plugin_list ||
1435 #endif
1436 	    (context->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS) ||
1437 	    vh->allocated_vhost_protocols)
1438 		lws_free((void *)vh->protocols);
1439 #if defined(LWS_WITH_NETWORK)
1440 	LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
1441 	if (lws_rops_fidx(ar, LWS_ROPS_destroy_vhost))
1442 		lws_rops_func_fidx(ar, LWS_ROPS_destroy_vhost).
1443 							destroy_vhost(vh);
1444 	LWS_FOR_EVERY_AVAILABLE_ROLE_END;
1445 #endif
1446 
1447 #ifdef LWS_WITH_ACCESS_LOG
1448 	if (vh->log_fd != (int)LWS_INVALID_FILE)
1449 		close(vh->log_fd);
1450 #endif
1451 
1452 #if defined (LWS_WITH_TLS)
1453 	lws_free_set_NULL(vh->tls.alloc_cert_path);
1454 #endif
1455 
1456 #if LWS_MAX_SMP > 1
1457 	lws_mutex_refcount_destroy(&context->mr);
1458 #endif
1459 
1460 #if defined(LWS_WITH_UNIX_SOCK)
1461 	if (LWS_UNIX_SOCK_ENABLED(vh)) {
1462 		n = unlink(vh->iface);
1463 		if (n)
1464 			lwsl_info("Closing unix socket %s: errno %d\n",
1465 				  vh->iface, errno);
1466 	}
1467 #endif
1468 	/*
1469 	 * although async event callbacks may still come for wsi handles with
1470 	 * pending close in the case of asycn event library like libuv,
1471 	 * they do not refer to the vhost.  So it's safe to free.
1472 	 */
1473 
1474 	if (vh->finalize)
1475 		vh->finalize(vh, vh->finalize_arg);
1476 
1477 #if defined(LWS_WITH_ABSTRACT)
1478 	/*
1479 	 * abstract instances
1480 	 */
1481 
1482 	lws_dll2_foreach_safe(&vh->abstract_instances_owner, NULL, destroy_ais);
1483 #endif
1484 
1485 #if defined(LWS_WITH_SERVER) && defined(LWS_WITH_SYS_METRICS)
1486 	lws_metric_destroy(&vh->mt_traffic_rx, 0);
1487 	lws_metric_destroy(&vh->mt_traffic_tx, 0);
1488 #endif
1489 
1490 	lws_dll2_remove(&vh->vh_being_destroyed_list);
1491 
1492 #if defined(LWS_WITH_SYS_FAULT_INJECTION)
1493 	lws_fi_destroy(&vh->fic);
1494 #endif
1495 
1496 	__lws_lc_untag(&vh->lc);
1497 
1498 	memset(vh, 0, sizeof(*vh));
1499 	lws_free(vh);
1500 }
1501 
1502 /*
1503  * Starts the vhost destroy process
1504  *
1505  * Vhosts are not simple to deal with because they are an abstraction that
1506  * crosses SMP thread boundaries, a wsi on any pt can bind to any vhost.  If we
1507  * want another pt to do something to its wsis safely, we have to asynchronously
1508  * ask it to do it.
1509  *
1510  * In addition, with event libs, closing any handles (which are bound to vhosts
1511  * in their wsi) can happens asynchronously, so we can't just linearly do some
1512  * cleanup flow and free it in one step.
1513  *
1514  * The vhost destroy is cut into two pieces:
1515  *
1516  * 1) dispose of the listen socket, either by passing it on to another vhost
1517  *    that was already sharing it, or just closing it.
1518  *
1519  *    If any wsi bound to the vhost, mark the vhost as in the process of being
1520  *    destroyed, triggering each pt to close all wsi bound to the vhost next
1521  *    time around the event loop.  Call lws_cancel_service() so all the pts wake
1522  *    to deal with this without long poll waits making delays.
1523  *
1524  * 2) When the number of wsis bound to the vhost reaches zero, do the final
1525  *    vhost destroy flow, this can be triggered from any pt.
1526  */
1527 
1528 void
1529 lws_vhost_destroy(struct lws_vhost *vh)
1530 {
1531 	struct lws_context *context = vh->context;
1532 
1533 	lws_context_lock(context, __func__); /* ------ context { */
1534 
1535 	/* dispose of the listen socket one way or another */
1536 	lws_vhost_destroy1(vh);
1537 
1538 	/* start async closure of all wsi on this pt thread attached to vh */
1539 	__lws_vhost_destroy_pt_wsi_dieback_start(vh);
1540 
1541 	lwsl_info("%s: count_bound_wsi %d\n", __func__, vh->count_bound_wsi);
1542 
1543 	/* if there are none, finalize now since no further chance */
1544 	if (!vh->count_bound_wsi) {
1545 		__lws_vhost_destroy2(vh);
1546 
1547 		goto out;
1548 	}
1549 
1550 	/*
1551 	 * We have some wsi bound to this vhost, we have to wait for these to
1552 	 * complete close and unbind before progressing the vhost removal.
1553 	 *
1554 	 * When the last bound wsi on this vh is destroyed we will auto-call
1555 	 * __lws_vhost_destroy2() to finalize vh destruction
1556 	 */
1557 
1558 #if LWS_MAX_SMP > 1
1559 	/* alert other pts they also need to do dieback flow for their wsi */
1560 	lws_cancel_service(context);
1561 #endif
1562 
1563 out:
1564 	lws_context_unlock(context); /* } context ------------------- */
1565 }
1566 
1567 
1568 void *
1569 lws_vhost_user(struct lws_vhost *vhost)
1570 {
1571 	return vhost->user;
1572 }
1573 
1574 int
1575 lws_get_vhost_listen_port(struct lws_vhost *vhost)
1576 {
1577 	return vhost->listen_port;
1578 }
1579 
1580 #if defined(LWS_WITH_SERVER)
1581 void
1582 lws_context_deprecate(struct lws_context *context, lws_reload_func cb)
1583 {
1584 	struct lws_vhost *vh = context->vhost_list, *vh1;
1585 
1586 	/*
1587 	 * "deprecation" means disable the context from accepting any new
1588 	 * connections and free up listen sockets to be used by a replacement
1589 	 * context.
1590 	 *
1591 	 * Otherwise the deprecated context remains operational, until its
1592 	 * number of connected sockets falls to zero, when it is deleted.
1593 	 */
1594 
1595 	/* for each vhost, close his listen socket */
1596 
1597 	while (vh) {
1598 		struct lws *wsi = vh->lserv_wsi;
1599 
1600 		if (wsi) {
1601 			wsi->socket_is_permanently_unusable = 1;
1602 			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "ctx deprecate");
1603 			wsi->a.context->deprecation_pending_listen_close_count++;
1604 			/*
1605 			 * other vhosts can share the listen port, they
1606 			 * point to the same wsi.  So zap those too.
1607 			 */
1608 			vh1 = context->vhost_list;
1609 			while (vh1) {
1610 				if (vh1->lserv_wsi == wsi)
1611 					vh1->lserv_wsi = NULL;
1612 				vh1 = vh1->vhost_next;
1613 			}
1614 		}
1615 		vh = vh->vhost_next;
1616 	}
1617 
1618 	context->deprecated = 1;
1619 	context->deprecation_cb = cb;
1620 }
1621 #endif
1622 
1623 #if defined(LWS_WITH_NETWORK)
1624 
1625 struct lws_vhost *
1626 lws_get_vhost_by_name(struct lws_context *context, const char *name)
1627 {
1628 	lws_start_foreach_ll(struct lws_vhost *, v,
1629 			     context->vhost_list) {
1630 		if (!v->being_destroyed && !strcmp(v->name, name))
1631 			return v;
1632 
1633 	} lws_end_foreach_ll(v, vhost_next);
1634 
1635 	return NULL;
1636 }
1637 
1638 
1639 #if defined(LWS_WITH_CLIENT)
1640 /*
1641  * This is the logic checking to see if the new connection wsi should have a
1642  * pipelining or muxing relationship with an existing "active connection" to
1643  * the same endpoint under the same conditions.
1644  *
1645  * This was originally in the client code but since the list is held on the
1646  * vhost (to ensure the same client tls ctx is involved) it's cleaner in vhost.c
1647  *
1648  * ACTIVE_CONNS_QUEUED: We're queued on an active connection, set *nwsi to that
1649  * ACTIVE_CONNS_MUXED: We are joining an active mux conn *nwsi as a child
1650  * ACTIVE_CONNS_SOLO: There's no existing conn to join either way
1651  */
1652 
1653 int
1654 lws_vhost_active_conns(struct lws *wsi, struct lws **nwsi, const char *adsin)
1655 {
1656 #if defined(LWS_WITH_TLS)
1657 	const char *my_alpn = lws_wsi_client_stash_item(wsi, CIS_ALPN,
1658 							_WSI_TOKEN_CLIENT_ALPN);
1659 #endif
1660 #if defined(LWS_WITH_TLS)
1661 	char newconn_cannot_use_h1 = 0;
1662 
1663 	if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) &&
1664 	    my_alpn && !strstr(my_alpn, "http/1.1"))
1665 		/*
1666 		 * new guy wants to use tls, he specifies the alpn and he does
1667 		 * not list h1 as a choice ==> he can't bind to existing h1
1668 		 */
1669 		newconn_cannot_use_h1 = 1;
1670 #endif
1671 
1672 	if (!lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) {
1673 		struct lws *w = lws_container_of(
1674 				wsi->dll2_cli_txn_queue.owner, struct lws,
1675 				dll2_cli_txn_queue_owner);
1676 		*nwsi = w;
1677 
1678 		return ACTIVE_CONNS_QUEUED;
1679 	}
1680 
1681 #if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)
1682 	if (wsi->mux.parent_wsi) {
1683 		/*
1684 		 * We already decided...
1685 		 */
1686 
1687 		*nwsi = wsi->mux.parent_wsi;
1688 
1689 		return ACTIVE_CONNS_MUXED;
1690 	}
1691 #endif
1692 
1693 	lws_context_lock(wsi->a.context, __func__); /* -------------- cx { */
1694 	lws_vhost_lock(wsi->a.vhost); /* ----------------------------------- { */
1695 
1696 	lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
1697 				   wsi->a.vhost->dll_cli_active_conns_owner.head) {
1698 		struct lws *w = lws_container_of(d, struct lws,
1699 						 dll_cli_active_conns);
1700 
1701 		lwsl_debug("%s: check %s %s %s %s %d %d\n", __func__,
1702 				lws_wsi_tag(wsi), lws_wsi_tag(w),
1703 			    adsin, w->cli_hostname_copy, wsi->c_port, w->c_port);
1704 
1705 		if (w != wsi &&
1706 		    /*
1707 		     * "same internet protocol"... this is a bit tricky,
1708 		     * since h2 start out as h1, and may stay at h1.
1709 		     *
1710 		     * But an idle h1 connection cannot be used by a connection
1711 		     * request that doesn't have http/1.1 in its alpn list...
1712 		     */
1713 		    (w->role_ops == wsi->role_ops ||
1714 		     (lwsi_role_http(w) && lwsi_role_http(wsi))) &&
1715 		     /* ... same role, or at least both some kind of http */
1716 		    w->cli_hostname_copy && !strcmp(adsin, w->cli_hostname_copy) &&
1717 		    /* same endpoint hostname */
1718 #if defined(LWS_WITH_TLS)
1719 		   !(newconn_cannot_use_h1 && w->role_ops == &role_ops_h1) &&
1720 		   /* if we can't use h1, old guy must not be h1 */
1721 		    (wsi->tls.use_ssl & LCCSCF_USE_SSL) ==
1722 		     (w->tls.use_ssl & LCCSCF_USE_SSL) &&
1723 		     /* must both agree on tls use or not */
1724 #endif
1725 		    wsi->c_port == w->c_port) {
1726 			/* same endpoint port */
1727 
1728 			/*
1729 			 * There's already an active connection.
1730 			 *
1731 			 * The server may have told the existing active
1732 			 * connection that it doesn't support pipelining...
1733 			 */
1734 			if (w->keepalive_rejected) {
1735 				lwsl_notice("defeating pipelining due to no "
1736 					  "keepalive on server\n");
1737 				goto solo;
1738 			}
1739 
1740 #if defined(LWS_WITH_HTTP2)
1741 			/*
1742 			 * h2: if in usable state already: just use it without
1743 			 *     going through the queue
1744 			 */
1745 			if (w->client_h2_alpn && w->client_mux_migrated &&
1746 			    (lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS ||
1747 			     lwsi_state(w) == LRS_ESTABLISHED ||
1748 			     lwsi_state(w) == LRS_IDLING)) {
1749 
1750 				lwsl_notice("%s: just join h2 directly 0x%x\n",
1751 						__func__, lwsi_state(w));
1752 
1753 				if (lwsi_state(w) == LRS_IDLING) {
1754 					// lwsi_set_state(w, LRS_ESTABLISHED);
1755 					_lws_generic_transaction_completed_active_conn(&w, 0);
1756 				}
1757 
1758 				//lwsi_set_state(w, LRS_H1C_ISSUE_HANDSHAKE2);
1759 
1760 				wsi->client_h2_alpn = 1;
1761 				lws_wsi_h2_adopt(w, wsi);
1762 				lws_vhost_unlock(wsi->a.vhost); /* } ---------- */
1763 				lws_context_unlock(wsi->a.context); /* -------------- cx { */
1764 
1765 				*nwsi = w;
1766 
1767 				return ACTIVE_CONNS_MUXED;
1768 			}
1769 #endif
1770 
1771 #if defined(LWS_ROLE_MQTT)
1772 			/*
1773 			 * MQTT: if in usable state already: just use it without
1774 			 *	 going through the queue
1775 			 */
1776 
1777 			if (lwsi_role_mqtt(wsi) && w->client_mux_migrated &&
1778 			    lwsi_state(w) == LRS_ESTABLISHED) {
1779 
1780 				if (lws_wsi_mqtt_adopt(w, wsi)) {
1781 					lwsl_notice("%s: join mqtt directly\n", __func__);
1782 					lws_dll2_remove(&wsi->dll2_cli_txn_queue);
1783 					wsi->client_mux_substream = 1;
1784 
1785 					lws_vhost_unlock(wsi->a.vhost); /* } ---------- */
1786 					lws_context_unlock(wsi->a.context); /* -------------- cx { */
1787 
1788 					return ACTIVE_CONNS_MUXED;
1789 				}
1790 			}
1791 #endif
1792 
1793 			/*
1794 			 * If the connection is viable but not yet in a usable
1795 			 * state, let's attach ourselves to it and wait for it
1796 			 * to get there or fail.
1797 			 */
1798 
1799 			lwsl_notice("%s: apply %s to txn queue on %s state 0x%lx\n",
1800 				  __func__, lws_wsi_tag(wsi), lws_wsi_tag(w),
1801 				  (unsigned long)w->wsistate);
1802 			/*
1803 			 * ...let's add ourselves to his transaction queue...
1804 			 * we are adding ourselves at the TAIL
1805 			 */
1806 			lws_dll2_add_tail(&wsi->dll2_cli_txn_queue,
1807 					  &w->dll2_cli_txn_queue_owner);
1808 
1809 			if (lwsi_state(w) == LRS_IDLING) {
1810 				// lwsi_set_state(w, LRS_ESTABLISHED);
1811 				_lws_generic_transaction_completed_active_conn(&w, 0);
1812 			}
1813 
1814 			/*
1815 			 * For eg, h1 next we'd pipeline our headers out on him,
1816 			 * and wait for our turn at client transaction_complete
1817 			 * to take over parsing the rx.
1818 			 */
1819 			lws_vhost_unlock(wsi->a.vhost); /* } ---------- */
1820 			lws_context_unlock(wsi->a.context); /* -------------- cx { */
1821 
1822 			*nwsi = w;
1823 
1824 			return ACTIVE_CONNS_QUEUED;
1825 		}
1826 
1827 	} lws_end_foreach_dll_safe(d, d1);
1828 
1829 solo:
1830 	lws_vhost_unlock(wsi->a.vhost); /* } ---------------------------------- */
1831 	lws_context_unlock(wsi->a.context); /* -------------- cx { */
1832 
1833 	/* there is nobody already connected in the same way */
1834 
1835 	return ACTIVE_CONNS_SOLO;
1836 }
1837 #endif
1838 #endif
1839 
1840 const char *
1841 lws_vh_tag(struct lws_vhost *vh)
1842 {
1843 	return lws_lc_tag(&vh->lc);
1844 }
1845