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":1600564822, "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":"bda11b6998652a4aaf9c2f4811311ece", "oid":{ "oid": "33a1e905113f05c3c1eec3b75e0727ca81a551b1", "alias": [ "refs/heads/v2.4-stable"]},"blobname": "test-apps/test-server-http.c", "blob": "/*\n * libwebsockets-test-server - libwebsockets test implementation\n *\n * Copyright (C) 2010-2016 Andy Green \u003candy@warmcat.com\u003e\n *\n * This file is made available under the Creative Commons CC0 1.0\n * Universal Public Domain Dedication.\n *\n * The person who associated a work with this deed has dedicated\n * the work to the public domain by waiving all of his or her rights\n * to the work worldwide under copyright law, including all related\n * and neighboring rights, to the extent allowed by law. You can copy,\n * modify, distribute and perform the work, even for commercial purposes,\n * all without asking permission.\n *\n * The test apps are intended to be adapted for use in your code, which\n * may be proprietary. So unlike the library itself, they are licensed\n * Public Domain.\n */\n#include \u0022test-server.h\u0022\n\n/*\n * This demo server shows how to use libwebsockets for one or more\n * websocket protocols in the same server\n *\n * It defines the following websocket protocols:\n *\n * dumb-increment-protocol: once the socket is opened, an incrementing\n *\t\t\t\tascii string is sent down it every 50ms.\n *\t\t\t\tIf you send \u0022reset\u005cn\u0022 on the websocket, then\n *\t\t\t\tthe incrementing number is reset to 0.\n *\n * lws-mirror-protocol: copies any received packet to every connection also\n *\t\t\t\tusing this protocol, including the sender\n */\n\n#if defined(LWS_OPENSSL_SUPPORT) \u0026\u0026 defined(LWS_HAVE_SSL_CTX_set1_param)\n/* location of the certificate revocation list */\nextern char crl_path[1024];\n#endif\n\nextern int debug_level;\n\nenum demo_protocols {\n\t/* always first */\n\tPROTOCOL_HTTP \u003d 0,\n\n\tPROTOCOL_DUMB_INCREMENT,\n\tPROTOCOL_LWS_MIRROR,\n\n\t/* always last */\n\tDEMO_PROTOCOL_COUNT\n};\n\n/*\n * We take a strict whitelist approach to stop ../ attacks\n */\nstruct serveable {\n\tconst char *urlpath;\n\tconst char *mimetype;\n};\n\n/*\n * this is just an example of parsing handshake headers, you don't need this\n * in your code unless you will filter allowing connections by the header\n * content\n */\nvoid\ndump_handshake_info(struct lws *wsi)\n{\n\tint n \u003d 0, len;\n\tchar buf[256];\n\tconst unsigned char *c;\n\n\tdo {\n\t\tc \u003d lws_token_to_string(n);\n\t\tif (!c) {\n\t\t\tn++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlen \u003d lws_hdr_total_length(wsi, n);\n\t\tif (!len || len \u003e sizeof(buf) - 1) {\n\t\t\tn++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlws_hdr_copy(wsi, buf, sizeof buf, n);\n\t\tbuf[sizeof(buf) - 1] \u003d '\u005c0';\n\n\t\tfprintf(stderr, \u0022 %s \u003d %s\u005cn\u0022, (char *)c, buf);\n\t\tn++;\n\t} while (c);\n}\n\nconst char * get_mimetype(const char *file)\n{\n\tint n \u003d strlen(file);\n\n\tif (n \u003c 5)\n\t\treturn NULL;\n\n\tif (!strcmp(\u0026file[n - 4], \u0022.ico\u0022))\n\t\treturn \u0022image/x-icon\u0022;\n\n\tif (!strcmp(\u0026file[n - 4], \u0022.png\u0022))\n\t\treturn \u0022image/png\u0022;\n\n\tif (!strcmp(\u0026file[n - 5], \u0022.html\u0022))\n\t\treturn \u0022text/html\u0022;\n\n\tif (!strcmp(\u0026file[n - 4], \u0022.css\u0022))\n\t\treturn \u0022text/css\u0022;\n\n\tif (!strcmp(\u0026file[n - 3], \u0022.js\u0022))\n\t\treturn \u0022text/javascript\u0022;\n\n\treturn NULL;\n}\n\n\nstatic const char * const param_names[] \u003d {\n\t\u0022text\u0022,\n\t\u0022send\u0022,\n\t\u0022file\u0022,\n\t\u0022upload\u0022,\n};\n\nenum enum_param_names {\n\tEPN_TEXT,\n\tEPN_SEND,\n\tEPN_FILE,\n\tEPN_UPLOAD,\n};\n\nstatic int\nfile_upload_cb(void *data, const char *name, const char *filename,\n\t char *buf, int len, enum lws_spa_fileupload_states state)\n{\n\tstruct per_session_data__http *pss \u003d\n\t\t\t(struct per_session_data__http *)data;\n\tint n;\n\n\t(void)n;\n\n\tswitch (state) {\n\tcase LWS_UFS_OPEN:\n\t\tstrncpy(pss-\u003efilename, filename, sizeof(pss-\u003efilename) - 1);\n\t\t/* we get the original filename in @filename arg, but for\n\t\t * simple demo use a fixed name so we don't have to deal with\n\t\t * attacks */\n\t\tpss-\u003epost_fd \u003d (lws_filefd_type)open(\u0022/tmp/post-file\u0022,\n\t\t\t O_CREAT | O_TRUNC | O_RDWR, 0600);\n\t\tbreak;\n\tcase LWS_UFS_FINAL_CONTENT:\n\tcase LWS_UFS_CONTENT:\n\t\tif (len) {\n\t\t\tpss-\u003efile_length +\u003d len;\n\n\t\t\t/* if the file length is too big, drop it */\n\t\t\tif (pss-\u003efile_length \u003e 100000)\n\t\t\t\treturn 1;\n\n\t\t\tn \u003d write((int)pss-\u003epost_fd, buf, len);\n\t\t\tlwsl_notice(\u0022%s: write %d says %d\u005cn\u0022, __func__, len, n);\n\t\t}\n\t\tif (state \u003d\u003d LWS_UFS_CONTENT)\n\t\t\tbreak;\n\t\tclose((int)pss-\u003epost_fd);\n\t\tpss-\u003epost_fd \u003d LWS_INVALID_FILE;\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\n/* this protocol server (always the first one) handles HTTP,\n *\n * Some misc callbacks that aren't associated with a protocol also turn up only\n * here on the first protocol server.\n */\n\nint callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,\n\t\t void *in, size_t len)\n{\n\tstruct per_session_data__http *pss \u003d\n\t\t\t(struct per_session_data__http *)user;\n\tunsigned char buffer[4096 + LWS_PRE];\n lws_filepos_t amount, file_len, sent;\n\tchar leaf_path[1024];\n\tconst char *mimetype;\n\tchar *other_headers;\n\tunsigned char *end, *start;\n\tstruct timeval tv;\n\tunsigned char *p;\n#ifndef LWS_NO_CLIENT\n\tstruct per_session_data__http *pss1;\n\tstruct lws *wsi1;\n#endif\n\tchar buf[256];\n\tchar b64[64];\n\tint n, m;\n#ifdef EXTERNAL_POLL\n\tstruct lws_pollargs *pa \u003d (struct lws_pollargs *)in;\n#endif\n\n\n\tswitch (reason) {\n\tcase LWS_CALLBACK_HTTP:\n\n\t\tlwsl_info(\u0022lws_http_serve: %s\u005cn\u0022, (const char *)in);\n\n\t\tif (debug_level \u0026 LLL_INFO) {\n\t\t\tdump_handshake_info(wsi);\n\n\t\t\t/* dump the individual URI Arg parameters */\n\t\t\tn \u003d 0;\n\t\t\twhile (lws_hdr_copy_fragment(wsi, buf, sizeof(buf),\n\t\t\t\t\t\t WSI_TOKEN_HTTP_URI_ARGS, n) \u003e 0) {\n\t\t\t\tlwsl_notice(\u0022URI Arg %d: %s\u005cn\u0022, ++n, buf);\n\t\t\t}\n\t\t}\n\n\t\tif (lws_get_peer_simple(wsi, buf, sizeof(buf)))\n\t\t\tlwsl_info(\u0022HTTP connect from %s\u005cn\u0022, buf);\n\n\t\tif (len \u003c 1) {\n\t\t\tlws_return_http_status(wsi,\n\t\t\t\t\t\tHTTP_STATUS_BAD_REQUEST, NULL);\n\t\t\tgoto try_to_reuse;\n\t\t}\n\n#if !defined(LWS_NO_CLIENT) \u0026\u0026 defined(LWS_OPENSSL_SUPPORT)\n\t\tif (!strncmp(in, \u0022/proxytest\u0022, 10)) {\n\t\t\tstruct lws_client_connect_info i;\n\t\t\tchar *rootpath \u003d \u0022/git/\u0022;\n\t\t\tconst char *p \u003d (const char *)in;\n\n\t\t\tif (lws_get_child(wsi))\n\t\t\t\tbreak;\n\n\t\t\tpss-\u003eclient_finished \u003d 0;\n\t\t\tmemset(\u0026i, 0, sizeof(i));\n\t\t\ti.context \u003d lws_get_context(wsi);\n\t\t\ti.address \u003d \u0022libwebsockets.org\u0022;\n\t\t\ti.port \u003d 443;\n\t\t\ti.ssl_connection \u003d 1;\n\t\t\tif (p[10])\n\t\t\t\ti.path \u003d (char *)in + 10;\n\t\t\telse\n\t\t\t\ti.path \u003d rootpath;\n\t\t\ti.host \u003d i.address;\n\t\t\ti.origin \u003d NULL;\n\t\t\ti.method \u003d \u0022GET\u0022;\n\t\t\ti.parent_wsi \u003d wsi;\n\t\t\ti.uri_replace_from \u003d \u0022libwebsockets.org/git/\u0022;\n\t\t\ti.uri_replace_to \u003d \u0022/proxytest/\u0022;\n\n\t\t\tif (!lws_client_connect_via_info(\u0026i)) {\n\t\t\t\tlwsl_err(\u0022proxy connect fail\u005cn\u0022);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n#endif\n\n#if 1\n\t\t/* this example server has no concept of directories */\n\t\tif (strchr((const char *)in + 1, '/')) {\n\t\t\tlws_return_http_status(wsi, HTTP_STATUS_NOT_ACCEPTABLE, NULL);\n\t\t\tgoto try_to_reuse;\n\t\t}\n#endif\n\n\t\t/* if a legal POST URL, let it continue and accept data */\n\t\tif (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {\n\t\t\tn \u003d lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_POST_URI);\n\t\t\tif (n \u003c 0)\n\t\t\t\treturn -1;\n\t\t\tif (strcmp(buf, \u0022/formtest\u0022)) {\n\t\t\t\tlws_return_http_status(wsi, HTTP_STATUS_NOT_ACCEPTABLE, NULL);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* check for the \u0022send a big file by hand\u0022 example case */\n\n\t\tif (!strcmp((const char *)in, \u0022/leaf.jpg\u0022)) {\n\t\t\tlws_fop_flags_t flags \u003d LWS_O_RDONLY;\n\n\t\t\tif (strlen(resource_path) \u003e sizeof(leaf_path) - 10)\n\t\t\t\treturn -1;\n\t\t\tsprintf(leaf_path, \u0022%s/leaf.jpg\u0022, resource_path);\n\n\t\t\t/* well, let's demonstrate how to send the hard way */\n\n\t\t\tp \u003d buffer + LWS_PRE;\n\t\t\tend \u003d p + sizeof(buffer) - LWS_PRE;\n\n\t\t\tpss-\u003efop_fd \u003d lws_vfs_file_open(\n\t\t\t\t\tlws_get_fops(lws_get_context(wsi)),\n\t\t\t\t\tleaf_path, \u0026flags);\n\t\t\tif (!pss-\u003efop_fd) {\n\t\t\t\tlwsl_err(\u0022failed to open file %s\u005cn\u0022, leaf_path);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tfile_len \u003d lws_vfs_get_length(pss-\u003efop_fd);\n\n\t\t\t/*\n\t\t\t * we will send a big jpeg file, but it could be\n\t\t\t * anything. Set the Content-Type: appropriately\n\t\t\t * so the browser knows what to do with it.\n\t\t\t *\n\t\t\t * Notice we use the APIs to build the header, which\n\t\t\t * will do the right thing for HTTP 1/1.1 and HTTP2\n\t\t\t * depending on what connection it happens to be working\n\t\t\t * on\n\t\t\t */\n\t\t\tif (lws_add_http_header_status(wsi, HTTP_STATUS_OK, \u0026p, end))\n\t\t\t\treturn 1;\n\t\t\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,\n\t\t\t\t \t(unsigned char *)\u0022libwebsockets\u0022,\n\t\t\t\t\t13, \u0026p, end))\n\t\t\t\treturn 1;\n\t\t\tif (lws_add_http_header_by_token(wsi,\n\t\t\t\t\tWSI_TOKEN_HTTP_CONTENT_TYPE,\n\t\t\t\t \t(unsigned char *)\u0022image/jpeg\u0022,\n\t\t\t\t\t10, \u0026p, end))\n\t\t\t\treturn 1;\n\t\t\tif (lws_add_http_header_content_length(wsi,\n\t\t\t\t\t\t\t file_len, \u0026p,\n\t\t\t\t\t\t\t end))\n\t\t\t\treturn 1;\n\t\t\tif (lws_finalize_http_header(wsi, \u0026p, end))\n\t\t\t\treturn 1;\n\n\t\t\t/*\n\t\t\t * send the http headers...\n\t\t\t * this won't block since it's the first payload sent\n\t\t\t * on the connection since it was established\n\t\t\t * (too small for partial)\n\t\t\t *\n\t\t\t * Notice they are sent using LWS_WRITE_HTTP_HEADERS\n\t\t\t * which also means you can't send body too in one step,\n\t\t\t * this is mandated by changes in HTTP2\n\t\t\t */\n\n\t\t\t*p \u003d '\u005c0';\n\t\t\tlwsl_info(\u0022%s\u005cn\u0022, buffer + LWS_PRE);\n\n\t\t\tn \u003d lws_write(wsi, buffer + LWS_PRE,\n\t\t\t\t p - (buffer + LWS_PRE),\n\t\t\t\t LWS_WRITE_HTTP_HEADERS);\n\t\t\tif (n \u003c 0) {\n\t\t\t\tlws_vfs_file_close(\u0026pss-\u003efop_fd);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\t/*\n\t\t\t * book us a LWS_CALLBACK_HTTP_WRITEABLE callback\n\t\t\t */\n\t\t\tlws_callback_on_writable(wsi);\n\t\t\tbreak;\n\t\t}\n\n\t\t/* if not, send a file the easy way */\n\t\tif (!strncmp(in, \u0022/cgit-data/\u0022, 11)) {\n\t\t\tin \u003d (char *)in + 11;\n\t\t\tstrcpy(buf, \u0022/usr/share/cgit\u0022);\n\t\t} else\n\t\t\tstrcpy(buf, resource_path);\n\n\t\tif (strcmp(in, \u0022/\u0022)) {\n\t\t\tif (*((const char *)in) !\u003d '/')\n\t\t\t\tstrcat(buf, \u0022/\u0022);\n\t\t\tstrncat(buf, in, sizeof(buf) - strlen(buf) - 1);\n\t\t} else /* default file to serve */\n\t\t\tstrcat(buf, \u0022/test.html\u0022);\n\t\tbuf[sizeof(buf) - 1] \u003d '\u005c0';\n\n\t\t/* refuse to serve files we don't understand */\n\t\tmimetype \u003d get_mimetype(buf);\n\t\tif (!mimetype) {\n\t\t\tlwsl_err(\u0022Unknown mimetype for %s\u005cn\u0022, buf);\n\t\t\tlws_return_http_status(wsi,\n\t\t\t\t HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, \u0022Unknown Mimetype\u0022);\n\t\t\treturn -1;\n\t\t}\n\n\t\t/* demonstrates how to set a cookie on / */\n\n\t\tother_headers \u003d leaf_path;\n\t\tp \u003d (unsigned char *)leaf_path;\n\t\tif (!strcmp((const char *)in, \u0022/\u0022) \u0026\u0026\n\t\t\t !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {\n\t\t\t/* this isn't very unguessable but it'll do for us */\n\t\t\tgettimeofday(\u0026tv, NULL);\n\t\t\tn \u003d sprintf(b64, \u0022test\u003dLWS_%u_%u_COOKIE;Max-Age\u003d360000\u0022,\n\t\t\t\t(unsigned int)tv.tv_sec,\n\t\t\t\t(unsigned int)tv.tv_usec);\n\n\t\t\tif (lws_add_http_header_by_name(wsi,\n\t\t\t\t(unsigned char *)\u0022set-cookie:\u0022,\n\t\t\t\t(unsigned char *)b64, n, \u0026p,\n\t\t\t\t(unsigned char *)leaf_path + sizeof(leaf_path)))\n\t\t\t\treturn 1;\n\t\t}\n#if !defined(LWS_WITH_HTTP2)\n\t\tif (lws_is_ssl(wsi) \u0026\u0026 lws_add_http_header_by_name(wsi,\n\t\t\t\t\t\t(unsigned char *)\n\t\t\t\t\t\t\u0022Strict-Transport-Security:\u0022,\n\t\t\t\t\t\t(unsigned char *)\n\t\t\t\t\t\t\u0022max-age\u003d15768000 ; \u0022\n\t\t\t\t\t\t\u0022includeSubDomains\u0022, 36, \u0026p,\n\t\t\t\t\t\t(unsigned char *)leaf_path +\n\t\t\t\t\t\t\tsizeof(leaf_path)))\n\t\t\treturn 1;\n#endif\n\t\tn \u003d (char *)p - leaf_path;\n\n\t\tn \u003d lws_serve_http_file(wsi, buf, mimetype, other_headers, n);\n\t\tif (n \u003c 0)\n\t\t\treturn -1; /* error*/\n\n\t\t/*\n\t\t * notice that the sending of the file completes asynchronously,\n\t\t * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when\n\t\t * it's done. That's the case even if we just completed the\n\t\t * send, so wait for that.\n\t\t */\n\t\tbreak;\n\n case LWS_CALLBACK_CLIENT_RECEIVE:\n ((char *)in)[len] \u003d '\u005c0';\n lwsl_info(\u0022rx %d '%s'\u005cn\u0022, (int)len, (char *)in);\n break;\n\n\tcase LWS_CALLBACK_HTTP_BODY:\n\t\t/* create the POST argument parser if not already existing */\n\t\tif (!pss-\u003espa) {\n\t\t\tpss-\u003espa \u003d lws_spa_create(wsi, param_names,\n\t\t\t\t\tARRAY_SIZE(param_names), 1024,\n\t\t\t\t\tfile_upload_cb, pss);\n\t\t\tif (!pss-\u003espa)\n\t\t\t\treturn -1;\n\n\t\t\tpss-\u003efilename[0] \u003d '\u005c0';\n\t\t\tpss-\u003efile_length \u003d 0;\n\t\t}\n\n\t\t/* let it parse the POST data */\n\t\tif (lws_spa_process(pss-\u003espa, in, len))\n\t\t\treturn -1;\n\t\tbreak;\n\n\tcase LWS_CALLBACK_HTTP_BODY_COMPLETION:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_HTTP_BODY_COMPLETION\u005cn\u0022);\n\t\t/*\n\t\t * the whole of the sent body arrived,\n\t\t * respond to the client with a redirect to show the\n\t\t * results\n\t\t */\n\n\t\t/* call to inform no more payload data coming */\n\t\tlws_spa_finalize(pss-\u003espa);\n\n\t\tp \u003d (unsigned char *)pss-\u003eresult + LWS_PRE;\n\t\tend \u003d p + sizeof(pss-\u003eresult) - LWS_PRE - 1;\n\t\tp +\u003d sprintf((char *)p,\n\t\t\t\u0022\u003chtml\u003e\u003cbody\u003e\u003ch1\u003eForm results (after urldecoding)\u003c/h1\u003e\u0022\n\t\t\t\u0022\u003ctable\u003e\u003ctr\u003e\u003ctd\u003eName\u003c/td\u003e\u003ctd\u003eLength\u003c/td\u003e\u003ctd\u003eValue\u003c/td\u003e\u003c/tr\u003e\u0022);\n\n\t\tfor (n \u003d 0; n \u003c ARRAY_SIZE(param_names); n++)\n\t\t\tp +\u003d lws_snprintf((char *)p, end - p,\n\t\t\t\t \u0022\u003ctr\u003e\u003ctd\u003e\u003cb\u003e%s\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e%d\u003c/td\u003e\u003ctd\u003e%s\u003c/td\u003e\u003c/tr\u003e\u0022,\n\t\t\t\t param_names[n],\n\t\t\t\t lws_spa_get_length(pss-\u003espa, n),\n\t\t\t\t lws_spa_get_string(pss-\u003espa, n));\n\n\t\tp +\u003d lws_snprintf((char *)p, end - p, \u0022\u003c/table\u003e\u003cbr\u003e\u003cb\u003efilename:\u003c/b\u003e %s, \u003cb\u003elength\u003c/b\u003e %ld\u0022,\n\t\t\t\tpss-\u003efilename, pss-\u003efile_length);\n\n\t\tp +\u003d lws_snprintf((char *)p, end - p, \u0022\u003c/body\u003e\u003c/html\u003e\u0022);\n\t\tpss-\u003eresult_len \u003d p - (unsigned char *)(pss-\u003eresult + LWS_PRE);\n\n\t\tp \u003d buffer + LWS_PRE;\n\t\tstart \u003d p;\n\t\tend \u003d p + sizeof(buffer) - LWS_PRE;\n\n\t\tif (lws_add_http_header_status(wsi, HTTP_STATUS_OK, \u0026p, end))\n\t\t\treturn 1;\n\n\t\tif (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,\n\t\t\t\t(unsigned char *)\u0022text/html\u0022, 9, \u0026p, end))\n\t\t\treturn 1;\n\t\tif (lws_add_http_header_content_length(wsi, pss-\u003eresult_len, \u0026p, end))\n\t\t\treturn 1;\n\t\tif (lws_finalize_http_header(wsi, \u0026p, end))\n\t\t\treturn 1;\n\n\t\tn \u003d lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);\n\t\tif (n \u003c 0)\n\t\t\treturn 1;\n\n\t\tn \u003d lws_write(wsi, (unsigned char *)pss-\u003eresult + LWS_PRE,\n\t\t\t pss-\u003eresult_len, LWS_WRITE_HTTP);\n\t\tif (n \u003c 0)\n\t\t\treturn 1;\n\t\tgoto try_to_reuse;\n\tcase LWS_CALLBACK_HTTP_DROP_PROTOCOL:\n\t\tlwsl_debug(\u0022LWS_CALLBACK_HTTP_DROP_PROTOCOL\u005cn\u0022);\n\n\t\t/* called when our wsi user_space is going to be destroyed */\n\t\tif (pss-\u003espa) {\n\t\t\tlws_spa_destroy(pss-\u003espa);\n\t\t\tpss-\u003espa \u003d NULL;\n\t\t}\n\t\tbreak;\n\tcase LWS_CALLBACK_HTTP_FILE_COMPLETION:\n\t\tgoto try_to_reuse;\n\n\tcase LWS_CALLBACK_HTTP_WRITEABLE:\n\t\tlwsl_info(\u0022LWS_CALLBACK_HTTP_WRITEABLE: %p\u005cn\u0022, wsi);\n\n\t\tif (pss-\u003eclient_finished)\n\t\t\treturn -1;\n\n\t\tif (!lws_get_child(wsi) \u0026\u0026 !pss-\u003efop_fd)\n\t\t\tgoto try_to_reuse;\n\n#ifndef LWS_NO_CLIENT\n\t\tif (pss-\u003ereason_bf \u0026 LWS_CB_REASON_AUX_BF__PROXY) {\n\t\t\tchar *px \u003d buf + LWS_PRE;\n\t\t\tint lenx \u003d sizeof(buf) - LWS_PRE;\n\t\t\t/*\n\t\t\t * our sink is writeable and our source has something\n\t\t\t * to read. So read a lump of source material of\n\t\t\t * suitable size to send or what's available, whichever\n\t\t\t * is the smaller.\n\t\t\t */\n\n\n\t\t\tpss-\u003ereason_bf \u0026\u003d ~LWS_CB_REASON_AUX_BF__PROXY;\n\t\t\twsi1 \u003d lws_get_child(wsi);\n\t\t\tif (!wsi1)\n\t\t\t\tbreak;\n\t\t\tif (lws_http_client_read(wsi1, \u0026px, \u0026lenx) \u003c 0)\n\t\t\t\treturn -1;\n\n\t\t\tif (pss-\u003eclient_finished)\n\t\t\t\treturn -1;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tif (lws_get_child(wsi))\n\t\t\tbreak;\n\n#endif\n\t\t/*\n\t\t * we can send more of whatever it is we were sending\n\t\t */\n\t\tsent \u003d 0;\n\t\tdo {\n\t\t\t/* we'd like the send this much */\n\t\t\tn \u003d sizeof(buffer) - LWS_PRE;\n\n\t\t\t/* but if the peer told us he wants less, we can adapt */\n\t\t\tm \u003d lws_get_peer_write_allowance(wsi);\n\n\t\t\t/* -1 means not using a protocol that has this info */\n\t\t\tif (m \u003d\u003d 0)\n\t\t\t\t/* right now, peer can't handle anything */\n\t\t\t\tgoto later;\n\n\t\t\tif (m !\u003d -1 \u0026\u0026 m \u003c n)\n\t\t\t\t/* he couldn't handle that much */\n\t\t\t\tn \u003d m;\n\n\t\t\tn \u003d lws_vfs_file_read(pss-\u003efop_fd,\n\t\t\t\t\t \u0026amount, buffer + LWS_PRE, n);\n\t\t\t/* problem reading, close conn */\n\t\t\tif (n \u003c 0) {\n\t\t\t\tlwsl_err(\u0022problem reading file\u005cn\u0022);\n\t\t\t\tgoto bail;\n\t\t\t}\n\t\t\tn \u003d (int)amount;\n\t\t\t/* sent it all, close conn */\n\t\t\tif (n \u003d\u003d 0)\n\t\t\t\tgoto penultimate;\n\t\t\t/*\n\t\t\t * To support HTTP2, must take care about preamble space\n\t\t\t *\n\t\t\t * identification of when we send the last payload frame\n\t\t\t * is handled by the library itself if you sent a\n\t\t\t * content-length header\n\t\t\t */\n\t\t\tm \u003d lws_write(wsi, buffer + LWS_PRE, n, LWS_WRITE_HTTP);\n\t\t\tif (m \u003c 0) {\n\t\t\t\tlwsl_err(\u0022write failed\u005cn\u0022);\n\t\t\t\t/* write failed, close conn */\n\t\t\t\tgoto bail;\n\t\t\t}\n\t\t\tif (m) /* while still active, extend timeout */\n\t\t\t\tlws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, 5);\n\t\t\tsent +\u003d m;\n\n\t\t} while (!lws_send_pipe_choked(wsi) \u0026\u0026 (sent \u003c 1024 * 1024));\nlater:\n\t\tlws_callback_on_writable(wsi);\n\t\tbreak;\npenultimate:\n\t\tlws_vfs_file_close(\u0026pss-\u003efop_fd);\n\t\tpss-\u003efop_fd \u003d NULL;\n\t\tgoto try_to_reuse;\n\nbail:\n\t\tlws_vfs_file_close(\u0026pss-\u003efop_fd);\n\n\t\treturn -1;\n\n\t/*\n\t * callback for confirming to continue with client IP appear in\n\t * protocol 0 callback since no websocket protocol has been agreed\n\t * yet. You can just ignore this if you won't filter on client IP\n\t * since the default unhandled callback return is 0 meaning let the\n\t * connection continue.\n\t */\n\tcase LWS_CALLBACK_FILTER_NETWORK_CONNECTION:\n\t\t/* if we returned non-zero from here, we kill the connection */\n\t\tbreak;\n\n#ifndef LWS_NO_CLIENT\n\tcase LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: {\n\t\tchar ctype[64], ctlen \u003d 0;\n\t\tlwsl_err(\u0022LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP\u005cn\u0022);\n\t\tp \u003d buffer + LWS_PRE;\n\t\tend \u003d p + sizeof(buffer) - LWS_PRE;\n\t\tif (lws_add_http_header_status(lws_get_parent(wsi), HTTP_STATUS_OK, \u0026p, end))\n\t\t\treturn 1;\n\t\tif (lws_add_http_header_by_token(lws_get_parent(wsi),\n\t\t\t\tWSI_TOKEN_HTTP_SERVER,\n\t\t\t \t(unsigned char *)\u0022libwebsockets\u0022,\n\t\t\t\t13, \u0026p, end))\n\t\t\treturn 1;\n\n\t\tctlen \u003d lws_hdr_copy(wsi, ctype, sizeof(ctype), WSI_TOKEN_HTTP_CONTENT_TYPE);\n\t\tif (ctlen \u003e 0) {\n\t\t\tif (lws_add_http_header_by_token(lws_get_parent(wsi),\n\t\t\t\tWSI_TOKEN_HTTP_CONTENT_TYPE,\n\t\t\t\t(unsigned char *)ctype, ctlen, \u0026p, end))\n\t\t\t\treturn 1;\n\t\t}\n#if 0\n\t\tif (lws_add_http_header_content_length(lws_get_parent(wsi),\n\t\t\t\t\t\t file_len, \u0026p, end))\n\t\t\treturn 1;\n#endif\n\t\tif (lws_finalize_http_header(lws_get_parent(wsi), \u0026p, end))\n\t\t\treturn 1;\n\n\t\t*p \u003d '\u005c0';\n\t\tlwsl_info(\u0022%s\u005cn\u0022, buffer + LWS_PRE);\n\n\t\tn \u003d lws_write(lws_get_parent(wsi), buffer + LWS_PRE,\n\t\t\t p - (buffer + LWS_PRE),\n\t\t\t LWS_WRITE_HTTP_HEADERS);\n\t\tif (n \u003c 0)\n\t\t\treturn -1;\n\n\t\tbreak; }\n\tcase LWS_CALLBACK_CLOSED_CLIENT_HTTP:\n\t\t//lwsl_err(\u0022LWS_CALLBACK_CLOSED_CLIENT_HTTP\u005cn\u0022);\n\t\treturn -1;\n\t\tbreak;\n\tcase LWS_CALLBACK_RECEIVE_CLIENT_HTTP:\n\t\t//lwsl_err(\u0022LWS_CALLBACK_RECEIVE_CLIENT_HTTP: wsi %p\u005cn\u0022, wsi);\n\t\tassert(lws_get_parent(wsi));\n\t\tif (!lws_get_parent(wsi))\n\t\t\tbreak;\n\t\tpss1 \u003d lws_wsi_user(lws_get_parent(wsi));\n\t\tpss1-\u003ereason_bf |\u003d LWS_CB_REASON_AUX_BF__PROXY;\n\t\tlws_callback_on_writable(lws_get_parent(wsi));\n\t\tbreak;\n\tcase LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:\n\t\t//lwsl_err(\u0022LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ len %d\u005cn\u0022, (int)len);\n\t\tassert(lws_get_parent(wsi));\n\t\tm \u003d lws_write(lws_get_parent(wsi), (unsigned char *)in,\n\t\t\t\tlen, LWS_WRITE_HTTP);\n\t\tif (m \u003c 0)\n\t\t\treturn -1;\n\t\tbreak;\n\tcase LWS_CALLBACK_COMPLETED_CLIENT_HTTP:\n\t\t//lwsl_err(\u0022LWS_CALLBACK_COMPLETED_CLIENT_HTTP\u005cn\u0022);\n\t\tassert(lws_get_parent(wsi));\n\t\tif (!lws_get_parent(wsi))\n\t\t\tbreak;\n\t\tpss1 \u003d lws_wsi_user(lws_get_parent(wsi));\n\t\tpss1-\u003eclient_finished \u003d 1;\n\t\tbreak;\n#endif\n\n\t/*\n\t * callbacks for managing the external poll() array appear in\n\t * protocol 0 callback\n\t */\n\n\tcase LWS_CALLBACK_LOCK_POLL:\n\t\t/*\n\t\t * lock mutex to protect pollfd state\n\t\t * called before any other POLL related callback\n\t\t * if protecting wsi lifecycle change, len \u003d\u003d 1\n\t\t */\n\t\ttest_server_lock(len);\n\t\tbreak;\n\n\tcase LWS_CALLBACK_UNLOCK_POLL:\n\t\t/*\n\t\t * unlock mutex to protect pollfd state when\n\t\t * called after any other POLL related callback\n\t\t * if protecting wsi lifecycle change, len \u003d\u003d 1\n\t\t */\n\t\ttest_server_unlock(len);\n\t\tbreak;\n\n#ifdef EXTERNAL_POLL\n\tcase LWS_CALLBACK_ADD_POLL_FD:\n\n\t\tif (count_pollfds \u003e\u003d max_poll_elements) {\n\t\t\tlwsl_err(\u0022LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\u005cn\u0022);\n\t\t\treturn 1;\n\t\t}\n\n\t\tfd_lookup[pa-\u003efd] \u003d count_pollfds;\n\t\tpollfds[count_pollfds].fd \u003d pa-\u003efd;\n\t\tpollfds[count_pollfds].events \u003d pa-\u003eevents;\n\t\tpollfds[count_pollfds++].revents \u003d 0;\n\t\tbreak;\n\n\tcase LWS_CALLBACK_DEL_POLL_FD:\n\t\tif (!--count_pollfds)\n\t\t\tbreak;\n\t\tm \u003d fd_lookup[pa-\u003efd];\n\t\t/* have the last guy take up the vacant slot */\n\t\tpollfds[m] \u003d pollfds[count_pollfds];\n\t\tfd_lookup[pollfds[count_pollfds].fd] \u003d m;\n\t\tbreak;\n\n\tcase LWS_CALLBACK_CHANGE_MODE_POLL_FD:\n\t pollfds[fd_lookup[pa-\u003efd]].events \u003d pa-\u003eevents;\n\t\tbreak;\n#endif\n\n\tcase LWS_CALLBACK_GET_THREAD_ID:\n\t\t/*\n\t\t * if you will call \u0022lws_callback_on_writable\u0022\n\t\t * from a different thread, return the caller thread ID\n\t\t * here so lws can use this information to work out if it\n\t\t * should signal the poll() loop to exit and restart early\n\t\t */\n\n\t\t/* return pthread_getthreadid_np(); */\n\n\t\tbreak;\n\n#if defined(LWS_OPENSSL_SUPPORT)\n\tcase LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:\n\t\t/* Verify the client certificate */\n\t\tif (!len || (SSL_get_verify_result((SSL*)in) !\u003d X509_V_OK)) {\n\t\t\tint err \u003d X509_STORE_CTX_get_error((X509_STORE_CTX*)user);\n\t\t\tint depth \u003d X509_STORE_CTX_get_error_depth((X509_STORE_CTX*)user);\n\t\t\tconst char* msg \u003d X509_verify_cert_error_string(err);\n\t\t\tlwsl_err(\u0022LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: SSL error: %s (%d), depth: %d\u005cn\u0022, msg, err, depth);\n\t\t\treturn 1;\n\t\t}\n\t\tbreak;\n#if defined(LWS_HAVE_SSL_CTX_set1_param) \u0026\u0026 !defined(LWS_WITH_MBEDTLS)\n\tcase LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:\n\t\tif (crl_path[0]) {\n\t\t\t/* Enable CRL checking */\n\t\t\tX509_VERIFY_PARAM *param \u003d X509_VERIFY_PARAM_new();\n\t\t\tX509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);\n\t\t\tSSL_CTX_set1_param((SSL_CTX*)user, param);\n\t\t\tX509_STORE *store \u003d SSL_CTX_get_cert_store((SSL_CTX*)user);\n\t\t\tX509_LOOKUP *lookup \u003d X509_STORE_add_lookup(store, X509_LOOKUP_file());\n\t\t\tn \u003d X509_load_cert_crl_file(lookup, crl_path, X509_FILETYPE_PEM);\n\t\t\tX509_VERIFY_PARAM_free(param);\n\t\t\tif (n !\u003d 1) {\n\t\t\t\tchar errbuf[256];\n\t\t\t\tn \u003d ERR_get_error();\n\t\t\t\tlwsl_err(\u0022LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: SSL error: %s (%d)\u005cn\u0022, ERR_error_string(n, errbuf), n);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\tbreak;\n#endif\n#endif\n\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn 0;\n\n\t/* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */\ntry_to_reuse:\n\tif (lws_http_transaction_completed(wsi))\n\t\treturn -1;\n\n\treturn 0;\n}\n","s":{"c":1600564822,"u": 953}} ],"g": 7416,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 1, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}