# HG changeset patch # User Olaf Wintermann # Date 1325106128 -3600 # Node ID f4d56bf9de40e724b34aae6f724261a6f0bb528a # Parent 3c2ed7a7a5fd4be8ea2c9ce8760116db0bcc9dd3 Added request body reader diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/httprequest.c --- 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); diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/io.c --- 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)); diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/io.h --- 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); diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/netbuf.c --- /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 +#include +#include + +#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; + } + } +} diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/nsapi.h --- 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 diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/objs.mk --- 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)%) diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/protocol.c --- 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; } diff -r 3c2ed7a7a5fd -r f4d56bf9de40 src/server/service.c --- 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 */