diff --git a/src/config_parser.rl b/src/config_parser.rl index 02002b5..6bd1073 100644 --- a/src/config_parser.rl +++ b/src/config_parser.rl @@ -479,8 +479,16 @@ _printf("got assignment: %s = %s; in line %zd\n", name->data.string->str, value_type_string(val->type), ctx->line); if (ctx->in_setup_block) { - /* in setup { } block => set default values for options */ - /* TODO */ + /* in setup { } block, override default values for options */ + + if (!plugin_set_default_option(srv, name->data.string->str, val)) { + ERROR(srv, "failed overriding default value for option \"%s\"", name->data.string->str); + value_free(name); + value_free(val); + return FALSE; + } + + value_free(val); } else if (g_str_has_prefix(name->data.string->str, "var.")) { /* assignment vor user defined variable, insert into hashtable */ diff --git a/src/connection.c b/src/connection.c index e6e8e48..a6f7581 100644 --- a/src/connection.c +++ b/src/connection.c @@ -157,7 +157,7 @@ connection* connection_new(worker *wrk) { action_stack_init(&con->action_stack); - con->options = g_slice_copy(srv->option_count * sizeof(*srv->option_def_values), srv->option_def_values); + con->options = g_slice_copy(srv->option_def_values->len * sizeof(option_value), srv->option_def_values->data); request_init(&con->request); physical_init(&con->physical); @@ -199,7 +199,7 @@ void connection_reset(connection *con) { action_stack_reset(con->srv, &con->action_stack); - memcpy(con->options, con->srv->option_def_values, con->srv->option_count * sizeof(*con->srv->option_def_values)); + memcpy(con->options, con->srv->option_def_values->data, con->srv->option_def_values->len * sizeof(option_value)); request_reset(&con->request); physical_reset(&con->physical); @@ -253,7 +253,7 @@ void connection_reset_keep_alive(connection *con) { action_stack_reset(con->srv, &con->action_stack); - memcpy(con->options, con->srv->option_def_values, con->srv->option_count * sizeof(*con->srv->option_def_values)); + memcpy(con->options, con->srv->option_def_values->data, con->srv->option_def_values->len * sizeof(option_value)); request_reset(&con->request); physical_reset(&con->physical); @@ -285,7 +285,7 @@ void connection_free(connection *con) { action_stack_clear(con->srv, &con->action_stack); - g_slice_free1(con->srv->option_count * sizeof(*con->srv->option_def_values), con->options); + g_slice_free1(con->srv->option_def_values->len * sizeof(option_value), con->options); request_clear(&con->request); physical_clear(&con->physical); diff --git a/src/plugin.c b/src/plugin.c index 279c0b1..1e9fe15 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -134,6 +134,7 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) { so->p = p; so->default_value = po->default_value; g_hash_table_insert(srv->options, (gchar*) po->name, so); + plugin_load_default_option(srv, so); } } @@ -326,38 +327,67 @@ void plugins_handle_close(connection *con) { } } -gboolean plugins_load_default_options(server *srv) { - GHashTableIter iter; - gpointer k, v; +gboolean plugin_set_default_option(server *srv, const gchar* name, value *val) { + server_option *sopt; + option_set setting; - g_hash_table_iter_init(&iter, srv->options); - while (g_hash_table_iter_next(&iter, &k, &v)) { - server_option *sopt = v; - option_value oval = { 0 }; - - if (!sopt->parse_option) { - switch (sopt->type) { - case VALUE_NONE: - break; - case VALUE_BOOLEAN: - oval.boolean = GPOINTER_TO_INT(sopt->default_value); - case VALUE_NUMBER: - oval.number = GPOINTER_TO_INT(sopt->default_value); - break; - case VALUE_STRING: - oval.string = g_string_new((const char*) sopt->default_value); - break; - default: - oval.ptr = NULL; - } - } else { - if (!sopt->parse_option(srv, sopt->p, sopt->module_index, NULL, &oval)) { - /* errors should be logged by parse function */ - return FALSE; - } + sopt = find_option(srv, name); + + if (!sopt) { + ERROR(srv, "unknown option \"%s\"", name); + return FALSE; + } + + /* free old value */ + setting.sopt = sopt; + setting.ndx = sopt->index; + setting.value = g_array_index(srv->option_def_values, option_value, sopt->index); + + release_option(srv, &setting); + + /* assign new value */ + if (!parse_option(srv, name, val, &setting)) { + return FALSE; + } + + g_array_index(srv->option_def_values, option_value, sopt->index) = setting.value; + + return TRUE; +} + +gboolean plugin_load_default_option(server *srv, server_option *sopt) { + option_value oval = {0}; + + if (!sopt) + return FALSE; + + if (!sopt->parse_option) { + switch (sopt->type) { + case VALUE_NONE: + break; + case VALUE_BOOLEAN: + oval.boolean = GPOINTER_TO_INT(sopt->default_value); + case VALUE_NUMBER: + oval.number = GPOINTER_TO_INT(sopt->default_value); + break; + case VALUE_STRING: + oval.string = g_string_new((const char*) sopt->default_value); + break; + default: + oval.ptr = NULL; + } + } else { + if (!sopt->parse_option(srv, sopt->p, sopt->module_index, NULL, &oval)) { + /* errors should be logged by parse function */ + return FALSE; } - srv->option_def_values[sopt->index] = oval; } + + if (srv->option_def_values->len <= sopt->index) + g_array_set_size(srv->option_def_values, sopt->index + 1); + + g_array_index(srv->option_def_values, option_value, sopt->index) = oval; + return TRUE; } @@ -372,9 +402,10 @@ void plugins_free_default_options(server *srv) { option_set mark; mark.sopt = sopt; mark.ndx = sopt->index; - mark.value = srv->option_def_values[sopt->index]; + + mark.value = g_array_index(srv->option_def_values, option_value, sopt->index); release_option(srv, &mark); - srv->option_def_values[sopt->index] = oempty; + g_array_index(srv->option_def_values, option_value, sopt->index) = oempty; } } diff --git a/src/plugin.h b/src/plugin.h index 09c1a95..31ea33f 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -132,7 +132,7 @@ struct server_setup { PluginSetup setup; }; -/* Needed my modules to register their plugin(s) */ +/* Needed by modules to register their plugin(s) */ LI_API gboolean plugin_register(server *srv, const gchar *name, PluginInit init); /* Internal needed functions */ @@ -156,9 +156,11 @@ LI_API action* create_action(server *srv, const gchar *name, value *value); /** For setup function, e.g. 'listen "127.0.0.1:8080"'; free value after call */ LI_API gboolean call_setup(server *srv, const char *name, value *val); -LI_API gboolean plugins_load_default_options(server *srv); LI_API void plugins_free_default_options(server *srv); +LI_API gboolean plugin_load_default_option(server *srv, server_option *sopt); +LI_API gboolean plugin_set_default_option(server *srv, const gchar* name, value *val); + /* needs connection *con and plugin *p */ #define OPTION(idx) _OPTION(con, p, idx) #define _OPTION(con, p, idx) (con->options[p->opt_base_index + idx]) diff --git a/src/plugin_core.c b/src/plugin_core.c index bb35f52..d1b11d1 100644 --- a/src/plugin_core.c +++ b/src/plugin_core.c @@ -453,7 +453,17 @@ static gboolean core_option_log_parse(server *srv, plugin *p, size_t ndx, value oval->list = arr; g_array_set_size(arr, 5); - if (!val) return TRUE; /* default value */ + + /* default value */ + if (!val) { + /* default: log LOG_LEVEL_WARNING and LOG_LEVEL_ERROR to stderr */ + log_t *log = srv->logs.stderr; + log_ref(srv, log); + g_array_index(arr, log_t*, LOG_LEVEL_WARNING) = log; + log_ref(srv, log); + g_array_index(arr, log_t*, LOG_LEVEL_ERROR) = log; + return TRUE; + } g_hash_table_iter_init(&iter, val->data.hash); while (g_hash_table_iter_next(&iter, &k, &v)) { diff --git a/src/server.c b/src/server.c index cdfc1c0..fbb7aa3 100644 --- a/src/server.c +++ b/src/server.c @@ -66,6 +66,7 @@ server* server_new() { srv->setups = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_setup_free); srv->plugins_handle_close = g_array_new(FALSE, TRUE, sizeof(plugin*)); + srv->option_def_values = g_array_new(FALSE, TRUE, sizeof(option_value)); srv->mainaction = NULL; @@ -122,10 +123,10 @@ void server_free(server* srv) { action_release(srv, srv->mainaction); - if (srv->option_def_values) { + if (srv->option_def_values->len) { plugins_free_default_options(srv); - g_slice_free1(srv->option_count * sizeof(*srv->option_def_values), srv->option_def_values); } + g_array_free(srv->option_def_values, TRUE); log_cleanup(srv); @@ -256,16 +257,6 @@ void server_start(server *srv) { srv->keep_alive_queue_timeout = 5; - srv->option_count = g_hash_table_size(srv->options); - srv->option_def_values = g_slice_alloc0(srv->option_count * sizeof(*srv->option_def_values)); - - /* set default option values */ - if (!plugins_load_default_options(srv)) { - ERROR(srv, "%s", "Error while loading option default values"); - server_stop(srv); - return; - } - plugins_prepare_callbacks(srv); for (i = 0; i < srv->sockets->len; i++) { diff --git a/src/server.h b/src/server.h index 231a7ef..97d90d6 100644 --- a/src/server.h +++ b/src/server.h @@ -50,8 +50,7 @@ struct server { GArray *plugins_handle_close; /** list of handle_close callbacks */ - size_t option_count; /**< set to size of value hash table */ - union option_value *option_def_values; + GArray *option_def_values;/** array of option_value */ struct action *mainaction; gboolean exiting; /** atomic access */