diff -r 8a0a7754f123 -r 43a746e905f6 src/server/util/io.c --- 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 #endif -#include /* 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;ifd, 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;iwritev(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 - * - * 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