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