Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1713527523, "reponame":"libwebsockets", "desc":"libwebsockets lightweight C networking library", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets", "f":3, "items": [ {"schema":"libjg2-1", "cid":"08e991d45d452dd9e4a7527e27ea2b35", "oid":{ "oid": "f28a45246e7ea479718ddba5e80deb355b23f5f3", "alias": [ "refs/heads/main"]},"blobname": "lib/core/context.c", "blob": "/*\n * libwebsockets - small server side websockets and web server implementation\n *\n * Copyright (C) 2010 - 2020 Andy Green \u003candy@warmcat.com\u003e\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \u0022Software\u0022), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \u0022AS IS\u0022, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n#include \u0022private-lib-core.h\u0022\n\n#ifndef LWS_BUILD_HASH\n#define LWS_BUILD_HASH \u0022unknown-build-hash\u0022\n#endif\n\nstatic const char *library_version \u003d LWS_LIBRARY_VERSION;\n\n#if defined(LWS_WITH_MBEDTLS)\nextern const char *mbedtls_client_preload_filepath;\n#endif\n\n#if defined(LWS_HAVE_SYS_RESOURCE_H)\n/* for setrlimit */\n#include \u003csys/resource.h\u003e\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n/* in ms */\nstatic uint32_t default_backoff_table[] \u003d { 1000, 3000, 9000, 17000 };\n#endif\n\n/**\n * lws_get_library_version: get version and git hash library built from\n *\n *\treturns a const char * to a string like \u00221.1 178d78c\u0022\n *\trepresenting the library version followed by the git head hash it\n *\twas built from\n */\nconst char *\nlws_get_library_version(void)\n{\n\treturn library_version;\n}\n\n#if defined(LWS_WITH_NETWORK)\n\n#if defined(LWS_WITH_SYS_STATE)\n\nstatic const char * system_state_names[] \u003d {\n\t\u0022undef\u0022,\n\t\u0022CONTEXT_CREATED\u0022,\n\t\u0022INITIALIZED\u0022,\n\t\u0022IFACE_COLDPLUG\u0022,\n\t\u0022DHCP\u0022,\n\t\u0022CPD_PRE_TIME\u0022,\n\t\u0022TIME_VALID\u0022,\n\t\u0022CPD_POST_TIME\u0022,\n\t\u0022POLICY_VALID\u0022,\n\t\u0022REGISTERED\u0022,\n\t\u0022AUTH1\u0022,\n\t\u0022AUTH2\u0022,\n\t\u0022ONE_TIME_UPDATES\u0022,\n\t\u0022OPERATIONAL\u0022,\n\t\u0022POLICY_INVALID\u0022,\n\t\u0022DESTROYING\u0022,\n\t\u0022AWAITING_MODAL_UPDATING\u0022,\n\t\u0022MODAL_UPDATING\u0022\n};\n\n\n/*\n * Handle provoking protocol init when we pass through the right system state\n */\n\nstatic int\nlws_state_notify_protocol_init(struct lws_state_manager *mgr,\n\t\t\t struct lws_state_notify_link *link, int current,\n\t\t\t int target)\n{\n\tstruct lws_context *context \u003d lws_container_of(mgr, struct lws_context,\n\t\t\t\t\t\t mgr_system);\n#if defined(LWS_WITH_SECURE_STREAMS) \u0026\u0026 \u005c\n defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM)\n\tlws_system_blob_t *ab0, *ab1;\n#endif\n\tint n;\n\n\t/*\n\t * Deal with any attachments that were waiting for the right state\n\t * to come along\n\t */\n\n\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++)\n\t\tlws_system_do_attach(\u0026context-\u003ept[n]);\n\n#if defined(LWS_WITH_SYS_DHCP_CLIENT)\n\tif (target \u003d\u003d LWS_SYSTATE_DHCP) {\n\t\t/*\n\t\t * Don't let it past here until at least one iface has been\n\t\t * configured for operation with DHCP\n\t\t */\n\n\t\tif (!lws_dhcpc_status(context, NULL))\n\t\t\treturn 1;\n\t}\n#endif\n\n#if defined(LWS_WITH_SYS_NTPCLIENT)\n\tif (target \u003d\u003d LWS_SYSTATE_TIME_VALID \u0026\u0026\n\t lws_now_secs() \u003c 1594017754) /* 06:42 Mon Jul 6 2020 UTC */ {\n\t\tlws_ntpc_trigger(context);\n\n\t\treturn 1;\n\t}\n#endif\n\n#if defined(LWS_WITH_OTA)\n\tif (target \u003d\u003d LWS_SYSTATE_OPERATIONAL) {\n\t\tuint16_t b;\n\n\t\t/*\n\t\t * We add jitter, so possibly large numbers of devices don't\n\t\t * all wake up and check for updates at the same moment after a\n\t\t * power outage\n\t\t */\n\n\t\tlws_get_random(context, \u0026b, 2);\n\t\tlws_sul_schedule(context, 0, \u0026context-\u003esul_ota_periodic,\n\t\t\t\t lws_ota_periodic_cb, (/* 30 + */ (b % 1000) *\n\t\t\t\t\t\t\tLWS_US_PER_MS));\n\t}\n#endif\n\n#if defined(LWS_WITH_NETLINK)\n\t/*\n\t * If we're going to use netlink routing data for DNS, we have to\n\t * wait to collect it asynchronously from the platform first. Netlink\n\t * role init starts a ctx sul for 350ms (reset to 100ms each time some\n\t * new netlink data comes) that sets nl_initial_done and tries to move\n\t * us to OPERATIONAL\n\t */\n\n\tif (target \u003d\u003d LWS_SYSTATE_IFACE_COLDPLUG \u0026\u0026\n\t context-\u003enetlink \u0026\u0026\n\t !context-\u003enl_initial_done) {\n\t\tlwsl_cx_info(context, \u0022waiting for netlink coldplug\u0022);\n\n\t\treturn 1;\n\t}\n#endif\n\n#if defined(LWS_WITH_SECURE_STREAMS) \u0026\u0026 \u005c\n defined(LWS_WITH_SECURE_STREAMS_SYS_AUTH_API_AMAZON_COM)\n\t/*\n\t * Skip this if we are running something without the policy for it\n\t *\n\t * If root token is empty, skip too.\n\t */\n\n\tab0 \u003d lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 0);\n\tab1 \u003d lws_system_get_blob(context, LWS_SYSBLOB_TYPE_AUTH, 1);\n\n\tif (target \u003d\u003d LWS_SYSTATE_AUTH1 \u0026\u0026\n\t context-\u003epss_policies \u0026\u0026 ab0 \u0026\u0026 ab1 \u0026\u0026\n\t !lws_system_blob_get_size(ab0) \u0026\u0026\n\t lws_system_blob_get_size(ab1)) {\n\t\tlwsl_cx_info(context,\n\t\t\t \u0022AUTH1 state triggering api.amazon.com auth\u0022);\n\t\t/*\n\t\t * Start trying to acquire it if it's not already in progress\n\t\t * returns nonzero if we determine it's not needed\n\t\t */\n\t\tif (!lws_ss_sys_auth_api_amazon_com(context))\n\t\t\treturn 1;\n\t}\n#endif\n\n#if defined(LWS_WITH_SECURE_STREAMS)\n#if defined(LWS_WITH_DRIVERS)\n\t/*\n\t * See if we should do the SS Captive Portal Detection\n\t */\n\tif (target \u003d\u003d LWS_SYSTATE_CPD_PRE_TIME) {\n\t\tif (lws_system_cpd_state_get(context) \u003d\u003d LWS_CPD_INTERNET_OK)\n\t\t\treturn 0; /* allow it */\n\n\t\t/*\n\t\t * Don't allow it to move past here until we get an IP and\n\t\t * CPD passes, driven by SMD\n\t\t */\n\n\t\treturn 1;\n\t}\n#endif\n\n#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\t/*\n\t * Skip this if we are running something without the policy for it\n\t */\n\tif (target \u003d\u003d LWS_SYSTATE_POLICY_VALID \u0026\u0026\n\t context-\u003epss_policies \u0026\u0026 !context-\u003epolicy_updated) {\n\n\t\tif (context-\u003ehss_fetch_policy)\n\t\t\treturn 1;\n\n\t\tlwsl_cx_debug(context, \u0022starting policy fetch\u0022);\n\t\t/*\n\t\t * Start trying to acquire it if it's not already in progress\n\t\t * returns nonzero if we determine it's not needed\n\t\t */\n\t\tif (!lws_ss_sys_fetch_policy(context))\n\t\t\t/* we have it */\n\t\t\treturn 0;\n\n\t\t/* deny while we fetch it */\n\n\t\treturn 1;\n\t}\n#endif\n#endif\n\n\t/* protocol part */\n\n\tif (context-\u003eprotocol_init_done)\n\t\treturn 0;\n\n\tif (target !\u003d LWS_SYSTATE_POLICY_VALID)\n\t\treturn 0;\n\n\tlwsl_cx_info(context, \u0022doing protocol init on POLICY_VALID\u005cn\u0022);\n\n\treturn lws_protocol_init(context);\n}\n\nstatic void\nlws_context_creation_completion_cb(lws_sorted_usec_list_t *sul)\n{\n\tstruct lws_context *context \u003d lws_container_of(sul, struct lws_context,\n\t\t\t\t\t\t sul_system_state);\n\n\t/* if nothing is there to intercept anything, go all the way */\n\tlws_state_transition_steps(\u0026context-\u003emgr_system,\n\t\t\t\t LWS_SYSTATE_OPERATIONAL);\n}\n#endif /* WITH_SYS_STATE */\n\n#if defined(LWS_WITH_SYS_SMD)\nstatic int\nlws_system_smd_cb(void *opaque, lws_smd_class_t _class, lws_usec_t timestamp,\n\t\t void *buf, size_t len)\n{\n\tstruct lws_context *cx \u003d (struct lws_context *)opaque;\n\n\tif (_class !\u003d LWSSMDCL_NETWORK)\n\t\treturn 0;\n\n\t/* something external requested CPD check */\n\n\tif (!lws_json_simple_strcmp(buf, len, \u0022\u005c\u0022trigger\u005c\u0022:\u0022, \u0022cpdcheck\u0022))\n\t\tlws_system_cpd_start(cx);\n\telse\n\t\t/*\n\t\t * IP acquisition on any interface triggers captive portal\n\t\t * check on default route\n\t\t */\n\t\tif (!lws_json_simple_strcmp(buf, len, \u0022\u005c\u0022type\u005c\u0022:\u0022, \u0022ipacq\u0022))\n\t\t\tlws_system_cpd_start(cx);\n\n#if defined(LWS_WITH_SYS_NTPCLIENT)\n\t/*\n\t * Captive portal detect showing internet workable triggers NTP Client\n\t */\n\tif (!lws_json_simple_strcmp(buf, len, \u0022\u005c\u0022type\u005c\u0022:\u0022, \u0022cps\u0022) \u0026\u0026\n\t !lws_json_simple_strcmp(buf, len, \u0022\u005c\u0022result\u005c\u0022:\u0022, \u0022OK\u0022) \u0026\u0026\n\t lws_now_secs() \u003c 1594017754) /* 06:42 Mon Jul 6 2020 UTC */\n\t\tlws_ntpc_trigger(cx);\n#endif\n\n#if defined(LWS_WITH_SYS_DHCP_CLIENT) \u0026\u0026 0\n\t/*\n\t * Any network interface linkup triggers DHCP\n\t */\n\tif (!lws_json_simple_strcmp(buf, len, \u0022\u005c\u0022type\u005c\u0022:\u0022, \u0022linkup\u0022))\n\t\tlws_ntpc_trigger(cx);\n\n#endif\n\n#if defined(LWS_WITH_DRIVERS) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\tlws_netdev_smd_cb(opaque, _class, timestamp, buf, len);\n#endif\n\n\treturn 0;\n}\n#endif\n\n\n\n#endif /* NETWORK */\n\n#if !defined(LWS_WITH_NO_LOGS)\n\nstatic const char * const opts_str \u003d\n#if defined(LWS_WITH_NETWORK)\n\t\t\t\u0022NET \u0022\n#else\n\t\t\t\u0022NoNET \u0022\n#endif\n#if defined(LWS_WITH_CLIENT)\n\t\t\t\u0022CLI \u0022\n#endif\n#if defined(LWS_WITH_SERVER)\n\t\t\t\u0022SRV \u0022\n#endif\n#if defined(LWS_ROLE_H1)\n\t\t\t\u0022H1 \u0022\n#endif\n#if defined(LWS_ROLE_H2)\n\t\t\t\u0022H2 \u0022\n#endif\n#if defined(LWS_ROLE_WS)\n\t\t\t\u0022WS \u0022\n#endif\n#if defined(LWS_ROLE_MQTT)\n\t\t\t\u0022MQTT \u0022\n#endif\n#if defined(LWS_WITH_SECURE_STREAMS) \u0026\u0026 !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\t\t\t\u0022SS-JSON-POL \u0022\n#endif\n#if defined(LWS_WITH_SECURE_STREAMS) \u0026\u0026 defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\t\t\t\u0022SS-STATIC-POL \u0022\n#endif\n#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n\t\t\t\u0022SSPROX \u0022\n#endif\n#if defined(LWS_WITH_CONMON)\n\t\t\t\u0022ConMon \u0022\n#endif\n#if defined(LWS_WITH_SYS_FAULT_INJECTION)\n\t\t\t\u0022FLTINJ \u0022\n#endif\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\t\t\t\u0022ASYNC_DNS \u0022\n#endif\n#if defined(LWS_WITH_SYS_NTPCLIENT)\n\t\t\t\u0022NTPCLIENT \u0022\n#endif\n#if defined(LWS_WITH_SYS_DHCP_CLIENT)\n\t\t\t\u0022DHCP_CLIENT \u0022\n#endif\n;\n\n#endif\n\n#if defined(LWS_WITH_EVLIB_PLUGINS) \u0026\u0026 defined(LWS_WITH_EVENT_LIBS)\nstatic const struct lws_evlib_map {\n\tuint64_t\tflag;\n\tconst char\t*name;\n} map[] \u003d {\n\t{ LWS_SERVER_OPTION_LIBUV, \u0022evlib_uv\u0022 },\n\t{ LWS_SERVER_OPTION_LIBEVENT, \u0022evlib_event\u0022 },\n\t{ LWS_SERVER_OPTION_GLIB, \u0022evlib_glib\u0022 },\n\t{ LWS_SERVER_OPTION_LIBEV, \u0022evlib_ev\u0022 },\n\t{ LWS_SERVER_OPTION_SDEVENT, \u0022evlib_sd\u0022 },\n\t{ LWS_SERVER_OPTION_ULOOP, \u0022evlib_uloop\u0022 },\n};\nstatic const char * const dlist[] \u003d {\n\t\u0022.\u0022,\t\t\t\t/* Priority 1: plugins in cwd */\n\tLWS_INSTALL_LIBDIR,\t\t/* Priority 2: plugins in install dir */\n\tNULL\n};\n#endif\n\nstruct lws_context *\nlws_create_context(const struct lws_context_creation_info *info)\n{\n\tstruct lws_context *context \u003d NULL;\n#if !defined(LWS_WITH_NO_LOGS)\n\tconst char *s \u003d \u0022IPv6-absent\u0022;\n#endif\n#if defined(LWS_WITH_FILE_OPS)\n\tstruct lws_plat_file_ops *prev;\n#endif\n#ifndef LWS_NO_DAEMONIZE\n\tpid_t pid_daemon \u003d get_daemonize_pid();\n#endif\n#if defined(LWS_WITH_NETWORK)\n\tconst lws_plugin_evlib_t *plev \u003d NULL;\n\tunsigned short count_threads \u003d 1;\n\tuint8_t *u;\n\tuint16_t us_wait_resolution \u003d 0;\n#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) \u0026\u0026 defined(LWS_WITH_CLIENT)\n\tstruct lws_cache_creation_info ci;\n#endif\n\n#if defined(__ANDROID__)\n\tstruct rlimit rt;\n#endif\n\tsize_t\n#if defined(LWS_PLAT_FREERTOS)\n\t\t/* smaller default, can set in info-\u003ept_serv_buf_size */\n\t\ts1 \u003d 2048,\n#else\n\t\ts1 \u003d 4096,\n#endif\n\t\tsize \u003d sizeof(struct lws_context);\n#endif\n#if !defined(LWS_PLAT_BAREMETAL) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\tint n;\n#endif\n\tunsigned int lpf \u003d info-\u003efd_limit_per_thread;\n#if defined(LWS_WITH_EVLIB_PLUGINS) \u0026\u0026 defined(LWS_WITH_EVENT_LIBS)\n\tstruct lws_plugin\t\t*evlib_plugin_list \u003d NULL;\n#if defined(_DEBUG) \u0026\u0026 !defined(LWS_WITH_NO_LOGS)\n\tchar\t\t*ld_env;\n#endif\n#endif\n#if defined(LWS_WITH_LIBUV)\n\tchar fatal_exit_defer \u003d 0;\n#endif\n\n\n\tif (lws_fi(\u0026info-\u003efic, \u0022ctx_createfail1\u0022))\n\t\tgoto early_bail;\n\n\tif (lpf) {\n\t\tlpf+\u003d 2;\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\t\tlpf++;\n#endif\n#if defined(LWS_WITH_SYS_NTPCLIENT)\n\t\tlpf++;\n#endif\n#if defined(LWS_WITH_SYS_DHCP_CLIENT)\n\t\tlpf++;\n#endif\n\t}\n\n#if defined(LWS_WITH_IPV6) \u0026\u0026 !defined(LWS_WITH_NO_LOGS)\n\tif (!lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_DISABLE_IPV6))\n\t\ts \u003d \u0022IPV6-on\u0022;\n\telse\n\t\ts \u003d \u0022IPV6-off\u0022;\n#endif\n\n\tif (lws_plat_context_early_init())\n\t\tgoto early_bail;\n\n#if defined(LWS_WITH_NETWORK)\n\tif (info-\u003ecount_threads)\n\t\tcount_threads \u003d (unsigned short)info-\u003ecount_threads;\n\n\tif (count_threads \u003e LWS_MAX_SMP)\n\t\tcount_threads \u003d LWS_MAX_SMP;\n\n\tif (info-\u003ept_serv_buf_size)\n\t\ts1 \u003d info-\u003ept_serv_buf_size;\n\n\t/* pt fakewsi and the pt serv buf allocations ride after the context */\n\tsize +\u003d count_threads * s1;\n#if !defined(LWS_PLAT_FREERTOS)\n\tsize +\u003d (count_threads * sizeof(struct lws));\n#endif\n\n\tif (info-\u003eevent_lib_custom) {\n\t\tplev \u003d info-\u003eevent_lib_custom;\n\t\tus_wait_resolution \u003d 0;\n\t}\n#if defined(LWS_WITH_POLL)\n\telse {\n\t\textern const lws_plugin_evlib_t evlib_poll;\n\t\tplev \u003d \u0026evlib_poll;\n#if !defined(LWS_PLAT_FREERTOS)\n\t\t/*\n\t\t * ... freertos has us-resolution select()...\n\t\t * others are to ms-resolution poll()\n\t\t */\n\t\tus_wait_resolution \u003d 1000;\n#endif\n\t}\n#endif\n\n#if defined(LWS_WITH_EVLIB_PLUGINS) \u0026\u0026 defined(LWS_WITH_EVENT_LIBS)\n\n\t/*\n\t * New style dynamically loaded event lib support\n\t *\n\t * We have to pick and load the event lib plugin before we allocate\n\t * the context object, so we can overallocate it correctly\n\t */\n\n#if defined(_DEBUG) \u0026\u0026 !defined(LWS_WITH_NO_LOGS)\n\tld_env \u003d getenv(\u0022LD_LIBRARY_PATH\u0022);\n\tlwsl_info(\u0022%s: ev lib path %s, '%s'\u005cn\u0022, __func__,\n\t\t\tLWS_INSTALL_LIBDIR, ld_env);\n#endif\n\n\tfor (n \u003d 0; n \u003c (int)LWS_ARRAY_SIZE(map); n++) {\n\t\tchar ok \u003d 0;\n\n\t\tif (!lws_check_opt(info-\u003eoptions, map[n].flag))\n\t\t\tcontinue;\n\n\t\tif (!lws_plugins_init(\u0026evlib_plugin_list,\n\t\t\t\t dlist, \u0022lws_evlib_plugin\u0022,\n\t\t\t\t map[n].name, NULL, NULL))\n\t\t\tok \u003d 1;\n\n\t\tif (!ok || lws_fi(\u0026info-\u003efic, \u0022ctx_createfail_plugin_init\u0022)) {\n\t\t\tlwsl_err(\u0022%s: failed to load %s\u005cn\u0022, __func__,\n\t\t\t\t\tmap[n].name);\n\t\t\tgoto bail;\n\t\t}\n\n#if defined(LWS_WITH_LIBUV)\n\t\tif (!n) /* libuv */\n\t\t\tfatal_exit_defer \u003d !!info-\u003eforeign_loops;\n#endif\n\n\t\tif (!evlib_plugin_list ||\n\t\t lws_fi(\u0026info-\u003efic, \u0022ctx_createfail_evlib_plugin\u0022)) {\n\t\t\tlwsl_err(\u0022%s: unable to load evlib plugin %s\u005cn\u0022,\n\t\t\t\t\t__func__, map[n].name);\n\n\t\t\tgoto bail;\n\t\t}\n\t\tplev \u003d (const lws_plugin_evlib_t *)evlib_plugin_list-\u003ehdr;\n\t\tbreak;\n\t}\n#else\n#if defined(LWS_WITH_EVENT_LIBS)\n\t/*\n\t * set the context event loops ops struct\n\t *\n\t * after this, all event_loop actions use the generic ops\n\t */\n\n\t/*\n\t * oldstyle built-in event lib support\n\t *\n\t * We have composed them into the libwebsockets lib itself, we can\n\t * just pick the ops we want and done\n\t */\n\n#if defined(LWS_WITH_LIBUV)\n\tif (lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_LIBUV)) {\n\t\textern const lws_plugin_evlib_t evlib_uv;\n\t\tplev \u003d \u0026evlib_uv;\n\t\tfatal_exit_defer \u003d !!info-\u003eforeign_loops;\n\t\tus_wait_resolution \u003d 0;\n\t}\n#endif\n\n#if defined(LWS_WITH_LIBEVENT)\n\tif (lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_LIBEVENT)) {\n\t\textern const lws_plugin_evlib_t evlib_event;\n\t\tplev \u003d \u0026evlib_event;\n\t\tus_wait_resolution \u003d 0;\n\t}\n#endif\n\n#if defined(LWS_WITH_GLIB)\n\tif (lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_GLIB)) {\n\t\textern const lws_plugin_evlib_t evlib_glib;\n\t\tplev \u003d \u0026evlib_glib;\n\t\tus_wait_resolution \u003d 0;\n\t}\n#endif\n\n#if defined(LWS_WITH_LIBEV)\n\tif (lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_LIBEV)) {\n\t\textern const lws_plugin_evlib_t evlib_ev;\n\t\tplev \u003d \u0026evlib_ev;\n\t\tus_wait_resolution \u003d 0;\n\t}\n#endif\n\n#if defined(LWS_WITH_SDEVENT)\n if (lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_SDEVENT)) {\n extern const lws_plugin_evlib_t evlib_sd;\n plev \u003d \u0026evlib_sd;\n us_wait_resolution \u003d 0;\n }\n#endif\n\n#if defined(LWS_WITH_ULOOP)\n if (lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_ULOOP)) {\n extern const lws_plugin_evlib_t evlib_uloop;\n plev \u003d \u0026evlib_uloop;\n us_wait_resolution \u003d 0;\n }\n#endif\n\n#endif /* with event libs */\n\n#endif /* not with ev plugins */\n\n\tif (!plev || lws_fi(\u0026info-\u003efic, \u0022ctx_createfail_evlib_sel\u0022))\n\t\tgoto fail_event_libs;\n\n#if defined(LWS_WITH_NETWORK)\n\tsize +\u003d (size_t)plev-\u003eops-\u003eevlib_size_ctx /* the ctx evlib priv */ +\n\t\t(count_threads * (size_t)plev-\u003eops-\u003eevlib_size_pt) /* the pt evlib priv */;\n#endif\n\n\tcontext \u003d lws_zalloc(size, \u0022context\u0022);\n\tif (!context || lws_fi(\u0026info-\u003efic, \u0022ctx_createfail_oom_ctx\u0022)) {\n#if defined(LWS_WITH_SYS_FAULT_INJECTION)\n\t\tlws_free(context);\n#endif\n\t\tlwsl_err(\u0022OOM\u0022);\n\t\tgoto early_bail;\n\t}\n\n#if defined(LWS_WITH_SYS_STATE)\n // NOTE: we need to init this fields because they may be used in logger when context destroying\n\tcontext-\u003emgr_system.state_names \u003d system_state_names;\n\tcontext-\u003emgr_system.context \u003d context;\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\tcontext-\u003eevent_loop_ops \u003d plev-\u003eops;\n\tcontext-\u003eus_wait_resolution \u003d us_wait_resolution;\n#if defined(LWS_WITH_TLS_JIT_TRUST)\n\t{\n\t\tstruct lws_cache_creation_info ci;\n\n\t\tmemset(\u0026ci, 0, sizeof(ci));\n\t\tci.cx \u003d context;\n\t\tci.ops \u003d \u0026lws_cache_ops_heap;\n\t\tci.name \u003d \u0022jitt\u0022;\n\t\tci.max_footprint \u003d info-\u003ejitt_cache_max_footprint;\n\t\tcontext-\u003etrust_cache \u003d lws_cache_create(\u0026ci);\n\t}\n#endif\n#endif\n#if defined(LWS_WITH_EVENT_LIBS)\n\t/* at the very end */\n\tcontext-\u003eevlib_ctx \u003d (uint8_t *)context + size -\n\t\t\t\t\tplev-\u003eops-\u003eevlib_size_ctx;\n#endif\n#if defined(LWS_WITH_EVLIB_PLUGINS) \u0026\u0026 defined(LWS_WITH_EVENT_LIBS)\n\tcontext-\u003eevlib_plugin_list \u003d evlib_plugin_list;\n#endif\n\n#if !defined(LWS_PLAT_FREERTOS)\n\tcontext-\u003euid \u003d info-\u003euid;\n\tcontext-\u003egid \u003d info-\u003egid;\n\tcontext-\u003eusername \u003d info-\u003eusername;\n\tcontext-\u003egroupname \u003d info-\u003egroupname;\n#endif\n\tcontext-\u003ename\t\t\t\u003d info-\u003evhost_name;\n\tif (info-\u003elog_cx)\n\t\tcontext-\u003elog_cx \u003d info-\u003elog_cx;\n\telse\n\t\tcontext-\u003elog_cx \u003d \u0026log_cx;\n\tlwsl_refcount_cx(context-\u003elog_cx, 1);\n\n\tcontext-\u003esystem_ops \u003d info-\u003esystem_ops;\n\tcontext-\u003ept_serv_buf_size \u003d (unsigned int)s1;\n\tcontext-\u003eprotocols_copy \u003d info-\u003eprotocols;\n#if defined(LWS_WITH_TLS_JIT_TRUST)\n\tcontext-\u003evh_idle_grace_ms \u003d info-\u003evh_idle_grace_ms ?\n\t\t\tinfo-\u003evh_idle_grace_ms : 5000;\n#endif\n\n#if defined(LWS_WITH_SYS_FAULT_INJECTION)\n\tcontext-\u003efic.name \u003d \u0022ctx\u0022;\n\tif (info-\u003efic.fi_owner.count)\n\t\t/*\n\t\t * This moves all the lws_fi_t from info-\u003efi to the context fi,\n\t\t * leaving it empty, so no injection added to default vhost\n\t\t */\n\t\tlws_fi_import(\u0026context-\u003efic, \u0026info-\u003efic);\n#endif\n\n\n#if defined(LWS_WITH_SYS_SMD)\n\tcontext-\u003esmd_ttl_us \u003d info-\u003esmd_ttl_us ? info-\u003esmd_ttl_us :\n#if defined(LWS_PLAT_FREERTOS)\n\t\t\t5000000;\n#else\n\t\t\t2000000;\n#endif\n\tcontext-\u003esmd_queue_depth \u003d (uint16_t)(info-\u003esmd_queue_depth ?\n\t\t\t\t\t\tinfo-\u003esmd_queue_depth :\n#if defined(LWS_PLAT_FREERTOS)\n\t\t\t\t\t\t20);\n#else\n\t\t\t\t\t\t40);\n#endif\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\tcontext-\u003elcg[LWSLCG_WSI].tag_prefix \u003d \u0022wsi\u0022;\n\tcontext-\u003elcg[LWSLCG_VHOST].tag_prefix \u003d \u0022vh\u0022;\n\tcontext-\u003elcg[LWSLCG_WSI_SERVER].tag_prefix \u003d \u0022wsisrv\u0022; /* adopted */\n\n#if defined(LWS_ROLE_H2) || defined(LWS_ROLE_MQTT)\n\tcontext-\u003elcg[LWSLCG_WSI_MUX].tag_prefix \u003d \u0022mux\u0022; /* a mux child wsi */\n#endif\n\n#if defined(LWS_WITH_CLIENT)\n\tcontext-\u003elcg[LWSLCG_WSI_CLIENT].tag_prefix \u003d \u0022wsicli\u0022;\n#endif\n\n#if defined(LWS_WITH_SECURE_STREAMS)\n#if defined(LWS_WITH_CLIENT)\n\tcontext-\u003elcg[LWSLCG_SS_CLIENT].tag_prefix \u003d \u0022SScli\u0022;\n#endif\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003elcg[LWSLCG_SS_SERVER].tag_prefix \u003d \u0022SSsrv\u0022;\n#endif\n#if defined(LWS_WITH_CLIENT)\n\tcontext-\u003elcg[LWSLCG_WSI_SS_CLIENT].tag_prefix \u003d \u0022wsiSScli\u0022;\n#endif\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003elcg[LWSLCG_WSI_SS_SERVER].tag_prefix \u003d \u0022wsiSSsrv\u0022;\n#endif\n#endif\n#endif\n\n#if defined(LWS_WITH_SYS_METRICS)\n\t/*\n\t * If we're not using secure streams, we can still pass in a linked-\n\t * list of metrics policies\n\t */\n\tcontext-\u003emetrics_policies \u003d info-\u003emetrics_policies;\n\tcontext-\u003emetrics_prefix \u003d info-\u003emetrics_prefix;\n\n\tcontext-\u003emt_service \u003d lws_metric_create(context,\n\t\t\t\t\tLWSMTFL_REPORT_DUTY_WALLCLOCK_US |\n\t\t\t\t\tLWSMTFL_REPORT_ONLY_GO, \u0022cpu.svc\u0022);\n\n#if defined(LWS_WITH_CLIENT)\n\n\tcontext-\u003emt_conn_dns \u003d lws_metric_create(context,\n\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t \u0022n.cn.dns\u0022);\n\tcontext-\u003emt_conn_tcp \u003d lws_metric_create(context,\n\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t \u0022n.cn.tcp\u0022);\n\tcontext-\u003emt_conn_tls \u003d lws_metric_create(context,\n\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t \u0022n.cn.tls\u0022);\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\tcontext-\u003emt_http_txn \u003d lws_metric_create(context,\n\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t \u0022n.http.txn\u0022);\n#endif\n\n\tcontext-\u003emth_conn_failures \u003d lws_metric_create(context,\n\t\t\t\t\tLWSMTFL_REPORT_HIST, \u0022n.cn.failures\u0022);\n\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\tcontext-\u003emt_adns_cache \u003d lws_metric_create(context,\n\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t \u0022n.cn.adns\u0022);\n#endif\n#if defined(LWS_WITH_SECURE_STREAMS)\n\tcontext-\u003emth_ss_conn \u003d lws_metric_create(context, LWSMTFL_REPORT_HIST,\n\t\t\t\t\t\t \u0022n.ss.conn\u0022);\n#endif\n#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n\tcontext-\u003emt_ss_cliprox_conn \u003d lws_metric_create(context,\n\t\t\tLWSMTFL_REPORT_HIST,\n\t\t\t\t\t\t\t\u0022n.ss.cliprox.conn\u0022);\n\tcontext-\u003emt_ss_cliprox_paylat \u003d lws_metric_create(context,\n\t\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t\t \u0022n.ss.cliprox.paylat\u0022);\n\tcontext-\u003emt_ss_proxcli_paylat \u003d lws_metric_create(context,\n\t\t\t\t\t\t\t LWSMTFL_REPORT_MEAN |\n\t\t\t\t\t\t\t LWSMTFL_REPORT_DUTY_WALLCLOCK_US,\n\t\t\t\t\t\t\t \u0022n.ss.proxcli.paylat\u0022);\n#endif\n\n#endif /* network + metrics + client */\n\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003emth_srv \u003d lws_metric_create(context,\n\t\t\t\t\t LWSMTFL_REPORT_HIST, \u0022n.srv\u0022);\n#endif /* network + metrics + server */\n\n#endif /* network + metrics */\n\n#endif /* network */\n\n#if defined(LWS_WITH_MBEDTLS)\n\t{\n\t\tchar mbedtls_version[32];\n\n#if defined(MBEDTLS_VERSION_C)\n\t\tmbedtls_version_get_string(mbedtls_version);\n#else\n\t\tlws_snprintf(mbedtls_version, sizeof(mbedtls_version), \u0022%s\u0022, MBEDTLS_VERSION_STRING);\n#endif\n\t\tlwsl_cx_notice(context, \u0022LWS: %s, MbedTLS-%s %s%s\u0022, library_version, mbedtls_version, opts_str, s);\n\t}\n#else\n\tlwsl_cx_notice(context, \u0022LWS: %s, %s%s\u0022, library_version, opts_str, s);\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\tlwsl_cx_info(context, \u0022Event loop: %s\u0022, plev-\u003eops-\u003ename);\n#endif\n\n\t/*\n\t * Proxy group\n\t */\n\n#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n#if defined(LWS_WITH_CLIENT)\n\tcontext-\u003elcg[LWSLCG_SSP_CLIENT].tag_prefix \u003d \u0022SSPcli\u0022;\n#endif\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003elcg[LWSLCG_SSP_ONWARD].tag_prefix \u003d \u0022SSPonw\u0022;\n#endif\n#if defined(LWS_WITH_CLIENT)\n\tcontext-\u003elcg[LWSLCG_WSI_SSP_CLIENT].tag_prefix \u003d \u0022wsiSSPcli\u0022;\n#endif\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003elcg[LWSLCG_WSI_SSP_ONWARD].tag_prefix \u003d \u0022wsiSSPonw\u0022;\n#endif\n#endif\n\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003elcg[LWSLCG_WSI_SSP_SINK].tag_prefix \u003d \u0022SSsink\u0022;\n\tcontext-\u003elcg[LWSLCG_WSI_SSP_SOURCE].tag_prefix \u003d \u0022SSsrc\u0022;\n#endif\n\n#if defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\t/* directly use the user-provided policy object list */\n\tcontext-\u003epss_policies \u003d info-\u003epss_policies;\n#endif\n\n#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) \u0026\u0026 defined(LWS_WITH_CLIENT)\n\tcontext-\u003ess_proxy_bind \u003d info-\u003ess_proxy_bind;\n\tcontext-\u003ess_proxy_port \u003d info-\u003ess_proxy_port;\n\tcontext-\u003ess_proxy_address \u003d info-\u003ess_proxy_address;\n\n\tif (info-\u003etxp_ops_ssproxy)\n\t\tcontext-\u003etxp_ppath.ops_onw \u003d info-\u003etxp_ops_ssproxy;\n\telse\n\t\tcontext-\u003etxp_ppath.ops_onw \u003d \u0026txp_ops_ssproxy_wsi;\n\tif (info-\u003etxp_ops_sspc)\n\t\tcontext-\u003etxp_cpath.ops_onw \u003d info-\u003etxp_ops_sspc;\n\telse\n\t\tcontext-\u003etxp_cpath.ops_onw \u003d \u0026txp_ops_sspc_wsi;\n\n\tcontext-\u003etxp_ssproxy_info \u003d info-\u003etxp_ssproxy_info;\n\n\tif (context-\u003ess_proxy_bind \u0026\u0026 context-\u003ess_proxy_address)\n\t\tlwsl_cx_notice(context, \u0022ss proxy bind '%s', port %d, ads '%s'\u0022,\n\t\t\tcontext-\u003ess_proxy_bind, context-\u003ess_proxy_port,\n\t\t\tcontext-\u003ess_proxy_address);\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\tcontext-\u003eundestroyed_threads \u003d count_threads;\n\tcontext-\u003ecount_threads \u003d count_threads;\n\n#if defined(LWS_ROLE_WS) \u0026\u0026 defined(LWS_WITHOUT_EXTENSIONS)\n if (info-\u003eextensions)\n lwsl_cx_warn(context, \u0022WITHOUT_EXTENSIONS but exts ptr set\u0022);\n#endif\n#endif /* network */\n\n#if defined(LWS_WITH_SECURE_STREAMS)\n#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\tcontext-\u003epss_policies_json \u003d info-\u003epss_policies_json;\n#endif\n#endif\n\n\t/* if he gave us names, set the uid / gid */\n\tif (lws_plat_drop_app_privileges(context, 0) ||\n\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_privdrop\u0022))\n\t\tgoto free_context_fail2;\n\n#if defined(LWS_WITH_TLS) \u0026\u0026 defined(LWS_WITH_NETWORK)\n#if defined(LWS_WITH_MBEDTLS)\n\tcontext-\u003etls_ops \u003d \u0026tls_ops_mbedtls;\n\n\tmbedtls_client_preload_filepath \u003d info-\u003embedtls_client_preload_filepath;\n#else\n\tcontext-\u003etls_ops \u003d \u0026tls_ops_openssl;\n#endif\n#endif\n\n#if LWS_MAX_SMP \u003e 1\n\tlws_mutex_refcount_init(\u0026context-\u003emr);\n#endif\n\n#if defined(LWS_PLAT_FREERTOS)\n#if defined(LWS_AMAZON_RTOS)\n\tcontext-\u003elast_free_heap \u003d xPortGetFreeHeapSize();\n#else\n\tcontext-\u003elast_free_heap \u003d esp_get_free_heap_size();\n#endif\n#endif\n\n#if defined(LWS_WITH_FILE_OPS)\n\t/* default to just the platform fops implementation */\n\n\tcontext-\u003efops_platform.LWS_FOP_OPEN\t\u003d _lws_plat_file_open;\n\tcontext-\u003efops_platform.LWS_FOP_CLOSE\t\u003d _lws_plat_file_close;\n\tcontext-\u003efops_platform.LWS_FOP_SEEK_CUR\t\u003d _lws_plat_file_seek_cur;\n\tcontext-\u003efops_platform.LWS_FOP_READ\t\u003d _lws_plat_file_read;\n\tcontext-\u003efops_platform.LWS_FOP_WRITE\t\u003d _lws_plat_file_write;\n\tcontext-\u003efops_platform.fi[0].sig\t\u003d NULL;\n\tcontext-\u003efops_platform.cx\t\t\u003d context;\n\n\t/*\n\t * arrange a linear linked-list of fops starting from context-\u003efops\n\t *\n\t * platform fops\n\t * [ -\u003e fops_zip (copied into context so .next settable) ]\n\t * [ -\u003e info-\u003efops ]\n\t */\n\n\tcontext-\u003efops \u003d \u0026context-\u003efops_platform;\n\tprev \u003d (struct lws_plat_file_ops *)context-\u003efops;\n\n#if defined(LWS_WITH_ZIP_FOPS)\n\t/* make a soft copy so we can set .next */\n\tcontext-\u003efops_zip \u003d fops_zip;\n\tprev-\u003enext \u003d \u0026context-\u003efops_zip;\n\tcontext-\u003efops_zip.cx \u003d context;\n\tprev \u003d (struct lws_plat_file_ops *)prev-\u003enext;\n#endif\n\n\t/* if user provided fops, tack them on the end of the list */\n\tif (info-\u003efops)\n\t\tprev-\u003enext \u003d info-\u003efops;\n#endif\n\n#if defined(LWS_WITH_SERVER)\n\tcontext-\u003ereject_service_keywords \u003d info-\u003ereject_service_keywords;\n#endif\n\tif (info-\u003eexternal_baggage_free_on_destroy)\n\t\tcontext-\u003eexternal_baggage_free_on_destroy \u003d\n\t\t\tinfo-\u003eexternal_baggage_free_on_destroy;\n#if defined(LWS_WITH_NETWORK)\n\tcontext-\u003etime_up \u003d lws_now_usecs();\n#endif\n\tcontext-\u003epcontext_finalize \u003d info-\u003epcontext;\n\n#if defined(LWS_WITH_TLS) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\tcontext-\u003esimultaneous_ssl_restriction \u003d\n\t\t\tinfo-\u003esimultaneous_ssl_restriction;\n\tcontext-\u003esimultaneous_ssl_handshake_restriction \u003d\n\t\t\tinfo-\u003esimultaneous_ssl_handshake_restriction;\n#endif\n\n\tcontext-\u003eoptions \u003d info-\u003eoptions;\n\n#if defined(LWS_HAVE_SYS_RESOURCE_H) \u0026\u0026 !defined(LWS_PLAT_FREERTOS) \u0026\u0026 !defined(LWS_PLAT_OPTEE) \u0026\u0026 !defined(WIN32) \u0026\u0026 !defined(LWS_PLAT_BAREMETAL)\n\t/*\n\t * If asked, try to set the rlimit / ulimit for process sockets / files.\n\t * We read the effective limit in a moment, so we will find out the\n\t * real limit according to system constraints then.\n\t */\n\tif (info-\u003erlimit_nofile) {\n\t\tstruct rlimit rl;\n\n\t\trl.rlim_cur \u003d (unsigned int)info-\u003erlimit_nofile;\n\t\trl.rlim_max \u003d (unsigned int)info-\u003erlimit_nofile;\n\t\tsetrlimit(RLIMIT_NOFILE, \u0026rl);\n\t}\n#endif\n\n#ifndef LWS_NO_DAEMONIZE\n\tif (pid_daemon) {\n\t\tcontext-\u003estarted_with_parent \u003d pid_daemon;\n\t\tlwsl_cx_info(context, \u0022 Started with daemon pid %u\u0022,\n\t\t\t\t(unsigned int)pid_daemon);\n\t}\n#endif\n#if defined(__ANDROID__)\n\tn \u003d getrlimit(RLIMIT_NOFILE, \u0026rt);\n\tif (n \u003d\u003d -1) {\n\t\tlwsl_cx_err(context, \u0022Get RLIMIT_NOFILE failed!\u0022);\n\n\t\tgoto free_context_fail2;\n\t}\n\tcontext-\u003emax_fds \u003d (unsigned int)rt.rlim_cur;\n#else\n#if defined(WIN32) || defined(_WIN32) || defined(LWS_AMAZON_RTOS) || defined(LWS_ESP_PLATFORM)\n\tcontext-\u003emax_fds \u003d getdtablesize();\n#else\n\t{\n\t\tlong l \u003d sysconf(_SC_OPEN_MAX);\n\n\t\tcontext-\u003emax_fds \u003d 2560;\n\n\t\tif (l \u003e 10000000)\n\t\t\tlwsl_cx_warn(context, \u0022unreasonable ulimit -n workaround\u0022);\n\t\telse\n\t\t\tif (l !\u003d -1l)\n\t\t\t\tcontext-\u003emax_fds \u003d (unsigned int)l;\n\t}\n#endif\n\tif ((int)context-\u003emax_fds \u003c 0 ||\n\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_maxfds\u0022)) {\n\t\tlwsl_cx_err(context, \u0022problem getting process max files\u0022);\n\n\t\tgoto free_context_fail2;\n\t}\n#endif\n\n\t/*\n\t * deal with any max_fds override, if it's reducing (setting it to\n\t * more than ulimit -n is meaningless). The platform init will\n\t * figure out what if this is something it can deal with.\n\t */\n\tif (info-\u003efd_limit_per_thread) {\n\t\tunsigned int mf \u003d lpf * context-\u003ecount_threads;\n\n\t\tif (mf \u003c context-\u003emax_fds) {\n\t\t\tcontext-\u003emax_fds_unrelated_to_ulimit \u003d 1;\n\t\t\tcontext-\u003emax_fds \u003d mf;\n\t\t}\n\t}\n\n#if defined(LWS_WITH_NETWORK)\n\tcontext-\u003etoken_limits \u003d info-\u003etoken_limits;\n#endif\n\n\n#if defined(LWS_WITH_TLS) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\ttime(\u0026context-\u003etls.last_cert_check_s);\n\tif (info-\u003ealpn)\n\t\tcontext-\u003etls.alpn_default \u003d info-\u003ealpn;\n\telse {\n\t\tchar *p \u003d context-\u003etls.alpn_discovered, first \u003d 1;\n\n\t\tLWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {\n\t\t\tif (ar-\u003ealpn) {\n\t\t\t\tif (!first)\n\t\t\t\t\t*p++ \u003d ',';\n\t\t\t\tp +\u003d lws_snprintf(p, (unsigned int)(\n\t\t\t\t\t(context-\u003etls.alpn_discovered +\n\t\t\t\t\tsizeof(context-\u003etls.alpn_discovered) -\n\t\t\t\t\t2) - p), \u0022%s\u0022, ar-\u003ealpn);\n\t\t\t\tfirst \u003d 0;\n\t\t\t}\n\t\t} LWS_FOR_EVERY_AVAILABLE_ROLE_END;\n\n\t\tcontext-\u003etls.alpn_default \u003d context-\u003etls.alpn_discovered;\n\t}\n\n#endif\n\n\tcontext-\u003etimeout_secs \u003d 15;\n\n#if defined(LWS_WITH_NETWORK)\n#if defined(WIN32)\n\tif (!info-\u003ewin32_connect_check_interval_usec)\n\t\tcontext-\u003ewin32_connect_check_interval_usec \u003d 1000;\n\telse\n\t\tcontext-\u003ewin32_connect_check_interval_usec \u003d\n\t\t\t\tinfo-\u003ewin32_connect_check_interval_usec;\n#endif\n\tif (info-\u003etimeout_secs)\n\t\tcontext-\u003etimeout_secs \u003d info-\u003etimeout_secs;\n#endif /* WITH_NETWORK */\n\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\tif (info-\u003emax_http_header_data)\n\t\tcontext-\u003emax_http_header_data \u003d info-\u003emax_http_header_data;\n\telse\n\t\tif (info-\u003emax_http_header_data2)\n\t\t\tcontext-\u003emax_http_header_data \u003d\n\t\t\t\t\t(unsigned short)info-\u003emax_http_header_data2;\n\t\telse\n\t\t\tcontext-\u003emax_http_header_data \u003d LWS_DEF_HEADER_LEN;\n\n\tif (info-\u003emax_http_header_pool)\n\t\tcontext-\u003emax_http_header_pool \u003d info-\u003emax_http_header_pool;\n\telse\n\t\tif (info-\u003emax_http_header_pool2)\n\t\t\tcontext-\u003emax_http_header_pool \u003d\n\t\t\t\t\t(unsigned short)info-\u003emax_http_header_pool2;\n\t\telse\n\t\t\tcontext-\u003emax_http_header_pool \u003d context-\u003emax_fds;\n#endif\n\n\tif (info-\u003efd_limit_per_thread)\n\t\tcontext-\u003efd_limit_per_thread \u003d lpf;\n\telse\n\t\tif (context-\u003ecount_threads)\n\t\t\tcontext-\u003efd_limit_per_thread \u003d context-\u003emax_fds /\n\t\t\t\t\t\t\tcontext-\u003ecount_threads;\n\n#if defined(LWS_WITH_SYS_SMD)\n\tlws_mutex_init(context-\u003esmd.lock_messages);\n\tlws_mutex_init(context-\u003esmd.lock_peers);\n\n\t/* lws_system smd participant */\n\n\tif (!lws_smd_register(context, context, 0, LWSSMDCL_NETWORK,\n\t\t\t lws_system_smd_cb)) {\n\t\tlwsl_cx_err(context, \u0022early smd register failed\u0022);\n\t}\n\n\t/* user smd participant */\n\n\tif (info-\u003eearly_smd_cb \u0026\u0026\n\t !lws_smd_register(context, info-\u003eearly_smd_opaque, 0,\n\t\t\t info-\u003eearly_smd_class_filter,\n\t\t\t info-\u003eearly_smd_cb)) {\n\t\tlwsl_cx_err(context, \u0022early smd register failed\u0022);\n\t}\n#endif\n\n#if !defined(LWS_PLAT_BAREMETAL) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\tn \u003d 0;\n#endif\n#if defined(LWS_WITH_NETWORK)\n\n\tcontext-\u003edefault_retry.retry_ms_table \u003d default_backoff_table;\n\tcontext-\u003edefault_retry.conceal_count \u003d\n\t\t\tcontext-\u003edefault_retry.retry_ms_table_count \u003d\n\t\t\t\t\tLWS_ARRAY_SIZE(default_backoff_table);\n\tcontext-\u003edefault_retry.jitter_percent \u003d 20;\n\tcontext-\u003edefault_retry.secs_since_valid_ping \u003d 300;\n\tcontext-\u003edefault_retry.secs_since_valid_hangup \u003d 310;\n\n\tif (info-\u003eretry_and_idle_policy \u0026\u0026\n\t info-\u003eretry_and_idle_policy-\u003esecs_since_valid_ping) {\n\t\tcontext-\u003edefault_retry.secs_since_valid_ping \u003d\n\t\t\t\tinfo-\u003eretry_and_idle_policy-\u003esecs_since_valid_ping;\n\t\tcontext-\u003edefault_retry.secs_since_valid_hangup \u003d\n\t\t\t\tinfo-\u003eretry_and_idle_policy-\u003esecs_since_valid_hangup;\n\t}\n\n\t/*\n\t * Allocate the per-thread storage for scratchpad buffers,\n\t * and header data pool\n\t */\n\tu \u003d (uint8_t *)\u0026context[1];\n\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\tcontext-\u003ept[n].serv_buf \u003d u;\n\t\tu +\u003d context-\u003ept_serv_buf_size;\n\n\t\tcontext-\u003ept[n].context \u003d context;\n\t\tcontext-\u003ept[n].tid \u003d (uint8_t)n;\n\n#if !defined(LWS_PLAT_FREERTOS)\n\t\t/*\n\t\t * We overallocated for a fakewsi (can't compose it in the\n\t\t * pt because size isn't known at that time). point to it\n\t\t * and zero it down. Fakewsis are needed to make callbacks work\n\t\t * when the source of the callback is not actually from a wsi\n\t\t * context.\n\t\t */\n\t\tcontext-\u003ept[n].fake_wsi \u003d (struct lws *)u;\n\t\tu +\u003d sizeof(struct lws);\n\n\t\tmemset(context-\u003ept[n].fake_wsi, 0, sizeof(struct lws));\n#endif\n\n\t\tcontext-\u003ept[n].evlib_pt \u003d u;\n\t\tu +\u003d plev-\u003eops-\u003eevlib_size_pt;\n\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\t\tcontext-\u003ept[n].http.ah_list \u003d NULL;\n\t\tcontext-\u003ept[n].http.ah_pool_length \u003d 0;\n#endif\n\t\tlws_pt_mutex_init(\u0026context-\u003ept[n]);\n\n#if defined(LWS_WITH_CGI)\n\t\tif (lws_rops_fidx(\u0026role_ops_cgi, LWS_ROPS_pt_init_destroy))\n\t\t\t(lws_rops_func_fidx(\u0026role_ops_cgi, LWS_ROPS_pt_init_destroy)).\n\t\t\t\tpt_init_destroy(context, info,\n\t\t\t\t\t\t\u0026context-\u003ept[n], 0);\n#endif\n\t}\n\n\tif (!info-\u003eka_interval \u0026\u0026 info-\u003eka_time \u003e 0) {\n\t\tlwsl_cx_err(context, \u0022info-\u003eka_interval can't be 0 if ka_time used\u0022);\n\t\tgoto free_context_fail;\n\t}\n\n#if defined(LWS_WITH_PEER_LIMITS)\n\t/* scale the peer hash table according to the max fds for the process,\n\t * so that the max list depth averages 16. Eg, 1024 fd -\u003e 64,\n\t * 102400 fd -\u003e 6400\n\t */\n\n\tcontext-\u003epl_hash_elements \u003d\n\t\t(context-\u003ecount_threads * context-\u003efd_limit_per_thread) / 16;\n\tcontext-\u003epl_hash_table \u003d lws_zalloc(sizeof(struct lws_peer *) *\n\t\t\tcontext-\u003epl_hash_elements, \u0022peer limits hash table\u0022);\n\n\tcontext-\u003eip_limit_ah \u003d info-\u003eip_limit_ah;\n\tcontext-\u003eip_limit_wsi \u003d info-\u003eip_limit_wsi;\n\tcontext-\u003epl_notify_cb \u003d info-\u003epl_notify_cb;\n#endif\n\n\t/*\n\t * fds table contains pollfd structs for as many pollfds as we can\n\t * handle... spread across as many service threads as we have going\n\t */\n\tn \u003d (int)(sizeof(struct lws_pollfd) * context-\u003ecount_threads *\n\t context-\u003efd_limit_per_thread);\n\tcontext-\u003ept[0].fds \u003d lws_zalloc((unsigned int)n, \u0022fds table\u0022);\n\tif (context-\u003ept[0].fds \u003d\u003d NULL ||\n\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_oom_fds\u0022)) {\n#if defined(LWS_WITH_SYS_FAULT_INJECTION)\n\t\tlws_free(context-\u003ept[0].fds);\n#endif\n\t\tlwsl_cx_err(context, \u0022OOM allocating %d fds\u005cn\u0022, context-\u003emax_fds);\n\t\tgoto free_context_fail;\n\t}\n#endif\n\n\tlwsl_cx_info(context, \u0022ctx: %5luB (%ld ctx + pt(%ld thr x %d)), \u0022\n\t\t \u0022pt-fds: %d\u0022,\n\t\t (long)sizeof(struct lws_context) +\n\t\t (context-\u003ecount_threads * context-\u003ept_serv_buf_size),\n\t\t (long)sizeof(struct lws_context),\n\t\t (long)context-\u003ecount_threads,\n\t\t context-\u003ept_serv_buf_size,\n\t\t context-\u003efd_limit_per_thread);\n\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\tlwsl_cx_info(context, \u0022 http: ah_data: %u, ah: %lu, max count %u\u0022,\n\t\t context-\u003emax_http_header_data,\n\t\t (long)sizeof(struct allocated_headers),\n\t\t context-\u003emax_http_header_pool);\n#endif\n\n#if defined(LWS_WITH_SERVER)\n\tif (info-\u003eserver_string) {\n\t\tcontext-\u003eserver_string \u003d info-\u003eserver_string;\n\t\tcontext-\u003eserver_string_len \u003d (short)\n\t\t\t\tstrlen(context-\u003eserver_string);\n\t}\n#endif\n\n#if LWS_MAX_SMP \u003e 1\n\t/* each thread serves his own chunk of fds */\n\tfor (n \u003d 1; n \u003c (int)context-\u003ecount_threads; n++)\n\t\tcontext-\u003ept[n].fds \u003d context-\u003ept[n - 1].fds +\n\t\t\t\t context-\u003efd_limit_per_thread;\n#endif\n\n\n\t/*\n\t * Past here, we may have added handles to the event lib\n\t * loop and if libuv, have to take care about how to unpick them...\n\t */\n\n\tif (lws_plat_init(context, info) ||\n\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_plat_init\u0022))\n\t\tgoto bail_libuv_aware;\n\n#if defined(LWS_WITH_NETWORK)\n\n\tif (lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_evlib_init\u0022))\n\t\tgoto bail_libuv_aware;\n\n\tif (context-\u003eevent_loop_ops-\u003einit_context)\n\t\tif (context-\u003eevent_loop_ops-\u003einit_context(context, info))\n\t\t\tgoto bail_libuv_aware;\n\n\tif (lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_evlib_pt\u0022))\n\t\tgoto bail_libuv_aware;\n\n\tif (context-\u003eevent_loop_ops-\u003einit_pt)\n\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\t\tvoid *lp \u003d NULL;\n\n\t\t\tif (info-\u003eforeign_loops)\n\t\t\t\tlp \u003d info-\u003eforeign_loops[n];\n\n\t\t\tif (context-\u003eevent_loop_ops-\u003einit_pt(context, lp, n))\n\t\t\t\tgoto bail_libuv_aware;\n\t\t}\n\n\tlws_context_lock(context, __func__);\n\tn \u003d __lws_create_event_pipes(context);\n\tlws_context_unlock(context);\n\tif (n)\n\t\tgoto bail_libuv_aware;\n\n\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\tLWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {\n\t\t\tif (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy))\n\t\t\t\t(lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)).\n\t\t\t\t\tpt_init_destroy(context, info,\n\t\t\t\t\t\t\t\u0026context-\u003ept[n], 0);\n\t\t} LWS_FOR_EVERY_AVAILABLE_ROLE_END;\n\t}\n#endif\n\n\tlws_context_init_ssl_library(context, info);\n\n\tcontext-\u003euser_space \u003d info-\u003euser;\n\n#if defined(LWS_WITH_SERVER)\n\tstrcpy(context-\u003ecanonical_hostname, \u0022unknown\u0022);\n#if defined(LWS_WITH_NETWORK)\n\tlws_server_get_canonical_hostname(context, info);\n#endif\n#endif\n\n#if defined(LWS_HAVE_SYS_CAPABILITY_H) \u0026\u0026 defined(LWS_HAVE_LIBCAP)\n\tmemcpy(context-\u003ecaps, info-\u003ecaps, sizeof(context-\u003ecaps));\n\tcontext-\u003ecount_caps \u003d info-\u003ecount_caps;\n#endif\n\n\n#if defined(LWS_WITH_NETWORK)\n\n#if defined(LWS_WITH_SYS_ASYNC_DNS) || defined(LWS_WITH_SYS_NTPCLIENT) || \u005c\n\tdefined(LWS_WITH_SYS_DHCP_CLIENT)\n\t{\n\t\t/*\n\t\t * system vhost\n\t\t */\n\n\t\tstruct lws_context_creation_info ii;\n\t\tconst struct lws_protocols *pp[4];\n\t\tstruct lws_vhost *vh;\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\t\textern const struct lws_protocols lws_async_dns_protocol;\n#endif\n#if defined(LWS_WITH_SYS_NTPCLIENT)\n\t\textern const struct lws_protocols lws_system_protocol_ntpc;\n#endif\n#if defined(LWS_WITH_SYS_DHCP_CLIENT)\n\t\textern const struct lws_protocols lws_system_protocol_dhcpc4;\n#endif\n\n\t\tn \u003d 0;\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\t\tpp[n++] \u003d \u0026lws_async_dns_protocol;\n#endif\n#if defined(LWS_WITH_SYS_NTPCLIENT)\n\t\tpp[n++] \u003d \u0026lws_system_protocol_ntpc;\n#endif\n#if defined(LWS_WITH_SYS_DHCP_CLIENT)\n\t\tpp[n++] \u003d \u0026lws_system_protocol_dhcpc4;\n#endif\n\t\tpp[n] \u003d NULL;\n\n\t\tmemset(\u0026ii, 0, sizeof(ii));\n\t\tii.vhost_name \u003d \u0022system\u0022;\n\t\tii.pprotocols \u003d pp;\n\t\tii.port \u003d CONTEXT_PORT_NO_LISTEN;\n\n\t\tif (lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_sys_vh\u0022))\n\t\t\tvh \u003d NULL;\n\t\telse\n\t\t\tvh \u003d lws_create_vhost(context, \u0026ii);\n\t\tif (!vh) {\n\t\t\tlwsl_cx_err(context, \u0022failed to create system vhost\u0022);\n\t\t\tgoto bail_libuv_aware;\n\t\t}\n\n\t\tcontext-\u003evhost_system \u003d vh;\n\n\t\tif (lws_protocol_init_vhost(vh, NULL) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_sys_vh_init\u0022)) {\n\t\t\tlwsl_cx_err(context, \u0022failed to init system vhost\u0022);\n\t\t\tgoto bail_libuv_aware;\n\t\t}\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\t\tlws_async_dns_init(context);\n\t\t\t//goto bail_libuv_aware;\n#endif\n\t}\n\n#endif\n\n#if defined(LWS_WITH_SYS_STATE)\n\t/*\n\t * init the lws_state mgr for the system state\n\t */\n\n\tcontext-\u003emgr_system.name\t\t\u003d \u0022system\u0022;\n\tcontext-\u003emgr_system.state\t\t\u003d LWS_SYSTATE_CONTEXT_CREATED;\n\tcontext-\u003emgr_system.parent\t\t\u003d context;\n#if defined(LWS_WITH_SYS_SMD)\n\tcontext-\u003emgr_system.smd_class\t\t\u003d LWSSMDCL_SYSTEM_STATE;\n#endif\n\n\tcontext-\u003eprotocols_notify.name\t\t\u003d \u0022prot_init\u0022;\n\tcontext-\u003eprotocols_notify.notify_cb\t\u003d lws_state_notify_protocol_init;\n\n\tlws_state_reg_notifier(\u0026context-\u003emgr_system, \u0026context-\u003eprotocols_notify);\n\n\t/*\n\t * insert user notifiers here so they can participate with vetoing us\n\t * trying to jump straight to operational, or at least observe us\n\t * reaching 'operational', before we returned from context creation.\n\t */\n\n\tlws_state_reg_notifier_list(\u0026context-\u003emgr_system,\n\t\t\t\t info-\u003eregister_notifier_list);\n#endif\n\n\t/*\n\t * if he's not saying he'll make his own vhosts later then act\n\t * compatibly and make a default vhost using the data in the info\n\t */\n\tif (!lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)\n\t\t\t|| info-\u003epprotocols) {\n\t\tif (!lws_create_vhost(context, info) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_def_vh\u0022)) {\n\t\t\tlwsl_cx_err(context, \u0022Failed to create default vhost\u0022);\n\n#if defined(LWS_WITH_PEER_LIMITS)\n\t\t\tlws_free_set_NULL(context-\u003epl_hash_table);\n#endif\n\t\t\tgoto bail;\n\t\t}\n\t}\n\n#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) \u0026\u0026 defined(LWS_WITH_CLIENT)\n\tif (info-\u003ehttp_nsc_filepath) {\n\t\tmemset(\u0026ci, 0, sizeof(ci));\n\n\t\tci.cx\t\t\t \u003d context;\n\t\tci.ops\t\t\t \u003d \u0026lws_cache_ops_nscookiejar;\n\t\tci.name\t\t\t \u003d \u0022NSC\u0022;\n\t\tci.u.nscookiejar.filepath \u003d info-\u003ehttp_nsc_filepath;\n\n\t\tcontext-\u003ensc \u003d lws_cache_create(\u0026ci);\n\t\tif (!context-\u003ensc)\n\t\t\tgoto bail;\n\n\t\tci.ops\t\t\t \u003d \u0026lws_cache_ops_heap;\n\t\tci.name\t\t\t \u003d \u0022L1\u0022;\n\t\tci.parent\t\t \u003d context-\u003ensc;\n\t\tci.max_footprint\t \u003d info-\u003ehttp_nsc_heap_max_footprint;\n\t\tci.max_items\t\t \u003d info-\u003ehttp_nsc_heap_max_items;\n\t\tci.max_payload\t\t \u003d info-\u003ehttp_nsc_heap_max_payload;\n\n\t\tcontext-\u003el1 \u003d lws_cache_create(\u0026ci);\n\t\tif (!context-\u003el1) {\n\t\t\tlwsl_cx_err(context, \u0022Failed to init cookiejar\u0022);\n\t\t\tgoto bail;\n\t\t}\n\t}\n#endif\n\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\tif (info-\u003easync_dns_servers) {\n\t\tconst char **dsrv \u003d info-\u003easync_dns_servers;\n\t\twhile (*dsrv) {\n\t\t\tlws_sockaddr46 sa46;\n\t\t\tif (!lws_sa46_parse_numeric_address(*dsrv, \u0026sa46)) {\n\t\t\t\tlwsl_cx_info(context, \u0022Adding DNS %s\u0022, *dsrv);\n\t\t\t\tlws_async_dns_server_add(context, \u0026sa46);\n\t\t\t}\n\t\t\tdsrv++;\n\t\t}\n\t}\n#endif\n\n#if defined(LWS_WITH_SECURE_STREAMS)\n\n#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\n\t\t/*\n\t\t * You must create your context with the explicit vhosts flag\n\t\t * in order to use secure streams\n\t\t */\n\tif (lws_check_opt(info-\u003eoptions,\n\t\t LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) {\n\n\t\tif (!context-\u003epss_policies_json)\n\t\t\tcontext-\u003epss_policies_json \u003d\n\t\u0022{\u005cn\u0022\n\t\t\u0022\u005c\u0022release\u005c\u0022: \u005c\u00221\u005c\u0022,\u005cn\u0022\n\t\t\u0022\u005c\u0022product\u005c\u0022: \u005c\u0022lws_default\u005c\u0022,\u005cn\u0022\n\t\t\u0022\u005c\u0022schema-version\u005c\u0022: 1,\u005cn\u0022\n\t\t\u0022\u005c\u0022retry\u005c\u0022: [{\u005cn\u0022\n\t\t\t\u0022\u005c\u0022default\u005c\u0022: {\u005cn\u0022\n\t\t\t\t\u0022\u005c\u0022backoff\u005c\u0022: [1000, 2000, 3000, 5000, 10000],\u005cn\u0022\n\t\t\t\t\u0022\u005c\u0022conceal\u005c\u0022: 5,\u005cn\u0022\n\t\t\t\t\u0022\u005c\u0022jitterpc\u005c\u0022: 20,\u005cn\u0022\n\t\t\t\t\u0022\u005c\u0022svalidping\u005c\u0022: 30,\u005cn\u0022\n\t\t\t\t\u0022\u005c\u0022svalidhup\u005c\u0022: 35\u005cn\u0022\n\t\t\t\u0022}\u005cn\u0022\n\t\t\u0022}],\u005cn\u0022\n\t\t\u0022\u005c\u0022s\u005c\u0022: [\u005cn\u0022\n\t\t\t\u0022{\u005cn\u0022\n\t\t\t\t\u0022\u005c\u0022__default\u005c\u0022: {\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022endpoint\u005c\u0022: \u005c\u0022${endpoint}\u005c\u0022,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022port\u005c\u0022: 443,\u005cn\u0022\n#if defined(LWS_WITH_HTTP2)\n\t\t\t\t\t\u0022\u005c\u0022protocol\u005c\u0022: \u005c\u0022h2\u005c\u0022,\u005cn\u0022\n#else\n\t\t\t\t\t\u0022\u005c\u0022protocol\u005c\u0022: \u005c\u0022h1\u005c\u0022,\u005cn\u0022\n#endif\n\t\t\t\t\t\u0022\u005c\u0022http_method\u005c\u0022: \u005c\u0022GET\u005c\u0022,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022http_url\u005c\u0022: \u005c\u0022\u005c\u0022,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022metadata\u005c\u0022: [{\u005cn\u0022\n\t\t\t\t\t\t\u0022\u005c\u0022endpoint\u005c\u0022:\u0022 \u0022\u005c\u0022\u005c\u0022,\u005cn\u0022\n\t\t\t\t\t\t\u0022\u005c\u0022acc\u005c\u0022:\u0022 \u0022\u005c\u0022accept\u005c\u0022,\u005cn\u0022\n\t\t\t\t\t\t\u0022\u005c\u0022ua\u005c\u0022:\u0022\t\u0022\u005c\u0022user-agent\u005c\u0022\u005cn\u0022\n\t\t\t\t\t\u0022}],\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022tls\u005c\u0022: true,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022allow_redirects\u005c\u0022: true,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022nghttp2_quirk_end_stream\u005c\u0022: true,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022h2q_oflow_txcr\u005c\u0022: true,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022direct_proto_str\u005c\u0022: true,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022opportunistic\u005c\u0022: true,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022retry\u005c\u0022: \u005c\u0022default\u005c\u0022,\u005cn\u0022\n\t\t\t\t\t\u0022\u005c\u0022timeout_ms\u005c\u0022: 2000\u005cn\u0022\n\t\t\t\t\u0022},\u005cn\u0022\n\t\t \u0022\u005c\u0022captive_portal_detect\u005c\u0022: {\u0022\n\t\t \u0022\u005c\u0022endpoint\u005c\u0022:\u0022 \u0022\u005c\u0022connectivitycheck.android.com\u005c\u0022,\u0022\n\t\t \u0022\u005c\u0022http_url\u005c\u0022:\u0022 \u0022\u005c\u0022generate_204\u005c\u0022,\u0022\n\t\t \u0022\u005c\u0022port\u005c\u0022:\u0022 \u002280,\u0022\n\t\t \u0022\u005c\u0022protocol\u005c\u0022:\u0022 \u0022\u005c\u0022h1\u005c\u0022,\u0022\n\t\t \u0022\u005c\u0022http_method\u005c\u0022:\u0022 \u0022\u005c\u0022GET\u005c\u0022,\u0022\n\t\t \u0022\u005c\u0022opportunistic\u005c\u0022:\u0022 \u0022true,\u0022\n\t\t \u0022\u005c\u0022http_expect\u005c\u0022:\u0022 \u0022204,\u0022\n\t\t \u0022\u005c\u0022http_fail_redirect\u005c\u0022: true\u005cn\u0022\n\t\t\t\t\u0022}\u005cn\u0022\n\t\t\t\u0022}\u005cn\u0022\n\t\t\u0022]\u005cn\u0022\n\t\u0022}\u005cn\u0022;\n\n\t\tif (lws_ss_policy_parse_begin(context, 0) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_ss_pol1\u0022)) {\n#if defined(LWS_WITH_SYS_FAULT_INJECTION)\n\t\t\tlws_ss_policy_parse_abandon(context);\n#endif\n\t\t\tgoto bail_libuv_aware;\n\t\t}\n\n\t\tn \u003d lws_ss_policy_parse(context,\n\t\t\t\t\t(uint8_t *)context-\u003epss_policies_json,\n\t\t\t\t\tstrlen(context-\u003epss_policies_json));\n\t\tif ((n !\u003d LEJP_CONTINUE \u0026\u0026 n \u003c 0) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_ss_pol2\u0022)) {\n\t\t\tlws_ss_policy_parse_abandon(context);\n\t\t\tgoto bail_libuv_aware;\n\t\t}\n\n\t\tif (lws_ss_policy_set(context, \u0022hardcoded\u0022) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_ss_pol3\u0022)) {\n\t\t\tlwsl_cx_err(context, \u0022policy set failed\u0022);\n\t\t\tgoto bail_libuv_aware;\n\t\t}\n\t}\n#else\n\tif (context-\u003epss_policies) {\n\t\t/* user code set the policy objects directly, no parsing step */\n\n\t\t/* you must set this content option to use SS */\n\t\tassert(lws_check_opt(info-\u003eoptions,\n\t\t\t\t LWS_SERVER_OPTION_EXPLICIT_VHOSTS));\n\n\t\tif (lws_ss_policy_set(context, \u0022hardcoded\u0022) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_ss_pol3\u0022)) {\n\t\t\tlwsl_cx_err(context, \u0022policy set failed\u0022);\n\t\t\tgoto bail_libuv_aware;\n\t\t}\n\t}\n#endif\n#endif\n\n\tlws_context_init_extensions(info, context);\n\n\tlwsl_cx_info(context, \u0022 mem: per-conn: %5lu bytes + protocol rx buf\u0022,\n\t\t (unsigned long)sizeof(struct lws));\n\n\t/*\n\t * drop any root privs for this process\n\t * to listen on port \u003c 1023 we would have needed root, but now we are\n\t * listening, we don't want the power for anything else\n\t */\n\tif (!lws_check_opt(info-\u003eoptions, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))\n\t\tif (lws_plat_drop_app_privileges(context, 1) ||\n\t\t lws_fi(\u0026context-\u003efic, \u0022ctx_createfail_privdrop\u0022))\n\t\t\tgoto bail_libuv_aware;\n\n#if defined(LWS_WITH_SYS_STATE)\n\t/*\n\t * We want to move on the syste, state as far as it can go towards\n\t * OPERATIONAL now. But we have to return from here first so the user\n\t * code that called us can set its copy of context, which it may be\n\t * relying on to perform operations triggered by the state change.\n\t *\n\t * We set up a sul to come back immediately and do the state change.\n\t */\n\n\tlws_sul_schedule(context, 0, \u0026context-\u003esul_system_state,\n\t\t\t lws_context_creation_completion_cb, 1);\n#endif\n\n\t/* expedite post-context init (eg, protocols) */\n\tlws_cancel_service(context);\n#endif\n\n\treturn context;\n\nearly_bail:\n\tlws_fi_destroy(\u0026info-\u003efic);\n\n\treturn NULL;\n\n#if defined(LWS_WITH_NETWORK)\nbail:\n\tlws_fi_destroy(\u0026info-\u003efic);\n\tlws_context_destroy(context);\n\n\treturn NULL;\n#endif\n\nbail_libuv_aware:\n\tlws_context_destroy(context);\n#if defined(LWS_WITH_LIBUV)\n\treturn fatal_exit_defer ? context : NULL;\n#else\n\treturn NULL;\n#endif\n\n#if defined(LWS_WITH_NETWORK)\nfail_event_libs:\n\tif (context)\n\tlwsl_cx_err(context, \u0022Requested event library support not configured\u0022);\n#endif\n\n#if defined(LWS_WITH_NETWORK)\nfree_context_fail:\n\tif (context) {\n#if defined(LWS_WITH_SYS_SMD)\n\t\t_lws_smd_destroy(context);\n#endif\n\t}\n#endif\nfree_context_fail2:\n\tif (context) {\n#if defined(LWS_WITH_SYS_METRICS)\n\t\tlws_metrics_destroy(context);\n#endif\n\t\tlws_fi_destroy(\u0026context-\u003efic);\n\t}\n\tlws_fi_destroy(\u0026info-\u003efic);\n\tif (context) {\n\t\tlwsl_refcount_cx(context-\u003elog_cx, -1);\n\t\tlws_free(context);\n\t}\n\n\treturn NULL;\n}\n\n#if defined(LWS_WITH_NETWORK)\nint\nlws_system_cpd_start(struct lws_context *cx)\n{\n\tcx-\u003ecaptive_portal_detect \u003d LWS_CPD_UNKNOWN;\n\n\t/* if there's a platform implementation, use it */\n\n\tif (lws_system_get_ops(cx) \u0026\u0026\n\t lws_system_get_ops(cx)-\u003ecaptive_portal_detect_request)\n\t\treturn lws_system_get_ops(cx)-\u003ecaptive_portal_detect_request(cx);\n\n#if defined(LWS_WITH_SECURE_STREAMS)\n\t/*\n\t * Otherwise try to use SS \u0022captive_portal_detect\u0022 if that's enabled\n\t */\n\treturn lws_ss_sys_cpd(cx);\n#else\n\treturn 0;\n#endif\n}\n\nstatic void\nlws_system_deferred_cb(lws_sorted_usec_list_t *sul)\n{\n\tstruct lws_context *cx \u003d\n\t\t lws_container_of(sul, struct lws_context, sul_cpd_defer);\n\n\tlws_system_cpd_start(cx);\n}\n\nvoid\nlws_system_cpd_start_defer(struct lws_context *cx, lws_usec_t defer_us)\n{\n\tlws_sul_schedule(cx, 0, \u0026cx-\u003esul_cpd_defer,\n\t\t\t lws_system_deferred_cb, defer_us);\n}\n\n#if (defined(LWS_WITH_SYS_STATE) \u0026\u0026 defined(LWS_WITH_SYS_SMD)) || !defined(LWS_WITH_NO_LOGS)\nstatic const char *cname[] \u003d { \u0022Unknown\u0022, \u0022OK\u0022, \u0022Captive\u0022, \u0022No internet\u0022 };\n#endif\n\nvoid\nlws_system_cpd_set(struct lws_context *cx, lws_cpd_result_t result)\n{\n\tif (cx-\u003ecaptive_portal_detect !\u003d LWS_CPD_UNKNOWN)\n\t\treturn;\n\n#if !defined(LWS_WITH_NO_LOGS)\n\tlwsl_cx_notice(cx, \u0022setting CPD result %s\u0022, cname[result]);\n#endif\n\n\tcx-\u003ecaptive_portal_detect \u003d (uint8_t)result;\n\n#if defined(LWS_WITH_SYS_STATE)\n#if defined(LWS_WITH_SYS_SMD)\n\tlws_smd_msg_printf(cx, LWSSMDCL_NETWORK,\n\t\t\t \u0022{\u005c\u0022type\u005c\u0022:\u005c\u0022cpd\u005c\u0022,\u005c\u0022result\u005c\u0022:\u005c\u0022%s\u005c\u0022}\u0022,\n\t\t\t cname[cx-\u003ecaptive_portal_detect]);\n#endif\n\n\t/* if nothing is there to intercept anything, go all the way */\n\tif (cx-\u003emgr_system.state !\u003d LWS_SYSTATE_POLICY_INVALID)\n\t\tlws_state_transition_steps(\u0026cx-\u003emgr_system,\n\t\t\t\t\t LWS_SYSTATE_OPERATIONAL);\n#endif\n}\n\nlws_cpd_result_t\nlws_system_cpd_state_get(struct lws_context *cx)\n{\n\treturn (lws_cpd_result_t)cx-\u003ecaptive_portal_detect;\n}\n\n#endif\n\nint\nlws_context_is_deprecated(struct lws_context *cx)\n{\n\treturn cx-\u003edeprecated;\n}\n\n/*\n * When using an event loop, the context destruction is in three separate\n * parts. This is to cover both internal and foreign event loops cleanly.\n *\n * - lws_context_destroy() simply starts a soft close of all wsi and\n * related allocations. The event loop continues.\n *\n * As the closes complete in the event loop, reference counting is used\n * to determine when everything is closed. It then calls\n * lws_context_destroy2().\n *\n * - lws_context_destroy2() cleans up the rest of the higher-level logical\n * lws pieces like vhosts. If the loop was foreign, it then proceeds to\n * lws_context_destroy3(). If it the loop is internal, it stops the\n * internal loops and waits for lws_context_destroy() to be called again\n * outside the event loop (since we cannot destroy the loop from\n * within the loop). That will cause lws_context_destroy3() to run\n * directly.\n *\n * - lws_context_destroy3() destroys any internal event loops and then\n * destroys the context itself, setting what was info.pcontext to NULL.\n */\n\n\n#if defined(LWS_WITH_NETWORK)\nstatic void\nlws_pt_destroy(struct lws_context_per_thread *pt)\n{\n\tvolatile struct lws_foreign_thread_pollfd *ftp, *next;\n\tvolatile struct lws_context_per_thread *vpt;\n#if defined(LWS_WITH_CGI)\n\tlws_ctx_t ctx \u003d pt-\u003econtext;\n\n\t\tif (lws_rops_fidx(\u0026role_ops_cgi, LWS_ROPS_pt_init_destroy))\n\t\t\t(lws_rops_func_fidx(\u0026role_ops_cgi, LWS_ROPS_pt_init_destroy)).\n\t\t\t\tpt_init_destroy(ctx, NULL, pt, 1);\n#endif\n\tvpt \u003d (volatile struct lws_context_per_thread *)pt;\n\tftp \u003d vpt-\u003eforeign_pfd_list;\n\twhile (ftp) {\n\t\tnext \u003d ftp-\u003enext;\n\t\tlws_free((void *)ftp);\n\t\tftp \u003d next;\n\t}\n\tvpt-\u003eforeign_pfd_list \u003d NULL;\n\n\tlws_pt_lock(pt, __func__);\n\n\tif (pt-\u003epipe_wsi) {\n\t\tlws_destroy_event_pipe(pt-\u003epipe_wsi);\n\t\tpt-\u003epipe_wsi \u003d NULL;\n\t}\n\n\tif ((pt-\u003edummy_pipe_fds[0] || pt-\u003edummy_pipe_fds[1])\n#if !defined(WIN32)\n\t \u0026\u0026 ((int)pt-\u003edummy_pipe_fds[0] !\u003d -1 || (int)pt-\u003edummy_pipe_fds[1] !\u003d -1)\n#endif\n\t) {\n\t\tstruct lws wsi;\n\n\t\tmemset(\u0026wsi, 0, sizeof(wsi));\n\t\twsi.a.context \u003d pt-\u003econtext;\n\t\twsi.tsi \u003d (char)pt-\u003etid;\n\t\tlws_plat_pipe_close(\u0026wsi);\n\t}\n\n#if defined(LWS_WITH_SECURE_STREAMS)\n\twhile (pt-\u003ess_owner.head)\n\t\tlws_ss_destroy_dll(pt-\u003ess_owner.head, NULL);\n\n#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) \u0026\u0026 defined(LWS_WITH_CLIENT)\n\tlws_dll2_foreach_safe(\u0026pt-\u003ess_client_owner, NULL, lws_sspc_destroy_dll);\n#endif\n\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\t\twhile (pt-\u003ehttp.ah_list)\n\t\t\t_lws_destroy_ah(pt, pt-\u003ehttp.ah_list);\n#endif\n\n#endif\n\n\tlws_pt_unlock(pt);\n\tpt-\u003epipe_wsi \u003d NULL;\n\n}\n#endif\n\n/*\n * Context destruction is now a state machine that's aware of SMP pts and\n * various event lib approaches.\n *\n * lws_context_destroy() expects to be called at the end of the user code's\n * usage of it. But it can also be called non-finally, as a way to stop\n * service and exit the outer user service loop, and then complete in the\n * final call.\n *\n * For libuv, with async close, it must decide by refcounting the hamdles on\n * the loop if it has extricated itself from the loop and can be destroyed.\n *\n * The various entry states for the staged destroy\n *\n * LWSCD_NO_DESTROY: begin destroy process\n * \t- mark context as starting destroy process\n * \t- start vhost destroy\n * \t- stop any further user protocol service\n *\n * LWSCD_PT_WAS_DEFERRED: come back here if any pt inside service\n * \t- Check for pts that are inside service loop, mark deferral needed if so\n * \t- If not, close all wsi on the pt loop and start logical pt destroy\n * \t- If any deferred, set state to LWSCD_PT_WAS_DEFERRED and exit\n *\n * LWSCD_PT_WAIT_ALL_DESTROYED: come back here for async loop / pt closes\n * \t- exit if any pt not marked as unused, or destroyed\n * \t- if all pt down, call into evlib to advance context destroy\n * \t- finalize vhost destruction\n * \t- finalize pt destruction\n *\t- if foreign loops, set state to LWSCD_FINALIZATION and exit\n *\n * LWSCD_FINALIZATION: come back here at final lws_destroy_context() call\n *\t- destroy sundries\n *\t- destroy and free the actual context\n */\n\nvoid\nlws_context_destroy(struct lws_context *context)\n{\n\tstruct lws_context **pcontext_finalize;\n#if defined(LWS_WITH_NETWORK)\n\tstruct lws_context_per_thread *pt;\n\tstruct lws_vhost *vh \u003d NULL, *vh1;\n\tint alive \u003d 0, deferred_pt \u003d 0;\n#endif\n#if defined(LWS_WITH_PEER_LIMITS)\n\tuint32_t nu;\n#endif\n\tint n;\n\n\tif (!context || context-\u003einside_context_destroy)\n\t\treturn;\n\n\tpcontext_finalize \u003d context-\u003epcontext_finalize;\n\n\tlws_context_lock(context, __func__);\n\tcontext-\u003einside_context_destroy \u003d 1;\n\n\tlwsl_cx_info(context, \u0022destroy_state %d\u0022, context-\u003edestroy_state);\n\n\tswitch (context-\u003edestroy_state) {\n\tcase LWSCD_NO_DESTROY:\n\t\t/*\n\t\t * We're getting started\n\t\t */\n\n\t\tlwsl_cx_info(context, \u0022starting context destroy flow\u0022);\n\t\tcontext-\u003ebeing_destroyed \u003d 1;\n\n#if defined(LWS_WITH_NETWORK)\n\n\t\t/*\n\t\t * Close any vhost listen wsi\n\t\t *\n\t\t * inform all the protocols that they are done and will have no\n\t\t * more callbacks.\n\t\t *\n\t\t * We can't free things until after the event loop shuts down.\n\t\t */\n\n\t\tif (context-\u003eprotocol_init_done)\n\t\t\tvh \u003d context-\u003evhost_list;\n\n\t\twhile (vh) {\n\t\t\tlwsl_vhost_info(vh, \u0022start close\u0022);\n\t\t\tvh1 \u003d vh-\u003evhost_next;\n\t\t\tlws_vhost_destroy1(vh);\n\t\t\tvh \u003d vh1;\n\t\t}\n#endif\n\n\t\tlws_plat_context_early_destroy(context);\n\n\t\tcontext-\u003eservice_no_longer_possible \u003d 1;\n\t\tcontext-\u003erequested_stop_internal_loops \u003d 1;\n\n\t\t/* fallthru */\n\n\tcase LWSCD_PT_WAS_DEFERRED:\n\n#if defined(LWS_WITH_NETWORK)\n\n\t\t/*\n\t\t * We want to mark the pts as their destruction having been\n\t\t * initiated, so they will reject any new wsi, and iterate all\n\t\t * existing pt wsi starting to close them.\n\t\t *\n\t\t * If the event loop has async close, we have to return after\n\t\t * this and try again when all the loops stop after all the\n\t\t * refcounted wsi are gone.\n\t\t */\n\n\t\tpt \u003d context-\u003ept;\n\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\t\tlws_pt_lock(pt, __func__);\n\n\t\t\t/* evlib will realize it needs to destroy pt */\n\t\t\tpt-\u003edestroy_self \u003d 1;\n\n\t\t\tif (pt-\u003einside_lws_service) {\n\t\t\t\tpt-\u003eevent_loop_pt_unused \u003d 1;\n\t\t\t\tdeferred_pt \u003d 1;\n\t\t\t\tgoto next;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Close every handle in the fds\n\t\t\t */\n\n\t\t\twhile (pt-\u003efds_count) {\n\t\t\t\tstruct lws *wsi \u003d wsi_from_fd(context,\n\t\t\t\t\t\t\t pt-\u003efds[0].fd);\n\n\t\t\t\tif (wsi) {\n\n\t\t\t\t\tlwsl_cx_debug(context,\n\t\t\t\t\t\t\u0022pt %d: closing wsi %p: role %s\u0022,\n\t\t\t\t\t\tn, wsi, wsi-\u003erole_ops-\u003ename);\n\n\t\t\t\t\tlws_close_free_wsi(wsi,\n\t\t\t\t\t\tLWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY,\n\t\t\t\t\t\t\u0022ctx destroy\u0022\n\t\t\t\t\t\t/* no protocol close */);\n\n\t\t\t\t\tif (pt-\u003epipe_wsi \u003d\u003d wsi)\n\t\t\t\t\t\tpt-\u003epipe_wsi \u003d NULL;\n\t\t\t\t}\n\t\t\t}\n\n#if defined(LWS_WITH_CGI)\n\t\t\t(lws_rops_func_fidx(\u0026role_ops_cgi,\n\t\t\t\t\t LWS_ROPS_pt_init_destroy)).\n\t\t\t\t\t pt_init_destroy(context, NULL,\n\t\t\t\t\t\t\t pt, 1);\n#endif\n\n\t\t\t/*\n\t\t\t * This closes handles that belong to the evlib pt\n\t\t\t * footprint, eg, timers, idle\n\t\t\t */\n\n\t\t\tif (context-\u003eevent_loop_ops-\u003edestroy_pt) {\n\t\t\t\tlwsl_cx_info(context,\n\t\t\t\t\t \u0022calling evlib destroy_pt %d\u005cn\u0022, n);\n\t\t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_pt(context, n);\n\t\t\t}\n\nnext:\n\t\t\tlws_pt_unlock(pt);\n\n\t\t\tpt++;\n\t\t}\n\n\t\tif (deferred_pt) {\n\t\t\tcontext-\u003edestroy_state \u003d LWSCD_PT_WAS_DEFERRED;\n\t\t\tlwsl_cx_notice(context, \u0022destroy from inside service\u0022);\n\t\t\tlws_cancel_service(context);\n\t\t\tgoto bail;\n\t\t}\n#endif\n\t\tcontext-\u003edestroy_state \u003d LWSCD_PT_WAIT_ALL_DESTROYED;\n\n\t\t/*\n\t\t * We have different needs depending if foreign loop or not.\n\t\t *\n\t\t * 1) If foreign loop, we really want to advance the\n\t\t * destroy_context() past here, and block only for libuv-\n\t\t * style async close completion.\n\t\t *\n\t\t * 2a) If poll, and we exited by ourselves and are calling a\n\t\t * final destroy_context() outside of any service already,\n\t\t * we want to advance all the way in one step.\n\t\t *\n\t\t * 2b) If poll, and we are reacting to a SIGINT, service\n\t\t * thread(s) may be in poll wait or servicing. We can't\n\t\t * advance the destroy_context() to the point it's freeing\n\t\t * things; we have to leave that for the final\n\t\t * destroy_context() after the service thread(s) are\n\t\t * finished calling for service.\n\t\t */\n\n#if defined(LWS_WITH_NETWORK)\n\n#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API)\n\t\tlws_ss_proxy_destroy(context);\n#endif\n\n\t\tif (context-\u003eevent_loop_ops-\u003edestroy_context1) {\n\t\t\tlwsl_cx_info(context, \u0022do evlib destroy_context1 and wait\u0022);\n\t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_context1(context);\n\n\t\t\tgoto bail;\n\t\t}\n\n\t\t/*\n\t\t * ...if the more typical sync close, we can clean up the pts\n\t\t * now ourselves...\n\t\t */\n\n\t\tlwsl_cx_info(context, \u0022manually destroying pts\u0022);\n\n\t\tpt \u003d context-\u003ept;\n\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++, pt++) {\n\t\t\tpt-\u003eevent_loop_pt_unused \u003d 1;\n\t\t\tlws_pt_destroy(pt);\n\t\t}\n#endif\n\t\t/* fallthru */\n\n\tcase LWSCD_PT_WAIT_ALL_DESTROYED:\n\n#if defined(LWS_WITH_NETWORK)\n\n\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++)\n\t\t\tif (!context-\u003ept[n].is_destroyed \u0026\u0026\n\t\t\t !context-\u003ept[n].event_loop_pt_unused)\n\t\t\t\talive++;\n\n\t\tlwsl_cx_info(context, \u0022PT_WAIT_ALL_DESTROYED: %d alive\u0022, alive);\n\n\t\tif (alive)\n\t\t\tbreak;\n\n\t\t/*\n\t\t * With foreign loops, removing all our fds from the loop\n\t\t * means there are no more ways for the foreign loop to give\n\t\t * us any further CPU once we leave here... so we must make\n\t\t * sure related service threads are exiting so we can pick up\n\t\t * again at the original app thread and do the context\n\t\t * destroy completion\n\t\t */\n\n\t\t/*\n\t\t * evlib specific loop destroy?\n\t\t */\n\t\tif (context-\u003eevent_loop_ops-\u003edestroy_context2)\n\t\t\t/*\n\t\t\t * He returns nonzero to indicate the evlib must\n\t\t\t * continue around the loop before destroy of it is\n\t\t\t * completed so it can be freed\n\t\t\t */\n\t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_context2(context);\n\t\tcontext-\u003erequested_stop_internal_loops \u003d 1;\n#endif\n\n\t\t/*\n\t\t * Every pt and wsi that may depend on the logical vhosts\n\t\t * is destroyed. We can remove the logical vhosts.\n\t\t */\n\n#if defined(LWS_WITH_SYS_STATE) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\tlws_state_transition(\u0026context-\u003emgr_system, LWS_SYSTATE_POLICY_INVALID);\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\t\t/*\n\t\t * free all the per-vhost allocations\n\t\t */\n\n\t\tvh \u003d context-\u003evhost_list;\n\t\twhile (vh) {\n\t\t\tvh1 \u003d vh-\u003evhost_next;\n\t\t//\tlwsl_vhost_debug(vh, \u0022vh %s destroy2\u0022, vh-\u003ename);\n\t\t\t__lws_vhost_destroy2(vh);\n\t\t\tvh \u003d vh1;\n\t\t}\n\n\t\t/* remove ourselves from the pending destruction list */\n\n\t\twhile (context-\u003evhost_pending_destruction_list)\n\t\t\t/* removes itself from list */\n\t\t\t__lws_vhost_destroy2(context-\u003evhost_pending_destruction_list);\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\t\tlws_ssl_context_destroy(context);\n#endif\n\t\tlws_plat_context_late_destroy(context);\n\n#if defined(LWS_WITH_PEER_LIMITS)\n\t\tif (context-\u003epl_hash_table)\n\t\t\tfor (nu \u003d 0; nu \u003c context-\u003epl_hash_elements; nu++)\t{\n\t\t\t\tif (!context-\u003epl_hash_table[nu])\n\t\t\t\t\tcontinue;\n\t\t\t\tlws_start_foreach_llp(struct lws_peer **, peer,\n\t\t\t\t\t\t context-\u003epl_hash_table[nu]) {\n\t\t\t\t\tstruct lws_peer *df \u003d *peer;\n\t\t\t\t\t*peer \u003d df-\u003enext;\n\t\t\t\t\tlws_free(df);\n\t\t\t\t\tcontinue;\n\t\t\t\t} lws_end_foreach_llp(peer, next);\n\t\t\t}\n\t\tlws_free(context-\u003epl_hash_table);\n#endif\n\n#if defined(LWS_WITH_NETWORK)\n\n\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\t\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[n];\n\n\t\t\t(void)pt;\n\n\t\t\tLWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {\n\t\t\t\tif (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy))\n\t\t\t\t\t(lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)).\n\t\t\t\t\t\tpt_init_destroy(context, NULL, pt, 1);\n\t\t\t} LWS_FOR_EVERY_AVAILABLE_ROLE_END;\n\n#if defined(LWS_WITH_CGI)\n\t\t\tlws_rops_func_fidx(\u0026role_ops_cgi,\n\t\t\t\t\t LWS_ROPS_pt_init_destroy).\n\t\t\t\t\t pt_init_destroy(context, NULL,\n\t\t\t\t\t \t\tpt, 1);\n#endif\n\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\t\t\twhile (pt-\u003ehttp.ah_list)\n\t\t\t\t_lws_destroy_ah(pt, pt-\u003ehttp.ah_list);\n#endif\n\t\t\tlwsl_cx_info(context, \u0022pt destroy %d\u0022, n);\n\t\t\tlws_pt_destroy(pt);\n\t\t}\n#endif /* NETWORK */\n\n\t\tcontext-\u003edestroy_state \u003d LWSCD_FINALIZATION;\n\n#if defined(LWS_WITH_NETWORK)\n\n\t\tif (context-\u003ept[0].event_loop_foreign \u0026\u0026\n\t\t context-\u003eevent_loop_ops-\u003edestroy_context1) {\n\n\t\t\tlwsl_cx_info(context,\n\t\t\t\t \u0022leaving final context destruction\u0022\n\t\t\t\t\t\u0022 for final call\u0022);\n\t\t\tgoto bail;\n\t\t}\n\n\t\tif (context-\u003eevent_loop_ops-\u003edestroy_context1 \u0026\u0026\n\t\t !context-\u003ept[0].event_loop_foreign) {\n\t\t\tlwsl_cx_notice(context, \u0022waiting for internal loop exit\u0022);\n\n\t\t\tgoto bail;\n\t\t}\n#endif\n\t\t/* fallthru */\n\n\tcase LWSCD_FINALIZATION:\n\n#if defined(LWS_WITH_SYS_METRICS)\n\t\tlws_metrics_dump(context);\n#endif\n\n\t\tcontext-\u003eevlib_finalize_destroy_after_int_loops_stop \u003d 1;\n\n#if defined(LWS_WITH_NETWORK)\n\t\tif (context-\u003eevent_loop_ops-\u003edestroy_context2)\n\t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_context2(context);\n#if defined(LWS_WITH_SYS_STATE)\n\t\tlws_state_transition_steps(\u0026context-\u003emgr_system,\n\t\t\t\t\t LWS_SYSTATE_CONTEXT_DESTROYING);\n#endif\n\t\t/*\n\t\t * finalize destroy of pt and things hanging off it\n\t\t */\n\n\t\tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n\t\t\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[n];\n\n\t\t\t/*\n\t\t\t * Destroy the pt-roles\n\t\t\t */\n\n\t\t\tLWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {\n\t\t\t\tif (lws_rops_fidx(ar, LWS_ROPS_pt_init_destroy))\n\t\t\t\t\t(lws_rops_func_fidx(ar, LWS_ROPS_pt_init_destroy)).\n\t\t\t\t\t\t\tpt_init_destroy(context, NULL, pt, 1);\n\t\t\t} LWS_FOR_EVERY_AVAILABLE_ROLE_END;\n\n\t\t#if defined(LWS_WITH_CGI)\n\t\t\tlws_rops_func_fidx(\u0026role_ops_cgi, LWS_ROPS_pt_init_destroy).\n\t\t\t\t\t\tpt_init_destroy(context, NULL, pt, 1);\n\t\t#endif\n\n\t\t\tlws_pt_mutex_destroy(pt);\n\t\t\tassert(!pt-\u003eis_destroyed);\n\t\t\tpt-\u003edestroy_self \u003d 0;\n\t\t\tpt-\u003eis_destroyed \u003d 1;\n\n\t\t\tlwsl_cx_info(context, \u0022pt %d fully destroyed\u0022,\n\t\t\t\t\t(int)(pt - pt-\u003econtext-\u003ept));\n\t\t}\n\n\t\t/*\n\t\t * wsis are gone, pts are gone, vhosts are gone.\n\t\t *\n\t\t * clean up the context and things hanging off it\n\t\t */\n\n#if defined(LWS_WITH_TLS_JIT_TRUST)\n\t\tlws_cache_destroy(\u0026context-\u003etrust_cache);\n\t\tlws_tls_jit_trust_inflight_destroy_all(context);\n#endif\n\n#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) \u0026\u0026 defined(LWS_WITH_CLIENT)\n\t\tlws_cache_destroy(\u0026context-\u003ensc);\n\t\tlws_cache_destroy(\u0026context-\u003el1);\n#endif\n\n#if defined(LWS_WITH_SYS_SMD)\n\t\t_lws_smd_destroy(context);\n#endif\n\n#if defined(LWS_WITH_SYS_ASYNC_DNS)\n\t\tlws_async_dns_deinit(\u0026context-\u003easync_dns);\n#endif\n#if defined(LWS_WITH_SYS_DHCP_CLIENT)\n\t\tlws_dhcpc_remove(context, NULL);\n#endif\n\n#if defined(LWS_WITH_DLO)\n\t\tlws_fonts_destroy(context);\n\t\tlws_dlo_file_destroy(context);\n#endif\n\n\t\tif (context-\u003ept[0].fds)\n\t\t\tlws_free_set_NULL(context-\u003ept[0].fds);\n#endif\n\t\tlws_context_deinit_ssl_library(context);\n\n#if defined(LWS_WITH_DETAILED_LATENCIES)\n\t\tif (context-\u003elatencies_fd !\u003d -1)\n\t\t\tcompatible_close(context-\u003elatencies_fd);\n#endif\n\n\t\tfor (n \u003d 0; n \u003c LWS_SYSBLOB_TYPE_COUNT; n++)\n\t\t\tlws_system_blob_destroy(\n\t\t\t\t\tlws_system_get_blob(context, (lws_system_blob_item_t)n, 0));\n\n#if defined(LWS_WITH_NETWORK) \u0026\u0026 defined(LWS_WITH_SECURE_STREAMS) \u0026\u0026 \u005c\n\t!defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)\n\n\t\twhile (context-\u003eserver_der_list) {\n\t\t\tstruct lws_ss_x509 *x \u003d context-\u003eserver_der_list;\n\n\t\t\tcontext-\u003eserver_der_list \u003d x-\u003enext;\n\t\t\tlws_free((void *)x-\u003eca_der);\n\t\t}\n\n\t\tif (context-\u003eac_policy)\n\t\t\tlwsac_free(\u0026context-\u003eac_policy);\n\n#if defined(LWS_WITH_SERVER)\n\t\t/* ... for every sink... */\n\t\tlws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,\n\t\t\t\t lws_dll2_get_head(\u0026context-\u003esinks)) {\n\t\t\tlws_ss_sinks_t *sn \u003d lws_container_of(d, lws_ss_sinks_t,\n\t\t\t\t\t\t\t list);\n\n\t\t\tassert(!sn-\u003eaccepts.count);\n\n\t\t\tlws_dll2_remove(\u0026sn-\u003elist);\n\t\t\tlws_free(sn);\n\n\t\t} lws_end_foreach_dll_safe(d, d1);\n#endif\n#endif\n\n\t\t/*\n\t\t * Context lock is about to go away\n\t\t */\n\n\t\tlws_context_unlock(context);\n\n#if LWS_MAX_SMP \u003e 1\n\t\tlws_mutex_refcount_destroy(\u0026context-\u003emr);\n#endif\n\n#if defined(LWS_WITH_SYS_METRICS) \u0026\u0026 defined(LWS_WITH_NETWORK)\n\t\tlws_metrics_destroy(context);\n#endif\n\n\t\tif (context-\u003eexternal_baggage_free_on_destroy)\n\t\t\tfree(context-\u003eexternal_baggage_free_on_destroy);\n\n#if defined(LWS_PLAT_FREERTOS)\n#if defined(LWS_AMAZON_RTOS)\n\t\tcontext-\u003elast_free_heap \u003d xPortGetFreeHeapSize();\n#else\n\t\tcontext-\u003elast_free_heap \u003d esp_get_free_heap_size();\n#endif\n#endif\n\n#if defined(LWS_WITH_EVLIB_PLUGINS) \u0026\u0026 defined(LWS_WITH_EVENT_LIBS)\n\t\tif (context-\u003eevlib_plugin_list)\n\t\t\tlws_plugins_destroy(\u0026context-\u003eevlib_plugin_list,\n\t\t\t\t\t NULL, NULL);\n#endif\n\n#if defined(LWS_WITH_SYS_FAULT_INJECTION)\n\t\tlws_fi_destroy(\u0026context-\u003efic);\n#endif\n\n\t\tlwsl_refcount_cx(context-\u003elog_cx, -1);\n\n\t\tlws_free(context);\n\n\t\tif (pcontext_finalize)\n\t\t\t*pcontext_finalize \u003d NULL;\n\n\t\treturn;\n\t}\n\n#if defined(LWS_WITH_NETWORK)\nbail:\n#endif\n\tlwsl_cx_info(context, \u0022leaving\u0022);\n\tcontext-\u003einside_context_destroy \u003d 0;\n\tlws_context_unlock(context);\n}\n\nint\nlws_context_is_being_destroyed(struct lws_context *context)\n{\n\treturn !!context-\u003ebeing_destroyed;\n}\n\n#if defined(LWS_WITH_SYS_STATE)\nstruct lws_context *\nlws_system_context_from_system_mgr(lws_state_manager_t *mgr)\n{\n#if defined(LWS_WITH_NETWORK)\n\treturn mgr-\u003econtext;\n#else\n\treturn NULL;\n#endif\n}\n#endif\n\nvoid\nlws_log_prepend_context(struct lws_log_cx *cx, void *obj, char **p, char *e)\n{\n\tstruct lws_context *lcx \u003d (struct lws_context *)obj;\n\n\tif (lcx-\u003ename)\n\t\t*p +\u003d lws_snprintf(*p, lws_ptr_diff_size_t(e, (*p)), \u0022%s: \u0022,\n\t\t\t\t lcx-\u003ename);\n}\n\nstruct lws_log_cx *\nlwsl_context_get_cx(struct lws_context *cx)\n{\n\tif (!cx)\n\t\treturn NULL;\n\n\treturn cx-\u003elog_cx;\n}\n","s":{"c":1713527523,"u": 1259}} ],"g": 91265,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}