diff --git a/include/types/hlua.h b/include/types/hlua.h index aada722d7e..1241778114 100644 --- a/include/types/hlua.h +++ b/include/types/hlua.h @@ -63,4 +63,14 @@ struct hlua_txn { void *l7; }; +/* This struct is used as a closure argument associated + * with dynamic sample-fetch created fucntions. This contains + * a pointer to the original sample_fetch struct. It is used + * to identify the function to execute with the sample fetch + * wrapper. + */ +struct hlua_sample_fetch { + struct sample_fetch *f; +}; + #endif /* _TYPES_HLUA_H */ diff --git a/src/hlua.c b/src/hlua.c index f3c329db6a..bf3ed29f14 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -11,6 +11,9 @@ #include #include +#include +#include +#include #include /* Lua uses longjmp to perform yield or throwing errors. This @@ -849,6 +852,57 @@ static int hlua_txn_new(lua_State *L, struct session *s, struct proxy *p, void * return 1; } +/* This function is an LUA binding. It is called with each sample-fetch. + * It uses closure argument to store the associated sample-fetch. It + * returns only one argument or throws an error. An error is throwed + * only if an error is encoutered during the argument parsing. If + * the "sample-fetch" function fails, nil is returned. + */ +__LJMP static int hlua_run_sample_fetch(lua_State *L) +{ + struct hlua_txn *s; + struct hlua_sample_fetch *f; + struct arg args[ARGM_NBARGS]; + int i; + struct sample smp; + + /* Get closure arguments. */ + f = (struct hlua_sample_fetch *)lua_touserdata(L, lua_upvalueindex(1)); + + /* Get traditionnal arguments. */ + s = MAY_LJMP(hlua_checktxn(L, 1)); + + /* Get extra arguments. */ + for (i = 0; i <= lua_gettop(L); i++) { + if (i >= ARGM_NBARGS) + break; + hlua_lua2arg(L, i + 2, &args[i]); + } + args[i].type = ARGT_STOP; + + /* Check arguments. */ + MAY_LJMP(hlua_lua2arg_check(L, 1, args, f->f->arg_mask)); + + /* Run the special args cehcker. */ + if (!f->f->val_args(args, NULL)) { + lua_pushfstring(L, "error in arguments"); + WILL_LJMP(lua_error(L)); + } + + /* Initialise the sample. */ + memset(&smp, 0, sizeof(smp)); + + /* Run the sample fetch process. */ + if (!f->f->process(s->p, s->s, s->l7, 0, args, &smp, f->f->kw, f->f->private)) { + lua_pushnil(L); + return 1; + } + + /* Convert the returned sample in lua value. */ + hlua_smp2lua(L, &smp); + return 1; +} + /* This function is used as a calback of a task. It is called by the * HAProxy task subsystem when the task is awaked. The LUA runtime can * return an E_AGAIN signal, the emmiter of this signal must set a @@ -1057,6 +1111,10 @@ int hlua_post_init() void hlua_init(void) { int i; + int idx; + struct sample_fetch *sf; + struct hlua_sample_fetch *hsf; + char *p; /* Initialise com signals pool session. */ pool2_hlua_com = create_pool("hlua_com", sizeof(struct hlua_com), MEM_F_SHARED); @@ -1128,6 +1186,37 @@ void hlua_init(void) lua_pushstring(gL.T, "__index"); lua_newtable(gL.T); + /* Browse existing fetches and create the associated + * object method. + */ + sf = NULL; + while ((sf = sample_fetch_getnext(sf, &idx)) != NULL) { + + /* Dont register the keywork if the arguments check function are + * not safe during the runtime. + */ + if ((sf->val_args != NULL) && + (sf->val_args != val_payload_lv) && + (sf->val_args != val_hdr)) + continue; + + /* gL.Tua doesn't support '.' and '-' in the function names, replace it + * by an underscore. + */ + strncpy(trash.str, sf->kw, trash.size); + trash.str[trash.size - 1] = '\0'; + for (p = trash.str; *p; p++) + if (*p == '.' || *p == '-' || *p == '+') + *p = '_'; + + /* Register the function. */ + lua_pushstring(gL.T, trash.str); + hsf = lua_newuserdata(gL.T, sizeof(struct hlua_sample_fetch)); + hsf->f = sf; + lua_pushcclosure(gL.T, hlua_run_sample_fetch, 1); + lua_settable(gL.T, -3); + } + /* Register Lua functions. */ hlua_class_function(gL.T, "set_priv", hlua_setpriv); hlua_class_function(gL.T, "get_priv", hlua_getpriv);