Fri, 12 Jan 2018 17:54:52 +0100
using non-blocking IO for SSL_accept
--- a/src/server/daemon/httplistener.c Wed Jan 10 18:47:37 2018 +0100 +++ b/src/server/daemon/httplistener.c Fri Jan 12 17:54:52 2018 +0100 @@ -402,33 +402,24 @@ conn->fd = clientfd; conn->listener = ls; if(ls->ssl) { + // SSL connections are always non-blocking + // set socket non blocking + int flags; + if((flags = fcntl(conn->fd, F_GETFL, 0)) == -1) { + flags = 0; + } + if(fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK)) { + perror("Error: acceptor_thread: fcntl"); + // TODO: error + } + SSL *ssl = SSL_new(ls->ssl->sslctx); SSL_set_fd(ssl, clientfd); - int ssl_ar = SSL_accept(ssl); - if(ssl_ar <= 0) { - int error = SSL_get_error(ssl, ssl_ar); - char *errstr; - switch(error) { - default: errstr = "unknown"; break; - case SSL_ERROR_ZERO_RETURN: errstr = "SSL_ERROR_ZERO_RETURN"; break; - case SSL_ERROR_WANT_READ: errstr = "SSL_ERROR_WANT_READ"; break; - case SSL_ERROR_WANT_WRITE: errstr = "SSL_ERROR_WANT_WRITE"; 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 = "SL_ERROR_SSL"; break; - } - log_ereport(LOG_VERBOSE, "SSL accept error[%d]: %s", error, errstr); - free(conn); - conn = NULL; - close(clientfd); - } else { - conn->ssl = ssl; - conn->read = connection_ssl_read; - conn->write = connection_ssl_write; - conn->close = connection_ssl_close; - } + + conn->ssl = ssl; + conn->read = connection_ssl_read; + conn->write = connection_ssl_write; + conn->close = connection_ssl_close; } else { conn->ssl = NULL; conn->read = connection_read;
--- a/src/server/daemon/sessionhandler.c Wed Jan 10 18:47:37 2018 +0100 +++ b/src/server/daemon/sessionhandler.c Fri Jan 12 17:54:52 2018 +0100 @@ -183,7 +183,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) { @@ -223,7 +223,7 @@ Event *event = malloc(sizeof(Event)); ZERO(event, sizeof(Event)); - event->fn = evt_request_input; + event->fn = conn->ssl ? evt_request_ssl_accept : evt_request_input; event->finish = evt_request_finish; event->cookie = io; @@ -237,6 +237,43 @@ } } +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 = "SL_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;
--- a/src/server/daemon/sessionhandler.h Wed Jan 10 18:47:37 2018 +0100 +++ b/src/server/daemon/sessionhandler.h Fri Jan 12 17:54:52 2018 +0100 @@ -125,6 +125,7 @@ void evt_enq_conn(SessionHandler *handler, Connection *conn); +int evt_request_ssl_accept(EventHandler *handler, Event *event); int evt_request_input(EventHandler *h, Event *event); int evt_request_finish(EventHandler *h, Event *event); int evt_request_error(EventHandler *h, Event *event);