src/server/daemon/sessionhandler.c

changeset 193
aa8393527b1e
parent 181
12828065f120
parent 192
6a145e13d933
child 194
6345f50208d5
--- a/src/server/daemon/sessionhandler.c	Thu Aug 31 16:29:49 2017 +0200
+++ b/src/server/daemon/sessionhandler.c	Sat Jan 13 19:01:00 2018 +0100
@@ -40,9 +40,9 @@
 #include "httplistener.h"
 
 typedef struct _event_http_io {
-    HTTPRequest *request;
-    HttpParser  *parser;
-    int         error;
+    HTTPRequest  *request;
+    HttpParser   *parser;
+    int          error;
 } EventHttpIO;
 
 
@@ -105,11 +105,30 @@
     free(conn);    
 }
 
+IOStream* create_connection_iostream(
+        SessionHandler *sh,
+        Connection *conn,
+        pool_handle_t *pool,
+        WSBool *ssl)
+{
+    IOStream *io = NULL;
+    if(conn->ssl) {
+        io = sslstream_new(pool, conn->ssl);
+        *ssl = 1;
+    } else {
+        io = sysstream_new(pool, conn->fd);
+        *ssl = 0;
+    }
+    return io;
+}
+
+
 SessionHandler* create_basic_session_handler() {
     BasicSessionHandler *handler = malloc(sizeof(BasicSessionHandler));
     handler->threadpool = threadpool_new(4, 8);
     handler->sh.enqueue_connection = basic_enq_conn;
     handler->sh.keep_alive = basic_keep_alive;
+    handler->sh.create_iostream = create_connection_iostream;
 
     return (SessionHandler*)handler;
 }
@@ -170,7 +189,7 @@
     }
     
     // process request
-    r = handle_request(&request, NULL); // TODO: use correct thread pool
+    r = handle_request(&request, NULL, NULL); // TODO: use correct thread pool
     
     // TODO: free, see evt_request_finish
 
@@ -189,6 +208,7 @@
     handler->eventhandler = get_default_event_handler();
     handler->sh.enqueue_connection = evt_enq_conn;
     handler->sh.keep_alive = evt_keep_alive;
+    handler->sh.create_iostream = create_connection_iostream;
     return (SessionHandler*)handler;
 }
 
@@ -200,7 +220,7 @@
     
     // set socket non blocking
     int flags;
-    if (-1 == (flags = fcntl(conn->fd, F_GETFL, 0))) {
+    if ((flags = fcntl(conn->fd, F_GETFL, 0)) == -1) {
         flags = 0;
     }
     if (fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK) != 0) {
@@ -238,14 +258,14 @@
      * evt_enq_conn() --> event handler --> handle_request()
      */
     
-    event_handler_t *ev = ((EventSessionHandler*)handler)->eventhandler;
-    
-    event_t *event = malloc(sizeof(event_t));
-    ZERO(event, sizeof(event_t));
-    event->fn = evt_request_input;
+    Event *event = malloc(sizeof(Event));
+    ZERO(event, sizeof(Event));
+    event->fn = conn->ssl ? evt_request_ssl_accept : evt_request_input;
     event->finish = evt_request_finish;
     event->cookie = io;
     
+    EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler);
+    
     if(ev_pollin(ev, conn->fd, event) != 0) {
         // TODO: ev_pollin should log, intercept some errors here
         log_ereport(LOG_FAILURE, "Cannot enqueue connection");
@@ -254,7 +274,44 @@
     }
 }
 
-int evt_request_input(event_handler_t *handler, event_t *event) {    
+int evt_request_ssl_accept(EventHandler *handler, Event *event) {
+    EventHttpIO *io = event->cookie;
+    Connection  *conn = io->request->connection;
+    
+    int ret = SSL_accept(conn->ssl);
+    if(ret <= 0) {
+        int error = SSL_get_error(conn->ssl, ret);
+        char *errstr;
+        switch(error) {
+            default: errstr = "unknown"; break;
+            case SSL_ERROR_WANT_READ: {
+                event->events = EVENT_POLLIN;
+                return 1;
+            }
+            case SSL_ERROR_WANT_WRITE: {
+                event->events = EVENT_POLLOUT;
+                return 1;
+            }
+            case SSL_ERROR_ZERO_RETURN: errstr = "SSL_ERROR_ZERO_RETURN"; break;
+            case SSL_ERROR_WANT_CONNECT: errstr = "SSL_ERROR_WANT_CONNECT"; break;
+            case SSL_ERROR_WANT_ACCEPT: errstr = "SSL_ERROR_WANT_ACCEPT"; break;
+            case SSL_ERROR_WANT_X509_LOOKUP: errstr = "SSL_ERROR_WANT_X509_LOOKUP"; break;
+            case SSL_ERROR_SYSCALL: errstr = "SSL_ERROR_SYSCALL"; break;
+            case SSL_ERROR_SSL: errstr = "SSL_ERROR_SSL"; break;
+            
+            log_ereport(LOG_VERBOSE, "SSL accept error[%d]: %s", error, errstr);
+            event->finish = evt_request_error;
+            io->error = 1;
+            return 0;
+        }
+    }
+    
+    // SSL_accept successful, start request input now
+    event->fn = evt_request_input;
+    return evt_request_input(handler, event);
+}
+
+int evt_request_input(EventHandler *handler, Event *event) {    
     EventHttpIO *io = event->cookie;
     HttpParser  *parser  = io->parser;
     HTTPRequest *request = io->request;
@@ -272,11 +329,11 @@
             // SSL specific error handling
             switch(conn->ssl_error) {
                 case SSL_ERROR_WANT_READ: {
-                    event->poll = EVENT_POLLIN;
+                    event->events = EVENT_POLLIN;
                     return 1;
                 }
                 case SSL_ERROR_WANT_WRITE: {
-                    event->poll = EVENT_POLLOUT;
+                    event->events = EVENT_POLLOUT;
                     return 1;
                 }
             }
@@ -302,7 +359,7 @@
          * we need more data -> return 1 to tell the event handler to
          * continue polling
          */
-        event->poll = EVENT_POLLIN;
+        event->events = EVENT_POLLIN;
         return 1;
     }
     
@@ -336,12 +393,12 @@
     return 0;
 }
 
-int evt_request_finish(event_handler_t *h, event_t *event) { 
+int evt_request_finish(EventHandler *h, Event *event) { 
     EventHttpIO *io = event->cookie;
     HttpParser  *parser  = io->parser;
     HTTPRequest *request = io->request;
       
-    int r = handle_request(request, NULL);
+    int r = handle_request(request, NULL, h);
     if(r != 0) {
         // TODO: error message
         connection_destroy(request->connection);
@@ -362,7 +419,7 @@
     return 0;
 }
 
-int evt_request_error(event_handler_t *h, event_t *event) { 
+int evt_request_error(EventHandler *h, Event *event) { 
     EventHttpIO *io = event->cookie;
     HttpParser  *parser  = io->parser;
     HTTPRequest *request = io->request;

mercurial