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
* 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;
}
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);
/* 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.
- */
-enum act_return hlua_tcp_req_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_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.
+/* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
+ * succes case, else return ACT_RET_PRS_ERR.
*/
-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)
+static enum act_parse_ret 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;
}
}};
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 }
}};
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
*
* set-var(<variable-name>) <expression>
*
- * It returns 0 if fails and <err> is filled with an error message. Otherwise,
- * it returns 1 and the variable <expr> is filled with the pointer to the
- * expression to execute.
+ * It returns ACT_RET_PRS_ERR if fails and <err> is filled with an error
+ * message. Otherwise, it returns ACT_RET_PRS_OK and the variable <expr>
+ * 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(<var-name>)'", 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(<var-name>)'", 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;
-
- if (!((*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;
- }
-
- 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))
+ 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;
- 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))
+ 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;
- 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))
+ }
+ 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(rule->arg.vars.expr->fetch->use));
+ free(rule->arg.vars.expr);
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;
}
}};
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 */ }
}};