Added request body reader

Wed, 28 Dec 2011 22:02:08 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 28 Dec 2011 22:02:08 +0100
changeset 8
f4d56bf9de40
parent 7
3c2ed7a7a5fd
child 9
30e51941a673

Added request body reader

src/server/httprequest.c file | annotate | diff | comparison | revisions
src/server/io.c file | annotate | diff | comparison | revisions
src/server/io.h file | annotate | diff | comparison | revisions
src/server/netbuf.c file | annotate | diff | comparison | revisions
src/server/nsapi.h file | annotate | diff | comparison | revisions
src/server/objs.mk file | annotate | diff | comparison | revisions
src/server/protocol.c file | annotate | diff | comparison | revisions
src/server/service.c file | annotate | diff | comparison | revisions
--- a/src/server/httprequest.c	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/httprequest.c	Wed Dec 28 22:02:08 2011 +0100
@@ -147,9 +147,56 @@
             hlen = ha->len;
         }
 
+        if(ha->headers[i].name[0] < 90) {
+            ha->headers[i].name[0] += 32;
+        }
         pblock_nvinsert(ha->headers[i].name, ha->headers[i].value, rq->rq.headers);
     }
 
+    /* check for request body and prepare input buffer */
+    char *ctlen_str = pblock_findkeyval(pb_key_content_length, rq->rq.headers);
+    if(ctlen_str) {
+        int ctlen = atoi(ctlen_str);
+        
+        printf("request body length: %d\n", ctlen);
+
+        netbuf *nb = request->netbuf;
+
+        /* create new netbuf */
+        NetIOStream *net_io = (NetIOStream*)net_stream_from_fd(
+                request->connection->fd);
+        net_io->max_read = ctlen;
+
+        sn->sn.inbuf = malloc(sizeof(netbuf));
+        sn->sn.inbuf->sd = net_io;
+        sn->sn.inbuf->pos = 0;
+        
+        /* prepare buffer */
+        int cur_input_len = nb->cursize - nb->pos;
+        if(cur_input_len >= ctlen) {
+
+            /*
+             * all data is already in the primary input buffer
+             * just link the new netbuf to the primary buffer
+             */
+            sn->sn.inbuf->maxsize = ctlen;
+            sn->sn.inbuf->cursize = ctlen;
+            sn->sn.inbuf->inbuf = nb->inbuf + nb->pos;
+        } else {
+            sn->sn.inbuf->maxsize = (ctlen > 2048) ? (2048) : (ctlen);
+            sn->sn.inbuf->inbuf = malloc(sizeof(sn->sn.inbuf->maxsize));
+
+            if(cur_input_len > 0) {
+                /* we have read a part of the request body -> copy to netbuf */
+                memcpy(sn->sn.inbuf->inbuf, nb->inbuf+nb->pos, cur_input_len);
+            }
+
+            sn->sn.inbuf->cursize = cur_input_len;
+        }
+    } else {
+        sn->sn.inbuf = NULL;
+    }
+
 
     // Send the request to the NSAPI system
     nsapi_handle_request(sn, rq);
--- a/src/server/io.c	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/io.c	Wed Dec 28 22:02:08 2011 +0100
@@ -38,6 +38,11 @@
     system_read
 };
 
+IOStream net_io_funcs = {
+    net_stream_write,
+    net_stream_read
+};
+
 
 IOStream* stream_new_from_fd(int fd) {
     SystemIOStream *st = malloc(sizeof(SystemIOStream));
@@ -55,6 +60,38 @@
 }
 
 
+IOStream* net_stream_from_fd(int fd) {
+    NetIOStream *st = malloc(sizeof(NetIOStream));
+    st->st = net_io_funcs;
+    st->fd = fd;
+    st->max_read = 0;
+    st->rd = 0;
+}
+
+ssize_t net_stream_write(IOStream *st, void *buf, size_t nbytes) {
+    // TODO: implement
+}
+
+ssize_t net_stream_read(IOStream *st, void *buf, size_t nbytes) {
+    NetIOStream *n = (NetIOStream*)st;
+    if(n->max_read != 0 && n->rd >= n->max_read) {
+        return 0;
+    }
+    ssize_t r = read(n->fd, buf, nbytes);
+    n->rd += r;
+    return r;
+}
+
+
+ssize_t net_read(SYS_NETFD fd, void *buf, size_t nbytes) {
+    ssize_t r = ((IOStream*)fd)->read(fd, buf, nbytes);
+    if(r == 0) {
+        return IO_EOF;
+    }
+    return r;
+}
+
+
 /* iovec buffer */
 iovec_buf_t *iovec_buf_create(pool_handle_t *pool) {
     iovec_buf_t *buf = pool_malloc(pool, sizeof(iovec_buf_t));
--- a/src/server/io.h	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/io.h	Wed Dec 28 22:02:08 2011 +0100
@@ -50,6 +50,17 @@
     int      fd;
 } SystemIOStream;
 
+typedef struct NetIOStream {
+    IOStream st;
+    int      fd;
+    size_t   max_read;
+    size_t   rd;
+} NetIOStream;
+
+
+/* net_ functions */
+ssize_t net_read(SYS_NETFD fd, void *buf, size_t nbytes);
+
 
 /* iovec buffer */
 typedef struct iovec_buf{
@@ -66,6 +77,11 @@
 ssize_t system_write(IOStream *st, void *buf, size_t nbytes);
 ssize_t system_read(IOStream *st, void *buf, size_t nbytes);
 
+/* net stream */
+IOStream* net_stream_from_fd(int fd);
+
+ssize_t net_stream_write(IOStream *st, void *buf, size_t nbytes);
+ssize_t net_stream_read(IOStream *st, void *buf, size_t nbytes);
 
 /* iovec buffer */
 iovec_buf_t *iovec_buf_create(pool_handle_t *pool);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/netbuf.c	Wed Dec 28 22:02:08 2011 +0100
@@ -0,0 +1,191 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 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.
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * 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 OWNER
+ * 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.
+ */
+
+/*
+ * netbuf.c: Handles buffered I/O on network sockets
+ *
+ * Rob McCool
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "nspr.h"
+#include "nsapi.h"
+#include "io.h"
+
+//include "buffer.h"
+
+
+#define NETBUF_RDTIMEOUT 120
+
+
+/* ----------------------------- netbuf_open ------------------------------ */
+
+
+NSAPI_PUBLIC netbuf *netbuf_open(SYS_NETFD sd, int sz) {
+    netbuf *buf = (netbuf *) malloc(sizeof(netbuf));
+
+    buf->rdtimeout = NETBUF_RDTIMEOUT;
+    buf->pos = sz;
+    buf->cursize = sz; /* force buffer_next on first getc */
+    buf->maxsize = sz;
+    buf->sd = sd;
+
+    buf->inbuf = NULL;
+    buf->errmsg = NULL;
+
+    return buf;
+}
+
+
+/* ----------------------------- netbuf_close ----------------------------- */
+
+
+NSAPI_PUBLIC void netbuf_close(netbuf *buf) {
+    if(buf->inbuf)
+        free(buf->inbuf);
+    free(buf);
+}
+
+
+/* ----------------------------- netbuf_replace --------------------------- */
+
+
+NSAPI_PUBLIC unsigned char * netbuf_replace(netbuf *buf,
+    unsigned char *inbuf, int pos, int cursize, int maxsize)
+{
+    unsigned char *oldbuf = buf->inbuf;
+
+    buf->inbuf = inbuf;
+    buf->pos = pos;
+    buf->cursize = cursize;
+    buf->maxsize = maxsize;
+
+    return oldbuf;
+}
+
+
+/* ----------------------------- netbuf_next ------------------------------ */
+
+
+NSAPI_PUBLIC int netbuf_next(netbuf *buf, int advance) {
+    int n;
+
+    if(!buf->inbuf)
+        buf->inbuf = (unsigned char *) malloc(buf->maxsize);
+
+    while(1) {
+        switch(n = net_read(buf->sd, (char *)(buf->inbuf), buf->maxsize)) {
+        //case IO_EOF:
+        case 0:
+            return IO_EOF;
+        case -1:
+            return IO_ERROR;
+        //case IO_ERROR:
+            //buf->errmsg = system_errmsg();
+        //    return IO_ERROR;
+        default:
+            buf->pos = advance;
+            buf->cursize = n;
+            return buf->inbuf[0];
+        }
+    }
+}
+
+NSAPI_PUBLIC int netbuf_getbytes(netbuf *buf, char *buffer, int size)
+{
+    int bytes;
+
+    if (!buf->inbuf) {
+        buf->inbuf = (unsigned char *) malloc(buf->maxsize);
+    } else {
+        if (buf->pos < buf->cursize) {
+            int bytes_in_buffer = buf->cursize - buf->pos;
+
+            if (bytes_in_buffer > size)
+                bytes_in_buffer = size;
+
+            memcpy(buffer, &(buf->inbuf[buf->pos]), bytes_in_buffer);
+
+            buf->pos += bytes_in_buffer;
+            return bytes_in_buffer;
+        }
+    }
+
+    /* The netbuf is empty.  Read data directly into the caller's buffer */
+    bytes = net_read(buf->sd, buffer, size);
+    if (bytes == 0)
+        return NETBUF_EOF;
+    if (bytes < 0) {
+        //buf->errmsg = system_errmsg();
+        return NETBUF_ERROR;
+    }
+    return bytes;
+}
+
+
+/* ----------------------------- netbuf_grab ------------------------------ */
+
+
+NSAPI_PUBLIC int netbuf_grab(netbuf *buf, int sz) {
+    int n;
+
+    if(!buf->inbuf) {
+        buf->inbuf = (unsigned char *) malloc(sz);
+        buf->maxsize = sz;
+    }
+    else if(sz > buf->maxsize) {
+        buf->inbuf = (unsigned char *) realloc(buf->inbuf, sz);
+        buf->maxsize = sz;
+    }
+
+    PR_ASSERT(buf->pos == buf->cursize);
+    buf->pos = 0;
+    buf->cursize = 0;
+
+    while(1) {
+        switch(n = net_read(buf->sd, (char *)(buf->inbuf), sz)) {
+        case 0:
+            return IO_EOF;
+        case -1: {
+            //buf->errmsg = system_errmsg();
+            return IO_ERROR;
+        }
+        default:
+            buf->cursize = n;
+            return n;
+        }
+    }
+}
--- a/src/server/nsapi.h	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/nsapi.h	Wed Dec 28 22:02:08 2011 +0100
@@ -1603,6 +1603,25 @@
  * -----------------------------------------------------------------------
  */
 
+
+/* new macro and function definitions begin */
+
+/* netbuf functions */
+NSAPI_PUBLIC netbuf *netbuf_open(SYS_NETFD sd, int sz);
+
+NSAPI_PUBLIC void netbuf_close(netbuf *buf);
+
+NSAPI_PUBLIC unsigned char * netbuf_replace(netbuf *buf,
+    unsigned char *inbuf, int pos, int cursize, int maxsize);
+
+NSAPI_PUBLIC int netbuf_next(netbuf *buf, int advance);
+
+NSAPI_PUBLIC int netbuf_getbytes(netbuf *buf, char *buffer, int size);
+
+NSAPI_PUBLIC int netbuf_grab(netbuf *buf, int sz);
+
+/* end new macro and function definitions */
+
 #define SYS_STDERR STDERR_FILENO
 
 #ifdef XP_WIN32
--- a/src/server/objs.mk	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/objs.mk	Wed Dec 28 22:02:08 2011 +0100
@@ -58,6 +58,7 @@
 MOBJ += nametrans.o
 MOBJ += service.o
 MOBJ += protocol.o
+MOBJ += netbuf.o
 
 MAINOBJS = $(MOBJ:%=$(OBJPRE)%)
 
--- a/src/server/protocol.c	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/protocol.c	Wed Dec 28 22:02:08 2011 +0100
@@ -267,7 +267,6 @@
             iovec_buf_write(out, ": ", 2);
             iovec_buf_write(out, value, strlen(value));
             iovec_buf_write(out, "\r\n", 2);
-            printf(".\n");
 
             p = p->next;
         }
--- a/src/server/service.c	Wed Dec 28 10:57:36 2011 +0100
+++ b/src/server/service.c	Wed Dec 28 22:02:08 2011 +0100
@@ -100,6 +100,23 @@
 int test_service(pblock *pb, Session *sn, Request *rq) {
     printf("test_service\n");
 
+    // request body test begin
+    char *ctval = pblock_findkeyval(pb_key_content_length, rq->headers);
+    if(ctval != NULL) {
+        printf("read request body\n");
+
+        printf("netbuf{%d}\n", sn->inbuf);
+
+        int c;
+        while((c = netbuf_getc(sn->inbuf)) != IO_EOF) {
+            putchar(c);
+        }
+        printf("\n");
+    }
+
+
+    // end test
+
     int fd = prepare_service_file(sn, rq);
     if(fd < 0) {
         /* TODO: service error */

mercurial