1 #include <uwsgi.h>
2
3 #include <lua.h>
4 #include <lualib.h>
5 #include <lauxlib.h>
6
7 #if LUA_VERSION_NUM < 502
8 # define luaL_newuwsgilib(L,l) luaL_register(L, "uwsgi",l)
9 # define lua_rawlen lua_objlen
10 #else
11 # define luaL_newuwsgilib(L,l) lua_newtable(L);luaL_setfuncs (L, l, 0);lua_pushvalue(L,-1);lua_setglobal(L,"uwsgi")
12 #endif
13
14 extern struct uwsgi_server uwsgi;
15
16 struct uwsgi_lua {
17 struct lua_State **L;
18 char *shell;
19 char *filename;
20 struct uwsgi_string_list *load;
21 int gc_freq;
22 } ulua;
23
24 struct uwsgi_plugin lua_plugin;
25
26 #define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
27
uwsgi_opt_luashell(char * opt,char * value,void * foobar)28 static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) {
29
30 uwsgi.honour_stdin = 1;
31 if (value) {
32 ulua.shell = value;
33 }
34 else {
35 ulua.shell = "";
36 }
37 }
38
39
40 static struct uwsgi_option uwsgi_lua_options[] = {
41
42 {"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
43 {"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0},
44 {"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
45 {"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0},
46 {"lua-gc-freq", no_argument, 0, "set the lua gc frequency (default: 0, runs after every request)", uwsgi_opt_set_int, &ulua.gc_freq, 0},
47
48 {0, 0, 0, 0},
49
50 };
51
ulua_check_args(lua_State * L,const char * func,int n)52 static void ulua_check_args(lua_State *L, const char *func, int n) {
53 int args = lua_gettop(L);
54 char error[1024];
55 if (args != n) {
56 if (n == 1) {
57 snprintf(error, 1024, "uwsgi.%s takes 1 parameter", func+10);
58 }
59 else {
60 snprintf(error, 1024, "uwsgi.%s takes %d parameters", func+10, n);
61 }
62 lua_pushstring(L, error);
63 lua_error(L);
64 }
65 }
66
uwsgi_api_log(lua_State * L)67 static int uwsgi_api_log(lua_State *L) {
68
69 const char *logline ;
70
71 lca(L, 1);
72
73 if (lua_isstring(L, 1)) {
74 logline = lua_tolstring(L, 1, NULL);
75 uwsgi_log( "%s\n", logline);
76 }
77
78 return 0;
79 }
80
uwsgi_api_register_rpc(lua_State * L)81 static int uwsgi_api_register_rpc(lua_State *L) {
82
83 uint8_t argc = lua_gettop(L);
84 const char *name;
85 // a hack for 64bit;
86 int func;
87 long lfunc;
88
89 if (argc < 2) {
90 lua_pushnil(L);
91 return 1;
92 }
93
94 name = lua_tolstring(L, 1, NULL);
95
96 lua_pushvalue(L, 2);
97 func = luaL_ref(L, LUA_REGISTRYINDEX);
98
99 uwsgi_log("registered function %d in Lua global table\n", func);
100 lfunc = func;
101
102 if (uwsgi_register_rpc((char *)name, &lua_plugin, 0, (void *) lfunc)) {
103 lua_pushnil(L);
104 }
105 else {
106 lua_pushboolean(L, 1);
107 }
108
109 return 1;
110 }
111
uwsgi_api_cache_set(lua_State * L)112 static int uwsgi_api_cache_set(lua_State *L) {
113
114 uint8_t argc = lua_gettop(L);
115 const char *key ;
116 const char *value ;
117 uint64_t expires = 0;
118 size_t vallen;
119 size_t keylen;
120 const char *cache = NULL;
121
122 if (argc < 2) goto error;
123
124 key = lua_tolstring(L, 1, &keylen);
125 value = lua_tolstring(L, 2, &vallen);
126 if (argc > 2) {
127 expires = lua_tonumber(L, 3);
128 if (argc > 3) {
129 cache = lua_tolstring(L, 4, NULL);
130 }
131 }
132
133 if (!uwsgi_cache_magic_set((char *)key, keylen, (char *)value, vallen, expires, 0, (char *) cache)) {
134 lua_pushboolean(L, 1);
135 return 1;
136 }
137 error:
138
139 lua_pushnil(L);
140 return 1;
141
142 }
143
uwsgi_api_cache_update(lua_State * L)144 static int uwsgi_api_cache_update(lua_State *L) {
145
146 uint8_t argc = lua_gettop(L);
147 const char *key ;
148 const char *value ;
149 uint64_t expires = 0;
150 size_t vallen;
151 size_t keylen;
152 const char *cache = NULL;
153
154 if (argc < 2) goto error;
155
156 key = lua_tolstring(L, 1, &keylen);
157 value = lua_tolstring(L, 2, &vallen);
158 if (argc > 2) {
159 expires = lua_tonumber(L, 3);
160 if (argc > 3) {
161 cache = lua_tolstring(L, 4, NULL);
162 }
163 }
164
165 if (!uwsgi_cache_magic_set((char *)key, keylen, (char *)value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE, (char *)cache)) {
166 lua_pushboolean(L, 1);
167 return 1;
168 }
169 error:
170
171 lua_pushnil(L);
172 return 1;
173
174 }
175
176
uwsgi_api_register_signal(lua_State * L)177 static int uwsgi_api_register_signal(lua_State *L) {
178
179 int args = lua_gettop(L);
180 uint8_t sig;
181 long lhandler;
182 const char *who;
183
184 if (args >= 3) {
185
186 sig = lua_tonumber(L, 1);
187 who = lua_tostring(L, 2);
188 lua_pushvalue(L, 3);
189 lhandler = luaL_ref(L, LUA_REGISTRYINDEX);
190
191 uwsgi_register_signal(sig, (char *)who, (void *) lhandler, 6);
192 }
193
194 lua_pushnil(L);
195 return 1;
196 }
197
uwsgi_api_cache_clear(lua_State * L)198 static int uwsgi_api_cache_clear(lua_State *L) {
199
200 const char *cache = NULL;
201 uint8_t argc = lua_gettop(L);
202
203 if (argc > 0) {
204 cache = lua_tolstring(L, 2, NULL);
205 }
206 if (!uwsgi_cache_magic_clear((char *)cache)) {
207 lua_pushboolean(L, 1);
208 return 1;
209 }
210
211 lua_pushnil(L);
212 return 1;
213
214 }
215
216
uwsgi_api_cache_del(lua_State * L)217 static int uwsgi_api_cache_del(lua_State *L) {
218
219 size_t keylen;
220 const char *key ;
221 const char *cache = NULL;
222 uint8_t argc = lua_gettop(L);
223
224 if (argc == 0) goto error;
225
226 if (lua_isstring(L, 1)) {
227 // get the key
228 key = lua_tolstring(L, 1, &keylen);
229 if (argc > 1) {
230 cache = lua_tolstring(L, 2, NULL);
231 }
232 if (!uwsgi_cache_magic_del((char *)key, keylen, (char *)cache)) {
233 lua_pushboolean(L, 1);
234 return 1;
235 }
236 }
237
238 error:
239 lua_pushnil(L);
240 return 1;
241
242 }
243
244
uwsgi_api_cache_exists(lua_State * L)245 static int uwsgi_api_cache_exists(lua_State *L) {
246
247 size_t keylen;
248 const char *key ;
249 const char *cache = NULL;
250 uint8_t argc = lua_gettop(L);
251
252 if (argc == 0) goto error;
253
254 if (lua_isstring(L, 1)) {
255 // get the key
256 key = lua_tolstring(L, 1, &keylen);
257 if (argc > 1) {
258 cache = lua_tolstring(L, 2, NULL);
259 }
260 if (uwsgi_cache_magic_exists((char *)key, keylen,(char *)cache)) {
261 lua_pushboolean(L, 1);
262 return 1;
263 }
264 }
265
266 error:
267 lua_pushnil(L);
268 return 1;
269
270 }
271
uwsgi_api_async_sleep(lua_State * L)272 static int uwsgi_api_async_sleep(lua_State *L) {
273 uint8_t argc = lua_gettop(L);
274 if (argc == 0) goto end;
275
276 struct wsgi_request *wsgi_req = current_wsgi_req();
277
278 int timeout = lua_tonumber(L, 1);
279
280 if (timeout >= 0) {
281 async_add_timeout(wsgi_req, timeout);
282 }
283 end:
284 lua_pushnil(L);
285 return 1;
286 }
287
uwsgi_api_wait_fd_read(lua_State * L)288 static int uwsgi_api_wait_fd_read(lua_State *L) {
289 uint8_t argc = lua_gettop(L);
290 if (argc == 0) goto end;
291
292 struct wsgi_request *wsgi_req = current_wsgi_req();
293
294 int fd = lua_tonumber(L, 1);
295 int timeout = 0;
296 if (argc > 1) {
297 timeout = lua_tonumber(L, 2);
298 }
299
300 if (async_add_fd_read(wsgi_req, fd, timeout)) {
301 lua_pushstring(L, "unable to call async_add_fd_read()");
302 lua_error(L);
303 return 0;
304 }
305 end:
306 lua_pushnil(L);
307 return 1;
308 }
309
uwsgi_api_wait_fd_write(lua_State * L)310 static int uwsgi_api_wait_fd_write(lua_State *L) {
311 uint8_t argc = lua_gettop(L);
312 if (argc == 0) goto end;
313
314 struct wsgi_request *wsgi_req = current_wsgi_req();
315
316 int fd = lua_tonumber(L, 1);
317 int timeout = 0;
318 if (argc > 1) {
319 timeout = lua_tonumber(L, 2);
320 }
321
322 if (async_add_fd_write(wsgi_req, fd, timeout)) {
323 lua_pushstring(L, "unable to call async_add_fd_write()");
324 lua_error(L);
325 return 0;
326 }
327 end:
328 lua_pushnil(L);
329 return 1;
330 }
331
uwsgi_api_async_connect(lua_State * L)332 static int uwsgi_api_async_connect(lua_State *L) {
333 uint8_t argc = lua_gettop(L);
334 if (argc == 0) goto end;
335
336 int fd = uwsgi_connect((char *)lua_tostring(L, 1), 0, 1);
337 lua_pushnumber(L, fd);
338 return 1;
339 end:
340 lua_pushnil(L);
341 return 1;
342 }
343
uwsgi_api_is_connected(lua_State * L)344 static int uwsgi_api_is_connected(lua_State *L) {
345 uint8_t argc = lua_gettop(L);
346 if (argc == 0) goto end;
347 int fd = lua_tonumber(L, 1);
348 if (uwsgi_is_connected(fd)) {
349 lua_pushboolean(L, 1);
350 return 1;
351 }
352 lua_pushboolean(L, 0);
353 return 1;
354 end:
355 lua_pushnil(L);
356 return 1;
357 }
358
uwsgi_api_close(lua_State * L)359 static int uwsgi_api_close(lua_State *L) {
360 uint8_t argc = lua_gettop(L);
361 if (argc == 0) goto end;
362 int fd = lua_tonumber(L, 1);
363 close(fd);
364 end:
365 lua_pushnil(L);
366 return 1;
367 }
368
369
uwsgi_api_ready_fd(lua_State * L)370 static int uwsgi_api_ready_fd(lua_State *L) {
371 struct wsgi_request *wsgi_req = current_wsgi_req();
372 int fd = uwsgi_ready_fd(wsgi_req);
373 lua_pushnumber(L, fd);
374 return 1;
375 }
376
uwsgi_api_websocket_handshake(lua_State * L)377 static int uwsgi_api_websocket_handshake(lua_State *L) {
378 uint8_t argc = lua_gettop(L);
379
380 const char *key = NULL, *origin = NULL, *proto = NULL;
381 size_t key_len = 0, origin_len = 0, proto_len = 0;
382
383 if (argc > 0) {
384 key = lua_tolstring(L, 1, &key_len);
385 if (argc > 1) {
386 origin = lua_tolstring(L, 2, &origin_len);
387 if (argc > 2) {
388 proto = lua_tolstring(L, 3, &proto_len);
389 }
390 }
391 }
392
393 struct wsgi_request *wsgi_req = current_wsgi_req();
394 if (uwsgi_websocket_handshake(wsgi_req, (char *)key, key_len, (char *)origin, origin_len, (char *) proto, proto_len)) {
395 goto error;
396 }
397
398 lua_pushnil(L);
399 return 1;
400
401 error:
402 lua_pushstring(L, "unable to complete websocket handshake");
403 lua_error(L);
404 return 0;
405 }
406
uwsgi_api_websocket_send(lua_State * L)407 static int uwsgi_api_websocket_send(lua_State *L) {
408 uint8_t argc = lua_gettop(L);
409 if (argc == 0) goto error;
410
411 size_t message_len = 0;
412 const char *message = lua_tolstring(L, 1, &message_len);
413 struct wsgi_request *wsgi_req = current_wsgi_req();
414
415 if (uwsgi_websocket_send(wsgi_req, (char *) message, message_len)) {
416 goto error;
417 }
418 lua_pushnil(L);
419 return 1;
420 error:
421 lua_pushstring(L, "unable to send websocket message");
422 lua_error(L);
423 return 0;
424 }
425
uwsgi_api_websocket_send_binary(lua_State * L)426 static int uwsgi_api_websocket_send_binary(lua_State *L) {
427 uint8_t argc = lua_gettop(L);
428 if (argc == 0) goto error;
429
430 size_t message_len = 0;
431 const char *message = lua_tolstring(L, 1, &message_len);
432 struct wsgi_request *wsgi_req = current_wsgi_req();
433
434 if (uwsgi_websocket_send_binary(wsgi_req, (char *) message, message_len)) {
435 goto error;
436 }
437 lua_pushnil(L);
438 return 1;
439 error:
440 lua_pushstring(L, "unable to send websocket binary message");
441 lua_error(L);
442 return 0;
443 }
444
uwsgi_api_websocket_send_from_sharedarea(lua_State * L)445 static int uwsgi_api_websocket_send_from_sharedarea(lua_State *L) {
446 uint8_t argc = lua_gettop(L);
447 if (argc < 2) goto error;
448
449 int id = lua_tonumber(L, 1);
450 uint64_t pos = lua_tonumber(L, 2);
451 uint64_t len = 0;
452 if (argc > 2) {
453 len = lua_tonumber(L, 3);
454 }
455 struct wsgi_request *wsgi_req = current_wsgi_req();
456
457 if (uwsgi_websocket_send_from_sharedarea(wsgi_req, id, pos, len)) {
458 goto error;
459 }
460 lua_pushnil(L);
461 return 1;
462 error:
463 lua_pushstring(L, "unable to send websocket message from sharedarea");
464 lua_error(L);
465 return 0;
466 }
467
uwsgi_api_websocket_send_binary_from_sharedarea(lua_State * L)468 static int uwsgi_api_websocket_send_binary_from_sharedarea(lua_State *L) {
469 uint8_t argc = lua_gettop(L);
470 if (argc < 2) goto error;
471
472 int id = lua_tonumber(L, 1);
473 uint64_t pos = lua_tonumber(L, 2);
474 uint64_t len = 0;
475 if (argc > 2) {
476 len = lua_tonumber(L, 3);
477 }
478 struct wsgi_request *wsgi_req = current_wsgi_req();
479
480 if (uwsgi_websocket_send_binary_from_sharedarea(wsgi_req, id, pos, len)) {
481 goto error;
482 }
483 lua_pushnil(L);
484 return 1;
485 error:
486 lua_pushstring(L, "unable to send websocket message from sharedarea");
487 lua_error(L);
488 return 0;
489 }
490
uwsgi_api_websocket_recv(lua_State * L)491 static int uwsgi_api_websocket_recv(lua_State *L) {
492 struct wsgi_request *wsgi_req = current_wsgi_req();
493 struct uwsgi_buffer *ub = uwsgi_websocket_recv(wsgi_req);
494 if (!ub) {
495 lua_pushstring(L, "unable to receive websocket message");
496 lua_error(L);
497 return 0;
498 }
499 lua_pushlstring(L, ub->buf, ub->pos);
500 uwsgi_buffer_destroy(ub);
501 return 1;
502 }
503
uwsgi_api_websocket_recv_nb(lua_State * L)504 static int uwsgi_api_websocket_recv_nb(lua_State *L) {
505 struct wsgi_request *wsgi_req = current_wsgi_req();
506 struct uwsgi_buffer *ub = uwsgi_websocket_recv_nb(wsgi_req);
507 if (!ub) {
508 lua_pushstring(L, "unable to receive websocket message");
509 lua_error(L);
510 return 0;
511 }
512 lua_pushlstring(L, ub->buf, ub->pos);
513 uwsgi_buffer_destroy(ub);
514 return 1;
515 }
516
uwsgi_api_cache_get(lua_State * L)517 static int uwsgi_api_cache_get(lua_State *L) {
518
519 char *value ;
520 uint64_t valsize;
521 size_t keylen;
522 const char *key ;
523 const char *cache = NULL;
524 uint8_t argc = lua_gettop(L);
525
526 if (argc == 0) goto error;
527
528 if (lua_isstring(L, 1)) {
529 // get the key
530 key = lua_tolstring(L, 1, &keylen);
531 if (argc > 1) {
532 cache = lua_tolstring(L, 2, NULL);
533 }
534 value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, NULL, (char *)cache);
535 if (value) {
536 lua_pushlstring(L, value, valsize);
537 free(value);
538 return 1;
539 }
540 }
541
542 error:
543 lua_pushnil(L);
544 return 1;
545
546 }
547
uwsgi_api_req_fd(lua_State * L)548 static int uwsgi_api_req_fd(lua_State *L) {
549
550 struct wsgi_request *wsgi_req = current_wsgi_req();
551
552 lua_pushnumber(L, wsgi_req->fd);
553 return 1;
554 }
555
uwsgi_api_lock(lua_State * L)556 static int uwsgi_api_lock(lua_State *L) {
557
558 int lock_num = 0;
559
560 // the spooler cannot lock resources
561 if (uwsgi.i_am_a_spooler) {
562 lua_pushstring(L, "The spooler cannot lock/unlock resources");
563 lua_error(L);
564 }
565
566 if (lua_gettop(L) > 0) {
567 lock_num = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1;
568 if (lock_num < 0 || lock_num > uwsgi.locks) {
569 lua_pushstring(L, "Invalid lock number");
570 lua_error(L);
571 }
572 }
573
574 uwsgi_lock(uwsgi.user_lock[lock_num]);
575
576 return 0;
577 }
578
579
uwsgi_api_unlock(lua_State * L)580 static int uwsgi_api_unlock(lua_State *L) {
581
582 int lock_num = 0;
583
584 // the spooler cannot lock resources
585 if (uwsgi.i_am_a_spooler) {
586 lua_pushstring(L, "The spooler cannot lock/unlock resources");
587 lua_error(L);
588 }
589
590 if (lua_gettop(L) > 0) {
591 lock_num = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1;
592 if (lock_num < 0 || lock_num > uwsgi.locks) {
593 lua_pushstring(L, "Invalid lock number");
594 lua_error(L);
595 }
596 }
597
598 uwsgi_unlock(uwsgi.user_lock[lock_num]);
599
600 return 0;
601 }
602
603 static const luaL_Reg uwsgi_api[] = {
604 {"log", uwsgi_api_log},
605 {"connection_fd", uwsgi_api_req_fd},
606
607 {"cache_get", uwsgi_api_cache_get},
608 {"cache_set", uwsgi_api_cache_set},
609 {"cache_update", uwsgi_api_cache_update},
610 {"cache_del", uwsgi_api_cache_del},
611 {"cache_exists", uwsgi_api_cache_exists},
612 {"cache_clear", uwsgi_api_cache_clear},
613
614 {"register_signal", uwsgi_api_register_signal},
615 {"register_rpc", uwsgi_api_register_rpc},
616
617 {"websocket_handshake", uwsgi_api_websocket_handshake},
618 {"websocket_recv", uwsgi_api_websocket_recv},
619 {"websocket_recv_nb", uwsgi_api_websocket_recv_nb},
620 {"websocket_send", uwsgi_api_websocket_send},
621 {"websocket_send_from_sharedarea", uwsgi_api_websocket_send_from_sharedarea},
622 {"websocket_send_binary", uwsgi_api_websocket_send_binary},
623 {"websocket_send_binary_from_sharedarea", uwsgi_api_websocket_send_binary_from_sharedarea},
624
625 {"lock", uwsgi_api_lock},
626 {"unlock", uwsgi_api_unlock},
627
628 {"async_sleep", uwsgi_api_async_sleep},
629 {"async_connect", uwsgi_api_async_connect},
630 {"is_connected", uwsgi_api_is_connected},
631 {"close", uwsgi_api_close},
632 {"wait_fd_read", uwsgi_api_wait_fd_read},
633 {"wait_fd_write", uwsgi_api_wait_fd_write},
634 {"ready_fd", uwsgi_api_ready_fd},
635
636 {NULL, NULL}
637 };
638
639
640
uwsgi_lua_input(lua_State * L)641 static int uwsgi_lua_input(lua_State *L) {
642
643 struct wsgi_request *wsgi_req = current_wsgi_req();
644 ssize_t sum = 0;
645
646 int n = lua_gettop(L);
647
648 if (n > 1) {
649 sum = lua_tonumber(L, 2);
650 }
651
652 ssize_t rlen = 0;
653
654 char *buf = uwsgi_request_body_read(wsgi_req, sum, &rlen);
655 if (buf) {
656 lua_pushlstring(L, buf, rlen);
657 return 1;
658 }
659
660 return 0;
661 }
662
uwsgi_lua_init()663 static int uwsgi_lua_init(){
664
665 uwsgi_log("Initializing Lua environment... (%d lua_States)\n", uwsgi.cores);
666
667 ulua.L = uwsgi_malloc( sizeof(lua_State*) * uwsgi.cores );
668
669 // ok the lua engine is ready
670 return 0;
671
672
673 }
674
uwsgi_lua_app()675 static void uwsgi_lua_app() {
676 int i;
677
678 if (!ulua.filename && !ulua.load && !ulua.shell) return;
679
680 for(i=0;i<uwsgi.cores;i++) {
681 ulua.L[i] = luaL_newstate();
682 luaL_openlibs(ulua.L[i]);
683 luaL_newuwsgilib(ulua.L[i], uwsgi_api);
684
685 lua_pushstring(ulua.L[i], UWSGI_VERSION);
686 lua_setfield(ulua.L[i], -2, "version");
687
688 struct uwsgi_string_list *usl = ulua.load;
689 while(usl) {
690 if (luaL_dofile(ulua.L[i], usl->value)) {
691 uwsgi_log("unable to load Lua file %s: %s\n", usl->value, lua_tostring(ulua.L[i], -1));
692 exit(1);
693 }
694 usl = usl->next;
695 }
696
697 if (ulua.filename) {
698 if (luaL_loadfile(ulua.L[i], ulua.filename)) {
699 uwsgi_log("unable to load Lua file %s: %s\n", ulua.filename, lua_tostring(ulua.L[i], -1));
700 exit(1);
701 }
702
703 // use a pcall
704 //lua_call(ulua.L[i], 0, 1);
705 if (lua_pcall(ulua.L[i], 0, 1, 0) != 0) {
706 uwsgi_log("%s\n", lua_tostring(ulua.L[i], -1));
707 exit(1);
708 }
709
710 // if the loaded lua app returns as a table, fetch the
711 // run function.
712 if (lua_istable(ulua.L[i], 2)) {
713 lua_pushstring(ulua.L[i], "run" );
714 lua_gettable(ulua.L[i], 2);
715 lua_replace(ulua.L[i], 2);
716 }
717
718 if (! lua_isfunction(ulua.L[i], 2)) {
719 uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n");
720 exit(1);
721 }
722 }
723
724 }
725 }
726
uwsgi_lua_request(struct wsgi_request * wsgi_req)727 static int uwsgi_lua_request(struct wsgi_request *wsgi_req) {
728
729 int i;
730 const char *http, *http2;
731 size_t slen, slen2;
732 char *ptrbuf;
733 lua_State *L = ulua.L[wsgi_req->async_id];
734
735 if (wsgi_req->async_status == UWSGI_AGAIN) {
736 if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
737 if (lua_type(L, -1) == LUA_TSTRING) {
738 http = lua_tolstring(L, -1, &slen);
739 uwsgi_response_write_body_do(wsgi_req, (char *)http, slen);
740 }
741 lua_pop(L, 1);
742 lua_pushvalue(L, -1);
743 return UWSGI_AGAIN;
744 }
745 goto clear;
746 }
747
748 /* Standard WSAPI request */
749 if (!wsgi_req->uh->pktsize) {
750 uwsgi_log( "Empty lua request. skip.\n");
751 return -1;
752 }
753
754 if (uwsgi_parse_vars(wsgi_req)) {
755 return -1;
756 }
757
758 // put function in the stack
759 //lua_getfield(L, LUA_GLOBALSINDEX, "run");
760 lua_pushvalue(L, -1);
761
762 // put cgi vars in the stack
763
764 lua_newtable(L);
765 lua_pushstring(L, "");
766 lua_setfield(L, -2, "CONTENT_TYPE");
767 for(i=0;i<wsgi_req->var_cnt;i+=2) {
768 lua_pushlstring(L, (char *)wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
769 // transform it in a valid c string TODO this is ugly
770 ptrbuf = wsgi_req->hvec[i].iov_base+wsgi_req->hvec[i].iov_len;
771 *ptrbuf = 0;
772 lua_setfield(L, -2, (char *)wsgi_req->hvec[i].iov_base);
773 }
774
775
776 // put "input" table
777 lua_newtable(L);
778 lua_pushcfunction(L, uwsgi_lua_input);
779 lua_setfield(L, -2, "read");
780 lua_setfield(L, -2, "input");
781
782 #ifdef UWSGI_DEBUG
783 uwsgi_log("stack pos %d\n", lua_gettop(L));
784 #endif
785
786 // call function
787 i = lua_pcall(L, 1, 3, 0);
788 if (i != 0) {
789 uwsgi_log("%s\n", lua_tostring(L, -1));
790 lua_pop(L, 1);
791 lua_pushvalue(L, -1);
792 goto clear2;
793 }
794
795 //uwsgi_log("%d %s %s %s\n",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1)));
796
797 // send status
798 if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
799 http = lua_tolstring(L, -3, &slen);
800 if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen))
801 goto clear2;
802 }
803 else {
804 uwsgi_log("[uwsgi-lua] invalid response status !!!\n");
805 // let's continue
806 }
807
808 // send headers
809
810 lua_pushnil(L);
811 while(lua_next(L, -3) != 0) {
812 http = lua_tolstring(L, -2, &slen);
813
814 if (lua_type(L, -1) == LUA_TTABLE) {
815 for (i = 1; /*empty*/ ; ++i) {
816 lua_rawgeti(L, -1, i);
817
818 if (lua_isnil(L, -1)) {
819 lua_pop(L, 1);
820 break;
821 }
822
823 http2 = lua_tolstring(L, -1, &slen2);
824 uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
825 lua_pop(L, 1);
826 }
827 }
828 else {
829 http2 = lua_tolstring(L, -1, &slen2);
830 uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
831 }
832 lua_pop(L, 1);
833 }
834
835 // send body with coroutine
836 lua_pushvalue(L, -1);
837
838 while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
839 if (lua_type(L, -1) == LUA_TSTRING) {
840 http = lua_tolstring(L, -1, &slen);
841 uwsgi_response_write_body_do(wsgi_req, (char *)http, slen);
842 }
843 lua_pop(L, 1);
844 lua_pushvalue(L, -1);
845 if (uwsgi.async > 1) {
846 return UWSGI_AGAIN;
847 }
848 }
849 clear:
850 lua_pop(L, 4);
851 clear2:
852 // set frequency
853 if (!ulua.gc_freq || uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests % ulua.gc_freq == 0) {
854 lua_gc(L, LUA_GCCOLLECT, 0);
855 }
856
857 return UWSGI_OK;
858
859 }
860
uwsgi_lua_after_request(struct wsgi_request * wsgi_req)861 static void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) {
862
863 log_request(wsgi_req);
864 }
865
866
uwsgi_lua_magic(char * mountpoint,char * lazy)867 static int uwsgi_lua_magic(char *mountpoint, char *lazy) {
868
869 if (!strcmp(lazy+strlen(lazy)-4, ".lua")) {
870 ulua.filename = lazy;
871 return 1;
872 }
873 else if (!strcmp(lazy+strlen(lazy)-3, ".ws")) {
874 ulua.filename = lazy;
875 return 1;
876 }
877
878
879 return 0;
880 }
881
uwsgi_lua_code_string(char * id,char * code,char * func,char * key,uint16_t keylen)882 static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_t keylen) {
883
884 static struct lua_State *L = NULL;
885
886 if (!L) {
887 L = luaL_newstate();
888 luaL_openlibs(L);
889 if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) {
890 uwsgi_log("unable to load file %s: %s\n", code, lua_tostring(L, -1));
891 lua_close(L);
892 L = NULL;
893 return NULL;
894 }
895 lua_getglobal(L, func);
896 if (!lua_isfunction(L,-1)) {
897 uwsgi_log("unable to find %s function in lua file %s\n", func, code);
898 lua_close(L);
899 L = NULL;
900 return NULL;
901 }
902 lua_pushnil(L);
903 }
904
905
906 lua_pop(L, 1);
907
908 lua_pushvalue(L, -1);
909 lua_pushlstring(L, key, keylen);
910
911 #ifdef UWSGI_DEBUG
912 uwsgi_log("stack pos %d %.*s\n", lua_gettop(L), keylen, key);
913 #endif
914
915 if (lua_pcall(L, 1, 1, 0) != 0) {
916 uwsgi_log("error running function `f': %s",
917 lua_tostring(L, -1));
918 return NULL;
919
920 }
921
922 if (lua_isstring(L, -1)) {
923 const char *ret = lua_tolstring(L, -1, NULL);
924 return (char *)ret;
925 }
926
927 return NULL;
928 }
929
uwsgi_lua_signal_handler(uint8_t sig,void * handler)930 static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
931
932 struct wsgi_request *wsgi_req = current_wsgi_req();
933
934 lua_State *L = ulua.L[wsgi_req->async_id];
935
936 #ifdef UWSGI_DEBUG
937 uwsgi_log("managing signal handler on core %d\n", wsgi_req->async_id);
938 #endif
939
940 lua_rawgeti(L, LUA_REGISTRYINDEX, (long) handler);
941
942 lua_pushnumber(L, sig);
943
944 if (lua_pcall(L, 1, 1, 0) != 0) {
945 uwsgi_log("error running function `f': %s",
946 lua_tostring(L, -1));
947
948 return -1;
949
950 }
951
952 return 0;
953
954 }
955
uwsgi_lua_rpc(void * func,uint8_t argc,char ** argv,uint16_t argvs[],char ** buffer)956 static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
957
958 uint8_t i;
959 const char *sv;
960 size_t sl;
961 long lfunc = (long) func;
962 int ifunc = lfunc;
963
964 struct wsgi_request *wsgi_req = current_wsgi_req();
965
966 lua_State *L = ulua.L[wsgi_req->async_id];
967
968 #ifdef UWSGI_DEBUG
969 uwsgi_log("get function %d\n", ifunc);
970 #endif
971 lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc);
972
973 for(i=0;i<argc;i++) {
974 lua_pushlstring(L, argv[i], argvs[i]);
975 }
976
977 if (lua_pcall(L, argc, 1, 0) != 0) {
978 uwsgi_log("error running function `f': %s", lua_tostring(L, -1));
979 return 0;
980 }
981
982
983 sv = lua_tolstring(L, -1, &sl);
984
985 #ifdef UWSGI_DEBUG
986 uwsgi_log("sv = %s sl = %lu\n", sv, (unsigned long) sl);
987 #endif
988 if (sl > 0) {
989 *buffer = uwsgi_malloc(sl);
990 memcpy(*buffer, sv, sl);
991 lua_pop(L, 1);
992 return sl;
993 }
994
995 lua_pop(L, 1);
996 return 0;
997
998 }
999
uwsgi_lua_configurator_array(lua_State * L)1000 static void uwsgi_lua_configurator_array(lua_State *L) {
1001
1002 int i;
1003 int n = lua_rawlen(L, -3);
1004
1005 for(i=1;i<=n;i++) {
1006 lua_rawgeti(L, 1, i);
1007 if (lua_istable(L, -1)) {
1008 lua_pushnil(L);
1009 while (lua_next(L, -2) != 0) {
1010 char *key = uwsgi_str((char *)lua_tostring(L, -2));
1011 char *value = uwsgi_str((char *)lua_tostring(L, -1));
1012 add_exported_option(key, value, 0);
1013 lua_pop(L, 1);
1014 }
1015 }
1016 }
1017 }
1018
1019
uwsgi_lua_configurator(char * filename,char * magic_table[])1020 static void uwsgi_lua_configurator(char *filename, char *magic_table[]) {
1021 size_t len = 0;
1022 uwsgi_log_initial("[uWSGI] getting Lua configuration from %s\n", filename);
1023 char *code = uwsgi_open_and_read(filename, &len, 1, magic_table);
1024 lua_State *L = luaL_newstate();
1025 if (!L) {
1026 uwsgi_log("unable to initialize Lua state for configuration\n");
1027 exit(1);
1028 }
1029 luaL_openlibs(L);
1030 if (luaL_dostring(L, code) != 0) {
1031 uwsgi_log("error running Lua configurator: %s\n", lua_tostring(L, -1));
1032 exit(1);
1033 }
1034 free(code);
1035
1036 if (!lua_istable(L, -1)) {
1037 uwsgi_log("Lua configurator has to return a table !!!\n");
1038 exit(1);
1039 }
1040
1041 lua_pushnil(L);
1042 // we always use uwsgi_str to avoid GC destroying our strings
1043 // and to be able to call lua_close at the end
1044 while (lua_next(L, -2) != 0) {
1045 // array ?
1046 if (lua_isnumber(L, -2)) {
1047 uwsgi_lua_configurator_array(L);
1048 break;
1049 }
1050 // dictionary
1051 else {
1052 char *key = uwsgi_str((char *)lua_tostring(L, -2));
1053 if (lua_istable(L, -1)) {
1054 lua_pushnil(L);
1055 while (lua_next(L, -2) != 0) {
1056 char *value = uwsgi_str((char *)lua_tostring(L, -1));
1057 add_exported_option(key, value, 0);
1058 lua_pop(L, 1);
1059 }
1060 }
1061 else {
1062 char *value = uwsgi_str((char *)lua_tostring(L, -1));
1063 add_exported_option(key, value, 0);
1064 }
1065 }
1066 lua_pop(L, 1);
1067 }
1068
1069 // this will destroy the whole Lua state
1070 lua_close(L);
1071 }
1072
uwsgi_register_lua_features()1073 static void uwsgi_register_lua_features() {
1074 uwsgi_register_configurator(".lua", uwsgi_lua_configurator);
1075 }
1076
uwsgi_lua_hijack(void)1077 static void uwsgi_lua_hijack(void) {
1078 if (ulua.shell && uwsgi.mywid == 1) {
1079 uwsgi.workers[uwsgi.mywid].hijacked = 1;
1080 uwsgi.workers[uwsgi.mywid].hijacked_count++;
1081 // re-map stdin to stdout and stderr if we are logging to a file
1082 if (uwsgi.logfile) {
1083 if (dup2(0, 1) < 0) {
1084 uwsgi_error("dup2()");
1085 }
1086 if (dup2(0, 2) < 0) {
1087 uwsgi_error("dup2()");
1088 }
1089 }
1090 int ret = -1;
1091 // run in the first state
1092 lua_State *L = ulua.L[0];
1093 lua_getglobal(L, "debug");
1094 lua_getfield(L, -1, "debug");
1095 ret = lua_pcall(L, 0, 0, 0);
1096 if (ret == 0) {
1097 exit(UWSGI_QUIET_CODE);
1098 }
1099 exit(0);
1100 }
1101
1102 }
1103
1104
1105 struct uwsgi_plugin lua_plugin = {
1106
1107 .name = "lua",
1108 .modifier1 = 6,
1109 .init = uwsgi_lua_init,
1110 .options = uwsgi_lua_options,
1111 .request = uwsgi_lua_request,
1112 .after_request = uwsgi_lua_after_request,
1113 .init_apps = uwsgi_lua_app,
1114 .magic = uwsgi_lua_magic,
1115 .signal_handler = uwsgi_lua_signal_handler,
1116
1117 .hijack_worker = uwsgi_lua_hijack,
1118
1119 .code_string = uwsgi_lua_code_string,
1120 .rpc = uwsgi_lua_rpc,
1121
1122 .on_load = uwsgi_register_lua_features,
1123 };
1124
1125