static int noit_lua_module_config(noit_module_t *mod, mtev_hash_table *options) { struct module_conf *mc; struct module_tls_conf *mtlsc; LMC_DECL(L, mod, object); mc = noit_module_get_userdata(mod); if(options) { mtevAssert(mc->options == NULL); mc->options = calloc(1, sizeof(*mc->options)); mtev_hash_init(mc->options); mtev_hash_merge_as_dict(mc->options, options); } else options = mc->options; mtlsc = __get_module_tls_conf(&mod->hdr); if(mtlsc->configured) return mtlsc->configured_return; SETUP_CALL(L, object, "config", return 0); noit_lua_setup_module(L, mod); mtev_lua_hash_to_table(L, options); lua_pcall(L, 2, 1, 0); /* If rv == 0, the caller will free options. We've * already freed options, that would be bad. fudge -> 1 */ RETURN_INT(L, object, "config", { mtlsc->configured = 1; mtlsc->configured_return = rv; });
static int mtev_lua_http_request_querystring(lua_State *L) { mtev_hash_table *h; CCALL_DECL(L, mtev_http_request, req, 0); h = mtev_http_request_querystring_table(req); if(lua_gettop(L) == 1) mtev_lua_hash_to_table(L, h); else if(lua_gettop(L) == 2) { const char *key = lua_tostring(L,2), *value; if(key == NULL) lua_pushnil(L); else { if(mtev_hash_retr_str(h, key, strlen(key), &value)) lua_pushstring(L, value); else lua_pushnil(L); } } else luaL_error(L, "invalid arguments to mtev_http_request:querystring()"); return 1; }
static int mtev_lua_http_request_headers(lua_State *L) { mtev_hash_table *h; CCALL_DECL(L, mtev_http_request, req, 0); h = mtev_http_request_headers_table(req); if(lua_gettop(L) == 1) mtev_lua_hash_to_table(L, h); else if(lua_gettop(L) == 2) { const char *hdr = lua_tostring(L,2); if(hdr == NULL) lua_pushnil(L); else { char *cp, *lower = alloca(strlen(hdr) + 1); memcpy(lower, hdr, strlen(hdr)+1); for(cp=lower; *cp; cp++) *cp = tolower(*cp); if(mtev_hash_retr_str(h, lower, strlen(lower), &hdr)) lua_pushstring(L, hdr); else lua_pushnil(L); } } else luaL_error(L, "invalid arguments to mtev_http_request:headers()"); return 1; }
static int noit_check_index_func(lua_State *L) { int n; const char *k; noit_check_t **udata, *check; n = lua_gettop(L); /* number of arguments */ mtevAssert(n == 2); if(!luaL_checkudata(L, 1, "noit_check_t")) { luaL_error(L, "metatable error, arg1 not a noit_check_t!"); } udata = lua_touserdata(L, 1); check = *udata; if(!lua_isstring(L, 2)) { luaL_error(L, "metatable error, arg2 not a string!"); } k = lua_tostring(L, 2); switch(*k) { case 'a': if(!strcmp(k, "available")) { lua_pushlightuserdata(L, check); lua_pushinteger(L, NP_AVAILABLE); lua_pushcclosure(L, noit_lua_set_available, 2); } else if(!strcmp(k, "availability")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_get_available, 1); } else break; return 1; case 'b': if(!strcmp(k, "bad")) { lua_pushlightuserdata(L, check); lua_pushinteger(L, NP_BAD); lua_pushcclosure(L, noit_lua_set_state, 2); } else break; return 1; case 'c': if(!strcmp(k, "config")) mtev_lua_hash_to_table(L, check->config); else if(!strcmp(k, "checkid")) { char uuid_str[UUID_STR_LEN + 1]; uuid_unparse_lower(check->checkid, uuid_str); lua_pushstring(L, uuid_str); } else break; return 1; case 'f': if(!strcmp(k, "flags")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_get_flags, 1); } else break; return 1; case 'g': if(!strcmp(k, "good")) { lua_pushlightuserdata(L, check); lua_pushinteger(L, NP_GOOD); lua_pushcclosure(L, noit_lua_set_state, 2); } else break; return 1; case 'i': if(!strcmp(k, "interpolate")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_interpolate, 1); } else if(!strcmp(k, "is_thread_local")) { if(check->fire_event && pthread_equal(pthread_self(), check->fire_event->thr_owner)) { lua_pushboolean(L, 1); } else { lua_pushboolean(L, 0); } return 1; } #define IF_METRIC_IMMEDIATE_BLOCK(name,type) \ if(!strcmp(k, "immediate_" name)) { \ lua_pushlightuserdata(L, check); \ lua_pushinteger(L, type); \ lua_pushcclosure(L, noit_lua_log_immediate_metric, 2); \ } else IF_METRIC_IMMEDIATE_BLOCK("metric", METRIC_GUESS) else IF_METRIC_IMMEDIATE_BLOCK("metric_string", METRIC_STRING) else IF_METRIC_IMMEDIATE_BLOCK("metric_int32", METRIC_INT32) else IF_METRIC_IMMEDIATE_BLOCK("metric_uint32", METRIC_UINT32) else IF_METRIC_IMMEDIATE_BLOCK("metric_int64", METRIC_INT64) else IF_METRIC_IMMEDIATE_BLOCK("metric_uint64", METRIC_UINT64) else IF_METRIC_IMMEDIATE_BLOCK("metric_double", METRIC_DOUBLE) else if(!strcmp(k, "immediate_histogram")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_set_histo_metric, 1); } else break; return 1; case 'm': if(!strcmp(k, "module")) lua_pushstring(L, check->module); #define IF_METRIC_BLOCK(name,type) \ if(!strcmp(k, name)) { \ lua_pushlightuserdata(L, check); \ lua_pushinteger(L, type); \ lua_pushcclosure(L, noit_lua_set_metric, 2); \ } else IF_METRIC_BLOCK("metric", METRIC_GUESS) else IF_METRIC_BLOCK("metric_string", METRIC_STRING) else IF_METRIC_BLOCK("metric_int32", METRIC_INT32) else IF_METRIC_BLOCK("metric_uint32", METRIC_UINT32) else IF_METRIC_BLOCK("metric_int64", METRIC_INT64) else IF_METRIC_BLOCK("metric_uint64", METRIC_UINT64) else IF_METRIC_BLOCK("metric_double", METRIC_DOUBLE) else if(!strcmp(k, "metric_json")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_set_metric_json, 1); } else break; return 1; case 'n': if(!strcmp(k, "name")) lua_pushstring(L, check->name); else break; return 1; case 'p': if(!strcmp(k, "period")) lua_pushinteger(L, check->period); else break; return 1; case 's': if(!strcmp(k, "set_flags")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_set_flags, 1); } else if(!strcmp(k, "state")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_get_state, 1); } else if(!strcmp(k, "status")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_set_status, 1); } else break; return 1; case 't': if(!strcmp(k, "target")) lua_pushstring(L, check->target); else if(!strcmp(k, "target_ip")) { if(check->target_ip[0] == '\0') lua_pushnil(L); else lua_pushstring(L, check->target_ip); } else if(!strcmp(k, "timeout")) lua_pushinteger(L, check->timeout); else break; return 1; case 'u': if(!strcmp(k, "unavailable")) { lua_pushlightuserdata(L, check); lua_pushinteger(L, NP_UNAVAILABLE); lua_pushcclosure(L, noit_lua_set_available, 2); } else if(!strcmp(k, "unset_flags")) { lua_pushlightuserdata(L, check); lua_pushcclosure(L, noit_lua_unset_flags, 1); } else if(!strcmp(k, "uuid")) { char uuid_str[UUID_STR_LEN+1]; uuid_unparse_lower(check->checkid, uuid_str); lua_pushstring(L, uuid_str); return 1; } else break; return 1; default: break; } luaL_error(L, "noit_check_t no such element: %s", k); return 0; }
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; }