added chunked transfer encoding

Wed, 22 May 2013 15:05:06 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 22 May 2013 15:05:06 +0200
changeset 65
14722c5f8856
parent 64
c7f5b062e622
child 66
74babc0082b7

added chunked transfer encoding

src/server/daemon/protocol.c file | annotate | diff | comparison | revisions
src/server/public/nsapi.h file | annotate | diff | comparison | revisions
src/server/public/vfs.h file | annotate | diff | comparison | revisions
src/server/util/io.c file | annotate | diff | comparison | revisions
src/server/util/io.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/protocol.c	Wed May 22 13:27:31 2013 +0200
+++ b/src/server/daemon/protocol.c	Wed May 22 15:05:06 2013 +0200
@@ -278,36 +278,64 @@
 }
 
 int http_start_response(Session *sn, Request *rq) {
-    int fd = ((SystemIOStream*)sn->csd)->fd;
+    int fd = ((NetIOStream*)sn->csd)->fd;
 
     if(rq->status_num == -1) {
         protocol_status(sn, rq, 200, "OK");
     }
 
-    /* set socket blocking */
+    // set socket blocking
     int flags;
     flags = fcntl(fd, F_GETFL, 0);
     fcntl(fd, F_SETFL, flags ^ O_NONBLOCK);
 
-    /* output buffer */
+    // output buffer
     sbuf_t *out = sbuf_new(512);
 
-    /* add the http status line to the output buffer */
+    // add the http status line to the output buffer
     add_http_status_line(out, sn->pool, rq);
 
-    /* add server header */
+    // add server header
     sbuf_write(out, "Server: webserver\r\n", 19);
-
-    /* add header from rq->srvhdrs */
+    
+    // check content length ans transfer encoding
+    char *ctlen = pblock_findkeyval(pb_key_content_length, rq->srvhdrs);
+    char *enc = pblock_findkeyval(pb_key_transfer_encoding, rq->srvhdrs);
+    if(ctlen && enc) {
+        pblock_removekey(pb_key_transfer_encoding, rq->srvhdrs);
+    }
+    if(!ctlen) {
+        // set transfer-encoding header
+        if(!enc) {
+            pblock_kvinsert(
+                    pb_key_transfer_encoding,
+                    "chunked",
+                    7,
+                    rq->srvhdrs);
+        } else if(strcmp(enc, "chunked")) {
+            pblock_removekey(pb_key_transfer_encoding, rq->srvhdrs);
+            pblock_kvinsert(
+                    pb_key_transfer_encoding,
+                    "chunked",
+                    7,
+                    rq->srvhdrs);
+        }
+        
+        // set stream property
+        NetIOStream *stream = (NetIOStream*)sn->csd;
+        stream->chunkedenc = 1;
+    }
+    
+    // add header from rq->srvhdrs
     add_http_response_header(out, rq);
     
-    /* add connection header */
+    // add connection header
     sbuf_write(out, "Connection: close\r\n", 19);
 
-    /* response header end */
+    // response header end
     sbuf_write(out, "\r\n", 2);
 
-    /* flush buffer to the socket */
+    // flush buffer to the socket
     write(fd, out->ptr, out->length);
     sbuf_free(out);
     
--- a/src/server/public/nsapi.h	Wed May 22 13:27:31 2013 +0200
+++ b/src/server/public/nsapi.h	Wed May 22 15:05:06 2013 +0200
@@ -546,15 +546,19 @@
  *      This structure is used to pass arguments to the net_writev()
  *      and FilterWritevFunc() functions.  
  */
-#ifdef _LP64
+typedef struct iovec NSAPIIOVec;
+
+/*
+//ifdef _LP64
 typedef struct NSAPIIOVec NSAPIIOVec;
 struct NSAPIIOVec {
     char *iov_base;
     int iov_len;
 };
-#else
+//else
 typedef struct iovec NSAPIIOVec;
-#endif /* _LP64 */
+//endif
+*/
 
 
 /*
@@ -1259,6 +1263,8 @@
 
 //NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, PRInt64 value, pblock *pb);
 
+#define pblock_remove(name, pb) (pblock_fr(name,pb,1))
+
 #define param_create INTparam_create
 #define param_free INTparam_free
 #define pblock_create INTpblock_create
--- a/src/server/public/vfs.h	Wed May 22 13:27:31 2013 +0200
+++ b/src/server/public/vfs.h	Wed May 22 15:05:06 2013 +0200
@@ -55,10 +55,10 @@
 };
 
 struct VFSContext {
+    pool_handle_t *pool;
     Session *sn;
     Request *rq;
     VFS *vfs;
-    pool_handle_t *pool;
     User *user;
     ACLListHandle *acllist;
     uint32_t aclreqaccess;
--- a/src/server/util/io.c	Wed May 22 13:27:31 2013 +0200
+++ b/src/server/util/io.c	Wed May 22 15:05:06 2013 +0200
@@ -48,10 +48,10 @@
 };
 
 IOStream net_io_funcs = {
-    net_stream_write,
-    net_stream_writev,
-    net_stream_read,
-    net_stream_sendfile
+    (io_write_f)net_stream_write,
+    (io_writev_f)net_stream_writev,
+    (io_read_f)net_stream_read,
+    (io_sendfile_f)net_stream_sendfile
 };
 
 
@@ -81,34 +81,60 @@
     st->fd = fd;
     st->max_read = 0;
     st->rd = 0;
+    st->chunkedenc = 0;
+    st->buffered = 0;
     return (IOStream*)st;
 }
 
-ssize_t net_stream_write(IOStream *st, void *buf, size_t nbytes) {
-    return write(((NetIOStream*)st)->fd, buf, nbytes);
-}
-
-ssize_t net_stream_writev(IOStream *st, struct iovec *iovec, int iovcnt) {
-    return writev(((NetIOStream*)st)->fd, iovec, iovcnt);
+ssize_t net_stream_write(NetIOStream *st, void *buf, size_t nbytes) {
+    if(st->chunkedenc) {
+        // TODO: on some plattforms iov_len is smaller than size_t
+        struct iovec io[2];
+        char chunk_len[16];
+        io[0].iov_base = chunk_len;
+        io[0].iov_len = snprintf(chunk_len, 16, "\n%x\r\n", nbytes);
+        io[1].iov_base = buf;
+        io[1].iov_len = nbytes;
+        ssize_t r = writev(st->fd, io, 2);
+        return r - io[0].iov_len;
+    } else {
+        return write(st->fd, buf, nbytes);
+    }
 }
 
-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) {
+ssize_t net_stream_writev(NetIOStream *st, struct iovec *iovec, int iovcnt) {
+    if(st->chunkedenc) {
+        struct iovec *io = calloc(iovcnt + 1, sizeof(struct iovec));
+        char chunk_len[16];
+        io[0].iov_base = chunk_len;
+        size_t len = 0;
+        for(int i=0;i<iovcnt;i++) {
+            len += iovec[i].iov_len;
+        }
+        io[0].iov_len = snprintf(chunk_len, 16, "\n%x\r\n", len);
+        memcpy(io + 1, iovec, iovcnt * sizeof(struct iovec));
+        ssize_t r = writev(st->fd, io, iovcnt + 1);
+        return r - io[0].iov_len;
+    } else {
+        return writev(st->fd, iovec, iovcnt);
+    }
+}
+
+ssize_t net_stream_read(NetIOStream *st, void *buf, size_t nbytes) {
+    if(st->max_read != 0 && st->rd >= st->max_read) {
         return 0;
     }
-    ssize_t r = read(n->fd, buf, nbytes);
-    n->rd += r;
+    ssize_t r = read(st->fd, buf, nbytes);
+    st->rd += r;
     return r;
 }
 
-ssize_t net_stream_sendfile(IOStream *st, sendfiledata *sfd) {
-    NetIOStream *io = (NetIOStream*)st;
+ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) {
     // TODO: header and trailer
     ssize_t ret = 0;
     off_t fileoffset = sfd->offset;
     if(sfd->fd->fd != -1) {
-        ret = sendfile(io->fd, sfd->fd->fd, &fileoffset, sfd->len);
+        ret = sendfile(st->fd, sfd->fd->fd, &fileoffset, sfd->len);
     } else {
         // TODO: regular copy
         fprintf(stderr, "sendfile not implemented for SYS_FILE\n");
--- a/src/server/util/io.h	Wed May 22 13:27:31 2013 +0200
+++ b/src/server/util/io.h	Wed May 22 15:05:06 2013 +0200
@@ -59,6 +59,8 @@
     int      fd;
     size_t   max_read;
     size_t   rd;
+    int      chunkedenc;
+    int      buffered;
 } NetIOStream;
 
 
@@ -88,10 +90,10 @@
 /* net stream */
 IOStream* net_stream_from_fd(pool_handle_t *pool, int fd);
 
-ssize_t net_stream_write(IOStream *st, void *buf, size_t nbytes);
-ssize_t net_stream_writev(IOStream *st, struct iovec *iovec, int iovcnt);
-ssize_t net_stream_read(IOStream *st, void *buf, size_t nbytes);
-ssize_t net_stream_sendfile(IOStream *st, sendfiledata *sfd);
+ssize_t net_stream_write(NetIOStream *st, void *buf, size_t nbytes);
+ssize_t net_stream_writev(NetIOStream *st, struct iovec *iovec, int iovcnt);
+ssize_t net_stream_read(NetIOStream *st, void *buf, size_t nbytes);
+ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd);
 
 /* iovec buffer */
 iovec_buf_t *iovec_buf_create(pool_handle_t *pool);

mercurial