# HG changeset patch # User Olaf Wintermann # Date 1369227906 -7200 # Node ID 14722c5f8856268f3b28e1847ce097015859d93a # Parent c7f5b062e622208951d9aa45e3119a75982fea81 added chunked transfer encoding diff -r c7f5b062e622 -r 14722c5f8856 src/server/daemon/protocol.c --- 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); diff -r c7f5b062e622 -r 14722c5f8856 src/server/public/nsapi.h --- 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 diff -r c7f5b062e622 -r 14722c5f8856 src/server/public/vfs.h --- 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; diff -r c7f5b062e622 -r 14722c5f8856 src/server/util/io.c --- 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;ifd, 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"); diff -r c7f5b062e622 -r 14722c5f8856 src/server/util/io.h --- 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);