1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * ws protocol handler plugin for "fulltext demo" 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Written in 2010-2019 by Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0 7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication. 8d4afb5ceSopenharmony_ci * 9d4afb5ceSopenharmony_ci * The person who associated a work with this deed has dedicated 10d4afb5ceSopenharmony_ci * the work to the public domain by waiving all of his or her rights 11d4afb5ceSopenharmony_ci * to the work worldwide under copyright law, including all related 12d4afb5ceSopenharmony_ci * and neighboring rights, to the extent allowed by law. You can copy, 13d4afb5ceSopenharmony_ci * modify, distribute and perform the work, even for commercial purposes, 14d4afb5ceSopenharmony_ci * all without asking permission. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * These test plugins are intended to be adapted for use in your code, which 17d4afb5ceSopenharmony_ci * may be proprietary. So unlike the library itself, they are licensed 18d4afb5ceSopenharmony_ci * Public Domain. 19d4afb5ceSopenharmony_ci */ 20d4afb5ceSopenharmony_ci 21d4afb5ceSopenharmony_ci#if !defined (LWS_PLUGIN_STATIC) 22d4afb5ceSopenharmony_ci#if !defined(LWS_DLL) 23d4afb5ceSopenharmony_ci#define LWS_DLL 24d4afb5ceSopenharmony_ci#endif 25d4afb5ceSopenharmony_ci#if !defined(LWS_INTERNAL) 26d4afb5ceSopenharmony_ci#define LWS_INTERNAL 27d4afb5ceSopenharmony_ci#endif 28d4afb5ceSopenharmony_ci#include <libwebsockets.h> 29d4afb5ceSopenharmony_ci#endif 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci#include <stdlib.h> 32d4afb5ceSopenharmony_ci#include <string.h> 33d4afb5ceSopenharmony_ci#include <fcntl.h> 34d4afb5ceSopenharmony_ci#include <sys/types.h> 35d4afb5ceSopenharmony_ci#include <sys/stat.h> 36d4afb5ceSopenharmony_ci#ifdef WIN32 37d4afb5ceSopenharmony_ci#include <io.h> 38d4afb5ceSopenharmony_ci#endif 39d4afb5ceSopenharmony_ci#include <stdio.h> 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_cistruct vhd_fts_demo { 42d4afb5ceSopenharmony_ci const char *indexpath; 43d4afb5ceSopenharmony_ci}; 44d4afb5ceSopenharmony_ci 45d4afb5ceSopenharmony_cistruct pss_fts_demo { 46d4afb5ceSopenharmony_ci struct lwsac *result; 47d4afb5ceSopenharmony_ci struct lws_fts_result_autocomplete *ac; 48d4afb5ceSopenharmony_ci struct lws_fts_result_filepath *fp; 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_ci uint32_t *li; 51d4afb5ceSopenharmony_ci int done; 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci uint8_t first:1; 54d4afb5ceSopenharmony_ci uint8_t ac_done:1; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci uint8_t fp_init_done:1; 57d4afb5ceSopenharmony_ci}; 58d4afb5ceSopenharmony_ci 59d4afb5ceSopenharmony_cistatic int 60d4afb5ceSopenharmony_cicallback_fts(struct lws *wsi, enum lws_callback_reasons reason, void *user, 61d4afb5ceSopenharmony_ci void *in, size_t len) 62d4afb5ceSopenharmony_ci{ 63d4afb5ceSopenharmony_ci struct vhd_fts_demo *vhd = (struct vhd_fts_demo *) 64d4afb5ceSopenharmony_ci lws_protocol_vh_priv_get(lws_get_vhost(wsi), 65d4afb5ceSopenharmony_ci lws_get_protocol(wsi)); 66d4afb5ceSopenharmony_ci struct pss_fts_demo *pss = (struct pss_fts_demo *)user; 67d4afb5ceSopenharmony_ci uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, 68d4afb5ceSopenharmony_ci *end = &buf[sizeof(buf) - 1]; 69d4afb5ceSopenharmony_ci struct lws_fts_search_params params; 70d4afb5ceSopenharmony_ci const char *ccp = (const char *)in; 71d4afb5ceSopenharmony_ci struct lws_fts_result *result; 72d4afb5ceSopenharmony_ci struct lws_fts_file *jtf; 73d4afb5ceSopenharmony_ci int n; 74d4afb5ceSopenharmony_ci 75d4afb5ceSopenharmony_ci switch (reason) { 76d4afb5ceSopenharmony_ci 77d4afb5ceSopenharmony_ci case LWS_CALLBACK_PROTOCOL_INIT: 78d4afb5ceSopenharmony_ci vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi), 79d4afb5ceSopenharmony_ci lws_get_protocol(wsi),sizeof(struct vhd_fts_demo)); 80d4afb5ceSopenharmony_ci if (!vhd) 81d4afb5ceSopenharmony_ci return 0; 82d4afb5ceSopenharmony_ci if (lws_pvo_get_str(in, "indexpath", 83d4afb5ceSopenharmony_ci (const char **)&vhd->indexpath)) 84d4afb5ceSopenharmony_ci return 1; 85d4afb5ceSopenharmony_ci 86d4afb5ceSopenharmony_ci return 0; 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP: 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_ci pss->first = 1; 91d4afb5ceSopenharmony_ci pss->ac_done = 0; 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci /* 94d4afb5ceSopenharmony_ci * we have a "subdirectory" selecting the task 95d4afb5ceSopenharmony_ci * 96d4afb5ceSopenharmony_ci * /a/ = autocomplete 97d4afb5ceSopenharmony_ci * /r/ = results 98d4afb5ceSopenharmony_ci */ 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci if (strncmp(ccp, "/a/", 3) && strncmp(ccp, "/r/", 3)) 101d4afb5ceSopenharmony_ci goto reply_404; 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_ci memset(¶ms, 0, sizeof(params)); 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci params.needle = ccp + 3; 106d4afb5ceSopenharmony_ci if (*(ccp + 1) == 'a') 107d4afb5ceSopenharmony_ci params.flags = LWSFTS_F_QUERY_AUTOCOMPLETE; 108d4afb5ceSopenharmony_ci if (*(ccp + 1) == 'r') 109d4afb5ceSopenharmony_ci params.flags = LWSFTS_F_QUERY_FILES | 110d4afb5ceSopenharmony_ci LWSFTS_F_QUERY_FILE_LINES | 111d4afb5ceSopenharmony_ci LWSFTS_F_QUERY_QUOTE_LINE; 112d4afb5ceSopenharmony_ci params.max_autocomplete = 10; 113d4afb5ceSopenharmony_ci params.max_files = 10; 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci jtf = lws_fts_open(vhd->indexpath); 116d4afb5ceSopenharmony_ci if (!jtf) { 117d4afb5ceSopenharmony_ci lwsl_err("unable to open %s\n", vhd->indexpath); 118d4afb5ceSopenharmony_ci /* we'll inform the client in the JSON */ 119d4afb5ceSopenharmony_ci goto reply_200; 120d4afb5ceSopenharmony_ci } 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci result = lws_fts_search(jtf, ¶ms); 123d4afb5ceSopenharmony_ci lws_fts_close(jtf); 124d4afb5ceSopenharmony_ci if (result) { 125d4afb5ceSopenharmony_ci pss->result = params.results_head; 126d4afb5ceSopenharmony_ci pss->ac = result->autocomplete_head; 127d4afb5ceSopenharmony_ci pss->fp = result->filepath_head; 128d4afb5ceSopenharmony_ci } 129d4afb5ceSopenharmony_ci /* NULL result will be told in the json as "indexed": 0 */ 130d4afb5ceSopenharmony_ci 131d4afb5ceSopenharmony_cireply_200: 132d4afb5ceSopenharmony_ci if (lws_add_http_common_headers(wsi, HTTP_STATUS_OK, 133d4afb5ceSopenharmony_ci "text/html", 134d4afb5ceSopenharmony_ci LWS_ILLEGAL_HTTP_CONTENT_LEN, &p, end)) 135d4afb5ceSopenharmony_ci return 1; 136d4afb5ceSopenharmony_ci 137d4afb5ceSopenharmony_ci if (lws_finalize_write_http_header(wsi, start, &p, end)) 138d4afb5ceSopenharmony_ci return 1; 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 141d4afb5ceSopenharmony_ci return 0; 142d4afb5ceSopenharmony_ci 143d4afb5ceSopenharmony_cireply_404: 144d4afb5ceSopenharmony_ci if (lws_add_http_common_headers(wsi, HTTP_STATUS_NOT_FOUND, 145d4afb5ceSopenharmony_ci "text/html", 146d4afb5ceSopenharmony_ci LWS_ILLEGAL_HTTP_CONTENT_LEN, &p, end)) 147d4afb5ceSopenharmony_ci return 1; 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci if (lws_finalize_write_http_header(wsi, start, &p, end)) 150d4afb5ceSopenharmony_ci return 1; 151d4afb5ceSopenharmony_ci return lws_http_transaction_completed(wsi); 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLOSED_HTTP: 154d4afb5ceSopenharmony_ci if (pss && pss->result) 155d4afb5ceSopenharmony_ci lwsac_free(&pss->result); 156d4afb5ceSopenharmony_ci break; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP_WRITEABLE: 159d4afb5ceSopenharmony_ci 160d4afb5ceSopenharmony_ci if (!pss) 161d4afb5ceSopenharmony_ci break; 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_ci n = LWS_WRITE_HTTP; 164d4afb5ceSopenharmony_ci if (pss->first) 165d4afb5ceSopenharmony_ci p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), 166d4afb5ceSopenharmony_ci "{\"indexed\": %d, \"ac\": [", !!pss->result); 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci while (pss->ac && lws_ptr_diff(end, p) > 256) { 169d4afb5ceSopenharmony_ci p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), 170d4afb5ceSopenharmony_ci "%c{\"ac\": \"%s\",\"matches\": %d," 171d4afb5ceSopenharmony_ci "\"agg\": %d, \"elided\": %d}", 172d4afb5ceSopenharmony_ci pss->first ? ' ' : ',', (char *)(pss->ac + 1), 173d4afb5ceSopenharmony_ci pss->ac->instances, pss->ac->agg_instances, 174d4afb5ceSopenharmony_ci pss->ac->elided); 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci pss->first = 0; 177d4afb5ceSopenharmony_ci pss->ac = pss->ac->next; 178d4afb5ceSopenharmony_ci } 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci if (!pss->ac_done && !pss->ac && pss->fp) { 181d4afb5ceSopenharmony_ci pss->ac_done = 1; 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), 184d4afb5ceSopenharmony_ci "], \"fp\": ["); 185d4afb5ceSopenharmony_ci } 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci while (pss->fp && lws_ptr_diff_size_t(end, p) > 256) { 188d4afb5ceSopenharmony_ci if (!pss->fp_init_done) { 189d4afb5ceSopenharmony_ci p += lws_snprintf((char *)p, 190d4afb5ceSopenharmony_ci lws_ptr_diff_size_t(end, p), 191d4afb5ceSopenharmony_ci "%c{\"path\": \"%s\",\"matches\": %d," 192d4afb5ceSopenharmony_ci "\"origlines\": %d," 193d4afb5ceSopenharmony_ci "\"hits\": [", pss->first ? ' ' : ',', 194d4afb5ceSopenharmony_ci ((char *)(pss->fp + 1)) + 195d4afb5ceSopenharmony_ci pss->fp->matches_length, 196d4afb5ceSopenharmony_ci pss->fp->matches, 197d4afb5ceSopenharmony_ci pss->fp->lines_in_file); 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci pss->li = ((uint32_t *)(pss->fp + 1)); 200d4afb5ceSopenharmony_ci pss->done = 0; 201d4afb5ceSopenharmony_ci pss->fp_init_done = 1; 202d4afb5ceSopenharmony_ci pss->first = 0; 203d4afb5ceSopenharmony_ci } else { 204d4afb5ceSopenharmony_ci while (pss->done < pss->fp->matches && 205d4afb5ceSopenharmony_ci lws_ptr_diff(end, p) > 256) { 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci p += lws_snprintf((char *)p, 208d4afb5ceSopenharmony_ci lws_ptr_diff_size_t(end, p), 209d4afb5ceSopenharmony_ci "%c\n{\"l\":%d,\"o\":%d," 210d4afb5ceSopenharmony_ci "\"s\":\"%s\"}", 211d4afb5ceSopenharmony_ci !pss->done ? ' ' : ',', 212d4afb5ceSopenharmony_ci pss->li[0], pss->li[1], 213d4afb5ceSopenharmony_ci *((const char **)&pss->li[2])); 214d4afb5ceSopenharmony_ci pss->li += 2 + (sizeof(const char *) / 215d4afb5ceSopenharmony_ci sizeof(uint32_t)); 216d4afb5ceSopenharmony_ci pss->done++; 217d4afb5ceSopenharmony_ci } 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci if (pss->done == pss->fp->matches) { 220d4afb5ceSopenharmony_ci *p++ = ']'; 221d4afb5ceSopenharmony_ci pss->fp_init_done = 0; 222d4afb5ceSopenharmony_ci pss->fp = pss->fp->next; 223d4afb5ceSopenharmony_ci if (!pss->fp) 224d4afb5ceSopenharmony_ci *p++ = '}'; 225d4afb5ceSopenharmony_ci } 226d4afb5ceSopenharmony_ci } 227d4afb5ceSopenharmony_ci } 228d4afb5ceSopenharmony_ci 229d4afb5ceSopenharmony_ci if (!pss->ac && !pss->fp) { 230d4afb5ceSopenharmony_ci n = LWS_WRITE_HTTP_FINAL; 231d4afb5ceSopenharmony_ci p += lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), 232d4afb5ceSopenharmony_ci "]}"); 233d4afb5ceSopenharmony_ci } 234d4afb5ceSopenharmony_ci 235d4afb5ceSopenharmony_ci if (lws_write(wsi, (uint8_t *)start, 236d4afb5ceSopenharmony_ci lws_ptr_diff_size_t(p, start), (enum lws_write_protocol)n) != 237d4afb5ceSopenharmony_ci lws_ptr_diff(p, start)) 238d4afb5ceSopenharmony_ci return 1; 239d4afb5ceSopenharmony_ci 240d4afb5ceSopenharmony_ci if (n == LWS_WRITE_HTTP_FINAL) { 241d4afb5ceSopenharmony_ci if (pss->result) 242d4afb5ceSopenharmony_ci lwsac_free(&pss->result); 243d4afb5ceSopenharmony_ci if (lws_http_transaction_completed(wsi)) 244d4afb5ceSopenharmony_ci return -1; 245d4afb5ceSopenharmony_ci } else 246d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci return 0; 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci default: 251d4afb5ceSopenharmony_ci break; 252d4afb5ceSopenharmony_ci } 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 255d4afb5ceSopenharmony_ci} 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci 258d4afb5ceSopenharmony_ci#define LWS_PLUGIN_PROTOCOL_FULLTEXT_DEMO \ 259d4afb5ceSopenharmony_ci { \ 260d4afb5ceSopenharmony_ci "lws-test-fts", \ 261d4afb5ceSopenharmony_ci callback_fts, \ 262d4afb5ceSopenharmony_ci sizeof(struct pss_fts_demo), \ 263d4afb5ceSopenharmony_ci 0, \ 264d4afb5ceSopenharmony_ci 0, NULL, 0 \ 265d4afb5ceSopenharmony_ci } 266d4afb5ceSopenharmony_ci 267d4afb5ceSopenharmony_ci#if !defined (LWS_PLUGIN_STATIC) 268d4afb5ceSopenharmony_ci 269d4afb5ceSopenharmony_ciLWS_VISIBLE const struct lws_protocols fulltext_demo_protocols[] = { 270d4afb5ceSopenharmony_ci LWS_PLUGIN_PROTOCOL_FULLTEXT_DEMO 271d4afb5ceSopenharmony_ci}; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ciLWS_VISIBLE const lws_plugin_protocol_t fulltext_demo = { 274d4afb5ceSopenharmony_ci .hdr = { 275d4afb5ceSopenharmony_ci "fulltext demo", 276d4afb5ceSopenharmony_ci "lws_protocol_plugin", 277d4afb5ceSopenharmony_ci LWS_BUILD_HASH, 278d4afb5ceSopenharmony_ci LWS_PLUGIN_API_MAGIC 279d4afb5ceSopenharmony_ci }, 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci .protocols = fulltext_demo_protocols, 282d4afb5ceSopenharmony_ci .count_protocols = LWS_ARRAY_SIZE(fulltext_demo_protocols), 283d4afb5ceSopenharmony_ci .extensions = NULL, 284d4afb5ceSopenharmony_ci .count_extensions = 0, 285d4afb5ceSopenharmony_ci}; 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci#endif 288