From f14103bc2c1f67d1af8e4d95254bd0bb5956796e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sun, 24 Jan 2010 21:30:41 +0100 Subject: [PATCH] Split options into two categories: simple (int, bool) and ref-counted pointers --- include/lighttpd/actions.h | 2 + include/lighttpd/options.h | 28 ++- include/lighttpd/plugin.h | 54 ++++-- include/lighttpd/plugin_core.h | 18 +- include/lighttpd/server.h | 4 +- include/lighttpd/typedefs.h | 11 +- include/lighttpd/value.h | 2 + include/lighttpd/virtualrequest.h | 1 + src/main/actions.c | 13 +- src/main/lighttpd-glue.c | 2 +- src/main/log.c | 36 ++-- src/main/options.c | 33 ---- src/main/plugin.c | 272 ++++++++++++++++++++++-------- src/main/plugin_core.c | 60 ++++--- src/main/response.c | 4 +- src/main/server.c | 17 +- src/main/value.c | 33 ++++ src/main/virtualrequest.c | 35 +++- src/modules/mod_access.c | 25 ++- src/modules/mod_accesslog.c | 45 ++--- src/modules/mod_auth.c | 4 +- src/modules/mod_balancer.c | 2 +- src/modules/mod_cache_disk_etag.c | 2 +- src/modules/mod_debug.c | 2 +- src/modules/mod_deflate.c | 4 +- src/modules/mod_dirlist.c | 6 +- src/modules/mod_expire.c | 2 +- src/modules/mod_fastcgi.c | 6 +- src/modules/mod_fortune.c | 2 +- src/modules/mod_lua.c | 4 +- src/modules/mod_openssl.c | 2 +- src/modules/mod_proxy.c | 2 +- src/modules/mod_redirect.c | 4 +- src/modules/mod_rewrite.c | 4 +- src/modules/mod_scgi.c | 4 +- src/modules/mod_status.c | 8 +- src/modules/mod_vhost.c | 4 +- 37 files changed, 516 insertions(+), 241 deletions(-) diff --git a/include/lighttpd/actions.h b/include/lighttpd/actions.h index b8a52c5..0bef4f9 100644 --- a/include/lighttpd/actions.h +++ b/include/lighttpd/actions.h @@ -57,6 +57,8 @@ struct liAction { union { liOptionSet setting; + liOptionPtrSet settingptr; + struct { liCondition *cond; liAction *target; /** action target to jump to if condition is fulfilled */ diff --git a/include/lighttpd/options.h b/include/lighttpd/options.h index 73e5466..d68762d 100644 --- a/include/lighttpd/options.h +++ b/include/lighttpd/options.h @@ -6,25 +6,35 @@ #endif union liOptionValue { - gpointer ptr; gint64 number; gboolean boolean; +}; + +struct liOptionPtrValue { + gint refcount; + + union { + gpointer ptr; /* some common pointer types */ - GString *string; - GArray *list; - GHashTable *hash; - liAction *action; - liCondition *cond; + GString *string; + GArray *list; + GHashTable *hash; + liAction *action; + liCondition *cond; + } data; + + liServerOptionPtr *sopt; }; struct liOptionSet { size_t ndx; liOptionValue value; - liServerOption *sopt; }; -/* Extract content from value, value set to none */ -LI_API liOptionValue li_value_extract(liValue *val); +struct liOptionPtrSet { + size_t ndx; + liOptionPtrValue *value; +}; #endif diff --git a/include/lighttpd/plugin.h b/include/lighttpd/plugin.h index cd6e98c..f39bafe 100644 --- a/include/lighttpd/plugin.h +++ b/include/lighttpd/plugin.h @@ -8,14 +8,11 @@ #define INIT_FUNC(x) \ LI_EXPORT void * x(server *srv, plugin *) -#define PLUGIN_DATA \ - size_t id; \ - ssize_t option_base_ndx - typedef void (*liPluginInitCB) (liServer *srv, liPlugin *p, gpointer userdata); typedef void (*liPluginFreeCB) (liServer *srv, liPlugin *p); typedef gboolean (*liPluginParseOptionCB) (liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval); -typedef void (*liPluginFreeOptionCB) (liServer *srv, liPlugin *p, size_t ndx, liOptionValue oval); +typedef gboolean (*liPluginParseOptionPtrCB)(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval); +typedef void (*liPluginFreeOptionPtrCB) (liServer *srv, liPlugin *p, size_t ndx, gpointer oval); typedef liAction*(*liPluginCreateActionCB) (liServer *srv, liPlugin *p, liValue *val, gpointer userdata); typedef gboolean (*liPluginSetupCB) (liServer *srv, liPlugin *p, liValue *val, gpointer userdata); typedef void (*liPluginAngelCB) (liServer *srv, liPlugin *p, gint32 id, GString *data); @@ -48,6 +45,7 @@ struct liPlugin { liPluginHandleVRCloseCB handle_vrclose; const liPluginOption *options; + const liPluginOptionPtr *optionptrs; const liPluginAction *actions; const liPluginSetup *setups; const liPluginAngel *angelcbs; @@ -57,9 +55,17 @@ struct liPluginOption { const gchar *name; liValueType type; - gpointer default_value; + gint64 default_value; liPluginParseOptionCB parse_option; - liPluginFreeOptionCB free_option; +}; + +struct liPluginOptionPtr { + const gchar *name; + liValueType type; + + gpointer default_value; + liPluginParseOptionPtrCB parse_option; + liPluginFreeOptionPtrCB free_option; }; struct liPluginAction { @@ -92,16 +98,33 @@ struct liServerOption { */ 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. */ - liPluginFreeOptionCB free_option; + liPluginFreeOptionPtrCB free_option; - /** if li_parse_option is NULL, the default_value is used; it is only used + /** if parse_option is NULL, the default_value is used; it is only used * for the following value types: - * - BOOLEAN, NUMBER: casted with GPOINTER_TO_INT, i.e. set it with GINT_TO_POINTER - * the numbers are limited to the 32-bit range according to the glib docs * - STRING: used for g_string_new, i.e. a const char* */ gpointer default_value; @@ -129,9 +152,7 @@ LI_API liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginIn LI_API void li_plugin_free(liServer *srv, liPlugin *p); LI_API void li_server_plugins_free(liServer *srv); -/** free val after call (val may be modified by parser) */ -LI_API gboolean li_parse_option(liServer *srv, const char *name, liValue *val, liOptionSet *mark); -LI_API void li_release_option(liServer *srv, liOptionSet *mark); /**< Does not free the option_set memory */ +LI_API void li_release_optionptr(liServer *srv, liOptionPtrValue *value); LI_API void li_plugins_prepare_callbacks(liServer *srv); @@ -162,9 +183,14 @@ 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); +extern liOptionPtrValue li_option_ptr_zero; + /* needs vrequest *vr and plugin *p */ #define OPTION(idx) _OPTION(vr, p, idx) #define _OPTION(vr, p, idx) (vr->options[p->opt_base_index + idx]) #define _OPTION_ABS(vr, idx) (vr->options[idx]) +#define OPTIONPTR(idx) _OPTIONPTR(vr, p, idx) +#define _OPTIONPTR(vr, p, idx) (vr->optionptrs[p->opt_base_index + idx] ? vr->optionptrs[p->opt_base_index + idx]->data : li_option_ptr_zero.data) +#define _OPTIONPTR_ABS(vr, idx) (vr->optionptrs[idx] ? vr->optionptrs[idx]->data : li_option_ptr_zero.data) #endif diff --git a/include/lighttpd/plugin_core.h b/include/lighttpd/plugin_core.h index d63f32f..c8a677a 100644 --- a/include/lighttpd/plugin_core.h +++ b/include/lighttpd/plugin_core.h @@ -8,25 +8,31 @@ typedef enum { LI_ETAG_USE_INODE = 1, LI_ETAG_USE_MTIME = 2, LI_ETAG_USE_SIZE = enum liCoreOptions { LI_CORE_OPTION_DEBUG_REQUEST_HANDLING = 0, - LI_CORE_OPTION_LOG_TS_FORMAT, + LI_CORE_OPTION_STATIC_RANGE_REQUESTS, + + LI_CORE_OPTION_MAX_KEEP_ALIVE_IDLE, + LI_CORE_OPTION_MAX_KEEP_ALIVE_REQUESTS, + + LI_CORE_OPTION_ETAG_FLAGS +}; + +enum liCoreOptionPtrs { + LI_CORE_OPTION_LOG_TS_FORMAT = 0, LI_CORE_OPTION_LOG, LI_CORE_OPTION_STATIC_FILE_EXCLUDE_EXTENSIONS, - LI_CORE_OPTION_STATIC_RANGE_REQUESTS, LI_CORE_OPTION_SERVER_NAME, LI_CORE_OPTION_SERVER_TAG, - LI_CORE_OPTION_MAX_KEEP_ALIVE_IDLE, - LI_CORE_OPTION_MAX_KEEP_ALIVE_REQUESTS, LI_CORE_OPTION_MIME_TYPES, - - LI_CORE_OPTION_ETAG_FLAGS }; /* the core plugin always has base index 0, as it is the first plugin loaded */ #define CORE_OPTION(idx) _CORE_OPTION(vr, idx) #define _CORE_OPTION(vr, idx) _OPTION_ABS(vr, idx) +#define CORE_OPTIONPTR(idx) _CORE_OPTIONPTR(vr, idx) +#define _CORE_OPTIONPTR(vr, idx) _OPTIONPTR_ABS(vr, idx) LI_API void li_plugin_core_init(liServer *srv, liPlugin *p, gpointer userdata); diff --git a/include/lighttpd/server.h b/include/lighttpd/server.h index 94a8955..063763a 100644 --- a/include/lighttpd/server.h +++ b/include/lighttpd/server.h @@ -72,13 +72,15 @@ struct liServer { /* registered by plugins */ GHashTable *options; /**< const gchar* => (liServerOption*) */ + GHashTable *optionptrs; /**< const gchar* => (liServerOptionPtr*) */ GHashTable *actions; /**< const gchar* => (liServerAction*) */ GHashTable *setups; /**< const gchar* => (liServerSetup*) */ GArray *li_plugins_handle_close; /** list of handle_close callbacks */ GArray *li_plugins_handle_vrclose; /** list of handle_vrclose callbacks */ - GArray *option_def_values;/** array of option_value */ + GArray *option_def_values;/** array of liOptionValue */ + GArray *optionptr_def_values;/** array of liOptionPtrValue* */ liAction *mainaction; gboolean exiting; /** atomic access */ diff --git a/include/lighttpd/typedefs.h b/include/lighttpd/typedefs.h index 0cfde75..16519db 100644 --- a/include/lighttpd/typedefs.h +++ b/include/lighttpd/typedefs.h @@ -34,6 +34,7 @@ typedef struct liBalancerFunc liBalancerFunc; typedef enum { ACTION_TSETTING, + ACTION_TSETTINGPTR, ACTION_TFUNCTION, ACTION_TCONDITION, ACTION_TLIST, @@ -125,9 +126,13 @@ typedef enum { /* options.h */ +typedef union liOptionValue liOptionValue; + +typedef struct liOptionPtrValue liOptionPtrValue; + typedef struct liOptionSet liOptionSet; -typedef union liOptionValue liOptionValue; +typedef struct liOptionPtrSet liOptionPtrSet; /* plugin.h */ typedef struct liPlugin liPlugin; @@ -136,6 +141,10 @@ typedef struct liPluginOption liPluginOption; typedef struct liServerOption liServerOption; +typedef struct liPluginOptionPtr liPluginOptionPtr; + +typedef struct liServerOptionPtr liServerOptionPtr; + typedef struct liPluginAction liPluginAction; typedef struct liServerAction liServerAction; diff --git a/include/lighttpd/value.h b/include/lighttpd/value.h index f891fe2..bc7c062 100644 --- a/include/lighttpd/value.h +++ b/include/lighttpd/value.h @@ -46,7 +46,9 @@ LI_API void li_value_list_free(GArray *vallist); /* extracts the pointer of a; set val->type to none (so a free on the value doesn't free the previous content) * returns NULL (and doesn't modify val->type) if the type doesn't match + * there is no need to extract scalar values - just copy them */ +LI_API gpointer li_value_extract_ptr(liValue *val); LI_API GString* li_value_extract_string(liValue *val); LI_API GArray* li_value_extract_list(liValue *val); LI_API GHashTable* li_value_extract_hash(liValue *val); diff --git a/include/lighttpd/virtualrequest.h b/include/lighttpd/virtualrequest.h index a81c829..3a7245b 100644 --- a/include/lighttpd/virtualrequest.h +++ b/include/lighttpd/virtualrequest.h @@ -62,6 +62,7 @@ struct liVRequest { liVRequestRef *ref; liOptionValue *options; + liOptionPtrValue **optionptrs; liVRequestState state; diff --git a/src/main/actions.c b/src/main/actions.c index e7361f8..2894b62 100644 --- a/src/main/actions.c +++ b/src/main/actions.c @@ -19,7 +19,9 @@ void li_action_release(liServer *srv, liAction *a) { if (g_atomic_int_dec_and_test(&a->refcount)) { switch (a->type) { case ACTION_TSETTING: - li_release_option(srv, &a->data.setting); + break; + case ACTION_TSETTINGPTR: + li_release_optionptr(srv, a->data.settingptr.value); break; case ACTION_TFUNCTION: if (a->data.function.free) { @@ -123,6 +125,7 @@ static void action_stack_element_release(liServer *srv, liVRequest *vr, action_s switch (a->type) { case ACTION_TSETTING: + case ACTION_TSETTINGPTR: break; case ACTION_TFUNCTION: if (ase->data.context && a->data.function.cleanup) { @@ -261,6 +264,14 @@ liHandlerResult li_action_execute(liVRequest *vr) { vr->options[a->data.setting.ndx] = a->data.setting.value; action_stack_pop(srv, vr, as); break; + case ACTION_TSETTINGPTR: + if (vr->optionptrs[a->data.settingptr.ndx] != a->data.settingptr.value) { + g_atomic_int_inc(&a->data.settingptr.value->refcount); + li_release_optionptr(srv, vr->optionptrs[a->data.settingptr.ndx]); + vr->optionptrs[a->data.settingptr.ndx] = a->data.settingptr.value; + } + action_stack_pop(srv, vr, as); + break; case ACTION_TFUNCTION: res = a->data.function.func(vr, a->data.function.param, &ase->data.context); switch (res) { diff --git a/src/main/lighttpd-glue.c b/src/main/lighttpd-glue.c index 9326290..4706d46 100644 --- a/src/main/lighttpd-glue.c +++ b/src/main/lighttpd-glue.c @@ -136,7 +136,7 @@ GString *li_mimetype_get(liVRequest *vr, GString *filename) { if (!vr || !filename || !filename->len) return NULL; - arr = CORE_OPTION(LI_CORE_OPTION_MIME_TYPES).list; + arr = CORE_OPTIONPTR(LI_CORE_OPTION_MIME_TYPES).list; for (guint i = 0; i < arr->len; i++) { gint k, j; diff --git a/src/main/log.c b/src/main/log.c index 00c2fa1..8428152 100644 --- a/src/main/log.c +++ b/src/main/log.c @@ -42,31 +42,37 @@ gboolean li_log_write_(liServer *srv, liVRequest *vr, liLogLevel log_level, guin liLog *log = NULL; liLogEntry *log_entry; liLogTimestamp *ts = NULL; + GArray *logs = NULL; if (vr != NULL) { if (!srv) srv = vr->wrk->srv; /* get log from connection */ - log = g_array_index(CORE_OPTION(LI_CORE_OPTION_LOG).list, liLog*, log_level); - if (log == NULL) - return TRUE; - ts = CORE_OPTION(LI_CORE_OPTION_LOG_TS_FORMAT).ptr; - if (!ts) - ts = g_array_index(srv->logs.timestamps, liLogTimestamp*, 0); + logs = CORE_OPTIONPTR(LI_CORE_OPTION_LOG).list; + ts = CORE_OPTIONPTR(LI_CORE_OPTION_LOG_TS_FORMAT).ptr; } else { - log = g_array_index(g_array_index(srv->option_def_values, liOptionValue, 0 + LI_CORE_OPTION_LOG).list, liLog*, log_level); - if (log == NULL) - return TRUE; + liOptionPtrValue *ologval; + ologval = g_array_index(srv->optionptr_def_values, liOptionPtrValue*, 0 + LI_CORE_OPTION_LOG); + if (ologval != NULL) logs = ologval->data.list; + } + + if (logs != NULL && log_level < logs->len) { + log = g_array_index(logs, liLog*, log_level); +/* if (log == NULL) + return TRUE;*/ + } + + if (!ts) { ts = g_array_index(srv->logs.timestamps, liLogTimestamp*, 0); } - li_log_ref(srv, log); + if (log) li_log_ref(srv, log); log_line = g_string_sized_new(0); va_start(ap, fmt); g_string_vprintf(log_line, fmt, ap); va_end(ap); - if (!(flags & LOG_FLAG_NOLOCK)) + if (log && !(flags & LOG_FLAG_NOLOCK)) log_lock(log); #if 0 @@ -135,11 +141,16 @@ gboolean li_log_write_(liServer *srv, liVRequest *vr, liLogLevel log_level, guin g_mutex_unlock(srv->logs.mutex); } - if (!(flags & LOG_FLAG_NOLOCK)) + if (log && !(flags & LOG_FLAG_NOLOCK)) log_unlock(log); g_string_append_len(log_line, CONST_STR_LEN("\r\n")); + if (!log) { + li_angel_log(srv, log_line); + return TRUE; + } + switch (g_atomic_int_get(&srv->state)) { case LI_SERVER_INIT: case LI_SERVER_LOADING: @@ -153,6 +164,7 @@ gboolean li_log_write_(liServer *srv, liVRequest *vr, liLogLevel log_level, guin default: break; } + log_entry = g_slice_new(liLogEntry); log_entry->log = log; log_entry->msg = log_line; diff --git a/src/main/options.c b/src/main/options.c index 7ff8e3f..fe0127b 100644 --- a/src/main/options.c +++ b/src/main/options.c @@ -1,36 +1,3 @@ #include -/* Extract ovalue from ovalue, ovalue set to none */ -liOptionValue li_value_extract(liValue *val) { - liOptionValue oval = {0}; - if (!val) return oval; - - switch (val->type) { - case LI_VALUE_NONE: - break; - case LI_VALUE_BOOLEAN: - oval.boolean = val->data.boolean; - break; - case LI_VALUE_NUMBER: - oval.number = val->data.number; - break; - case LI_VALUE_STRING: - oval.string = val->data.string; - break; - case LI_VALUE_LIST: - oval.list = val->data.list; - break; - case LI_VALUE_HASH: - oval.hash = val->data.hash; - break; - case LI_VALUE_ACTION: - oval.ptr = val->data.val_action.action; - break; - case LI_VALUE_CONDITION: - oval.ptr = val->data.val_action.action; - break; - } - val->type = LI_VALUE_NONE; - return oval; -} diff --git a/src/main/plugin.c b/src/main/plugin.c index a8497d7..fe653ba 100644 --- a/src/main/plugin.c +++ b/src/main/plugin.c @@ -2,8 +2,11 @@ #include 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); +liOptionPtrValue li_option_ptr_zero = { 0 }; + static liPlugin* plugin_new(const gchar *name) { liPlugin *p = g_slice_new0(liPlugin); p->name = name; @@ -14,13 +17,20 @@ static void li_plugin_free_options(liServer *srv, liPlugin *p) { size_t i; const liPluginOption *po; liServerOption *so; + const liPluginOptionPtr *pop; + liServerOptionPtr *sop; - if (!p->options) return; - for (i = 0; (po = &p->options[i])->name; i++) { + if (p->options) for (i = 0; (po = &p->options[i])->name; i++) { 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); } + + 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); + } } static void li_plugin_free_actions(liServer *srv, liPlugin *p) { @@ -130,6 +140,7 @@ 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++) { @@ -141,10 +152,17 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in 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 : "", + p->name); + li_plugin_free(srv, p); + return NULL; + } so = g_slice_new0(liServerOption); so->type = po->type; so->parse_option = po->parse_option; - so->free_option = po->free_option; so->index = g_hash_table_size(srv->options); so->module_index = i; so->p = p; @@ -154,6 +172,42 @@ 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 : "", + 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 : "", + 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); + } + } + if (p->actions) { size_t i; liServerAction *sa; @@ -206,17 +260,50 @@ static liServerOption* find_option(liServer *srv, const char *name) { return (liServerOption*) g_hash_table_lookup(srv->options, name); } -gboolean li_parse_option(liServer *srv, const char *name, liValue *val, liOptionSet *mark) { - liServerOption *sopt; - - if (!srv || !name || !mark) return FALSE; +static gboolean li_parse_option(liServer *srv, liServerOption *sopt, const char *name, liValue *val, liOptionSet *mark) { + if (!srv || !name || !mark || !sopt) return FALSE; - sopt = find_option(srv, name); - if (!sopt) { - ERROR(srv, "Unknown option '%s'", name); + 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); return FALSE; } + 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 { + if (!sopt->parse_option(srv, sopt->p, sopt->module_index, val, &mark->value)) { + /* 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); +} + +static gboolean li_parse_optionptr(liServer *srv, liServerOptionPtr *sopt, const char *name, liValue *val, liOptionPtrSet *mark) { + liOptionPtrValue *oval; + gpointer ptr = NULL; + + if (!srv || !name || !mark || !sopt) return FALSE; + 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); @@ -224,26 +311,39 @@ gboolean li_parse_option(liServer *srv, const char *name, liValue *val, liOption } if (!sopt->parse_option) { - mark->value = li_value_extract(val); + ptr = li_value_extract_ptr(val); } else { - if (!sopt->parse_option(srv, sopt->p, sopt->module_index, val, &mark->value)) { + if (!sopt->parse_option(srv, sopt->p, sopt->module_index, val, &ptr)) { /* errors should be logged by parse function */ return FALSE; } } + if (ptr) { + oval = g_slice_new0(liOptionPtrValue); + oval->refcount = 1; + oval->sopt = sopt; + oval->data.ptr = ptr; + } else { + oval = NULL; + } + mark->ndx = sopt->index; - mark->sopt = sopt; + mark->value = oval; return TRUE; } -void li_release_option(liServer *srv, liOptionSet *mark) { /** Does not free the option_set memory */ - liServerOption *sopt; - if (!srv || !mark || !mark->sopt) return; - sopt = mark->sopt; +void li_release_optionptr(liServer *srv, liOptionPtrValue *value) { + liServerOptionPtr *sopt; + + if (!srv || !value) return; - mark->sopt = NULL; + assert(g_atomic_int_get(&value->refcount) > 0); + if (!g_atomic_int_dec_and_test(&value->refcount)) return; + + sopt = value->sopt; + value->sopt = NULL; if (!sopt->free_option) { switch (sopt->type) { case LI_VALUE_NONE: @@ -252,39 +352,43 @@ void li_release_option(liServer *srv, liOptionSet *mark) { /** Does not free the /* Nothing to free */ break; case LI_VALUE_STRING: - if (mark->value.string) - g_string_free(mark->value.string, TRUE); + if (value->data.string) + g_string_free(value->data.string, TRUE); break; case LI_VALUE_LIST: - if (mark->value.list) - li_value_list_free(mark->value.list); + if (value->data.list) + li_value_list_free(value->data.list); break; case LI_VALUE_HASH: - if (mark->value.hash) - g_hash_table_destroy(mark->value.hash); + if (value->data.hash) + g_hash_table_destroy(value->data.hash); break; case LI_VALUE_ACTION: - if (mark->value.action) - li_action_release(srv, mark->value.action); + if (value->data.action) + li_action_release(srv, value->data.action); break; case LI_VALUE_CONDITION: - if (mark->value.cond) - li_condition_release(srv, mark->value.cond); + if (value->data.cond) + li_condition_release(srv, value->data.cond); break; } } else { - sopt->free_option(srv, sopt->p, sopt->module_index, mark->value); - } - { - liOptionValue empty = {0}; - mark->value = empty; + sopt->free_option(srv, sopt->p, sopt->module_index, value->data.ptr); } + g_slice_free(liOptionPtrValue, value); } liAction* li_option_action(liServer *srv, const gchar *name, liValue *val) { liOptionSet setting; + liServerOption *sopt; + + sopt = find_option(srv, name); + if (!sopt) { + ERROR(srv, "Unknown option '%s'", name); + return FALSE; + } - if (!li_parse_option(srv, name, val, &setting)) { + if (!li_parse_option(srv, sopt, name, val, &setting)) { return NULL; } @@ -359,30 +463,30 @@ void li_plugins_handle_vrclose(liVRequest *vr) { gboolean li_plugin_set_default_option(liServer *srv, const gchar* name, liValue *val) { liServerOption *sopt; - liOptionSet setting; - liOptionValue v; - - sopt = find_option(srv, name); + liServerOptionPtr *soptptr; - if (!sopt) { - ERROR(srv, "unknown option \"%s\"", name); - return FALSE; - } + if (NULL != (sopt = find_option(srv, name))) { + liOptionSet setting; - /* assign new value */ - if (!li_parse_option(srv, name, val, &setting)) { - return FALSE; - } + /* assign new value */ + if (!li_parse_option(srv, sopt, name, val, &setting)) { + return FALSE; + } - v = g_array_index(srv->option_def_values, liOptionValue, sopt->index); - g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value; + g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value; + } else if (NULL != (soptptr = find_optionptr(srv, name))) { + liOptionPtrSet setting; - /* free old value */ - setting.sopt = sopt; - setting.ndx = sopt->index; - setting.value = v; + /* assign new value */ + if (!li_parse_optionptr(srv, soptptr, name, val, &setting)) { + return FALSE; + } - li_release_option(srv, &setting); + g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index) = setting.value; + } else { + ERROR(srv, "unknown option \"%s\"", name); + return FALSE; + } return TRUE; } @@ -395,18 +499,16 @@ static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt) if (!sopt->parse_option) { switch (sopt->type) { - case LI_VALUE_NONE: - break; case LI_VALUE_BOOLEAN: oval.boolean = GPOINTER_TO_INT(sopt->default_value); + break; case LI_VALUE_NUMBER: oval.number = GPOINTER_TO_INT(sopt->default_value); break; - case LI_VALUE_STRING: - oval.string = g_string_new((const char*) sopt->default_value); - break; default: - oval.ptr = NULL; + ERROR(srv, "Invalid type '%s' for scalar option", + li_value_type_string(sopt->type)); + return FALSE; } } else { if (!sopt->parse_option(srv, sopt->p, sopt->module_index, NULL, &oval)) { @@ -423,25 +525,57 @@ static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt) return TRUE; } +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 { + if (!sopt->parse_option(srv, sopt->p, sopt->module_index, NULL, &ptr)) { + /* 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; +} + static void li_plugin_free_default_options(liServer *srv, liPlugin *p) { - static const liOptionValue oempty = {0}; GHashTableIter iter; gpointer k, v; - g_hash_table_iter_init(&iter, srv->options); + g_hash_table_iter_init(&iter, srv->optionptrs); while (g_hash_table_iter_next(&iter, &k, &v)) { - liServerOption *sopt = v; - liOptionSet mark; - mark.sopt = sopt; - mark.ndx = sopt->index; + liServerOptionPtr *sopt = v; if (sopt->p != p) continue; - mark.value = g_array_index(srv->option_def_values, liOptionValue, sopt->index); - - li_release_option(srv, &mark); - g_array_index(srv->option_def_values, liOptionValue, sopt->index) = oempty; + 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; } } diff --git a/src/main/plugin_core.c b/src/main/plugin_core.c index 5adfe5f..8379a66 100644 --- a/src/main/plugin_core.c +++ b/src/main/plugin_core.c @@ -420,7 +420,7 @@ static liHandlerResult core_handle_static(liVRequest *vr, gpointer param, gpoint struct stat st; int err; liHandlerResult res; - GArray *exclude_arr = CORE_OPTION(LI_CORE_OPTION_STATIC_FILE_EXCLUDE_EXTENSIONS).list; + GArray *exclude_arr = CORE_OPTIONPTR(LI_CORE_OPTION_STATIC_FILE_EXCLUDE_EXTENSIONS).list; static const gchar boundary[] = "fkj49sn38dcn3"; UNUSED(param); @@ -822,7 +822,7 @@ static gboolean core_module_load(liServer *srv, liPlugin* p, liValue *val, gpoin } } g_array_free(mods->data.list, TRUE); - mods->data.list = li_value_extract_ist(val); + mods->data.list = li_value_extract_list(val); } else { ERROR(srv, "module_load takes either a string or a list of strings as parameter, %s given", li_value_type_string(val->type)); return FALSE; @@ -880,7 +880,7 @@ static gboolean core_stat_cache_ttl(liServer *srv, liPlugin* p, liValue *val, gp * OPTIONS */ -static gboolean core_option_log_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { +static gboolean core_option_log_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { GHashTableIter iter; gpointer k, v; liLogLevel level; @@ -890,7 +890,7 @@ static gboolean core_option_log_parse(liServer *srv, liPlugin *p, size_t ndx, li UNUSED(p); UNUSED(ndx); - oval->list = arr; + *oval = arr; g_array_set_size(arr, 6); /* default value */ @@ -937,8 +937,8 @@ static gboolean core_option_log_parse(liServer *srv, liPlugin *p, size_t ndx, li return TRUE; } -static void core_option_log_free(liServer *srv, liPlugin *p, size_t ndx, liOptionValue oval) { - GArray *arr = oval.list; +static void core_option_log_free(liServer *srv, liPlugin *p, size_t ndx, gpointer oval) { + GArray *arr = oval; UNUSED(p); UNUSED(ndx); @@ -951,25 +951,25 @@ static void core_option_log_free(liServer *srv, liPlugin *p, size_t ndx, liOptio g_array_free(arr, TRUE); } -static gboolean core_option_log_timestamp_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { +static gboolean core_option_log_timestamp_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { UNUSED(p); UNUSED(ndx); if (!val) return TRUE; - oval->ptr = li_log_timestamp_new(srv, li_value_extract_string(val)); + *oval = li_log_timestamp_new(srv, li_value_extract_string(val)); return TRUE; } -static void core_option_log_timestamp_free(liServer *srv, liPlugin *p, size_t ndx, liOptionValue oval) { +static void core_option_log_timestamp_free(liServer *srv, liPlugin *p, size_t ndx, gpointer oval) { UNUSED(p); UNUSED(ndx); - if (!oval.ptr) return; - li_log_timestamp_free(srv, oval.ptr); + if (!oval) return; + li_log_timestamp_free(srv, oval); } -static gboolean core_option_static_exclude_exts_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { +static gboolean core_option_static_exclude_exts_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { GArray *arr; UNUSED(srv); UNUSED(p); @@ -987,13 +987,13 @@ static gboolean core_option_static_exclude_exts_parse(liServer *srv, liPlugin *p } /* everything ok */ - oval->list = li_value_extract_list(val); + *oval = li_value_extract_list(val); return TRUE; } -static gboolean core_option_mime_types_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { +static gboolean core_option_mime_types_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { GArray *arr; UNUSED(srv); UNUSED(p); @@ -1002,7 +1002,7 @@ static gboolean core_option_mime_types_parse(liServer *srv, liPlugin *p, size_t /* default value */ if (!val) { - oval->list = g_array_new(FALSE, TRUE, sizeof(liValue)); + *oval = g_array_new(FALSE, TRUE, sizeof(liValue)); return TRUE; } @@ -1030,20 +1030,21 @@ static gboolean core_option_mime_types_parse(liServer *srv, liPlugin *p, size_t } /* everything ok */ - oval->list = li_value_extract_list(val); + *oval = li_value_extract_list(val); return TRUE; } -static void core_option_mime_types_free(liServer *srv, liPlugin *p, size_t ndx, liOptionValue oval) { +static void core_option_mime_types_free(liServer *srv, liPlugin *p, size_t ndx, gpointer oval) { + GArray *list = oval; UNUSED(srv); UNUSED(p); UNUSED(ndx); - for (guint i = 0; i < oval.list->len; i++) - li_value_free(g_array_index(oval.list, liValue*, i)); + for (guint i = 0; i < list->len; i++) + li_value_free(g_array_index(list, liValue*, i)); - g_array_free(oval.list, TRUE); + g_array_free(list, TRUE); } static gboolean core_option_etag_use_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { @@ -1489,23 +1490,29 @@ static void core_suspend(liServer *srv, liPlugin *p, gint32 id, GString *data) { } static const liPluginOption options[] = { - { "debug.log_request_handling", LI_VALUE_BOOLEAN, GINT_TO_POINTER(FALSE), NULL, NULL }, + { "debug.log_request_handling", LI_VALUE_BOOLEAN, FALSE, NULL }, + { "static.range_requests", LI_VALUE_BOOLEAN, TRUE, NULL }, + + { "keepalive.timeout", LI_VALUE_NUMBER, 5, NULL }, + { "keepalive.requests", LI_VALUE_NUMBER, 0, NULL }, + + { "etag.use", LI_VALUE_NONE, 0, core_option_etag_use_parse }, /* type in config is list, internal type is number for flags */ + + { NULL, 0, 0, NULL } +}; + +static const liPluginOptionPtr optionptrs[] = { { "log.timestamp", LI_VALUE_STRING, NULL, core_option_log_timestamp_parse, core_option_log_timestamp_free }, { "log", LI_VALUE_HASH, NULL, core_option_log_parse, core_option_log_free }, { "static.exclude_extensions", LI_VALUE_LIST, NULL, core_option_static_exclude_exts_parse, NULL }, - { "static.range_requests", LI_VALUE_BOOLEAN, GINT_TO_POINTER(TRUE), NULL, NULL }, { "server.name", LI_VALUE_STRING, NULL, NULL, NULL }, { "server.tag", LI_VALUE_STRING, PACKAGE_DESC, NULL, NULL }, - { "keepalive.timeout", LI_VALUE_NUMBER, GINT_TO_POINTER(5), NULL, NULL }, - { "keepalive.requests", LI_VALUE_NUMBER, GINT_TO_POINTER(0), NULL, NULL }, { "mime_types", LI_VALUE_LIST, NULL, core_option_mime_types_parse, core_option_mime_types_free }, - { "etag.use", LI_VALUE_NONE, NULL, core_option_etag_use_parse, NULL }, /* type in config is list, internal type is number for flags */ - { NULL, 0, NULL, NULL, NULL } }; @@ -1564,6 +1571,7 @@ void li_plugin_core_init(liServer *srv, liPlugin *p, gpointer userdata) { UNUSED(srv); UNUSED(userdata); p->options = options; + p->optionptrs = optionptrs; p->actions = actions; p->setups = setups; p->angelcbs = angelcbs; diff --git a/src/main/response.c b/src/main/response.c index d31a8e9..af0f36a 100644 --- a/src/main/response.c +++ b/src/main/response.c @@ -113,7 +113,7 @@ gboolean li_response_send_headers(liConnection *con) { } if (!have_server) { - GString *tag = CORE_OPTION(LI_CORE_OPTION_SERVER_TAG).string; + GString *tag = CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_TAG).string; if (tag->len) { g_string_append_len(head, CONST_STR_LEN("Server: ")); @@ -244,7 +244,7 @@ void li_response_send_error_page(liConnection *con) { g_string_append_len(html, str, len); g_string_append_len(html, CONST_STR_LEN("

")); - g_string_append_len(html, GSTR_LEN(CORE_OPTION(LI_CORE_OPTION_SERVER_TAG).string)); + g_string_append_len(html, GSTR_LEN(CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_TAG).string)); g_string_append_len(html, CONST_STR_LEN( "

\n" " \n" diff --git a/src/main/server.c b/src/main/server.c index 46a8280..671204a 100644 --- a/src/main/server.c +++ b/src/main/server.c @@ -41,10 +41,14 @@ void li_server_socket_acquire(liServerSocket* sock) { g_atomic_int_inc(&sock->refcount); } -static void server_value_free(gpointer _so) { +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); } @@ -108,13 +112,15 @@ liServer* li_server_new(const gchar *module_dir) { srv->modules = li_modules_new(srv, module_dir); 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_value_free); + 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*)); srv->mainaction = NULL; @@ -246,6 +252,13 @@ void li_server_free(liServer* srv) { } 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); diff --git a/src/main/value.c b/src/main/value.c index 2f59af7..1d827a7 100644 --- a/src/main/value.c +++ b/src/main/value.c @@ -236,6 +236,39 @@ GString *li_value_to_string(liValue *val) { return str; } +gpointer li_value_extract_ptr(liValue *val) { + gpointer ptr = NULL; + + if (!val) return NULL; + + switch (val->type) { + case LI_VALUE_NONE: + break; + case LI_VALUE_BOOLEAN: + break; + case LI_VALUE_NUMBER: + break; + case LI_VALUE_STRING: + ptr = val->data.string; + break; + case LI_VALUE_LIST: + ptr = val->data.list; + break; + case LI_VALUE_HASH: + ptr = val->data.hash; + break; + case LI_VALUE_ACTION: + ptr = val->data.val_action.action; + break; + case LI_VALUE_CONDITION: + ptr = val->data.val_action.action; + break; + } + val->type = LI_VALUE_NONE; + return ptr; +} + + GString* li_value_extract_string(liValue *val) { if (val->type != LI_VALUE_STRING) return NULL; val->type = LI_VALUE_NONE; diff --git a/src/main/virtualrequest.c b/src/main/virtualrequest.c index cb04eb6..5b4b222 100644 --- a/src/main/virtualrequest.c +++ b/src/main/virtualrequest.c @@ -155,6 +155,15 @@ liVRequest* li_vrequest_new(liConnection *con, liVRequestHandlerCB handle_respon vr->plugin_ctx = g_ptr_array_new(); g_ptr_array_set_size(vr->plugin_ctx, g_hash_table_size(srv->plugins)); vr->options = g_slice_copy(srv->option_def_values->len * sizeof(liOptionValue), srv->option_def_values->data); + vr->optionptrs = g_slice_copy(srv->optionptr_def_values->len * sizeof(liOptionPtrValue*), srv->optionptr_def_values->data); + { + guint i; + for (i = 0; i < srv->optionptr_def_values->len; i++) { + if (vr->optionptrs[i]) { + g_atomic_int_inc(&vr->optionptrs[i]->refcount); + } + } + } li_request_init(&vr->request); li_physical_init(&vr->physical); @@ -188,6 +197,8 @@ liVRequest* li_vrequest_new(liConnection *con, liVRequestHandlerCB handle_respon } void li_vrequest_free(liVRequest* vr) { + liServer *srv = vr->wrk->srv; + li_action_stack_clear(vr, &vr->action_stack); li_plugins_handle_vrclose(vr); g_ptr_array_free(vr->plugin_ctx, TRUE); @@ -207,7 +218,14 @@ void li_vrequest_free(liVRequest* vr) { g_atomic_int_set(&vr->queued, 0); } - g_slice_free1(vr->wrk->srv->option_def_values->len * sizeof(liOptionValue), vr->options); + g_slice_free1(srv->option_def_values->len * sizeof(liOptionValue), vr->options); + { + guint i; + for (i = 0; i < srv->optionptr_def_values->len; i++) { + li_release_optionptr(srv, vr->optionptrs[i]); + } + } + g_slice_free1(srv->optionptr_def_values->len * sizeof(liOptionPtrValue*), vr->optionptrs); while (vr->stat_cache_entries->len > 0 ) { @@ -225,6 +243,8 @@ void li_vrequest_free(liVRequest* vr) { } void li_vrequest_reset(liVRequest *vr, gboolean keepalive) { + liServer *srv = vr->wrk->srv; + li_action_stack_reset(vr, &vr->action_stack); li_plugins_handle_vrclose(vr); { @@ -266,7 +286,18 @@ void li_vrequest_reset(liVRequest *vr, gboolean keepalive) { li_stat_cache_entry_release(vr, sce); } - memcpy(vr->options, vr->wrk->srv->option_def_values->data, vr->wrk->srv->option_def_values->len * sizeof(liOptionValue)); + memcpy(vr->options, srv->option_def_values->data, srv->option_def_values->len * sizeof(liOptionValue)); + { + guint i; + for (i = 0; i < srv->optionptr_def_values->len; i++) { + liOptionPtrValue *oval = g_array_index(srv->optionptr_def_values, liOptionPtrValue*, i); + if (vr->optionptrs[i] != oval) { + li_release_optionptr(srv, vr->optionptrs[i]); + g_atomic_int_inc(&oval->refcount); + vr->optionptrs[i] = oval; + } + } + } if (1 != g_atomic_int_get(&vr->ref->refcount)) { /* If we are not the only user of vr->ref we have to get a new one and detach the old */ diff --git a/src/modules/mod_access.c b/src/modules/mod_access.c index 1bec1bf..676f90f 100644 --- a/src/modules/mod_access.c +++ b/src/modules/mod_access.c @@ -55,14 +55,21 @@ struct access_check_data { }; typedef struct access_check_data access_check_data; -enum { ACCESS_DENY = 1, ACCESS_ALLOW = 2 } access_values; +enum { ACCESS_DENY = 1, ACCESS_ALLOW = 2 }; +enum { + OPTION_LOG_BLOCKED = 0 +}; + +enum { + OPTION_REDIRECT_URL = 0 +}; static liHandlerResult access_check(liVRequest *vr, gpointer param, gpointer *context) { access_check_data *acd = param; liSockAddr *addr = vr->con->remote_addr.addr; - gboolean log_blocked = _OPTION(vr, acd->p, 0).boolean; - GString *redirect_url = _OPTION(vr, acd->p, 1).string; + gboolean log_blocked = _OPTION(vr, acd->p, OPTION_LOG_BLOCKED).boolean; + GString *redirect_url = _OPTIONPTR(vr, acd->p, OPTION_REDIRECT_URL).string; UNUSED(context); UNUSED(redirect_url); @@ -202,8 +209,8 @@ failed_free_acd: static liHandlerResult access_deny(liVRequest *vr, gpointer param, gpointer *context) { - gboolean log_blocked = _OPTION(vr, ((liPlugin*)param), 0).boolean; - GString *redirect_url = _OPTION(vr, ((liPlugin*)param), 1).string; + gboolean log_blocked = _OPTION(vr, ((liPlugin*)param), OPTION_LOG_BLOCKED).boolean; + GString *redirect_url = _OPTIONPTR(vr, ((liPlugin*)param), OPTION_REDIRECT_URL).string; UNUSED(context); UNUSED(redirect_url); @@ -233,7 +240,12 @@ static liAction* access_deny_create(liServer *srv, liPlugin* p, liValue *val, gp static const liPluginOption options[] = { - { "access.log_blocked", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "access.log_blocked", LI_VALUE_BOOLEAN, 0, NULL }, + + { NULL, 0, 0, NULL } +}; + +static const liPluginOptionPtr optionptrs[] = { { "access.redirect_url", LI_VALUE_STRING, NULL, NULL, NULL }, { NULL, 0, NULL, NULL, NULL } @@ -255,6 +267,7 @@ static void plugin_access_init(liServer *srv, liPlugin *p, gpointer userdata) { UNUSED(srv); UNUSED(userdata); p->options = options; + p->optionptrs = optionptrs; p->actions = actions; p->setups = setups; } diff --git a/src/modules/mod_accesslog.c b/src/modules/mod_accesslog.c index 16239fc..240e8ba 100644 --- a/src/modules/mod_accesslog.c +++ b/src/modules/mod_accesslog.c @@ -43,7 +43,7 @@ struct al_data { typedef struct al_data al_data; enum { - AL_OPTION_ACCESSLOG, + AL_OPTION_ACCESSLOG = 0, AL_OPTION_ACCESSLOG_FORMAT }; @@ -339,8 +339,8 @@ static GString *al_format_log(liVRequest *vr, al_data *ald, GArray *format) { g_string_append_len(str, GSTR_LEN(req->uri.path)); break; case AL_FORMAT_SERVER_NAME: - if (CORE_OPTION(LI_CORE_OPTION_SERVER_NAME).string) - g_string_append_len(str, GSTR_LEN(CORE_OPTION(LI_CORE_OPTION_SERVER_NAME).string)); + if (CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_NAME).string) + g_string_append_len(str, GSTR_LEN(CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_NAME).string)); else g_string_append_len(str, GSTR_LEN(req->uri.host)); break; @@ -386,8 +386,8 @@ static void al_handle_vrclose(liVRequest *vr, liPlugin *p) { /* VRequest closed, log it */ GString *msg; liResponse *resp = &vr->response; - liLog *log = OPTION(AL_OPTION_ACCESSLOG).ptr; - GArray *format = OPTION(AL_OPTION_ACCESSLOG_FORMAT).list; + liLog *log = OPTIONPTR(AL_OPTION_ACCESSLOG).ptr; + GArray *format = OPTIONPTR(AL_OPTION_ACCESSLOG_FORMAT).list; UNUSED(p); @@ -403,16 +403,16 @@ static void al_handle_vrclose(liVRequest *vr, liPlugin *p) { -static void al_option_accesslog_free(liServer *srv, liPlugin *p, size_t ndx, liOptionValue oval) { +static void al_option_accesslog_free(liServer *srv, liPlugin *p, size_t ndx, gpointer oval) { UNUSED(p); UNUSED(ndx); - if (!oval.ptr) return; + if (!oval) return; - li_log_unref(srv, oval.ptr); + li_log_unref(srv, oval); } -static gboolean al_option_accesslog_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { +static gboolean al_option_accesslog_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { liLog *log; UNUSED(p); @@ -430,12 +430,12 @@ static gboolean al_option_accesslog_parse(liServer *srv, liPlugin *p, size_t ndx log = li_log_new(srv, li_log_type_from_path(val->data.string), val->data.string); - oval->ptr = log; + *oval = log; return TRUE; } -static void al_option_accesslog_format_free(liServer *srv, liPlugin *p, size_t ndx, liOptionValue oval) { +static void al_option_accesslog_format_free(liServer *srv, liPlugin *p, size_t ndx, gpointer oval) { GArray *arr; guint i; @@ -443,9 +443,9 @@ static void al_option_accesslog_format_free(liServer *srv, liPlugin *p, size_t n UNUSED(p); UNUSED(ndx); - if (!oval.list) return; + if (!oval) return; - arr = oval.list; + arr = oval; for (i = 0; i < arr->len; i++) { al_format_entry *afe = &g_array_index(arr, al_format_entry, i); @@ -456,7 +456,7 @@ static void al_option_accesslog_format_free(liServer *srv, liPlugin *p, size_t n g_array_free(arr, TRUE); } -static gboolean al_option_accesslog_format_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { +static gboolean al_option_accesslog_format_parse(liServer *srv, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { GArray *arr; UNUSED(p); @@ -479,15 +479,15 @@ static gboolean al_option_accesslog_format_parse(liServer *srv, liPlugin *p, siz return FALSE; } - oval->list = arr; + *oval = arr; return TRUE; } -static const liPluginOption options[] = { +static const liPluginOptionPtr optionptrs[] = { { "accesslog", LI_VALUE_NONE, NULL, al_option_accesslog_parse, al_option_accesslog_free }, - { "accesslog.format", LI_VALUE_STRING, NULL, al_option_accesslog_format_parse, al_option_accesslog_format_free }, + { "accesslog.format", LI_VALUE_STRING, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"", al_option_accesslog_format_parse, al_option_accesslog_format_free }, { NULL, 0, NULL, NULL, NULL } }; @@ -513,7 +513,7 @@ static void plugin_accesslog_init(liServer *srv, liPlugin *p, gpointer userdata) UNUSED(srv); UNUSED(userdata); p->free = plugin_accesslog_free; - p->options = options; + p->optionptrs = optionptrs; p->actions = actions; p->setups = setups; p->handle_vrclose = al_handle_vrclose; @@ -524,19 +524,10 @@ static void plugin_accesslog_init(liServer *srv, liPlugin *p, gpointer userdata) } LI_API gboolean mod_accesslog_init(liModules *mods, liModule *mod) { - liValue *val; - GString *str; - MODULE_VERSION_CHECK(mods); mod->config = li_plugin_register(mods->main, "mod_accesslog", plugin_accesslog_init, NULL); - /* set default accesslog format */ - str = g_string_new_len(CONST_STR_LEN("%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"")); - val = li_value_new_string(str); - li_plugin_set_default_option(mods->main, "accesslog.format", val); - li_value_free(val); - return mod->config != NULL; } diff --git a/src/modules/mod_auth.c b/src/modules/mod_auth.c index 74f6cbe..ca5c000 100644 --- a/src/modules/mod_auth.c +++ b/src/modules/mod_auth.c @@ -500,9 +500,9 @@ static liAction* auth_deny(liServer *srv, liPlugin* p, liValue *val, gpointer us } static const liPluginOption options[] = { - { "auth.debug", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "auth.debug", LI_VALUE_BOOLEAN, 0, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_balancer.c b/src/modules/mod_balancer.c index e309c2d..e22b04d 100644 --- a/src/modules/mod_balancer.c +++ b/src/modules/mod_balancer.c @@ -180,7 +180,7 @@ static liAction* balancer_rr(liServer *srv, liPlugin* p, liValue *val, gpointer static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_cache_disk_etag.c b/src/modules/mod_cache_disk_etag.c index a56a8bf..a46a970 100644 --- a/src/modules/mod_cache_disk_etag.c +++ b/src/modules/mod_cache_disk_etag.c @@ -321,7 +321,7 @@ static liAction* cache_etag_create(liServer *srv, liPlugin* p, liValue *val, gpo } static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_debug.c b/src/modules/mod_debug.c index b10724e..a083ddf 100644 --- a/src/modules/mod_debug.c +++ b/src/modules/mod_debug.c @@ -308,7 +308,7 @@ static liAction* debug_show_connections_create(liServer *srv, liPlugin* p, liVal static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_deflate.c b/src/modules/mod_deflate.c index fc96221..a900fa8 100644 --- a/src/modules/mod_deflate.c +++ b/src/modules/mod_deflate.c @@ -716,9 +716,9 @@ option_failed: } static const liPluginOption options[] = { - { "deflate.debug", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "deflate.debug", LI_VALUE_BOOLEAN, FALSE, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_dirlist.c b/src/modules/mod_dirlist.c index 45d3a8d..1853e90 100644 --- a/src/modules/mod_dirlist.c +++ b/src/modules/mod_dirlist.c @@ -574,7 +574,7 @@ static liHandlerResult dirlist(liVRequest *vr, gpointer param, gpointer *context g_string_append_len(listing, CONST_STR_LEN(javascript_sort)); } - g_string_append_printf(listing, html_footer, CORE_OPTION(LI_CORE_OPTION_SERVER_TAG).string->str); + g_string_append_printf(listing, html_footer, CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_TAG).string->str); li_chunkqueue_append_string(vr->out, listing); g_string_free(encoded, TRUE); @@ -781,9 +781,9 @@ static liAction* dirlist_create(liServer *srv, liPlugin* p, liValue *val, gpoint } static const liPluginOption options[] = { - { "dirlist.debug", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "dirlist.debug", LI_VALUE_BOOLEAN, 0, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_expire.c b/src/modules/mod_expire.c index e2cf5e9..ead7e8b 100644 --- a/src/modules/mod_expire.c +++ b/src/modules/mod_expire.c @@ -236,7 +236,7 @@ static liAction* expire_create(liServer *srv, liPlugin* p, liValue *val, gpointe static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_fastcgi.c b/src/modules/mod_fastcgi.c index 2715454..5a6b074 100644 --- a/src/modules/mod_fastcgi.c +++ b/src/modules/mod_fastcgi.c @@ -327,7 +327,7 @@ static void fastcgi_env_create(liVRequest *vr, liEnvironmentDup *envdup, GByteAr liConnection *con = vr->con; GString *tmp = con->wrk->tmp_str; - fastcgi_env_add(buf, envdup, CONST_STR_LEN("SERVER_SOFTWARE"), GSTR_LEN(CORE_OPTION(LI_CORE_OPTION_SERVER_TAG).string)); + fastcgi_env_add(buf, envdup, CONST_STR_LEN("SERVER_SOFTWARE"), GSTR_LEN(CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_TAG).string)); fastcgi_env_add(buf, envdup, CONST_STR_LEN("SERVER_NAME"), GSTR_LEN(vr->request.uri.host)); fastcgi_env_add(buf, envdup, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); { @@ -785,9 +785,9 @@ static liAction* fastcgi_create(liServer *srv, liPlugin* p, liValue *val, gpoint } static const liPluginOption options[] = { - { "fastcgi.log_plain_errors", LI_VALUE_BOOLEAN, GINT_TO_POINTER(FALSE), NULL, NULL }, + { "fastcgi.log_plain_errors", LI_VALUE_BOOLEAN, FALSE, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_fortune.c b/src/modules/mod_fortune.c index 06768da..8e2f37a 100644 --- a/src/modules/mod_fortune.c +++ b/src/modules/mod_fortune.c @@ -145,7 +145,7 @@ static gboolean fortune_load(liServer *srv, liPlugin* p, liValue *val, gpointer static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_lua.c b/src/modules/mod_lua.c index b2951a9..dca9177 100644 --- a/src/modules/mod_lua.c +++ b/src/modules/mod_lua.c @@ -391,7 +391,7 @@ static luaPlugin* lua_plugin_create_data(liServer *srv, lua_State *L) { } static const liPluginOption lp_options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static void lua_plugin_free(liServer *srv, liPlugin *p) { @@ -537,7 +537,7 @@ static gboolean lua_plugin(liServer *srv, liPlugin *p, liValue *val, gpointer us } static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_openssl.c b/src/modules/mod_openssl.c index a0989fb..0cf0c09 100644 --- a/src/modules/mod_openssl.c +++ b/src/modules/mod_openssl.c @@ -472,7 +472,7 @@ error_free_socket: } static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_proxy.c b/src/modules/mod_proxy.c index 65077f2..df9f3d5 100644 --- a/src/modules/mod_proxy.c +++ b/src/modules/mod_proxy.c @@ -440,7 +440,7 @@ static liAction* proxy_create(liServer *srv, liPlugin* p, liValue *val, gpointer } static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_redirect.c b/src/modules/mod_redirect.c index aecd7fa..1bacb5d 100644 --- a/src/modules/mod_redirect.c +++ b/src/modules/mod_redirect.c @@ -514,9 +514,9 @@ static liAction* redirect_create(liServer *srv, liPlugin* p, liValue *val, gpoin static const liPluginOption options[] = { - { "redirect.debug", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "redirect.debug", LI_VALUE_BOOLEAN, FALSE, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_rewrite.c b/src/modules/mod_rewrite.c index a8c391a..43662f0 100644 --- a/src/modules/mod_rewrite.c +++ b/src/modules/mod_rewrite.c @@ -483,9 +483,9 @@ static liAction* rewrite_create(liServer *srv, liPlugin* p, liValue *val, gpoint static const liPluginOption options[] = { - { "rewrite.debug", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "rewrite.debug", LI_VALUE_BOOLEAN, FALSE, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_scgi.c b/src/modules/mod_scgi.c index 76c0595..2faf315 100644 --- a/src/modules/mod_scgi.c +++ b/src/modules/mod_scgi.c @@ -177,7 +177,7 @@ static void scgi_env_create(liVRequest *vr, liEnvironmentDup *envdup, GByteArray scgi_env_add(buf, envdup, CONST_STR_LEN("SCGI"), CONST_STR_LEN("1")); - scgi_env_add(buf, envdup, CONST_STR_LEN("SERVER_SOFTWARE"), GSTR_LEN(CORE_OPTION(LI_CORE_OPTION_SERVER_TAG).string)); + scgi_env_add(buf, envdup, CONST_STR_LEN("SERVER_SOFTWARE"), GSTR_LEN(CORE_OPTIONPTR(LI_CORE_OPTION_SERVER_TAG).string)); scgi_env_add(buf, envdup, CONST_STR_LEN("SERVER_NAME"), GSTR_LEN(vr->request.uri.host)); scgi_env_add(buf, envdup, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); { @@ -535,7 +535,7 @@ static liAction* scgi_create(liServer *srv, liPlugin* p, liValue *val, gpointer } static const liPluginOption options[] = { - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = { diff --git a/src/modules/mod_status.c b/src/modules/mod_status.c index 45dc1f0..ba87d53 100644 --- a/src/modules/mod_status.c +++ b/src/modules/mod_status.c @@ -533,7 +533,7 @@ static GString *status_info_full(liVRequest *vr, liPlugin *p, gboolean short_inf } /* css */ - css = _OPTION(vr, p, 0).string; + css = _OPTIONPTR(vr, p, 0).string; if (!css || !css->len) /* default css */ g_string_append_len(html, CONST_STR_LEN(css_default)); @@ -936,7 +936,7 @@ static liHandlerResult status_info_runtime(liVRequest *vr, liPlugin *p) { /* css */ { - GString* css = _OPTION(vr, p, 0).string; + GString* css = _OPTIONPTR(vr, p, 0).string; if (!css || !css->len) /* default css */ g_string_append_len(html, CONST_STR_LEN(css_default)); @@ -1144,6 +1144,10 @@ static liHandlerResult status_info_runtime(liVRequest *vr, liPlugin *p) { static const liPluginOption options[] = { + { NULL, 0, 0, NULL } +}; + +static const liPluginOptionPtr optionptrs[] = { { "status.css", LI_VALUE_STRING, NULL, NULL, NULL }, { NULL, 0, NULL, NULL, NULL } diff --git a/src/modules/mod_vhost.c b/src/modules/mod_vhost.c index 8133e50..b1b39c8 100644 --- a/src/modules/mod_vhost.c +++ b/src/modules/mod_vhost.c @@ -686,9 +686,9 @@ static liAction* vhost_pattern_create(liServer *srv, liPlugin* p, liValue *val, static const liPluginOption options[] = { - { "vhost.debug", LI_VALUE_BOOLEAN, NULL, NULL, NULL }, + { "vhost.debug", LI_VALUE_BOOLEAN, FALSE, NULL }, - { NULL, 0, NULL, NULL, NULL } + { NULL, 0, 0, NULL } }; static const liPluginAction actions[] = {