improved request processing

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 7
3c2ed7a7a5fd

improved request processing

.hgignore file | annotate | diff | comparison | revisions
Makefile file | annotate | diff | comparison | revisions
src/server/Makefile file | annotate | diff | comparison | revisions
src/server/conf.c file | annotate | diff | comparison | revisions
src/server/httprequest.c file | annotate | diff | comparison | revisions
src/server/httprequest.h file | annotate | diff | comparison | revisions
src/server/nametrans.c file | annotate | diff | comparison | revisions
src/server/nsapi.h file | annotate | diff | comparison | revisions
src/server/object.c file | annotate | diff | comparison | revisions
src/server/object.h file | annotate | diff | comparison | revisions
src/server/request.c file | annotate | diff | comparison | revisions
src/server/request.h file | annotate | diff | comparison | revisions
src/server/service.c file | annotate | diff | comparison | revisions
src/server/vserver.c file | annotate | diff | comparison | revisions
src/server/vserver.h file | annotate | diff | comparison | revisions
src/server/webserver.c file | annotate | diff | comparison | revisions
templates/conf/obj.conf file | annotate | diff | comparison | revisions
templates/docs/hello.txt file | annotate | diff | comparison | revisions
--- /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
 
     
--- a/templates/conf/obj.conf	Mon Dec 26 15:48:32 2011 +0100
+++ b/templates/conf/obj.conf	Tue Dec 27 20:12:21 2011 +0100
@@ -5,7 +5,7 @@
 #
 
 <Object name="default">
-NameTrans fn="docroot" path="docs/"
+NameTrans fn="test-nametrans"
 Service fn="test-service"
 </Object>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/docs/hello.txt	Tue Dec 27 20:12:21 2011 +0100
@@ -0,0 +1,3 @@
+Hello World!
+------------
+

mercurial