]> git.proxmox.com Git - ceph.git/blame - ceph/src/civetweb/src/mod_duktape.inl
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / civetweb / src / mod_duktape.inl
CommitLineData
7c673cae
FG
1/* This file is part of the CivetWeb web server.
2 * See https://github.com/civetweb/civetweb/
3 * (C) 2015 by the CivetWeb authors, MIT license.
4 */
5
6#include "duktape.h"
7
8/* TODO: the mg context should be added to duktape as well */
9/* Alternative: redefine a new, clean API from scratch (instead of using mg),
10 * or at least do not add problematic functions. */
11/* For evaluation purposes, currently only "send" is supported.
12 * All other ~50 functions will be added later. */
13
14/* Note: This is only experimental support, so the API may still change. */
15
16static const char *civetweb_conn_id = "\xFF"
17 "civetweb_conn";
18static const char *civetweb_ctx_id = "\xFF"
19 "civetweb_ctx";
20
21
22static void *
23mg_duk_mem_alloc(void *udata, duk_size_t size)
24{
25 return mg_malloc(size);
26}
27
28
29static void *
30mg_duk_mem_realloc(void *udata, void *ptr, duk_size_t newsize)
31{
32 return mg_realloc(ptr, newsize);
33}
34
35
36static void
37mg_duk_mem_free(void *udata, void *ptr)
38{
39 mg_free(ptr);
40}
41
42
43static void
44mg_duk_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg)
45{
46 /* Script is called "protected" (duk_peval_file), so script errors should
47 * never yield in a call to this function. Maybe calls prior to executing
48 * the script could raise a fatal error. */
49 struct mg_connection *conn;
50
51 duk_push_global_stash(ctx);
52 duk_get_prop_string(ctx, -1, civetweb_conn_id);
53 conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
54
55 mg_cry(conn, "%s", msg);
56}
57
58
59static duk_ret_t
60duk_itf_write(duk_context *ctx)
61{
62 struct mg_connection *conn;
63 duk_double_t ret;
64 duk_size_t len = 0;
65 const char *val = duk_require_lstring(ctx, -1, &len);
66
67 /*
68 duk_push_global_stash(ctx);
69 duk_get_prop_string(ctx, -1, civetweb_conn_id);
70 conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
71 */
72 duk_push_current_function(ctx);
73 duk_get_prop_string(ctx, -1, civetweb_conn_id);
74 conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
75
76 if (!conn) {
77 duk_error(ctx,
78 DUK_ERR_INTERNAL_ERROR,
79 "function not available without connection object");
80 /* probably never reached, but satisfies static code analysis */
81 return DUK_RET_INTERNAL_ERROR;
82 }
83
84 ret = mg_write(conn, val, len);
85
86 duk_push_number(ctx, ret);
87 return 1;
88}
89
90
91static duk_ret_t
92duk_itf_read(duk_context *ctx)
93{
94 struct mg_connection *conn;
95 char buf[1024];
96 int len;
97
98 duk_push_global_stash(ctx);
99 duk_get_prop_string(ctx, -1, civetweb_conn_id);
100 conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
101
102 if (!conn) {
103 duk_error(ctx,
104 DUK_ERR_INTERNAL_ERROR,
105 "function not available without connection object");
106 /* probably never reached, but satisfies static code analysis */
107 return DUK_RET_INTERNAL_ERROR;
108 }
109
110 len = mg_read(conn, buf, sizeof(buf));
111
112 duk_push_lstring(ctx, buf, len);
113 return 1;
114}
115
116
117static duk_ret_t
118duk_itf_getoption(duk_context *ctx)
119{
120 struct mg_context *cv_ctx;
121 const char *ret;
122 duk_size_t len = 0;
123 const char *val = duk_require_lstring(ctx, -1, &len);
124
125 duk_push_current_function(ctx);
126 duk_get_prop_string(ctx, -1, civetweb_ctx_id);
127 cv_ctx = (struct mg_context *)duk_to_pointer(ctx, -1);
128
129 if (!cv_ctx) {
130 duk_error(ctx,
131 DUK_ERR_INTERNAL_ERROR,
132 "function not available without connection object");
133 /* probably never reached, but satisfies static code analysis */
134 return DUK_RET_INTERNAL_ERROR;
135 }
136
137 ret = mg_get_option(cv_ctx, val);
138 if (ret) {
139 duk_push_string(ctx, ret);
140 } else {
141 duk_push_null(ctx);
142 }
143
144 return 1;
145}
146
147
148static void
149mg_exec_duktape_script(struct mg_connection *conn, const char *script_name)
150{
151 int i;
152 duk_context *ctx = NULL;
153
154 conn->must_close = 1;
155
156 /* Create Duktape interpreter state */
157 ctx = duk_create_heap(mg_duk_mem_alloc,
158 mg_duk_mem_realloc,
159 mg_duk_mem_free,
160 NULL,
161 mg_duk_fatal_handler);
162 if (!ctx) {
163 mg_cry(conn, "Failed to create a Duktape heap.");
164 goto exec_duktape_finished;
165 }
166
167 /* Add "conn" object */
168 duk_push_global_object(ctx);
169 duk_push_object(ctx); /* create a new table/object ("conn") */
170
171 duk_push_c_function(ctx, duk_itf_write, 1 /* 1 = nargs */);
172 duk_push_pointer(ctx, (void *)conn);
173 duk_put_prop_string(ctx, -2, civetweb_conn_id);
174 duk_put_prop_string(ctx, -2, "write"); /* add function conn.write */
175
176 duk_push_c_function(ctx, duk_itf_read, 0 /* 0 = nargs */);
177 duk_push_pointer(ctx, (void *)conn);
178 duk_put_prop_string(ctx, -2, civetweb_conn_id);
179 duk_put_prop_string(ctx, -2, "read"); /* add function conn.read */
180
181 duk_push_string(ctx, conn->request_info.request_method);
182 duk_put_prop_string(ctx, -2, "request_method"); /* add string conn.r... */
183
184 duk_push_string(ctx, conn->request_info.request_uri);
185 duk_put_prop_string(ctx, -2, "request_uri");
186
187 duk_push_string(ctx, conn->request_info.local_uri);
188 duk_put_prop_string(ctx, -2, "uri");
189
190 duk_push_string(ctx, conn->request_info.http_version);
191 duk_put_prop_string(ctx, -2, "http_version");
192
193 duk_push_string(ctx, conn->request_info.query_string);
194 duk_put_prop_string(ctx, -2, "query_string");
195
196 duk_push_string(ctx, conn->request_info.remote_addr);
197 duk_put_prop_string(ctx, -2, "remote_addr");
198
199 duk_push_int(ctx, conn->request_info.remote_port);
200 duk_put_prop_string(ctx, -2, "remote_port");
201
202 duk_push_int(ctx, ntohs(conn->client.lsa.sin.sin_port));
203 duk_put_prop_string(ctx, -2, "server_port");
204
205 duk_push_object(ctx); /* subfolder "conn.http_headers" */
206 for (i = 0; i < conn->request_info.num_headers; i++) {
207 duk_push_string(ctx, conn->request_info.http_headers[i].value);
208 duk_put_prop_string(ctx, -2, conn->request_info.http_headers[i].name);
209 }
210 duk_put_prop_string(ctx, -2, "http_headers");
211
212 duk_put_prop_string(ctx, -2, "conn"); /* call the table "conn" */
213
214 /* Add "civetweb" object */
215 duk_push_global_object(ctx);
216 duk_push_object(ctx); /* create a new table/object ("conn") */
217
218 duk_push_string(ctx, CIVETWEB_VERSION);
219 duk_put_prop_string(ctx, -2, "version");
220
221 duk_push_string(ctx, script_name);
222 duk_put_prop_string(ctx, -2, "script_name");
223
224 if (conn->ctx != NULL) {
225 duk_push_c_function(ctx, duk_itf_getoption, 1 /* 1 = nargs */);
226 duk_push_pointer(ctx, (void *)(conn->ctx));
227 duk_put_prop_string(ctx, -2, civetweb_ctx_id);
228 duk_put_prop_string(ctx, -2, "getoption"); /* add function conn.write */
229
230 if (conn->ctx->systemName != NULL) {
231 duk_push_string(ctx, conn->ctx->systemName);
232 duk_put_prop_string(ctx, -2, "system");
233 }
234 }
235
236 duk_put_prop_string(ctx, -2, "civetweb"); /* call the table "civetweb" */
237
238 duk_push_global_stash(ctx);
239 duk_push_pointer(ctx, (void *)conn);
240 duk_put_prop_string(ctx, -2, civetweb_conn_id);
241
242 if (duk_peval_file(ctx, script_name) != 0) {
243 mg_cry(conn, "%s", duk_safe_to_string(ctx, -1));
244 goto exec_duktape_finished;
245 }
246 duk_pop(ctx); /* ignore result */
247
248exec_duktape_finished:
249 duk_destroy_heap(ctx);
250}