--- a/src/server/util/io.c Sat Feb 04 16:42:11 2017 +0100 +++ b/src/server/util/io.c Sat Feb 18 13:27:25 2017 +0100 @@ -64,6 +64,7 @@ #include "../daemon/vfs.h" #include "io.h" #include "pool.h" +#include "../daemon/event.h" #include "ucx/utils.h" IOStream native_io_funcs = { @@ -72,7 +73,10 @@ (io_read_f)net_sys_read, (io_sendfile_f)NET_SYS_SENDFILE, (io_close_f)net_sys_close, - NULL + NULL, + (io_setmode_f)net_sys_setmode, + (io_poll_f)net_sys_poll, + 0 }; IOStream http_io_funcs = { @@ -81,7 +85,10 @@ (io_read_f)net_http_read, (io_sendfile_f)net_http_sendfile, (io_close_f)net_http_close, - (io_finish_f)net_http_finish + (io_finish_f)net_http_finish, + (io_setmode_f)net_http_setmode, + (io_poll_f)net_http_poll, + 0 }; IOStream ssl_io_funcs = { @@ -90,7 +97,10 @@ (io_read_f)net_ssl_read, NULL, (io_close_f)net_ssl_close, - (io_finish_f)net_ssl_finish + (io_finish_f)net_ssl_finish, + (io_setmode_f)net_ssl_setmode, + (io_poll_f)net_ssl_poll, + 0 }; @@ -170,6 +180,34 @@ close(st->fd); } +void net_sys_setmode(SysStream *st, int mode) { + int flags; + if (-1 == (flags = fcntl(st->fd, F_GETFL, 0))) { + flags = 0; + } + if(mode == IO_MODE_BLOCKING) { + if (fcntl(st->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { + perror("fcntl"); + // TODO: error + } + } else if(mode == IO_MODE_NONBLOCKING) { + if (fcntl(st->fd, F_SETFL, flags | O_NONBLOCK) != 0) { + perror("fcntl"); + // TODO: error + } + } +} + +int net_sys_poll(SysStream *st, EventHandler *ev, int events, Event *cb) { + switch(events) { + default: return -1; + case IO_POLL_NONE: return ev_remove_poll(ev, st->fd); + case IO_POLL_IN: return ev_pollin(ev, st->fd, cb); + case IO_POLL_OUT: return ev_pollout(ev, st->fd, cb); + case IO_POLL_IN | IO_POLL_OUT: return -1; // TODO: implement + } +} + #elif defined(XP_WIN32) ssize_t net_sys_write(SysStream *st, void *buf, size_t nbytes) { @@ -287,6 +325,14 @@ } } +void net_http_setmode(HttpStream *st, int mode) { + st->fd->setmode(st->fd, mode); +} + +int net_http_poll(HttpStream *st, EventHandler *ev, int events, Event *cb) { + return st->fd->poll(st->fd, ev, events, cb); +} + /* * SSLStream implementation @@ -341,6 +387,34 @@ } +void net_ssl_setmode(SSLStream *st, int mode) { + int flags; + if (-1 == (flags = fcntl(SSL_get_fd(st->ssl), F_GETFL, 0))) { + flags = 0; + } + if(mode == IO_MODE_BLOCKING) { + if (fcntl(SSL_get_fd(st->ssl), F_SETFL, flags & ~O_NONBLOCK) != 0) { + perror("fcntl"); + // TODO: error + } + } else if(mode == IO_MODE_NONBLOCKING) { + if (fcntl(SSL_get_fd(st->ssl), F_SETFL, flags | O_NONBLOCK) != 0) { + perror("fcntl"); + // TODO: error + } + } +} + +int net_ssl_poll(SSLStream *st, EventHandler *ev, int events, Event *cb) { + int fd = SSL_get_fd(st->ssl); + switch(events) { + default: return -1; + case IO_POLL_NONE: return ev_remove_poll(ev, fd); + case IO_POLL_IN: return ev_pollin(ev, fd, cb); + case IO_POLL_OUT: return ev_pollout(ev, fd, cb); + case IO_POLL_IN | IO_POLL_OUT: return -1; // TODO: implement + } +} /* -------------------- public nsapi network functions -------------------- */ @@ -348,6 +422,9 @@ ssize_t r = ((IOStream*)fd)->read(fd, buf, nbytes); if(r == 0) { return IO_EOF; + } else if(r < 0) { + ((IOStream*)fd)->io_errno = errno; + return IO_ERROR; } return r; } @@ -355,6 +432,7 @@ ssize_t net_write(SYS_NETFD fd, void *buf, size_t nbytes) { ssize_t r = ((IOStream*)fd)->write(fd, buf, nbytes); if(r < 0) { + ((IOStream*)fd)->io_errno = errno; return IO_ERROR; } return r; @@ -363,6 +441,7 @@ ssize_t net_writev(SYS_NETFD fd, struct iovec *iovec, int iovcnt) { ssize_t r = ((IOStream*)fd)->writev(fd, iovec, iovcnt); if(r < 0) { + ((IOStream*)fd)->io_errno = errno; return IO_ERROR; } return r; @@ -375,6 +454,9 @@ ssize_t r = net_write(fd, buf.ptr, buf.length); free(buf.ptr); va_end(arg); + if(r < 0) { + ((IOStream*)fd)->io_errno = errno; + } return r; } @@ -383,14 +465,15 @@ if(out->sendfile && sfd->fd && sfd->fd->fd != -1) { ssize_t r = out->sendfile(fd, sfd); if(r < 0) { + out->io_errno = errno; return IO_ERROR; } + return r; } else { // stream/file does not support sendfile // do regular copy return net_fallback_sendfile(out, sfd); } - return IO_ERROR; } // private @@ -418,12 +501,14 @@ hlen -= r; if(r <= 0) { free(buf); + fd->io_errno = errno; return IO_ERROR; } } if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) { free(buf); + fd->io_errno = errno; return IO_ERROR; } @@ -442,6 +527,7 @@ } free(buf); if(length > 0) { + fd->io_errno = errno; return IO_ERROR; } @@ -450,6 +536,7 @@ trailer += r; tlen -= r; if(r <= 0) { + fd->io_errno = errno; return IO_ERROR; } } @@ -466,6 +553,17 @@ ((IOStream*)fd)->close(fd); } +int net_setnonblock(SYS_NETFD fd, int nonblock) { + ((IOStream*)fd)->setmode( + fd, + nonblock ? IO_MODE_NONBLOCKING : IO_MODE_BLOCKING); + return 0; +} + +int net_errno(SYS_NETFD fd) { + return ((IOStream*)fd)->io_errno; +} + // private void net_finish(SYS_NETFD fd) { ((IOStream*)fd)->finish(fd);