Line data Source code
1 : #ifndef DDEBUG
2 : #define DDEBUG 0
3 : #endif
4 : #include "ddebug.h"
5 :
6 :
7 : #include "ngx_http_lua_output.h"
8 : #include "ngx_http_lua_util.h"
9 : #include "ngx_http_lua_contentby.h"
10 : #include <math.h>
11 :
12 :
13 : static int ngx_http_lua_ngx_say(lua_State *L);
14 : static int ngx_http_lua_ngx_print(lua_State *L);
15 : static int ngx_http_lua_ngx_flush(lua_State *L);
16 : static int ngx_http_lua_ngx_eof(lua_State *L);
17 : static int ngx_http_lua_ngx_send_headers(lua_State *L);
18 : static int ngx_http_lua_ngx_echo(lua_State *L, unsigned newline);
19 : static void ngx_http_lua_flush_cleanup(void *data);
20 :
21 :
22 : static int
23 0 : ngx_http_lua_ngx_print(lua_State *L)
24 : {
25 : dd("calling lua print");
26 0 : return ngx_http_lua_ngx_echo(L, 0);
27 : }
28 :
29 :
30 : static int
31 1 : ngx_http_lua_ngx_say(lua_State *L)
32 : {
33 : dd("calling");
34 1 : return ngx_http_lua_ngx_echo(L, 1);
35 : }
36 :
37 :
38 : static int
39 1 : ngx_http_lua_ngx_echo(lua_State *L, unsigned newline)
40 : {
41 : ngx_http_request_t *r;
42 : ngx_http_lua_ctx_t *ctx;
43 : const char *p;
44 : size_t len;
45 : size_t size;
46 : ngx_buf_t *b;
47 : ngx_chain_t *cl;
48 : ngx_int_t rc;
49 : int i;
50 : int nargs;
51 : int type;
52 : const char *msg;
53 :
54 1 : r = ngx_http_lua_get_req(L);
55 1 : if (r == NULL) {
56 0 : return luaL_error(L, "no request object found");
57 : }
58 :
59 1 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
60 :
61 1 : if (ctx == NULL) {
62 0 : return luaL_error(L, "no request ctx found");
63 : }
64 :
65 1 : ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
66 : | NGX_HTTP_LUA_CONTEXT_ACCESS
67 : | NGX_HTTP_LUA_CONTEXT_CONTENT);
68 :
69 1 : if (ctx->acquired_raw_req_socket) {
70 0 : lua_pushnil(L);
71 0 : lua_pushliteral(L, "raw request socket acquired");
72 0 : return 2;
73 : }
74 :
75 1 : if (r->header_only) {
76 0 : lua_pushnil(L);
77 0 : lua_pushliteral(L, "header only");
78 0 : return 2;
79 : }
80 :
81 1 : if (ctx->eof) {
82 0 : lua_pushnil(L);
83 0 : lua_pushliteral(L, "seen eof");
84 0 : return 2;
85 : }
86 :
87 1 : nargs = lua_gettop(L);
88 1 : size = 0;
89 :
90 2 : for (i = 1; i <= nargs; i++) {
91 :
92 1 : type = lua_type(L, i);
93 :
94 1 : switch (type) {
95 1 : case LUA_TNUMBER:
96 : case LUA_TSTRING:
97 :
98 1 : lua_tolstring(L, i, &len);
99 1 : size += len;
100 1 : break;
101 :
102 0 : case LUA_TNIL:
103 :
104 0 : size += sizeof("nil") - 1;
105 0 : break;
106 :
107 0 : case LUA_TBOOLEAN:
108 :
109 0 : if (lua_toboolean(L, i)) {
110 0 : size += sizeof("true") - 1;
111 :
112 : } else {
113 0 : size += sizeof("false") - 1;
114 : }
115 :
116 0 : break;
117 :
118 0 : case LUA_TTABLE:
119 :
120 0 : size += ngx_http_lua_calc_strlen_in_table(L, i, i,
121 : 0 /* strict */);
122 0 : break;
123 :
124 0 : case LUA_TLIGHTUSERDATA:
125 :
126 : dd("userdata: %p", lua_touserdata(L, i));
127 :
128 0 : if (lua_touserdata(L, i) == NULL) {
129 0 : size += sizeof("null") - 1;
130 0 : break;
131 : }
132 :
133 0 : continue;
134 :
135 0 : default:
136 :
137 0 : msg = lua_pushfstring(L, "string, number, boolean, nil, "
138 : "ngx.null, or array table expected, "
139 : "but got %s", lua_typename(L, type));
140 :
141 0 : return luaL_argerror(L, i, msg);
142 : }
143 : }
144 :
145 1 : if (newline) {
146 1 : size += sizeof("\n") - 1;
147 : }
148 :
149 1 : if (size == 0) {
150 0 : rc = ngx_http_lua_send_header_if_needed(r, ctx);
151 0 : if (rc == NGX_ERROR || rc > NGX_OK) {
152 0 : lua_pushnil(L);
153 0 : lua_pushliteral(L, "nginx output filter error");
154 0 : return 2;
155 : }
156 :
157 0 : lua_pushinteger(L, 1);
158 0 : return 1;
159 : }
160 :
161 1 : ctx->seen_body_data = 1;
162 :
163 1 : cl = ngx_http_lua_chain_get_free_buf(r->connection->log, r->pool,
164 : &ctx->free_bufs, size);
165 :
166 1 : if (cl == NULL) {
167 0 : return luaL_error(L, "no memory");
168 : }
169 :
170 1 : b = cl->buf;
171 :
172 2 : for (i = 1; i <= nargs; i++) {
173 1 : type = lua_type(L, i);
174 1 : switch (type) {
175 1 : case LUA_TNUMBER:
176 : case LUA_TSTRING:
177 1 : p = lua_tolstring(L, i, &len);
178 1 : b->last = ngx_copy(b->last, (u_char *) p, len);
179 1 : break;
180 :
181 0 : case LUA_TNIL:
182 0 : *b->last++ = 'n';
183 0 : *b->last++ = 'i';
184 0 : *b->last++ = 'l';
185 0 : break;
186 :
187 0 : case LUA_TBOOLEAN:
188 0 : if (lua_toboolean(L, i)) {
189 0 : *b->last++ = 't';
190 0 : *b->last++ = 'r';
191 0 : *b->last++ = 'u';
192 0 : *b->last++ = 'e';
193 :
194 : } else {
195 0 : *b->last++ = 'f';
196 0 : *b->last++ = 'a';
197 0 : *b->last++ = 'l';
198 0 : *b->last++ = 's';
199 0 : *b->last++ = 'e';
200 : }
201 :
202 0 : break;
203 :
204 0 : case LUA_TTABLE:
205 0 : b->last = ngx_http_lua_copy_str_in_table(L, i, b->last);
206 0 : break;
207 :
208 0 : case LUA_TLIGHTUSERDATA:
209 0 : *b->last++ = 'n';
210 0 : *b->last++ = 'u';
211 0 : *b->last++ = 'l';
212 0 : *b->last++ = 'l';
213 0 : break;
214 :
215 0 : default:
216 0 : return luaL_error(L, "impossible to reach here");
217 : }
218 : }
219 :
220 1 : if (newline) {
221 1 : *b->last++ = '\n';
222 : }
223 :
224 : #if 0
225 : if (b->last != b->end) {
226 : return luaL_error(L, "buffer error: %p != %p", b->last, b->end);
227 : }
228 : #endif
229 :
230 1 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
231 : newline ? "lua say response" : "lua print response");
232 :
233 1 : rc = ngx_http_lua_send_chain_link(r, ctx, cl);
234 :
235 1 : if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
236 0 : lua_pushnil(L);
237 0 : lua_pushliteral(L, "nginx output filter error");
238 0 : return 2;
239 : }
240 :
241 : dd("downstream write: %d, buf len: %d", (int) rc,
242 : (int) (b->last - b->pos));
243 :
244 1 : lua_pushinteger(L, 1);
245 1 : return 1;
246 : }
247 :
248 :
249 : size_t
250 0 : ngx_http_lua_calc_strlen_in_table(lua_State *L, int index, int arg_i,
251 : unsigned strict)
252 : {
253 : double key;
254 : int max;
255 : int i;
256 : int type;
257 : size_t size;
258 : size_t len;
259 : const char *msg;
260 :
261 0 : if (index < 0) {
262 0 : index = lua_gettop(L) + index + 1;
263 : }
264 :
265 : dd("table index: %d", index);
266 :
267 0 : max = 0;
268 :
269 0 : lua_pushnil(L); /* stack: table key */
270 0 : while (lua_next(L, index) != 0) { /* stack: table key value */
271 : dd("key type: %s", luaL_typename(L, -2));
272 :
273 0 : if (lua_type(L, -2) == LUA_TNUMBER) {
274 :
275 0 : key = lua_tonumber(L, -2);
276 :
277 : dd("key value: %d", (int) key);
278 :
279 0 : if (floor(key) == key && key >= 1) {
280 0 : if (key > max) {
281 0 : max = (int) key;
282 : }
283 :
284 0 : lua_pop(L, 1); /* stack: table key */
285 0 : continue;
286 : }
287 : }
288 :
289 : /* not an array (non positive integer key) */
290 0 : lua_pop(L, 2); /* stack: table */
291 :
292 0 : luaL_argerror(L, arg_i, "non-array table found");
293 0 : return 0;
294 : }
295 :
296 0 : size = 0;
297 :
298 0 : for (i = 1; i <= max; i++) {
299 0 : lua_rawgeti(L, index, i); /* stack: table value */
300 0 : type = lua_type(L, -1);
301 :
302 0 : switch (type) {
303 0 : case LUA_TNUMBER:
304 : case LUA_TSTRING:
305 :
306 0 : lua_tolstring(L, -1, &len);
307 0 : size += len;
308 0 : break;
309 :
310 0 : case LUA_TNIL:
311 :
312 0 : if (strict) {
313 0 : goto bad_type;
314 : }
315 :
316 0 : size += sizeof("nil") - 1;
317 0 : break;
318 :
319 0 : case LUA_TBOOLEAN:
320 :
321 0 : if (strict) {
322 0 : goto bad_type;
323 : }
324 :
325 0 : if (lua_toboolean(L, -1)) {
326 0 : size += sizeof("true") - 1;
327 :
328 : } else {
329 0 : size += sizeof("false") - 1;
330 : }
331 :
332 0 : break;
333 :
334 0 : case LUA_TTABLE:
335 :
336 0 : size += ngx_http_lua_calc_strlen_in_table(L, -1, arg_i, strict);
337 0 : break;
338 :
339 0 : case LUA_TLIGHTUSERDATA:
340 :
341 0 : if (strict) {
342 0 : goto bad_type;
343 : }
344 :
345 0 : if (lua_touserdata(L, -1) == NULL) {
346 0 : size += sizeof("null") - 1;
347 0 : break;
348 : }
349 :
350 0 : continue;
351 :
352 : default:
353 :
354 0 : bad_type:
355 :
356 0 : msg = lua_pushfstring(L, "bad data type %s found",
357 : lua_typename(L, type));
358 0 : return luaL_argerror(L, arg_i, msg);
359 : }
360 :
361 0 : lua_pop(L, 1); /* stack: table */
362 : }
363 :
364 0 : return size;
365 : }
366 :
367 :
368 : u_char *
369 0 : ngx_http_lua_copy_str_in_table(lua_State *L, int index, u_char *dst)
370 : {
371 : double key;
372 : int max;
373 : int i;
374 : int type;
375 : size_t len;
376 : u_char *p;
377 :
378 0 : if (index < 0) {
379 0 : index = lua_gettop(L) + index + 1;
380 : }
381 :
382 0 : max = 0;
383 :
384 0 : lua_pushnil(L); /* stack: table key */
385 0 : while (lua_next(L, index) != 0) { /* stack: table key value */
386 0 : key = lua_tonumber(L, -2);
387 0 : if (key > max) {
388 0 : max = (int) key;
389 : }
390 :
391 0 : lua_pop(L, 1); /* stack: table key */
392 : }
393 :
394 0 : for (i = 1; i <= max; i++) {
395 0 : lua_rawgeti(L, index, i); /* stack: table value */
396 0 : type = lua_type(L, -1);
397 0 : switch (type) {
398 0 : case LUA_TNUMBER:
399 : case LUA_TSTRING:
400 0 : p = (u_char *) lua_tolstring(L, -1, &len);
401 0 : dst = ngx_copy(dst, p, len);
402 0 : break;
403 :
404 0 : case LUA_TNIL:
405 0 : *dst++ = 'n';
406 0 : *dst++ = 'i';
407 0 : *dst++ = 'l';
408 0 : break;
409 :
410 0 : case LUA_TBOOLEAN:
411 0 : if (lua_toboolean(L, -1)) {
412 0 : *dst++ = 't';
413 0 : *dst++ = 'r';
414 0 : *dst++ = 'u';
415 0 : *dst++ = 'e';
416 :
417 : } else {
418 0 : *dst++ = 'f';
419 0 : *dst++ = 'a';
420 0 : *dst++ = 'l';
421 0 : *dst++ = 's';
422 0 : *dst++ = 'e';
423 : }
424 :
425 0 : break;
426 :
427 0 : case LUA_TTABLE:
428 0 : dst = ngx_http_lua_copy_str_in_table(L, -1, dst);
429 0 : break;
430 :
431 0 : case LUA_TLIGHTUSERDATA:
432 :
433 0 : *dst++ = 'n';
434 0 : *dst++ = 'u';
435 0 : *dst++ = 'l';
436 0 : *dst++ = 'l';
437 0 : break;
438 :
439 0 : default:
440 0 : luaL_error(L, "impossible to reach here");
441 0 : return NULL;
442 : }
443 :
444 0 : lua_pop(L, 1); /* stack: table */
445 : }
446 :
447 0 : return dst;
448 : }
449 :
450 :
451 : /**
452 : * Force flush out response content
453 : * */
454 : static int
455 0 : ngx_http_lua_ngx_flush(lua_State *L)
456 : {
457 : ngx_http_request_t *r;
458 : ngx_http_lua_ctx_t *ctx;
459 : ngx_chain_t *cl;
460 : ngx_int_t rc;
461 : int n;
462 0 : unsigned wait = 0;
463 : ngx_event_t *wev;
464 : ngx_http_core_loc_conf_t *clcf;
465 : ngx_http_lua_co_ctx_t *coctx;
466 :
467 0 : n = lua_gettop(L);
468 0 : if (n > 1) {
469 0 : return luaL_error(L, "attempt to pass %d arguments, but accepted 0 "
470 : "or 1", n);
471 : }
472 :
473 0 : r = ngx_http_lua_get_req(L);
474 :
475 0 : if (n == 1 && r == r->main) {
476 0 : luaL_checktype(L, 1, LUA_TBOOLEAN);
477 0 : wait = lua_toboolean(L, 1);
478 : }
479 :
480 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
481 0 : if (ctx == NULL) {
482 0 : return luaL_error(L, "no request ctx found");
483 : }
484 :
485 0 : ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
486 : | NGX_HTTP_LUA_CONTEXT_ACCESS
487 : | NGX_HTTP_LUA_CONTEXT_CONTENT);
488 :
489 0 : if (ctx->acquired_raw_req_socket) {
490 0 : lua_pushnil(L);
491 0 : lua_pushliteral(L, "raw request socket acquired");
492 0 : return 2;
493 : }
494 :
495 0 : coctx = ctx->cur_co_ctx;
496 0 : if (coctx == NULL) {
497 0 : return luaL_error(L, "no co ctx found");
498 : }
499 :
500 0 : if (r->header_only) {
501 0 : lua_pushnil(L);
502 0 : lua_pushliteral(L, "header only");
503 0 : return 2;
504 : }
505 :
506 0 : if (ctx->eof) {
507 0 : lua_pushnil(L);
508 0 : lua_pushliteral(L, "seen eof");
509 0 : return 2;
510 : }
511 :
512 0 : if (ctx->buffering) {
513 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
514 : "lua http 1.0 buffering makes ngx.flush() a no-op");
515 :
516 0 : lua_pushnil(L);
517 0 : lua_pushliteral(L, "buffering");
518 0 : return 2;
519 : }
520 :
521 : #if 1
522 0 : if ((!r->header_sent && !ctx->header_sent)
523 0 : || (!ctx->seen_body_data && !wait))
524 : {
525 0 : lua_pushnil(L);
526 0 : lua_pushliteral(L, "nothing to flush");
527 0 : return 2;
528 : }
529 : #endif
530 :
531 0 : cl = ngx_http_lua_get_flush_chain(r, ctx);
532 0 : if (cl == NULL) {
533 0 : return luaL_error(L, "no memory");
534 : }
535 :
536 0 : rc = ngx_http_lua_send_chain_link(r, ctx, cl);
537 :
538 : dd("send chain: %d", (int) rc);
539 :
540 0 : if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
541 0 : lua_pushnil(L);
542 0 : lua_pushliteral(L, "nginx output filter error");
543 0 : return 2;
544 : }
545 :
546 : dd("wait:%d, rc:%d, buffered:0x%x", wait, (int) rc,
547 : r->connection->buffered);
548 :
549 0 : wev = r->connection->write;
550 :
551 0 : if (wait && (r->connection->buffered & NGX_HTTP_LOWLEVEL_BUFFERED
552 0 : || wev->delayed))
553 : {
554 0 : ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
555 : "lua flush requires waiting: buffered 0x%uxd, "
556 : "delayed:%d", (unsigned) r->connection->buffered,
557 : wev->delayed);
558 :
559 0 : coctx->flushing = 1;
560 0 : ctx->flushing_coros++;
561 :
562 0 : if (ctx->entered_content_phase) {
563 : /* mimic ngx_http_set_write_handler */
564 0 : r->write_event_handler = ngx_http_lua_content_wev_handler;
565 :
566 : } else {
567 0 : r->write_event_handler = ngx_http_core_run_phases;
568 : }
569 :
570 0 : clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
571 :
572 0 : if (!wev->delayed) {
573 0 : ngx_add_timer(wev, clcf->send_timeout);
574 : }
575 :
576 0 : if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
577 0 : if (wev->timer_set) {
578 0 : wev->delayed = 0;
579 0 : ngx_del_timer(wev);
580 : }
581 :
582 0 : lua_pushnil(L);
583 0 : lua_pushliteral(L, "connection broken");
584 0 : return 2;
585 : }
586 :
587 0 : ngx_http_lua_cleanup_pending_operation(ctx->cur_co_ctx);
588 0 : coctx->cleanup = ngx_http_lua_flush_cleanup;
589 0 : coctx->data = r;
590 :
591 0 : return lua_yield(L, 0);
592 : }
593 :
594 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
595 : "lua flush asynchronously");
596 :
597 0 : lua_pushinteger(L, 1);
598 0 : return 1;
599 : }
600 :
601 :
602 : /**
603 : * Send last_buf, terminate output stream
604 : * */
605 : static int
606 0 : ngx_http_lua_ngx_eof(lua_State *L)
607 : {
608 : ngx_http_request_t *r;
609 : ngx_http_lua_ctx_t *ctx;
610 : ngx_int_t rc;
611 :
612 0 : r = ngx_http_lua_get_req(L);
613 0 : if (r == NULL) {
614 0 : return luaL_error(L, "no request object found");
615 : }
616 :
617 0 : if (lua_gettop(L) != 0) {
618 0 : return luaL_error(L, "no argument is expected");
619 : }
620 :
621 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
622 0 : if (ctx == NULL) {
623 0 : return luaL_error(L, "no ctx found");
624 : }
625 :
626 0 : if (ctx->acquired_raw_req_socket) {
627 0 : lua_pushnil(L);
628 0 : lua_pushliteral(L, "raw request socket acquired");
629 0 : return 2;
630 : }
631 :
632 0 : if (ctx->eof) {
633 0 : lua_pushnil(L);
634 0 : lua_pushliteral(L, "seen eof");
635 0 : return 2;
636 : }
637 :
638 0 : ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
639 : | NGX_HTTP_LUA_CONTEXT_ACCESS
640 : | NGX_HTTP_LUA_CONTEXT_CONTENT);
641 :
642 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
643 : "lua send eof");
644 :
645 0 : rc = ngx_http_lua_send_chain_link(r, ctx, NULL /* indicate last_buf */);
646 :
647 : dd("send chain: %d", (int) rc);
648 :
649 0 : if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
650 0 : lua_pushnil(L);
651 0 : lua_pushliteral(L, "nginx output filter error");
652 0 : return 2;
653 : }
654 :
655 0 : lua_pushinteger(L, 1);
656 0 : return 1;
657 : }
658 :
659 :
660 : void
661 18 : ngx_http_lua_inject_output_api(lua_State *L)
662 : {
663 18 : lua_pushcfunction(L, ngx_http_lua_ngx_send_headers);
664 18 : lua_setfield(L, -2, "send_headers");
665 :
666 18 : lua_pushcfunction(L, ngx_http_lua_ngx_print);
667 18 : lua_setfield(L, -2, "print");
668 :
669 18 : lua_pushcfunction(L, ngx_http_lua_ngx_say);
670 18 : lua_setfield(L, -2, "say");
671 :
672 18 : lua_pushcfunction(L, ngx_http_lua_ngx_flush);
673 18 : lua_setfield(L, -2, "flush");
674 :
675 18 : lua_pushcfunction(L, ngx_http_lua_ngx_eof);
676 18 : lua_setfield(L, -2, "eof");
677 18 : }
678 :
679 :
680 : /**
681 : * Send out headers
682 : * */
683 : static int
684 0 : ngx_http_lua_ngx_send_headers(lua_State *L)
685 : {
686 : ngx_int_t rc;
687 : ngx_http_request_t *r;
688 : ngx_http_lua_ctx_t *ctx;
689 :
690 0 : r = ngx_http_lua_get_req(L);
691 0 : if (r == NULL) {
692 0 : return luaL_error(L, "no request found");
693 : }
694 :
695 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
696 0 : if (ctx == NULL) {
697 0 : return luaL_error(L, "no ctx found");
698 : }
699 :
700 0 : ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
701 : | NGX_HTTP_LUA_CONTEXT_ACCESS
702 : | NGX_HTTP_LUA_CONTEXT_CONTENT);
703 :
704 0 : if (!r->header_sent && !ctx->header_sent) {
705 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
706 : "lua send headers");
707 :
708 0 : rc = ngx_http_lua_send_header_if_needed(r, ctx);
709 0 : if (rc == NGX_ERROR || rc > NGX_OK) {
710 0 : lua_pushnil(L);
711 0 : lua_pushliteral(L, "nginx output filter error");
712 0 : return 2;
713 : }
714 : }
715 :
716 0 : lua_pushinteger(L, 1);
717 0 : return 1;
718 : }
719 :
720 :
721 : ngx_int_t
722 0 : ngx_http_lua_flush_resume_helper(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx)
723 : {
724 : int n;
725 : lua_State *vm;
726 : ngx_int_t rc;
727 : ngx_uint_t nreqs;
728 : ngx_connection_t *c;
729 :
730 0 : c = r->connection;
731 :
732 0 : ctx->cur_co_ctx->cleanup = NULL;
733 :
734 : /* push the return values */
735 :
736 0 : if (c->timedout) {
737 0 : lua_pushnil(ctx->cur_co_ctx->co);
738 0 : lua_pushliteral(ctx->cur_co_ctx->co, "timeout");
739 0 : n = 2;
740 :
741 0 : } else if (c->error) {
742 0 : lua_pushnil(ctx->cur_co_ctx->co);
743 0 : lua_pushliteral(ctx->cur_co_ctx->co, "client aborted");
744 0 : n = 2;
745 :
746 : } else {
747 0 : lua_pushinteger(ctx->cur_co_ctx->co, 1);
748 0 : n = 1;
749 : }
750 :
751 0 : vm = ngx_http_lua_get_lua_vm(r, ctx);
752 0 : nreqs = c->requests;
753 :
754 0 : rc = ngx_http_lua_run_thread(vm, r, ctx, n);
755 :
756 0 : ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
757 : "lua run thread returned %d", rc);
758 :
759 0 : if (rc == NGX_AGAIN) {
760 0 : return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs);
761 : }
762 :
763 0 : if (rc == NGX_DONE) {
764 0 : ngx_http_lua_finalize_request(r, NGX_DONE);
765 0 : return ngx_http_lua_run_posted_threads(c, vm, r, ctx, nreqs);
766 : }
767 :
768 : /* rc == NGX_ERROR || rc >= NGX_OK */
769 :
770 0 : if (ctx->entered_content_phase) {
771 0 : ngx_http_lua_finalize_request(r, rc);
772 0 : return NGX_DONE;
773 : }
774 :
775 0 : return rc;
776 : }
777 :
778 :
779 : static void
780 0 : ngx_http_lua_flush_cleanup(void *data)
781 : {
782 : ngx_http_request_t *r;
783 : ngx_event_t *wev;
784 : ngx_http_lua_ctx_t *ctx;
785 0 : ngx_http_lua_co_ctx_t *coctx = data;
786 :
787 0 : coctx->flushing = 0;
788 :
789 0 : r = coctx->data;
790 0 : if (r == NULL) {
791 0 : return;
792 : }
793 :
794 0 : wev = r->connection->write;
795 :
796 0 : if (wev && wev->timer_set) {
797 0 : ngx_del_timer(wev);
798 : }
799 :
800 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
801 0 : if (ctx == NULL) {
802 0 : return;
803 : }
804 :
805 0 : ctx->flushing_coros--;
806 : }
807 :
808 : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|