Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"en-US,en;q\u003d0.5", "gen_ut":1571480878, "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":"04d72aabf581eac178a67d74b59168b3", "oid":{ "oid": "b7a04a67d15efd0f17bf795b8d3648425b604581", "alias": [ "refs/heads/master"]},"blobname": "lib/core-net/wsi.c", "blob": "/*\n * libwebsockets - small server side websockets and web server implementation\n *\n * Copyright (C) 2010 - 2019 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#if defined (_DEBUG)\nvoid lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)\n{\n\twsi-\u003ewsistate \u003d (wsi-\u003ewsistate \u0026 (~LWSI_ROLE_MASK)) | role;\n\n\tlwsl_debug(\u0022lwsi_set_role(%p, 0x%lx)\u005cn\u0022, wsi,\n\t\t\t\t\t(unsigned long)wsi-\u003ewsistate);\n}\n\nvoid lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)\n{\n\twsi-\u003ewsistate \u003d (wsi-\u003ewsistate \u0026 (~LRS_MASK)) | lrs;\n\n\tlwsl_debug(\u0022lwsi_set_state(%p, 0x%lx)\u005cn\u0022, wsi,\n\t\t\t\t\t(unsigned long)wsi-\u003ewsistate);\n}\n#endif\n\n\nvoid\nlws_vhost_bind_wsi(struct lws_vhost *vh, struct lws *wsi)\n{\n\tif (wsi-\u003evhost \u003d\u003d vh)\n\t\treturn;\n\tlws_context_lock(vh-\u003econtext, __func__); /* ---------- context { */\n\twsi-\u003evhost \u003d vh;\n\tvh-\u003ecount_bound_wsi++;\n\tlws_context_unlock(vh-\u003econtext); /* } context ---------- */\n\tlwsl_info(\u0022%s: vh %s: count_bound_wsi %d\u005cn\u0022,\n\t\t __func__, vh-\u003ename, vh-\u003ecount_bound_wsi);\n\tassert(wsi-\u003evhost-\u003ecount_bound_wsi \u003e 0);\n}\n\nvoid\nlws_vhost_unbind_wsi(struct lws *wsi)\n{\n\tif (!wsi-\u003evhost)\n\t\treturn;\n\n\tlws_context_lock(wsi-\u003econtext, __func__); /* ---------- context { */\n\n\tassert(wsi-\u003evhost-\u003ecount_bound_wsi \u003e 0);\n\twsi-\u003evhost-\u003ecount_bound_wsi--;\n\tlwsl_info(\u0022%s: vh %s: count_bound_wsi %d\u005cn\u0022, __func__,\n\t\t wsi-\u003evhost-\u003ename, wsi-\u003evhost-\u003ecount_bound_wsi);\n\n\tif (!wsi-\u003evhost-\u003ecount_bound_wsi \u0026\u0026\n\t wsi-\u003evhost-\u003ebeing_destroyed) {\n\t\t/*\n\t\t * We have closed all wsi that were bound to this vhost\n\t\t * by any pt: nothing can be servicing any wsi belonging\n\t\t * to it any more.\n\t\t *\n\t\t * Finalize the vh destruction\n\t\t */\n\t\t__lws_vhost_destroy2(wsi-\u003evhost);\n\t}\n\twsi-\u003evhost \u003d NULL;\n\n\tlws_context_unlock(wsi-\u003econtext); /* } context ---------- */\n}\n\nLWS_VISIBLE struct lws *\nlws_get_network_wsi(struct lws *wsi)\n{\n\tif (!wsi)\n\t\treturn NULL;\n\n#if defined(LWS_WITH_HTTP2)\n\tif (!wsi-\u003ehttp2_substream\n#if defined(LWS_WITH_CLIENT)\n\t\t\t\u0026\u0026 !wsi-\u003eclient_h2_substream\n#endif\n\t)\n\t\treturn wsi;\n\n\twhile (wsi-\u003eh2.parent_wsi)\n\t\twsi \u003d wsi-\u003eh2.parent_wsi;\n#endif\n\n\treturn wsi;\n}\n\n\nLWS_VISIBLE LWS_EXTERN const struct lws_protocols *\nlws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)\n{\n\tint n;\n\n\tfor (n \u003d 0; n \u003c vh-\u003ecount_protocols; n++)\n\t\tif (vh-\u003eprotocols[n].name \u0026\u0026 !strcmp(name, vh-\u003eprotocols[n].name))\n\t\t\treturn \u0026vh-\u003eprotocols[n];\n\n\treturn NULL;\n}\n\nLWS_VISIBLE int\nlws_callback_all_protocol(struct lws_context *context,\n\t\t\t const struct lws_protocols *protocol, int reason)\n{\n\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[0];\n\tunsigned int n, m \u003d context-\u003ecount_threads;\n\tstruct lws *wsi;\n\n\twhile (m--) {\n\t\tfor (n \u003d 0; n \u003c pt-\u003efds_count; n++) {\n\t\t\twsi \u003d wsi_from_fd(context, pt-\u003efds[n].fd);\n\t\t\tif (!wsi)\n\t\t\t\tcontinue;\n\t\t\tif (wsi-\u003eprotocol \u003d\u003d protocol)\n\t\t\t\tprotocol-\u003ecallback(wsi, reason, wsi-\u003euser_space,\n\t\t\t\t\t\t NULL, 0);\n\t\t}\n\t\tpt++;\n\t}\n\n\treturn 0;\n}\n\nLWS_VISIBLE int\nlws_callback_all_protocol_vhost_args(struct lws_vhost *vh,\n\t\t\t const struct lws_protocols *protocol, int reason,\n\t\t\t void *argp, size_t len)\n{\n\tstruct lws_context *context \u003d vh-\u003econtext;\n\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[0];\n\tunsigned int n, m \u003d context-\u003ecount_threads;\n\tstruct lws *wsi;\n\n\twhile (m--) {\n\t\tfor (n \u003d 0; n \u003c pt-\u003efds_count; n++) {\n\t\t\twsi \u003d wsi_from_fd(context, pt-\u003efds[n].fd);\n\t\t\tif (!wsi)\n\t\t\t\tcontinue;\n\t\t\tif (wsi-\u003evhost \u003d\u003d vh \u0026\u0026 (wsi-\u003eprotocol \u003d\u003d protocol ||\n\t\t\t\t\t\t !protocol))\n\t\t\t\twsi-\u003eprotocol-\u003ecallback(wsi, reason,\n\t\t\t\t\t\twsi-\u003euser_space, argp, len);\n\t\t}\n\t\tpt++;\n\t}\n\n\treturn 0;\n}\n\nLWS_VISIBLE int\nlws_callback_all_protocol_vhost(struct lws_vhost *vh,\n\t\t\t const struct lws_protocols *protocol, int reason)\n{\n\treturn lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0);\n}\n\nLWS_VISIBLE LWS_EXTERN int\nlws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)\n{\n\tint n;\n\n\tfor (n \u003d 0; n \u003c wsi-\u003evhost-\u003ecount_protocols; n++)\n\t\tif (wsi-\u003evhost-\u003eprotocols[n].callback(wsi, reason, NULL, in, len))\n\t\t\treturn 1;\n\n\treturn 0;\n}\n\nLWS_VISIBLE LWS_EXTERN int\nlws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in,\n\t\t\t\t size_t len)\n{\n\tint n;\n\tstruct lws *wsi \u003d lws_zalloc(sizeof(*wsi), \u0022fake wsi\u0022);\n\n\tif (!wsi)\n\t\treturn 1;\n\n\twsi-\u003econtext \u003d vh-\u003econtext;\n\tlws_vhost_bind_wsi(vh, wsi);\n\n\tfor (n \u003d 0; n \u003c wsi-\u003evhost-\u003ecount_protocols; n++) {\n\t\twsi-\u003eprotocol \u003d \u0026vh-\u003eprotocols[n];\n\t\tif (wsi-\u003eprotocol-\u003ecallback(wsi, reason, NULL, in, len)) {\n\t\t\tlws_free(wsi);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\tlws_free(wsi);\n\n\treturn 0;\n}\n\n\nLWS_VISIBLE int\nlws_rx_flow_control(struct lws *wsi, int _enable)\n{\n\tstruct lws_context_per_thread *pt \u003d \u0026wsi-\u003econtext-\u003ept[(int)wsi-\u003etsi];\n\tint en \u003d _enable;\n\n\t// h2 ignores rx flow control atm\n\tif (lwsi_role_h2(wsi) || wsi-\u003ehttp2_substream ||\n\t lwsi_role_h2_ENCAPSULATION(wsi))\n\t\treturn 0; // !!!\n\n\tlwsl_info(\u0022%s: %p 0x%x\u005cn\u0022, __func__, wsi, _enable);\n\n\tif (!(_enable \u0026 LWS_RXFLOW_REASON_APPLIES)) {\n\t\t/*\n\t\t * convert user bool style to bitmap style... in user simple\n\t\t * bool style _enable \u003d 0 \u003d flow control it, \u003d 1 \u003d allow rx\n\t\t */\n\t\ten \u003d LWS_RXFLOW_REASON_APPLIES | LWS_RXFLOW_REASON_USER_BOOL;\n\t\tif (_enable \u0026 1)\n\t\t\ten |\u003d LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT;\n\t}\n\n\tlws_pt_lock(pt, __func__);\n\n\t/* any bit set in rxflow_bitmap DISABLEs rxflow control */\n\tif (en \u0026 LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT)\n\t\twsi-\u003erxflow_bitmap \u0026\u003d ~(en \u0026 0xff);\n\telse\n\t\twsi-\u003erxflow_bitmap |\u003d en \u0026 0xff;\n\n\tif ((LWS_RXFLOW_PENDING_CHANGE | (!wsi-\u003erxflow_bitmap)) \u003d\u003d\n\t wsi-\u003erxflow_change_to)\n\t\tgoto skip;\n\n\twsi-\u003erxflow_change_to \u003d LWS_RXFLOW_PENDING_CHANGE |\n\t\t\t\t(!wsi-\u003erxflow_bitmap);\n\n\tlwsl_info(\u0022%s: %p: bitmap 0x%x: en 0x%x, ch 0x%x\u005cn\u0022, __func__, wsi,\n\t\t wsi-\u003erxflow_bitmap, en, wsi-\u003erxflow_change_to);\n\n\tif (_enable \u0026 LWS_RXFLOW_REASON_FLAG_PROCESS_NOW ||\n\t !wsi-\u003erxflow_will_be_applied) {\n\t\ten \u003d __lws_rx_flow_control(wsi);\n\t\tlws_pt_unlock(pt);\n\n\t\treturn en;\n\t}\n\nskip:\n\tlws_pt_unlock(pt);\n\n\treturn 0;\n}\n\nLWS_VISIBLE void\nlws_rx_flow_allow_all_protocol(const struct lws_context *context,\n\t\t\t const struct lws_protocols *protocol)\n{\n\tconst struct lws_context_per_thread *pt \u003d \u0026context-\u003ept[0];\n\tstruct lws *wsi;\n\tunsigned int n, m \u003d context-\u003ecount_threads;\n\n\twhile (m--) {\n\t\tfor (n \u003d 0; n \u003c pt-\u003efds_count; n++) {\n\t\t\twsi \u003d wsi_from_fd(context, pt-\u003efds[n].fd);\n\t\t\tif (!wsi)\n\t\t\t\tcontinue;\n\t\t\tif (wsi-\u003eprotocol \u003d\u003d protocol)\n\t\t\t\tlws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);\n\t\t}\n\t\tpt++;\n\t}\n}\n\nint user_callback_handle_rxflow(lws_callback_function callback_function,\n\t\t\t\tstruct lws *wsi,\n\t\t\t\tenum lws_callback_reasons reason, void *user,\n\t\t\t\tvoid *in, size_t len)\n{\n\tint n;\n\n\twsi-\u003erxflow_will_be_applied \u003d 1;\n\tn \u003d callback_function(wsi, reason, user, in, len);\n\twsi-\u003erxflow_will_be_applied \u003d 0;\n\tif (!n)\n\t\tn \u003d __lws_rx_flow_control(wsi);\n\n\treturn n;\n}\n\nLWS_EXTERN int\n__lws_rx_flow_control(struct lws *wsi)\n{\n\tstruct lws *wsic \u003d wsi-\u003echild_list;\n\n\t// h2 ignores rx flow control atm\n\tif (lwsi_role_h2(wsi) || wsi-\u003ehttp2_substream ||\n\t lwsi_role_h2_ENCAPSULATION(wsi))\n\t\treturn 0; // !!!\n\n\t/* if he has children, do those if they were changed */\n\twhile (wsic) {\n\t\tif (wsic-\u003erxflow_change_to \u0026 LWS_RXFLOW_PENDING_CHANGE)\n\t\t\t__lws_rx_flow_control(wsic);\n\n\t\twsic \u003d wsic-\u003esibling_list;\n\t}\n\n\t/* there is no pending change */\n\tif (!(wsi-\u003erxflow_change_to \u0026 LWS_RXFLOW_PENDING_CHANGE))\n\t\treturn 0;\n\n\t/* stuff is still buffered, not ready to really accept new input */\n\tif (lws_buflist_next_segment_len(\u0026wsi-\u003ebuflist, NULL)) {\n\t\t/* get ourselves called back to deal with stashed buffer */\n\t\tlws_callback_on_writable(wsi);\n\t\t// return 0;\n\t}\n\n\t/* now the pending is cleared, we can change rxflow state */\n\n\twsi-\u003erxflow_change_to \u0026\u003d ~LWS_RXFLOW_PENDING_CHANGE;\n\n\tlwsl_info(\u0022rxflow: wsi %p change_to %d\u005cn\u0022, wsi,\n\t\t wsi-\u003erxflow_change_to \u0026 LWS_RXFLOW_ALLOW);\n\n\t/* adjust the pollfd for this wsi */\n\n\tif (wsi-\u003erxflow_change_to \u0026 LWS_RXFLOW_ALLOW) {\n\t\tlwsl_info(\u0022%s: reenable POLLIN\u005cn\u0022, __func__);\n\t\t// lws_buflist_describe(\u0026wsi-\u003ebuflist, NULL, __func__);\n\t\tif (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) {\n\t\t\tlwsl_info(\u0022%s: fail\u005cn\u0022, __func__);\n\t\t\treturn -1;\n\t\t}\n\t} else\n\t\tif (__lws_change_pollfd(wsi, LWS_POLLIN, 0))\n\t\t\treturn -1;\n\n\treturn 0;\n}\n\n\nLWS_VISIBLE const struct lws_protocols *\nlws_get_protocol(struct lws *wsi)\n{\n\treturn wsi-\u003eprotocol;\n}\n\n\nint\nlws_ensure_user_space(struct lws *wsi)\n{\n\tif (!wsi-\u003eprotocol)\n\t\treturn 0;\n\n\t/* allocate the per-connection user memory (if any) */\n\n\tif (wsi-\u003eprotocol-\u003eper_session_data_size \u0026\u0026 !wsi-\u003euser_space) {\n\t\twsi-\u003euser_space \u003d lws_zalloc(\n\t\t\t wsi-\u003eprotocol-\u003eper_session_data_size, \u0022user space\u0022);\n\t\tif (wsi-\u003euser_space \u003d\u003d NULL) {\n\t\t\tlwsl_err(\u0022%s: OOM\u005cn\u0022, __func__);\n\t\t\treturn 1;\n\t\t}\n\t} else\n\t\tlwsl_debug(\u0022%s: %p protocol pss %lu, user_space\u003d%p\u005cn\u0022, __func__,\n\t\t\t wsi, (long)wsi-\u003eprotocol-\u003eper_session_data_size,\n\t\t\t wsi-\u003euser_space);\n\treturn 0;\n}\n\nLWS_VISIBLE void *\nlws_adjust_protocol_psds(struct lws *wsi, size_t new_size)\n{\n\t((struct lws_protocols *)lws_get_protocol(wsi))-\u003eper_session_data_size \u003d\n\t\tnew_size;\n\n\tif (lws_ensure_user_space(wsi))\n\t\t\treturn NULL;\n\n\treturn wsi-\u003euser_space;\n}\n\n\n\nLWS_VISIBLE int\nlws_is_ssl(struct lws *wsi)\n{\n#if defined(LWS_WITH_TLS)\n\treturn wsi-\u003etls.use_ssl \u0026 LCCSCF_USE_SSL;\n#else\n\t(void)wsi;\n\treturn 0;\n#endif\n}\n\n#if defined(LWS_WITH_TLS) \u0026\u0026 !defined(LWS_WITH_MBEDTLS)\nLWS_VISIBLE lws_tls_conn*\nlws_get_ssl(struct lws *wsi)\n{\n\treturn wsi-\u003etls.ssl;\n}\n#endif\n\nLWS_VISIBLE int\nlws_partial_buffered(struct lws *wsi)\n{\n\treturn lws_has_buffered_out(wsi);\n}\n\nLWS_VISIBLE lws_fileofs_t\nlws_get_peer_write_allowance(struct lws *wsi)\n{\n\tif (!wsi-\u003erole_ops-\u003etx_credit)\n\t\treturn -1;\n\treturn wsi-\u003erole_ops-\u003etx_credit(wsi);\n}\n\nLWS_VISIBLE void\nlws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,\n\t\t const struct lws_role_ops *ops)\n{\n#if defined(_DEBUG)\n\tconst char *name \u003d \u0022(unset)\u0022;\n#endif\n\twsi-\u003ewsistate \u003d role | state;\n\tif (ops)\n\t\twsi-\u003erole_ops \u003d ops;\n#if defined(_DEBUG)\n\tif (wsi-\u003erole_ops)\n\t\tname \u003d wsi-\u003erole_ops-\u003ename;\n\tlwsl_debug(\u0022%s: %p: wsistate 0x%lx, ops %s\u005cn\u0022, __func__, wsi,\n\t\t (unsigned long)wsi-\u003ewsistate, name);\n#endif\n}\n\nLWS_VISIBLE LWS_EXTERN int\nlws_parse_uri(char *p, const char **prot, const char **ads, int *port,\n\t const char **path)\n{\n\tconst char *end;\n\tchar unix_skt \u003d 0;\n\n\t/* cut up the location into address, port and path */\n\t*prot \u003d p;\n\twhile (*p \u0026\u0026 (*p !\u003d ':' || p[1] !\u003d '/' || p[2] !\u003d '/'))\n\t\tp++;\n\tif (!*p) {\n\t\tend \u003d p;\n\t\tp \u003d (char *)*prot;\n\t\t*prot \u003d end;\n\t} else {\n\t\t*p \u003d '\u005c0';\n\t\tp +\u003d 3;\n\t}\n\tif (*p \u003d\u003d '+') /* unix skt */\n\t\tunix_skt \u003d 1;\n\n\t*ads \u003d p;\n\tif (!strcmp(*prot, \u0022http\u0022) || !strcmp(*prot, \u0022ws\u0022))\n\t\t*port \u003d 80;\n\telse if (!strcmp(*prot, \u0022https\u0022) || !strcmp(*prot, \u0022wss\u0022))\n\t\t*port \u003d 443;\n\n\tif (*p \u003d\u003d '[') {\n\t\t++(*ads);\n\t\twhile (*p \u0026\u0026 *p !\u003d ']')\n\t\t\tp++;\n\t\tif (*p)\n\t\t\t*p++ \u003d '\u005c0';\n\t} else\n\t\twhile (*p \u0026\u0026 *p !\u003d ':' \u0026\u0026 (unix_skt || *p !\u003d '/'))\n\t\t\tp++;\n\n\tif (*p \u003d\u003d ':') {\n\t\t*p++ \u003d '\u005c0';\n\t\t*port \u003d atoi(p);\n\t\twhile (*p \u0026\u0026 *p !\u003d '/')\n\t\t\tp++;\n\t}\n\t*path \u003d \u0022/\u0022;\n\tif (*p) {\n\t\t*p++ \u003d '\u005c0';\n\t\tif (*p)\n\t\t\t*path \u003d p;\n\t}\n\n\treturn 0;\n}\n\n/* ... */\n\nLWS_VISIBLE LWS_EXTERN const char *\nlws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len)\n{\n\tint n \u003d 0, sl \u003d (int)strlen(name);\n\n\twhile (lws_hdr_copy_fragment(wsi, buf, len,\n\t\t\t WSI_TOKEN_HTTP_URI_ARGS, n) \u003e\u003d 0) {\n\n\t\tif (!strncmp(buf, name, sl))\n\t\t\treturn buf + sl;\n\n\t\tn++;\n\t}\n\n\treturn NULL;\n}\n\n\n#if defined(LWS_WITHOUT_EXTENSIONS)\n\n/* we need to provide dummy callbacks for internal exts\n * so user code runs when faced with a lib compiled with\n * extensions disabled.\n */\n\nLWS_VISIBLE int\nlws_extension_callback_pm_deflate(struct lws_context *context,\n const struct lws_extension *ext,\n struct lws *wsi,\n enum lws_extension_callback_reasons reason,\n void *user, void *in, size_t len)\n{\n\t(void)context;\n\t(void)ext;\n\t(void)wsi;\n\t(void)reason;\n\t(void)user;\n\t(void)in;\n\t(void)len;\n\n\treturn 0;\n}\n\nLWS_EXTERN int\nlws_set_extension_option(struct lws *wsi, const char *ext_name,\n\t\t\t const char *opt_name, const char *opt_val)\n{\n\treturn -1;\n}\n#endif\n\nLWS_VISIBLE LWS_EXTERN int\nlws_is_cgi(struct lws *wsi) {\n#ifdef LWS_WITH_CGI\n\treturn !!wsi-\u003ehttp.cgi;\n#else\n\treturn 0;\n#endif\n}\n\nconst struct lws_protocol_vhost_options *\nlws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name)\n{\n\twhile (pvo) {\n\t\tif (!strcmp(pvo-\u003ename, name))\n\t\t\tbreak;\n\n\t\tpvo \u003d pvo-\u003enext;\n\t}\n\n\treturn pvo;\n}\n\nint\nlws_pvo_get_str(void *in, const char *name, const char **result)\n{\n\tconst struct lws_protocol_vhost_options *pv \u003d\n\t\tlws_pvo_search((const struct lws_protocol_vhost_options *)in,\n\t\t\t\tname);\n\n\tif (!pv)\n\t\treturn 1;\n\n\t*result \u003d (const char *)pv-\u003evalue;\n\n\treturn 0;\n}\n\nint\nlws_broadcast(struct lws_context_per_thread *pt, int reason, void *in, size_t len)\n{\n\tstruct lws_vhost *v \u003d pt-\u003econtext-\u003evhost_list;\n\tint n, ret \u003d 0;\n\n\tpt-\u003efake_wsi-\u003econtext \u003d pt-\u003econtext;\n\n\twhile (v) {\n\t\tconst struct lws_protocols *p \u003d v-\u003eprotocols;\n\t\tpt-\u003efake_wsi-\u003evhost \u003d v; /* not a real bound wsi */\n\n\t\tfor (n \u003d 0; n \u003c v-\u003ecount_protocols; n++) {\n\t\t\tpt-\u003efake_wsi-\u003eprotocol \u003d p;\n\t\t\tif (p-\u003ecallback \u0026\u0026\n\t\t\t p-\u003ecallback(pt-\u003efake_wsi, reason, NULL, in, len))\n\t\t\t\tret |\u003d 1;\n\t\t\tp++;\n\t\t}\n\t\tv \u003d v-\u003evhost_next;\n\t}\n\n\treturn ret;\n}\n\nLWS_VISIBLE LWS_EXTERN void *\nlws_wsi_user(struct lws *wsi)\n{\n\treturn wsi-\u003euser_space;\n}\n\nLWS_VISIBLE LWS_EXTERN void\nlws_set_wsi_user(struct lws *wsi, void *data)\n{\n\tif (wsi-\u003euser_space_externally_allocated)\n\t\twsi-\u003euser_space \u003d data;\n\telse\n\t\tlwsl_err(\u0022%s: Cannot set internally-allocated user_space\u005cn\u0022,\n\t\t\t __func__);\n}\n\nLWS_VISIBLE LWS_EXTERN struct lws *\nlws_get_parent(const struct lws *wsi)\n{\n\treturn wsi-\u003eparent;\n}\n\nLWS_VISIBLE LWS_EXTERN struct lws *\nlws_get_child(const struct lws *wsi)\n{\n\treturn wsi-\u003echild_list;\n}\n\nLWS_VISIBLE LWS_EXTERN void *\nlws_get_opaque_parent_data(const struct lws *wsi)\n{\n\treturn wsi-\u003eopaque_parent_data;\n}\n\nLWS_VISIBLE LWS_EXTERN void\nlws_set_opaque_parent_data(struct lws *wsi, void *data)\n{\n\twsi-\u003eopaque_parent_data \u003d data;\n}\n\nLWS_VISIBLE LWS_EXTERN void *\nlws_get_opaque_user_data(const struct lws *wsi)\n{\n\treturn wsi-\u003eopaque_user_data;\n}\n\nLWS_VISIBLE LWS_EXTERN void\nlws_set_opaque_user_data(struct lws *wsi, void *data)\n{\n\twsi-\u003eopaque_user_data \u003d data;\n}\n\nLWS_VISIBLE LWS_EXTERN int\nlws_get_child_pending_on_writable(const struct lws *wsi)\n{\n\treturn wsi-\u003eparent_pending_cb_on_writable;\n}\n\nLWS_VISIBLE LWS_EXTERN void\nlws_clear_child_pending_on_writable(struct lws *wsi)\n{\n\twsi-\u003eparent_pending_cb_on_writable \u003d 0;\n}\n\n\n\nLWS_VISIBLE LWS_EXTERN const char *\nlws_get_vhost_name(struct lws_vhost *vhost)\n{\n\treturn vhost-\u003ename;\n}\n\nLWS_VISIBLE LWS_EXTERN int\nlws_get_vhost_port(struct lws_vhost *vhost)\n{\n\treturn vhost-\u003elisten_port;\n}\n\nLWS_VISIBLE LWS_EXTERN void *\nlws_get_vhost_user(struct lws_vhost *vhost)\n{\n\treturn vhost-\u003euser;\n}\n\nLWS_VISIBLE LWS_EXTERN const char *\nlws_get_vhost_iface(struct lws_vhost *vhost)\n{\n\treturn vhost-\u003eiface;\n}\n\nLWS_VISIBLE lws_sockfd_type\nlws_get_socket_fd(struct lws *wsi)\n{\n\tif (!wsi)\n\t\treturn -1;\n\treturn wsi-\u003edesc.sockfd;\n}\n\n\nLWS_VISIBLE struct lws_vhost *\nlws_vhost_get(struct lws *wsi)\n{\n\treturn wsi-\u003evhost;\n}\n\nLWS_VISIBLE struct lws_vhost *\nlws_get_vhost(struct lws *wsi)\n{\n\treturn wsi-\u003evhost;\n}\n\nLWS_VISIBLE const struct lws_protocols *\nlws_protocol_get(struct lws *wsi)\n{\n\treturn wsi-\u003eprotocol;\n}\n\n#if defined(LWS_WITH_UDP)\nLWS_VISIBLE const struct lws_udp *\nlws_get_udp(const struct lws *wsi)\n{\n\treturn wsi-\u003eudp;\n}\n#endif\n\nLWS_VISIBLE LWS_EXTERN struct lws_context *\nlws_get_context(const struct lws *wsi)\n{\n\treturn wsi-\u003econtext;\n}\n\n#if defined(LWS_WITH_CLIENT)\nint\n_lws_generic_transaction_completed_active_conn(struct lws *wsi)\n{\n\tstruct lws *wsi_eff \u003d lws_client_wsi_effective(wsi);\n\n\t/*\n\t * Are we constitutionally capable of having a queue, ie, we are on\n\t * the \u0022active client connections\u0022 list?\n\t *\n\t * If not, that's it for us.\n\t */\n\n\tif (lws_dll2_is_detached(\u0026wsi-\u003edll_cli_active_conns))\n\t\treturn 0; /* no new transaction */\n\n\t/* if this was a queued guy, close him and remove from queue */\n\n\tif (wsi-\u003etransaction_from_pipeline_queue) {\n\t\tlwsl_debug(\u0022closing queued wsi %p\u005cn\u0022, wsi_eff);\n\t\t/* so the close doesn't trigger a CCE */\n\t\twsi_eff-\u003ealready_did_cce \u003d 1;\n\t\t__lws_close_free_wsi(wsi_eff,\n\t\t\tLWS_CLOSE_STATUS_CLIENT_TRANSACTION_DONE,\n\t\t\t\u0022queued client done\u0022);\n\t}\n\n\t/* after the first one, they can only be coming from the queue */\n\twsi-\u003etransaction_from_pipeline_queue \u003d 1;\n\n\twsi-\u003ehdr_parsing_completed \u003d 0;\n\n\t/* is there a new tail after removing that one? */\n\twsi_eff \u003d lws_client_wsi_effective(wsi);\n\n\t/*\n\t * Do we have something pipelined waiting?\n\t * it's OK if he hasn't managed to send his headers yet... he's next\n\t * in line to do that...\n\t */\n\tif (wsi_eff \u003d\u003d wsi) {\n\t\t/*\n\t\t * Nothing pipelined... we should hang around a bit\n\t\t * in case something turns up...\n\t\t */\n\t\tlwsl_info(\u0022%s: nothing pipelined waiting\u005cn\u0022, __func__);\n\t\tlwsi_set_state(wsi, LRS_IDLING);\n\n\t\tlws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);\n\n\t\treturn 0; /* no new transaction right now */\n\t}\n\n\treturn 1; /* new transaction */\n}\n#endif\n\nLWS_VISIBLE int LWS_WARN_UNUSED_RESULT\nlws_raw_transaction_completed(struct lws *wsi)\n{\n\tif (lws_has_buffered_out(wsi)) {\n\t\t/*\n\t\t * ...so he tried to send something large, but it went out\n\t\t * as a partial, but he immediately called us to say he wants\n\t\t * to close the connection.\n\t\t *\n\t\t * Defer the close until the last part of the partial is sent.\n\t\t *\n\t\t */\n\t\tlwsl_debug(\u0022%s: %p: deferring due to partial\u005cn\u0022, __func__, wsi);\n\t\twsi-\u003eclose_when_buffered_out_drained \u003d 1;\n\t\tlws_callback_on_writable(wsi);\n\n\t\treturn 0;\n\t}\n\n\treturn -1;\n}\n\nint\nlws_bind_protocol(struct lws *wsi, const struct lws_protocols *p,\n\t\t const char *reason)\n{\n//\tif (wsi-\u003eprotocol \u003d\u003d p)\n//\t\treturn 0;\n\tconst struct lws_protocols *vp \u003d wsi-\u003evhost-\u003eprotocols, *vpo;\n\n\tif (wsi-\u003eprotocol \u0026\u0026 wsi-\u003eprotocol_bind_balance) {\n\t\twsi-\u003eprotocol-\u003ecallback(wsi,\n\t\t wsi-\u003erole_ops-\u003eprotocol_unbind_cb[!!lwsi_role_server(wsi)],\n\t\t\t\t\twsi-\u003euser_space, (void *)reason, 0);\n\t\twsi-\u003eprotocol_bind_balance \u003d 0;\n\t}\n\tif (!wsi-\u003euser_space_externally_allocated)\n\t\tlws_free_set_NULL(wsi-\u003euser_space);\n\n\tlws_same_vh_protocol_remove(wsi);\n\n\twsi-\u003eprotocol \u003d p;\n\tif (!p)\n\t\treturn 0;\n\n\tif (lws_ensure_user_space(wsi))\n\t\treturn 1;\n\n\tif (p \u003e vp \u0026\u0026 p \u003c \u0026vp[wsi-\u003evhost-\u003ecount_protocols])\n\t\tlws_same_vh_protocol_insert(wsi, (int)(p - vp));\n\telse {\n\t\tint n \u003d wsi-\u003evhost-\u003ecount_protocols;\n\t\tint hit \u003d 0;\n\n\t\tvpo \u003d vp;\n\n\t\twhile (n--) {\n\t\t\tif (p-\u003ename \u0026\u0026 vp-\u003ename \u0026\u0026 !strcmp(p-\u003ename, vp-\u003ename)) {\n\t\t\t\thit \u003d 1;\n\t\t\t\tlws_same_vh_protocol_insert(wsi, (int)(vp - vpo));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvp++;\n\t\t}\n\t\tif (!hit)\n\t\t\tlwsl_err(\u0022%s: %p is not in vhost '%s' protocols list\u005cn\u0022,\n\t\t\t\t __func__, p, wsi-\u003evhost-\u003ename);\n\t}\n\n\tif (wsi-\u003eprotocol-\u003ecallback(wsi, wsi-\u003erole_ops-\u003eprotocol_bind_cb[\n\t\t\t\t !!lwsi_role_server(wsi)],\n\t\t\t\t wsi-\u003euser_space, NULL, 0))\n\t\treturn 1;\n\n\twsi-\u003eprotocol_bind_balance \u003d 1;\n\n\treturn 0;\n}\n\nvoid\nlws_http_close_immortal(struct lws *wsi)\n{\n\tstruct lws *nwsi;\n\n\tif (!wsi-\u003ehttp2_substream)\n\t\treturn;\n\n\tassert(wsi-\u003eh2_stream_immortal);\n\twsi-\u003eh2_stream_immortal \u003d 0;\n\n\tnwsi \u003d lws_get_network_wsi(wsi);\n\tlwsl_debug(\u0022%s: %p %p %d\u005cn\u0022, __func__, wsi, nwsi,\n\t\t\t\t nwsi-\u003eimmortal_substream_count);\n\tassert(nwsi-\u003eimmortal_substream_count);\n\tnwsi-\u003eimmortal_substream_count--;\n\tif (!nwsi-\u003eimmortal_substream_count)\n\t\t/*\n\t\t * since we closed the only immortal stream on this nwsi, we\n\t\t * need to reapply a normal timeout regime to the nwsi\n\t\t */\n\t\tlws_set_timeout(nwsi, PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE,\n\t\t\t\twsi-\u003evhost-\u003ekeepalive_timeout ?\n\t\t\t\t wsi-\u003evhost-\u003ekeepalive_timeout : 31);\n}\n\nvoid\nlws_http_mark_immortal(struct lws *wsi)\n{\n\tstruct lws *nwsi;\n\n\tlws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);\n\n\tif (!wsi-\u003ehttp2_substream\n#if defined(LWS_WITH_CLIENT)\n\t\t\t\u0026\u0026 !wsi-\u003eclient_h2_substream\n#endif\n\t) {\n\t\tlwsl_err(\u0022%s: not h2 substream\u005cn\u0022, __func__);\n\t\treturn;\n\t}\n\n\tnwsi \u003d lws_get_network_wsi(wsi);\n\n\tlwsl_debug(\u0022%s: %p %p %d\u005cn\u0022, __func__, wsi, nwsi,\n\t\t\t\t nwsi-\u003eimmortal_substream_count);\n\n\twsi-\u003eh2_stream_immortal \u003d 1;\n\tassert(nwsi-\u003eimmortal_substream_count \u003c 255); /* largest count */\n\tnwsi-\u003eimmortal_substream_count++;\n\tif (nwsi-\u003eimmortal_substream_count \u003d\u003d 1)\n\t\tlws_set_timeout(nwsi, NO_PENDING_TIMEOUT, 0);\n}\n\n\nint\nlws_http_mark_sse(struct lws *wsi)\n{\n\tlws_http_headers_detach(wsi);\n\tlws_http_mark_immortal(wsi);\n\n\tif (wsi-\u003ehttp2_substream)\n\t\twsi-\u003eh2_stream_carries_sse \u003d 1;\n\n\treturn 0;\n}\n","s":{"c":1571480878,"u": 678}} ],"g": 2697,"chitpc": 0,"ehitpc": 0, "indexed":0 }