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