[core] handle differences between options/actions/setups in plugin.c
This commit is contained in:
parent
8e41187ff6
commit
061b2a4262
|
@ -7,8 +7,7 @@
|
|||
|
||||
LI_API gboolean li_config_lua_load(liLuaState *LL, liServer *srv, liWorker *wrk, const gchar *filename, liAction **pact, gboolean allow_setup, liValue *args);
|
||||
|
||||
LI_API gboolean li_lua_config_publish_str_hash(liServer *srv, liWorker *wrk, lua_State *L, GHashTable *ht, int (*wrapper)(liServer *srv, liWorker *wrk, lua_State *L, gpointer data));
|
||||
LI_API int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *L, gpointer _sa);
|
||||
LI_API int li_lua_config_handle_server_setup(liServer *srv, liWorker *wrk, lua_State *L, gpointer _ss);
|
||||
LI_API void li_lua_push_action_table(liServer *srv, liWorker *wrk, lua_State *L);
|
||||
LI_API void li_lua_push_setup_table(liServer *srv, liWorker *wrk, lua_State *L);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,71 +93,12 @@ struct liPluginAngel {
|
|||
liPluginAngelCB angel_cb;
|
||||
};
|
||||
|
||||
/* Internal structures */
|
||||
struct liServerOption {
|
||||
liPlugin *p;
|
||||
|
||||
/** the value is freed with li_value_free after the parse call, so you
|
||||
* probably want to extract pointers via li_value_extract_*
|
||||
* val is zero to get the global default value if nothing is specified
|
||||
* save result in value
|
||||
*
|
||||
* Default behaviour (NULL) is to extract the inner value from val
|
||||
*/
|
||||
liPluginParseOptionCB parse_option;
|
||||
|
||||
/** if parse_option is NULL, the default_value is used */
|
||||
gint64 default_value;
|
||||
|
||||
size_t index, module_index;
|
||||
liValueType type;
|
||||
};
|
||||
|
||||
struct liServerOptionPtr {
|
||||
liPlugin *p;
|
||||
|
||||
/** the value is freed with li_value_free after the parse call, so you
|
||||
* probably want to extract pointers via li_value_extract_*
|
||||
* val is zero to get the global default value if nothing is specified
|
||||
* save result in value
|
||||
*
|
||||
* Default behaviour (NULL) is to extract the inner value from val
|
||||
*/
|
||||
liPluginParseOptionPtrCB parse_option;
|
||||
|
||||
/** the free_option handler has to free all allocated resources;
|
||||
* it may get called with 0 initialized options, so you have to
|
||||
* check the value.
|
||||
*/
|
||||
liPluginFreeOptionPtrCB free_option;
|
||||
|
||||
/** if parse_option is NULL, the default_value is used; it is only used
|
||||
* for the following value types:
|
||||
* - STRING: used for g_string_new, i.e. a const char*
|
||||
*/
|
||||
gpointer default_value;
|
||||
|
||||
size_t index, module_index;
|
||||
liValueType type;
|
||||
};
|
||||
|
||||
struct liServerAction {
|
||||
liPlugin *p;
|
||||
liPluginCreateActionCB create_action;
|
||||
gpointer userdata;
|
||||
};
|
||||
|
||||
struct liServerSetup {
|
||||
liPlugin *p;
|
||||
liPluginSetupCB setup;
|
||||
gpointer userdata;
|
||||
};
|
||||
|
||||
/* Needed by modules to register their plugin(s) */
|
||||
LI_API liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB init, gpointer userdata);
|
||||
|
||||
/* Internal needed functions */
|
||||
LI_API void li_plugin_free(liServer *srv, liPlugin *p);
|
||||
LI_API void li_server_plugins_init(liServer *srv);
|
||||
LI_API void li_server_plugins_free(liServer *srv);
|
||||
|
||||
LI_API void li_release_optionptr(liServer *srv, liOptionPtrValue *value);
|
||||
|
@ -179,17 +120,9 @@ LI_API void li_plugins_handle_close(liConnection *con);
|
|||
LI_API void li_plugins_handle_vrclose(liVRequest *vr);
|
||||
|
||||
/* Needed for config frontends */
|
||||
/** For parsing 'somemod.option = "somevalue"', free value after call */
|
||||
LI_API liAction* li_option_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val);
|
||||
/** For parsing 'somemod.action value', e.g. 'rewrite "/url" => "/destination"'
|
||||
* free value after call
|
||||
*/
|
||||
LI_API liAction* li_create_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val);
|
||||
/** For setup function, e.g. 'listen "127.0.0.1:8080"'; free value after call */
|
||||
LI_API gboolean li_call_setup(liServer *srv, const char *name, liValue *val);
|
||||
|
||||
/** free val after call */
|
||||
LI_API gboolean li_plugin_set_default_option(liServer *srv, const gchar* name, liValue *val);
|
||||
/* "val" gets freed in any case */
|
||||
LI_API liAction *li_plugin_config_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val);
|
||||
LI_API gboolean li_plugin_config_setup(liServer *srv, const char *name, liValue *val);
|
||||
|
||||
LI_API void li_plugins_init_lua(liLuaState *LL, liServer *srv, liWorker *wrk);
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ liAction* li_lua_make_action(lua_State *L, int ndx) {
|
|||
lua_setfield(L, -2, "__index"); /* -1 */
|
||||
lua_setmetatable(L, -2); /* -1 */
|
||||
if (NULL != wrk) {
|
||||
li_lua_config_publish_str_hash(wrk->srv, wrk, L, wrk->srv->actions, li_lua_config_handle_server_action); /* +1 */
|
||||
li_lua_push_action_table(wrk->srv, wrk, L); /* +1 */
|
||||
lua_setfield(L, -2, "action"); /* -1 */
|
||||
}
|
||||
lua_setfenv(L, -2); /* -1 */
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
typedef int (*LuaWrapper)(liServer *srv, liWorker *wrk, lua_State *L, gpointer data);
|
||||
typedef int (*LuaWrapper)(liServer *srv, liWorker *wrk, lua_State *L, const char *key);
|
||||
|
||||
static liValue* lua_params_to_value(liServer *srv, lua_State *L) {
|
||||
liValue *val, *subval;
|
||||
switch (lua_gettop(L)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 1: /* first parameter is the table the __call method is for */
|
||||
return NULL;
|
||||
case 2:
|
||||
return li_value_from_lua(srv, L);
|
||||
|
@ -31,117 +31,72 @@ static liValue* lua_params_to_value(liServer *srv, lua_State *L) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Creates a table on the lua stack */
|
||||
static void lua_push_publish_hash_metatable(liServer *srv, liWorker *wrk, lua_State *L);
|
||||
|
||||
static int lua_str_hash_index(lua_State *L) {
|
||||
static int _lua_dynamic_hash_index_call(lua_State *L) {
|
||||
liServer *srv;
|
||||
liWorker *wrk;
|
||||
GHashTable *ht;
|
||||
LuaWrapper wrapper;
|
||||
const char *key;
|
||||
|
||||
srv = (liServer*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
wrk = (liWorker*) lua_touserdata(L, lua_upvalueindex(2));
|
||||
lua_pushstring(L, "__ht"); lua_rawget(L, 1);
|
||||
ht = (GHashTable*) lua_touserdata(L, -1); lua_pop(L, 1);
|
||||
lua_pushstring(L, "__wrapper"); lua_rawget(L, 1);
|
||||
wrapper = (LuaWrapper)(intptr_t) lua_touserdata(L, -1); lua_pop(L, 1);
|
||||
if (!lua_isstring(L, 2) || !ht || !wrapper) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
lua_pushstring(L, "lookup failed (lua_str_hash_index)");
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
wrapper = (LuaWrapper)(intptr_t) lua_touserdata(L, lua_upvalueindex(3));
|
||||
key = luaL_checklstring(L, lua_upvalueindex(4), NULL);
|
||||
|
||||
/* TRACE(srv, "str hash index: '%s'", luaL_checklstring(L, 2, NULL)); */
|
||||
return wrapper(srv, wrk, L, key);
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushlightuserdata(L, ht);
|
||||
lua_setfield(L, -2, "__ht");
|
||||
lua_pushlightuserdata(L, (void*)(intptr_t)wrapper);
|
||||
lua_setfield(L, -2, "__wrapper");
|
||||
/* downside of this dynamic hash: you always get a function back on __index,
|
||||
* no matter whether the key actually exists
|
||||
*/
|
||||
static int _lua_dynamic_hash_index(lua_State *L) {
|
||||
int key_ndx;
|
||||
|
||||
lua_pushvalue(L, lua_upvalueindex(4));
|
||||
lua_pushvalue(L, 2);
|
||||
lua_concat(L, 2);
|
||||
key_ndx = lua_gettop(L);
|
||||
|
||||
lua_newtable(L); /* result */
|
||||
lua_newtable(L); /* meta table */
|
||||
|
||||
/* call method */
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_pushvalue(L, lua_upvalueindex(2));
|
||||
lua_pushvalue(L, lua_upvalueindex(3));
|
||||
lua_pushvalue(L, key_ndx);
|
||||
lua_pushcclosure(L, _lua_dynamic_hash_index_call, 4);
|
||||
lua_setfield(L, -2, "__call");
|
||||
|
||||
/* index for "nested" keys */
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_pushvalue(L, lua_upvalueindex(2));
|
||||
lua_pushvalue(L, lua_upvalueindex(3));
|
||||
lua_pushvalue(L, key_ndx); /* append a "." to the current key for nesting */
|
||||
lua_pushstring(L, ".");
|
||||
lua_concat(L, 2);
|
||||
lua_pushcclosure(L, _lua_dynamic_hash_index, 4);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushstring(L, "__key"); lua_rawget(L, 1);
|
||||
if (lua_isstring(L, -1)) {
|
||||
lua_pushstring(L, ".");
|
||||
lua_pushvalue(L, 2);
|
||||
lua_concat(L, 3);
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
lua_pushvalue(L, 2);
|
||||
}
|
||||
lua_setfield(L, -2, "__key");
|
||||
|
||||
lua_push_publish_hash_metatable(srv, wrk, L);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_str_hash_call(lua_State *L) {
|
||||
liServer *srv;
|
||||
liWorker *wrk;
|
||||
GHashTable *ht;
|
||||
LuaWrapper wrapper;
|
||||
const char *key;
|
||||
gpointer d;
|
||||
|
||||
srv = (liServer*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
wrk = (liWorker*) lua_touserdata(L, lua_upvalueindex(2));
|
||||
lua_pushstring(L, "__ht"); lua_rawget(L, 1);
|
||||
ht = (GHashTable*) lua_touserdata(L, -1); lua_pop(L, 1);
|
||||
lua_pushstring(L, "__wrapper"); lua_rawget(L, 1);
|
||||
wrapper = (LuaWrapper)(intptr_t) lua_touserdata(L, -1); lua_pop(L, 1);
|
||||
lua_pushstring(L, "__key"); lua_rawget(L, 1);
|
||||
key = luaL_checklstring(L, -1, NULL);
|
||||
|
||||
/* DEBUG(srv, "str hash call: '%s'", key); */
|
||||
|
||||
if (key && NULL != (d = g_hash_table_lookup(ht, key))) {
|
||||
lua_pop(L, 1);
|
||||
return wrapper(srv, wrk, L, d);
|
||||
}
|
||||
|
||||
lua_pop(L, lua_gettop(L));
|
||||
lua_pushstring(L, "lookup '");
|
||||
lua_pushstring(L, key);
|
||||
lua_pushstring(L, "' failed (lua_str_hash_call)");
|
||||
lua_concat(L, 3);
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LUA_PUBLISH_HASH "GHashTable*"
|
||||
static void lua_push_publish_hash_metatable(liServer *srv, liWorker *wrk, lua_State *L) {
|
||||
if (luaL_newmetatable(L, LUA_PUBLISH_HASH)) {
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushlightuserdata(L, wrk);
|
||||
lua_pushcclosure(L, lua_str_hash_index, 2);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushlightuserdata(L, wrk);
|
||||
lua_pushcclosure(L, lua_str_hash_call, 2);
|
||||
lua_setfield(L, -2, "__call");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean li_lua_config_publish_str_hash(liServer *srv, liWorker *wrk, lua_State *L, GHashTable *ht, LuaWrapper wrapper) {
|
||||
lua_newtable(L); /* { } */
|
||||
lua_pushlightuserdata(L, ht);
|
||||
lua_setfield(L, -2, "__ht");
|
||||
lua_pushlightuserdata(L, (void*)(intptr_t)wrapper);
|
||||
lua_setfield(L, -2, "__wrapper");
|
||||
|
||||
lua_push_publish_hash_metatable(srv, wrk, L);
|
||||
static void lua_push_dynamic_hash(liServer *srv, liWorker *wrk, lua_State *L, LuaWrapper wrapper) {
|
||||
lua_newtable(L);
|
||||
lua_newtable(L); /* meta table */
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushlightuserdata(L, wrk);
|
||||
lua_pushlightuserdata(L, (void*)(intptr_t) wrapper);
|
||||
lua_pushstring(L, ""); /* nesting starts at "root" with empty string */
|
||||
lua_pushcclosure(L, _lua_dynamic_hash_index, 4);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_setmetatable(L, -2);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *L, gpointer _sa) {
|
||||
liServerAction *sa = (liServerAction*) _sa;
|
||||
liValue *val;
|
||||
static int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *L, const char *key) {
|
||||
liAction *a;
|
||||
liValue *val;
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
|
||||
lua_checkstack(L, 16);
|
||||
|
@ -149,9 +104,7 @@ int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *
|
|||
|
||||
li_lua_unlock(LL);
|
||||
|
||||
/* TRACE(srv, "%s", "Creating action"); */
|
||||
a = sa->create_action(srv, wrk, sa->p, val, sa->userdata);
|
||||
li_value_free(val);
|
||||
a = li_plugin_config_action(srv, wrk, key, val);
|
||||
|
||||
li_lua_lock(LL);
|
||||
|
||||
|
@ -163,31 +116,38 @@ int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *
|
|||
return li_lua_push_action(srv, L, a);
|
||||
}
|
||||
|
||||
int li_lua_config_handle_server_setup(liServer *srv, liWorker *wrk, lua_State *L, gpointer _ss) {
|
||||
liServerSetup *ss = (liServerSetup*) _ss;
|
||||
void li_lua_push_action_table(liServer *srv, liWorker *wrk, lua_State *L) {
|
||||
lua_push_dynamic_hash(srv, wrk, L, li_lua_config_handle_server_action);
|
||||
}
|
||||
|
||||
static int li_lua_config_handle_server_setup(liServer *srv, liWorker *wrk, lua_State *L, const char *key) {
|
||||
gboolean result;
|
||||
liValue *val;
|
||||
gboolean res;
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
UNUSED(wrk);
|
||||
assert(srv->main_worker == wrk);
|
||||
|
||||
lua_checkstack(L, 16);
|
||||
val = lua_params_to_value(srv, L);
|
||||
|
||||
li_lua_unlock(LL);
|
||||
/* TRACE(srv, "%s", "Calling setup"); */
|
||||
res = ss->setup(srv, ss->p, val, ss->userdata);
|
||||
|
||||
result = li_plugin_config_setup(srv, key, val);
|
||||
|
||||
li_lua_lock(LL);
|
||||
|
||||
if (!res) {
|
||||
li_value_free(val);
|
||||
if (!result) {
|
||||
lua_pushstring(L, "setup failed");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
li_value_free(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void li_lua_push_setup_table(liServer *srv, liWorker *wrk, lua_State *L) {
|
||||
assert(srv->main_worker == wrk);
|
||||
lua_push_dynamic_hash(srv, wrk, L, li_lua_config_handle_server_setup);
|
||||
}
|
||||
|
||||
gboolean li_config_lua_load(liLuaState *LL, liServer *srv, liWorker *wrk, const gchar *filename, liAction **pact, gboolean allow_setup, liValue *args) {
|
||||
int errfunc;
|
||||
int lua_stack_top;
|
||||
|
@ -209,11 +169,12 @@ gboolean li_config_lua_load(liLuaState *LL, liServer *srv, liWorker *wrk, const
|
|||
_DEBUG(srv, wrk, NULL, "Loaded config script '%s'", filename);
|
||||
|
||||
if (allow_setup) {
|
||||
li_lua_config_publish_str_hash(srv, wrk, L, srv->setups, li_lua_config_handle_server_setup);
|
||||
assert(wrk == srv->main_worker);
|
||||
li_lua_push_setup_table(srv, wrk, L);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "setup");
|
||||
}
|
||||
|
||||
li_lua_config_publish_str_hash(srv, wrk, L, srv->actions, li_lua_config_handle_server_action);
|
||||
li_lua_push_action_table(srv, wrk, L);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "action");
|
||||
|
||||
li_lua_push_lvalues_dict(srv, L);
|
||||
|
|
|
@ -684,26 +684,20 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
|
|||
g_array_append_val(al->data.list, a);
|
||||
}
|
||||
/* setup action */
|
||||
else if (ctx->in_setup_block && NULL != g_hash_table_lookup(srv->setups, name->data.string->str)) {
|
||||
else if (ctx->in_setup_block) {
|
||||
_printf("%s", "... which is a setup action\n");
|
||||
|
||||
if (!li_call_setup(srv, name->data.string->str, val)) {
|
||||
if (!li_plugin_config_setup(srv, name->data.string->str, val)) {
|
||||
li_value_free(name);
|
||||
if (val)
|
||||
li_value_free(val);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (val)
|
||||
li_value_free(val);
|
||||
}
|
||||
/* normal action */
|
||||
else if (!ctx->in_setup_block && NULL != g_hash_table_lookup(srv->actions, name->data.string->str)) {
|
||||
else {
|
||||
_printf("%s", "... which is a normal action\n");
|
||||
|
||||
al = g_queue_peek_head(ctx->action_list_stack);
|
||||
a = li_create_action(srv, srv->main_worker, name->data.string->str, val);
|
||||
li_value_free(val);
|
||||
a = li_plugin_config_action(srv, srv->main_worker, name->data.string->str, val);
|
||||
|
||||
if (a == NULL) {
|
||||
li_value_free(name);
|
||||
|
@ -712,52 +706,6 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
|
|||
|
||||
g_array_append_val(al->data.list, a);
|
||||
}
|
||||
/* option assignment */
|
||||
else if (NULL != g_hash_table_lookup(srv->optionptrs, name->data.string->str) || NULL != g_hash_table_lookup(srv->options, name->data.string->str)) {
|
||||
_printf("%s", "... which is an option assignment\n");
|
||||
|
||||
if (!val) {
|
||||
WARNING(srv, "action %s takes a parameter", name->data.string->str);
|
||||
li_value_free(name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ctx->in_setup_block) {
|
||||
/* in setup { } block, override default values for options */
|
||||
if (!li_plugin_set_default_option(srv, name->data.string->str, val)) {
|
||||
ERROR(srv, "failed overriding default value for option \"%s\"", name->data.string->str);
|
||||
li_value_free(name);
|
||||
li_value_free(val);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
li_value_free(val);
|
||||
} else {
|
||||
/* normal assignment */
|
||||
a = li_option_action(srv, srv->main_worker, name->data.string->str, val);
|
||||
li_value_free(val);
|
||||
|
||||
if (a == NULL) {
|
||||
li_value_free(name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
al = g_queue_peek_head(ctx->action_list_stack);
|
||||
g_array_append_val(al->data.list, a);
|
||||
}
|
||||
} else {
|
||||
if (!ctx->in_setup_block && NULL != g_hash_table_lookup(srv->setups, name->data.string->str)) {
|
||||
WARNING(srv, "action %s can only be called in a setup block", name->data.string->str);
|
||||
} else if (ctx->in_setup_block && NULL != g_hash_table_lookup(srv->actions, name->data.string->str)) {
|
||||
WARNING(srv, "action %s can't be called in a setup block", name->data.string->str);
|
||||
} else {
|
||||
WARNING(srv, "unknown action %s", name->data.string->str);
|
||||
}
|
||||
if (val)
|
||||
li_value_free(val);
|
||||
li_value_free(name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
li_value_free(name);
|
||||
}
|
||||
|
@ -1528,7 +1476,7 @@ gboolean li_config_parse(liServer *srv, const gchar *config_path) {
|
|||
}
|
||||
|
||||
/* append fallback "static" action */
|
||||
a = li_create_action(srv, srv->main_worker, "static", NULL);
|
||||
a = li_plugin_config_action(srv, srv->main_worker, "static", NULL);
|
||||
g_array_append_val(srv->mainaction->data.list, a);
|
||||
|
||||
g_get_current_time(&end);
|
||||
|
|
|
@ -1,6 +1,66 @@
|
|||
|
||||
#include <lighttpd/base.h>
|
||||
|
||||
/* Internal structures */
|
||||
struct liServerOption {
|
||||
liPlugin *p;
|
||||
|
||||
/** the value is freed with li_value_free after the parse call, so you
|
||||
* probably want to extract pointers via li_value_extract_*
|
||||
* val is zero to get the global default value if nothing is specified
|
||||
* save result in value
|
||||
*
|
||||
* Default behaviour (NULL) is to extract the inner value from val
|
||||
*/
|
||||
liPluginParseOptionCB parse_option;
|
||||
|
||||
/** if parse_option is NULL, the default_value is used */
|
||||
gint64 default_value;
|
||||
|
||||
size_t index, module_index;
|
||||
liValueType type;
|
||||
};
|
||||
|
||||
struct liServerOptionPtr {
|
||||
liPlugin *p;
|
||||
|
||||
/** the value is freed with li_value_free after the parse call, so you
|
||||
* probably want to extract pointers via li_value_extract_*
|
||||
* val is zero to get the global default value if nothing is specified
|
||||
* save result in value
|
||||
*
|
||||
* Default behaviour (NULL) is to extract the inner value from val
|
||||
*/
|
||||
liPluginParseOptionPtrCB parse_option;
|
||||
|
||||
/** the free_option handler has to free all allocated resources;
|
||||
* it may get called with 0 initialized options, so you have to
|
||||
* check the value.
|
||||
*/
|
||||
liPluginFreeOptionPtrCB free_option;
|
||||
|
||||
/** if parse_option is NULL, the default_value is used; it is only used
|
||||
* for the following value types:
|
||||
* - STRING: used for g_string_new, i.e. a const char*
|
||||
*/
|
||||
gpointer default_value;
|
||||
|
||||
size_t index, module_index;
|
||||
liValueType type;
|
||||
};
|
||||
|
||||
struct liServerAction {
|
||||
liPlugin *p;
|
||||
liPluginCreateActionCB create_action;
|
||||
gpointer userdata;
|
||||
};
|
||||
|
||||
struct liServerSetup {
|
||||
liPlugin *p;
|
||||
liPluginSetupCB setup;
|
||||
gpointer userdata;
|
||||
};
|
||||
|
||||
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt);
|
||||
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt);
|
||||
static void li_plugin_free_default_options(liServer *srv, liPlugin *p);
|
||||
|
@ -81,9 +141,36 @@ void li_plugin_free(liServer *srv, liPlugin *p) {
|
|||
g_slice_free(liPlugin, p);
|
||||
}
|
||||
|
||||
static void server_option_free(gpointer _so) {
|
||||
g_slice_free(liServerOption, _so);
|
||||
}
|
||||
|
||||
static void server_optionptr_free(gpointer _so) {
|
||||
g_slice_free(liServerOptionPtr, _so);
|
||||
}
|
||||
|
||||
static void server_action_free(gpointer _sa) {
|
||||
g_slice_free(liServerAction, _sa);
|
||||
}
|
||||
|
||||
static void server_setup_free(gpointer _ss) {
|
||||
g_slice_free(liServerSetup, _ss);
|
||||
}
|
||||
|
||||
void li_server_plugins_init(liServer *srv) {
|
||||
srv->plugins = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
srv->options = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_option_free);
|
||||
srv->optionptrs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_optionptr_free);
|
||||
srv->actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_action_free);
|
||||
srv->setups = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_setup_free);
|
||||
|
||||
srv->li_plugins_handle_close = g_array_new(FALSE, TRUE, sizeof(liPlugin*));
|
||||
srv->li_plugins_handle_vrclose = g_array_new(FALSE, TRUE, sizeof(liPlugin*));
|
||||
srv->option_def_values = g_array_new(FALSE, TRUE, sizeof(liOptionValue));
|
||||
srv->optionptr_def_values = g_array_new(FALSE, TRUE, sizeof(liOptionPtrValue*));
|
||||
}
|
||||
|
||||
void li_server_plugins_free(liServer *srv) {
|
||||
gpointer key, val;
|
||||
GHashTableIter i;
|
||||
liServerState s;
|
||||
|
||||
s = g_atomic_int_get(&srv->state);
|
||||
|
@ -92,23 +179,76 @@ void li_server_plugins_free(liServer *srv) {
|
|||
return;
|
||||
}
|
||||
|
||||
g_hash_table_iter_init(&i, srv->plugins);
|
||||
while (g_hash_table_iter_next(&i, &key, &val)) {
|
||||
liPlugin *p = (liPlugin*) val;
|
||||
g_array_free(srv->option_def_values, TRUE);
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; i < srv->optionptr_def_values->len; i++) {
|
||||
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, i));
|
||||
}
|
||||
}
|
||||
g_array_free(srv->optionptr_def_values, TRUE);
|
||||
|
||||
li_plugin_free_options(srv, p);
|
||||
li_plugin_free_actions(srv, p);
|
||||
li_plugin_free_setups(srv, p);
|
||||
if (p->free)
|
||||
p->free(srv, p);
|
||||
{
|
||||
gpointer key, val;
|
||||
GHashTableIter i;
|
||||
g_hash_table_iter_init(&i, srv->plugins);
|
||||
while (g_hash_table_iter_next(&i, &key, &val)) {
|
||||
liPlugin *p = (liPlugin*) val;
|
||||
|
||||
g_slice_free(liPlugin, p);
|
||||
li_plugin_free_options(srv, p);
|
||||
li_plugin_free_actions(srv, p);
|
||||
li_plugin_free_setups(srv, p);
|
||||
if (p->free)
|
||||
p->free(srv, p);
|
||||
|
||||
g_slice_free(liPlugin, p);
|
||||
}
|
||||
}
|
||||
g_hash_table_destroy(srv->plugins);
|
||||
g_hash_table_destroy(srv->options);
|
||||
g_hash_table_destroy(srv->optionptrs);
|
||||
g_hash_table_destroy(srv->actions);
|
||||
g_hash_table_destroy(srv->setups);
|
||||
|
||||
g_array_free(srv->li_plugins_handle_close, TRUE);
|
||||
g_array_free(srv->li_plugins_handle_vrclose, TRUE);
|
||||
}
|
||||
|
||||
static gboolean check_name_free(liServer *srv, liPlugin *p, const gchar *name, gboolean setup_ns, gboolean action_ns) {
|
||||
liServerOption *so;
|
||||
liServerOptionPtr *sop;
|
||||
liServerAction *sa;
|
||||
liServerSetup *ss;
|
||||
|
||||
if (NULL != (so = (liServerOption*)g_hash_table_lookup(srv->options, name))) {
|
||||
ERROR(srv, "Name conflict: option '%s' already registered by plugin '%s', unloading '%s'",
|
||||
name,
|
||||
NULL != so->p ? so->p->name : "<none>",
|
||||
p->name);
|
||||
return FALSE;
|
||||
}
|
||||
if (NULL != (sop = (liServerOptionPtr*)g_hash_table_lookup(srv->optionptrs, name))) {
|
||||
ERROR(srv, "Name conflict: option '%s' already registered by plugin '%s', unloading '%s'",
|
||||
name,
|
||||
NULL != sop->p ? sop->p->name : "<none>",
|
||||
p->name);
|
||||
return FALSE;
|
||||
}
|
||||
if (action_ns && NULL != (sa = (liServerAction*)g_hash_table_lookup(srv->actions, name))) {
|
||||
ERROR(srv, "Name conflict: action '%s' already registered by plugin '%s', unloading '%s'",
|
||||
name,
|
||||
NULL != sa->p ? sa->p->name : "<none>",
|
||||
p->name);
|
||||
return FALSE;
|
||||
}
|
||||
if (setup_ns && NULL != (ss = (liServerSetup*)g_hash_table_lookup(srv->setups, name))) {
|
||||
ERROR(srv, "Name conflict: setup '%s' already registered by plugin '%s', unloading '%s'",
|
||||
name,
|
||||
NULL != ss->p ? ss->p->name : "<none>",
|
||||
p->name);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB init, gpointer userdata) {
|
||||
|
@ -142,26 +282,10 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
|
|||
if (p->options) {
|
||||
size_t i;
|
||||
liServerOption *so;
|
||||
liServerOptionPtr *sop;
|
||||
const liPluginOption *po;
|
||||
|
||||
for (i = 0; (po = &p->options[i])->name; i++) {
|
||||
if (NULL != (so = (liServerOption*)g_hash_table_lookup(srv->options, po->name))) {
|
||||
ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'",
|
||||
po->name,
|
||||
so->p ? so->p->name : "<none>",
|
||||
p->name);
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
if (NULL != (sop = (liServerOptionPtr*)g_hash_table_lookup(srv->optionptrs, po->name))) {
|
||||
ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'",
|
||||
po->name,
|
||||
sop->p ? sop->p->name : "<none>",
|
||||
p->name);
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
if (!check_name_free(srv, p, po->name, TRUE, TRUE)) goto fail;
|
||||
so = g_slice_new0(liServerOption);
|
||||
so->type = po->type;
|
||||
so->parse_option = po->parse_option;
|
||||
|
@ -176,27 +300,11 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
|
|||
|
||||
if (p->optionptrs) {
|
||||
size_t i;
|
||||
liServerOption *so_;
|
||||
liServerOptionPtr *so;
|
||||
const liPluginOptionPtr *po;
|
||||
|
||||
for (i = 0; (po = &p->optionptrs[i])->name; i++) {
|
||||
if (NULL != (so_ = (liServerOption*)g_hash_table_lookup(srv->options, po->name))) {
|
||||
ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'",
|
||||
po->name,
|
||||
so_->p ? so_->p->name : "<none>",
|
||||
p->name);
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
if (NULL != (so = (liServerOptionPtr*)g_hash_table_lookup(srv->optionptrs, po->name))) {
|
||||
ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'",
|
||||
po->name,
|
||||
so->p ? so->p->name : "<none>",
|
||||
p->name);
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
if (!check_name_free(srv, p, po->name, TRUE, TRUE)) goto fail;
|
||||
so = g_slice_new0(liServerOptionPtr);
|
||||
so->type = po->type;
|
||||
so->parse_option = po->parse_option;
|
||||
|
@ -216,14 +324,7 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
|
|||
const liPluginAction *pa;
|
||||
|
||||
for (i = 0; (pa = &p->actions[i])->name; i++) {
|
||||
if (NULL != (sa = (liServerAction*)g_hash_table_lookup(srv->actions, pa->name))) {
|
||||
ERROR(srv, "Action '%s' already registered by plugin '%s', unloading '%s'",
|
||||
pa->name,
|
||||
sa->p ? sa->p->name : "<none>",
|
||||
p->name);
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
if (!check_name_free(srv, p, pa->name, FALSE, TRUE)) goto fail;
|
||||
sa = g_slice_new0(liServerAction);
|
||||
sa->create_action = pa->create_action;
|
||||
sa->p = p;
|
||||
|
@ -238,14 +339,7 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
|
|||
const liPluginSetup *ps;
|
||||
|
||||
for (i = 0; (ps = &p->setups[i])->name; i++) {
|
||||
if (NULL != (ss = (liServerSetup*)g_hash_table_lookup(srv->setups, ps->name))) {
|
||||
ERROR(srv, "Setup '%s' already registered by plugin '%s', unloading '%s'",
|
||||
ps->name,
|
||||
ss->p ? ss->p->name : "<none>",
|
||||
p->name);
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
if (!check_name_free(srv, p, ps->name, TRUE, FALSE)) goto fail;
|
||||
ss = g_slice_new0(liServerSetup);
|
||||
ss->setup = ps->setup;
|
||||
ss->p = p;
|
||||
|
@ -255,6 +349,10 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
|
|||
}
|
||||
|
||||
return p;
|
||||
|
||||
fail:
|
||||
li_plugin_free(srv, p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -263,7 +361,7 @@ static liServerOption* find_option(liServer *srv, const char *name) {
|
|||
}
|
||||
|
||||
static gboolean li_parse_option(liServer *srv, liWorker *wrk, liServerOption *sopt, const char *name, liValue *val, liOptionSet *mark) {
|
||||
if (!srv || !wrk || !name || !mark || !sopt) return FALSE;
|
||||
assert(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != val && NULL != mark);
|
||||
|
||||
if (sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
|
||||
ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s",
|
||||
|
@ -304,7 +402,7 @@ static gboolean li_parse_optionptr(liServer *srv, liWorker *wrk, liServerOptionP
|
|||
liOptionPtrValue *oval;
|
||||
gpointer ptr = NULL;
|
||||
|
||||
if (!srv || !wrk || !name || !mark || !sopt) return FALSE;
|
||||
assert(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != val && NULL != mark);
|
||||
|
||||
if (sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
|
||||
ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s",
|
||||
|
@ -338,8 +436,9 @@ static gboolean li_parse_optionptr(liServer *srv, liWorker *wrk, liServerOptionP
|
|||
|
||||
void li_release_optionptr(liServer *srv, liOptionPtrValue *value) {
|
||||
liServerOptionPtr *sopt;
|
||||
assert(NULL != srv);
|
||||
|
||||
if (!srv || !value) return;
|
||||
if (NULL == value) return;
|
||||
|
||||
assert(g_atomic_int_get(&value->refcount) > 0);
|
||||
if (!g_atomic_int_dec_and_test(&value->refcount)) return;
|
||||
|
@ -380,63 +479,75 @@ void li_release_optionptr(liServer *srv, liOptionPtrValue *value) {
|
|||
g_slice_free(liOptionPtrValue, value);
|
||||
}
|
||||
|
||||
liAction* li_option_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val) {
|
||||
liAction *li_plugin_config_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val) {
|
||||
liAction *a = NULL;
|
||||
liServerAction *sa;
|
||||
liServerOption *sopt;
|
||||
liServerOptionPtr *soptptr;
|
||||
|
||||
if (NULL != (sopt = find_option(srv, name))) {
|
||||
if (NULL != (sa = (liServerAction*) g_hash_table_lookup(srv->actions, name))) {
|
||||
if (NULL == (a = sa->create_action(srv, wrk, sa->p, val, sa->userdata))) {
|
||||
ERROR(srv, "Action '%s' creation failed", name);
|
||||
}
|
||||
} else if (NULL != (sopt = find_option(srv, name))) {
|
||||
liOptionSet setting;
|
||||
|
||||
if (!li_parse_option(srv, wrk, sopt, name, val, &setting)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!li_parse_option(srv, wrk, sopt, name, val, &setting)) goto exit;
|
||||
|
||||
return li_action_new_setting(setting);
|
||||
a = li_action_new_setting(setting);
|
||||
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
|
||||
liOptionPtrSet setting;
|
||||
|
||||
if (!li_parse_optionptr(srv, wrk, soptptr, name, val, &setting)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!li_parse_optionptr(srv, wrk, soptptr, name, val, &setting)) goto exit;
|
||||
|
||||
return li_action_new_settingptr(setting);
|
||||
a = li_action_new_settingptr(setting);
|
||||
} else if (NULL != g_hash_table_lookup(srv->setups, name)) {
|
||||
ERROR(srv, "'%s' can only be called in a setup block", name);
|
||||
} else {
|
||||
ERROR(srv, "Unknown option '%s'", name);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
liAction* li_create_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val) {
|
||||
liAction *a;
|
||||
liServerAction *sa;
|
||||
|
||||
if (NULL == (sa = (liServerAction*) g_hash_table_lookup(srv->actions, name))) {
|
||||
ERROR(srv, "Action '%s' doesn't exist", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NULL == (a = sa->create_action(srv, wrk, sa->p, val, sa->userdata))) {
|
||||
ERROR(srv, "Action '%s' creation failed", name);
|
||||
return NULL;
|
||||
ERROR(srv, "unknown action %s", name);
|
||||
}
|
||||
|
||||
exit:
|
||||
li_value_free(val);
|
||||
return a;
|
||||
}
|
||||
|
||||
gboolean li_call_setup(liServer *srv, const char *name, liValue *val) {
|
||||
gboolean li_plugin_config_setup(liServer *srv, const char *name, liValue *val) {
|
||||
gboolean result = FALSE;
|
||||
liServerSetup *ss;
|
||||
liServerOption *sopt;
|
||||
liServerOptionPtr *soptptr;
|
||||
|
||||
if (NULL == (ss = (liServerSetup*) g_hash_table_lookup(srv->setups, name))) {
|
||||
ERROR(srv, "Setup function '%s' doesn't exist", name);
|
||||
return FALSE;
|
||||
if (NULL != (ss = (liServerSetup*) g_hash_table_lookup(srv->setups, name))) {
|
||||
if (!ss->setup(srv, ss->p, val, ss->userdata)) {
|
||||
ERROR(srv, "Setup '%s' failed", name);
|
||||
goto exit;
|
||||
}
|
||||
result = TRUE;
|
||||
} else if (NULL != (sopt = find_option(srv, name))) {
|
||||
liOptionSet setting;
|
||||
|
||||
if (!li_parse_option(srv, srv->main_worker, sopt, name, val, &setting)) goto exit;
|
||||
|
||||
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value;
|
||||
result = TRUE;
|
||||
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
|
||||
liOptionPtrSet setting;
|
||||
|
||||
if (!li_parse_optionptr(srv, srv->main_worker, soptptr, name, val, &setting)) goto exit;
|
||||
|
||||
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index));
|
||||
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index) = setting.value;
|
||||
result = TRUE;
|
||||
} else if (NULL != g_hash_table_lookup(srv->setups, name)) {
|
||||
ERROR(srv, "'%s' can only be called in a setup block", name);
|
||||
} else {
|
||||
ERROR(srv, "unknown setup %s", name);
|
||||
}
|
||||
|
||||
if (!ss->setup(srv, ss->p, val, ss->userdata)) {
|
||||
ERROR(srv, "Setup '%s' failed", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
exit:
|
||||
li_value_free(val);
|
||||
return result;
|
||||
}
|
||||
|
||||
void li_plugins_prepare_callbacks(liServer *srv) {
|
||||
|
@ -472,38 +583,6 @@ void li_plugins_handle_vrclose(liVRequest *vr) {
|
|||
}
|
||||
}
|
||||
|
||||
gboolean li_plugin_set_default_option(liServer* srv, const gchar* name, liValue* val) {
|
||||
liServerOption *sopt;
|
||||
liServerOptionPtr *soptptr;
|
||||
|
||||
if (NULL != (sopt = find_option(srv, name))) {
|
||||
liOptionSet setting;
|
||||
|
||||
/* assign new value */
|
||||
if (!li_parse_option(srv, srv->main_worker, sopt, name, val, &setting)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value;
|
||||
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
|
||||
liOptionPtrSet setting;
|
||||
|
||||
/* assign new value */
|
||||
if (!li_parse_optionptr(srv, srv->main_worker, soptptr, name, val, &setting)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index));
|
||||
|
||||
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index) = setting.value;
|
||||
} else {
|
||||
ERROR(srv, "unknown option \"%s\"", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt) {
|
||||
liOptionValue oval = {0};
|
||||
|
||||
|
|
|
@ -101,58 +101,6 @@ static liAction* core_when(liServer *srv, liWorker *wrk, liPlugin* p, liValue *v
|
|||
return a;
|
||||
}
|
||||
|
||||
static liAction* core_set(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
||||
liValue *val_val, *val_name;
|
||||
liAction *a;
|
||||
UNUSED(p); UNUSED(userdata);
|
||||
|
||||
if (!val) {
|
||||
ERROR(srv, "%s", "need parameter");
|
||||
return NULL;
|
||||
}
|
||||
if (val->type != LI_VALUE_LIST) {
|
||||
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
|
||||
return NULL;
|
||||
}
|
||||
if (val->data.list->len != 2) {
|
||||
ERROR(srv, "expected list with length 2, has length %u", val->data.list->len);
|
||||
return NULL;
|
||||
}
|
||||
val_name = g_array_index(val->data.list, liValue*, 0);
|
||||
val_val = g_array_index(val->data.list, liValue*, 1);
|
||||
if (val_name->type != LI_VALUE_STRING) {
|
||||
ERROR(srv, "expected string as first parameter, got %s", li_value_type_string(val_name->type));
|
||||
return NULL;
|
||||
}
|
||||
a = li_option_action(srv, wrk, val_name->data.string->str, val_val);
|
||||
return a;
|
||||
}
|
||||
|
||||
static gboolean core_setup_set(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
||||
liValue *val_val, *val_name;
|
||||
UNUSED(p); UNUSED(userdata);
|
||||
|
||||
if (!val) {
|
||||
ERROR(srv, "%s", "need parameter");
|
||||
return FALSE;
|
||||
}
|
||||
if (val->type != LI_VALUE_LIST) {
|
||||
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
|
||||
return FALSE;
|
||||
}
|
||||
if (val->data.list->len != 2) {
|
||||
ERROR(srv, "expected list with length 2, has length %u", val->data.list->len);
|
||||
return FALSE;
|
||||
}
|
||||
val_name = g_array_index(val->data.list, liValue*, 0);
|
||||
val_val = g_array_index(val->data.list, liValue*, 1);
|
||||
if (val_name->type != LI_VALUE_STRING) {
|
||||
ERROR(srv, "expected string as first parameter, got %s", li_value_type_string(val_name->type));
|
||||
return FALSE;
|
||||
}
|
||||
return li_plugin_set_default_option(srv, val_name->data.string->str, val_val);
|
||||
}
|
||||
|
||||
typedef struct docroot_split docroot_split;
|
||||
struct docroot_split {
|
||||
GString *hostname;
|
||||
|
@ -2105,7 +2053,6 @@ static const liPluginOptionPtr optionptrs[] = {
|
|||
static const liPluginAction actions[] = {
|
||||
{ "list", core_list, NULL },
|
||||
{ "when", core_when, NULL },
|
||||
{ "set", core_set, NULL },
|
||||
|
||||
{ "docroot", core_docroot, NULL },
|
||||
{ "alias", core_alias, NULL },
|
||||
|
@ -2145,7 +2092,6 @@ static const liPluginAction actions[] = {
|
|||
};
|
||||
|
||||
static const liPluginSetup setups[] = {
|
||||
{ "set_default", core_setup_set, NULL },
|
||||
{ "listen", core_listen, NULL },
|
||||
{ "workers", core_workers, NULL },
|
||||
{ "workers.cpu_affinity", core_workers_cpu_affinity, NULL },
|
||||
|
|
|
@ -44,22 +44,6 @@ void li_server_socket_acquire(liServerSocket* sock) {
|
|||
g_atomic_int_inc(&sock->refcount);
|
||||
}
|
||||
|
||||
static void server_option_free(gpointer _so) {
|
||||
g_slice_free(liServerOption, _so);
|
||||
}
|
||||
|
||||
static void server_optionptr_free(gpointer _so) {
|
||||
g_slice_free(liServerOptionPtr, _so);
|
||||
}
|
||||
|
||||
static void server_action_free(gpointer _sa) {
|
||||
g_slice_free(liServerAction, _sa);
|
||||
}
|
||||
|
||||
static void server_setup_free(gpointer _ss) {
|
||||
g_slice_free(liServerSetup, _ss);
|
||||
}
|
||||
|
||||
static void server_fetch_db_free(gpointer db) {
|
||||
li_fetch_database_release((liFetchDatabase*) db);
|
||||
}
|
||||
|
@ -104,19 +88,10 @@ liServer* li_server_new(const gchar *module_dir, gboolean module_resident) {
|
|||
|
||||
srv->modules = li_modules_new(srv, module_dir, module_resident);
|
||||
|
||||
srv->plugins = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
srv->options = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_option_free);
|
||||
srv->optionptrs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_optionptr_free);
|
||||
srv->actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_action_free);
|
||||
srv->setups = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_setup_free);
|
||||
li_server_plugins_init(srv);
|
||||
|
||||
srv->prepare_callbacks = g_array_new(FALSE, TRUE, sizeof(liServerPrepareCallbackData));
|
||||
|
||||
srv->li_plugins_handle_close = g_array_new(FALSE, TRUE, sizeof(liPlugin*));
|
||||
srv->li_plugins_handle_vrclose = g_array_new(FALSE, TRUE, sizeof(liPlugin*));
|
||||
srv->option_def_values = g_array_new(FALSE, TRUE, sizeof(liOptionValue));
|
||||
srv->optionptr_def_values = g_array_new(FALSE, TRUE, sizeof(liOptionPtrValue*));
|
||||
|
||||
srv->mainaction = NULL;
|
||||
|
||||
srv->action_mutex = g_mutex_new();
|
||||
|
@ -251,17 +226,7 @@ void li_server_free(liServer* srv) {
|
|||
g_array_free(srv->ts_formats, TRUE);
|
||||
}
|
||||
|
||||
g_array_free(srv->option_def_values, TRUE);
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; i < srv->optionptr_def_values->len; i++) {
|
||||
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, i));
|
||||
}
|
||||
}
|
||||
g_array_free(srv->optionptr_def_values, TRUE);
|
||||
li_server_plugins_free(srv);
|
||||
g_array_free(srv->li_plugins_handle_close, TRUE);
|
||||
g_array_free(srv->li_plugins_handle_vrclose, TRUE);
|
||||
|
||||
if (NULL != srv->prepare_callbacks) {
|
||||
guint i, len;
|
||||
|
|
|
@ -492,10 +492,10 @@ static gboolean lua_plugin_load(liServer *srv, liPlugin *p, GString *filename, l
|
|||
goto failed_unlock_lua;
|
||||
}
|
||||
|
||||
li_lua_config_publish_str_hash(srv, srv->main_worker, L, srv->setups, li_lua_config_handle_server_setup);
|
||||
li_lua_push_setup_table(srv, srv->main_worker, L);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "setup");
|
||||
|
||||
li_lua_config_publish_str_hash(srv, srv->main_worker, L, srv->actions, li_lua_config_handle_server_action);
|
||||
li_lua_push_action_table(srv, srv->main_worker, L);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "action");
|
||||
|
||||
li_lua_push_lvalues_dict(srv, L);
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from base import *
|
||||
from requests import *
|
||||
|
||||
LUA_TEST_OPTIONS="""
|
||||
|
||||
setup["server.tag"]("lighttpd 2.0 with lua")
|
||||
|
||||
function changetag(tag)
|
||||
return action["server.tag"](tag)
|
||||
end
|
||||
|
||||
actions = {
|
||||
["lua.changetag"] = changetag
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
class TestSetupOption(CurlRequest):
|
||||
URL = "/"
|
||||
EXPECT_RESPONSE_HEADERS = [("Server", "lighttpd 2.0 with lua")]
|
||||
|
||||
class TestChangeOption(CurlRequest):
|
||||
URL = "/?change"
|
||||
EXPECT_RESPONSE_HEADERS = [("Server", "lighttpd 2.0 with modified lua")]
|
||||
|
||||
class Test(GroupTest):
|
||||
group = [
|
||||
TestSetupOption, TestChangeOption,
|
||||
]
|
||||
|
||||
def Prepare(self):
|
||||
test_options_lua = self.PrepareFile("lua/test_options.lua", LUA_TEST_OPTIONS)
|
||||
self.plain_config = """
|
||||
setup {{ lua.plugin "{test_options_lua}"; }}
|
||||
""".format(test_options_lua = test_options_lua)
|
||||
self.config = """
|
||||
if req.query == "change" {
|
||||
lua.changetag "lighttpd 2.0 with modified lua";
|
||||
}
|
||||
"""
|
Loading…
Reference in New Issue