Mon, 24 Aug 2020 17:07:41 +0200
replace old server config loader
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/serverconfig.c Mon Aug 24 17:07:41 2020 +0200 @@ -0,0 +1,322 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2020 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "serverconfig.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include <ucx/buffer.h> +#include <ucx/utils.h> + +ServerConfig* serverconfig_load(const char *file) { + FILE *in = fopen(file, "r"); + if(in == NULL) { + return NULL; + } + + UcxBuffer *buf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND); + if(!buf) { + fclose(in); + return NULL; + } + + ucx_stream_copy(in, buf, (read_func)fread, (write_func)ucx_buffer_write); + fclose(in); + + ServerConfig *scfg = serverconfig_parse(scstrn(buf->space, buf->size)); + + ucx_buffer_free(buf); + return scfg; +} + + +static CFGToken get_next_token(scstr_t content, int *pos) { + CFGToken token = { {NULL, 0}, CFG_NO_TOKEN }; + CFGTokenType type = CFG_TOKEN; + + int start = *pos; + + int token_begin = -1; + int token_end = content.length-1; + + int quote = 0; + int comment = 0; + + int i; + char prev = 0; + for(i=start;i<content.length;i++) { + char c = content.ptr[i]; + if(c == '\n') { + if(quote) { + *pos = i; + return token; // error + } else if(start == i) { + // single newline char token + type = CFG_TOKEN_NEWLINE; + token_begin = i; + token_end = i+1; + break; + } + + token_end = i; + if(token_begin < 0) { + // only space/comment token + token_begin = start; + type = comment ? CFG_TOKEN_COMMENT : CFG_TOKEN_SPACE; + } + // make sure next run will return current newline char as token + i--; + break; + } else if(quote) { + if(c == '"' && prev != '\\') { + quote = 0; + } + } else if(comment) { + // ignore + if(c == '\n') { + comment = 0; + } + } else if(c == '#') { + comment = 1; + } else if(isspace(c)) { + if(token_begin >= 0) { + token_end = i; + break; + } + } else if(c == '"') { + quote = 1; + if(token_begin < 0) { + token_begin = i; + } + } else if(token_begin < 0) { + token_begin = i; + } + prev = c; + } + + *pos = i + 1; + + if(token_begin < 0) { + return token; // error + } + + token.type = type; + token.content = scstrsubsl(content, token_begin, token_end - token_begin); + return token; +} + + +static void test_print_config(ConfigNode *parent) { + UCX_FOREACH(elm, parent->children) { + ConfigNode *node = elm->data; + + if(node->type == CONFIG_NODE_SPACE) { + printf("sp: %s", node->text_begin.ptr); + } else if(node->type == CONFIG_NODE_COMMENT) { + printf("cm: %s", node->text_begin.ptr); + } else if(node->type == CONFIG_NODE_OBJECT) { + printf("o{: %s : %s", node->name.ptr, node->text_begin.ptr); + test_print_config(node); + printf("o}: %s", node->text_end.ptr); + } else if(node->type == CONFIG_NODE_DIRECTIVE) { + printf("di: %s", node->text_begin.ptr); + } else { + printf("fk: %s", node->text_begin.ptr); + } + } +} + +ServerConfig* serverconfig_parse(scstr_t content) { + UcxMempool *mp = ucx_mempool_new(512); + if(!mp) return NULL; + UcxAllocator *a = mp->allocator; + + ServerConfig *config = ucx_mempool_malloc(mp, sizeof(ServerConfig)); + if(!config) { + ucx_mempool_destroy(mp); + return NULL; + } + config->mp = mp; + + // PARSE: + // first non space/comment token is directive/object name + // following tokens are arguments + // newline starts new directive + // '{' converts directive to object and following directives will + // be placed into the object + int pos = 0; // needed for tokenizer + CFGToken token; + + ConfigNode *root_obj = ucx_mempool_calloc(mp, 1, sizeof(ConfigNode)); + root_obj->type = CONFIG_NODE_OBJECT; + + UcxList *node_stack = ucx_list_prepend(NULL, root_obj); + + ConfigNode *current = ucx_mempool_calloc(mp, 1, sizeof(ConfigNode)); + current->type = CONFIG_NODE_SPACE; + ConfigNode *obj = NULL; + int obj_closed = 0; + + int text_start = 0; + int err = 0; + while((token = get_next_token(content, &pos)).type != CFG_NO_TOKEN) { + //printf("%s [%.*s]\n", token_type_str(token.type), (int)token.content.length, token.content.ptr); + + switch(token.type) { + CFG_NO_TOKEN: break; + case CFG_TOKEN_COMMENT: { + if(current->type == CONFIG_NODE_SPACE) { + current->type = CONFIG_NODE_COMMENT; + } + break; + } + case CFG_TOKEN_SPACE: break; + case CFG_TOKEN_NEWLINE: { + scstr_t line = scstrsubsl(content, text_start, pos - text_start); + text_start = pos; + + sstr_t line_cp = sstrdup_a(a, line); + + ConfigNode *parent = node_stack->data; + if(current->type == CONFIG_NODE_CLOSE_OBJECT) { + parent->text_end = line_cp; + node_stack = ucx_list_remove_a(a, node_stack, node_stack); + } else if(current->type == CONFIG_NODE_OPEN_OBJECT) { + sstr_t new_textbegin = sstrcat_a(a, 2, obj->text_begin, line_cp); + alfree(a, obj->text_begin.ptr); + alfree(a, line_cp.ptr); + obj->text_begin = new_textbegin; + } else { + current->text_begin = line_cp; + ConfigNode *parent = node_stack->data; + parent->children = ucx_list_append_a(a, parent->children, current); + } + + if(obj && obj->type == CONFIG_NODE_OBJECT) { + node_stack = ucx_list_prepend_a(a, node_stack, obj); + obj = NULL; + } + + current = ucx_mempool_calloc(mp, 1, sizeof(ConfigNode)); + current->type = CONFIG_NODE_SPACE; + + obj_closed = 0; + break; + } + case CFG_TOKEN: { + if(!sstrcmp(token.content, S("{"))) { + if(!obj) { + err = 1; + break; + } + obj->type = CONFIG_NODE_OBJECT; + if(current != obj) { + current->type = CONFIG_NODE_OPEN_OBJECT; + } + } else if(!sstrcmp(token.content, S("}"))) { + obj_closed = 1; // force newline before next directive + obj = NULL; + current->type = CONFIG_NODE_CLOSE_OBJECT; + } else { + if(obj_closed) { + err = 1; + break; + } + + if(!current->name.ptr) { + current->name = sstrdup_a(a, token.content); + current->type = CONFIG_NODE_DIRECTIVE; + obj = current; + } else { + ConfigArg *arg = ucx_mempool_calloc(mp, 1, sizeof(ConfigArg)); + // TODO: add support for key/value + arg->value = sstrdup_a(a, token.content); + current->args = ucx_list_append_a(a, current->args, arg); + } + } + break; + } + } + + if(err) { + break; + } + } + + if(pos < content.length || err) { + // content not fully parsed because of an error + ucx_mempool_destroy(mp); + return NULL; + } + + //test_print_config(&root_obj); + config->root = root_obj; + config->tab = sstrdup_a(a, SC("\t")); + + return config; +} + +void serverconfig_free(ServerConfig *cfg) { + ucx_mempool_destroy(cfg->mp); +} + +ConfigNode* serverconfig_get_node(ConfigNode *parent, ConfigNodeType type, scstr_t name) { + UCX_FOREACH(elm, parent->children) { + ConfigNode *node = elm->data; + if(node->type == type && !sstrcmp(node->name, name)) { + return node; + } + } + return NULL; +} + +UcxList* serverconfig_get_node_list(ConfigNode *parent, ConfigNodeType type, scstr_t name) { + UcxList *nodes = NULL; + + UCX_FOREACH(elm, parent->children) { + ConfigNode *node = elm->data; + if(node->type == type && !sstrcmp(node->name, name)) { + nodes = ucx_list_append(nodes, node); + } + } + + return nodes; +} + +scstr_t serverconfig_directive_value(ConfigNode *obj, scstr_t name) { + ConfigNode *node = serverconfig_get_node(obj, CONFIG_NODE_DIRECTIVE, name); + if(node && ucx_list_size(node->args) == 1) { + ConfigArg *arg = node->args->data; + return SCSTR(arg->value); + } + return scstrn(NULL, 0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/serverconfig.h Mon Aug 24 17:07:41 2020 +0200 @@ -0,0 +1,110 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2020 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WS_CONFIG_SERVERCONFIG_H +#define WS_CONFIG_SERVERCONFIG_H + +#include <ucx/list.h> +#include <ucx/map.h> +#include <ucx/mempool.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct ServerConfig ServerConfig; +typedef struct ConfigNode ConfigNode; +typedef struct ConfigArg ConfigArg; +typedef struct CFGToken CFGToken; + +typedef enum ConfigNodeType ConfigNodeType; +typedef enum CFGTokenType CFGTokenType; + +struct ServerConfig { + UcxMempool *mp; + ConfigNode *root; + sstr_t tab; +}; + +enum ConfigNodeType { + CONFIG_NODE_SPACE = 0, + CONFIG_NODE_COMMENT, + CONFIG_NODE_OBJECT, + CONFIG_NODE_DIRECTIVE, + CONFIG_NODE_OPEN_OBJECT, + CONFIG_NODE_CLOSE_OBJECT +}; + +struct ConfigNode { + sstr_t text_begin; + sstr_t text_end; + ConfigNodeType type; + + sstr_t name; + UcxList *args; + UcxList *children; +}; + +struct ConfigArg { + sstr_t name; + sstr_t value; +}; + + +enum CFGTokenType { + CFG_NO_TOKEN = 0, + CFG_TOKEN_COMMENT, + CFG_TOKEN_SPACE, + CFG_TOKEN_NEWLINE, + CFG_TOKEN +}; + +struct CFGToken { + scstr_t content; + CFGTokenType type; +}; + +ServerConfig* serverconfig_load(const char *file); + +ServerConfig* serverconfig_parse(scstr_t content); + +void serverconfig_free(ServerConfig *cfg); + +ConfigNode* serverconfig_get_node(ConfigNode *parent, ConfigNodeType type, scstr_t name); + +UcxList* serverconfig_get_node_list(ConfigNode *parent, ConfigNodeType type, scstr_t name); + +scstr_t serverconfig_directive_value(ConfigNode *obj, scstr_t name); + +#ifdef __cplusplus +} +#endif + +#endif /* WS_CONFIG_SERVERCONFIG_H */ +
--- a/src/server/daemon/config.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/config.c Mon Aug 24 17:07:41 2020 +0200 @@ -128,10 +128,12 @@ ServerConfiguration* load_server_conf(char *file) { log_ereport(LOG_VERBOSE, "load_server_conf"); - ServerConfig2 *serverconf2 = load_server_config(file); - if(serverconf2 == NULL) { + ServerConfig *serverconf = serverconfig_load(file); + if(!serverconf) { log_ereport(LOG_FAILURE, "Cannot load server.conf"); + return NULL; } + pool_handle_t *pool = pool_create(); @@ -167,49 +169,54 @@ */ // init logfile first - UcxList *lfl = ucx_map_sstr_get(serverconf2->objects, sstrn("LogFile", 7)); - if(lfl != NULL) { - ServerConfigObject *logobj = lfl->data; - if(logobj == NULL) { + UcxList *list = NULL; + + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("LogFile")); + if(list) { + ConfigNode *logobj = list->data; + if(!logobj) { // error - return NULL; + return NULL; // TODO: fix memory leak } int ret = cfg_handle_logfile(serverconfig, logobj); if(ret != 0) { // cannot initialize log file - return NULL; + return NULL; // TODO: fix memory leak } } else { // horrible error return NULL; } + ucx_list_free(list); - UcxList *list = ucx_map_sstr_get(serverconf2->objects, sstrn("Runtime", 7)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Runtime")); UCX_FOREACH(elm, list) { - ServerConfigObject *scfgobj = elm->data; - if(cfg_handle_runtime(serverconfig, scfgobj)) { + ConfigNode *runtimeobj = elm->data; + if(cfg_handle_runtime(serverconfig, runtimeobj)) { // error return NULL; } } + ucx_list_free(list); - list = ucx_map_sstr_get(serverconf2->objects, sstrn("Threadpool", 10)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Threadpool")); UCX_FOREACH(elm, list) { if(cfg_handle_threadpool(serverconfig, elm->data)) { return NULL; } } + ucx_list_free(list); // check thread pool config if(check_thread_pool_cfg() != 0) { /* critical error */ return NULL; } - list = ucx_map_sstr_get(serverconf2->objects, sstrn("EventHandler", 12)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("EventHandler")); UCX_FOREACH(elm, list) { if(cfg_handle_eventhandler( - serverconfig, (ServerConfigObject*)elm->data)) { + serverconfig, elm->data)) { // error return NULL; } @@ -219,38 +226,43 @@ /* critical error */ return NULL; } + ucx_list_free(list); - list = ucx_map_sstr_get(serverconf2->objects, sstrn("AccessLog", 9)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("AccessLog")); UCX_FOREACH(elm, list) { - ServerConfigObject *scfgobj = elm->data; + ConfigNode *scfgobj = elm->data; if(cfg_handle_accesslog(serverconfig, scfgobj)) { return NULL; } } + ucx_list_free(list); - list = ucx_map_sstr_get(serverconf2->objects, sstrn("AuthDB", 6)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("AuthDB")); UCX_FOREACH(elm, list) { - ServerConfigObject *scfgobj = elm->data; + ConfigNode *scfgobj = elm->data; if(cfg_handle_authdb(serverconfig, scfgobj)) { return NULL; } } + ucx_list_free(list); - list = ucx_map_sstr_get(serverconf2->objects, sstrn("Listener", 8)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("Listener")); UCX_FOREACH(elm, list) { - ServerConfigObject *scfgobj = elm->data; + ConfigNode *scfgobj = elm->data; if(cfg_handle_listener(serverconfig, scfgobj)) { return NULL; } } + ucx_list_free(list); - list = ucx_map_sstr_get(serverconf2->objects, sstrn("VirtualServer", 13)); + list = serverconfig_get_node_list(serverconf->root, CONFIG_NODE_OBJECT, SC("VirtualServer")); UCX_FOREACH(elm, list) { - ServerConfigObject *scfgobj = elm->data; + ConfigNode *scfgobj = elm->data; if(cfg_handle_vs(serverconfig, scfgobj)) { return NULL; } } + ucx_list_free(list); // set VirtualServer for all listeners @@ -274,7 +286,8 @@ ls = ls->next; } - free_server_config(serverconf2); + serverconfig_free(serverconf); + return serverconfig; } @@ -294,22 +307,23 @@ } -int cfg_handle_runtime(ServerConfiguration *cfg, ServerConfigObject *obj) { - sstr_t user = cfg_directivelist_get_str(obj->directives, sstr("User")); +int cfg_handle_runtime(ServerConfiguration *cfg, ConfigNode *obj) { + scstr_t user = serverconfig_directive_value(obj, SC("User")); if(user.ptr) { - cfg->user = sstrdup_pool(cfg->pool, user); + cfg->user = sstrdup_a(cfg->a, user); } - sstr_t tmp = cfg_directivelist_get_str(obj->directives, sstr("Temp")); + scstr_t tmp = serverconfig_directive_value(obj, SC("Temp")); if(tmp.ptr) { - cfg->tmp = sstrdup_pool(cfg->pool, tmp); + cfg->tmp = sstrdup_a(cfg->a, tmp); } else { + // TODO: do this check after all config loading is done log_ereport(LOG_MISCONFIG, "no temporary directory specified"); return -1; } // mime file - sstr_t mf = cfg_directivelist_get_str(obj->directives, sstr("MimeFile")); - sstr_t base = sstr("config/"); + scstr_t mf = serverconfig_directive_value(obj, SC("MimeFile")); + scstr_t base = SC("config/"); sstr_t file = sstrcat(2, base, mf); if(mime_conf_load(cfg, file)) { @@ -320,9 +334,9 @@ return 0; } -int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj) { - sstr_t file = cfg_directivelist_get_str(obj->directives, sstr("File")); - sstr_t lvl = cfg_directivelist_get_str(obj->directives, sstr("Level")); +int cfg_handle_logfile(ServerConfiguration *cfg, ConfigNode *obj) { + scstr_t file = serverconfig_directive_value(obj, SC("File")); + scstr_t lvl = serverconfig_directive_value(obj, SC("Level")); if(file.ptr == NULL || lvl.ptr == NULL) { /* missing log file parameters */ @@ -330,21 +344,18 @@ } LogConfig logcfg; - logcfg.file = sstrdup(file).ptr; - logcfg.level = sstrdup(lvl).ptr; + logcfg.file = file.ptr; + logcfg.level = lvl.ptr; logcfg.log_stdout = 0; logcfg.log_stderr = 0; /* TODO: stdout, stderr config */ int ret = init_log_file(&logcfg); - - free(logcfg.file); - free(logcfg.level); return ret; } -int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj) { +int cfg_handle_threadpool(ServerConfiguration *cfg, ConfigNode *obj) { ThreadPoolConfig poolcfg; poolcfg.min_threads = 4; poolcfg.min_threads = 4; @@ -352,21 +363,11 @@ poolcfg.queue_size = 64; poolcfg.stack_size = 262144; - sstr_t name = cfg_directivelist_get_str( - obj->directives, - sstr("Name")); - sstr_t min = cfg_directivelist_get_str( - obj->directives, - sstr("MinThreads")); - sstr_t max = cfg_directivelist_get_str( - obj->directives, - sstr("MaxThreads")); - sstr_t stack = cfg_directivelist_get_str( - obj->directives, - sstr("StackSize")); - sstr_t queue = cfg_directivelist_get_str( - obj->directives, - sstr("QueueSize")); + scstr_t name = serverconfig_directive_value(obj, SC("Name")); + scstr_t min = serverconfig_directive_value(obj, SC("MinThreads")); + scstr_t max = serverconfig_directive_value(obj, SC("MaxThreads")); + scstr_t stack = serverconfig_directive_value(obj, SC("StackSize")); + scstr_t queue = serverconfig_directive_value(obj, SC("QueueSize")); // TODO: Type if(name.length == 0) { @@ -375,27 +376,19 @@ } if(min.length != 0) { - min = sstrdup(min); poolcfg.min_threads = atoi(min.ptr); - free(min.ptr); } if(max.length != 0) { - max = sstrdup(max); poolcfg.max_threads = atoi(max.ptr); - free(max.ptr); } if(stack.length != 0) { - stack = sstrdup(stack); poolcfg.stack_size = atoi(stack.ptr); - free(stack.ptr); } if(queue.length != 0) { - queue = sstrdup(queue); poolcfg.queue_size = atoi(queue.ptr); - free(queue.ptr); } create_threadpool(name, &poolcfg); @@ -403,32 +396,26 @@ return 0; } -int cfg_handle_eventhandler(ServerConfiguration *c, ServerConfigObject *obj) { +int cfg_handle_eventhandler(ServerConfiguration *c, ConfigNode *obj) { EventHandlerConfig evcfg; - sstr_t name = cfg_directivelist_get_str(obj->directives, sstr("Name")); - sstr_t threads = cfg_directivelist_get_str( - obj->directives, - sstr("Threads")); - sstr_t isdefault = cfg_directivelist_get_str( - obj->directives, - sstr("Default")); + scstr_t name = serverconfig_directive_value(obj, SC("Name")); + scstr_t threads = serverconfig_directive_value(obj, SC("Threads")); + scstr_t isdefault = serverconfig_directive_value(obj, SC("Default")); evcfg.name = name; - sstr_t s = sstrdup(threads); - evcfg.nthreads = atoi(s.ptr); - free(s.ptr); + evcfg.nthreads = atoi(threads.ptr); evcfg.isdefault = util_getboolean(isdefault.ptr, 0); return create_event_handler(&evcfg); } -int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj) { +int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj) { // TODO: use a name to identify the log file - sstr_t file = cfg_directivelist_get_str(obj->directives, sstr("File")); + scstr_t file = serverconfig_directive_value(obj, SC("File")); if(file.ptr == NULL) { return 0; } @@ -443,10 +430,10 @@ return 0; } AccessLog *log = pool_malloc(cfg->pool, sizeof(AccessLog)); - log->file = sstrdup_pool(cfg->pool, file); + log->file = sstrdup_a(cfg->a, file); log->format = format; log->log = log_file; - cfg->logfiles = ucx_list_append(cfg->logfiles, log); + cfg->logfiles = ucx_list_append_a(cfg->a, cfg->logfiles, log); if(!cfg->default_log) { cfg->default_log = log; @@ -455,62 +442,31 @@ return 0; } -int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj) { - sstr_t name = cfg_directivelist_get_str(obj->directives, sstr("Name")); - sstr_t type = cfg_directivelist_get_str(obj->directives, sstr("Type")); +int cfg_handle_authdb(ServerConfiguration *cfg, ConfigNode *obj) { + scstr_t name = serverconfig_directive_value(obj, SC("Name")); + scstr_t type = serverconfig_directive_value(obj, SC("Type")); AuthDB *authdb = NULL; if(!sstrcmp(type, sstr("ldap"))) { LDAPConfig conf; - sstr_t host = cfg_directivelist_get_str( - obj->directives, - sstr("Host")); - sstr_t port = cfg_directivelist_get_str( - obj->directives, - sstr("Port")); - sstr_t basedn = cfg_directivelist_get_str( - obj->directives, - sstr("BaseDN")); - sstr_t binddn = cfg_directivelist_get_str( - obj->directives, - sstr("BindDN")); - sstr_t basepw = cfg_directivelist_get_str( - obj->directives, - sstr("BindPW")); + scstr_t host = serverconfig_directive_value(obj, SC("Host")); + scstr_t port = serverconfig_directive_value( obj, SC("Port")); + scstr_t basedn = serverconfig_directive_value(obj, SC("BaseDN")); + scstr_t binddn = serverconfig_directive_value(obj, SC("BindDN")); + scstr_t basepw = serverconfig_directive_value(obj, SC("BindPW")); - host = sstrdup(host); - port = sstrdup(port); - basedn = sstrdup(basedn); - binddn = sstrdup(binddn); - basepw = sstrdup(basepw); - - conf.hostname = host.ptr; + conf.hostname = sstrdup_a(cfg->a, host).ptr; conf.port = atoi(port.ptr); - conf.basedn = basedn.ptr; - conf.binddn = binddn.ptr; - conf.bindpw = basepw.ptr; + conf.basedn = sstrdup_a(cfg->a, basedn).ptr; + conf.binddn = sstrdup_a(cfg->a, binddn).ptr; + conf.bindpw = sstrdup_a(cfg->a, basepw).ptr; - name = sstrdup(name); - - authdb = create_ldap_authdb(name.ptr, &conf); - - // TODO: create_ldap_authdb should copy the strings - /* - free(host.ptr); - free(port.ptr); - free(basedn.ptr); - free(binddn.ptr); - free(basepw.ptr); - free(name.ptr); - */ - + authdb = create_ldap_authdb(cfg, name.ptr, &conf); } else if(!sstrcmp(type, sstr("keyfile"))) { // we only need the file parameter - sstr_t file = cfg_directivelist_get_str( - obj->directives, - sstr("File")); + scstr_t file = serverconfig_directive_value(obj, SC("File")); if(file.length == 0) { log_ereport( LOG_MISCONFIG, @@ -531,42 +487,33 @@ return 0; } -int cfg_handle_listener(ServerConfiguration *cfg, ServerConfigObject *obj) { +int cfg_handle_listener(ServerConfiguration *cfg, ConfigNode *obj) { ListenerConfig lc; ZERO(&lc, sizeof(ListenerConfig)); lc.cfg = cfg; lc.port = 8080; lc.nacceptors = 1; - // TODO: use sstrdup_pool? - lc.name = sstrdup(cfg_directivelist_get_str( - obj->directives, - sstr("Name"))); - lc.port = atoi(cfg_directivelist_get_str( - obj->directives, - sstr("Port")).ptr); - lc.vs = sstrdup(cfg_directivelist_get_str( - obj->directives, - sstr("DefaultVS"))); - lc.threadpool = sstrdup(cfg_directivelist_get_str( - obj->directives, - sstr("Threadpool"))); + scstr_t name = serverconfig_directive_value(obj, SC("Name")); + scstr_t port = serverconfig_directive_value(obj, SC("Port")); + scstr_t vs = serverconfig_directive_value(obj, SC("DefaultVS")); + scstr_t thrp = serverconfig_directive_value(obj, SC("Threadpool")); + scstr_t blck = serverconfig_directive_value(obj, SC("BlockingIO")); - sstr_t blockingio = cfg_directivelist_get_str( - obj->directives, - sstr("BlockingIO")); - if(blockingio.ptr) { - lc.blockingio = util_getboolean_s(blockingio, WS_FALSE); - } + // TODO: use sstrdup_pool? + lc.name = sstrdup(name); + lc.port = atoi(port.ptr); + lc.vs = sstrdup(vs); + lc.threadpool = sstrdup(thrp); - sstr_t ssl = cfg_directivelist_get_str(obj->directives, S("SSL")); + lc.blockingio = util_getboolean_s(blck, WS_FALSE); + + scstr_t ssl = serverconfig_directive_value(obj, SC("SSL")); if(util_getboolean_s(ssl, WS_FALSE)) { - sstr_t cert = cfg_directivelist_get_str(obj->directives, S("Cert")); - sstr_t privkey = cfg_directivelist_get_str(obj->directives, S("Key")); - sstr_t chain = cfg_directivelist_get_str(obj->directives, S("CertChain")); - sstr_t disableprot = cfg_directivelist_get_str( - obj->directives, - S("SSLDisableProtocol")); + scstr_t cert = serverconfig_directive_value(obj, SC("Cert")); + scstr_t privkey = serverconfig_directive_value(obj, SC("Key")); + scstr_t chain = serverconfig_directive_value(obj, SC("CertChain")); + scstr_t disableprot = serverconfig_directive_value(obj, SC("SSLDisableProtocol")); WSBool config_ok = WS_TRUE; // TODO: log error @@ -603,30 +550,21 @@ return 1; } - listener->default_vs.vs_name = lc.vs.ptr; - cfg->listeners = ucx_list_append(cfg->listeners, listener); + listener->default_vs.vs_name = sstrdup_a(cfg->a, lc.vs).ptr; + cfg->listeners = ucx_list_append_a(cfg->a, cfg->listeners, listener); return 0; } -int cfg_handle_vs(ServerConfiguration *cfg, ServerConfigObject *obj) { +int cfg_handle_vs(ServerConfiguration *cfg, ConfigNode *obj) { VirtualServer *vs = vs_new(); - vs->name = sstrdup(cfg_directivelist_get_str( - obj->directives, - sstr("Name"))); - vs->host = sstrdup(cfg_directivelist_get_str( - obj->directives, - sstr("Host"))); - vs->document_root = sstrdup(cfg_directivelist_get_str( - obj->directives, - sstr("DocRoot"))); - sstr_t objfile = cfg_directivelist_get_str( - obj->directives, - sstr("ObjectFile")); - sstr_t aclfile = cfg_directivelist_get_str( - obj->directives, - sstr("ACLFile")); + vs->name = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("Name"))); + vs->host = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("Host"))); + vs->document_root = sstrdup_a(cfg->a, serverconfig_directive_value(obj, SC("DocRoot"))); + + scstr_t objfile = serverconfig_directive_value(obj, SC("ObjectFile")); + scstr_t aclfile = serverconfig_directive_value(obj, SC("ACLFile")); // load the object config file sstr_t base = sstr("config/"); @@ -916,7 +854,7 @@ return &acllist->acl; } -AuthDB* keyfile_load(ServerConfiguration *cfg, sstr_t file) { +AuthDB* keyfile_load(ServerConfiguration *cfg, scstr_t file) { Keyfile *keyfile = keyfile_new(cfg->a); if(!keyfile) { return NULL;
--- a/src/server/daemon/config.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/config.h Mon Aug 24 17:07:41 2020 +0200 @@ -39,6 +39,7 @@ #include "../config/mimeconf.h" #include "../config/acl.h" #include "../config/keyfile.h" +#include "../config/serverconfig.h" #include "acldata.h" #include "keyfile_auth.h" @@ -79,21 +80,21 @@ void init_server_config_parser(); -int cfg_handle_runtime(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_runtime(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_logfile(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_logfile(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_threadpool(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_threadpool(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_eventhandler(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_eventhandler(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_accesslog(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_authdb(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_listener(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_listener(ServerConfiguration *cfg, ConfigNode *obj); -int cfg_handle_vs(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_vs(ServerConfiguration *cfg, ConfigNode *obj); ServerConfiguration* load_server_conf(char *file); void cfg_ref(ServerConfiguration *cfg); @@ -104,7 +105,7 @@ ACLData* acl_conf_load(ServerConfiguration *cfg, sstr_t file); ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl); -AuthDB* keyfile_load(ServerConfiguration *cfg, sstr_t file); +AuthDB* keyfile_load(ServerConfiguration *cfg, scstr_t file);
--- a/src/server/daemon/event.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/event.c Mon Aug 24 17:07:41 2020 +0200 @@ -88,7 +88,7 @@ } EventHandlerConfig cfg; - cfg.name = sstr("default"); + cfg.name = SC("default"); cfg.nthreads = 1; cfg.isdefault = 1;
--- a/src/server/daemon/event.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/event.h Mon Aug 24 17:07:41 2020 +0200 @@ -43,7 +43,7 @@ } EVHandler; typedef struct event_handler_conf { - sstr_t name; + scstr_t name; int nthreads; int isdefault; } EventHandlerConfig;
--- a/src/server/daemon/httplistener.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/httplistener.c Mon Aug 24 17:07:41 2020 +0200 @@ -237,23 +237,18 @@ } // TODO: cleanup on error - sstr_t file; int ret; char errbuf[512]; if(!conf->chainfile.ptr) { - file = sstrdup(conf->certfile); - ret = SSL_CTX_use_certificate_file(ctx, file.ptr, SSL_FILETYPE_PEM); - free(file.ptr); + ret = SSL_CTX_use_certificate_file(ctx, conf->certfile.ptr, SSL_FILETYPE_PEM); if(!ret) { ERR_error_string(ERR_get_error(), errbuf); log_ereport(LOG_MISCONFIG, "Cannot load ssl chain file: %s", errbuf); return NULL; } } else { - file = sstrdup(conf->chainfile); - ret = SSL_CTX_use_certificate_chain_file(ctx, file.ptr); - free(file.ptr); + ret = SSL_CTX_use_certificate_chain_file(ctx, conf->chainfile.ptr); if(!ret) { ERR_error_string(ERR_get_error(), errbuf); log_ereport(LOG_MISCONFIG, "Cannot load ssl cert file: %s", errbuf); @@ -261,9 +256,7 @@ } } - file = sstrdup(conf->privkeyfile); - ret = SSL_CTX_use_PrivateKey_file(ctx, file.ptr, SSL_FILETYPE_PEM); - free(file.ptr); + ret = SSL_CTX_use_PrivateKey_file(ctx, conf->privkeyfile.ptr, SSL_FILETYPE_PEM); if(!ret) { ERR_error_string(ERR_get_error(), errbuf); log_ereport(LOG_MISCONFIG, "Cannot load ssl key file: %s", errbuf);
--- a/src/server/daemon/httplistener.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/httplistener.h Mon Aug 24 17:07:41 2020 +0200 @@ -64,10 +64,10 @@ int nacceptors; WSBool blockingio; WSBool ssl; - sstr_t certfile; - sstr_t privkeyfile; - sstr_t chainfile; - sstr_t disable_proto; + scstr_t certfile; + scstr_t privkeyfile; + scstr_t chainfile; + scstr_t disable_proto; }; struct _acceptor {
--- a/src/server/daemon/ldap_auth.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/ldap_auth.c Mon Aug 24 17:07:41 2020 +0200 @@ -47,9 +47,9 @@ #endif } -AuthDB* create_ldap_authdb(char *name, LDAPConfig *conf) { - LDAPAuthDB *authdb = malloc(sizeof(LDAPAuthDB)); - authdb->authdb.name = strdup(name); +AuthDB* create_ldap_authdb(ServerConfiguration *cfg, const char *name, LDAPConfig *conf) { + LDAPAuthDB *authdb = almalloc(cfg->a, sizeof(LDAPAuthDB)); + authdb->authdb.name = pool_strdup(cfg->pool, name); authdb->authdb.get_user = ldap_get_user; authdb->authdb.use_cache = 1; authdb->config = *conf; @@ -64,7 +64,7 @@ // initialize group cache authdb->groups.first = NULL; authdb->groups.last = NULL; - authdb->groups.map = ucx_map_new(32); + authdb->groups.map = ucx_map_new_a(cfg->a, 32); return (AuthDB*) authdb; }
--- a/src/server/daemon/ldap_auth.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/ldap_auth.h Mon Aug 24 17:07:41 2020 +0200 @@ -34,6 +34,8 @@ #include <ldap.h> #include <ucx/map.h> +#include "config.h" + #ifdef __cplusplus extern "C" { #endif @@ -90,7 +92,7 @@ LDAPGroup *next; }; -AuthDB* create_ldap_authdb(char *name, LDAPConfig *conf); +AuthDB* create_ldap_authdb(ServerConfiguration *cfg, const char *name, LDAPConfig *conf); LDAP* get_ldap_session(LDAPAuthDB *authdb);
--- a/src/server/daemon/log.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/log.c Mon Aug 24 17:07:41 2020 +0200 @@ -335,7 +335,9 @@ * This source file only manages access log files. IO is performed directly * by AddLog safs. */ -LogFile* get_access_log_file(sstr_t file) { +LogFile* get_access_log_file(scstr_t file) { + // TODO: this looks dubious + if(!access_log_files) { access_log_files = ucx_map_new(4); }
--- a/src/server/daemon/log.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/log.h Mon Aug 24 17:07:41 2020 +0200 @@ -40,10 +40,10 @@ #endif typedef struct { - char *file; - char *level; - int log_stdout; - int log_stderr; + const char *file; + const char *level; + int log_stdout; + int log_stderr; } LogConfig; typedef struct { @@ -75,7 +75,7 @@ void log_remove_logdup(LogDup *dup); // access logging -LogFile* get_access_log_file(sstr_t file); +LogFile* get_access_log_file(scstr_t file); #ifdef __cplusplus }
--- a/src/server/daemon/main.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/main.c Mon Aug 24 17:07:41 2020 +0200 @@ -167,7 +167,7 @@ int status; status = webserver_init(); if(status != 0) { - log_ereport(LOG_FAILURE, "cannot initialize server."); + log_ereport(LOG_FAILURE, "Cannot initialize server."); return EXIT_FAILURE; }
--- a/src/server/daemon/threadpools.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/threadpools.c Mon Aug 24 17:07:41 2020 +0200 @@ -45,7 +45,7 @@ static threadpool_t *default_io_pool; static threadpool_t *last_io_pool; -int create_threadpool(sstr_t name, ThreadPoolConfig *cfg) { +int create_threadpool(scstr_t name, ThreadPoolConfig *cfg) { if(thread_pool_map == NULL) { thread_pool_map = ucx_map_new(16); } @@ -77,7 +77,7 @@ } } -int create_io_pool(sstr_t name, int numthreads) { +int create_io_pool(scstr_t name, int numthreads) { if(io_pool_map == NULL) { io_pool_map = ucx_map_new(4); } @@ -110,13 +110,13 @@ cfg.max_threads = 8; cfg.queue_size = 64; cfg.stack_size = 262144; - if(create_threadpool(sstr("default"), &cfg)) { + if(create_threadpool(SC("default"), &cfg)) { return 1; } } if(num_iopools == 0) { - if(create_io_pool(sstr("default"), 8)) { + if(create_io_pool(SC("default"), 8)) { return 1; } }
--- a/src/server/daemon/threadpools.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/threadpools.h Mon Aug 24 17:07:41 2020 +0200 @@ -45,7 +45,7 @@ int queue_size; } ThreadPoolConfig; -int create_threadpool(sstr_t name, ThreadPoolConfig *cfg); +int create_threadpool(scstr_t name, ThreadPoolConfig *cfg); int check_thread_pool_cfg();
--- a/src/server/daemon/webserver.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/daemon/webserver.c Mon Aug 24 17:07:41 2020 +0200 @@ -87,7 +87,6 @@ init_configuration_manager(); ServerConfiguration *cfg; if(cfgmgr_load_config(&cfg) != 0) { - fprintf(stderr, "Cannot load configuration\n"); return -1; }
--- a/src/server/util/util.c Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/util/util.c Mon Aug 24 17:07:41 2020 +0200 @@ -394,7 +394,7 @@ return def; } -int util_getboolean_s(sstr_t s, int def) { +int util_getboolean_s(scstr_t s, int def) { if(s.length == 0) { return def; }
--- a/src/server/util/util.h Mon Aug 24 12:50:16 2020 +0200 +++ b/src/server/util/util.h Mon Aug 24 17:07:41 2020 +0200 @@ -197,7 +197,7 @@ NSAPI_PUBLIC PRBool INTutil_format_http_version(const char *v, int *protv_num, char *buffer, int size); NSAPI_PUBLIC int INTutil_getboolean(const char *v, int def); -int util_getboolean_s(sstr_t s, int def); +int util_getboolean_s(scstr_t s, int def); // new NSAPI_PUBLIC int util_strtoint(char *str, int64_t *value);