{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1730921594,
"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":"63d49db4eeb551ecf94a8d325930da26",
"oid":{ "oid": "626f8816cfb211ec3ccfa56dc9f67af251e130e3", "alias": [ "refs/heads/main"]},"blobname": "lib/roles/http/header.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#include \u0022lextable-strings.h\u0022\n\n\nconst unsigned char *\nlws_token_to_string(enum lws_token_indexes token)\n{\n\tif ((unsigned int)token \u003e\u003d LWS_ARRAY_SIZE(set))\n\t\treturn NULL;\n\n\treturn (unsigned char *)set[token];\n}\n\n/*\n * Return http header index if one matches slen chars of s, or -1\n */\n\nint\nlws_http_string_to_known_header(const char *s, size_t slen)\n{\n\tint n;\n\n\tfor (n \u003d 0; n \u003c (int)LWS_ARRAY_SIZE(set); n++)\n\t\tif (!strncmp(set[n], s, slen))\n\t\t\treturn n;\n\n\treturn LWS_HTTP_NO_KNOWN_HEADER;\n}\n\n#ifdef LWS_WITH_HTTP2\nint\nlws_wsi_is_h2(struct lws *wsi)\n{\n\treturn wsi-\u003eupgraded_to_http2 ||\n\t wsi-\u003emux_substream ||\n#if defined(LWS_WITH_CLIENT)\n\t wsi-\u003eclient_mux_substream ||\n#endif\n\t lwsi_role_h2(wsi) ||\n\t lwsi_role_h2_ENCAPSULATION(wsi);\n}\n#endif\n\nint\nlws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,\n\t\t\t const unsigned char *value, int length,\n\t\t\t unsigned char **p, unsigned char *end)\n{\n#ifdef LWS_WITH_HTTP2\n\tif (lws_wsi_is_h2(wsi))\n\t\treturn lws_add_http2_header_by_name(wsi, name,\n\t\t\t\t\t\t value, length, p, end);\n#else\n\t(void)wsi;\n#endif\n\tif (name) {\n\t\tchar has_colon \u003d 0;\n\t\twhile (*p \u003c end \u0026\u0026 *name) {\n\t\t\thas_colon \u003d has_colon || *name \u003d\u003d ':';\n\t\t\t*((*p)++) \u003d *name++;\n\t\t}\n\t\tif (*p + (has_colon ? 1 : 2) \u003e\u003d end)\n\t\t\treturn 1;\n\t\tif (!has_colon)\n\t\t\t*((*p)++) \u003d ':';\n\t\t*((*p)++) \u003d ' ';\n\t}\n\tif (*p + length + 3 \u003e\u003d end)\n\t\treturn 1;\n\n\tif (value)\n\t\tmemcpy(*p, value, (unsigned int)length);\n\t*p +\u003d length;\n\t*((*p)++) \u003d '\u005cx0d';\n\t*((*p)++) \u003d '\u005cx0a';\n\n\treturn 0;\n}\n\nint lws_finalize_http_header(struct lws *wsi, unsigned char **p,\n\t\t\t unsigned char *end)\n{\n#ifdef LWS_WITH_HTTP2\n\tif (lws_wsi_is_h2(wsi))\n\t\treturn 0;\n#else\n\t(void)wsi;\n#endif\n\tif ((lws_intptr_t)(end - *p) \u003c 3)\n\t\treturn 1;\n\t*((*p)++) \u003d '\u005cx0d';\n\t*((*p)++) \u003d '\u005cx0a';\n\n\treturn 0;\n}\n\nint\nlws_finalize_write_http_header(struct lws *wsi, unsigned char *start,\n\t\t\t unsigned char **pp, unsigned char *end)\n{\n\tunsigned char *p;\n\tint len;\n\n\tif (lws_finalize_http_header(wsi, pp, end))\n\t\treturn 1;\n\n\tp \u003d *pp;\n\tlen \u003d lws_ptr_diff(p, start);\n\n\tif (lws_write(wsi, start, (unsigned int)len, LWS_WRITE_HTTP_HEADERS) !\u003d len)\n\t\treturn 1;\n\n\treturn 0;\n}\n\nint\nlws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,\n\t\t\t const unsigned char *value, int length,\n\t\t\t unsigned char **p, unsigned char *end)\n{\n\tconst unsigned char *name;\n#ifdef LWS_WITH_HTTP2\n\tif (lws_wsi_is_h2(wsi))\n\t\treturn lws_add_http2_header_by_token(wsi, token, value,\n\t\t\t\t\t\t length, p, end);\n#endif\n\tname \u003d lws_token_to_string(token);\n\tif (!name)\n\t\treturn 1;\n\n\treturn lws_add_http_header_by_name(wsi, name, value, length, p, end);\n}\n\nint\nlws_add_http_header_content_length(struct lws *wsi,\n\t\t\t\t lws_filepos_t content_length,\n\t\t\t\t unsigned char **p, unsigned char *end)\n{\n\tchar b[24];\n\tint n;\n\n\tn \u003d lws_snprintf(b, sizeof(b) - 1, \u0022%llu\u0022, (unsigned long long)content_length);\n\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,\n\t\t\t\t\t (unsigned char *)b, n, p, end))\n\t\treturn 1;\n\twsi-\u003ehttp.tx_content_length \u003d content_length;\n\twsi-\u003ehttp.tx_content_remain \u003d content_length;\n\n\tlwsl_info(\u0022%s: %s: tx_content_length/remain %llu\u005cn\u0022, __func__,\n\t\t lws_wsi_tag(wsi), (unsigned long long)content_length);\n\n\treturn 0;\n}\n\n#if defined(LWS_WITH_SERVER)\n\nint\nlws_add_http_common_headers(struct lws *wsi, unsigned int code,\n\t\t\t const char *content_type, lws_filepos_t content_len,\n\t\t\t unsigned char **p, unsigned char *end)\n{\n\tconst char *ka[] \u003d { \u0022close\u0022, \u0022keep-alive\u0022 };\n\tint types[] \u003d { HTTP_CONNECTION_CLOSE, HTTP_CONNECTION_KEEP_ALIVE },\n\t\t\tt \u003d 0;\n\n\tif (lws_add_http_header_status(wsi, code, p, end))\n\t\treturn 1;\n\n\tif (content_type \u0026\u0026\n\t lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,\n\t\t \t\t\t(unsigned char *)content_type,\n\t\t \t\t\t(int)strlen(content_type), p, end))\n\t\treturn 1;\n\n#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)\n\tif (!wsi-\u003ehttp.lcs \u0026\u0026 content_type \u0026\u0026\n\t (!strncmp(content_type, \u0022text/\u0022, 5) ||\n\t !strcmp(content_type, \u0022application/javascript\u0022) ||\n\t !strcmp(content_type, \u0022image/svg+xml\u0022)))\n\t\tlws_http_compression_apply(wsi, NULL, p, end, 0);\n#endif\n\n\t/*\n\t * if we decided to compress it, we don't know the content length...\n\t * the compressed data will go out chunked on h1\n\t */\n\tif (\n#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)\n\t !wsi-\u003ehttp.lcs \u0026\u0026\n#endif\n\t content_len !\u003d LWS_ILLEGAL_HTTP_CONTENT_LEN) {\n\t\tif (lws_add_http_header_content_length(wsi, content_len,\n\t\t\t\t\t\t p, end))\n\t\t\treturn 1;\n\t} else {\n\t\t/* there was no length... it normally means CONNECTION_CLOSE */\n#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)\n\n\t\tif (!wsi-\u003emux_substream \u0026\u0026 wsi-\u003ehttp.lcs) {\n\t\t\t/* so...\n\t\t\t * - h1 connection\n\t\t\t * - http compression transform active\n\t\t\t * - did not send content length\n\t\t\t *\n\t\t\t * then mark as chunked...\n\t\t\t */\n\t\t\twsi-\u003ehttp.comp_ctx.chunking \u003d 1;\n\t\t\tif (lws_add_http_header_by_token(wsi,\n\t\t\t\t\tWSI_TOKEN_HTTP_TRANSFER_ENCODING,\n\t\t\t\t\t(unsigned char *)\u0022chunked\u0022, 7, p, end))\n\t\t\t\treturn -1;\n\n\t\t\t/* ... but h1 compression is chunked, if active we can\n\t\t\t * still pipeline\n\t\t\t */\n\t\t\tif (wsi-\u003ehttp.lcs \u0026\u0026\n\t\t\t wsi-\u003ehttp.conn_type \u003d\u003d HTTP_CONNECTION_KEEP_ALIVE)\n\t\t\t\tt \u003d 1;\n\t\t}\n#endif\n\t\tif (!wsi-\u003emux_substream) {\n\t\t\tif (lws_add_http_header_by_token(wsi,\n\t\t\t\t\t\t WSI_TOKEN_CONNECTION,\n\t\t\t\t\t\t (unsigned char *)ka[t],\n\t\t\t\t\t\t (int)strlen(ka[t]), p, end))\n\t\t\t\treturn 1;\n\n\t\t\twsi-\u003ehttp.conn_type \u003d (enum http_conn_type)types[t];\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic const char * const err400[] \u003d {\n\t\u0022Bad Request\u0022,\n\t\u0022Unauthorized\u0022,\n\t\u0022Payment Required\u0022,\n\t\u0022Forbidden\u0022,\n\t\u0022Not Found\u0022,\n\t\u0022Method Not Allowed\u0022,\n\t\u0022Not Acceptable\u0022,\n\t\u0022Proxy Auth Required\u0022,\n\t\u0022Request Timeout\u0022,\n\t\u0022Conflict\u0022,\n\t\u0022Gone\u0022,\n\t\u0022Length Required\u0022,\n\t\u0022Precondition Failed\u0022,\n\t\u0022Request Entity Too Large\u0022,\n\t\u0022Request URI too Long\u0022,\n\t\u0022Unsupported Media Type\u0022,\n\t\u0022Requested Range Not Satisfiable\u0022,\n\t\u0022Expectation Failed\u0022\n};\n\nstatic const char * const err500[] \u003d {\n\t\u0022Internal Server Error\u0022,\n\t\u0022Not Implemented\u0022,\n\t\u0022Bad Gateway\u0022,\n\t\u0022Service Unavailable\u0022,\n\t\u0022Gateway Timeout\u0022,\n\t\u0022HTTP Version Not Supported\u0022\n};\n\n/* security best practices from Mozilla Observatory */\n\nstatic const\nstruct lws_protocol_vhost_options pvo_hsbph[] \u003d {{\n\tNULL, NULL, \u0022referrer-policy:\u0022, \u0022no-referrer\u0022\n}, {\n\t\u0026pvo_hsbph[0], NULL, \u0022x-frame-options:\u0022, \u0022deny\u0022\n}, {\n\t\u0026pvo_hsbph[1], NULL, \u0022x-xss-protection:\u0022, \u00221; mode\u003dblock\u0022\n}, {\n\t\u0026pvo_hsbph[2], NULL, \u0022x-content-type-options:\u0022, \u0022nosniff\u0022\n}, {\n\t\u0026pvo_hsbph[3], NULL, \u0022content-security-policy:\u0022,\n\t\u0022default-src 'none'; img-src 'self' data: ; \u0022\n\t\t\u0022script-src 'self'; font-src 'self'; \u0022\n\t\t\u0022style-src 'self'; connect-src 'self' ws: wss:; \u0022\n\t\t\u0022frame-ancestors 'none'; base-uri 'none';\u0022\n\t\t\u0022form-action 'self';\u0022\n}};\n\nint\nlws_add_http_header_status(struct lws *wsi, unsigned int _code,\n\t\t\t unsigned char **p, unsigned char *end)\n{\n\tstatic const char * const hver[] \u003d {\n\t\t\u0022HTTP/1.0\u0022, \u0022HTTP/1.1\u0022, \u0022HTTP/2\u0022\n\t};\n\tconst struct lws_protocol_vhost_options *headers;\n\tunsigned int code \u003d _code \u0026 LWSAHH_CODE_MASK;\n\tconst char *description \u003d \u0022\u0022, *p1;\n\tunsigned char code_and_desc[60];\n\tint n;\n\n\twsi-\u003ehttp.response_code \u003d code;\n#ifdef LWS_WITH_ACCESS_LOG\n\twsi-\u003ehttp.access_log.response \u003d (int)code;\n#endif\n\n#ifdef LWS_WITH_HTTP2\n\tif (lws_wsi_is_h2(wsi)) {\n\t\tn \u003d lws_add_http2_header_status(wsi, code, p, end);\n\t\tif (n)\n\t\t\treturn n;\n\t} else\n#endif\n\t{\n\t\tif (code \u003e\u003d 400 \u0026\u0026 code \u003c (400 + LWS_ARRAY_SIZE(err400)))\n\t\t\tdescription \u003d err400[code - 400];\n\t\tif (code \u003e\u003d 500 \u0026\u0026 code \u003c (500 + LWS_ARRAY_SIZE(err500)))\n\t\t\tdescription \u003d err500[code - 500];\n\n\t\tif (code \u003d\u003d 100)\n\t\t\tdescription \u003d \u0022Continue\u0022;\n\t\tif (code \u003d\u003d 200)\n\t\t\tdescription \u003d \u0022OK\u0022;\n\t\tif (code \u003d\u003d 304)\n\t\t\tdescription \u003d \u0022Not Modified\u0022;\n\t\telse\n\t\t\tif (code \u003e\u003d 300 \u0026\u0026 code \u003c 400)\n\t\t\t\tdescription \u003d \u0022Redirect\u0022;\n\n\t\tif (wsi-\u003ehttp.request_version \u003c LWS_ARRAY_SIZE(hver))\n\t\t\tp1 \u003d hver[wsi-\u003ehttp.request_version];\n\t\telse\n\t\t\tp1 \u003d hver[0];\n\n\t\tn \u003d lws_snprintf((char *)code_and_desc,\n\t\t\t\t sizeof(code_and_desc) - 1, \u0022%s %u %s\u0022,\n\t\t\t\t p1, code, description);\n\n\t\tif (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p,\n\t\t\t\t\t\tend))\n\t\t\treturn 1;\n\t}\n\n\theaders \u003d wsi-\u003ea.vhost-\u003eheaders;\n\twhile (headers) {\n\t\tif (lws_add_http_header_by_name(wsi,\n\t\t\t\t(const unsigned char *)headers-\u003ename,\n\t\t\t\t(unsigned char *)headers-\u003evalue,\n\t\t\t\t(int)strlen(headers-\u003evalue), p, end))\n\t\t\treturn 1;\n\n\t\theaders \u003d headers-\u003enext;\n\t}\n\n\tif (wsi-\u003ea.vhost-\u003eoptions \u0026\n\t LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE) {\n\t\theaders \u003d \u0026pvo_hsbph[LWS_ARRAY_SIZE(pvo_hsbph) - 1];\n\t\twhile (headers) {\n\t\t\tif (lws_add_http_header_by_name(wsi,\n\t\t\t\t\t(const unsigned char *)headers-\u003ename,\n\t\t\t\t\t(unsigned char *)headers-\u003evalue,\n\t\t\t\t\t(int)strlen(headers-\u003evalue), p, end))\n\t\t\t\treturn 1;\n\n\t\t\theaders \u003d headers-\u003enext;\n\t\t}\n\t}\n\n\tif (wsi-\u003ea.context-\u003eserver_string \u0026\u0026\n\t !(_code \u0026 LWSAHH_FLAG_NO_SERVER_NAME)) {\n\t\tassert(wsi-\u003ea.context-\u003eserver_string_len \u003e 0);\n\t\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,\n\t\t\t\t(unsigned char *)wsi-\u003ea.context-\u003eserver_string,\n\t\t\t\twsi-\u003ea.context-\u003eserver_string_len, p, end))\n\t\t\treturn 1;\n\t}\n\n\tif (wsi-\u003ea.vhost-\u003eoptions \u0026 LWS_SERVER_OPTION_STS)\n\t\tif (lws_add_http_header_by_name(wsi, (unsigned char *)\n\t\t\t\t\u0022Strict-Transport-Security:\u0022,\n\t\t\t\t(unsigned char *)\u0022max-age\u003d15768000 ; \u0022\n\t\t\t\t\u0022includeSubDomains\u0022, 36, p, end))\n\t\t\treturn 1;\n\n\tif (*p \u003e\u003d (end - 2)) {\n\t\tlwsl_err(\u0022%s: reached end of buffer\u005cn\u0022, __func__);\n\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\nint\nlws_return_http_status(struct lws *wsi, unsigned int code,\n\t\t const char *html_body)\n{\n\tstruct lws_context *context \u003d lws_get_context(wsi);\n\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[(int)wsi-\u003etsi];\n\tunsigned char *p \u003d pt-\u003eserv_buf + LWS_PRE;\n\tunsigned char *start \u003d p;\n\tunsigned char *end \u003d p + context-\u003ept_serv_buf_size - LWS_PRE;\n\tchar *body \u003d (char *)start + context-\u003ept_serv_buf_size - 512;\n\tint n \u003d 0, m \u003d 0, len;\n\tchar slen[20];\n\n\tif (!wsi-\u003ea.vhost) {\n\t\tlwsl_err(\u0022%s: wsi not bound to vhost\u005cn\u0022, __func__);\n\n\t\treturn 1;\n\t}\n#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n\tif (!wsi-\u003ehandling_404 \u0026\u0026\n\t wsi-\u003ea.vhost-\u003ehttp.error_document_404 \u0026\u0026\n\t code \u003d\u003d HTTP_STATUS_NOT_FOUND)\n\t\t/* we should do a redirect, and do the 404 there */\n\t\tif (lws_http_redirect(wsi, HTTP_STATUS_FOUND,\n\t\t\t (uint8_t *)wsi-\u003ea.vhost-\u003ehttp.error_document_404,\n\t\t\t (int)strlen(wsi-\u003ea.vhost-\u003ehttp.error_document_404),\n\t\t\t \u0026p, end) \u003e 0)\n\t\t\treturn 0;\n#endif\n\n\t/* if the redirect failed, just do a simple status */\n\tp \u003d start;\n\n\tif (!html_body)\n\t\thtml_body \u003d \u0022\u0022;\n\n\tif (lws_add_http_header_status(wsi, code, \u0026p, end))\n\t\treturn 1;\n\n\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,\n\t\t\t\t\t (unsigned char *)\u0022text/html\u0022, 9,\n\t\t\t\t\t \u0026p, end))\n\t\treturn 1;\n\n\tlen \u003d lws_snprintf(body, 510, \u0022\u003chtml\u003e\u003chead\u003e\u0022\n\t\t\u0022\u003cmeta charset\u003dutf-8 http-equiv\u003d\u005c\u0022Content-Language\u005c\u0022 \u0022\n\t\t\t\u0022content\u003d\u005c\u0022en\u005c\u0022/\u003e\u0022\n\t\t\u0022\u003clink rel\u003d\u005c\u0022stylesheet\u005c\u0022 type\u003d\u005c\u0022text/css\u005c\u0022 \u0022\n\t\t\t\u0022href\u003d\u005c\u0022/error.css\u005c\u0022/\u003e\u0022\n\t\t\u0022\u003c/head\u003e\u003cbody\u003e\u003ch1\u003e%u\u003c/h1\u003e%s\u003c/body\u003e\u003c/html\u003e\u0022, code, html_body);\n\n\n\tn \u003d lws_snprintf(slen, 12, \u0022%d\u0022, len);\n\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,\n\t\t\t\t\t (unsigned char *)slen, n, \u0026p, end))\n\t\treturn 1;\n\n\tif (lws_finalize_http_header(wsi, \u0026p, end))\n\t\treturn 1;\n\n#if defined(LWS_WITH_HTTP2)\n\tif (wsi-\u003emux_substream) {\n\n\t\t/*\n\t\t * for HTTP/2, the headers must be sent separately, since they\n\t\t * go out in their own frame. That puts us in a bind that\n\t\t * we won't always be able to get away with two lws_write()s in\n\t\t * sequence, since the first may use up the writability due to\n\t\t * the pipe being choked or SSL_WANT_.\n\t\t *\n\t\t * However we do need to send the human-readable body, and the\n\t\t * END_STREAM.\n\t\t *\n\t\t * Solve it by writing the headers now...\n\t\t */\n\t\tm \u003d lws_write(wsi, start, lws_ptr_diff_size_t(p, start),\n\t\t\t LWS_WRITE_HTTP_HEADERS);\n\t\tif (m !\u003d lws_ptr_diff(p, start))\n\t\t\treturn 1;\n\n\t\t/*\n\t\t * ... but stash the body and send it as a priority next\n\t\t * handle_POLLOUT\n\t\t */\n\t\twsi-\u003ehttp.tx_content_length \u003d (unsigned int)len;\n\t\twsi-\u003ehttp.tx_content_remain \u003d (unsigned int)len;\n\n\t\twsi-\u003eh2.pending_status_body \u003d lws_malloc((unsigned int)len + LWS_PRE + 1,\n\t\t\t\t\t\t\t\u0022pending status body\u0022);\n\t\tif (!wsi-\u003eh2.pending_status_body)\n\t\t\treturn -1;\n\n\t\tstrcpy(wsi-\u003eh2.pending_status_body + LWS_PRE, body);\n\t\tlws_callback_on_writable(wsi);\n\n\t\treturn 0;\n\t} else\n#endif\n\t{\n\t\t/*\n\t\t * for http/1, we can just append the body after the finalized\n\t\t * headers and send it all in one go.\n\t\t */\n\n\t\tn \u003d lws_ptr_diff(p, start) + len;\n\t\tmemcpy(p, body, (unsigned int)len);\n\t\tm \u003d lws_write(wsi, start, (unsigned int)n, LWS_WRITE_HTTP);\n\t\tif (m !\u003d n)\n\t\t\treturn 1;\n\t}\n\n\treturn m !\u003d n;\n}\n\nint\nlws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,\n\t\t unsigned char **p, unsigned char *end)\n{\n\tunsigned char *start \u003d *p;\n\n\tif (lws_add_http_header_status(wsi, (unsigned int)code, p, end))\n\t\treturn -1;\n\n\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, loc, len,\n\t\t\t\t\t p, end))\n\t\treturn -1;\n\t/*\n\t * if we're going with http/1.1 and keepalive, we have to give fake\n\t * content metadata so the client knows we completed the transaction and\n\t * it can do the redirect...\n\t */\n\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,\n\t\t\t\t\t (unsigned char *)\u0022text/html\u0022, 9, p,\n\t\t\t\t\t end))\n\t\treturn -1;\n\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,\n\t\t\t\t\t (unsigned char *)\u00220\u0022, 1, p, end))\n\t\treturn -1;\n\n\tif (lws_finalize_http_header(wsi, p, end))\n\t\treturn -1;\n\n\treturn lws_write(wsi, start, lws_ptr_diff_size_t(*p, start),\n\t\t\t LWS_WRITE_HTTP_HEADERS | LWS_WRITE_H2_STREAM_END);\n}\n#endif\n\n#if !defined(LWS_WITH_HTTP_STREAM_COMPRESSION)\nint\nlws_http_compression_apply(struct lws *wsi, const char *name,\n\t\t\t unsigned char **p, unsigned char *end, char decomp)\n{\n\t(void)wsi;\n\t(void)name;\n\t(void)p;\n\t(void)end;\n\t(void)decomp;\n\n\treturn 0;\n}\n#endif\n\nint\nlws_http_headers_detach(struct lws *wsi)\n{\n\treturn lws_header_table_detach(wsi, 0);\n}\n\n#if defined(LWS_WITH_SERVER)\n\nvoid\nlws_sul_http_ah_lifecheck(lws_sorted_usec_list_t *sul)\n{\n\tstruct allocated_headers *ah;\n\tstruct lws_context_per_thread *pt \u003d lws_container_of(sul,\n\t\t\tstruct lws_context_per_thread, sul_ah_lifecheck);\n\tstruct lws *wsi;\n\ttime_t now;\n\tint m;\n\n\tnow \u003d time(NULL);\n\n\tlws_pt_lock(pt, __func__);\n\n\tah \u003d pt-\u003ehttp.ah_list;\n\twhile (ah) {\n\t\tint len;\n\t\tchar buf[256];\n\t\tconst unsigned char *c;\n\n\t\tif (!ah-\u003ein_use || !ah-\u003ewsi || !ah-\u003eassigned ||\n\t\t (ah-\u003ewsi-\u003ea.vhost \u0026\u0026\n\t\t (now - ah-\u003eassigned) \u003c\n\t\t ah-\u003ewsi-\u003ea.vhost-\u003etimeout_secs_ah_idle + 360)) {\n\t\t\tah \u003d ah-\u003enext;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t * a single ah session somehow got held for\n\t\t * an unreasonable amount of time.\n\t\t *\n\t\t * Dump info on the connection...\n\t\t */\n\t\twsi \u003d ah-\u003ewsi;\n\t\tbuf[0] \u003d '\u005c0';\n#if !defined(LWS_PLAT_OPTEE)\n\t\tlws_get_peer_simple(wsi, buf, sizeof(buf));\n#else\n\t\tbuf[0] \u003d '\u005c0';\n#endif\n\t\tlwsl_notice(\u0022%s: ah excessive hold: wsi %p\u005cn\u0022\n\t\t\t \u0022 peer address: %s\u005cn\u0022\n\t\t\t \u0022 ah pos %lu\u005cn\u0022, __func__, lws_wsi_tag(wsi),\n\t\t\t buf, (unsigned long)ah-\u003epos);\n\t\tbuf[0] \u003d '\u005c0';\n\t\tm \u003d 0;\n\t\tdo {\n\t\t\tc \u003d lws_token_to_string((enum lws_token_indexes)m);\n\t\t\tif (!c)\n\t\t\t\tbreak;\n\t\t\tif (!(*c))\n\t\t\t\tbreak;\n\n\t\t\tlen \u003d lws_hdr_total_length(wsi, (enum lws_token_indexes)m);\n\t\t\tif (!len || len \u003e (int)sizeof(buf) - 1) {\n\t\t\t\tm++;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (lws_hdr_copy(wsi, buf, sizeof buf, (enum lws_token_indexes)m) \u003e 0) {\n\t\t\t\tbuf[sizeof(buf) - 1] \u003d '\u005c0';\n\n\t\t\t\tlwsl_notice(\u0022 %s \u003d %s\u005cn\u0022,\n\t\t\t\t\t (const char *)c, buf);\n\t\t\t}\n\t\t\tm++;\n\t\t} while (1);\n\n\t\t/* explicitly detach the ah */\n\t\tlws_header_table_detach(wsi, 0);\n\n\t\t/* ... and then drop the connection */\n\n\t\t__lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,\n\t\t\t\t\t \u0022excessive ah\u0022);\n\n\t\tah \u003d pt-\u003ehttp.ah_list;\n\t}\n\n\tlws_pt_unlock(pt);\n}\n#endif\n","s":{"c":1730921594,"u": 1769}}
],"g": 8027,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}