libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 243e8fcd6054e4c0d2964b0d4b29e0c15861498d
parent 1b71798df8b8341b894dfc6223d01bd1cb8e83bd
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Mon,  5 Jun 2017 20:39:26 +0300

Used separate 'state' for TLS layer (independent of state of HTTP process)

Diffstat:
Msrc/microhttpd/connection.c | 42+++++++++++++++++++++++++++---------------
Msrc/microhttpd/connection_https.c | 9++++++---
Msrc/microhttpd/daemon.c | 2+-
Msrc/microhttpd/internal.h | 36++++++++++++++++++++++++------------
4 files changed, 58 insertions(+), 31 deletions(-)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -1648,6 +1648,25 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection) /* Do not update states of suspended connection */ if (connection->suspended) return; /* States will be updated after resume. */ +#ifdef HTTPS_SUPPORT + if (MHD_TLS_CONN_NO_TLS != connection->tls_state) + { /* HTTPS connection. */ + switch (connection->tls_state) + { + case MHD_TLS_CONN_INIT: + connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; + return; + case MHD_TLS_CONN_HANDSHAKING: + if (0 == gnutls_record_get_direction (connection->tls_session)) + connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; + else + connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE; + return; + default: + break; + } + } +#endif /* HTTPS_SUPPORT */ while (1) { #if DEBUG_STATES @@ -1658,14 +1677,6 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection) #endif switch (connection->state) { -#ifdef HTTPS_SUPPORT - case MHD_TLS_CONNECTION_INIT: - if (0 == gnutls_record_get_direction (connection->tls_session)) - connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; - else - connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE; - break; -#endif /* HTTPS_SUPPORT */ case MHD_CONNECTION_INIT: case MHD_CONNECTION_URL_RECEIVED: case MHD_CONNECTION_HEADER_PART_RECEIVED: @@ -2959,9 +2970,6 @@ MHD_connection_handle_write (struct MHD_Connection *connection) break; case MHD_CONNECTION_CLOSED: return MHD_YES; - case MHD_TLS_CONNECTION_INIT: - EXTRA_CHECK (0); - break; case MHD_CONNECTION_IN_CLEANUP: EXTRA_CHECK (0); break; @@ -3072,6 +3080,14 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) connection->in_idle = true; while (! connection->suspended) { +#ifdef HTTPS_SUPPORT + if (MHD_TLS_CONN_NO_TLS != connection->tls_state) + { /* HTTPS connection. */ + if ((MHD_TLS_CONN_INIT <= connection->tls_state) && + (MHD_TLS_CONN_CONNECTED > connection->tls_state)) + break; + } +#endif /* HTTPS_SUPPORT */ #if DEBUG_STATES MHD_DLOG (daemon, _("In function %s handling connection at state: %s\n"), @@ -3080,10 +3096,6 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) #endif switch (connection->state) { -#ifdef HTTPS_SUPPORT - case MHD_TLS_CONNECTION_INIT: - break; -#endif /* HTTPS_SUPPORT */ case MHD_CONNECTION_INIT: line = get_next_header_line (connection, &line_len); diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c @@ -147,23 +147,26 @@ run_tls_handshake (struct MHD_Connection *connection) { int ret; - if (MHD_TLS_CONNECTION_INIT == connection->state) + if ((MHD_TLS_CONN_INIT == connection->tls_state) || + (MHD_TLS_CONN_HANDSHAKING == connection->tls_state)) { ret = gnutls_handshake (connection->tls_session); if (ret == GNUTLS_E_SUCCESS) { - /* set connection state to enable HTTP processing */ - connection->state = MHD_CONNECTION_INIT; + /* set connection TLS state to enable HTTP processing */ + connection->tls_state = MHD_TLS_CONN_CONNECTED; MHD_update_last_activity_ (connection); return MHD_NO; } if ( (GNUTLS_E_AGAIN == ret) || (GNUTLS_E_INTERRUPTED == ret) ) { + connection->tls_state = MHD_TLS_CONN_HANDSHAKING; /* handshake not done */ return MHD_YES; } /* handshake failed */ + connection->tls_state = MHD_TLS_CONN_TLS_FAILED; #ifdef HAVE_MESSAGES MHD_DLOG (connection->daemon, _("Error: received handshake message out of context\n")); diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -2258,7 +2258,7 @@ internal_add_connection (struct MHD_Daemon *daemon, else { #ifdef HTTPS_SUPPORT - connection->state = MHD_TLS_CONNECTION_INIT; + connection->tls_state = MHD_TLS_CONN_INIT; MHD_set_https_callbacks (connection); gnutls_init (&connection->tls_session, GNUTLS_SERVER); diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -510,27 +510,34 @@ enum MHD_CONNECTION_STATE */ MHD_CONNECTION_IN_CLEANUP = MHD_CONNECTION_CLOSED + 1, - /* - * SSL/TLS connection states - */ - - /** - * The initial connection state for all secure connectoins - * Handshake messages will be processed in this state & while - * in the #MHD_TLS_HELLO_REQUEST state - */ - MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1, - #ifdef UPGRADE_SUPPORT /** * Connection was "upgraded" and socket is now under the * control of the application. */ - MHD_CONNECTION_UPGRADE = MHD_TLS_CONNECTION_INIT + 1, + MHD_CONNECTION_UPGRADE #endif /* UPGRADE_SUPPORT */ }; + +/** + * States of TLS transport layer. + */ +enum MHD_TLS_CONN_STATE +{ + MHD_TLS_CONN_NO_TLS = 0, /**< Not a TLS connection (plain socket). */ + MHD_TLS_CONN_INIT, /**< TLS connection is not established yet. */ + MHD_TLS_CONN_HANDSHAKING, /**< TLS is in handshake process. */ + MHD_TLS_CONN_CONNECTED, /**< TLS is established. */ + MHD_TLS_CONN_WR_CLOSING, /**< Closing WR side of TLS layer. */ + MHD_TLS_CONN_WR_CLOSED, /**< WR side of TLS layer is closed. */ + MHD_TLS_CONN_TLS_CLOSING, /**< TLS session is terminating. */ + MHD_TLS_CONN_TLS_CLOSED, /**< TLS session is terminated. */ + MHD_TLS_CONN_TLS_FAILED, /**< TLS session failed. */ + MHD_TLS_CONN_INVALID_STATE/**< Sentinel. Not a valid value. */ +}; + /** * Should all state transitions be printed to stderr? */ @@ -973,6 +980,11 @@ struct MHD_Connection int cipher; /** + * State of connection's TLS layer + */ + enum MHD_TLS_CONN_STATE tls_state; + + /** * Could it be that we are ready to read due to TLS buffers * even though the socket is not? */