improves event handler and ssl error handling

Tue, 27 Dec 2016 17:19:00 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 27 Dec 2016 17:19:00 +0100
changeset 133
87b405d61f64
parent 132
e9afb5387007
child 134
44415e4399ce

improves event handler and ssl error handling

src/server/daemon/auth.c file | annotate | diff | comparison | revisions
src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/event.h file | annotate | diff | comparison | revisions
src/server/daemon/event_bsd.c file | annotate | diff | comparison | revisions
src/server/daemon/event_linux.c file | annotate | diff | comparison | revisions
src/server/daemon/event_solaris.c file | annotate | diff | comparison | revisions
src/server/daemon/httplistener.c file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.c file | annotate | diff | comparison | revisions
src/server/daemon/keyfile_auth.c file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.c file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.h file | annotate | diff | comparison | revisions
src/server/daemon/webserver.c file | annotate | diff | comparison | revisions
src/server/safs/cgi.c file | annotate | diff | comparison | revisions
src/server/util/io.c file | annotate | diff | comparison | revisions
src/server/util/io.h file | annotate | diff | comparison | revisions
--- 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));
 }
 
--- a/src/server/util/io.h	Tue Dec 27 14:02:28 2016 +0100
+++ b/src/server/util/io.h	Tue Dec 27 17:19:00 2016 +0100
@@ -82,7 +82,8 @@
 
 typedef struct SSLStream {
     IOStream st;
-    SSL      *ssl; 
+    SSL      *ssl;
+    int      error;
 } SSLStream;
 
 

mercurial