mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-27 04:09:31 +03:00
implementing thread_main_connection_upgrade
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user