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