Sat, 21 Jan 2012 16:37:35 +0100
Added configuration manager
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2011 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 "../public/nsapi.h" #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/mman.h> #include "../ucx/string.h" #include "httplistener.h" #include "config.h" #include "func.h" #include "vserver.h" #include "../util/pblock.h" pool_handle_t *cfg_pool; // TODO: Funktion für ConfigDirective -> directive // TODO: Funktion für UcxList parameter list -> pblock // TODO: ConfigurationManager // TODO: server.conf UcxMap *server_conf_handlers; // type: ServerConfigHandler* void load_init_conf(char *file) { printf("load_init_conf\n"); InitConfig *cfg = load_init_config(file); if(cfg == NULL) { return; } cfg_pool = pool_create(); // one pool for one Configuration UcxDlist *dirs = cfg->directives; while(dirs != NULL) { ConfigDirective *dir = dirs->data; /* create NSAPI directive */ directive *d = malloc(sizeof(directive)); d->param = pblock_create_pool(cfg_pool, 8); UcxList *param = dir->param; while(param != NULL) { ConfigParam *p = param->data; pblock_nvlinsert( p->name.ptr, p->name.length, p->value.ptr, p->value.length, d->param); param = param->next; } /* get function */ char *func_name = pblock_findval("fn", d->param); d->func = get_function(func_name); if(d->func == NULL) { free(d); continue; } /* execute init directive */ d->func->func(d->param, NULL, NULL); dirs = dirs->next; } free_init_config(cfg); } ServerConfiguration* load_server_conf(char *file) { printf("load_server_conf\n"); ServerConfig *serverconf = load_server_config(file); if(serverconf == NULL) { fprintf(stderr, "Cannot load server.conf\n"); } ServerConfiguration *serverconfig = malloc(sizeof(ServerConfiguration)); serverconfig->pool = pool_create(); serverconfig->listeners = NULL; serverconfig->host_vs = ucx_map_new(16); // TODO: init serverconfig stuff /* convert ServerConfig to ServerConfiguration */ for(int i=0;i<serverconf->objects->size;i++) { UcxMapElement *elm = &serverconf->objects->map[i]; while(elm != NULL) { UcxList *list = elm->data; while(list != NULL) { ServerConfigObject *scfgobj = list->data; /* get handler */ ServerConfigHandler *handler = ucx_map_sstr_get( server_conf_handlers, scfgobj->type); if(handler != NULL) { void *object_data = NULL; if(handler->element_start != NULL) { object_data = handler->element_start( handler, serverconfig); } /* process the directives */ UcxDlist *dirs = scfgobj->directives; while(dirs != NULL) { handler->process_directive( handler, serverconfig, dirs->data, object_data); dirs = dirs->next; } if(handler->element_end != NULL) { handler->element_end( handler, serverconfig, NULL, object_data); } } list = list->next; } elm = elm->next; } } /* set VirtualServer for all listeners */ UcxList *ls = serverconfig->listeners; while(ls) { HttpListener *listener = ls->data; sstr_t vsname = sstr(listener->default_vs.vs_name); /* search for VirtualServer */ int b = 0; for(int i=0;i<serverconfig->host_vs->size;i++) { UcxMapElement *elm = &serverconfig->host_vs->map[i]; while(elm != NULL && elm->data != NULL) { VirtualServer *vs = elm->data; if(!sstrcmp(vsname, vs->name)) { b = 1; listener->default_vs.vs = vs; break; } elm = elm->next; } if(b) { break; } } ls = ls->next; } return serverconfig; } void init_server_config_parser() { /* create handler map */ server_conf_handlers = ucx_map_new(8); /* create and add default handlers */ ServerConfigHandler *runtime = calloc(1, sizeof(ServerConfigHandler)); runtime->init = NULL; runtime->process_directive = handle_runtime_directive; ucx_map_cstr_put(server_conf_handlers, "Runtime", runtime); ServerConfigHandler *listener = calloc(1, sizeof(ServerConfigHandler)); listener->init = NULL; listener->element_start = handle_listener_start; listener->element_end = handle_listener_end; listener->process_directive = handle_listener_directive; ucx_map_cstr_put(server_conf_handlers, "Listener", listener); ServerConfigHandler *vserver = calloc(1, sizeof(ServerConfigHandler)); vserver->init = NULL; vserver->element_start = handle_vserver_start; vserver->element_end = handle_vserver_end; vserver->process_directive = handle_vserver_directive; ucx_map_cstr_put(server_conf_handlers, "VirtualServer", vserver); } /* * server.conf handlers */ int handle_runtime_directive( ServerConfigHandler *h, ServerConfiguration *conf, ConfigDirective *dir, void *data) { return 0; } void* handle_listener_start(ServerConfigHandler *h, ServerConfiguration *cfg) { /* free this in handle_listener_end */ ListenerConfig *listener = calloc(1, sizeof(ListenerConfig)); listener->nacceptors = 1; listener->port = 0; //printf("<Listener>\n"); return listener; } int handle_listener_directive( ServerConfigHandler *h, ServerConfiguration *conf, ConfigDirective *dir, void *data) { ListenerConfig *listener = data; ConfigParam *param = dir->param->data; if(!sstrcmp(dir->directive_type, sstr("Name"))) { listener->name = sstrdub(param->name); //printf("Name %s\n", listener->name.ptr); } else if(!sstrcmp(dir->directive_type, sstr("Port"))) { listener->port = atoi(param->name.ptr); //printf("Port %d\n", listener->port); } else if(!sstrcmp(dir->directive_type, sstr("DefaultVS"))) { listener->vs = sstrdub(param->name); //printf("DefaultVS %s\n", param->name.ptr); } return 0; } int handle_listener_end( ServerConfigHandler *h, ServerConfiguration *conf, ConfigDirective *dir, void *data) { //printf("</Listener>\n\n"); /* add listener to server configuration */ ListenerConfig *lc = data; HttpListener *listener = http_listener_new(lc); listener->default_vs.vs_name = lc->vs.ptr; //free(lc); conf->listeners = ucx_list_append(conf->listeners, listener); return 0; } void* handle_vserver_start(ServerConfigHandler *h, ServerConfiguration *cfg) { //printf("<VirtualServer>\n"); VirtualServer *vs = vs_new(); return vs; } int handle_vserver_directive( ServerConfigHandler *h, ServerConfiguration *conf, ConfigDirective *dir, void *data) { VirtualServer *vs = data; ConfigParam *param = dir->param->data; if(!sstrcmp(dir->directive_type, sstr("Name"))) { vs->name = sstrdub(param->name); //printf("Name %s\n", vs->name.ptr); } else if(!sstrcmp(dir->directive_type, sstr("Host"))) { vs->host = sstrdub(param->name); //printf("Host %s\n", vs->host.ptr); } else if(!sstrcmp(dir->directive_type, sstr("ObjectFile"))) { sstr_t base = sstr("conf/"); sstr_t file; file.length = base.length + param->name.length + 1; file.ptr = alloca(file.length); file.ptr[file.length] = 0; file = sstrncat(2, file, base, param->name); //printf("ObjectFile %s\n", file.ptr); vs->objects = load_obj_conf(file.ptr); } else if(!sstrcmp(dir->directive_type, sstr("DocRoot"))) { vs->document_root = sstrdub(param->name); } // TODO: Listener, ACLFile, DAVFile, DocRoot, ... return 0; } int handle_vserver_end( ServerConfigHandler *h, ServerConfiguration *conf, ConfigDirective *dir, void *data) { //printf("</VirtualServer>\n\n"); VirtualServer *vs = data; ucx_map_sstr_put(conf->host_vs, vs->host, vs); return 0; } HTTPObjectConfig* load_obj_conf(char *file) { printf("load_obj_conf\n"); // new conf function test ObjectConfig *cfg = load_object_config(file); if(cfg == NULL) { return NULL; } /* create object config */ HTTPObjectConfig *conf = calloc(sizeof(HTTPObjectConfig), 1); conf->pool = pool_create(); /* convert ObjectConfig to HTTPObjectConfig */ /* add objects */ conf->nobj = ucx_dlist_size(cfg->objects); conf->objects = calloc(1, sizeof(httpd_object*)); UcxDlist *objlist = cfg->objects; int i = 0; while(objlist != NULL) { ConfigObject *cob = objlist->data; /* get name and ppath */ char *name = NULL; char *ppath = NULL; if(cob->name.length > 0) { name = sstrdub(cob->name).ptr; } if(cob->ppath.length > 0) { ppath = sstrdub(cob->ppath).ptr; } /* create and add object */ httpd_object *obj = object_new(name); obj->path = NULL; conf->objects[i] = obj; /* add directives */ for(int i=0;i<6;i++) { UcxDlist *dirs = cob->directives[i]; while(dirs != NULL) { ConfigDirective *cfgdir = dirs->data; directive *d = malloc(sizeof(directive)); d->cond = NULL; d->param = pblock_create_pool(conf->pool, 8); /* add params */ UcxList *param = cfgdir->param; while(param != NULL) { ConfigParam *p = param->data; pblock_nvlinsert( p->name.ptr, p->name.length, p->value.ptr, p->value.length, d->param); param = param->next; } /* get function */ char *func_name = pblock_findval("fn", d->param); d->func = get_function(func_name); dirs = dirs->next; /* add function to dtable */ object_add_directive(obj, d, cfgdir->type_num); } } /* next */ i++; objlist = objlist->next; } free_object_config(cfg); return conf; }