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