Tue, 27 Dec 2011 20:12:21 +0100
improved request processing
/* * 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 "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 "sstring.h" #include "httplistener.h" #include "conf.h" #include "func.h" #include "vserver.h" #include "pblock.h" VirtualServer *default_vs; void load_init_conf(char *file) { printf("load_init_conf\n"); } void load_server_conf(char *file) { printf("load_server_conf\n"); ListenerConfig *conf = malloc(sizeof(ListenerConfig)); conf->port = 9090; conf->nacceptors = 1; conf->name = "default"; http_listener_new(conf); // virtual server default_vs = vs_new(); // load obj.conf default_vs->objects = load_obj_conf("conf/obj.conf"); default_vs->default_obj_name = "default"; // begin objset test /* httpd_objset *objset = default_vs->objset; for(int i=0;i<objset->pos;i++) { httpd_object *obj = objset->obj[i]; printf("<object [%s]>\n", obj->name); for(int j=0;j<obj->nd;j++) { dtable *dt; switch(j) { case NSAPIAuthTrans: { printf(" Get AuthTrans Directives\n"); dt = object_get_dtable(obj, NSAPIAuthTrans); break; } case NSAPINameTrans: { printf(" Get NameTrans Directives\n"); dt = object_get_dtable(obj, NSAPINameTrans); break; } case NSAPIPathCheck: { printf(" Get PathCheck Directives\n"); dt = object_get_dtable(obj, NSAPIPathCheck); break; } case NSAPIService: { printf(" Get Service Directives\n"); dt = object_get_dtable(obj, NSAPIService); break; } default: { printf("j: %d\n", j); dt = object_get_dtable(obj, j); break; } } if(dt != NULL) { printf(" dtable[%d].length = %d\n", dt, dt->ndir); } else { continue; } for(int k=0;k<dt->ndir;k++) { directive *d = dt->directive[k]; if(d == NULL) { printf("d is null\n"); } else { printf(" Directive[%d].name = %s\n", d, d->func->name); } } } } */ // end objset test } VirtualServer* conf_get_default_vs() { return default_vs; } HTTPObjectConfig* load_obj_conf(char *file) { printf("load_obj_conf\n"); /* create object config */ ObjectConfParser parser; HTTPObjectConfig *conf = calloc(sizeof(HTTPObjectConfig), 1); conf->pool = pool_create(); parser.conf = conf; FILE *in = fopen("conf/obj.conf", "r"); if(in == NULL) { fprintf(stderr, "Cannot open conf/obj.conf\n"); return NULL; } char buf[512]; int len = 512; while(!feof(in)) { fgets(buf, len, in); if(*buf == 0) { continue; } char *ptr; if((ptr = strrchr(buf, '\n'))) { ptr[0] = 0; } sstr_t line = string_trim(sstr(buf)); if(line.length > 0) { obj_conf_parse_line(&parser, line); } } return conf; } void obj_conf_parse_line(ObjectConfParser *parser, sstr_t line) { //printf("{%s}[%d]\n", line.ptr, line.length); if(line.ptr[0] == '#') { return; } if(line.length < 3) { // to short for everything fprintf(stderr, "obj.conf: line to short \"%s\"\n", line.ptr); return; } // TODO: ersetzen if(line.ptr[0] == '<') { if(line.ptr[1] == '/') { // end tag if(line.ptr[2] == 'O' && parser->obj != NULL) { // end of Object httpobjconf_add_object(parser->conf, parser->obj); parser->obj = NULL; return; } } else { // new tag httpd_object *obj = parse_new_object_tag(line); parser->obj = obj; } } else { // directive parse_directive(parser, line); } } /* utils */ sstr_t string_trim(sstr_t string) { sstr_t newstr = string; int nsoff = 0; int l = 1; for(int i=0;i<string.length;i++) { char c = string.ptr[i]; if(l) { /* leading whitespace */ if(c > 32) { l = 0; nsoff = i; newstr.ptr = &string.ptr[i]; newstr.length = string.length - nsoff; } } else { /* trailing whitespace */ if(c > 32) { newstr.length = (i - nsoff) + 1; } } } return newstr; } httpd_object* parse_new_object_tag(sstr_t line) { int i = 0; int b = 0; sstr_t name; sstr_t value; char *obj_name = NULL; char *obj_ppath = NULL; for(;i<line.length;i++) { if(line.ptr[i] < 33) { b = 1; } else if(b == 1) { break; } } if(!b || line.ptr[i] < 33) { printf("1\n"); return NULL; } b = 0; /* parse name=value params */ for(;i<line.length;i++) { if(line.ptr[i] == '>') { break; } /* get name */ name.ptr = line.ptr + i; for(;i<line.length;i++) { if(line.ptr[i] == '=') { b = 1; i++; break; } } if(!b) { printf("2\n"); return NULL; } name.length = line.ptr + i - name.ptr - 1; if(line.ptr[i] == '\"') { i++; // TODO: Bug wenn end of line - wird nicht erkannt! } value.ptr = line.ptr + i; for(;i<line.length;i++) { char c = line.ptr[i]; if(c < 33 || c == '\"' || c == '>') { b = 1; break; } } if(!b) { printf("3\n"); return NULL; } value.length = line.ptr + i - value.ptr; if(sstrcmp(name, sstrn("name", 4)) == 0) { obj_name = sstrdub(value).ptr; } else if (sstrcmp(name, sstrn("ppath", 5)) == 0) { obj_ppath = sstrdub(value).ptr; } /* printf("name: [%d]{", name.length); fwrite(name.ptr, 1, name.length, stdout); printf("}\n"); printf("value: [%d]{", value.length); fwrite(value.ptr, 1, value.length, stdout); printf("}\n"); */ char c = line.ptr[i]; if(c == '>') { break; } else { i++; } } if(obj_name != NULL || obj_ppath != NULL) { httpd_object *o = object_new(obj_name); o->path = obj_ppath; return o; } return NULL; } void parse_directive(ObjectConfParser *parser, sstr_t line) { int i = 0; int b = 0; sstr_t directive_type = line; directive *directive = malloc(sizeof(directive)); directive->cond = NULL; directive->param = pblock_create_pool(parser->conf->pool, 8); for(;i<line.length;i++) { if(line.ptr[i] < 33) { b = 1; directive_type.length = i; if(directive_type.length <= 0) { fprintf(stderr, "parse error: cannot parse directive\n"); return; } } else if(b == 1) { break; } } /* parse name=value params */ sstr_t name; sstr_t value; for(;i<line.length;i++) { /* get name */ name.ptr = line.ptr + i; for(;i<line.length;i++) { if(line.ptr[i] == '=') { b = 1; i++; break; } } if(!b) { printf("2\n"); return; } name.length = line.ptr + i - name.ptr - 1; if(line.ptr[i] == '\"') { i++; // TODO: Bug wenn end of line - wird nicht erkannt! } value.ptr = line.ptr + i; for(;i<line.length;i++) { char c = line.ptr[i]; if(c < 33 || c == '\"') { b = 1; break; } } if(!b) { printf("3\n"); return; } value.length = line.ptr + i - value.ptr; name = string_trim(name); value = string_trim(value); /* insert name and value into directive pblock */ pblock_nvlinsert( name.ptr, name.length, value.ptr, value.length, directive->param); } /* get function */ char *func_name = pblock_findval("fn", directive->param); directive->func = get_function(func_name); /* get nsapi function type */ int dt = -1; if(sstrcmp(directive_type, sstr("AuthTrans")) == 0) { dt = 0; } else if(sstrcmp(directive_type, sstr("NameTrans")) == 0) { dt = 1; } else if(sstrcmp(directive_type, sstr("PathCheck")) == 0) { dt = 2; } else if(sstrcmp(directive_type, sstr("ObjectType")) == 0) { dt = 3; } else if(sstrcmp(directive_type, sstr("Service")) == 0) { dt = 4; } else if(sstrcmp(directive_type, sstr("AddLog")) == 0) { //dt = 5; return; } object_add_directive(parser->obj, directive, dt); }