Tue, 27 Dec 2011 20:12:21 +0100
improved request processing
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Tue Dec 27 20:12:21 2011 +0100 @@ -0,0 +1,2 @@ +relre:^work/.*$ +relre:^build/.*$
--- a/Makefile Mon Dec 26 15:48:32 2011 +0100 +++ b/Makefile Tue Dec 27 20:12:21 2011 +0100 @@ -57,5 +57,7 @@ @echo "copy scripts" sed s:%%WS_INSTALL_DIR%%:$(WS_INSTALL_DIR):g templates/bin/startserv.template > $(WS_INSTALL_DIR)bin/startserv chmod +x $(WS_INSTALL_DIR)bin/startserv + @echo "copy docs" + cp -R templates/docs $(WS_INSTALL_DIR)
--- a/src/server/Makefile Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/Makefile Tue Dec 27 20:12:21 2011 +0100 @@ -30,7 +30,7 @@ OBJ_DIR = $(BUILD_ROOT)build/ CFLAGS = -I/usr/include/mps -g -LDFLAGS = -L/usr/lib/mps -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lposix4 -lsocket -lnsl -lgen -lm -R/usr/lib/mps +LDFLAGS = -L/usr/lib/mps -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lposix4 -lsocket -lnsl -lgen -lm -R/usr/lib/mps -l sendfile MAIN_TARGET = $(BUILD_ROOT)work/bin/webservd
--- a/src/server/conf.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/conf.c Tue Dec 27 20:12:21 2011 +0100 @@ -56,7 +56,7 @@ printf("load_server_conf\n"); ListenerConfig *conf = malloc(sizeof(ListenerConfig)); - conf->port = 8080; + conf->port = 9090; conf->nacceptors = 1; conf->name = "default"; @@ -64,7 +64,8 @@ // virtual server default_vs = vs_new(); - default_vs->objset = create_test_objset(); + // load obj.conf + default_vs->objects = load_obj_conf("conf/obj.conf"); default_vs->default_obj_name = "default"; // begin objset test
--- a/src/server/httprequest.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/httprequest.c Tue Dec 27 20:12:21 2011 +0100 @@ -67,6 +67,7 @@ rq->phase = NSAPIAuthTrans; // fill session structure + sn->sys_fd = request->connection->fd; sn->sn.pool = pool_create(); sn->sn.csd = stream_new_from_fd(request->connection->fd); sn->sn.client = NULL; @@ -176,6 +177,7 @@ switch(rq->phase) { case NSAPIAuthTrans: { rq->phase++; + nsapi_context_next_stage(&rq->context); } case NSAPINameTrans: { printf(">>> NameTrans\n"); @@ -184,13 +186,17 @@ break; } rq->phase++; + nsapi_context_next_stage(&rq->context); } case NSAPIPathCheck: { printf(">>> PathCheck\n"); rq->phase++; + nsapi_context_next_stage(&rq->context); } case NSAPIObjectType: { + printf(">>> ObjectType\n"); rq->phase++; + nsapi_context_next_stage(&rq->context); } case NSAPIService: { printf(">>> Service\n"); @@ -199,6 +205,12 @@ break; } rq->phase++; + nsapi_context_next_stage(&rq->context); + } + case NSAPIAddLog: { + printf(">>> AddLog\n"); + rq->phase++; + nsapi_context_next_stage(&rq->context); } case REQ_FINISH: { printf(">>> Finish\n"); @@ -212,49 +224,97 @@ } int nsapi_finish_request(NSAPISession *sn, NSAPIRequest *rq) { + // TODO: free memory + close(sn->sys_fd); + return 0; } int nsapi_nametrans(NSAPISession *sn, NSAPIRequest *rq) { - httpd_objset *objset = rq->vs->objset; + HTTPObjectConfig *objconf = rq->vs->objects; printf("nsapi_nametrans\n"); + httpd_objset *objset = objset_create(sn->sn.pool); + rq->rq.os = objset; + /* first object in objconf is the default object TODO: make sure it is */ + objset_add_object(sn->sn.pool, objset, objconf->objects[0]); - int ret = -1; - for(int i=0;i<objset->pos;i++) { - httpd_object *obj = objset->obj[i]; - dtable *dt = object_get_dtable(obj, NSAPINameTrans); - - printf("object[%s] dt: %d\n", obj->name, dt); + httpd_object *obj = objset->obj[0]; /* nametrans only in default object */ + dtable *dt = object_get_dtable(obj, NSAPINameTrans); - // execute directives - for(int j=0;j<dt->ndir;j++) { - directive *d = dt->dirs[j]; + /* execute directives */ + int ret = rq->context.last_req_code; + char *name = NULL; + char *ppath = NULL; + for(int i=NCX_DI(rq);i<dt->ndir;i++) { + directive *d = dt->dirs[i]; - printf("execute [%s]\n", d->func->name); - ret = d->func->func(d->param, (Session*)sn, (Request*)rq); - if(ret == REQ_PROCEED || ret == REQ_PROCESSING) { - break; - } + printf("execute [%s]\n", d->func->name); + ret = d->func->func(d->param, (Session*)sn, (Request*)rq); + + /* check for name or ppath */ + name = pblock_findkeyval(pb_key_name, rq->rq.vars); + ppath = pblock_findkeyval(pb_key_ppath, rq->rq.vars); + + /* add additional objects to the objset */ + if(add_objects(objconf, objset, sn, rq, name, ppath) == REQ_ABORTED) { + fprintf(stderr, "add_objects failed\n"); + return REQ_ABORTED; } - // TODO: stultus - if(ret == REQ_PROCEED || ret == REQ_PROCESSING) { - break; + if(ret != REQ_NOACTION) { + /* + * if a saf is still processing, we need to save the context, to + * process this object at a later time + */ + if(ret == REQ_PROCESSING) { + /* save nsapi context */ + /* add +1 to start next round with next function */ + rq->context.dtable_index = i + 1; + } + + return ret; } } - // todo: check object, path, ... - char *ppath = pblock_findkeyval(pb_key_ppath, rq->rq.vars); - printf("ppath: [%s]\n", ppath); + /* if no function has set the ppath var, translate it to docroot */ + if(ret == REQ_NOACTION && ppath == NULL) { + sstr_t docroot = rq->vs->document_root; + if(docroot.length < 1) { + printf("docroot too short\n"); + return REQ_ABORTED; /* docroot too short */ + } + /* if there is a trailing '/', remove it */ + if(docroot.ptr[docroot.length - 1] == '/') { + docroot.length--; + } + + sstr_t uri = sstr(pblock_findkeyval(pb_key_uri, rq->rq.reqpb)); - return ret; + sstr_t translated; + translated.length = docroot.length + uri.length; + translated.ptr = alloca(translated.length + 1); + translated = sstrncat(2, translated, docroot, uri); + + pblock_kvinsert( + pb_key_ppath, + translated.ptr, + translated.length, + rq->rq.vars); + } + + return REQ_PROCEED; } int nsapi_service(NSAPISession *sn, NSAPIRequest *rq) { - httpd_objset *objset = rq->vs->objset; + printf("nsapi_service\n"); + httpd_objset *objset = rq->rq.os; - int ret = -1; - for(int i=0;i<objset->pos;i++) { + if(NCX_OI(rq) == -1) { + NCX_OI(rq) = objset->pos - 1; + } + + int ret = rq->context.last_req_code; + for(int i=NCX_OI(rq);i>=0;i--) { httpd_object *obj = objset->obj[i]; dtable *dt = object_get_dtable(obj, NSAPIService); @@ -263,17 +323,39 @@ directive *d = dt->dirs[j]; ret = d->func->func(d->param, (Session*)sn, (Request*)rq); - if(ret == REQ_PROCEED || ret == REQ_PROCESSING) { - break; + if(ret != REQ_NOACTION) { + if(ret == REQ_PROCESSING) { + /* save nsapi context */ + rq->context.objset_index = i; + + /* add +1 to start next round with next function */ + rq->context.dtable_index = j + 1; + } + + return ret; } } - - // TODO: stultus - if(ret == REQ_PROCEED || ret == REQ_PROCESSING) { - break; - } } return ret; } +/* + * adds objects with specific name or path to the httpd_objset + */ +int add_objects( + HTTPObjectConfig *objs, + httpd_objset *os, + NSAPISession *sn, + NSAPIRequest *rq, + char *name, + char *path) +{ + /* first, add all objects with a matching path */ + + + /* add object with object with matching name */ + + + return REQ_PROCEED; +}
--- a/src/server/httprequest.h Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/httprequest.h Tue Dec 27 20:12:21 2011 +0100 @@ -84,6 +84,14 @@ int nsapi_service(NSAPISession *sn, NSAPIRequest *rq); +int add_objects( + HTTPObjectConfig *objs, + httpd_objset *os, + NSAPISession *sn, + NSAPIRequest *rq, + char *name, + char *path); + /* request.h functions */ int request_initialize( pool_handle_t *pool,
--- a/src/server/nametrans.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/nametrans.c Tue Dec 27 20:12:21 2011 +0100 @@ -34,8 +34,8 @@ printf("test_nametrans...\n"); // set ppath - char *ppath = "/export/home/olaf/Desktop/hello.txt"; - pblock_kvinsert(pb_key_ppath, ppath, strlen(ppath), rq->vars); + //char *ppath = "/export/home/olaf/Desktop/hello.txt"; + //pblock_kvinsert(pb_key_ppath, ppath, strlen(ppath), rq->vars); - return REQ_PROCEED; + return REQ_NOACTION; }
--- a/src/server/nsapi.h Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/nsapi.h Tue Dec 27 20:12:21 2011 +0100 @@ -340,6 +340,7 @@ /**** END NSAPI extensions ****/ + /* --- End miscellaneous definitions --- */ /* --- Begin native platform includes --- */ @@ -347,6 +348,7 @@ #ifdef XP_UNIX #include <unistd.h> #include <sys/file.h> +#include <alloca.h> /* new */ #ifndef HPUX #include <sys/select.h> #endif
--- a/src/server/object.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/object.c Tue Dec 27 20:12:21 2011 +0100 @@ -30,6 +30,7 @@ #include "object.h" +#include "pool.h" #include "func.h" @@ -64,6 +65,25 @@ } +/* objset functions */ +httpd_objset* objset_create(pool_handle_t *pool) { + httpd_objset *os = pool_malloc(pool, sizeof(httpd_objset)); + + os->obj = pool_calloc(pool, 2, sizeof(void*)); + os->pos = 0; + + return os; +} + +void objset_add_object(pool_handle_t *p, httpd_objset *os, httpd_object *obj) { + if(os->pos != 0 && os->pos % 2 == 0) { + os->obj = pool_realloc(p, os->obj, (os->pos + 2) * sizeof(void*)); + } + os->obj[os->pos] = obj; + os->pos++; +} + + httpd_objset* create_test_objset() { @@ -93,3 +113,10 @@ conf->objects = realloc(conf->objects, conf->nobj * sizeof(void*)); conf->objects[conf->nobj - 1] = obj; } + + +void nsapi_context_next_stage(NSAPIContext *context) { + context->dtable_index = 0; + context->objset_index = -1; + context->last_req_code = REQ_NOACTION; +}
--- a/src/server/object.h Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/object.h Tue Dec 27 20:12:21 2011 +0100 @@ -43,6 +43,7 @@ NSAPIPathCheck, NSAPIObjectType, NSAPIService, + NSAPIAddLog, REQ_FINISH, NUM_NSAPI_TYPES }; @@ -90,7 +91,11 @@ ConditionResult **results; int nres; - httpd_objset *objset; + //httpd_objset *objset; + int last_req_code; + + int objset_index; + int dtable_index; }; struct HTTPObjectConfig { @@ -120,6 +125,18 @@ #define object_get_dtable(obj,type) &obj->dt[type]; + +/* + * creates a new httpd_objset + */ +httpd_objset* objset_create(pool_handle_t *pool); + +/* + * adds a object to the objset + */ +void objset_add_object(pool_handle_t *p, httpd_objset *os, httpd_object *obj); + + /* * creates a new HTTPObjectConfig */ @@ -132,7 +149,10 @@ -httpd_objset* create_test_objset(); +/* + * prepares the NSAPI context for the next request stage + */ +void nsapi_context_next_stage(NSAPIContext *context); #ifdef __cplusplus
--- a/src/server/request.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/request.c Tue Dec 27 20:12:21 2011 +0100 @@ -33,6 +33,7 @@ /* Code from req.cpp */ +/* fremden Code durch eigenen ersetzen */ /* -------------------------- request_initialize -------------------------- */ @@ -87,5 +88,11 @@ // TODO: nrq + /* NSAPI execution context */ + nrq->context.last_req_code = REQ_NOACTION; + + nrq->context.objset_index = -1; + nrq->context.dtable_index = 0; + return 0; }
--- a/src/server/request.h Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/request.h Tue Dec 27 20:12:21 2011 +0100 @@ -38,12 +38,16 @@ typedef struct NSAPIRequest NSAPIRequest; +struct NSAPIRequest { + Request rq; + RequestPhase phase; + VirtualServer *vs; + NSAPIContext context; +}; -struct NSAPIRequest { - Request rq; - RequestPhase phase; - VirtualServer *vs; -}; +/* macros for short context access */ +#define NCX_OI(rq) rq->context.objset_index +#define NCX_DI(rq) rq->context.dtable_index #define REQ_HASHSIZE 10
--- a/src/server/service.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/service.c Tue Dec 27 20:12:21 2011 +0100 @@ -27,41 +27,95 @@ */ #include <stdio.h> +#include <errno.h> #include "service.h" #include "io.h" #include "pblock.h" #include "protocol.h" +#include <sys/sendfile.h> + +// TODO: system sendfile Abstraktionen in neue Datei auslagern +/* +ssize_t sys_sendfile(int out_fd, int in_fd, off_t *off, size_t len) { + +} +*/ +#define sys_sendfile sendfile + + +/* + * prepares for servicing a file + * + * adds content-length header and starts the response + * + * return the file descriptor or an error code + */ +int prepare_service_file(Session *sn, Request *rq) { + char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); + + /* open the file */ + int fd = open(ppath, O_RDONLY); + if(fd < 0) { + perror("prepare_service_file: open"); + + int status = 500; + switch(errno) { + case EACCES: { + status = 403; + break; + } + case ENOENT: { + status = 404; + break; + } + } + protocol_status(sn, rq, status, NULL); + return -1; + } + + /* get stat */ + struct stat stat; + if (fstat(fd, &stat) != 0) { + perror("prepare_service_file: stat"); + + protocol_status(sn, rq, 500, NULL); + return -1; + } + + /* add content-length header*/ + char contentLength[32]; + int len = snprintf(contentLength, 32, "%d", stat.st_size); + + pblock_kvinsert(pb_key_content_length, contentLength, len, rq->srvhdrs); + + /* start response */ + protocol_status(sn, rq, 200, NULL); + http_start_response(sn, rq); + + return fd; +} + int test_service(pblock *pb, Session *sn, Request *rq) { printf("test_service\n"); - SystemIOStream *io = (SystemIOStream*) sn->csd; - char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); - FILE *out = fdopen(io->fd, "w"); - FILE *in = fopen(ppath, "r"); - printf("open path: %s\n", ppath); - - protocol_status(sn, rq, 200, NULL); - - http_start_response(sn, rq); + int fd = prepare_service_file(sn, rq); + if(fd < 0) { + /* TODO: service error */ + http_start_response(sn, rq); + return REQ_PROCEED; + } - /* - fprintf(out, "HTTP/1.1 200 OK\n"); - fprintf(out, "Server: Webserver Pre-Alpha\n"); - fprintf(out, "Concent-Length: 27\n"); - fprintf(out, "Connection: close\n\n"); - fflush(out); - */ + /* send file*/ + SystemIOStream *io = (SystemIOStream*) sn->csd; - char buffer[128]; - int r; - while((r = fread(buffer, 1, 64, in)) > 0) { - fwrite(buffer, 1, r, out); - } - fflush(out); - fclose(in); - fclose(out); + off_t fileoffset = 0; + int len = atoi(pblock_findkeyval(pb_key_content_length, rq->srvhdrs)); + printf("content-length: %d\n", len); + sendfile(io->fd, fd, &fileoffset, len); + + close(fd); return REQ_PROCEED; }
--- a/src/server/vserver.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/vserver.c Tue Dec 27 20:12:21 2011 +0100 @@ -31,7 +31,8 @@ VirtualServer* vs_new() { VirtualServer *vs = malloc(sizeof(VirtualServer)); vs->default_obj_name = NULL; - vs->objset = NULL; + vs->objects = NULL; + vs->document_root = sstr("docs"); return vs; }
--- a/src/server/vserver.h Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/vserver.h Tue Dec 27 20:12:21 2011 +0100 @@ -32,13 +32,17 @@ #include "object.h" #include "nsapi.h" +#include "sstring.h" + #ifdef __cplusplus extern "C" { #endif struct VirtualServer { - char *default_obj_name; - httpd_objset *objset; + char *default_obj_name; + HTTPObjectConfig *objects; + + sstr_t document_root; }; VirtualServer* vs_new();
--- a/src/server/webserver.c Mon Dec 26 15:48:32 2011 +0100 +++ b/src/server/webserver.c Tue Dec 27 20:12:21 2011 +0100 @@ -55,9 +55,6 @@ // load server.conf load_server_conf(NULL); - // load obj.conf - HTTPObjectConfig *obj_conf = load_obj_conf("conf/obj.conf"); - // init NSAPI functions