Tue, 10 Nov 2015 21:11:06 +0100
refactored IO system
--- a/src/server/daemon/httprequest.c Sat Oct 31 20:10:21 2015 +0100 +++ b/src/server/daemon/httprequest.c Tue Nov 10 21:11:06 2015 +0100 @@ -109,11 +109,13 @@ sn->sn.pool = pool; //sn->sn.csd = stream_new_from_fd(pool, request->connection->fd); //sn->sn.csd = net_stream_from_fd(pool, request->connection->fd); + IOStream *io; if(request->connection->ssl) { - sn->sn.csd = net_ssl_stream(pool, request->connection->ssl); + io = sslstream_new(pool, request->connection->ssl); } else { - sn->sn.csd = net_stream_from_fd(pool, request->connection->fd); + io = sysstream_new(pool, request->connection->fd); } + sn->sn.csd = httpstream_new(pool, io); sn->sn.client = pblock_create_pool(sn->sn.pool, 8); @@ -295,9 +297,7 @@ netbuf *nb = request->netbuf; // create new netbuf - NetIOStream *net_io = (NetIOStream*)net_stream_from_fd( - pool, - request->connection->fd); + HttpStream *net_io = (HttpStream*)httpstream_new(pool, io); net_io->max_read = ctlen; sn->sn.inbuf = pool_malloc(pool, sizeof(netbuf));
--- a/src/server/daemon/protocol.c Sat Oct 31 20:10:21 2015 +0100 +++ b/src/server/daemon/protocol.c Tue Nov 10 21:11:06 2015 +0100 @@ -342,7 +342,7 @@ } // set stream property - NetIOStream *stream = (NetIOStream*)sn->csd; + HttpStream *stream = (HttpStream*)sn->csd; stream->chunked_enc = 1; rq->rq_attr.chunked = 1; }
--- a/src/server/public/nsapi.h Sat Oct 31 20:10:21 2015 +0100 +++ b/src/server/public/nsapi.h Tue Nov 10 21:11:06 2015 +0100 @@ -1232,6 +1232,7 @@ ssize_t net_sendfile(SYS_NETFD fd, sendfiledata *sfd); ssize_t net_read(SYS_NETFD fd, void *buf, size_t nbytes); int net_flush(SYS_NETFD sd); +void net_close(SYS_NETFD fd); // NSAPI extension ssize_t net_printf(SYS_NETFD fd, char *format, ...);
--- a/src/server/util/io.c Sat Oct 31 20:10:21 2015 +0100 +++ b/src/server/util/io.c Tue Nov 10 21:11:06 2015 +0100 @@ -37,28 +37,28 @@ #ifndef BSD #include <sys/sendfile.h> #endif -#include <limits.h> /* asprintf */ #include "../daemon/vfs.h" #include "io.h" #include "pool.h" +#include "ucx/utils.h" IOStream native_io_funcs = { - system_write, - system_writev, - system_read, - NULL, - NULL, + (io_write_f)net_sys_write, + (io_writev_f)net_sys_writev, + (io_read_f)net_sys_read, + (io_sendfile_f)net_sys_sendfile, + (io_close_f)net_sys_close, NULL }; -IOStream net_io_funcs = { - (io_write_f)net_stream_write, - (io_writev_f)net_stream_writev, - (io_read_f)net_stream_read, - (io_sendfile_f)net_stream_sendfile, - (io_close_f)net_stream_close, - (io_finish_f)net_stream_finish +IOStream http_io_funcs = { + (io_write_f)net_http_write, + (io_writev_f)net_http_writev, + (io_read_f)net_http_read, + (io_sendfile_f)net_http_sendfile, + (io_close_f)net_http_close, + (io_finish_f)net_http_finish }; IOStream ssl_io_funcs = { @@ -71,81 +71,31 @@ }; -IOStream* stream_new_from_fd(pool_handle_t *pool, int fd) { - SystemIOStream *st = pool_malloc(pool, sizeof(SystemIOStream)); +/* + * SysStream implementation + */ + +IOStream* sysstream_new(pool_handle_t *pool, int fd) { + SysStream *st = pool_malloc(pool, sizeof(SysStream)); st->st = native_io_funcs; st->fd = fd; return (IOStream*)st; } -ssize_t system_write(IOStream *st, void *buf, size_t nbytes) { - return write(((SystemIOStream*)st)->fd, buf, nbytes); -} - -ssize_t system_writev(IOStream *st, struct iovec *iovec, int iovcnt) { - return writev(((SystemIOStream*)st)->fd, iovec, iovcnt); -} - -ssize_t system_read(IOStream *st, void *buf, size_t nbytes) { - return read(((SystemIOStream*)st)->fd, buf, nbytes); -} - - -IOStream* net_stream_from_fd(pool_handle_t *pool, int fd) { - NetIOStream *st = pool_malloc(pool, sizeof(NetIOStream)); - st->st = net_io_funcs; - st->fd = fd; - st->max_read = 0; - st->read = 0; - st->chunked_enc = 0; - st->buffered = 0; - return (IOStream*)st; +#ifdef XP_UNIX +ssize_t net_sys_write(SysStream *st, void *buf, size_t nbytes) { + return write(st->fd, buf, nbytes); } -ssize_t net_stream_write(NetIOStream *st, void *buf, size_t nbytes) { - if(st->chunked_enc) { - // 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, "\r\n%zx\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_sys_writev(SysStream *st, struct iovec *iovec, int iovcnt) { + return writev(st->fd, iovec, iovcnt); } -ssize_t net_stream_writev(NetIOStream *st, struct iovec *iovec, int iovcnt) { - if(st->chunked_enc) { - 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, "\r\n%zx\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_sys_read(SysStream *st, void *buf, size_t nbytes) { + return read(st->fd, buf, nbytes); } -ssize_t net_stream_read(NetIOStream *st, void *buf, size_t nbytes) { - if(st->max_read != 0 && st->read >= st->max_read) { - return 0; - } - ssize_t r = read(st->fd, buf, nbytes); - st->read += r; - return r; -} - -ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) { +ssize_t net_sys_sendfile(SysStream *st, sendfiledata *sfd) { ssize_t ret = 0; off_t fileoffset = sfd->offset; if(sfd->fd->fd != -1) { @@ -192,19 +142,130 @@ return ret; } -void net_stream_close(NetIOStream *st) { +void net_sys_close(SysStream *st) { close(st->fd); } -void net_stream_finish(NetIOStream *st) { +#elif defined(XP_WIN32) + +ssize_t net_sys_write(SysStream *st, void *buf, size_t nbytes) { + int ret = send(st->socket, buf, nbytes, 0); + if(ret == SOCKET_ERROR) { + return IO_ERROR; + } + return ret; +} + +ssize_t net_sys_writev(SysStream *st, struct iovec *iovec, int iovcnt) { + // TODO +} + +ssize_t net_sys_read(SysStream *st, void *buf, size_t nbytes) { + int ret = recv(st->socket, buf, nbytes, 0); + if(ret == SOCKET_ERROR) { + return IO_ERROR; + } + return ret; +} + +ssize_t net_sys_sendfile(SysStream *st, sendfiledata *sfd) { + // TODO +} + +void net_sys_close(SysStream *st) { + closesocket(st->socket); +} + +#endif + + +/* + * HttpStream implementation + */ + +IOStream* httpstream_new(pool_handle_t *pool, IOStream *fd) { + HttpStream *st = pool_malloc(pool, sizeof(HttpStream)); + st->st = http_io_funcs; + st->fd = fd; + st->max_read = 0; + st->read = 0; + st->chunked_enc = WS_FALSE; + st->buffered = WS_FALSE; + return (IOStream*)st; +} + +ssize_t net_http_write(HttpStream *st, void *buf, size_t nbytes) { + IOStream *fd = st->fd; if(st->chunked_enc) { - write(st->fd, "0\r\n\r\n", 5); + // 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, "\r\n%zx\r\n", nbytes); + io[1].iov_base = buf; + io[1].iov_len = nbytes; + ssize_t r = fd->writev(fd, io, 2); + return r - io[0].iov_len; + } else { + return fd->write(fd, buf, nbytes); + } +} + +ssize_t net_http_writev(HttpStream *st, struct iovec *iovec, int iovcnt) { + IOStream *fd = st->fd; + if(st->chunked_enc) { + 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, "\r\n%zx\r\n", len); + memcpy(io + 1, iovec, iovcnt * sizeof(struct iovec)); + ssize_t r = fd->writev(fd, io, iovcnt + 1); + return r - io[0].iov_len; + } else { + return fd->writev(fd, iovec, iovcnt); + } +} + +ssize_t net_http_read(HttpStream *st, void *buf, size_t nbytes) { + if(st->max_read != 0 && st->read >= st->max_read) { + return 0; + } + ssize_t r = st->fd->read(st->fd, buf, nbytes); + st->read += r; + return r; +} + +ssize_t net_http_sendfile(HttpStream *st, sendfiledata *sfd) { + ssize_t ret = 0; + if(st->fd->sendfile) { + ret = st->fd->sendfile(st->fd, sfd); + } else { + + } + + return ret; +} + +void net_http_close(HttpStream *st) { + st->fd->close(st->fd); +} + +void net_http_finish(HttpStream *st) { + if(st->chunked_enc) { + st->fd->write(st->fd, "0\r\n\r\n", 5); } } -/* ssl stream */ -IOStream* net_ssl_stream(pool_handle_t *pool, SSL *ssl) { +/* + * SSLStream implementation + */ + +IOStream* sslstream_new(pool_handle_t *pool, SSL *ssl) { SSLStream *st = pool_malloc(pool, sizeof(SSLStream)); st->st = ssl_io_funcs; st->ssl = ssl; @@ -241,6 +302,8 @@ } +/* -------------------- public nsapi network functions -------------------- */ + ssize_t net_read(SYS_NETFD fd, void *buf, size_t nbytes) { ssize_t r = ((IOStream*)fd)->read(fd, buf, nbytes); if(r == 0) { @@ -268,85 +331,89 @@ ssize_t net_printf(SYS_NETFD fd, char *format, ...) { va_list arg; va_start(arg, format); - char *buf; - ssize_t len = vasprintf(&buf, format, arg); - ssize_t r = net_write(fd, buf, len); - free(buf); + sstr_t buf = ucx_vasprintf(ucx_default_allocator(), format, arg); + ssize_t r = net_write(fd, buf.ptr, buf.length); + free(buf.ptr); return r; } ssize_t net_sendfile(SYS_NETFD fd, sendfiledata *sfd) { - NetIOStream *out = fd; - if(out->st.sendfile && sfd->fd && sfd->fd->fd != -1) { - ssize_t r = ((IOStream*)fd)->sendfile(fd, sfd); + IOStream *out = fd; + if(out->sendfile && sfd->fd && sfd->fd->fd != -1) { + ssize_t r = out->sendfile(fd, sfd); if(r < 0) { return IO_ERROR; } } else { // stream/file does not support sendfile // do regular copy - char *buf = malloc(4096); - if(!buf) { - // TODO: out of memory error - return IO_ERROR; - } - char *header = (char*)sfd->header; - int hlen = sfd->hlen; - char *trailer = (char*)sfd->trailer; - int tlen = sfd->tlen; - if(header == NULL) { - hlen = 0; - } - if(trailer == NULL) { - tlen = 0; - } - - ssize_t r; - while(hlen > 0) { - r = out->st.write(fd, header, hlen); - header += r; - hlen -= r; - if(r <= 0) { - free(buf); - return IO_ERROR; - } - } - - if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) { + return net_copy_file(out, sfd); + } + return IO_ERROR; +} + +// private +ssize_t net_copy_file(IOStream *fd, sendfiledata *sfd) { + char *buf = malloc(4096); + if(!buf) { + // TODO: out of memory error + return IO_ERROR; + } + char *header = (char*)sfd->header; + int hlen = sfd->hlen; + char *trailer = (char*)sfd->trailer; + int tlen = sfd->tlen; + if(header == NULL) { + hlen = 0; + } + if(trailer == NULL) { + tlen = 0; + } + + ssize_t r; + while(hlen > 0) { + r = fd->write(fd, header, hlen); + header += r; + hlen -= r; + if(r <= 0) { free(buf); return IO_ERROR; } - - size_t length = sfd->len; - while(length > 0) { - if((r = system_fread(sfd->fd, buf, 4096)) <= 0) { - break; - } - char *write_buf = buf; - while(r > 0) { - ssize_t w = out->st.write(fd, write_buf, r); - r -= w; - length -= w; - write_buf += w; - } + } + + if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) { + free(buf); + return IO_ERROR; + } + + size_t length = sfd->len; + while(length > 0) { + if((r = system_fread(sfd->fd, buf, 4096)) <= 0) { + break; } - free(buf); - if(length > 0) { + char *write_buf = buf; + while(r > 0) { + ssize_t w = fd->write(fd, write_buf, r); + r -= w; + length -= w; + write_buf += w; + } + } + free(buf); + if(length > 0) { + return IO_ERROR; + } + + while(tlen > 0) { + r = fd->write(fd, trailer, tlen); + trailer += r; + tlen -= r; + if(r <= 0) { return IO_ERROR; } - - while(tlen > 0) { - r = out->st.write(fd, trailer, tlen); - trailer += r; - tlen -= r; - if(r <= 0) { - return IO_ERROR; - } - } - - return sfd->hlen + sfd->len + sfd->tlen; } - return IO_ERROR; + + return sfd->hlen + sfd->len + sfd->tlen; } int net_flush(SYS_NETFD sd) { @@ -358,136 +425,7 @@ ((IOStream*)fd)->close(fd); } +// private void net_finish(SYS_NETFD fd) { ((IOStream*)fd)->finish(fd); } - - -/* iovec buffer */ -iovec_buf_t *iovec_buf_create(pool_handle_t *pool) { - iovec_buf_t *buf = pool_malloc(pool, sizeof(iovec_buf_t)); - - buf->pool = pool; - buf->iov = pool_calloc(pool, 32, sizeof(struct iovec)); - buf->maxiovec = 32; - buf->iovctn = 0; - - return buf; -} - -void iovec_buf_write(iovec_buf_t *io, void *buf, size_t nbyte) { - if(io->iovctn >= io->maxiovec) { - io->iov = pool_realloc( - io->pool, - io->iov, - (io->maxiovec + 16) * sizeof(struct iovec)); - } - - io->iov[io->iovctn].iov_base = buf; - io->iov[io->iovctn].iov_len = nbyte; - io->iovctn++; -} - -ssize_t iovec_buf_flush(iovec_buf_t *io, int fd) { - return writev(fd, io->iov, io->iovctn); -} - - -/* TODO: add asprintf to new file */ - -/* - * asprintf implementation for Solaris 10 - * source from OpenSolaris - * file: /onnv/onnv-gate/usr/src/lib/libc/port/print/asprintf.c - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Copyright (c) 2004 Darren Tucker. - * - * Based originally on asprintf.c from OpenBSD: - * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef __SunOS_5_10 - -#define INIT_SZ 128 - -/* VARARGS2 */ -int -vasprintf(char **str, const char *format, va_list ap) -{ - char string[INIT_SZ]; - char *newstr; - int ret; - size_t len; - - *str = NULL; - ret = vsnprintf(string, INIT_SZ, format, ap); - if (ret < 0) /* retain the value of errno from vsnprintf() */ - return (-1); - if (ret < INIT_SZ) { - len = ret + 1; - if ((newstr = malloc(len)) == NULL) - return (-1); /* retain errno from malloc() */ - (void) strlcpy(newstr, string, len); - *str = newstr; - return (ret); - } - /* - * We will perform this loop more than once only if some other - * thread modifies one of the vasprintf() arguments after our - * previous call to vsnprintf(). - */ - for (;;) { - if (ret == INT_MAX) { /* Bad length */ - errno = ENOMEM; - return (-1); - } - len = ret + 1; - if ((newstr = malloc(len)) == NULL) - return (-1); /* retain errno from malloc() */ - ret = vsnprintf(newstr, len, format, ap); - if (ret < 0) { /* retain errno from vsnprintf() */ - free(newstr); - return (-1); - } - if (ret < len) { - *str = newstr; - return (ret); - } - free(newstr); - } -} - -int -asprintf(char **str, const char *format, ...) -{ - va_list ap; - int ret; - - *str = NULL; - va_start(ap, format); - ret = vasprintf(str, format, ap); - va_end(ap); - - return (ret); -} - -#endif
--- a/src/server/util/io.h Sat Oct 31 20:10:21 2015 +0100 +++ b/src/server/util/io.h Tue Nov 10 21:11:06 2015 +0100 @@ -30,14 +30,21 @@ #define IOSTREAM_H #include <openssl/ssl.h> +#include "../public/nsapi.h" +#include "systems.h" -#include "../public/nsapi.h" +#ifdef _WIN32 +#include <windows.h> +#include <winsock2.h> +#endif #ifdef __cplusplus extern "C" { #endif -typedef struct io_stream IOStream; +typedef struct IOStream IOStream; +typedef struct SysStream SysStream; +typedef struct HttpStream HttpStream; typedef ssize_t(*io_write_f)(IOStream *, void *, size_t); typedef ssize_t(*io_writev_f)(IOStream *, struct iovec *, int); @@ -46,7 +53,7 @@ typedef void(*io_close_f)(IOStream *); typedef void(*io_finish_f)(IOStream *); -struct io_stream { +struct IOStream { io_write_f write; io_writev_f writev; io_read_f read; @@ -55,19 +62,23 @@ io_finish_f finish; }; -typedef struct SystemIOStream { - IOStream st; - int fd; -} SystemIOStream; - -typedef struct NetIOStream { +struct SysStream { IOStream st; +#ifdef XP_UNIX int fd; - size_t max_read; - size_t read; - int chunked_enc; - int buffered; -} NetIOStream; +#elif defined(XP_WIN32) + SOCKET socket; +#endif +}; + +struct HttpStream { + IOStream st; + IOStream *fd; + uint64_t max_read; + uint64_t read; + WSBool chunked_enc; + WSBool buffered; +}; typedef struct SSLStream { IOStream st; @@ -75,42 +86,28 @@ } SSLStream; -/* net_ functions */ -ssize_t net_read(SYS_NETFD fd, void *buf, size_t nbytes); -ssize_t net_write(SYS_NETFD fd, void *buf, size_t nbytes); -ssize_t net_printf(SYS_NETFD fd, char *format, ...); -ssize_t net_sendfile(SYS_NETFD fd, sendfiledata *sfd); -void net_close(SYS_NETFD fd); -void net_finish(SYS_NETFD fd); - -/* iovec buffer */ -typedef struct iovec_buf{ - struct iovec *iov; - int iovctn; - int maxiovec; - pool_handle_t *pool; -} iovec_buf_t; - /* system stream */ -IOStream* stream_new_from_fd(pool_handle_t *pool, int fd); +IOStream* sysstream_new(pool_handle_t *pool, int fd); -ssize_t system_write(IOStream *st, void *buf, size_t nbytes); -ssize_t system_writev(IOStream *st, struct iovec *iovec, int iovcnt); -ssize_t system_read(IOStream *st, void *buf, size_t nbytes); +ssize_t net_sys_write(SysStream *st, void *buf, size_t nbytes); +ssize_t net_sys_writev(SysStream *st, struct iovec *iovec, int iovcnt); +ssize_t net_sys_read(SysStream *st, void *buf, size_t nbytes); +ssize_t net_sys_sendfile(SysStream *st, sendfiledata *sfd); +void net_sys_close(SysStream *st); -/* net stream */ -IOStream* net_stream_from_fd(pool_handle_t *pool, int fd); +/* http stream */ +IOStream* httpstream_new(pool_handle_t *pool, IOStream *fd); -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); -void net_stream_close(NetIOStream *st); -void net_stream_finish(NetIOStream *st); +ssize_t net_http_write(HttpStream *st, void *buf, size_t nbytes); +ssize_t net_http_writev(HttpStream *st, struct iovec *iovec, int iovcnt); +ssize_t net_http_read(HttpStream *st, void *buf, size_t nbytes); +ssize_t net_http_sendfile(HttpStream *st, sendfiledata *sfd); +void net_http_close(HttpStream *st); +void net_http_finish(HttpStream *st); /* ssl stream */ -IOStream* net_ssl_stream(pool_handle_t *pool, SSL *ssl); +IOStream* sslstream_new(pool_handle_t *pool, SSL *ssl); ssize_t net_ssl_write(SSLStream *st, void *buf, size_t nbytes); ssize_t net_ssl_writev(SSLStream *st, struct iovec *iovec, int iovcnt); @@ -118,19 +115,9 @@ void net_ssl_close(SSLStream *st); void net_ssl_finish(SSLStream *st); -/* iovec buffer */ -iovec_buf_t *iovec_buf_create(pool_handle_t *pool); -void iovec_buf_write(iovec_buf_t *io, void *buf, size_t nbyte); -ssize_t iovec_buf_flush(iovec_buf_t *io, int fd); - - - -#ifdef __SunOS_5_10 - -int vasprintf(char **str, const char *format, va_list ap); -int asprintf(char **str, const char *format, ...); - -#endif +/* net_ functions */ +ssize_t net_copy_file(IOStream *fd, sendfiledata *sfd); +void net_finish(SYS_NETFD fd); #ifdef __cplusplus }