2 * libwebsockets web server application
4 * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "core/private.h"
25 /* this is needed for Travis CI */
29 #define ESC_INSTALL_DATADIR "_lws_ddir_"
31 static const char * const paths_global[] = {
36 "global.count-threads",
38 "global.server-string",
40 "global.ws-pingpong-secs",
41 "global.timeout-secs",
42 "global.reject-service-keywords[].*",
43 "global.reject-service-keywords[]",
44 "global.default-alpn",
47 enum lejp_global_paths {
58 LWJPGP_REJECT_SERVICE_KEYWORDS_NAME,
59 LWJPGP_REJECT_SERVICE_KEYWORDS,
63 static const char * const paths_vhosts[] = {
69 "vhosts[].unix-socket",
70 "vhosts[].unix-socket-perms",
72 "vhosts[].host-ssl-key",
73 "vhosts[].host-ssl-cert",
74 "vhosts[].host-ssl-ca",
75 "vhosts[].access-log",
76 "vhosts[].mounts[].mountpoint",
77 "vhosts[].mounts[].origin",
78 "vhosts[].mounts[].protocol",
79 "vhosts[].mounts[].default",
80 "vhosts[].mounts[].auth-mask",
81 "vhosts[].mounts[].cgi-timeout",
82 "vhosts[].mounts[].cgi-env[].*",
83 "vhosts[].mounts[].cache-max-age",
84 "vhosts[].mounts[].cache-reuse",
85 "vhosts[].mounts[].cache-revalidate",
86 "vhosts[].mounts[].basic-auth",
87 "vhosts[].mounts[].cache-intermediaries",
88 "vhosts[].mounts[].extra-mimetypes.*",
89 "vhosts[].mounts[].interpret.*",
90 "vhosts[].ws-protocols[].*.*",
91 "vhosts[].ws-protocols[].*",
92 "vhosts[].ws-protocols[]",
93 "vhosts[].keepalive_timeout",
94 "vhosts[].enable-client-ssl",
96 "vhosts[].ecdh-curve",
99 "vhosts[].ssl-option-set",
100 "vhosts[].ssl-option-clear",
101 "vhosts[].mounts[].pmo[].*",
102 "vhosts[].headers[].*",
103 "vhosts[].headers[]",
104 "vhosts[].client-ssl-key",
105 "vhosts[].client-ssl-cert",
106 "vhosts[].client-ssl-ca",
107 "vhosts[].client-ssl-ciphers",
109 "vhosts[].client-cert-required",
110 "vhosts[].ignore-missing-cert",
111 "vhosts[].error-document-404",
113 "vhosts[].ssl-client-option-set",
114 "vhosts[].ssl-client-option-clear",
115 "vhosts[].tls13-ciphers",
116 "vhosts[].client-tls13-ciphers",
117 "vhosts[].strict-host-check",
119 "vhosts[].listen-accept-role",
120 "vhosts[].listen-accept-protocol",
121 "vhosts[].apply-listen-accept", /* deprecates "onlyraw" */
122 "vhosts[].fallback-listen-accept",
123 "vhosts[].allow-non-tls",
124 "vhosts[].redirect-http",
125 "vhosts[].allow-http-on-https",
127 "vhosts[].disable-no-protocol-ws-upgrades",
130 enum lejp_vhost_paths {
137 LEJPVP_UNIXSKT_PERMS,
140 LEJPVP_HOST_SSL_CERT,
145 LEJPVP_MOUNT_PROTOCOL,
147 LEJPVP_DEFAULT_AUTH_MASK,
150 LEJPVP_MOUNT_CACHE_MAX_AGE,
151 LEJPVP_MOUNT_CACHE_REUSE,
152 LEJPVP_MOUNT_CACHE_REVALIDATE,
153 LEJPVP_MOUNT_BASIC_AUTH,
154 LEJPVP_MOUNT_CACHE_INTERMEDIARIES,
155 LEJPVP_MOUNT_EXTRA_MIMETYPES,
156 LEJPVP_MOUNT_INTERPRET,
157 LEJPVP_PROTOCOL_NAME_OPT,
158 LEJPVP_PROTOCOL_NAME,
160 LEJPVP_KEEPALIVE_TIMEOUT,
161 LEJPVP_ENABLE_CLIENT_SSL,
166 LEJPVP_SSL_OPTION_SET,
167 LEJPVP_SSL_OPTION_CLEAR,
171 LEJPVP_CLIENT_SSL_KEY,
172 LEJPVP_CLIENT_SSL_CERT,
173 LEJPVP_CLIENT_SSL_CA,
174 LEJPVP_CLIENT_CIPHERS,
176 LEJPVP_FLAG_CLIENT_CERT_REQUIRED,
177 LEJPVP_IGNORE_MISSING_CERT,
178 LEJPVP_ERROR_DOCUMENT_404,
180 LEJPVP_SSL_CLIENT_OPTION_SET,
181 LEJPVP_SSL_CLIENT_OPTION_CLEAR,
182 LEJPVP_TLS13_CIPHERS,
183 LEJPVP_CLIENT_TLS13_CIPHERS,
184 LEJPVP_FLAG_STRICT_HOST_CHECK,
186 LEJPVP_LISTEN_ACCEPT_ROLE,
187 LEJPVP_LISTEN_ACCEPT_PROTOCOL,
188 LEJPVP_FLAG_APPLY_LISTEN_ACCEPT,
189 LEJPVP_FLAG_FALLBACK_LISTEN_ACCEPT,
190 LEJPVP_FLAG_ALLOW_NON_TLS,
191 LEJPVP_FLAG_REDIRECT_HTTP,
192 LEJPVP_FLAG_ALLOW_HTTP_ON_HTTPS,
194 LEJPVP_FLAG_DISABLE_NO_PROTOCOL_WS_UPGRADES,
197 #define MAX_PLUGIN_DIRS 10
200 struct lws_context_creation_info *info;
201 struct lws_context *context;
202 const struct lws_protocols *protocols;
203 const struct lws_protocols **pprotocols;
204 const struct lws_extension *extensions;
205 char *p, *end, valid;
206 struct lws_http_mount *head, *last;
208 struct lws_protocol_vhost_options *pvo;
209 struct lws_protocol_vhost_options *pvo_em;
210 struct lws_protocol_vhost_options *pvo_int;
211 struct lws_http_mount m;
212 const char **plugin_dirs;
213 int count_plugin_dirs;
215 unsigned int reject_ws_with_no_protocol:1;
216 unsigned int enable_client_ssl:1;
217 unsigned int fresh_mount:1;
218 unsigned int any_vhosts:1;
219 unsigned int chunk:1;
223 lwsws_align(struct jpargs *a)
225 if ((lws_intptr_t)(a->p) & 15)
226 a->p += 16 - ((lws_intptr_t)(a->p) & 15);
234 arg_to_bool(const char *s)
236 static const char * const on[] = { "on", "yes", "true" };
242 for (n = 0; n < (int)LWS_ARRAY_SIZE(on); n++)
243 if (!strcasecmp(s, on[n]))
250 set_reset_flag(unsigned int *p, const char *state, unsigned int flag)
252 if (arg_to_bool(state))
259 lejp_globals_cb(struct lejp_ctx *ctx, char reason)
261 struct jpargs *a = (struct jpargs *)ctx->user;
262 struct lws_protocol_vhost_options *rej;
265 /* we only match on the prepared path strings */
266 if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
269 /* this catches, eg, vhosts[].headers[].xxx */
270 if (reason == LEJPCB_VAL_STR_END &&
271 ctx->path_match == LWJPGP_REJECT_SERVICE_KEYWORDS_NAME + 1) {
272 rej = lwsws_align(a);
273 a->p += sizeof(*rej);
275 n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
276 rej->next = a->info->reject_service_keywords;
277 a->info->reject_service_keywords = rej;
279 lwsl_notice(" adding rej %s=%s\n", a->p, ctx->buf);
287 switch (ctx->path_match - 1) {
289 a->info->uid = atoi(ctx->buf);
292 a->info->gid = atoi(ctx->buf);
294 case LEJPGP_USERNAME:
295 a->info->username = a->p;
297 case LEJPGP_GROUPNAME:
298 a->info->groupname = a->p;
300 case LEJPGP_COUNT_THREADS:
301 a->info->count_threads = atoi(ctx->buf);
303 case LWJPGP_INIT_SSL:
304 if (arg_to_bool(ctx->buf))
305 a->info->options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
307 case LEJPGP_SERVER_STRING:
308 a->info->server_string = a->p;
310 case LEJPGP_PLUGIN_DIR:
311 if (a->count_plugin_dirs == MAX_PLUGIN_DIRS - 1) {
312 lwsl_err("Too many plugin dirs\n");
315 a->plugin_dirs[a->count_plugin_dirs++] = a->p;
318 case LWJPGP_PINGPONG_SECS:
319 a->info->ws_ping_pong_interval = atoi(ctx->buf);
322 case LWJPGP_TIMEOUT_SECS:
323 a->info->timeout_secs = atoi(ctx->buf);
326 case LWJPGP_DEFAULT_ALPN:
327 a->info->alpn = a->p;
335 a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
342 lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
344 struct jpargs *a = (struct jpargs *)ctx->user;
345 struct lws_protocol_vhost_options *pvo, *mp_cgienv, *headers;
346 struct lws_http_mount *m;
351 lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match);
352 for (n = 0; n < ctx->wildcount; n++)
353 lwsl_notice(" %d\n", ctx->wild[n]);
356 if (reason == LEJPCB_OBJECT_START && ctx->path_match == LEJPVP + 1) {
360 /* set the defaults for this vhost */
361 a->reject_ws_with_no_protocol = 0;
366 i[0] = a->info->count_threads;
367 i[1] = a->info->options & (
368 LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME |
369 LWS_SERVER_OPTION_LIBUV |
370 LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
371 LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
372 LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN |
373 LWS_SERVER_OPTION_LIBEVENT |
374 LWS_SERVER_OPTION_LIBEV
376 ss = a->info->server_string;
377 i[2] = a->info->ws_ping_pong_interval;
378 i[3] = a->info->timeout_secs;
380 memset(a->info, 0, sizeof(*a->info));
382 a->info->count_threads = i[0];
383 a->info->options = i[1];
384 a->info->server_string = ss;
385 a->info->ws_ping_pong_interval = i[2];
386 a->info->timeout_secs = i[3];
388 a->info->protocols = a->protocols;
389 a->info->pprotocols = a->pprotocols;
390 a->info->extensions = a->extensions;
391 #if defined(LWS_WITH_TLS)
392 a->info->client_ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
393 "ECDHE-RSA-AES256-GCM-SHA384:"
394 "DHE-RSA-AES256-GCM-SHA384:"
395 "ECDHE-RSA-AES256-SHA384:"
396 "HIGH:!aNULL:!eNULL:!EXPORT:"
397 "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
398 "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
399 "!DHE-RSA-AES128-SHA256:"
400 "!AES128-GCM-SHA256:"
402 "!DHE-RSA-AES256-SHA256:"
403 "!AES256-GCM-SHA384:"
406 a->info->ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
407 "ECDHE-RSA-AES256-GCM-SHA384:"
408 "DHE-RSA-AES256-GCM-SHA384:"
409 "ECDHE-RSA-AES256-SHA384:"
410 "HIGH:!aNULL:!eNULL:!EXPORT:"
411 "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
412 "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
413 "!DHE-RSA-AES128-SHA256:"
414 "!AES128-GCM-SHA256:"
416 "!DHE-RSA-AES256-SHA256:"
417 "!AES256-GCM-SHA384:"
419 a->info->keepalive_timeout = 5;
422 if (reason == LEJPCB_OBJECT_START &&
423 ctx->path_match == LEJPVP_MOUNTS + 1) {
425 memset(&a->m, 0, sizeof(a->m));
428 /* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
429 if (reason == LEJPCB_OBJECT_START &&
430 ctx->path_match == LEJPVP_PROTOCOL_NAME + 1) {
431 a->pvo = lwsws_align(a);
432 a->p += sizeof(*a->pvo);
434 n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
435 /* ie, enable this protocol, no options yet */
436 a->pvo->next = a->info->pvo;
437 a->info->pvo = a->pvo;
439 lwsl_info(" adding protocol %s\n", a->p);
441 a->pvo->value = a->p;
442 a->pvo->options = NULL;
446 /* this catches, eg, vhosts[].headers[].xxx */
447 if ((reason == LEJPCB_VAL_STR_END || reason == LEJPCB_VAL_STR_CHUNK) &&
448 ctx->path_match == LEJPVP_HEADERS_NAME + 1) {
451 headers = lwsws_align(a);
452 a->p += sizeof(*headers);
454 n = lejp_get_wildcard(ctx, 0, a->p,
455 lws_ptr_diff(a->end, a->p));
456 /* ie, add this header */
457 headers->next = a->info->headers;
458 a->info->headers = headers;
459 headers->name = a->p;
461 lwsl_notice(" adding header %s=%s\n", a->p, ctx->buf);
468 headers->value = a->p;
469 headers->options = NULL;
471 a->chunk = reason == LEJPCB_VAL_STR_CHUNK;
475 if (reason == LEJPCB_OBJECT_END &&
476 (ctx->path_match == LEJPVP + 1 || !ctx->path[0]) &&
479 struct lws_vhost *vhost;
481 //lwsl_notice("%s\n", ctx->path);
482 if (!a->info->port &&
483 !(a->info->options & LWS_SERVER_OPTION_UNIX_SOCK)) {
484 lwsl_err("Port required (eg, 443)\n");
488 a->info->mounts = a->head;
490 vhost = lws_create_vhost(a->context, a->info);
492 lwsl_err("Failed to create vhost %s\n",
493 a->info->vhost_name);
498 if (a->reject_ws_with_no_protocol) {
499 a->reject_ws_with_no_protocol = 0;
501 vhost->default_protocol_index = 255;
504 #if defined(LWS_WITH_TLS)
505 if (a->enable_client_ssl) {
506 const char *cert_filepath =
507 a->info->client_ssl_cert_filepath;
508 const char *private_key_filepath =
509 a->info->client_ssl_private_key_filepath;
510 const char *ca_filepath =
511 a->info->client_ssl_ca_filepath;
512 const char *cipher_list =
513 a->info->client_ssl_cipher_list;
515 memset(a->info, 0, sizeof(*a->info));
516 a->info->client_ssl_cert_filepath = cert_filepath;
517 a->info->client_ssl_private_key_filepath =
518 private_key_filepath;
519 a->info->client_ssl_ca_filepath = ca_filepath;
520 a->info->client_ssl_cipher_list = cipher_list;
521 a->info->options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
522 lws_init_vhost_client_ssl(a->info, vhost);
529 if (reason == LEJPCB_OBJECT_END &&
530 ctx->path_match == LEJPVP_MOUNTS + 1) {
531 static const char * const mount_protocols[] = {
545 if (!a->m.mountpoint || !a->m.origin) {
546 lwsl_err("mountpoint and origin required\n");
549 lwsl_debug("adding mount %s\n", a->m.mountpoint);
551 memcpy(m, &a->m, sizeof(*m));
553 a->last->mount_next = m;
555 for (n = 0; n < (int)LWS_ARRAY_SIZE(mount_protocols); n++)
556 if (!strncmp(a->m.origin, mount_protocols[n],
557 strlen(mount_protocols[n]))) {
558 lwsl_info("----%s\n", a->m.origin);
559 m->origin_protocol = n;
560 m->origin = a->m.origin +
561 strlen(mount_protocols[n]);
565 if (n == (int)LWS_ARRAY_SIZE(mount_protocols)) {
566 lwsl_err("unsupported protocol:// %s\n", a->m.origin);
578 /* we only match on the prepared path strings */
579 if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
582 switch (ctx->path_match - 1) {
584 a->info->vhost_name = a->p;
587 a->info->port = atoi(ctx->buf);
589 case LEJPVP_INTERFACE:
590 a->info->iface = a->p;
593 if (arg_to_bool(ctx->buf))
594 a->info->options |= LWS_SERVER_OPTION_UNIX_SOCK;
596 a->info->options &= ~(LWS_SERVER_OPTION_UNIX_SOCK);
598 case LEJPVP_UNIXSKT_PERMS:
599 a->info->unix_socket_perms = a->p;
602 if (arg_to_bool(ctx->buf))
603 a->info->options |= LWS_SERVER_OPTION_STS;
605 a->info->options &= ~(LWS_SERVER_OPTION_STS);
607 case LEJPVP_HOST_SSL_KEY:
608 a->info->ssl_private_key_filepath = a->p;
610 case LEJPVP_HOST_SSL_CERT:
611 a->info->ssl_cert_filepath = a->p;
613 case LEJPVP_HOST_SSL_CA:
614 a->info->ssl_ca_filepath = a->p;
616 case LEJPVP_ACCESS_LOG:
617 a->info->log_filepath = a->p;
619 case LEJPVP_MOUNTPOINT:
620 a->m.mountpoint = a->p;
621 a->m.mountpoint_len = (unsigned char)strlen(ctx->buf);
624 if (!strncmp(ctx->buf, "callback://", 11))
625 a->m.protocol = a->p + 11;
633 case LEJPVP_DEFAULT_AUTH_MASK:
634 a->m.auth_mask = atoi(ctx->buf);
636 case LEJPVP_MOUNT_CACHE_MAX_AGE:
637 a->m.cache_max_age = atoi(ctx->buf);
639 case LEJPVP_MOUNT_CACHE_REUSE:
640 a->m.cache_reusable = arg_to_bool(ctx->buf);
642 case LEJPVP_MOUNT_CACHE_REVALIDATE:
643 a->m.cache_revalidate = arg_to_bool(ctx->buf);
645 case LEJPVP_MOUNT_CACHE_INTERMEDIARIES:
646 a->m.cache_intermediaries = arg_to_bool(ctx->buf);;
648 case LEJPVP_MOUNT_BASIC_AUTH:
649 a->m.basic_auth_login_file = a->p;
651 case LEJPVP_CGI_TIMEOUT:
652 a->m.cgi_timeout = atoi(ctx->buf);
654 case LEJPVP_KEEPALIVE_TIMEOUT:
655 a->info->keepalive_timeout = atoi(ctx->buf);
657 #if defined(LWS_WITH_TLS)
658 case LEJPVP_CLIENT_CIPHERS:
659 a->info->client_ssl_cipher_list = a->p;
663 a->info->ssl_cipher_list = a->p;
665 case LEJPVP_TLS13_CIPHERS:
666 a->info->tls1_3_plus_cipher_list = a->p;
668 case LEJPVP_CLIENT_TLS13_CIPHERS:
669 a->info->client_tls_1_3_plus_cipher_list = a->p;
672 case LEJPVP_ECDH_CURVE:
673 a->info->ecdh_curve = a->p;
677 mp_cgienv = lwsws_align(a);
678 a->p += sizeof(*a->m.cgienv);
680 mp_cgienv->next = a->m.cgienv;
681 a->m.cgienv = mp_cgienv;
683 n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
684 mp_cgienv->name = a->p;
686 mp_cgienv->value = a->p;
687 mp_cgienv->options = NULL;
688 //lwsl_notice(" adding pmo / cgi-env '%s' = '%s'\n",
689 // mp_cgienv->name, mp_cgienv->value);
692 case LEJPVP_PROTOCOL_NAME_OPT:
694 * vhosts[].ws-protocols[].xxx-protocol.yyy-option
695 * ie, these are options attached to a protocol with { }
697 pvo = lwsws_align(a);
698 a->p += sizeof(*a->pvo);
700 n = lejp_get_wildcard(ctx, 1, a->p, lws_ptr_diff(a->end, a->p));
701 /* ie, enable this protocol, no options yet */
702 pvo->next = a->pvo->options;
703 a->pvo->options = pvo;
710 case LEJPVP_MOUNT_EXTRA_MIMETYPES:
711 a->pvo_em = lwsws_align(a);
712 a->p += sizeof(*a->pvo_em);
714 n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
715 /* ie, enable this protocol, no options yet */
716 a->pvo_em->next = a->m.extra_mimetypes;
717 a->m.extra_mimetypes = a->pvo_em;
718 a->pvo_em->name = a->p;
719 lwsl_notice(" + extra-mimetypes %s -> %s\n", a->p, ctx->buf);
721 a->pvo_em->value = a->p;
722 a->pvo_em->options = NULL;
725 case LEJPVP_MOUNT_INTERPRET:
726 a->pvo_int = lwsws_align(a);
727 a->p += sizeof(*a->pvo_int);
729 n = lejp_get_wildcard(ctx, 0, a->p, lws_ptr_diff(a->end, a->p));
730 /* ie, enable this protocol, no options yet */
731 a->pvo_int->next = a->m.interpret;
732 a->m.interpret = a->pvo_int;
733 a->pvo_int->name = a->p;
734 lwsl_notice(" adding interpret %s -> %s\n", a->p,
737 a->pvo_int->value = a->p;
738 a->pvo_int->options = NULL;
741 case LEJPVP_ENABLE_CLIENT_SSL:
742 a->enable_client_ssl = arg_to_bool(ctx->buf);
744 #if defined(LWS_WITH_TLS)
745 case LEJPVP_CLIENT_SSL_KEY:
746 a->info->client_ssl_private_key_filepath = a->p;
748 case LEJPVP_CLIENT_SSL_CERT:
749 a->info->client_ssl_cert_filepath = a->p;
751 case LEJPVP_CLIENT_SSL_CA:
752 a->info->client_ssl_ca_filepath = a->p;
757 set_reset_flag(&a->info->options, ctx->buf,
758 LWS_SERVER_OPTION_DISABLE_IPV6);
761 case LEJPVP_FLAG_ONLYRAW:
762 set_reset_flag(&a->info->options, ctx->buf,
763 LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG);
766 case LEJPVP_IPV6ONLY:
767 a->info->options |= LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY;
768 set_reset_flag(&a->info->options, ctx->buf,
769 LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
772 case LEJPVP_FLAG_CLIENT_CERT_REQUIRED:
773 if (arg_to_bool(ctx->buf))
775 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
778 case LEJPVP_IGNORE_MISSING_CERT:
779 set_reset_flag(&a->info->options, ctx->buf,
780 LWS_SERVER_OPTION_IGNORE_MISSING_CERT);
783 case LEJPVP_FLAG_STRICT_HOST_CHECK:
784 set_reset_flag(&a->info->options, ctx->buf,
785 LWS_SERVER_OPTION_VHOST_UPG_STRICT_HOST_CHECK);
788 case LEJPVP_ERROR_DOCUMENT_404:
789 a->info->error_document_404 = a->p;
792 case LEJPVP_SSL_OPTION_SET:
793 a->info->ssl_options_set |= atol(ctx->buf);
795 case LEJPVP_SSL_OPTION_CLEAR:
796 a->info->ssl_options_clear |= atol(ctx->buf);
799 case LEJPVP_SSL_CLIENT_OPTION_SET:
800 a->info->ssl_client_options_set |= atol(ctx->buf);
802 case LEJPVP_SSL_CLIENT_OPTION_CLEAR:
803 a->info->ssl_client_options_clear |= atol(ctx->buf);
807 a->info->alpn = a->p;
810 case LEJPVP_LISTEN_ACCEPT_ROLE:
811 a->info->listen_accept_role = a->p;
813 case LEJPVP_LISTEN_ACCEPT_PROTOCOL:
814 a->info->listen_accept_protocol = a->p;
817 case LEJPVP_FLAG_APPLY_LISTEN_ACCEPT:
818 set_reset_flag(&a->info->options, ctx->buf,
819 LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG);
821 case LEJPVP_FLAG_FALLBACK_LISTEN_ACCEPT:
822 lwsl_notice("vh %s: LEJPVP_FLAG_FALLBACK_LISTEN_ACCEPT: %s\n",
823 a->info->vhost_name, ctx->buf);
824 set_reset_flag(&a->info->options, ctx->buf,
825 LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG);
827 case LEJPVP_FLAG_ALLOW_NON_TLS:
828 set_reset_flag(&a->info->options, ctx->buf,
829 LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT);
831 case LEJPVP_FLAG_REDIRECT_HTTP:
832 set_reset_flag(&a->info->options, ctx->buf,
833 LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS);
835 case LEJPVP_FLAG_ALLOW_HTTP_ON_HTTPS:
836 set_reset_flag(&a->info->options, ctx->buf,
837 LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER);
840 case LEJPVP_FLAG_DISABLE_NO_PROTOCOL_WS_UPGRADES:
841 a->reject_ws_with_no_protocol = 1;
850 p[LEJP_STRING_CHUNK] = '\0';
851 p1 = strstr(p, ESC_INSTALL_DATADIR);
853 n = lws_ptr_diff(p1, p);
854 if (n > a->end - a->p)
855 n = lws_ptr_diff(a->end, a->p);
856 lws_strncpy(a->p, p, n + 1);
858 a->p += lws_snprintf(a->p, a->end - a->p, "%s",
859 LWS_INSTALL_DATADIR);
860 p += n + strlen(ESC_INSTALL_DATADIR);
863 a->p += lws_snprintf(a->p, a->end - a->p, "%s", p);
864 if (reason == LEJPCB_VAL_STR_END)
871 * returns 0 = OK, 1 = can't open, 2 = parsing error
875 lwsws_get_config(void *user, const char *f, const char * const *paths,
876 int count_paths, lejp_callback cb)
878 unsigned char buf[128];
882 fd = lws_open(f, O_RDONLY);
884 lwsl_err("Cannot open %s\n", f);
887 lwsl_info("%s: %s\n", __func__, f);
888 lejp_construct(&ctx, cb, user, paths, count_paths);
891 n = read(fd, buf, sizeof(buf));
895 m = (int)(signed char)lejp_parse(&ctx, buf, n);
896 } while (m == LEJP_CONTINUE);
903 lwsl_err("%s(%u): parsing error %d: %s\n", f, n, m,
904 lejp_error_to_string(m));
911 struct lws_dir_args {
913 const char * const *paths;
919 lwsws_get_config_d_cb(const char *dirpath, void *user,
920 struct lws_dir_entry *lde)
922 struct lws_dir_args *da = (struct lws_dir_args *)user;
925 if (lde->type != LDOT_FILE && lde->type != LDOT_UNKNOWN /* ZFS */)
928 lws_snprintf(path, sizeof(path) - 1, "%s/%s", dirpath, lde->name);
930 return lwsws_get_config(da->user, path, da->paths,
931 da->count_paths, da->cb);
935 lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
938 struct lws_dir_args da;
940 const char * const *old = info->plugin_dirs;
943 memset(&a, 0, sizeof(a));
947 a.end = (a.p + *len) - 1;
951 info->plugin_dirs = (void *)a.p;
952 a.plugin_dirs = (void *)a.p; /* writeable version */
953 a.p += MAX_PLUGIN_DIRS * sizeof(void *);
955 /* copy any default paths */
957 while (old && *old) {
958 a.plugin_dirs[a.count_plugin_dirs++] = *old;
962 lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
963 if (lwsws_get_config(&a, dd, paths_global,
964 LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
966 lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
969 da.paths = paths_global;
970 da.count_paths = LWS_ARRAY_SIZE(paths_global),
971 da.cb = lejp_globals_cb;
973 if (lws_dir(dd, &da, lwsws_get_config_d_cb) > 1)
976 a.plugin_dirs[a.count_plugin_dirs] = NULL;
979 *len = lws_ptr_diff(a.end, a.p);
985 lwsws_get_config_vhosts(struct lws_context *context,
986 struct lws_context_creation_info *info, const char *d,
989 struct lws_dir_args da;
993 memset(&a, 0, sizeof(a));
1000 a.protocols = info->protocols;
1001 a.pprotocols = info->pprotocols;
1002 a.extensions = info->extensions;
1004 lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
1005 if (lwsws_get_config(&a, dd, paths_vhosts,
1006 LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
1008 lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
1011 da.paths = paths_vhosts;
1012 da.count_paths = LWS_ARRAY_SIZE(paths_vhosts),
1013 da.cb = lejp_vhosts_cb;
1015 if (lws_dir(dd, &da, lwsws_get_config_d_cb) > 1)
1019 *len = lws_ptr_diff(a.end, a.p);
1021 if (!a.any_vhosts) {
1022 lwsl_err("Need at least one vhost\n");
1026 // lws_finalize_startup(context);