{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1711721492,
"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":"ed164088f94eb6da1f66259d31665a04",
"oid":{ "oid": "e4be3317ee421f951fb16a85c7edacc9b8a0e6aa", "alias": [ "refs/heads/main"]},"blobname": "plugins/raw-proxy/protocol_lws_raw_proxy.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#if !defined (LWS_PLUGIN_STATIC)\n#if !defined(LWS_DLL)\n#define LWS_DLL\n#endif\n#if !defined(LWS_INTERNAL)\n#define LWS_INTERNAL\n#endif\n#include \u003clibwebsockets.h\u003e\n#endif\n\n#include \u003cstring.h\u003e\n#include \u003csys/types.h\u003e\n#include \u003cfcntl.h\u003e\n\n#define RING_DEPTH 8\n\nstruct packet {\n\tvoid *payload;\n\tuint32_t len;\n\tuint32_t ticket;\n};\n\nenum {\n\tACC,\n\tONW\n};\n\n/*\n * Because both sides of the connection want to share this, we allocate it\n * during accepted adoption and both sides have a pss that is just a wrapper\n * pointing to this.\n *\n * The last one of the accepted side and the onward side to close frees it.\n * This removes any chance of one side or the other having an invalidated\n * pointer to the pss.\n */\n\nstruct conn {\n\tstruct lws *wsi[2];\n\n\t/* rings containing unsent rx from accepted and onward sides */\n\tstruct lws_ring *r[2];\n\tuint32_t t[2]; /* ring tail */\n\n\tuint32_t ticket_next;\n\tuint32_t ticket_retired;\n\n\tchar rx_enabled[2];\n\tchar closed[2];\n\tchar established[2];\n};\n\nstruct raw_pss {\n\tstruct conn *conn;\n};\n\n/* one of these is created for each vhost our protocol is used with */\n\nstruct raw_vhd {\n\tchar addr[128];\n\tuint16_t port;\n\tchar ipv6;\n};\n\nstatic void\n__destroy_packet(void *_pkt)\n{\n\tstruct packet *pkt \u003d _pkt;\n\n\tfree(pkt-\u003epayload);\n\tpkt-\u003epayload \u003d NULL;\n\tpkt-\u003elen \u003d 0;\n}\n\nstatic void\ndestroy_conn(struct raw_vhd *vhd, struct raw_pss *pss)\n{\n\tstruct conn *conn \u003d pss-\u003econn;\n\n\tif (conn-\u003er[ACC])\n\t\tlws_ring_destroy(conn-\u003er[ACC]);\n\tif (conn-\u003er[ONW])\n\t\tlws_ring_destroy(conn-\u003er[ONW]);\n\n\tpss-\u003econn \u003d NULL;\n\n\tfree(conn);\n}\n\nstatic int\nconnect_client(struct raw_vhd *vhd, struct raw_pss *pss)\n{\n\tstruct lws_client_connect_info i;\n\tchar host[128];\n\tstruct lws *cwsi;\n\n\tlws_snprintf(host, sizeof(host), \u0022%s:%u\u0022, vhd-\u003eaddr, vhd-\u003eport);\n\n\tmemset(\u0026i, 0, sizeof(i));\n\n\ti.method \u003d \u0022RAW\u0022;\n\ti.context \u003d lws_get_context(pss-\u003econn-\u003ewsi[ACC]);\n\ti.port \u003d vhd-\u003eport;\n\ti.address \u003d vhd-\u003eaddr;\n\ti.host \u003d host;\n\ti.origin \u003d host;\n\ti.ssl_connection \u003d 0;\n\ti.vhost \u003d lws_get_vhost(pss-\u003econn-\u003ewsi[ACC]);\n\ti.local_protocol_name \u003d \u0022raw-proxy\u0022;\n\ti.protocol \u003d \u0022raw-proxy\u0022;\n\ti.path \u003d \u0022/\u0022;\n\t/*\n\t * The \u0022onward\u0022 client wsi has its own pss but shares the \u0022conn\u0022\n\t * created when the inbound connection was accepted. We need to stash\n\t * the address of the shared conn and apply it to the client psss\n\t * when the client connection completes.\n\t */\n\ti.opaque_user_data \u003d pss-\u003econn;\n\ti.pwsi \u003d \u0026pss-\u003econn-\u003ewsi[ONW];\n\n\tlwsl_info(\u0022%s: onward: %s:%d%s\u005cn\u0022, __func__, i.address, i.port, i.path);\n\n\tcwsi \u003d lws_client_connect_via_info(\u0026i);\n\tif (!cwsi)\n\t\tlwsl_err(\u0022%s: client connect failed early\u005cn\u0022, __func__);\n\n\treturn !cwsi;\n}\n\nstatic int\nflow_control(struct conn *conn, int side, int enable)\n{\n\tif (conn-\u003eclosed[side] ||\n\t enable \u003d\u003d conn-\u003erx_enabled[side] ||\n\t !conn-\u003eestablished[side])\n\t\treturn 0;\n\n\tif (lws_rx_flow_control(conn-\u003ewsi[side], enable))\n\t\treturn 1;\n\n\tconn-\u003erx_enabled[side] \u003d (char)enable;\n\tlwsl_info(\u0022%s: %s side: %s\u005cn\u0022, __func__, side ? \u0022ONW\u0022 : \u0022ACC\u0022,\n\t\t enable ? \u0022rx enabled\u0022 : \u0022rx flow controlled\u0022);\n\n\treturn 0;\n}\n\nstatic int\ncallback_raw_proxy(struct lws *wsi, enum lws_callback_reasons reason,\n\t\t void *user, void *in, size_t len)\n{\n\tstruct raw_pss *pss \u003d (struct raw_pss *)user;\n\tstruct raw_vhd *vhd \u003d (struct raw_vhd *)lws_protocol_vh_priv_get(\n\t\t\t\t lws_get_vhost(wsi), lws_get_protocol(wsi));\n\tconst struct packet *ppkt;\n\tstruct conn *conn \u003d NULL;\n\tstruct lws_tokenize ts;\n\tlws_tokenize_elem e;\n\tstruct packet pkt;\n\tconst char *cp;\n\tint n;\n\n\tif (pss)\n\t\tconn \u003d pss-\u003econn;\n\n\tswitch (reason) {\n\tcase LWS_CALLBACK_PROTOCOL_INIT:\n\t\tvhd \u003d lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),\n\t\t\t\tlws_get_protocol(wsi), sizeof(struct raw_vhd));\n\t\tif (!vhd)\n\t\t\treturn 0;\n\t\tif (lws_pvo_get_str(in, \u0022onward\u0022, \u0026cp)) {\n\t\t\tlwsl_warn(\u0022%s: vh %s: pvo 'onward' required\u005cn\u0022, __func__,\n\t\t\t\t lws_get_vhost_name(lws_get_vhost(wsi)));\n\n\t\t\treturn 0;\n\t\t}\n\t\tlws_tokenize_init(\u0026ts, cp, LWS_TOKENIZE_F_DOT_NONTERM |\n\t\t\t\t\t LWS_TOKENIZE_F_MINUS_NONTERM |\n\t\t\t\t\t LWS_TOKENIZE_F_NO_FLOATS);\n\t\tts.len \u003d strlen(cp);\n\n\t\tif (lws_tokenize(\u0026ts) !\u003d LWS_TOKZE_TOKEN)\n\t\t\tgoto bad_onward;\n\t\tif (!strncmp(ts.token, \u0022ipv6\u0022, ts.token_len))\n\t\t\tvhd-\u003eipv6 \u003d 1;\n\t\telse\n\t\t\tif (strncmp(ts.token, \u0022ipv4\u0022, ts.token_len))\n\t\t\t\tgoto bad_onward;\n\n\t\t/* then the colon */\n\t\tif (lws_tokenize(\u0026ts) !\u003d LWS_TOKZE_DELIMITER)\n\t\t\tgoto bad_onward;\n\n\t\te \u003d lws_tokenize(\u0026ts);\n\t\tif (!vhd-\u003eipv6) {\n\t\t\tif (e !\u003d LWS_TOKZE_TOKEN ||\n\t\t\t ts.token_len + 1 \u003e\u003d (int)sizeof(vhd-\u003eaddr))\n\t\t\t\tgoto bad_onward;\n\n\t\t\tlws_strncpy(vhd-\u003eaddr, ts.token, ts.token_len + 1);\n\t\t\te \u003d lws_tokenize(\u0026ts);\n\t\t\tif (e \u003d\u003d LWS_TOKZE_DELIMITER) {\n\t\t\t\t/* there should be a port then */\n\t\t\t\te \u003d lws_tokenize(\u0026ts);\n\t\t\t\tif (e !\u003d LWS_TOKZE_INTEGER)\n\t\t\t\t\tgoto bad_onward;\n\t\t\t\tvhd-\u003eport \u003d (uint16_t)atoi(ts.token);\n\t\t\t\te \u003d lws_tokenize(\u0026ts);\n\t\t\t}\n\t\t\tif (e !\u003d LWS_TOKZE_ENDED)\n\t\t\t\tgoto bad_onward;\n\t\t} else\n\t\t\tlws_strncpy(vhd-\u003eaddr, ts.token, sizeof(vhd-\u003eaddr));\n\n\t\tlwsl_notice(\u0022%s: vh %s: onward %s:%s:%d\u005cn\u0022, __func__,\n\t\t\t lws_get_vhost_name(lws_get_vhost(wsi)),\n\t\t\t vhd-\u003eipv6 ? \u0022ipv6\u0022: \u0022ipv4\u0022, vhd-\u003eaddr, vhd-\u003eport);\n\t\tbreak;\n\nbad_onward:\n\t\tlwsl_err(\u0022%s: onward pvo format must be ipv4:addr[:port] \u0022\n\t\t\t \u0022 or ipv6:addr, not '%s'\u005cn\u0022, __func__, cp);\n\t\treturn -1;\n\n\tcase LWS_CALLBACK_PROTOCOL_DESTROY:\n\t\tbreak;\n\n\t/* callbacks related to client \u0022onward side\u0022 */\n\n\tcase LWS_CALLBACK_CLIENT_CONNECTION_ERROR:\n\t\tlwsl_err(\u0022CLIENT_CONNECTION_ERROR: %s\u005cn\u0022,\n\t\t\t in ? (char *)in : \u0022(null)\u0022);\n\t\tbreak;\n\n case LWS_CALLBACK_RAW_PROXY_CLI_ADOPT:\n\t\tlwsl_debug(\u0022%s: %p: LWS_CALLBACK_RAW_CLI_ADOPT: pss %p\u005cn\u0022, __func__, wsi, pss);\n\t\tif (conn || !pss)\n\t\t\tbreak;\n\t\tconn \u003d pss-\u003econn \u003d lws_get_opaque_user_data(wsi);\n\t\tif (!conn)\n\t\t\tbreak;\n\t\tconn-\u003eestablished[ONW] \u003d 1;\n\t\t/* they start enabled */\n\t\tconn-\u003erx_enabled[ACC] \u003d 1;\n\t\tconn-\u003erx_enabled[ONW] \u003d 1;\n\n\t\t/* he disabled his rx while waiting for use to be established */\n\t\tflow_control(conn, ACC, 1);\n\n\t\tlws_callback_on_writable(wsi);\n\t\tlws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);\n\t\tbreak;\n\n\tcase LWS_CALLBACK_RAW_PROXY_CLI_CLOSE:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_PROXY_CLI_CLOSE\u005cn\u0022);\n\t\tif (!conn)\n\t\t\tbreak;\n\n\t\tconn-\u003eclosed[ONW] \u003d 1;\n\n\t\tif (conn-\u003eclosed[ACC])\n\t\t\tdestroy_conn(vhd, pss);\n\n\t\tbreak;\n\n\tcase LWS_CALLBACK_RAW_PROXY_CLI_RX:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_PROXY_CLI_RX: %d\u005cn\u0022, (int)len);\n\n\t\tif (!conn)\n\t\t\treturn 0;\n\n\t\tif (!pss || !conn-\u003ewsi[ACC] || conn-\u003eclosed[ACC]) {\n\t\t\tlwsl_info(\u0022 pss %p, wsi[ACC] %p, closed[ACC] %d\u005cn\u0022,\n\t\t\t\t pss, conn-\u003ewsi[ACC], conn-\u003eclosed[ACC]);\n\t\t\treturn -1;\n\t\t}\n\t\tpkt.payload \u003d malloc(len);\n\t\tif (!pkt.payload) {\n\t\t\tlwsl_notice(\u0022OOM: dropping\u005cn\u0022);\n\t\t\treturn -1;\n\t\t}\n\t\tpkt.len \u003d (uint32_t)len;\n\t\tpkt.ticket \u003d conn-\u003eticket_next++;\n\n\t\tmemcpy(pkt.payload, in, len);\n\t\tif (!lws_ring_insert(conn-\u003er[ONW], \u0026pkt, 1)) {\n\t\t\t__destroy_packet(\u0026pkt);\n\t\t\tlwsl_notice(\u0022dropping!\u005cn\u0022);\n\t\t\treturn -1;\n\t\t}\n\n\t\tlwsl_debug(\u0022After onward RX: acc free: %d...\u005cn\u0022,\n\t\t\t (int)lws_ring_get_count_free_elements(conn-\u003er[ONW]));\n\n\t\tif (conn-\u003erx_enabled[ONW] \u0026\u0026\n\t\t lws_ring_get_count_free_elements(conn-\u003er[ONW]) \u003c 2)\n\t\t\tflow_control(conn, ONW, 0);\n\n\t\tif (!conn-\u003eclosed[ACC])\n\t\t\tlws_callback_on_writable(conn-\u003ewsi[ACC]);\n\t\tbreak;\n\n\tcase LWS_CALLBACK_RAW_PROXY_CLI_WRITEABLE:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_PROXY_CLI_WRITEABLE\u005cn\u0022);\n\n\t\tif (!conn)\n\t\t\tbreak;\n\n\t\tppkt \u003d lws_ring_get_element(conn-\u003er[ACC], \u0026conn-\u003et[ACC]);\n\t\tif (!ppkt) {\n\t\t\tlwsl_info(\u0022%s: CLI_WRITABLE had nothing in acc ring\u005cn\u0022,\n\t\t\t\t __func__);\n\t\t\tbreak;\n\t\t}\n\n\t\tif (ppkt-\u003eticket !\u003d conn-\u003eticket_retired + 1) {\n\t\t\tlwsl_info(\u0022%s: acc ring has %d but next %d\u005cn\u0022, __func__,\n\t\t\t\t ppkt-\u003eticket, conn-\u003eticket_retired + 1);\n\t\t\tlws_callback_on_writable(conn-\u003ewsi[ACC]);\n\t\t\tbreak;\n\t\t}\n\n\t\tn \u003d lws_write(wsi, ppkt-\u003epayload, ppkt-\u003elen, LWS_WRITE_RAW);\n\t\tif (n \u003c 0) {\n\t\t\tlwsl_info(\u0022%s: WRITEABLE: %d\u005cn\u0022, __func__, n);\n\n\t\t\treturn -1;\n\t\t}\n\n\t\tconn-\u003eticket_retired \u003d ppkt-\u003eticket;\n\t\tlws_ring_consume(conn-\u003er[ACC], \u0026conn-\u003et[ACC], NULL, 1);\n\t\tlws_ring_update_oldest_tail(conn-\u003er[ACC], conn-\u003et[ACC]);\n\n\t\tlwsl_debug(\u0022acc free: %d...\u005cn\u0022,\n\t\t\t (int)lws_ring_get_count_free_elements(conn-\u003er[ACC]));\n\n\t\tif (!conn-\u003erx_enabled[ACC] \u0026\u0026\n\t\t lws_ring_get_count_free_elements(conn-\u003er[ACC]) \u003e 2)\n\t\t\tflow_control(conn, ACC, 1);\n\n\t\tppkt \u003d lws_ring_get_element(conn-\u003er[ACC], \u0026conn-\u003et[ACC]);\n\t\tlwsl_debug(\u0022%s: CLI_WRITABLE: next acc pkt %p idx %d vs %d\u005cn\u0022,\n\t\t\t __func__, ppkt, ppkt ? ppkt-\u003eticket : 0,\n\t\t\t\t\t conn-\u003eticket_retired + 1);\n\n\t\tif (ppkt \u0026\u0026 ppkt-\u003eticket \u003d\u003d conn-\u003eticket_retired + 1)\n\t\t\tlws_callback_on_writable(wsi);\n\t\telse {\n\t\t\t/*\n\t\t\t * defer checking for accepted side closing until we\n\t\t\t * sent everything in the ring to onward\n\t\t\t */\n\t\t\tif (conn-\u003eclosed[ACC])\n\t\t\t\t/*\n\t\t\t\t * there is never going to be any more... but\n\t\t\t\t * we may have some tx still in tx buflist /\n\t\t\t\t * partial\n\t\t\t\t */\n\t\t\t\treturn lws_raw_transaction_completed(wsi);\n\n\t\t\tif (lws_ring_get_element(conn-\u003er[ONW], \u0026conn-\u003et[ONW]))\n\t\t\t\tlws_callback_on_writable(conn-\u003ewsi[ACC]);\n\t\t}\n\t\tbreak;\n\n\t/* callbacks related to raw socket descriptor \u0022accepted side\u0022 */\n\n case LWS_CALLBACK_RAW_PROXY_SRV_ADOPT:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_SRV_ADOPT\u005cn\u0022);\n\t\tif (!pss)\n\t\t\treturn -1;\n\t\tconn \u003d pss-\u003econn \u003d malloc(sizeof(struct conn));\n\t\tif (!pss-\u003econn)\n\t\t\treturn -1;\n\t\tmemset(conn, 0, sizeof(*conn));\n\n\t\tconn-\u003ewsi[ACC] \u003d wsi;\n\t\tconn-\u003eticket_next \u003d 1;\n\n\t\tconn-\u003er[ACC] \u003d lws_ring_create(sizeof(struct packet),\n\t\t\t\t\t RING_DEPTH, __destroy_packet);\n\t\tif (!conn-\u003er[ACC]) {\n\t\t\tlwsl_err(\u0022%s: OOM\u005cn\u0022, __func__);\n\t\t\treturn -1;\n\t\t}\n\t\tconn-\u003er[ONW] \u003d lws_ring_create(sizeof(struct packet),\n\t\t\t\t\t RING_DEPTH, __destroy_packet);\n\t\tif (!conn-\u003er[ONW]) {\n\t\t\tlws_ring_destroy(conn-\u003er[ACC]);\n\t\t\tconn-\u003er[ACC] \u003d NULL;\n\t\t\tlwsl_err(\u0022%s: OOM\u005cn\u0022, __func__);\n\n\t\t\treturn -1;\n\t\t}\n\n\t\tconn-\u003eestablished[ACC] \u003d 1;\n\n\t\t/* disable any rx until the client side is up */\n\t\tflow_control(conn, ACC, 0);\n\n\t\tlws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);\n\n\t\t/* try to create the onward client connection */\n\t\tconnect_client(vhd, pss);\n break;\n\n\tcase LWS_CALLBACK_RAW_PROXY_SRV_CLOSE:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_PROXY_SRV_CLOSE:\u005cn\u0022);\n\n\t\tif (!conn)\n\t\t\tbreak;\n\n\t\tconn-\u003eclosed[ACC] \u003d 1;\n\t\tif (conn-\u003eclosed[ONW])\n\t\t\tdestroy_conn(vhd, pss);\n\t\tbreak;\n\n\tcase LWS_CALLBACK_RAW_PROXY_SRV_RX:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_PROXY_SRV_RX: rx %d\u005cn\u0022, (int)len);\n\n\t\tif (!conn || !conn-\u003ewsi[ONW]) {\n\t\t\tlwsl_err(\u0022%s: LWS_CALLBACK_RAW_PROXY_SRV_RX: \u0022\n\t\t\t\t \u0022conn-\u003ewsi[ONW] NULL\u005cn\u0022, __func__);\n\t\t\treturn -1;\n\t\t}\n\t\tif (conn-\u003eclosed[ONW]) {\n\t\t\tlwsl_info(\u0022 closed[ONW] %d\u005cn\u0022, conn-\u003eclosed[ONW]);\n\t\t\treturn -1;\n\t\t}\n\n\t\tif (!len)\n\t\t\treturn 0;\n\n\t\tpkt.payload \u003d malloc(len);\n\t\tif (!pkt.payload) {\n\t\t\tlwsl_notice(\u0022OOM: dropping\u005cn\u0022);\n\t\t\treturn -1;\n\t\t}\n\t\tpkt.len \u003d (uint32_t)len;\n\t\tpkt.ticket \u003d conn-\u003eticket_next++;\n\n\t\tmemcpy(pkt.payload, in, len);\n\t\tif (!lws_ring_insert(conn-\u003er[ACC], \u0026pkt, 1)) {\n\t\t\t__destroy_packet(\u0026pkt);\n\t\t\tlwsl_notice(\u0022dropping!\u005cn\u0022);\n\t\t\treturn -1;\n\t\t}\n\n\t\tlwsl_debug(\u0022After acc RX: acc free: %d...\u005cn\u0022,\n\t\t\t (int)lws_ring_get_count_free_elements(conn-\u003er[ACC]));\n\n\t\tif (conn-\u003erx_enabled[ACC] \u0026\u0026\n\t\t lws_ring_get_count_free_elements(conn-\u003er[ACC]) \u003c\u003d 2)\n\t\t\tflow_control(conn, ACC, 0);\n\n\t\tif (conn-\u003eestablished[ONW] \u0026\u0026 !conn-\u003eclosed[ONW])\n\t\t\tlws_callback_on_writable(conn-\u003ewsi[ONW]);\n\t\tbreak;\n\n\tcase LWS_CALLBACK_RAW_PROXY_SRV_WRITEABLE:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_RAW_PROXY_SRV_WRITEABLE\u005cn\u0022);\n\n\t\tif (!conn || !conn-\u003eestablished[ONW] || conn-\u003eclosed[ONW])\n\t\t\tbreak;\n\n\t\tppkt \u003d lws_ring_get_element(conn-\u003er[ONW], \u0026conn-\u003et[ONW]);\n\t\tif (!ppkt) {\n\t\t\tlwsl_info(\u0022%s: SRV_WRITABLE nothing in onw ring\u005cn\u0022,\n\t\t\t\t __func__);\n\t\t\tbreak;\n\t\t}\n\n\t\tif (ppkt-\u003eticket !\u003d conn-\u003eticket_retired + 1) {\n\t\t\tlwsl_info(\u0022%s: onw ring has %d but next %d\u005cn\u0022, __func__,\n\t\t\t\t ppkt-\u003eticket, conn-\u003eticket_retired + 1);\n\t\t\tlws_callback_on_writable(conn-\u003ewsi[ONW]);\n\t\t\tbreak;\n\t\t}\n\n\t\tn \u003d lws_write(wsi, ppkt-\u003epayload, ppkt-\u003elen, LWS_WRITE_RAW);\n\t\tif (n \u003c 0) {\n\t\t\tlwsl_info(\u0022%s: WRITEABLE: %d\u005cn\u0022, __func__, n);\n\n\t\t\treturn -1;\n\t\t}\n\n\t\tconn-\u003eticket_retired \u003d ppkt-\u003eticket;\n\t\tlws_ring_consume(conn-\u003er[ONW], \u0026conn-\u003et[ONW], NULL, 1);\n\t\tlws_ring_update_oldest_tail(conn-\u003er[ONW], conn-\u003et[ONW]);\n\n\t\tlwsl_debug(\u0022onward free: %d... waiting %d\u005cn\u0022,\n\t\t\t (int)lws_ring_get_count_free_elements(conn-\u003er[ONW]),\n\t\t\t (int)lws_ring_get_count_waiting_elements(conn-\u003er[ONW],\n\t\t\t\t\t\t\t\t\u0026conn-\u003et[ONW]));\n\n\t\tif (!conn-\u003erx_enabled[ONW] \u0026\u0026\n\t\t lws_ring_get_count_free_elements(conn-\u003er[ONW]) \u003e 2)\n\t\t\tflow_control(conn, ONW, 1);\n\n\t\tppkt \u003d lws_ring_get_element(conn-\u003er[ONW], \u0026conn-\u003et[ONW]);\n\t\tlwsl_debug(\u0022%s: SRV_WRITABLE: next onw pkt %p idx %d vs %d\u005cn\u0022,\n\t\t\t __func__, ppkt, ppkt ? ppkt-\u003eticket : 0,\n\t\t\t\t\t conn-\u003eticket_retired + 1);\n\n\t\tif (ppkt \u0026\u0026 ppkt-\u003eticket \u003d\u003d conn-\u003eticket_retired + 1)\n\t\t\tlws_callback_on_writable(wsi);\n\t\telse {\n\t\t\t/*\n\t\t\t * defer checking for onward side closing until we\n\t\t\t * sent everything in the ring to accepted side\n\t\t\t */\n\t\t\tif (conn-\u003eclosed[ONW])\n\t\t\t\t/*\n\t\t\t\t * there is never going to be any more... but\n\t\t\t\t * we may have some tx still in tx buflist /\n\t\t\t\t * partial\n\t\t\t\t */\n\t\t\t\treturn lws_raw_transaction_completed(wsi);\n\n\t\tif (lws_ring_get_element(conn-\u003er[ACC], \u0026conn-\u003et[ACC]))\n\t\t\tlws_callback_on_writable(conn-\u003ewsi[ONW]);\n\t\t}\n\t\tbreak;\n\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn lws_callback_http_dummy(wsi, reason, user, in, len);\n}\n\n#define LWS_PLUGIN_PROTOCOL_RAW_PROXY { \u005c\n\t\t\u0022raw-proxy\u0022, \u005c\n\t\tcallback_raw_proxy, \u005c\n\t\tsizeof(struct raw_pss), \u005c\n\t\t8192, \u005c\n\t\t8192, NULL, 0 \u005c\n\t}\n\n#if !defined (LWS_PLUGIN_STATIC)\n\nLWS_VISIBLE const struct lws_protocols lws_raw_proxy_protocols[] \u003d {\n\tLWS_PLUGIN_PROTOCOL_RAW_PROXY\n};\n\nLWS_VISIBLE const lws_plugin_protocol_t lws_raw_proxy \u003d {\n\t.hdr \u003d {\n\t\t\u0022raw proxy\u0022,\n\t\t\u0022lws_protocol_plugin\u0022,\n\t\tLWS_BUILD_HASH,\n\t\tLWS_PLUGIN_API_MAGIC\n\t},\n\n\t.protocols \u003d lws_raw_proxy_protocols,\n\t.count_protocols \u003d LWS_ARRAY_SIZE(lws_raw_proxy_protocols),\n\t.extensions \u003d NULL,\n\t.count_extensions \u003d 0,\n};\n#endif\n\n\n","s":{"c":1711721492,"u": 833}}
],"g": 2874,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}