diff --git a/src/hlua.c b/src/hlua.c index 0582070aa..fa67b15f2 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -4215,64 +4215,29 @@ __LJMP static int hlua_register_fetches(lua_State *L) return 0; } -/* global {tcp|http}-request parser. Return 1 in succes case, else return 0. */ -static int hlua_parse_rule(const char **args, int *cur_arg, struct proxy *px, - struct hlua_rule **rule_p, char **err) -{ - struct hlua_rule *rule; - - /* Memory for the rule. */ - rule = malloc(sizeof(*rule)); - if (!rule) { - memprintf(err, "out of memory error"); - return 0; - } - *rule_p = rule; - - /* The requiered arg is a function name. */ - if (!args[*cur_arg]) { - memprintf(err, "expect Lua function name"); - return 0; - } - - /* Lookup for the symbol, and check if it is a function. */ - lua_getglobal(gL.T, args[*cur_arg]); - if (lua_isnil(gL.T, -1)) { - lua_pop(gL.T, 1); - memprintf(err, "Lua function '%s' not found", args[*cur_arg]); - return 0; - } - if (!lua_isfunction(gL.T, -1)) { - lua_pop(gL.T, 1); - memprintf(err, "'%s' is not a function", args[*cur_arg]); - return 0; - } - - /* Reference the Lua function and store the reference. */ - rule->fcn.function_ref = luaL_ref(gL.T, LUA_REGISTRYINDEX); - rule->fcn.name = strdup(args[*cur_arg]); - if (!rule->fcn.name) { - memprintf(err, "out of memory error."); - return 0; - } - (*cur_arg)++; - - /* TODO: later accept arguments. */ - rule->args = NULL; - - return 1; -} - /* This function is a wrapper to execute each LUA function declared * as an action wrapper during the initialisation period. This function - * return 1 if the processing is finished (with oe without error) and - * return 0 if the function must be called again because the LUA - * returns a yield. + * return ACT_RET_CONT if the processing is finished (with or without + * error) and return ACT_RET_YIELD if the function must be called again + * because the LUA returns a yield. */ -static enum act_return hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, - struct stream *s, unsigned int analyzer) +static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { char **arg; + unsigned int analyzer; + + switch (rule->from) { + case ACT_F_TCP_REQ_CNT: analyzer = AN_REQ_INSPECT_FE ; break; + case ACT_F_TCP_RES_CNT: analyzer = AN_RES_INSPECT ; break; + case ACT_F_HTTP_REQ: analyzer = AN_REQ_HTTP_PROCESS_FE; break; + case ACT_F_HTTP_RES: analyzer = AN_RES_HTTP_PROCESS_BE; break; + default: + send_log(px, LOG_ERR, "Lua: internal error while execute action."); + if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) + Alert("Lua: internal error while execute action.\n"); + return ACT_RET_CONT; + } /* In the execution wrappers linked with a stream, the * Lua context can be not initialized. This behavior @@ -4280,9 +4245,11 @@ static enum act_return hlua_request_act_wrapper(struct hlua_rule *rule, struct p * Lua initialization cause 5% performances loss. */ if (!s->hlua.T && !hlua_ctx_init(&s->hlua, s->task)) { - send_log(px, LOG_ERR, "Lua action '%s': can't initialize Lua context.", rule->fcn.name); + send_log(px, LOG_ERR, "Lua action '%s': can't initialize Lua context.", + rule->arg.hlua_rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) - Alert("Lua action '%s': can't initialize Lua context.\n", rule->fcn.name); + Alert("Lua action '%s': can't initialize Lua context.\n", + rule->arg.hlua_rule->fcn.name); return ACT_RET_CONT; } @@ -4290,30 +4257,36 @@ static enum act_return hlua_request_act_wrapper(struct hlua_rule *rule, struct p if (!HLUA_IS_RUNNING(&s->hlua)) { /* Check stack available size. */ if (!lua_checkstack(s->hlua.T, 1)) { - send_log(px, LOG_ERR, "Lua function '%s': full stack.", rule->fcn.name); + send_log(px, LOG_ERR, "Lua function '%s': full stack.", + rule->arg.hlua_rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) - Alert("Lua function '%s': full stack.\n", rule->fcn.name); + Alert("Lua function '%s': full stack.\n", + rule->arg.hlua_rule->fcn.name); return ACT_RET_CONT; } /* Restore the function in the stack. */ - lua_rawgeti(s->hlua.T, LUA_REGISTRYINDEX, rule->fcn.function_ref); + lua_rawgeti(s->hlua.T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref); /* Create and and push object stream in the stack. */ if (!hlua_txn_new(s->hlua.T, s, px)) { - send_log(px, LOG_ERR, "Lua function '%s': full stack.", rule->fcn.name); + send_log(px, LOG_ERR, "Lua function '%s': full stack.", + rule->arg.hlua_rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) - Alert("Lua function '%s': full stack.\n", rule->fcn.name); + Alert("Lua function '%s': full stack.\n", + rule->arg.hlua_rule->fcn.name); return ACT_RET_CONT; } s->hlua.nargs = 1; /* push keywords in the stack. */ - for (arg = rule->args; arg && *arg; arg++) { + for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) { if (!lua_checkstack(s->hlua.T, 1)) { - send_log(px, LOG_ERR, "Lua function '%s': full stack.", rule->fcn.name); + send_log(px, LOG_ERR, "Lua function '%s': full stack.", + rule->arg.hlua_rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) - Alert("Lua function '%s': full stack.\n", rule->fcn.name); + Alert("Lua function '%s': full stack.\n", + rule->arg.hlua_rule->fcn.name); return ACT_RET_CONT; } lua_pushstring(s->hlua.T, *arg); @@ -4358,102 +4331,73 @@ static enum act_return hlua_request_act_wrapper(struct hlua_rule *rule, struct p /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ - send_log(px, LOG_ERR, "Lua function '%s': %s.", rule->fcn.name, lua_tostring(s->hlua.T, -1)); + send_log(px, LOG_ERR, "Lua function '%s': %s.", + rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua.T, -1)); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) - Alert("Lua function '%s': %s.\n", rule->fcn.name, lua_tostring(s->hlua.T, -1)); + Alert("Lua function '%s': %s.\n", + rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua.T, -1)); lua_pop(s->hlua.T, 1); return ACT_RET_CONT; case HLUA_E_ERR: /* Display log. */ - send_log(px, LOG_ERR, "Lua function '%s' return an unknown error.", rule->fcn.name); + send_log(px, LOG_ERR, "Lua function '%s' return an unknown error.", + rule->arg.hlua_rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) - Alert("Lua function '%s' return an unknown error.\n", rule->fcn.name); + Alert("Lua function '%s' return an unknown error.\n", + rule->arg.hlua_rule->fcn.name); default: return ACT_RET_CONT; } } -/* Lua execution wrapper for "tcp-request". This function uses - * "hlua_request_act_wrapper" for executing the LUA code. +/* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in + * succes case, else return ACT_RET_PRS_ERR. */ -enum act_return hlua_tcp_req_act_wrapper(struct act_rule *act_rule, struct proxy *px, - struct session *sess, struct stream *s) +static enum act_parse_ret action_register_lua(const char **args, int *cur_arg, struct proxy *px, + struct act_rule *rule, char **err) { - return hlua_request_act_wrapper(act_rule->arg.hlua_rule, px, s, AN_REQ_INSPECT_FE); -} - -/* Lua execution wrapper for "tcp-response". This function uses - * "hlua_request_act_wrapper" for executing the LUA code. - */ -enum act_return hlua_tcp_res_act_wrapper(struct act_rule *act_rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return hlua_request_act_wrapper(act_rule->arg.hlua_rule, px, s, AN_RES_INSPECT); -} - -/* Lua execution wrapper for http-request. - * This function uses "hlua_request_act_wrapper" for executing - * the LUA code. - */ -enum act_return hlua_http_req_act_wrapper(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return hlua_request_act_wrapper(rule->arg.hlua_rule, px, s, AN_REQ_HTTP_PROCESS_FE); -} - -/* Lua execution wrapper for http-response. - * This function uses "hlua_request_act_wrapper" for executing - * the LUA code. - */ -enum act_return hlua_http_res_act_wrapper(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return hlua_request_act_wrapper(rule->arg.hlua_rule, px, s, AN_RES_HTTP_PROCESS_BE); -} - -/* tcp-request <*> configuration wrapper. */ -static enum act_parse_ret tcp_req_action_register_lua(const char **args, int *cur_arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!hlua_parse_rule(args, cur_arg, px, &rule->arg.hlua_rule, err)) + /* Memory for the rule. */ + rule->arg.hlua_rule = malloc(sizeof(*rule->arg.hlua_rule)); + if (!rule->arg.hlua_rule) { + memprintf(err, "out of memory error"); return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = hlua_tcp_req_act_wrapper; - return ACT_RET_PRS_OK; -} + } -/* tcp-response <*> configuration wrapper. */ -static enum act_parse_ret tcp_res_action_register_lua(const char **args, int *cur_arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!hlua_parse_rule(args, cur_arg, px, &rule->arg.hlua_rule, err)) + /* The requiered arg is a function name. */ + if (!args[*cur_arg]) { + memprintf(err, "expect Lua function name"); return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = hlua_tcp_res_act_wrapper; - return ACT_RET_PRS_OK; -} + } -/* http-request <*> configuration wrapper. */ -static enum act_parse_ret http_req_action_register_lua(const char **args, int *cur_arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!hlua_parse_rule(args, cur_arg, px, &rule->arg.hlua_rule, err)) + /* Lookup for the symbol, and check if it is a function. */ + lua_getglobal(gL.T, args[*cur_arg]); + if (lua_isnil(gL.T, -1)) { + lua_pop(gL.T, 1); + memprintf(err, "Lua function '%s' not found", args[*cur_arg]); return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = hlua_http_req_act_wrapper; - return ACT_RET_PRS_OK; -} + } + if (!lua_isfunction(gL.T, -1)) { + lua_pop(gL.T, 1); + memprintf(err, "'%s' is not a function", args[*cur_arg]); + return ACT_RET_PRS_ERR; + } -/* http-response <*> configuration wrapper. */ -static enum act_parse_ret http_res_action_register_lua(const char **args, int *cur_arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!hlua_parse_rule(args, cur_arg, px, &rule->arg.hlua_rule, err)) + /* Reference the Lua function and store the reference. */ + rule->arg.hlua_rule->fcn.function_ref = luaL_ref(gL.T, LUA_REGISTRYINDEX); + rule->arg.hlua_rule->fcn.name = strdup(args[*cur_arg]); + if (!rule->arg.hlua_rule->fcn.name) { + memprintf(err, "out of memory error."); return ACT_RET_PRS_ERR; + } + (*cur_arg)++; + + /* TODO: later accept arguments. */ + rule->arg.hlua_rule->args = NULL; + rule->action = ACT_ACTION_CONT; - rule->action_ptr = hlua_http_res_act_wrapper; + rule->action_ptr = hlua_action; return ACT_RET_PRS_OK; } @@ -4584,22 +4528,22 @@ static struct cfg_kw_list cfg_kws = {{ },{ }}; static struct action_kw_list http_req_kws = { { }, { - { "lua", http_req_action_register_lua }, + { "lua", action_register_lua }, { NULL, NULL } }}; static struct action_kw_list http_res_kws = { { }, { - { "lua", http_res_action_register_lua }, + { "lua", action_register_lua }, { NULL, NULL } }}; static struct action_kw_list tcp_req_cont_kws = { { }, { - { "lua", tcp_req_action_register_lua }, + { "lua", action_register_lua }, { NULL, NULL } }}; static struct action_kw_list tcp_res_cont_kws = { { }, { - { "lua", tcp_res_action_register_lua }, + { "lua", action_register_lua }, { NULL, NULL } }}; diff --git a/src/vars.c b/src/vars.c index dec6685b4..d1d05cc17 100644 --- a/src/vars.c +++ b/src/vars.c @@ -479,57 +479,36 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct stream *strm, struc return 1; } -/* Returns 0 if we need to come back later to complete the sample's retrieval, - * otherwise 1. For now all processing is considered final so we only return 1. - */ -static inline enum act_return action_store(struct sample_expr *expr, const char *name, - enum vars_scope scope, struct proxy *px, - struct stream *s, int sens) +/* Always returns ACT_RET_CONT even if an error occurs. */ +static enum act_return action_store(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { struct sample smp; + int dir; + + switch (rule->from) { + case ACT_F_TCP_REQ_CNT: dir = SMP_OPT_DIR_REQ; break; + case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break; + case ACT_F_HTTP_REQ: dir = SMP_OPT_DIR_REQ; break; + case ACT_F_HTTP_RES: dir = SMP_OPT_DIR_RES; break; + default: + send_log(px, LOG_ERR, "Vars: internal error while execute action store."); + if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) + Alert("Vars: internal error while execute action store.\n"); + return ACT_RET_CONT; + } /* Process the expression. */ memset(&smp, 0, sizeof(smp)); - if (!sample_process(px, s->sess, s, sens|SMP_OPT_FINAL, expr, &smp)) + if (!sample_process(px, s->sess, s, dir|SMP_OPT_FINAL, + rule->arg.vars.expr, &smp)) return ACT_RET_CONT; /* Store the sample, and ignore errors. */ - sample_store_stream(name, scope, s, &smp); + sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, s, &smp); return ACT_RET_CONT; } -/* Wrapper for action_store */ -static enum act_return action_tcp_req_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return action_store(rule->arg.vars.expr, rule->arg.vars.name, - rule->arg.vars.scope, px, s, SMP_OPT_DIR_REQ); -} - -/* Wrapper for action_store */ -static enum act_return action_tcp_res_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return action_store(rule->arg.vars.expr, rule->arg.vars.name, - rule->arg.vars.scope, px, s, SMP_OPT_DIR_RES); -} - -/* Wrapper for action_store */ -static enum act_return action_http_req_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return action_store(rule->arg.vars.expr, rule->arg.vars.name, - rule->arg.vars.scope, px, s, SMP_OPT_DIR_REQ); -} - -/* Wrapper for action_store */ -static enum act_return action_http_res_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) -{ - return action_store(rule->arg.vars.expr, rule->arg.vars.name, - rule->arg.vars.scope, px, s, SMP_OPT_DIR_RES); -} - /* This two function checks the variable name and replace the * configuration string name by the global string name. its * the same string, but the global pointer can be easy to @@ -554,106 +533,63 @@ static int conv_check_var(struct arg *args, struct sample_conv *conv, * * set-var() * - * It returns 0 if fails and is filled with an error message. Otherwise, - * it returns 1 and the variable is filled with the pointer to the - * expression to execute. + * It returns ACT_RET_PRS_ERR if fails and is filled with an error + * message. Otherwise, it returns ACT_RET_PRS_OK and the variable + * is filled with the pointer to the expression to execute. */ -static int parse_vars(const char **args, int *arg, struct proxy *px, - int flags, char **err, struct sample_expr **expr, - const char **name, enum vars_scope *scope) +static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy *px, + struct act_rule *rule, char **err) { const char *var_name = args[*arg-1]; int var_len; const char *kw_name; + int flags; var_name += strlen("set-var"); if (*var_name != '(') { memprintf(err, "invalid variable '%s'. Expects 'set-var()'", args[*arg-1]); - return 0; + return ACT_RET_PRS_ERR; } var_name++; /* jump the '(' */ var_len = strlen(var_name); var_len--; /* remove the ')' */ if (var_name[var_len] != ')') { memprintf(err, "invalid variable '%s'. Expects 'set-var()'", args[*arg-1]); - return 0; + return ACT_RET_PRS_ERR; } - *name = register_name(var_name, var_len, scope, err); - if (!*name) - return 0; + rule->arg.vars.name = register_name(var_name, var_len, &rule->arg.vars.scope, err); + if (!rule->arg.vars.name) + return ACT_RET_PRS_ERR; kw_name = args[*arg-1]; - *expr = sample_parse_expr((char **)args, arg, px->conf.args.file, px->conf.args.line, - err, &px->conf.args); - if (!*expr) - return 0; + rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file, + px->conf.args.line, err, &px->conf.args); + if (!rule->arg.vars.expr) + return ACT_RET_PRS_ERR; - if (!((*expr)->fetch->val & flags)) { + switch (rule->from) { + case ACT_F_TCP_REQ_CNT: flags = SMP_VAL_FE_REQ_CNT; break; + case ACT_F_TCP_RES_CNT: flags = SMP_VAL_BE_RES_CNT; break; + case ACT_F_HTTP_REQ: flags = SMP_VAL_FE_HRQ_HDR; break; + case ACT_F_HTTP_RES: flags = SMP_VAL_BE_HRS_HDR; break; + default: + memprintf(err, + "internal error, unexpected rule->from=%d, please report this bug!", + rule->from); + return ACT_RET_PRS_ERR; + } + if (!(rule->arg.vars.expr->fetch->val & flags)) { memprintf(err, "fetch method '%s' extracts information from '%s', none of which is available here", - kw_name, sample_src_names((*expr)->fetch->use)); - free(*expr); - return 0; + kw_name, sample_src_names(rule->arg.vars.expr->fetch->use)); + free(rule->arg.vars.expr); + return ACT_RET_PRS_ERR; } - return 1; -} - -/* Wrapper for parse_vars */ -static enum act_parse_ret parse_tcp_req_store(const char **args, int *arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!parse_vars(args, arg, px, SMP_VAL_FE_REQ_CNT, err, - &rule->arg.vars.expr, - &rule->arg.vars.name, - &rule->arg.vars.scope)) - return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = action_tcp_req_store; - return ACT_RET_PRS_OK; -} - -/* Wrapper for parse_vars */ -static enum act_parse_ret parse_tcp_res_store(const char **args, int *arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!parse_vars(args, arg, px, SMP_VAL_BE_RES_CNT, err, - &rule->arg.vars.expr, - &rule->arg.vars.name, - &rule->arg.vars.scope)) - return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = action_tcp_res_store; - return ACT_RET_PRS_OK; -} - -/* Wrapper for parse_vars */ -static enum act_parse_ret parse_http_req_store(const char **args, int *arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!parse_vars(args, arg, px, SMP_VAL_FE_HRQ_HDR, err, - &rule->arg.vars.expr, - &rule->arg.vars.name, - &rule->arg.vars.scope)) - return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = action_http_req_store; - return ACT_RET_PRS_OK; -} - -/* Wrapper for parse_vars */ -static enum act_parse_ret parse_http_res_store(const char **args, int *arg, struct proxy *px, - struct act_rule *rule, char **err) -{ - if (!parse_vars(args, arg, px, SMP_VAL_BE_HRS_HDR, err, - &rule->arg.vars.expr, - &rule->arg.vars.name, - &rule->arg.vars.scope)) - return ACT_RET_PRS_ERR; - rule->action = ACT_ACTION_CONT; - rule->action_ptr = action_http_res_store; + rule->action = ACT_ACTION_CONT; + rule->action_ptr = action_store; return ACT_RET_PRS_OK; } @@ -711,22 +647,22 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { }}; static struct action_kw_list tcp_req_kws = { { }, { - { "set-var", parse_tcp_req_store, 1 }, + { "set-var", parse_store, 1 }, { /* END */ } }}; static struct action_kw_list tcp_res_kws = { { }, { - { "set-var", parse_tcp_res_store, 1 }, + { "set-var", parse_store, 1 }, { /* END */ } }}; static struct action_kw_list http_req_kws = { { }, { - { "set-var", parse_http_req_store, 1 }, + { "set-var", parse_store, 1 }, { /* END */ } }}; static struct action_kw_list http_res_kws = { { }, { - { "set-var", parse_http_res_store, 1 }, + { "set-var", parse_store, 1 }, { /* END */ } }};