static ngx_int_t ngx_stream_lua_socket_udp_resume(ngx_stream_session_t *s, ngx_stream_lua_ctx_t *ctx) { int nret; lua_State *vm; ngx_int_t rc; ngx_connection_t *c; ngx_stream_lua_co_ctx_t *coctx; ngx_stream_lua_socket_udp_upstream_t *u; ctx->resume_handler = ngx_stream_lua_wev_handler; ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream lua udp operation done, resuming lua thread"); coctx = ctx->cur_co_ctx; #if 0 ngx_stream_lua_probe_info("udp resume"); #endif u = coctx->data; ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream lua udp socket calling prepare retvals handler %p, " "u:%p", u->prepare_retvals, u); nret = u->prepare_retvals(s, u, ctx->cur_co_ctx->co); if (nret == NGX_AGAIN) { return NGX_DONE; } c = s->connection; vm = ngx_stream_lua_get_lua_vm(s, ctx); rc = ngx_stream_lua_run_thread(vm, s, ctx, nret); ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream lua run thread returned %d", rc); if (rc == NGX_AGAIN) { return ngx_stream_lua_run_posted_threads(c, vm, s, ctx); } if (rc == NGX_DONE) { ngx_stream_lua_finalize_session(s, NGX_DONE); return ngx_stream_lua_run_posted_threads(c, vm, s, ctx); } if (ctx->entered_content_phase) { ngx_stream_lua_finalize_session(s, rc); return NGX_DONE; } return rc; }
ngx_int_t ngx_stream_lua_flush_resume_helper(ngx_stream_session_t *s, ngx_stream_lua_ctx_t *ctx) { int n; lua_State *vm; ngx_int_t rc; ngx_connection_t *c; c = s->connection; ctx->cur_co_ctx->cleanup = NULL; /* push the return values */ if (c->timedout) { lua_pushnil(ctx->cur_co_ctx->co); lua_pushliteral(ctx->cur_co_ctx->co, "timeout"); n = 2; } else if (c->error) { lua_pushnil(ctx->cur_co_ctx->co); lua_pushliteral(ctx->cur_co_ctx->co, "client aborted"); n = 2; } else { lua_pushinteger(ctx->cur_co_ctx->co, 1); n = 1; } vm = ngx_stream_lua_get_lua_vm(s, ctx); rc = ngx_stream_lua_run_thread(vm, s, ctx, n); ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream lua run thread returned %d", rc); if (rc == NGX_AGAIN) { return ngx_stream_lua_run_posted_threads(c, vm, s, ctx); } if (rc == NGX_DONE) { ngx_stream_lua_finalize_session(s, NGX_DONE); return ngx_stream_lua_run_posted_threads(c, vm, s, ctx); } /* rc == NGX_ERROR || rc >= NGX_OK */ if (ctx->entered_content_phase) { ngx_stream_lua_finalize_session(s, rc); return NGX_DONE; } return rc; }
int ngx_stream_lua_coroutine_create_helper(lua_State *L, ngx_stream_session_t *s, ngx_stream_lua_ctx_t *ctx, ngx_stream_lua_co_ctx_t **pcoctx) { lua_State *vm; /* the Lua VM */ lua_State *co; /* new coroutine to be created */ ngx_stream_lua_co_ctx_t *coctx; /* co ctx for the new coroutine */ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected"); ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT | NGX_STREAM_LUA_CONTEXT_TIMER); vm = ngx_stream_lua_get_lua_vm(s, ctx); /* create new coroutine on root Lua state, so it always yields * to main Lua thread */ co = lua_newthread(vm); #if 0 /* TODO */ ngx_stream_lua_probe_user_coroutine_create(s, L, co); #endif coctx = ngx_stream_lua_get_co_ctx(co, ctx); if (coctx == NULL) { coctx = ngx_stream_lua_create_co_ctx(s, ctx); if (coctx == NULL) { return luaL_error(L, "no memory"); } } else { ngx_memzero(coctx, sizeof(ngx_stream_lua_co_ctx_t)); coctx->co_ref = LUA_NOREF; } coctx->co = co; coctx->co_status = NGX_STREAM_LUA_CO_SUSPENDED; /* make new coroutine share globals of the parent coroutine. * NOTE: globals don't have to be separated! */ ngx_stream_lua_get_globals_table(L); lua_xmove(L, co, 1); ngx_stream_lua_set_globals_table(co); lua_xmove(vm, L, 1); /* move coroutine from main thread to L */ lua_pushvalue(L, 1); /* copy entry function to top of L*/ lua_xmove(L, co, 1); /* move entry function from L to co */ if (pcoctx) { *pcoctx = coctx; } #ifdef NGX_LUA_USE_ASSERT coctx->co_top = 1; #endif return 1; /* return new coroutine to Lua */ }