2008-07-08 19:29:02 +00:00
|
|
|
|
2008-11-16 20:33:53 +00:00
|
|
|
#include <lighttpd/base.h>
|
2008-07-08 19:29:02 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt);
|
2010-01-24 20:30:41 +00:00
|
|
|
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt);
|
2009-07-09 20:17:24 +00:00
|
|
|
static void li_plugin_free_default_options(liServer *srv, liPlugin *p);
|
2008-10-01 22:13:07 +00:00
|
|
|
|
2010-01-27 16:15:25 +00:00
|
|
|
liOptionPtrValue li_option_ptr_zero = { 0, { 0 } , 0 };
|
2010-01-24 20:30:41 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liPlugin* plugin_new(const gchar *name) {
|
|
|
|
liPlugin *p = g_slice_new0(liPlugin);
|
2008-07-23 16:01:19 +00:00
|
|
|
p->name = name;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
static void li_plugin_free_options(liServer *srv, liPlugin *p) {
|
2008-07-23 19:34:19 +00:00
|
|
|
size_t i;
|
2009-07-08 19:06:07 +00:00
|
|
|
const liPluginOption *po;
|
|
|
|
liServerOption *so;
|
2010-01-24 20:30:41 +00:00
|
|
|
const liPluginOptionPtr *pop;
|
|
|
|
liServerOptionPtr *sop;
|
2008-07-23 19:34:19 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
if (p->options) for (i = 0; (po = &p->options[i])->name; i++) {
|
2008-07-23 19:34:19 +00:00
|
|
|
if (NULL == (so = g_hash_table_lookup(srv->options, po->name))) break;
|
|
|
|
if (so->p != p) break;
|
|
|
|
g_hash_table_remove(srv->options, po->name);
|
|
|
|
}
|
2010-01-24 20:30:41 +00:00
|
|
|
|
|
|
|
if (p->optionptrs) for (i = 0; (pop = &p->optionptrs[i])->name; i++) {
|
|
|
|
if (NULL == (sop = g_hash_table_lookup(srv->optionptrs, pop->name))) break;
|
|
|
|
if (sop->p != p) break;
|
|
|
|
g_hash_table_remove(srv->optionptrs, pop->name);
|
|
|
|
}
|
2008-07-23 19:34:19 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
static void li_plugin_free_actions(liServer *srv, liPlugin *p) {
|
2008-07-23 19:34:19 +00:00
|
|
|
size_t i;
|
2009-07-08 19:06:07 +00:00
|
|
|
const liPluginAction *pa;
|
|
|
|
liServerAction *sa;
|
2008-07-23 19:34:19 +00:00
|
|
|
|
|
|
|
if (!p->actions) return;
|
|
|
|
for (i = 0; (pa = &p->actions[i])->name; i++) {
|
|
|
|
if (NULL == (sa = g_hash_table_lookup(srv->actions, pa->name))) break;
|
|
|
|
if (sa->p != p) break;
|
|
|
|
g_hash_table_remove(srv->actions, pa->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
static void li_plugin_free_setups(liServer *srv, liPlugin *p) {
|
2008-07-23 19:34:19 +00:00
|
|
|
size_t i;
|
2009-08-30 17:25:01 +00:00
|
|
|
const liPluginSetup *ps;
|
2009-07-08 19:06:07 +00:00
|
|
|
liServerSetup *ss;
|
2008-07-23 19:34:19 +00:00
|
|
|
|
|
|
|
if (!p->setups) return;
|
|
|
|
for (i = 0; (ps = &p->setups[i])->name; i++) {
|
|
|
|
if (NULL == (ss = g_hash_table_lookup(srv->setups, ps->name))) break;
|
|
|
|
if (ss->p != p) break;
|
|
|
|
g_hash_table_remove(srv->setups, ps->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_plugin_free(liServer *srv, liPlugin *p) {
|
2009-08-30 18:43:13 +00:00
|
|
|
liServerState s;
|
|
|
|
|
2008-07-23 16:01:19 +00:00
|
|
|
if (!p) return;
|
|
|
|
|
2009-08-30 18:43:13 +00:00
|
|
|
s = g_atomic_int_get(&srv->state);
|
|
|
|
if (LI_SERVER_INIT != s && LI_SERVER_DOWN != s) {
|
2008-08-08 16:49:00 +00:00
|
|
|
ERROR(srv, "Cannot free plugin '%s' while server is running", p->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-07-23 19:34:19 +00:00
|
|
|
g_hash_table_remove(srv->plugins, p->name);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_plugin_free_default_options(srv, p);
|
|
|
|
li_plugin_free_options(srv, p);
|
|
|
|
li_plugin_free_actions(srv, p);
|
|
|
|
li_plugin_free_setups(srv, p);
|
2008-10-27 19:12:48 +00:00
|
|
|
if (p->free)
|
|
|
|
p->free(srv, p);
|
2008-07-23 19:34:19 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
g_slice_free(liPlugin, p);
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_server_plugins_free(liServer *srv) {
|
2009-01-01 15:44:42 +00:00
|
|
|
gpointer key, val;
|
|
|
|
GHashTableIter i;
|
2009-08-30 18:43:13 +00:00
|
|
|
liServerState s;
|
2009-01-01 15:44:42 +00:00
|
|
|
|
2009-08-30 18:43:13 +00:00
|
|
|
s = g_atomic_int_get(&srv->state);
|
|
|
|
if (LI_SERVER_INIT != s && LI_SERVER_DOWN != s) {
|
2008-09-24 18:02:47 +00:00
|
|
|
ERROR(srv, "%s", "Cannot free plugins while server is running");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&i, srv->plugins);
|
2008-09-26 14:11:08 +00:00
|
|
|
while (g_hash_table_iter_next(&i, &key, &val)) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liPlugin *p = (liPlugin*) val;
|
2008-09-26 22:37:50 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_plugin_free_options(srv, p);
|
|
|
|
li_plugin_free_actions(srv, p);
|
|
|
|
li_plugin_free_setups(srv, p);
|
2009-10-04 14:38:53 +00:00
|
|
|
if (p->free)
|
|
|
|
p->free(srv, p);
|
2008-09-24 18:02:47 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
g_slice_free(liPlugin, p);
|
2008-09-24 18:02:47 +00:00
|
|
|
}
|
|
|
|
g_hash_table_destroy(srv->plugins);
|
|
|
|
g_hash_table_destroy(srv->options);
|
2010-05-08 09:55:52 +00:00
|
|
|
g_hash_table_destroy(srv->optionptrs);
|
2008-09-24 18:02:47 +00:00
|
|
|
g_hash_table_destroy(srv->actions);
|
|
|
|
g_hash_table_destroy(srv->setups);
|
|
|
|
}
|
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB init, gpointer userdata) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liPlugin *p;
|
2009-08-30 18:43:13 +00:00
|
|
|
liServerState s;
|
2008-07-23 16:01:19 +00:00
|
|
|
|
|
|
|
if (!init) {
|
2009-12-21 11:29:14 +00:00
|
|
|
ERROR(srv, "Plugin '%s' needs an init function", name);
|
2008-10-22 14:54:44 +00:00
|
|
|
return NULL;
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
|
|
|
|
2009-08-30 18:43:13 +00:00
|
|
|
s = g_atomic_int_get(&srv->state);
|
|
|
|
if (LI_SERVER_INIT != s) {
|
2008-08-08 16:49:00 +00:00
|
|
|
ERROR(srv, "Cannot register plugin '%s' after server was started", name);
|
2008-10-22 14:54:44 +00:00
|
|
|
return NULL;
|
2008-08-08 16:49:00 +00:00
|
|
|
}
|
|
|
|
|
2008-07-23 16:01:19 +00:00
|
|
|
if (g_hash_table_lookup(srv->plugins, name)) {
|
2009-12-21 11:29:14 +00:00
|
|
|
ERROR(srv, "Plugin '%s' already registered", name);
|
2008-10-22 14:54:44 +00:00
|
|
|
return NULL;
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p = plugin_new(name);
|
2009-01-01 15:44:42 +00:00
|
|
|
p->id = g_hash_table_size(srv->plugins);
|
2008-07-23 16:01:19 +00:00
|
|
|
g_hash_table_insert(srv->plugins, (gchar*) p->name, p);
|
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
init(srv, p, userdata);
|
2008-08-08 16:49:00 +00:00
|
|
|
p->opt_base_index = g_hash_table_size(srv->options);
|
2010-01-27 16:38:27 +00:00
|
|
|
p->optptr_base_index = g_hash_table_size(srv->optionptrs);
|
2008-07-23 16:01:19 +00:00
|
|
|
|
|
|
|
if (p->options) {
|
|
|
|
size_t i;
|
2009-07-08 19:06:07 +00:00
|
|
|
liServerOption *so;
|
2010-01-24 20:30:41 +00:00
|
|
|
liServerOptionPtr *sop;
|
2009-07-08 19:06:07 +00:00
|
|
|
const liPluginOption *po;
|
2008-07-23 16:01:19 +00:00
|
|
|
|
2008-07-23 19:34:19 +00:00
|
|
|
for (i = 0; (po = &p->options[i])->name; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (NULL != (so = (liServerOption*)g_hash_table_lookup(srv->options, po->name))) {
|
2008-07-23 16:01:19 +00:00
|
|
|
ERROR(srv, "Option '%s' already registered by plugin '%s', unloading '%s'",
|
2008-07-23 19:34:19 +00:00
|
|
|
po->name,
|
2008-07-23 16:01:19 +00:00
|
|
|
so->p ? so->p->name : "<none>",
|
|
|
|
p->name);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_plugin_free(srv, p);
|
2008-10-22 14:54:44 +00:00
|
|
|
return NULL;
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
2010-01-24 20:30:41 +00:00
|
|
|
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;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
so = g_slice_new0(liServerOption);
|
2008-07-23 16:01:19 +00:00
|
|
|
so->type = po->type;
|
2009-12-21 17:19:12 +00:00
|
|
|
so->parse_option = po->parse_option;
|
2008-07-23 16:01:19 +00:00
|
|
|
so->index = g_hash_table_size(srv->options);
|
|
|
|
so->module_index = i;
|
|
|
|
so->p = p;
|
2008-08-15 18:38:20 +00:00
|
|
|
so->default_value = po->default_value;
|
2008-07-23 19:34:19 +00:00
|
|
|
g_hash_table_insert(srv->options, (gchar*) po->name, so);
|
2008-10-01 20:20:31 +00:00
|
|
|
plugin_load_default_option(srv, so);
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
2008-07-23 19:34:19 +00:00
|
|
|
}
|
2008-07-23 16:01:19 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
so = g_slice_new0(liServerOptionPtr);
|
|
|
|
so->type = po->type;
|
|
|
|
so->parse_option = po->parse_option;
|
|
|
|
so->free_option = po->free_option;
|
|
|
|
so->index = g_hash_table_size(srv->optionptrs);
|
|
|
|
so->module_index = i;
|
|
|
|
so->p = p;
|
|
|
|
so->default_value = po->default_value;
|
|
|
|
g_hash_table_insert(srv->optionptrs, (gchar*) po->name, so);
|
|
|
|
plugin_load_default_optionptr(srv, so);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-23 19:34:19 +00:00
|
|
|
if (p->actions) {
|
|
|
|
size_t i;
|
2009-07-08 19:06:07 +00:00
|
|
|
liServerAction *sa;
|
|
|
|
const liPluginAction *pa;
|
2008-07-23 19:34:19 +00:00
|
|
|
|
|
|
|
for (i = 0; (pa = &p->actions[i])->name; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (NULL != (sa = (liServerAction*)g_hash_table_lookup(srv->actions, pa->name))) {
|
2008-07-23 19:34:19 +00:00
|
|
|
ERROR(srv, "Action '%s' already registered by plugin '%s', unloading '%s'",
|
|
|
|
pa->name,
|
|
|
|
sa->p ? sa->p->name : "<none>",
|
|
|
|
p->name);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_plugin_free(srv, p);
|
2008-10-22 14:54:44 +00:00
|
|
|
return NULL;
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
sa = g_slice_new0(liServerAction);
|
2009-12-21 17:19:12 +00:00
|
|
|
sa->create_action = pa->create_action;
|
2008-07-23 19:34:19 +00:00
|
|
|
sa->p = p;
|
2009-12-21 11:29:14 +00:00
|
|
|
sa->userdata = pa->userdata;
|
2008-07-23 19:34:19 +00:00
|
|
|
g_hash_table_insert(srv->actions, (gchar*) pa->name, sa);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->setups) {
|
|
|
|
size_t i;
|
2009-07-08 19:06:07 +00:00
|
|
|
liServerSetup *ss;
|
2009-08-30 17:25:01 +00:00
|
|
|
const liPluginSetup *ps;
|
2008-07-23 19:34:19 +00:00
|
|
|
|
|
|
|
for (i = 0; (ps = &p->setups[i])->name; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (NULL != (ss = (liServerSetup*)g_hash_table_lookup(srv->setups, ps->name))) {
|
2008-07-23 19:34:19 +00:00
|
|
|
ERROR(srv, "Setup '%s' already registered by plugin '%s', unloading '%s'",
|
|
|
|
ps->name,
|
|
|
|
ss->p ? ss->p->name : "<none>",
|
|
|
|
p->name);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_plugin_free(srv, p);
|
2008-10-22 14:54:44 +00:00
|
|
|
return NULL;
|
2008-07-23 19:34:19 +00:00
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
ss = g_slice_new0(liServerSetup);
|
2008-07-23 19:34:19 +00:00
|
|
|
ss->setup = ps->setup;
|
|
|
|
ss->p = p;
|
2009-12-21 11:29:14 +00:00
|
|
|
ss->userdata = ps->userdata;
|
2008-07-23 19:34:19 +00:00
|
|
|
g_hash_table_insert(srv->setups, (gchar*) ps->name, ss);
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-22 14:54:44 +00:00
|
|
|
return p;
|
2008-07-23 16:01:19 +00:00
|
|
|
}
|
2008-07-23 20:33:29 +00:00
|
|
|
|
2008-07-24 11:25:40 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liServerOption* find_option(liServer *srv, const char *name) {
|
|
|
|
return (liServerOption*) g_hash_table_lookup(srv->options, name);
|
2008-07-24 11:25:40 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
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;
|
2008-07-24 11:25:40 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
if (sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
|
|
|
|
ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s",
|
|
|
|
li_value_type_string(val->type), li_value_type_string(sopt->type), name);
|
2008-07-24 11:25:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
if (!sopt->parse_option) {
|
|
|
|
switch (sopt->type) {
|
|
|
|
case LI_VALUE_BOOLEAN:
|
|
|
|
mark->value.boolean = val->data.boolean;
|
|
|
|
break;
|
|
|
|
case LI_VALUE_NUMBER:
|
|
|
|
mark->value.number = val->data.number;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERROR(srv, "Invalid scalar option type '%s' for option %s",
|
|
|
|
li_value_type_string(sopt->type), name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!sopt->parse_option(srv, wrk, sopt->p, sopt->module_index, val, &mark->value)) {
|
2010-01-24 20:30:41 +00:00
|
|
|
/* errors should be logged by parse function */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mark->ndx = sopt->index;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static liServerOptionPtr* find_optionptr(liServer *srv, const char *name) {
|
|
|
|
return (liServerOptionPtr*) g_hash_table_lookup(srv->optionptrs, name);
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static gboolean li_parse_optionptr(liServer *srv, liWorker *wrk, liServerOptionPtr *sopt, const char *name, liValue *val, liOptionPtrSet *mark) {
|
2010-01-24 20:30:41 +00:00
|
|
|
liOptionPtrValue *oval;
|
|
|
|
gpointer ptr = NULL;
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!srv || !wrk || !name || !mark || !sopt) return FALSE;
|
2010-01-24 20:30:41 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
|
2008-09-26 14:11:08 +00:00
|
|
|
ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s",
|
2009-07-09 20:17:24 +00:00
|
|
|
li_value_type_string(val->type), li_value_type_string(sopt->type), name);
|
2008-07-24 11:25:40 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-12-21 17:19:12 +00:00
|
|
|
if (!sopt->parse_option) {
|
2010-01-24 20:30:41 +00:00
|
|
|
ptr = li_value_extract_ptr(val);
|
2008-07-24 11:25:40 +00:00
|
|
|
} else {
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!sopt->parse_option(srv, wrk, sopt->p, sopt->module_index, val, &ptr)) {
|
2008-07-24 11:25:40 +00:00
|
|
|
/* errors should be logged by parse function */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
if (ptr) {
|
|
|
|
oval = g_slice_new0(liOptionPtrValue);
|
|
|
|
oval->refcount = 1;
|
|
|
|
oval->sopt = sopt;
|
|
|
|
oval->data.ptr = ptr;
|
|
|
|
} else {
|
|
|
|
oval = NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-24 11:25:40 +00:00
|
|
|
mark->ndx = sopt->index;
|
2010-01-24 20:30:41 +00:00
|
|
|
mark->value = oval;
|
2008-07-24 11:25:40 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
void li_release_optionptr(liServer *srv, liOptionPtrValue *value) {
|
|
|
|
liServerOptionPtr *sopt;
|
|
|
|
|
|
|
|
if (!srv || !value) return;
|
2008-07-24 11:25:40 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
assert(g_atomic_int_get(&value->refcount) > 0);
|
|
|
|
if (!g_atomic_int_dec_and_test(&value->refcount)) return;
|
|
|
|
|
|
|
|
sopt = value->sopt;
|
|
|
|
value->sopt = NULL;
|
2008-07-24 11:25:40 +00:00
|
|
|
if (!sopt->free_option) {
|
|
|
|
switch (sopt->type) {
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_NONE:
|
|
|
|
case LI_VALUE_BOOLEAN:
|
|
|
|
case LI_VALUE_NUMBER:
|
2008-07-24 11:25:40 +00:00
|
|
|
/* Nothing to free */
|
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_STRING:
|
2010-01-24 20:30:41 +00:00
|
|
|
if (value->data.string)
|
|
|
|
g_string_free(value->data.string, TRUE);
|
2008-07-24 11:25:40 +00:00
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_LIST:
|
2010-01-24 20:30:41 +00:00
|
|
|
if (value->data.list)
|
|
|
|
li_value_list_free(value->data.list);
|
2008-07-24 11:25:40 +00:00
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_HASH:
|
2010-01-24 20:30:41 +00:00
|
|
|
if (value->data.hash)
|
|
|
|
g_hash_table_destroy(value->data.hash);
|
2008-07-24 11:25:40 +00:00
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_ACTION:
|
2010-01-24 20:30:41 +00:00
|
|
|
if (value->data.action)
|
|
|
|
li_action_release(srv, value->data.action);
|
2008-07-24 11:25:40 +00:00
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_CONDITION:
|
2010-01-24 20:30:41 +00:00
|
|
|
if (value->data.cond)
|
|
|
|
li_condition_release(srv, value->data.cond);
|
2008-07-24 11:25:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2010-01-24 20:30:41 +00:00
|
|
|
sopt->free_option(srv, sopt->p, sopt->module_index, value->data.ptr);
|
2008-09-26 14:11:08 +00:00
|
|
|
}
|
2010-01-24 20:30:41 +00:00
|
|
|
g_slice_free(liOptionPtrValue, value);
|
2008-07-24 11:25:40 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
liAction* li_option_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val) {
|
2010-01-24 20:30:41 +00:00
|
|
|
liServerOption *sopt;
|
2010-01-27 16:15:25 +00:00
|
|
|
liServerOptionPtr *soptptr;
|
2010-01-24 20:30:41 +00:00
|
|
|
|
2010-01-27 16:15:25 +00:00
|
|
|
if (NULL != (sopt = find_option(srv, name))) {
|
|
|
|
liOptionSet setting;
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!li_parse_option(srv, wrk, sopt, name, val, &setting)) {
|
2010-01-27 16:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return li_action_new_setting(setting);
|
|
|
|
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
|
|
|
|
liOptionPtrSet setting;
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!li_parse_optionptr(srv, wrk, soptptr, name, val, &setting)) {
|
2010-01-27 16:15:25 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return li_action_new_settingptr(setting);
|
|
|
|
} else {
|
2010-01-24 20:30:41 +00:00
|
|
|
ERROR(srv, "Unknown option '%s'", name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-08-04 19:28:56 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
liAction* li_create_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liAction *a;
|
|
|
|
liServerAction *sa;
|
2008-07-24 11:25:40 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (NULL == (sa = (liServerAction*) g_hash_table_lookup(srv->actions, name))) {
|
2008-07-24 11:25:40 +00:00
|
|
|
ERROR(srv, "Action '%s' doesn't exist", name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
if (NULL == (a = sa->create_action(srv, wrk, sa->p, val, sa->userdata))) {
|
2008-07-24 11:25:40 +00:00
|
|
|
ERROR(srv, "Action '%s' creation failed", name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
gboolean li_call_setup(liServer *srv, const char *name, liValue *val) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liServerSetup *ss;
|
2008-07-23 20:33:29 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (NULL == (ss = (liServerSetup*) g_hash_table_lookup(srv->setups, name))) {
|
2008-07-23 20:33:29 +00:00
|
|
|
ERROR(srv, "Setup function '%s' doesn't exist", name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
if (!ss->setup(srv, ss->p, val, ss->userdata)) {
|
2008-07-23 20:33:29 +00:00
|
|
|
ERROR(srv, "Setup '%s' failed", name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2008-08-08 17:44:54 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_plugins_prepare_callbacks(liServer *srv) {
|
2008-08-08 17:44:54 +00:00
|
|
|
GHashTableIter iter;
|
2009-07-08 19:06:07 +00:00
|
|
|
liPlugin *p;
|
2008-09-26 15:09:30 +00:00
|
|
|
gpointer v;
|
2008-08-08 17:44:54 +00:00
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
2008-09-26 15:09:30 +00:00
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
2009-07-08 19:06:07 +00:00
|
|
|
p = (liPlugin*) v;
|
2008-08-08 17:44:54 +00:00
|
|
|
if (p->handle_close)
|
2009-07-09 20:17:24 +00:00
|
|
|
g_array_append_val(srv->li_plugins_handle_close, p);
|
2009-01-01 15:44:42 +00:00
|
|
|
if (p->handle_vrclose)
|
2009-07-09 20:17:24 +00:00
|
|
|
g_array_append_val(srv->li_plugins_handle_vrclose, p);
|
2008-08-08 17:44:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_plugins_handle_close(liConnection *con) {
|
|
|
|
GArray *a = con->srv->li_plugins_handle_close;
|
2008-08-08 17:44:54 +00:00
|
|
|
guint i, len = a->len;
|
|
|
|
for (i = 0; i < len; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liPlugin *p = g_array_index(a, liPlugin*, i);
|
2008-09-08 00:20:55 +00:00
|
|
|
p->handle_close(con, p);
|
2008-08-08 17:44:54 +00:00
|
|
|
}
|
|
|
|
}
|
2008-09-26 15:09:30 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_plugins_handle_vrclose(liVRequest *vr) {
|
|
|
|
GArray *a = vr->wrk->srv->li_plugins_handle_vrclose;
|
2009-01-01 15:44:42 +00:00
|
|
|
guint i, len = a->len;
|
|
|
|
for (i = 0; i < len; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liPlugin *p = g_array_index(a, liPlugin*, i);
|
2009-01-01 15:44:42 +00:00
|
|
|
p->handle_vrclose(vr, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
gboolean li_plugin_set_default_option(liServer* srv, const gchar* name, liValue* val) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liServerOption *sopt;
|
2010-01-24 20:30:41 +00:00
|
|
|
liServerOptionPtr *soptptr;
|
2008-10-01 20:20:31 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
if (NULL != (sopt = find_option(srv, name))) {
|
|
|
|
liOptionSet setting;
|
2008-10-01 20:20:31 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
/* assign new value */
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!li_parse_option(srv, srv->main_worker, sopt, name, val, &setting)) {
|
2010-01-24 20:30:41 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2008-10-01 20:20:31 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value;
|
|
|
|
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
|
|
|
|
liOptionPtrSet setting;
|
2008-10-01 20:20:31 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
/* assign new value */
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!li_parse_optionptr(srv, srv->main_worker, soptptr, name, val, &setting)) {
|
2010-01-24 20:30:41 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2008-10-01 22:13:07 +00:00
|
|
|
|
2010-09-12 15:44:00 +00:00
|
|
|
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index));
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index) = setting.value;
|
|
|
|
} else {
|
|
|
|
ERROR(srv, "unknown option \"%s\"", name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-10-01 22:13:07 +00:00
|
|
|
|
2008-10-01 20:20:31 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt) {
|
|
|
|
liOptionValue oval = {0};
|
2008-10-01 20:20:31 +00:00
|
|
|
|
|
|
|
if (!sopt)
|
|
|
|
return FALSE;
|
|
|
|
|
2009-12-21 17:19:12 +00:00
|
|
|
if (!sopt->parse_option) {
|
2008-10-01 20:20:31 +00:00
|
|
|
switch (sopt->type) {
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_BOOLEAN:
|
2008-10-01 20:20:31 +00:00
|
|
|
oval.boolean = GPOINTER_TO_INT(sopt->default_value);
|
2010-01-24 20:30:41 +00:00
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VALUE_NUMBER:
|
2008-10-01 20:20:31 +00:00
|
|
|
oval.number = GPOINTER_TO_INT(sopt->default_value);
|
|
|
|
break;
|
|
|
|
default:
|
2010-01-24 20:30:41 +00:00
|
|
|
ERROR(srv, "Invalid type '%s' for scalar option",
|
|
|
|
li_value_type_string(sopt->type));
|
|
|
|
return FALSE;
|
2008-10-01 20:20:31 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!sopt->parse_option(srv, srv->main_worker, sopt->p, sopt->module_index, NULL, &oval)) {
|
2008-10-01 20:20:31 +00:00
|
|
|
/* errors should be logged by parse function */
|
|
|
|
return FALSE;
|
2008-09-26 15:09:30 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-01 20:20:31 +00:00
|
|
|
|
|
|
|
if (srv->option_def_values->len <= sopt->index)
|
|
|
|
g_array_set_size(srv->option_def_values, sopt->index + 1);
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = oval;
|
2008-10-01 20:20:31 +00:00
|
|
|
|
2008-09-26 15:09:30 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt) {
|
|
|
|
gpointer ptr = NULL;
|
|
|
|
liOptionPtrValue *oval = NULL;
|
|
|
|
|
|
|
|
if (!sopt)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!sopt->parse_option) {
|
|
|
|
switch (sopt->type) {
|
|
|
|
case LI_VALUE_STRING:
|
|
|
|
ptr = g_string_new((const char*) sopt->default_value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ptr = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
2010-05-07 18:54:50 +00:00
|
|
|
if (!sopt->parse_option(srv, srv->main_worker, sopt->p, sopt->module_index, NULL, &ptr)) {
|
2010-01-24 20:30:41 +00:00
|
|
|
/* errors should be logged by parse function */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptr) {
|
|
|
|
oval = g_slice_new0(liOptionPtrValue);
|
|
|
|
oval->refcount = 1;
|
|
|
|
oval->data.ptr = ptr;
|
|
|
|
oval->sopt = sopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (srv->optionptr_def_values->len <= sopt->index)
|
|
|
|
g_array_set_size(srv->optionptr_def_values, sopt->index + 1);
|
|
|
|
|
|
|
|
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index));
|
|
|
|
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index) = oval;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
static void li_plugin_free_default_options(liServer *srv, liPlugin *p) {
|
2008-09-26 15:09:30 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
gpointer k, v;
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
g_hash_table_iter_init(&iter, srv->optionptrs);
|
2008-09-26 15:09:30 +00:00
|
|
|
while (g_hash_table_iter_next(&iter, &k, &v)) {
|
2010-01-24 20:30:41 +00:00
|
|
|
liServerOptionPtr *sopt = v;
|
2008-10-01 20:20:31 +00:00
|
|
|
|
2008-10-22 14:54:44 +00:00
|
|
|
if (sopt->p != p)
|
|
|
|
continue;
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index));
|
|
|
|
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index) = NULL;
|
2008-09-26 15:09:30 +00:00
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
|
2010-02-13 14:29:21 +00:00
|
|
|
void li_plugins_prepare_worker(liWorker *wrk) { /* blocking callbacks */
|
2010-02-13 14:41:09 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
liServer *srv = wrk->srv;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_prepare_worker) {
|
|
|
|
p->handle_prepare_worker(srv, p, wrk);
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
}
|
|
|
|
void li_plugins_prepare(liServer* srv) { /* "prepare", async */
|
2010-02-13 14:41:09 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_prepare) {
|
|
|
|
p->handle_prepare(srv, p);
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
void li_plugins_worker_stop(liWorker *wrk) { /* blocking callbacks */
|
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
liServer *srv = wrk->srv;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_worker_stop) {
|
|
|
|
p->handle_worker_stop(srv, p, wrk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-30 18:43:13 +00:00
|
|
|
void li_plugins_start_listen(liServer *srv) { /* "warmup" */
|
2010-02-13 14:41:09 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_start_listen) {
|
|
|
|
p->handle_start_listen(srv, p);
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
}
|
|
|
|
void li_plugins_stop_listen(liServer *srv) { /* "prepare suspend", async */
|
2010-02-13 14:41:09 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_stop_listen) {
|
|
|
|
p->handle_stop_listen(srv, p);
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
}
|
|
|
|
void li_plugins_start_log(liServer *srv) { /* "run" */
|
2010-02-13 14:41:09 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_start_log) {
|
|
|
|
p->handle_start_log(srv, p);
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
}
|
|
|
|
void li_plugins_stop_log(liServer *srv) { /* "suspend now" */
|
2010-02-13 14:41:09 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
|
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_stop_log) {
|
|
|
|
p->handle_stop_log(srv, p);
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 18:43:13 +00:00
|
|
|
}
|
2010-05-14 11:09:34 +00:00
|
|
|
|
|
|
|
void li_plugins_init_lua(struct lua_State *L, liServer *srv, liWorker *wrk) {
|
|
|
|
GHashTableIter iter;
|
|
|
|
liPlugin *p;
|
|
|
|
gpointer v;
|
|
|
|
|
2010-06-06 10:29:25 +00:00
|
|
|
if (NULL == srv->plugins) return;
|
|
|
|
|
2010-05-14 11:09:34 +00:00
|
|
|
g_hash_table_iter_init(&iter, srv->plugins);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
|
|
|
p = (liPlugin*) v;
|
|
|
|
if (p->handle_init_lua) {
|
|
|
|
p->handle_init_lua(L, srv, wrk, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|