src/server/conf.c

Tue, 27 Dec 2011 20:12:21 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 27 Dec 2011 20:12:21 +0100
changeset 6
ce8fecc9847d
parent 5
dbc01588686e
child 12
34aa8001ea53
permissions
-rw-r--r--

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);
}

mercurial