summaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c236
1 files changed, 212 insertions, 24 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 780ba28e..dbf21e18 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -123,7 +123,7 @@ mhd_panic_std (void *cls,
MHD_PanicCallback mhd_panic;
/**
- * Closure argument for "mhd_panic".
+ * Closure argument for #mhd_panic.
*/
void *mhd_panic_cls;
@@ -401,7 +401,9 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon,
* @return number of bytes actually received
*/
static ssize_t
-recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
+recv_tls_adapter (struct MHD_Connection *connection,
+ void *other,
+ size_t i)
{
ssize_t res;
@@ -410,7 +412,9 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
connection->daemon->num_tls_read_ready--;
connection->tls_read_ready = MHD_NO;
}
- res = gnutls_record_recv (connection->tls_session, other, i);
+ res = gnutls_record_recv (connection->tls_session,
+ other,
+ i);
if ( (GNUTLS_E_AGAIN == res) ||
(GNUTLS_E_INTERRUPTED == res) )
{
@@ -447,11 +451,14 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
*/
static ssize_t
send_tls_adapter (struct MHD_Connection *connection,
- const void *other, size_t i)
+ const void *other,
+ size_t i)
{
int res;
- res = gnutls_record_send (connection->tls_session, other, i);
+ res = gnutls_record_send (connection->tls_session,
+ other,
+ i);
if ( (GNUTLS_E_AGAIN == res) ||
(GNUTLS_E_INTERRUPTED == res) )
{
@@ -2157,6 +2164,123 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
}
+#if HTTPS_SUPPORT
+/**
+ * Performs bi-directional forwarding on upgraded HTTPS connections
+ * based on the readyness state stored in the @a urh handle.
+ *
+ * @param urh handle to process
+ */
+static void
+process_urh (struct MHD_UpgradeResponseHandle *urh)
+{
+#if FIXME_BUFFERS
+ // FIXME: we need buffer/buffer_size/buffer_off for
+ // both directions to be somehow stored within urh.
+ // (Note that despite using the same variable names
+ // below, we need actually different buffers for each
+ // direction.)
+
+ /* handle reading from HTTPS client and writing to application */
+ if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) &&
+ (buffer_off < buffer_size) )
+ {
+ ssize_t res;
+
+ res = gnutls_record_recv (uri->connection->tls_session,
+ &buffer[buffer_off],
+ buffer_size - buffer_off);
+ if ( (GNUTLS_E_AGAIN == res) ||
+ (GNUTLS_E_INTERRUPTED == res) )
+ {
+ urh->celi_client &= ~MHD_EPOLL_STATE_READ_READY;
+ }
+ else if (res > 0)
+ {
+ buffer_off += res;
+ }
+ }
+ if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) &&
+ (buffer_off > 0) )
+ {
+ size_t res;
+
+ res = write (urh->mhd_socket,
+ buffer,
+ buffer_off);
+ if (-1 == res)
+ {
+ /* FIXME: differenciate by errno? */
+ urh->celi_mhd &= ~MHD_EPOLL_STATE_WRITE_READY;
+ }
+ else
+ {
+ if (buffer_off != res)
+ {
+ memmove (buffer,
+ &buffer[res],
+ buffer_off - res);
+ buffer_off -= res;
+ }
+ else
+ {
+ buffer_off = 0;
+ }
+ }
+ }
+
+ /* handle reading from application and writing to HTTPS client */
+ if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) &&
+ (buffer_off < buffer_size) )
+ {
+ size_t res;
+
+ res = read (urh->mhd_socket,
+ &buffer[buffer_off],
+ buffer_size - buffer_off);
+ if (-1 == res)
+ {
+ /* FIXME: differenciate by errno? */
+ urh->celi_mhd &= ~MHD_EPOLL_STATE_READ_READY;
+ }
+ else
+ {
+ buffer_off += res;
+ }
+ }
+ if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) &&
+ (buffer_off > 0) )
+ {
+ ssize_t res;
+
+ res = gnutls_record_send (uri->connection->tls_session,
+ buffer,
+ buffer_off);
+ if ( (GNUTLS_E_AGAIN == res) ||
+ (GNUTLS_E_INTERRUPTED == res) )
+ {
+ urh->celi_client &= ~MHD_EPOLL_STATE_WRITE_READY;
+ }
+ else if (res > 0)
+ {
+ if (buffer_off != res)
+ {
+ memmove (buffer,
+ &buffer[res],
+ buffer_off - res);
+ buffer_off -= res;
+ }
+ else
+ {
+ buffer_off = 0;
+ }
+ }
+ }
+#endif
+}
+#endif
+
+
/**
* Run webserver operations. This method should be called by clients
* in combination with #MHD_get_fdset if the client-controlled select
@@ -2185,7 +2309,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
MHD_socket ds;
struct MHD_Connection *pos;
struct MHD_Connection *next;
+#if HTTPS_SUPPORT
struct MHD_UpgradeResponseHandle *urh;
+#endif
unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY |
MHD_USE_SELECT_INTERNALLY | MHD_USE_POLL_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION;
@@ -2239,8 +2365,17 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
#if HTTPS_SUPPORT
for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
{
- // if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) &&
- // (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) )
+ /* update urh state based on select() output */
+ if (FD_ISSET (urh->connection->socket_fd, read_fd_set))
+ urh->celi_client |= MHD_EPOLL_STATE_READ_READY;
+ if (FD_ISSET (urh->connection->socket_fd, write_fd_set))
+ urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY;
+ if (FD_ISSET (urh->mhd_socket, read_fd_set))
+ urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY;
+ if (FD_ISSET (urh->mhd_socket, write_fd_set))
+ urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY;
+ /* call generic forwarding function for passing data */
+ process_urh (urh);
}
#endif
MHD_cleanup_connections (daemon);
@@ -2298,10 +2433,10 @@ MHD_select (struct MHD_Daemon *daemon,
{
/* accept only, have one thread per connection */
if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
- (!MHD_add_to_fd_set_ (daemon->socket_fd,
- &rs,
- &maxsock,
- FD_SETSIZE)) )
+ (! MHD_add_to_fd_set_ (daemon->socket_fd,
+ &rs,
+ &maxsock,
+ FD_SETSIZE)) )
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon, "Could not add listen socket to fdset");
@@ -2310,10 +2445,10 @@ MHD_select (struct MHD_Daemon *daemon,
}
}
if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) &&
- (!MHD_add_to_fd_set_ (daemon->wpipe[0],
- &rs,
- &maxsock,
- FD_SETSIZE)) )
+ (! MHD_add_to_fd_set_ (daemon->wpipe[0],
+ &rs,
+ &maxsock,
+ FD_SETSIZE)) )
{
#if defined(MHD_WINSOCK_SOCKETS)
/* fdset limit reached, new connections
@@ -2322,10 +2457,10 @@ MHD_select (struct MHD_Daemon *daemon,
if (MHD_INVALID_SOCKET != daemon->socket_fd)
{
FD_CLR (daemon->socket_fd, &rs);
- if (!MHD_add_to_fd_set_ (daemon->wpipe[0],
- &rs,
- &maxsock,
- FD_SETSIZE))
+ if (! MHD_add_to_fd_set_ (daemon->wpipe[0],
+ &rs,
+ &maxsock,
+ FD_SETSIZE))
{
#endif /* MHD_WINSOCK_SOCKETS */
#ifdef HAVE_MESSAGES
@@ -2410,6 +2545,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
unsigned int num_connections;
struct MHD_Connection *pos;
struct MHD_Connection *next;
+#if HTTPS_SUPPORT
+ struct MHD_UpgradeResponseHandle *urh;
+ struct MHD_UpgradeResponseHandle *urhn;
+#endif
if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) &&
(MHD_YES == resume_suspended_connections (daemon)) )
@@ -2419,6 +2558,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
num_connections = 0;
for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
num_connections++;
+#if HTTPS_SUPPORT
+ for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
+ num_connections += 2;
+#endif
{
MHD_UNSIGNED_LONG_LONG ltimeout;
unsigned int i;
@@ -2428,7 +2571,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
int poll_pipe;
struct pollfd *p;
- p = malloc(sizeof (struct pollfd) * (2 + num_connections));
+ p = malloc (sizeof (struct pollfd) * (2 + num_connections));
if (NULL == p)
{
#ifdef HAVE_MESSAGES
@@ -2493,6 +2636,23 @@ MHD_poll_all (struct MHD_Daemon *daemon,
}
i++;
}
+#if HTTPS_SUPPORT
+ for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
+ {
+ p[poll_server+i].fd = urh->connection->socket_fd;
+ if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_client))
+ p[poll_server+i].events |= POLLIN;
+ if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client))
+ p[poll_server+i].events |= POLLOUT;
+ i++;
+ p[poll_server+i].fd = urh->mhd_socket;
+ if (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd))
+ p[poll_server+i].events |= POLLIN;
+ if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd))
+ p[poll_server+i].events |= POLLOUT;
+ i++;
+ }
+#endif
if (0 == poll_server + num_connections)
{
free(p);
@@ -2542,6 +2702,33 @@ MHD_poll_all (struct MHD_Daemon *daemon,
0 != (p[poll_server+i].revents & POLLOUT),
MHD_NO);
}
+#if HTTPS_SUPPORT
+ for (urh = daemon->urh_head; NULL != urh; urh = urhn)
+ {
+ urhn = urh->next;
+ if (p[poll_server+i].fd != urh->connection->socket_fd)
+ continue; /* fd mismatch, something else happened, retry later ... */
+ if (0 != (p[poll_server+i].revents & POLLIN))
+ urh->celi_client |= MHD_EPOLL_STATE_READ_READY;
+ if (0 != (p[poll_server+i].revents & POLLOUT))
+ urh->celi_client |= MHD_EPOLL_STATE_WRITE_READY;
+ i++;
+ if (p[poll_server+i].fd != urh->mhd_socket)
+ {
+ /* fd mismatch, something else happened, retry later ... */
+ /* may still be able to do something based on updates
+ to socket_fd availability */
+ process_urh (urh);
+ continue;
+ }
+ if (0 != (p[poll_server+i].revents & POLLIN))
+ urh->celi_mhd |= MHD_EPOLL_STATE_READ_READY;
+ if (0 != (p[poll_server+i].revents & POLLOUT))
+ urh->celi_mhd |= MHD_EPOLL_STATE_WRITE_READY;
+ i++;
+ process_urh (urh);
+ }
+#endif
/* handle 'listen' FD */
if ( (-1 != poll_listen) &&
(0 != (p[poll_listen].revents & POLLIN)) )
@@ -3081,9 +3268,10 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon)
* @param format format string
* @param va arguments to the format string (fprintf-style)
*/
-typedef void (*VfprintfFunctionPointerType)(void *cls,
- const char *format,
- va_list va);
+typedef void
+(*VfprintfFunctionPointerType)(void *cls,
+ const char *format,
+ va_list va);
/**
@@ -3687,7 +3875,7 @@ MHD_start_daemon_va (unsigned int flags,
}
if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
(1 == use_pipe) &&
- (!MHD_SCKT_FD_FITS_FDSET_(daemon->wpipe[0], NULL)) )
+ (! MHD_SCKT_FD_FITS_FDSET_(daemon->wpipe[0], NULL)) )
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,