libmicrohttpd

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

commit 5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822
parent 9562d1656d683cce2a2557fc0c2e5573fabfc6bb
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu, 15 Feb 2018 07:38:38 +0100

implementing thread_main_connection_upgrade

Diffstat:
Msrc/lib/connection_add.c | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/daemon_poll.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/daemon_poll.h | 12++++++++++++
Msrc/lib/daemon_select.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/daemon_select.h | 12++++++++++++
5 files changed, 218 insertions(+), 0 deletions(-)

diff --git a/src/lib/connection_add.c b/src/lib/connection_add.c @@ -24,6 +24,48 @@ #include "internal.h" #include "connection_add.h" #include "daemon_ip_limit.h" +#include "daemon_select.h" +#include "daemon_poll.h" + + +#ifdef UPGRADE_SUPPORT +/** + * Main function of the thread that handles an individual connection + * after it was "upgraded" when #MHD_USE_THREAD_PER_CONNECTION is set. + * @remark To be called only from thread that process + * connection's recv(), send() and response. + * + * @param con the connection this thread will handle + */ +static void +thread_main_connection_upgrade (struct MHD_Connection *con) +{ +#ifdef HTTPS_SUPPORT + struct MHD_UpgradeResponseHandle *urh = con->request.urh; + struct MHD_Daemon *daemon = con->daemon; + + /* Here, we need to bi-directionally forward + until the application tells us that it is done + with the socket; */ + if ( (NULL != daemon->tls_api) && + (MHD_ELS_POLL != daemon->event_loop_syscall) ) + { + MHD_daemon_upgrade_connection_with_select (con); + } +#ifdef HAVE_POLL + else if (NULL != daemon->tls_api) + { + MHD_daemon_upgrade_connection_with_poll_ (con); + } +#endif + /* end HTTPS */ +#endif /* HTTPS_SUPPORT */ + /* TLS forwarding was finished. Cleanup socketpair. */ + MHD_connection_finish_forward_ (con); + /* Do not set 'urh->clean_ready' yet as 'urh' will be used + * in connection thread for a little while. */ +} +#endif /* UPGRADE_SUPPORT */ /** diff --git a/src/lib/daemon_poll.c b/src/lib/daemon_poll.c @@ -450,4 +450,64 @@ MHD_daemon_poll_ (struct MHD_Daemon *daemon, #endif } + +#ifdef HTTPS_SUPPORT +/** + * Process upgraded connection with a poll() loop. + * We are in our own thread, only processing @a con + * + * @param con connection to process + */ +void +MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con) +{ + struct MHD_UpgradeResponseHandle *urh = con->request.urh; + struct MHD_Daemon *daemon = con->daemon; + struct pollfd p[2]; + + memset (p, + 0, + sizeof (p)); + p[0].fd = urh->connection->socket_fd; + p[1].fd = urh->mhd.socket; + + while ( (0 != urh->in_buffer_size) || + (0 != urh->out_buffer_size) || + (0 != urh->in_buffer_used) || + (0 != urh->out_buffer_used) ) + { + int timeout; + + urh_update_pollfd (urh, + p); + + if ( (con->tls_read_ready) && + (urh->in_buffer_used < urh->in_buffer_size)) + timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */ + else + timeout = -1; + + if (MHD_sys_poll_ (p, + 2, + timeout) < 0) + { + const int err = MHD_socket_get_error_ (); + + if (MHD_SCKT_ERR_IS_EINTR_ (err)) + continue; +#ifdef HAVE_MESSAGES + MHD_DLOG (con->daemon, + MHD_SC_UNEXPECTED_POLL_ERROR, + _("Error during poll: `%s'\n"), + MHD_socket_strerr_ (err)); +#endif + break; + } + urh_from_pollfd (urh, + p); + process_urh (urh); + } +} +#endif + /* end of daemon_poll.c */ diff --git a/src/lib/daemon_poll.h b/src/lib/daemon_poll.h @@ -68,4 +68,16 @@ MHD_daemon_poll_ (struct MHD_Daemon *daemon, #endif +#ifdef HTTPS_SUPPORT +/** + * Process upgraded connection with a poll() loop. + * We are in our own thread, only processing @a con + * + * @param con connection to process + */ +void +MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con) + MHD_NONNULL(1); +#endif + #endif diff --git a/src/lib/daemon_select.c b/src/lib/daemon_select.c @@ -477,6 +477,98 @@ internal_run_from_select (struct MHD_Daemon *daemon, } +#ifdef HTTPS_SUPPORT +/** + * Process upgraded connection with a select loop. + * We are in our own thread, only processing @a con + * + * @param con connection to process + */ +void +MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con) +{ + struct MHD_UpgradeResponseHandle *urh = con->request.urh; + struct MHD_Daemon *daemon = con->daemon; + + while ( (0 != urh->in_buffer_size) || + (0 != urh->out_buffer_size) || + (0 != urh->in_buffer_used) || + (0 != urh->out_buffer_used) ) + { + /* use select */ + fd_set rs; + fd_set ws; + fd_set es; + MHD_socket max_fd; + int num_ready; + bool result; + + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + max_fd = MHD_INVALID_SOCKET; + result = urh_to_fdset (urh, + &rs, + &ws, + &es, + &max_fd, + FD_SETSIZE); + if (! result) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (con->daemon, + MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE, + _("Error preparing select\n")); +#endif + break; + } + /* FIXME: does this check really needed? */ + if (MHD_INVALID_SOCKET != max_fd) + { + struct timeval* tvp; + struct timeval tv; + if ( (con->tls_read_ready) && + (urh->in_buffer_used < urh->in_buffer_size)) + { /* No need to wait if incoming data is already pending in TLS buffers. */ + tv.tv_sec = 0; + tv.tv_usec = 0; + tvp = &tv; + } + else + tvp = NULL; + num_ready = MHD_SYS_select_ (max_fd + 1, + &rs, + &ws, + &es, + tvp); + } + else + num_ready = 0; + if (num_ready < 0) + { + const int err = MHD_socket_get_error_(); + + if (MHD_SCKT_ERR_IS_EINTR_(err)) + continue; +#ifdef HAVE_MESSAGES + MHD_DLOG (con->daemon, + MHD_SC_UNEXPECTED_SELECT_ERROR, + _("Error during select (%d): `%s'\n"), + err, + MHD_socket_strerr_ (err)); +#endif + break; + } + urh_from_fdset (urh, + &rs, + &ws, + &es); + process_urh (urh); + } +} +#endif + + /** * Run webserver operations. This method should be called by clients * in combination with #MHD_get_fdset and #MHD_get_timeout() if the diff --git a/src/lib/daemon_select.h b/src/lib/daemon_select.h @@ -40,4 +40,16 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon, MHD_NONNULL(1); +#ifdef HTTPS_SUPPORT +/** + * Process upgraded connection with a select loop. + * We are in our own thread, only processing @a con + * + * @param con connection to process + */ +void +MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con) + MHD_NONNULL(1); +#endif + #endif