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