static int noit_lua_module_onload(mtev_image_t *img) { int rv; lua_State *L; lua_module_closure_t *lmc; struct module_conf *mc; mc = mtev_image_get_userdata(img); lmc = lmc_tls_get(img); L = lmc->lua_state; if(!L) return -1; lua_getglobal(L, "require"); lua_pushstring(L, mc->object); rv = lua_pcall(L, 1, 1, 0); if(rv) { int i; mtevL(nlerr, "lua: %s.onload failed\n", mc->object); i = lua_gettop(L); if(i>0) { if(lua_isstring(L, i)) { const char *err; size_t len; err = lua_tolstring(L, i, &len); mtevL(nlerr, "lua: %s\n", err); } } lua_pop(L,i); return -1; } lua_pop(L, lua_gettop(L)); mtev_lua_pushmodule(L, mc->object); if(lua_isnil(L, -1)) { lua_pop(L, 1); mtevL(nlerr, "lua: no such object %s\n", mc->object); return -1; } lua_getfield(L, -1, "onload"); lua_remove(L, -2); if(!lua_isfunction(L, -1)) { lua_pop(L, 1); /* No onload */ return 0; } noit_lua_setup_module(L, (noit_module_t *)img); lua_pcall(L, 1, 1, 0); if(lua_isnumber(L, -1)) { int rv; rv = lua_tointeger(L, -1); lua_pop(L, 1); return rv; } mtevL(nlerr, "%s.onload must return a integer not %s (%s)\n", mc->object, mtev_lua_type_name(lua_type(L,-1)), lua_tostring(L,-1)); lua_pop(L,1); return -1; }
static int lua_web_handler(mtev_http_rest_closure_t *restc, int npats, char **pats) { int status, base, rv, mask = 0; int complete = 0; lua_web_conf_t *conf = the_one_conf; lua_module_closure_t *lmc = &conf->lmc; mtev_lua_resume_info_t *ri; mtev_lua_resume_rest_info_t *ctx = NULL; lua_State *L; eventer_t conne; mtev_http_request *req = mtev_http_session_request(restc->http_ctx); mtev_http_response *res = mtev_http_session_response(restc->http_ctx); if(!lmc || !conf || !conf->dispatch) { goto boom; } if(mtev_http_request_get_upload(req, NULL) == NULL && mtev_http_request_has_payload(req)) { const void *payload = NULL; int payload_len = 0; payload = rest_get_raw_upload(restc, &mask, &complete, &payload_len); if(!complete) return mask; mtev_http_request_set_upload(req, (char *)payload, (int64_t)payload_len, req_payload_free, NULL); restc->call_closure_free(restc->call_closure); restc->call_closure = NULL; } if(restc->call_closure == NULL) { ri = calloc(1, sizeof(*ri)); ri->bound_thread = pthread_self(); ri->context_magic = LUA_REST_INFO_MAGIC; ctx = ri->context_data = calloc(1, sizeof(mtev_lua_resume_rest_info_t)); ctx->restc = restc; ri->lmc = lmc; lua_getglobal(lmc->lua_state, "mtev_coros"); ri->coro_state = lua_newthread(lmc->lua_state); ri->coro_state_ref = luaL_ref(lmc->lua_state, -2); mtev_lua_set_resume_info(lmc->lua_state, ri); lua_pop(lmc->lua_state, 1); /* pops mtev_coros */ restc->call_closure = ri; restc->call_closure_free = rest_lua_ctx_free; } ri = restc->call_closure; ctx = ri->context_data; ctx->httpcode = 404; L = ri->coro_state; lua_getglobal(L, "require"); lua_pushstring(L, conf->dispatch); rv = lua_pcall(L, 1, 1, 0); if(rv) { int i; mtevL(mtev_error, "lua: require %s failed\n", conf->dispatch); i = lua_gettop(L); if(i>0) { if(lua_isstring(L, i)) { const char *err; size_t len; err = lua_tolstring(L, i, &len); mtevL(mtev_error, "lua: %s\n", err); } } lua_pop(L,i); goto boom; } lua_pop(L, lua_gettop(L)); mtev_lua_pushmodule(L, conf->dispatch); if(lua_isnil(L, -1)) { lua_pop(L, 1); ctx->err = strdup("no such module"); goto boom; } lua_getfield(L, -1, "handler"); lua_remove(L, -2); if(!lua_isfunction(L, -1)) { lua_pop(L, 1); ctx->err = strdup("no 'handler' function in module"); goto boom; } mtev_lua_setup_restc(L, restc); mtev_lua_hash_to_table(L, restc->ac->config); conne = mtev_http_connection_event(mtev_http_session_connection(restc->http_ctx)); eventer_remove(conne); restc->fastpath = lua_web_restc_fastpath; status = lmc->resume(ri, 2); if(status == 0) return 0; if(mtev_http_response_complete(res) != mtev_true) { boom: mtev_http_response_standard(restc->http_ctx, (ctx && ctx->httpcode) ? ctx->httpcode : 500, "ERROR", "text/plain"); if(ctx && ctx->err) mtev_http_response_append(restc->http_ctx, ctx->err, strlen(ctx->err)); mtev_http_response_end(restc->http_ctx); } return 0; }
static int lua_general_handler(mtev_dso_generic_t *self) { int status, rv; lua_general_conf_t *conf = get_config(self); lua_module_closure_t *lmc = pthread_getspecific(conf->key); mtev_lua_resume_info_t *ri = NULL; const char *err = NULL; char errbuf[128]; lua_State *L; if(!lmc) mtev_lua_general_init(self); lmc = pthread_getspecific(conf->key); if(!lmc || !conf || !conf->module || !conf->function) { goto boom; } ri = lua_general_new_resume_info(lmc); L = ri->coro_state; lua_getglobal(L, "require"); lua_pushstring(L, conf->module); rv = lua_pcall(L, 1, 1, 0); if(rv) { int i; mtevL(nlerr, "lua: require %s failed\n", conf->module); mtev_lua_traceback(L); i = lua_gettop(L); if(i>0) { if(lua_isstring(L, i)) { const char *err; size_t len; err = lua_tolstring(L, i, &len); mtevL(nlerr, "lua: %s\n", err); } } lua_pop(L,i); goto boom; } lua_pop(L, lua_gettop(L)); mtev_lua_pushmodule(L, conf->module); if(lua_isnil(L, -1)) { lua_pop(L, 1); snprintf(errbuf, sizeof(errbuf), "no such module: '%s'", conf->module); err = errbuf; goto boom; } lua_getfield(L, -1, conf->function); lua_remove(L, -2); if(!lua_isfunction(L, -1)) { lua_pop(L, 1); snprintf(errbuf, sizeof(errbuf), "no function '%s' in module '%s'", conf->function, conf->module); err = errbuf; goto boom; } status = lmc->resume(ri, 0); if(status == 0) return 0; /* If we've failed, resume has freed ri, so we should just return. */ mtevL(nlerr, "lua dispatch error: %d\n", status); tragic_failure(self); return 0; boom: if(err) mtevL(nlerr, "lua dispatch error: %s\n", err); if(ri) lua_general_ctx_free(ri); tragic_failure(self); return 0; }