added support for absolute URIs and improved keep alive

Sat, 17 Oct 2015 21:17:34 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 17 Oct 2015 21:17:34 +0200
changeset 101
7fbcdbad0baa
parent 100
e9bb8449df02
child 102
136a76e293b5

added support for absolute URIs and improved keep alive

make/clang.mk file | annotate | diff | comparison | revisions
src/server/config/acl.c file | annotate | diff | comparison | revisions
src/server/config/keyfile.c file | annotate | diff | comparison | revisions
src/server/config/mimeconf.c file | annotate | diff | comparison | revisions
src/server/daemon/httplistener.c file | annotate | diff | comparison | revisions
src/server/daemon/httpparser.c file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.c file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.h file | annotate | diff | comparison | revisions
src/server/daemon/ldap_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/protocol.c file | annotate | diff | comparison | revisions
--- a/make/clang.mk	Sat Oct 17 18:07:04 2015 +0200
+++ b/make/clang.mk	Sat Oct 17 21:17:34 2015 +0200
@@ -30,7 +30,7 @@
 LDFLAGS = -Wl,-R,'$$ORIGIN/../lib'
 
 CC  = clang
-CXX = clang
+CXX = clang++
 LD = clang
 
 SHLIB_CFLAGS = -fPIC
--- a/src/server/config/acl.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/config/acl.c	Sat Oct 17 21:17:34 2015 +0200
@@ -110,7 +110,7 @@
     ACLConfig *cur = f->cur;
     UcxAllocator *mp = f->parser.mp;
     
-    size_t tkn = 0;
+    ssize_t tkn = 0;
     sstr_t *tk = sstrsplit(line, sstr(":"), &tkn);
     if(!tk || tkn < 3) {
         fprintf(stderr, "parse_ace: to few tokens\n");
@@ -161,7 +161,7 @@
     }
     s = tk[n];
     
-    size_t maskn = 0;
+    ssize_t maskn = 0;
     sstr_t *accessmask = sstrsplit(s, sstr(","), &maskn);
     for(int i=0;i<maskn;i++) {
         sstr_t access = accessmask[i];
@@ -195,7 +195,7 @@
             break;
         } else {
             // set flags
-            size_t fln = 0;
+            ssize_t fln = 0;
             sstr_t *flags = sstrsplit(s, sstr(","), &fln);
             for(int i=0;i<fln;i++) {
                 sstr_t flag = flags[i];
--- a/src/server/config/keyfile.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/config/keyfile.c	Sat Oct 17 21:17:34 2015 +0200
@@ -67,7 +67,7 @@
     KeyfileConfig *conf = p;
     UcxAllocator *mp = conf->parser.mp;
     
-    size_t tkn = 0;
+    ssize_t tkn = 0;
     sstr_t *tk = sstrsplit(line, sstrn(";", 1), &tkn);
     
     if(tkn < 2) {
@@ -115,7 +115,7 @@
     // get groups
     if(tkn == 3) {
         sstr_t groups_str = sstrtrim(tk[2]);
-        size_t ngroups = 0;
+        ssize_t ngroups = 0;
         sstr_t *groups = sstrsplit(groups_str, sstrn(",", 1), &ngroups);
         entry->groups = mp->calloc(mp->pool, ngroups, sizeof(sstr_t));
         entry->numgroups = ngroups;
--- a/src/server/config/mimeconf.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/config/mimeconf.c	Sat Oct 17 21:17:34 2015 +0200
@@ -83,7 +83,7 @@
         } else if(!sstrcmp(param->name, sstr("exts"))) {
             // comma-separated file extensions
             
-            size_t nx = 0;
+            ssize_t nx = 0;
             sstr_t *exts = sstrsplit(param->value, sstrn(",", 1), &nx);
             for(int i=0;i<nx;i++) {
                 sstr_t extstr = sstrdup_a(mp, exts[i]);
--- a/src/server/daemon/httplistener.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/daemon/httplistener.c	Sat Oct 17 21:17:34 2015 +0200
@@ -274,7 +274,7 @@
             perror("Error: acceptor_thread: accept");
             continue;
         }
-        
+           
         // check listener
         HttpListener *ls = listener;
         int acceptor_exit = 0;
--- a/src/server/daemon/httpparser.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/daemon/httpparser.c	Sat Oct 17 21:17:34 2015 +0200
@@ -41,6 +41,8 @@
     parser->state = 0;
     parser->start_line.ptr = (char*)request->netbuf->inbuf;
     parser->start_line.length = 0;
+    
+    parser->offset = 0;
 
     return parser;
 }
@@ -75,16 +77,23 @@
     while(buf->pos < buf->cursize) {
         unsigned char c = buf->inbuf[buf->pos];
         if(c == '\n') {
-            if(buf->pos <= 1) {
+            size_t lnlen = buf->pos - parser->offset + 1;
+            if(lnlen <= 2) {
+                if(lnlen == 1 || buf->inbuf[buf->pos-1] == '\r') {
+                    // skip empty line
+                    buf->pos++;
+                    parser->offset = buf->pos;
+                    return 1;
+                }
                 // insufficient chars for request, return error
                 return 2;
             }
             if(buf->inbuf[buf->pos - 1] == '\r') {
-                parser->start_line.length = buf->pos;
+                parser->start_line.length = lnlen - 1;
             } else {
-                parser->start_line.length = buf->pos + 1;
+                parser->start_line.length = lnlen;
             }
-            parser->start_line.ptr = (char*)buf->inbuf;
+            parser->start_line.ptr = (char*)buf->inbuf + parser->offset;
             buf->pos++;
             return 0;
         }
@@ -98,7 +107,9 @@
 
     parser->offset = buf->pos; // line offset
     parser->name.ptr = NULL;
+    parser->name.length = 0;
     parser->value.ptr = NULL;
+    parser->value.length = 0;
     while(1) {
         if(buf->pos >= buf->cursize) {
             return 1;
@@ -109,7 +120,7 @@
             parser->wl = 0;
             if(c == ':' && parser->value.ptr == NULL) {
                 parser->name.ptr = (char*)buf->inbuf + parser->offset;
-                buf->inbuf[buf->pos-1] = 0;
+                parser->name.length = buf->pos - parser->offset - 1;
             } else if(parser->name.ptr != NULL && parser->value.ptr == NULL) {
                 parser->value.ptr = (char*)buf->inbuf + buf->pos - 1;
             }
@@ -121,21 +132,24 @@
             } else {
                 parser->offset = buf->pos;
                 if(parser->value.ptr != NULL) {
-                    buf->inbuf[buf->pos-1] = 0;
+                    parser->value.length = (buf->inbuf + buf->pos - 1)
+                            - (unsigned char*)parser->value.ptr;
                     if(buf->inbuf[buf->pos-2] == '\r') {
-                        buf->inbuf[buf->pos-2] = 0;
+                        parser->value.length--;
                     }
                     // add header
                     header_add(
                             parser->request->headers,
-                            parser->name.ptr,
-                            parser->value.ptr);
+                            parser->name,
+                            parser->value);
                 } else {
                     // error: no value
                     return 2;
                 }
                 parser->name.ptr = NULL;
                 parser->value.ptr = NULL;
+                parser->name.length = 0;
+                parser->value.length = 0;
                 parser->wl = 1;
             }
         }
--- a/src/server/daemon/httprequest.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/daemon/httprequest.c	Sat Oct 17 21:17:34 2015 +0200
@@ -56,6 +56,33 @@
     req->headers = hd;
 }
 
+void http_request_cleanup(HTTPRequest *req) {
+    // TODO: implement
+}
+
+sstr_t http_request_get_abspath(HTTPRequest *req) {
+    sstr_t uri = req->uri;
+    
+    int i = 0;
+    if(uri.ptr[0] == '/') {
+        return uri;
+    } else if(sstrprefix(uri, S("http://"))) {
+        i = 7;
+    } else if(sstrprefix(uri, S("https://"))) {
+        i = 8;
+    } else if(!sstrcmp(uri, S("*"))) {
+        return uri;
+    }
+    
+    for(;i<uri.length;i++) {
+        if(uri.ptr[i] == '/') {
+            return sstrsubs(uri, i);
+        }
+    }
+    
+    return S("/");
+}
+
 int handle_request(HTTPRequest *request, threadpool_t *thrpool) {
     // handle nsapi request
     
@@ -137,13 +164,28 @@
             request->httpv.ptr,
             request->httpv.length,
             rq->rq.reqpb);
-    // TODO: protocol num
+    
+    if(!sstrcmp(request->httpv, S("HTTP/1.1"))) {
+        rq->rq.protv_num = PROTOCOL_VERSION_HTTP11;
+    } else if(!sstrcmp(request->httpv, S("HTTP/1.0"))) {
+        rq->rq.protv_num = PROTOCOL_VERSION_HTTP10;
+    } else {
+        // TODO: invalid protocol version - abort
+    }
 
     /*
      * get absolute path and query of the request uri
      */
     // TODO: check for '#'
-    sstr_t absPath = request->uri;
+    sstr_t absPath = http_request_get_abspath(request);
+    if(!absPath.ptr) {
+        // TODO: error msg
+        return 1;
+    } else if(absPath.ptr[0] == '*') {
+        // TODO: implement global OPTIONS
+        return 1;
+    }
+    
     sstr_t query;
     query.length = 0;
     
@@ -200,24 +242,38 @@
             i = 0;
             hlen = ha->len;
         }
+        
+        Header header = ha->headers[i];
 
-        if(ha->headers[i].name[0] < 90) {
-            ha->headers[i].name[0] += 32;
+        if(header.name.ptr[0] < 90) {
+            header.name.ptr[0] += 32;
         }
 
         // change to lower case
-        char *header_name = ha->headers[i].name;
-        for(int i=0;header_name[i]!=0;i++) {
-            if(header_name[i] > 64 && header_name[i] < 97) {
-                header_name[i] += 32;
+        for(int i=0;i<header.name.length;i++) {
+            if(header.name.ptr[i] > 64 && header.name.ptr[i] < 97) {
+                header.name.ptr[i] += 32;
             }
         }
-
-        pblock_nvinsert(
-                ha->headers[i].name,
-                ha->headers[i].value,
+        
+        pblock_nvlinsert(
+                header.name.ptr,
+                header.name.length,
+                header.value.ptr,
+                header.value.length,
                 rq->rq.headers);
     }
+    
+    // parse connection header
+    rq->rq.rq_attr.keep_alive = (rq->rq.protv_num >= PROTOCOL_VERSION_HTTP11);
+    char *conn_str = pblock_findkeyval(pb_key_connection, rq->rq.headers);
+    if(conn_str) {
+        if(!strcasecmp(conn_str, "keep-alive")) {
+            rq->rq.rq_attr.keep_alive = 1;
+        } else if(!strcasecmp(conn_str, "close")) {
+            rq->rq.rq_attr.keep_alive = 0;
+        }
+    }
        
     // check for request body and prepare input buffer
     char *ctlen_str = pblock_findkeyval(pb_key_content_length, rq->rq.headers);
@@ -284,7 +340,7 @@
 
 
 
-void header_add(HeaderArray *hd, char *name, char *value) {
+void header_add(HeaderArray *hd, sstr_t name, sstr_t value) {
     while(hd->len >= hd->alloc) {
         if(hd->next == NULL) {
             HeaderArray *block = malloc(sizeof(HeaderArray));
--- a/src/server/daemon/httprequest.h	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/daemon/httprequest.h	Sat Oct 17 21:17:34 2015 +0200
@@ -56,8 +56,8 @@
 };
 
 struct _header {
-    char *name;
-    char *value;
+    sstr_t name;
+    sstr_t value;
 };
 
 struct _header_array {
@@ -70,6 +70,8 @@
 void http_request_init(HTTPRequest *req);
 void http_request_cleanup(HTTPRequest *req);
 
+sstr_t http_request_get_abspath(HTTPRequest *req);
+
 /*
  * starts request processing after reading the request header
  * 
@@ -80,7 +82,7 @@
 
 
 
-void header_add(HeaderArray *hd, char *name, char *value);
+void header_add(HeaderArray *hd, sstr_t name, sstr_t value);
 void header_array_free(HeaderArray *hd);
 
 int nsapi_handle_request(NSAPISession *sn, NSAPIRequest *rq);
--- a/src/server/daemon/ldap_auth.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/daemon/ldap_auth.c	Sat Oct 17 21:17:34 2015 +0200
@@ -249,7 +249,7 @@
                                 values[i]->bv_len);
                         wsgroup->members[i].name = sstrdup(member).ptr;
                         // TODO: uid?
-                        printf("added member: %.*s\n", member.length, member.ptr);
+                        printf("added member: %.*s\n", (int)member.length, member.ptr);
                     }
                 }
             }
--- a/src/server/daemon/protocol.c	Sat Oct 17 18:07:04 2015 +0200
+++ b/src/server/daemon/protocol.c	Sat Oct 17 21:17:34 2015 +0200
@@ -342,15 +342,14 @@
     add_http_response_header(out, rq);
     
     // add connection header
-    char *conn_str = pblock_findkeyval(pb_key_connection, rq->headers);
-    if(conn_str && !strcasecmp(conn_str, "keep-alive")) {
+    if(rq->rq_attr.keep_alive) {
         sbuf_write(out, "Connection: keep-alive\r\n", 24);
         pblock_kvinsert(pb_key_connection, "keep-alive", 10, rq->srvhdrs);
-        rq->rq_attr.keep_alive = 1;
     } else {
         sbuf_write(out, "Connection: close\r\n", 19);
         pblock_kvinsert(pb_key_connection, "close", 5, rq->srvhdrs);
     }
+    
 
     // response header end
     sbuf_write(out, "\r\n", 2);

mercurial