Tue, 27 Dec 2016 17:19:00 +0100
improves event handler and ssl error handling
--- a/src/server/daemon/auth.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/auth.c Tue Dec 27 17:19:00 2016 +0100 @@ -95,9 +95,9 @@ if(e == elm) { break; } - UserCacheElm *n = e->next_user; + UserCacheElm *nu = e->next_user; auth_cache_remove_from_map(e); - e = n; + e = nu; } cache.head = elm->next_user; if(cache.trail == elm) {
--- a/src/server/daemon/config.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/config.c Tue Dec 27 17:19:00 2016 +0100 @@ -775,8 +775,8 @@ conf->objects[i] = obj; // add directives - for(int i=0;i<NUM_NSAPI_TYPES-1;i++) { - UcxList *dirs = cob->directives[i]; + for(int j=0;j<NUM_NSAPI_TYPES-1;j++) { + UcxList *dirs = cob->directives[j]; while(dirs != NULL) { ConfigDirective *cfgdir = dirs->data;
--- a/src/server/daemon/event.h Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/event.h Tue Dec 27 17:19:00 2016 +0100 @@ -35,6 +35,9 @@ #ifdef __cplusplus extern "C" { #endif + +#define EVENT_POLLIN 0x1 +#define EVENT_POLLOUT 0x2 typedef struct event_handler event_handler_t; typedef struct event event_t; @@ -49,6 +52,7 @@ event_func finish; intptr_t object; int events; + int poll; void *cookie; };
--- a/src/server/daemon/event_bsd.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/event_bsd.c Tue Dec 27 17:19:00 2016 +0100 @@ -103,8 +103,10 @@ for(int i=0;i<nev;i++) { event_t *event = (event_t*)events[i].udata; if(event->fn) { + int ep = event->poll; if(event->fn(ev, event)) { - // TODO: reassociate? + // TODO: reassociate? + // TODO: check ep and event->poll } else if(event->finish) { event->finish(ev, event); } @@ -127,12 +129,14 @@ } int ev_pollin(event_handler_t *h, int fd, event_t *event) { + event->poll = EVENT_POLLIN; struct kevent kev; EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, event); return kevent(ev_get_port(h), &kev, 1, NULL, 0, NULL); } int ev_pollout(event_handler_t *h, int fd, event_t *event) { + event->poll = EVENT_POLLOUT; struct kevent kev; EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, event); return kevent(ev_get_port(h), &kev, 1, NULL, 0, NULL);
--- a/src/server/daemon/event_linux.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/event_linux.c Tue Dec 27 17:19:00 2016 +0100 @@ -97,24 +97,49 @@ /* wait for events */ int ret = epoll_wait(ep, events, 16, 100000); if(ret == -1 && errno != EINTR) { - /* TODO: check for error */ - perror("epoll_wait"); + log_ereport(LOG_FAILURE, "epoll_wait failed: %s", strerror(errno)); continue; } for(int i=0;i<ret;i++) { event_t *event = events[i].data.ptr; if(event->fn) { + int saved_ev = event->poll; if(!event->fn(ev, event)) { // event fn returned 0 -> remove event from epoll if(epoll_ctl(ep, EPOLL_CTL_DEL, event->object, NULL)) { - perror("epoll_ctl"); + log_ereport( + LOG_FAILURE, + "epoll_ctl failed: %s", + strerror(errno)); } // if set, execute event->finish if(event->finish) { event->finish(ev, event); } + } else { + if(saved_ev != event->poll) { + // event type changed + struct epoll_event epev; + epev.events = EPOLLET; + epev.data.ptr = event; + + // adjust epoll events + if((event->poll & EVENT_POLLIN) == EVENT_POLLIN) { + epev.events |= EPOLLIN; + } + if((event->poll & EVENT_POLLOUT) == EVENT_POLLOUT) { + epev.events |= EPOLLOUT; + } + + if(epoll_ctl(ep, EPOLL_CTL_MOD, event->object, NULL)) { + log_ereport( + LOG_FAILURE, + "epoll_wait failed: %s", + strerror(errno)); + } + } } } } @@ -136,23 +161,25 @@ int ev_pollin(event_handler_t *h, int fd, event_t *event) { event->object = (intptr_t)fd; + event->poll = EVENT_POLLIN; struct epoll_event epev; - epev.events = EPOLLIN | EPOLLET; /* input event, edge triggered */ + epev.events = EPOLLIN | EPOLLET; // input event, edge triggered epev.data.ptr = event; return epoll_ctl(ev_get_port(h), EPOLL_CTL_ADD, fd, &epev); } int ev_pollout(event_handler_t *h, int fd, event_t *event) { event->object = (intptr_t)fd; + event->poll = EVENT_POLLOUT; struct epoll_event epev; - epev.events = EPOLLOUT | EPOLLET; /* input event, edge triggered */ + epev.events = EPOLLOUT | EPOLLET; // input event, edge triggered epev.data.ptr = event; return epoll_ctl(ev_get_port(h), EPOLL_CTL_ADD, fd, &epev); } int evt_send(event_handler_t *h, event_t *event) { event->object = 0; - // TODO: implement using threadpool + // TODO: implement using threadpool or eventfd fprintf(stderr, "Warning: evt_send not implemented\n"); return 0; }
--- a/src/server/daemon/event_solaris.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/event_solaris.c Tue Dec 27 17:19:00 2016 +0100 @@ -100,15 +100,28 @@ for(int i=0;i<nev;i++) { event_t *event = events[i].portev_user; if(event->fn) { + int saved_ev = event->poll; if(event->fn(ev, event)) { /* * on solaris we have to reassociate the fd after * each event * we do this if the event function returns 1 */ - if(ev_poll(ev, event)) { - perror("port_associate"); - } + + if(event->poll != saved_ev) { + // event type changed + int ne = 0; + if((event->poll & EVENT_POLLIN) == EVENT_POLLIN) { + ne |= POLLIN; + } + if((event->poll & EVENT_POLLOUT) == EVENT_POLLOUT) { + ne |= POLLOUT; + } + } + + if(ev_poll(ev, event)) { + perror("port_associate"); + } } else if(event->finish) { event->finish(ev, event); } @@ -133,6 +146,7 @@ int ev_pollin(event_handler_t *h, int fd, event_t *event) { event->object = (intptr_t)fd; event->events = POLLIN; + event->poll = EVENT_POLLIN; return port_associate( ev_get_port(h), PORT_SOURCE_FD, @@ -144,6 +158,7 @@ int ev_pollout(event_handler_t *h, int fd, event_t *event) { event->object = (intptr_t)fd; event->events = POLLOUT; + event->poll EVENT_POLLOUT; return port_associate( ev_get_port(h), PORT_SOURCE_FD,
--- a/src/server/daemon/httplistener.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/httplistener.c Tue Dec 27 17:19:00 2016 +0100 @@ -248,7 +248,7 @@ } } else { file = sstrdup(conf->chainfile); - int ret = SSL_CTX_use_certificate_chain_file(ctx, file.ptr); + ret = SSL_CTX_use_certificate_chain_file(ctx, file.ptr); free(file.ptr); if(!ret) { ERR_error_string(ERR_get_error(), errbuf);
--- a/src/server/daemon/httprequest.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/httprequest.c Tue Dec 27 17:19:00 2016 +0100 @@ -264,9 +264,9 @@ } // change to lower case - for(int i=0;i<header.name.length;i++) { - if(header.name.ptr[i] > 64 && header.name.ptr[i] < 97) { - header.name.ptr[i] += 32; + for(int j=0;j<header.name.length;j++) { + if(header.name.ptr[j] > 64 && header.name.ptr[j] < 97) { + header.name.ptr[j] += 32; } }
--- a/src/server/daemon/keyfile_auth.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/keyfile_auth.c Tue Dec 27 17:19:00 2016 +0100 @@ -57,8 +57,8 @@ UCX_MAP_FOREACH(key, user, i) { free(user->user.name); free(user->hash); - for(int i=0;i<user->numgroups;i++) { - free(user->groups[i].ptr); + for(int n=0;n<user->numgroups;n++) { + free(user->groups[n].ptr); } free(user->groups); }
--- a/src/server/daemon/sessionhandler.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/sessionhandler.c Tue Dec 27 17:19:00 2016 +0100 @@ -60,7 +60,7 @@ int connection_ssl_read(Connection *conn, void *buf, int len) { int ret = SSL_read(conn->ssl, buf, len); if(ret <= 0) { - conn->ssl_error = ERR_get_error(); + conn->ssl_error = SSL_get_error(conn->ssl, ret); } return ret; } @@ -68,13 +68,17 @@ int connection_ssl_write(Connection *conn, const void *buf, int len) { int ret = SSL_write(conn->ssl, buf, len); if(ret <= 0) { - conn->ssl_error = ERR_get_error(); + conn->ssl_error = SSL_get_error(conn->ssl, ret); } return ret; } void connection_ssl_close(Connection *conn) { - SSL_shutdown(conn->ssl); + int ret = SSL_shutdown(conn->ssl); + if(ret != 1) { + conn->ssl_error = SSL_get_error(conn->ssl, ret); + log_ereport(LOG_VERBOSE, "SSL_shutdown failed: %d", conn->ssl_error); + } close(conn->fd); } @@ -222,8 +226,8 @@ if(ev_pollin(ev, conn->fd, event) != 0) { // TODO: ev_pollin should log, intercept some errors here - log_ereport(LOG_WARN, "ev_pollin failed: %s", strerror(errno)); - close(conn->fd); + log_ereport(LOG_FAILURE, "Cannot enqueue connection"); + connection_destroy(conn); // TODO: free stuff } } @@ -242,6 +246,20 @@ buf->inbuf + buf->pos, buf->maxsize - buf->pos); if(r <= 0) { + if(conn->ssl) { + // SSL specific error handling + switch(conn->ssl_error) { + case SSL_ERROR_WANT_READ: { + event->poll = EVENT_POLLIN; + return 1; + } + case SSL_ERROR_WANT_WRITE: { + event->poll = EVENT_POLLOUT; + return 1; + } + } + } + event->finish = evt_request_error; return 0; } @@ -260,6 +278,7 @@ * we need more data -> return 1 to tell the event handler to * continue polling */ + event->poll = EVENT_POLLIN; return 1; }
--- a/src/server/daemon/sessionhandler.h Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/sessionhandler.h Tue Dec 27 17:19:00 2016 +0100 @@ -50,7 +50,7 @@ HttpListener *listener; SessionHandler *session_handler; SSL *ssl; - long ssl_error; + int ssl_error; int (*read)(Connection *conn, void *buf, int len); int (*write)(Connection *conn, const void *buf, int len); void (*close)(Connection *conn);
--- a/src/server/daemon/webserver.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/daemon/webserver.c Tue Dec 27 17:19:00 2016 +0100 @@ -126,13 +126,11 @@ vars->Vuserpw = NULL; } } - free(pwbuf); if(!vars->Vuserpw) { log_ereport(LOG_WARN, "globalvars->Vuserpw is null"); } if(cfg->user.ptr) { - char *pwbuf = malloc(DEF_PWBUF); vars->Vuserpw = malloc(sizeof(struct passwd)); // open user database //setpwent(); @@ -144,9 +142,9 @@ free(vars->Vuserpw); vars->Vuserpw = NULL; } - free(pwbuf); //endpwent(); // TODO: close or not? } + free(pwbuf); // change uid if(vars->Vuserpw && ws_uid == 0) {
--- a/src/server/safs/cgi.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/safs/cgi.c Tue Dec 27 17:19:00 2016 +0100 @@ -113,7 +113,7 @@ while((r = read(cgip.out[0], buf, 4096)) > 0) { if(cgiheader) { size_t pos; - int ret = cgi_parse_response(parser, buf, r, &pos); + ret = cgi_parse_response(parser, buf, r, &pos); if(ret == -1) { protocol_status(sn, rq, 500, NULL); result = REQ_ABORTED; @@ -259,22 +259,22 @@ if(!sstrcmp(name, S("status"))) { sstr_t codestr = value; - int i; - for(i=0;i<codestr.length;i++) { - if(!isdigit(codestr.ptr[i])) { + int j; + for(j=0;j<codestr.length;j++) { + if(!isdigit(codestr.ptr[j])) { break; } - if(i > 2) { + if(j > 2) { break; } } - codestr.ptr[i] = '\0'; + codestr.ptr[j] = '\0'; int64_t s = 0; util_strtoint(codestr.ptr, &s); parser->status = (int)s; - sstr_t msg = sstrtrim(sstrsubs(value, i + 1)); + sstr_t msg = sstrtrim(sstrsubs(value, j + 1)); if(msg.length > 0) { parser->msg = sstrdup_pool(parser->sn->pool, msg).ptr;
--- a/src/server/util/io.c Tue Dec 27 14:02:28 2016 +0100 +++ b/src/server/util/io.c Tue Dec 27 17:19:00 2016 +0100 @@ -283,11 +283,16 @@ SSLStream *st = pool_malloc(pool, sizeof(SSLStream)); st->st = ssl_io_funcs; st->ssl = ssl; + st->error = 0; return (IOStream*)st; } ssize_t net_ssl_write(SSLStream *st, void *buf, size_t nbytes) { - return SSL_write(st->ssl, buf, nbytes); + int ret = SSL_write(st->ssl, buf, nbytes); + if(ret <= 0) { + st->error = SSL_get_error(st->ssl, ret); + } + return ret; } ssize_t net_ssl_writev(SSLStream *st, struct iovec *iovec, int iovcnt) { @@ -295,6 +300,7 @@ for(int i=0;i<iovcnt;i++) { int ret = SSL_write(st->ssl, iovec[i].iov_base, iovec[i].iov_len); if(ret <= 0) { + st->error = SSL_get_error(st->ssl, ret); return 0; } r += ret; @@ -303,11 +309,18 @@ } ssize_t net_ssl_read(SSLStream *st, void *buf, size_t nbytes) { - return SSL_read(st->ssl, buf, nbytes); + int ret = SSL_read(st->ssl, buf, nbytes); + if(ret <= 0) { + st->error = SSL_get_error(st->ssl, ret); + } + return ret; } void net_ssl_close(SSLStream *st) { - SSL_shutdown(st->ssl); + int ret = SSL_shutdown(st->ssl); + if(ret != 1) { + st->error = SSL_get_error(st->ssl, ret); + } close(SSL_get_fd(st->ssl)); }