--- 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;