gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] GNU libmicrohttpd branch master updated. dd


From: gitolite
Subject: [GNUnet-SVN] [libmicrohttpd] GNU libmicrohttpd branch master updated. dd327c1d13252373cd1730e445d19930417571bf
Date: Thu, 27 Oct 2016 21:47:16 +0200 (CEST)

The branch, master has been updated
       via  dd327c1d13252373cd1730e445d19930417571bf (commit)
       via  fd0ceb70580e4fc7096720e123a25970b69631d9 (commit)
       via  92c4de41465e1120129584bce6981034166f762a (commit)
       via  c38412e3fd082f2d90adc12594b9657c9496a854 (commit)
       via  f2cb0ef073b5e0ae50200aec3f69822b6663e3d3 (commit)
       via  9224b3e326ee3631901bd97e1b1f62c27c08c169 (commit)
       via  01e28f110abc278c40ab7d153665c2dac9d867ce (commit)
       via  80d4152e1f287d1572833246dcc3aa676410e9f4 (commit)
       via  5b01262799b1eef4e78b0264f9715fbf7bff1857 (commit)
       via  55bc012c93d89944f8138ef0c5914c229aa13987 (commit)
       via  d528519166ae590ec3cc6b7d7dabb3e19616ff00 (commit)
       via  dcc664ad7ee696ba3aeb19d35f15b0b3efd292cf (commit)
       via  ac89091aa66df30a2711d5b8b7c735f64686fe3d (commit)
       via  d7f5dece99015b3d624ee25585dfa028c079bea2 (commit)
       via  9eebca21c09e278cb2a48c6dbb9beec35800d647 (commit)
       via  24b215aadc6f67d5de00d201d120416fe70d90a9 (commit)
       via  afe4f08eda64657f268e0d83e204041b2c281194 (commit)
      from  aa4da2538f101e1070b35dae41323197166fb21c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit dd327c1d13252373cd1730e445d19930417571bf
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Thu Oct 27 22:43:48 2016 +0300

    Skip locking when not required

commit fd0ceb70580e4fc7096720e123a25970b69631d9
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Wed Oct 26 21:43:15 2016 +0300

    MHD_stop_daemon(): structurize closing logic

commit 92c4de41465e1120129584bce6981034166f762a
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Thu Oct 27 22:26:32 2016 +0300

    MHD_epoll(): do not clear ITC before processing upgraded connections

commit c38412e3fd082f2d90adc12594b9657c9496a854
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Thu Oct 27 22:12:57 2016 +0300

    epoll mode: always watch to ITC level if ITC was requested.

commit f2cb0ef073b5e0ae50200aec3f69822b6663e3d3
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Thu Oct 27 22:11:24 2016 +0300

    epoll mode: use level trigger for ITC.
    Level trigger is better: MHD need to always react to high ITC level.

commit 9224b3e326ee3631901bd97e1b1f62c27c08c169
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Wed Oct 26 19:08:34 2016 +0300

    MHD_stop_daemon(): close all connections from daemon's thread, not from the 
caller thread.

commit 01e28f110abc278c40ab7d153665c2dac9d867ce
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Wed Oct 26 22:00:38 2016 +0300

    Added thread-safety functions marks

commit 80d4152e1f287d1572833246dcc3aa676410e9f4
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Mon Oct 24 21:17:27 2016 +0300

    Used smaller locked mutex scope.

commit 5b01262799b1eef4e78b0264f9715fbf7bff1857
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Mon Oct 24 20:12:26 2016 +0300

    Notify application about finished HTTP connection before starting upgrade.
    Unified HTTPS and HTTP modes.

commit 55bc012c93d89944f8138ef0c5914c229aa13987
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Mon Oct 24 19:43:22 2016 +0300

    MHD_response_execute_upgrade_(): deduplicate code.

commit d528519166ae590ec3cc6b7d7dabb3e19616ff00
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Sat Oct 22 11:26:31 2016 +0300

    Added support for suspending connection in thread-per-connection mode

commit dcc664ad7ee696ba3aeb19d35f15b0b3efd292cf
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Wed Oct 19 12:22:03 2016 +0300

    process_urh(): handle daemon shutdown

commit ac89091aa66df30a2711d5b8b7c735f64686fe3d
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Tue Oct 18 22:53:00 2016 +0300

    process_urh(): report errors

commit d7f5dece99015b3d624ee25585dfa028c079bea2
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Tue Oct 18 21:06:22 2016 +0300

    MHD_response_execute_upgrade_(): improved handling of buffer sizes

commit 9eebca21c09e278cb2a48c6dbb9beec35800d647
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Tue Oct 18 20:55:45 2016 +0300

    struct MHD_UpgradeResponseHandle: improve readability by renaming members

commit 24b215aadc6f67d5de00d201d120416fe70d90a9
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Tue Oct 18 20:26:38 2016 +0300

    Improve upgraded TLS socket closure processing

commit afe4f08eda64657f268e0d83e204041b2c281194
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Mon Oct 17 23:36:06 2016 +0300

    process_urh(): check returned errors and prevent further reading from 
socket when disconnect is detected.

-----------------------------------------------------------------------

Summary of changes:
 src/include/microhttpd.h  |   2 +-
 src/microhttpd/daemon.c   | 566 +++++++++++++++++++++++++++++++---------------
 src/microhttpd/internal.h |   4 +-
 src/microhttpd/response.c |  43 ++--
 4 files changed, 396 insertions(+), 219 deletions(-)

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index ebd94c7..efba0ee 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -126,7 +126,7 @@ typedef intptr_t ssize_t;
  * Current version of the library.
  * 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00095102
+#define MHD_VERSION 0x00095103
 
 /**
  * MHD-internal return code for "YES".
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 03bc3a1..da764ca 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -38,6 +38,10 @@
 #include "mhd_itc.h"
 #include "mhd_compat.h"
 
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+
 #if HAVE_SEARCH_H
 #include <search.h>
 #else
@@ -86,6 +90,17 @@
  */
 #define DEBUG_CONNECT MHD_NO
 
+/* Forward declarations. */
+/**
+ * Close all connections for the daemon.
+ * Must only be called when MHD_Daemon::shutdown was set to MHD_YES.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
+ *
+ * @param daemon daemon to close down
+ */
+static void
+close_all_connections (struct MHD_Daemon *daemon);
 
 /**
  * Default implementation of the panic function,
@@ -665,7 +680,7 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
               MHD_socket *max_fd,
               unsigned int fd_setsize)
 {
-  if ( (urh->out_buffer_off < urh->out_buffer_size) &&
+  if ( (urh->out_buffer_used < urh->out_buffer_size) &&
        (MHD_INVALID_SOCKET != urh->mhd.socket) &&
        (! MHD_add_to_fd_set_ (urh->mhd.socket,
                               rs,
@@ -679,7 +694,7 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
                               max_fd,
                               fd_setsize)) )
     return MHD_NO;
-  if ( (urh->in_buffer_off < urh->in_buffer_size) &&
+  if ( (urh->in_buffer_used < urh->in_buffer_size) &&
        (MHD_INVALID_SOCKET != urh->connection->socket_fd) &&
        (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
                               rs,
@@ -997,27 +1012,53 @@ MHD_cleanup_upgraded_connection_ (struct MHD_Connection 
*connection)
 /**
  * Performs bi-directional forwarding on upgraded HTTPS connections
  * based on the readyness state stored in the @a urh handle.
+ * @remark To be called only from thread that process
+ * connection's recv(), send() and response.
  *
  * @param urh handle to process
  */
 static void
 process_urh (struct MHD_UpgradeResponseHandle *urh)
 {
-  int fin_read;
+  if (MHD_NO != urh->connection->daemon->shutdown)
+    {
+      /* Daemon shutting down, application will not receive any more data. */
+      urh->was_closed = MHD_YES;
+    }
+  if (MHD_NO != urh->was_closed)
+    {
+      /* Application was closed connections: no more data
+       * can be forwarded to application socket. */
+      if (0 < urh->in_buffer_used)
+        {
+#ifdef HAVE_MESSAGES
+          MHD_DLOG (urh->connection->daemon,
+                    _("Failed to forward to application " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
+                        " bytes of data received from remote side: application 
shut down socket\n"),
+                    (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used);
+#endif
+
+        }
+      urh->in_buffer_size = 0;
+      urh->in_buffer_used = 0;
+      urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+      /* Reading from remote client is not required anymore. */
+      urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
+    }
 
   /* handle reading from TLS client and writing to application */
   if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
-       (urh->in_buffer_off < urh->in_buffer_size) )
+       (urh->in_buffer_used < urh->in_buffer_size) )
     {
       ssize_t res;
       size_t buf_size;
 
-      buf_size = urh->in_buffer_size - urh->in_buffer_off;
+      buf_size = urh->in_buffer_size - urh->in_buffer_used;
       if (buf_size > SSIZE_MAX)
         buf_size = SSIZE_MAX;
 
       res = gnutls_record_recv (urh->connection->tls_session,
-                                &urh->in_buffer[urh->in_buffer_off],
+                                &urh->in_buffer[urh->in_buffer_used],
                                 buf_size);
       if ( (GNUTLS_E_AGAIN == res) ||
            (GNUTLS_E_INTERRUPTED == res) )
@@ -1026,22 +1067,24 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
         }
       else if (res > 0)
         {
-          urh->in_buffer_off += res;
+          urh->in_buffer_used += res;
         }
-      if (0 == res)
+      else if (0 >= res)
         {
-          /* connection was shut down, signal by shrinking buffer,
-             which will eventually ensure this FD is no longer listed. */
-          urh->in_buffer_size = urh->in_buffer_off;
+          /* Connection was shut down or got unrecoverable error.
+           * signal by shrinking buffer so no more attempts will be
+           * performed to receive data. */
+          urh->in_buffer_size = 0;
+          urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
         }
     }
   if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
-       (urh->in_buffer_off > 0) )
+       (urh->in_buffer_used > 0) )
     {
       ssize_t res;
       size_t data_size;
 
-      data_size = urh->in_buffer_off;
+      data_size = urh->in_buffer_used;
       if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
         data_size = MHD_SCKT_SEND_MAX_SIZE_;
 
@@ -1055,70 +1098,105 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
           if ( (MHD_SCKT_ERR_IS_EINTR_ (err)) ||
                (MHD_SCKT_ERR_IS_EAGAIN_ (err)) )
             urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
-          else
+          else if (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err))
             {
               /* persistent / unrecoverable error, treat as
-                 if connection was shut down */
+                 if connection was shut down.
+                 Do not try to receive to 'in_buffer' and
+                 discard any unsent data. */
+#ifdef HAVE_MESSAGES
+              MHD_DLOG (urh->connection->daemon,
+                        _("Failed to forward to application " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
+                            " bytes of data received from remote side: %s\n"),
+                        (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
+                        MHD_socket_strerr_ (err));
+#endif
               urh->in_buffer_size = 0;
-              urh->in_buffer_off = 0;
+              urh->in_buffer_used = 0;
+              urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+              urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
             }
         }
       else
         {
-          if (urh->in_buffer_off != res)
+          if (urh->in_buffer_used != res)
             {
               memmove (urh->in_buffer,
                        &urh->in_buffer[res],
-                       urh->in_buffer_off - res);
-              urh->in_buffer_off -= res;
+                       urh->in_buffer_used - res);
+              urh->in_buffer_used -= res;
             }
           else
             {
-              urh->in_buffer_off = 0;
+              urh->in_buffer_used = 0;
             }
         }
     }
 
   /* handle reading from application and writing to HTTPS client */
-  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
-       (urh->out_buffer_off < urh->out_buffer_size) )
-    {
+  if ( ((0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) ||
+        (MHD_NO != urh->was_closed)) &&
+       (urh->out_buffer_used < urh->out_buffer_size) )
+    {
+      /* If application signaled MHD about socket closure then
+       * check for any pending data even if socket is not marked
+       * as 'ready' (signal may arrive after poll()/select()).
+       * Socketpair for forwarding is always in non-blocking mode
+       * so no risk that recv() will block the thread. */
       ssize_t res;
       size_t buf_size;
 
-      buf_size = urh->out_buffer_size - urh->out_buffer_off;
+      buf_size = urh->out_buffer_size - urh->out_buffer_used;
       if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
         buf_size = MHD_SCKT_SEND_MAX_SIZE_;
 
       res = MHD_recv_ (urh->mhd.socket,
-                       &urh->out_buffer[urh->out_buffer_off],
+                       &urh->out_buffer[urh->out_buffer_used],
                        buf_size);
       if (-1 == res)
         {
-          /* FIXME: differenciate by errno? */
-          urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
+          if (MHD_NO != urh->was_closed)
+            {
+              /* Connection was shuted down or all data received and
+               * application will not forward any more data. */
+              urh->out_buffer_size = 0;
+              urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
+            }
+          else
+            {
+              const int err = MHD_socket_get_error_ ();
+              if ( (MHD_SCKT_ERR_IS_EINTR_ (err)) ||
+                   (MHD_SCKT_ERR_IS_EAGAIN_ (err)) )
+                urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
+              else if (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err))
+                {
+                  /* persistent / unrecoverable error, treat as
+                     if connection was shut down */
+                  urh->out_buffer_size = 0;
+                  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
+                }
+            }
         }
       else
         {
-          urh->out_buffer_off += res;
+          urh->out_buffer_used += res;
         }
       if (0 == res)
         {
-          /* connection was shut down, signal by shrinking buffer,
-             which will eventually ensure this FD is no longer listed. */
-          urh->out_buffer_size = urh->out_buffer_off;
+          /* Connection was shut down or got unrecoverable error.
+           * signal by shrinking buffer so no more attempts will be
+           * performed to receive data. */
+          urh->out_buffer_size = 0;
+          urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
         }
-      fin_read = (0 == res);
     }
-  else
-    fin_read = 0;
   if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
-       (urh->out_buffer_off > 0) )
+       (urh->out_buffer_used > 0) )
     {
       ssize_t res;
       size_t data_size;
 
-      data_size = urh->out_buffer_off;
+      data_size = urh->out_buffer_used;
       if (data_size > SSIZE_MAX)
         data_size = SSIZE_MAX;
 
@@ -1132,30 +1210,60 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
         }
       else if (res > 0)
         {
-          if (urh->out_buffer_off != res)
+          if (urh->out_buffer_used != res)
             {
               memmove (urh->out_buffer,
                        &urh->out_buffer[res],
-                       urh->out_buffer_off - res);
-              urh->out_buffer_off -= res;
+                       urh->out_buffer_used - res);
+              urh->out_buffer_used -= res;
             }
           else
             {
-              urh->out_buffer_off = 0;
+              urh->out_buffer_used = 0;
             }
         }
       else
         {
           /* persistent / unrecoverable error, treat as
-             if connection was shut down */
+             if connection was shut down.
+             Do not try to receive to 'out_buffer' and
+             discard any unsent data. */
+#ifdef HAVE_MESSAGES
+          MHD_DLOG (urh->connection->daemon,
+                    _("Failed to forward to remote client " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
+                        " bytes of data received from application: %s\n"),
+                    (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
+                    gnutls_strerror(res));
+#endif
           urh->out_buffer_size = 0;
-          urh->out_buffer_off = 0;
+          urh->out_buffer_used = 0;
+          urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+          urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
         }
     }
+
+  if ( (MHD_NO != urh->connection->daemon->shutdown) &&
+       ((0 != urh->out_buffer_size) ||
+        (0 != urh->out_buffer_used)) )
+    {
+      /* Daemon shutting down, discard any remaining forward data. */
+#ifdef HAVE_MESSAGES
+      if (0 < urh->out_buffer_used)
+        MHD_DLOG (urh->connection->daemon,
+                  _("Failed to forward to remote client " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
+                      " bytes of data received from application: daemon shut 
down\n"),
+                  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
+#endif
+      urh->out_buffer_size = 0;
+      urh->out_buffer_used = 0;
+      urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+      urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
+    }
+
   /* cleanup connection if it was closed and all data was sent */
-  if ( (MHD_YES == urh->was_closed) &&
-       (0 == urh->out_buffer_off) &&
-       (MHD_YES == fin_read) )
+  if ( (MHD_NO != urh->was_closed) &&
+       (0 == urh->out_buffer_size) &&
+       (0 == urh->out_buffer_used) )
     {
       MHD_cleanup_upgraded_connection_ (urh->connection);
     }
@@ -1166,6 +1274,8 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
 /**
  * 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
  */
@@ -1233,8 +1343,10 @@ thread_main_connection_upgrade (struct MHD_Connection 
*con)
                           &rs,
                           &ws);
           process_urh (urh);
-          if ( (0 == urh->out_buffer_size) &&
-               (0 == urh->in_buffer_size) )
+          if ( (0 == urh->in_buffer_size) &&
+               (0 == urh->out_buffer_size) &&
+               (0 == urh->in_buffer_used) &&
+               (0 == urh->out_buffer_used) )
             break; /* connections died, we have no more purpose here */
         }
     }
@@ -1253,11 +1365,11 @@ thread_main_connection_upgrade (struct MHD_Connection 
*con)
                   sizeof (struct pollfd) * 2);
           p[0].fd = urh->connection->socket_fd;
           p[1].fd = urh->mhd.socket;
-          if (urh->in_buffer_off < urh->in_buffer_size)
+          if (urh->in_buffer_used < urh->in_buffer_size)
             p[0].events |= POLLIN;
           if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
             p[0].events |= POLLOUT;
-          if (urh->out_buffer_off < urh->out_buffer_size)
+          if (urh->out_buffer_used < urh->out_buffer_size)
             p[1].events |= POLLIN;
           if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
             p[1].events |= POLLOUT;
@@ -1287,8 +1399,10 @@ thread_main_connection_upgrade (struct MHD_Connection 
*con)
           if (0 != (p[1].revents & POLLOUT))
             urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
           process_urh (urh);
-          if ( (0 == urh->out_buffer_size) &&
-               (0 == urh->in_buffer_size) )
+          if ( (0 == urh->in_buffer_size) &&
+               (0 == urh->out_buffer_size) &&
+               (0 == urh->in_buffer_used) &&
+               (0 == urh->out_buffer_used) )
             break; /* connections died, we have no more purpose here */
         }
     }
@@ -1330,11 +1444,82 @@ thread_main_handle_connection (void *data)
   struct pollfd p[1 + EXTRA_SLOTS];
 #endif
 #undef EXTRA_SLOTS
+#ifdef HAVE_POLL
+  const _MHD_bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
+#else  /* ! HAVE_POLL */
+  const _MHD_bool use_poll = 0;
+#endif /* ! HAVE_POLL */
+  _MHD_bool was_suspended;
 
+  was_suspended = 0;
   while ( (MHD_YES != daemon->shutdown) &&
          (MHD_CONNECTION_CLOSED != con->state) )
     {
       const unsigned int timeout = daemon->connection_timeout;
+      _MHD_bool was_suspended = 0;
+
+      if (MHD_NO != con->suspended)
+        {
+          /* Connection was suspended, wait for resume. */
+          was_suspended = !0;
+          if (!use_poll)
+            {
+              FD_ZERO (&rs);
+              if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
+                                        &rs,
+                                        NULL,
+                                        FD_SETSIZE))
+                {
+  #ifdef HAVE_MESSAGES
+                  MHD_DLOG (con->daemon,
+                            _("Failed to add FD to fd_set\n"));
+  #endif
+                  goto exit;
+                }
+              if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
+                                       &rs, NULL, NULL, NULL))
+                {
+                  const int err = MHD_socket_get_error_();
+
+                  if (MHD_SCKT_ERR_IS_EINTR_(err))
+                    continue;
+#ifdef HAVE_MESSAGES
+                  MHD_DLOG (con->daemon,
+                            _("Error during select (%d): `%s'\n"),
+                            err,
+                            MHD_socket_strerr_ (err));
+#endif
+                  break;
+                }
+            }
+#ifdef HAVE_POLL
+          else /* use_poll */
+            {
+              p[0].events = POLLIN;
+              p[0].fd = MHD_itc_r_fd_ (daemon->itc);
+              p[0].revents = 0;
+              if (0 > MHD_sys_poll_ (p, 1, -1))
+                {
+                  if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_))
+                    continue;
+#ifdef HAVE_MESSAGES
+                  MHD_DLOG (con->daemon,
+                            _("Error during poll: `%s'\n"),
+                            MHD_socket_last_strerr_ ());
+#endif
+                  break;
+                }
+            }
+#endif /* HAVE_POLL */
+          MHD_itc_clear_ (daemon->itc);
+          continue; /* Check again for resume. */
+        } /* End of "suspended" branch. */
+
+      if ( was_suspended && (0 != con->connection_timeout) )
+        {
+          con->last_activity = MHD_monotonic_sec_counter(); /* Reset timeout 
timer. */
+          was_suspended = 0;
+        }
 
       tvp = NULL;
 #if HTTPS_SUPPORT
@@ -1540,14 +1725,8 @@ thread_main_handle_connection (void *data)
 #endif
       if (MHD_CONNECTION_UPGRADE == con->state)
         {
-          thread_main_connection_upgrade (con);
-#if HTTPS_SUPPORT
-          if (0 != (daemon->options & MHD_USE_TLS) )
-            break;
-#endif
-
-          /* skip usual clean up EXCEPT for the completion
-             notification (which must be done in this thread)! */
+          /* Normal HTTP processing is finished,
+           * notify application. */
           if ( (NULL != daemon->notify_completed) &&
                (MHD_YES == con->client_aware) )
             daemon->notify_completed (daemon->notify_completed_cls,
@@ -1556,6 +1735,14 @@ thread_main_handle_connection (void *data)
                                       MHD_REQUEST_TERMINATED_COMPLETED_OK);
           con->client_aware = MHD_NO;
 
+          thread_main_connection_upgrade (con);
+#if HTTPS_SUPPORT
+          if (0 != (daemon->options & MHD_USE_TLS) )
+            break;
+#endif
+
+          /* skip usual clean up EXCEPT for the completion
+             notification (which must be done in this thread)! */
           return (MHD_THRD_RTRN_TYPE_) 0;
         }
     }
@@ -1766,6 +1953,9 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon);
  *
  * Per-IP connection limits are ignored when using this API.
  *
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
+ *
  * @param daemon daemon that manages the connection
  * @param client_socket socket to manage (MHD will expect
  *        to receive an HTTP request from this socket next).
@@ -2171,6 +2361,10 @@ internal_add_connection (struct MHD_Daemon *daemon,
  * socket leaks or lead to undefined behavior).  You must explicitly
  * resume all connections before stopping the daemon.
  *
+ * @remark In thread-per-connection mode: can be called from any thread,
+ * in any other mode: to be called only from thread that process
+ * daemon's select()/poll()/etc.
+ *
  * @param connection the connection to suspend
  */
 void
@@ -2250,6 +2444,8 @@ MHD_resume_connection (struct MHD_Connection *connection)
     MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
   connection->resuming = MHD_YES;
   daemon->resuming = MHD_YES;
+  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+    MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
   if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
        (! MHD_itc_activate_ (daemon->itc, "r")) )
     {
@@ -2258,8 +2454,6 @@ MHD_resume_connection (struct MHD_Connection *connection)
                 _("Failed to signal resume via inter-thread communication 
channel."));
 #endif
     }
-  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
-    MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
 }
 
 
@@ -2278,10 +2472,10 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
   int ret;
 
   ret = MHD_NO;
+  if (MHD_NO == daemon->resuming)
+    return ret;
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
     MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
-  if (MHD_NO != daemon->resuming)
-    next = daemon->suspended_connections_head;
 
   /* Clear the flag *only* if connections will be resumed otherwise
      it may accidentally clear flag that was set at the same time in
@@ -2334,7 +2528,17 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
       pos->resuming = MHD_NO;
     }
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
-    MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
+    {
+      MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
+      if (MHD_NO != ret)
+        { /* Wake up suspended connections. */
+          if ( !MHD_itc_activate_(daemon->itc, "w"))
+#ifdef HAVE_MESSAGES
+            MHD_DLOG (daemon,
+                      _("Failed to signal resume of connection via 
inter-thread communication channel."));
+#endif
+        }
+    }
   return ret;
 }
 
@@ -2406,6 +2610,8 @@ MHD_add_connection (struct MHD_Daemon *daemon,
  * Accept an incoming connection and create the MHD_Connection object for
  * it.  This function also enforces policy by way of checking with the
  * accept policy callback.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
  *
  * @param daemon handle with the listen socket
  * @return #MHD_YES on success (connections denied by policy or due
@@ -2622,6 +2828,8 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
  * `select()` or `poll()` should at most block, not the timeout value set
  * for connections.  This function MUST NOT be called if MHD is
  * running with #MHD_USE_THREAD_PER_CONNECTION.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
  *
  * @param daemon daemon to query for timeout
  * @param timeout set to the timeout (in milliseconds)
@@ -3089,13 +3297,13 @@ MHD_poll_all (struct MHD_Daemon *daemon,
     for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
       {
         p[poll_server+i].fd = urh->connection->socket_fd;
-        if (urh->in_buffer_off < urh->in_buffer_size)
+        if (urh->in_buffer_used < urh->in_buffer_size)
           p[poll_server+i].events |= POLLIN;
         if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
           p[poll_server+i].events |= POLLOUT;
         i++;
         p[poll_server+i].fd = urh->mhd.socket;
-        if (urh->out_buffer_off < urh->out_buffer_size)
+        if (urh->out_buffer_used < urh->out_buffer_size)
           p[poll_server+i].events |= POLLIN;
         if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
           p[poll_server+i].events |= POLLOUT;
@@ -3314,6 +3522,8 @@ MHD_poll (struct MHD_Daemon *daemon,
  * upgraded.  This requires a separate epoll() invocation as we
  * cannot use the `struct MHD_Connection` data structures for
  * the `union epoll_data` in this case.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
  */
 static int
 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
@@ -3414,6 +3624,9 @@ MHD_epoll (struct MHD_Daemon *daemon,
   int num_events;
   unsigned int i;
   unsigned int series_length;
+#if HTTPS_SUPPORT
+   _MHD_bool run_upgraded = 0;
+#endif
 
   if (-1 == daemon->epoll_fd)
     return MHD_NO; /* we're down! */
@@ -3525,7 +3738,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
             {
               /* activity on an upgraded connection, we process
                  those in a separate epoll() */
-              run_epoll_for_upgrade (daemon);
+              run_upgraded = !0;
               continue;
             }
 #endif
@@ -3587,6 +3800,9 @@ MHD_epoll (struct MHD_Daemon *daemon,
         }
     }
 
+  if (run_upgraded)
+    run_epoll_for_upgrade (daemon);
+
   /* we handle resumes here because we may have ready connections
      that will not be placed into the epoll list immediately. */
   if (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME))
@@ -3745,16 +3961,11 @@ MHD_select_thread (void *cls)
       MHD_cleanup_connections (daemon);
     }
 
-  /* give resumed formerly suspended connections a chance to
-     be included in the cleanup */
-  resume_suspended_connections (daemon);
-  /* run clean up in this thread as well */
-  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
-    {
-      /* We did everything in this thread, so also the clean up */
-      while (NULL != (pos = daemon->connections_head))
-        close_connection (pos);
-    }
+  /* Resume any pending for resume connections, join
+   * all connection's threads (if any) and finally cleanup
+   * everything. */
+  close_all_connections (daemon);
+
   return (MHD_THRD_RTRN_TYPE_)0;
 }
 
@@ -4375,6 +4586,8 @@ setup_epoll_fd (struct MHD_Daemon *daemon)
 /**
  * Setup epoll() FD for the daemon and initialize it to listen
  * on the listen FD.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
  *
  * @param daemon daemon to initialize for epoll()
  * @return #MHD_YES on success, #MHD_NO on failure
@@ -4411,10 +4624,9 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
 #endif
       return MHD_NO;
     }
-  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
-       (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) )
+  if (MHD_ITC_IS_VALID_(daemon->itc))
     {
-      event.events = EPOLLIN | EPOLLET;
+      event.events = EPOLLIN;
       event.data.ptr = NULL;
       event.data.fd = MHD_itc_r_fd_ (daemon->itc);
       if (0 != epoll_ctl (daemon->epoll_fd,
@@ -4655,16 +4867,6 @@ MHD_start_daemon_va (unsigned int flags,
       goto free_and_fail;
     }
 
-  if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
-       (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) )
-    {
-#ifdef HAVE_MESSAGES
-      MHD_DLOG (daemon,
-                _("Combining MHD_USE_THREAD_PER_CONNECTION and 
MHD_USE_SUSPEND_RESUME is not supported.\n"));
-#endif
-      goto free_and_fail;
-    }
-
 #ifdef __SYMBIAN32__
   if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | 
MHD_USE_THREAD_PER_CONNECTION)))
     {
@@ -5188,9 +5390,10 @@ thread_failed:
 
 
 /**
- * Close all connections for the daemon; must only be called after
- * all of the threads have been joined and there is no more concurrent
- * activity on the connection lists.
+ * Close all connections for the daemon.
+ * Must only be called when MHD_Daemon::shutdown was set to MHD_YES.
+ * @remark To be called only from thread that process
+ * daemon's select()/poll()/etc.
  *
  * @param daemon daemon to close down
  */
@@ -5203,7 +5406,11 @@ close_all_connections (struct MHD_Daemon *daemon)
      running into the check for there not being any suspended
      connections left in case of a tight race with a recently
      resumed connection. */
-  resume_suspended_connections (daemon);
+  if (0 != (MHD_USE_SUSPEND_RESUME & daemon->options))
+    {
+      daemon->resuming = MHD_YES; /* Force check for pending resume. */
+      resume_suspended_connections (daemon);
+    }
   /* first, make sure all threads are aware of shutdown; need to
      traverse DLLs in peace... */
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
@@ -5314,106 +5521,101 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
 #endif
   if (0 != (MHD_USE_SUSPEND_RESUME & daemon->options))
     resume_suspended_connections (daemon);
+
   daemon->shutdown = MHD_YES;
   fd = daemon->socket_fd;
   daemon->socket_fd = MHD_INVALID_SOCKET;
-  /* Prepare workers for shutdown */
-  if (NULL != daemon->worker_pool)
-    {
-      /* #MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to 
check */
-      for (i = 0; i < daemon->worker_pool_size; ++i)
-       {
-         daemon->worker_pool[i].shutdown = MHD_YES;
-         daemon->worker_pool[i].socket_fd = MHD_INVALID_SOCKET;
-#ifdef EPOLL_SUPPORT
-         if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
-              (-1 != daemon->worker_pool[i].epoll_fd) &&
-              (MHD_INVALID_SOCKET == fd) )
-           epoll_shutdown (&daemon->worker_pool[i]);
-#endif
-       }
-    }
-  if (MHD_ITC_IS_VALID_(daemon->itc))
+
+  if ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ||
+       (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
     {
-      if (! MHD_itc_activate_ (daemon->itc, "e"))
-       MHD_PANIC (_("Failed to signal shutdown via inter-thread communication 
channel"));
-    }
+      /* Separate thread(s) is used for select()/poll()/etc. */
+      if (NULL != daemon->worker_pool)
+        {
+          /* Pool of workers is used.  */
+          /* Initiate shutdown process in wokers. */
+          for (i = 0; i < daemon->worker_pool_size; ++i)
+            {
+              daemon->worker_pool[i].shutdown = MHD_YES;
+              daemon->worker_pool[i].socket_fd = MHD_INVALID_SOCKET;
+              if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
+                {
+                  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
+                    MHD_PANIC (_("Failed to signal shutdown via inter-thread 
communication channel."));
+                }
 #ifdef HAVE_LISTEN_SHUTDOWN
-  else
-    {
-      /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
-      if ( (MHD_INVALID_SOCKET != fd) &&
-           (0 == (daemon->options & MHD_USE_ITC)) )
-       (void) shutdown (fd,
-                         SHUT_RDWR);
-    }
-#endif
-#ifdef EPOLL_SUPPORT
-  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
-       (-1 != daemon->epoll_fd) &&
-       (MHD_INVALID_SOCKET == fd) )
-    epoll_shutdown (daemon);
-#endif
-
-#if DEBUG_CLOSE
-#ifdef HAVE_MESSAGES
-  MHD_DLOG (daemon,
-            _("MHD listen socket shutdown\n"));
-#endif
+              else if (MHD_INVALID_SOCKET != fd)
+                {
+                  /* fd might be MHD_INVALID_SOCKET here due to 
'MHD_quiesce_daemon' */
+                  /* No problem if shutdown will be called several times for 
the same socket. */
+                    (void) shutdown (fd, SHUT_RDWR);
+                }
 #endif
-
-
-  /* Signal workers to stop and clean them up */
-  if (NULL != daemon->worker_pool)
-    {
-      /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to 
check */
-      for (i = 0; i < daemon->worker_pool_size; ++i)
-       {
-         if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
-           {
-             if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
-               MHD_PANIC (_("Failed to signal shutdown via inter-thread 
communication channel."));
-           }
-         if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
-            MHD_PANIC (_("Failed to join a thread\n"));
-         close_all_connections (&daemon->worker_pool[i]);
-         MHD_mutex_destroy_chk_ 
(&daemon->worker_pool[i].cleanup_connection_mutex);
+            }
+          /* Start harvesting. */
+          for (i = 0; i < daemon->worker_pool_size; ++i)
+            {
+              if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
+                MHD_PANIC (_("Failed to join a thread\n"));
 #ifdef EPOLL_SUPPORT
-         if (-1 != daemon->worker_pool[i].epoll_fd)
-           MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
+              if (-1 != daemon->worker_pool[i].epoll_fd)
+                MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
 #if HTTPS_SUPPORT
-         if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
-           MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
+              if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
+                MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
 #endif
 #endif
-          /* Individual ITCs are always used */
-          if (1)
-            {
               if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc) )
-                {
-                  MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
-                }
-           }
-       }
-      free (daemon->worker_pool);
+                MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
+              MHD_mutex_destroy_chk_ 
(&daemon->worker_pool[i].cleanup_connection_mutex);
+            }
+          free (daemon->worker_pool);
+        }
+      else
+        {
+          /* Single internal thread is used for select()/poll()/etc. */
+          if (MHD_ITC_IS_VALID_(daemon->itc))
+            {
+              if (! MHD_itc_activate_ (daemon->itc, "e"))
+                MHD_PANIC (_("Failed to signal shutdown via inter-thread 
communication channel"));
+            }
+#ifdef HAVE_LISTEN_SHUTDOWN
+          else
+            {
+              /* fd might be MHD_INVALID_SOCKET here due to 
'MHD_quiesce_daemon' */
+              if (MHD_INVALID_SOCKET != fd)
+                (void) shutdown (fd, SHUT_RDWR);
+            }
+#endif
+          if (! MHD_join_thread_ (daemon->pid))
+            {
+              MHD_PANIC (_("Failed to join a thread\n"));
+            }
+        }
     }
   else
     {
-      /* clean up master threads */
-      if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
-           ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
-             (0 == daemon->worker_pool_size) ) )
-       {
-         if (! MHD_join_thread_ (daemon->pid))
-           {
-             MHD_PANIC (_("Failed to join a thread\n"));
-           }
-       }
+      /* Internal threads are not used for select()/poll()/etc. */
+      close_all_connections (daemon);
     }
-  close_all_connections (daemon);
+
   if (MHD_INVALID_SOCKET != fd)
     MHD_socket_close_chk_ (fd);
 
+  if (MHD_ITC_IS_VALID_ (daemon->itc))
+    MHD_itc_destroy_chk_ (daemon->itc);
+
+#ifdef EPOLL_SUPPORT
+  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
+       (-1 != daemon->epoll_fd) )
+    MHD_socket_close_chk_ (daemon->epoll_fd);
+#if HTTPS_SUPPORT
+  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
+       (-1 != daemon->epoll_upgrade_fd) )
+    MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
+#endif
+#endif
+
   /* TLS clean up */
 #if HTTPS_SUPPORT
   if (MHD_YES == daemon->have_dhparams)
@@ -5428,16 +5630,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
         gnutls_certificate_free_credentials (daemon->x509_cred);
     }
 #endif
-#ifdef EPOLL_SUPPORT
-  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
-       (-1 != daemon->epoll_fd) )
-    MHD_socket_close_chk_ (daemon->epoll_fd);
-#if HTTPS_SUPPORT
-  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
-       (-1 != daemon->epoll_upgrade_fd) )
-    MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
-#endif
-#endif
 
 #ifdef DAUTH_SUPPORT
   free (daemon->nnc);
@@ -5446,8 +5638,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
   MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
   MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
 
-  if (MHD_ITC_IS_VALID_(daemon->itc))
-    MHD_itc_destroy_chk_ (daemon->itc);
   free (daemon);
 }
 
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 4a3fe58..1f239f1 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -1027,12 +1027,12 @@ struct MHD_UpgradeResponseHandle
   /**
    * Number of bytes actually in use in the @e in_buffer
    */
-  size_t in_buffer_off;
+  size_t in_buffer_used;
 
   /**
    * Number of bytes actually in use in the @e out_buffer
    */
-  size_t out_buffer_off;
+  size_t out_buffer_used;
 
   /**
    * The socket we gave to the application (r/w).
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 09e73f9..b0fffe1 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -821,7 +821,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
     urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
     pool = connection->pool;
     avail = MHD_pool_get_free (pool);
-    if (avail < 8)
+    if (avail < RESERVE_EBUF_SIZE)
       {
         /* connection's pool is totally at the limit,
            use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
@@ -839,19 +839,10 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
                                  MHD_NO);
       }
     /* use half the buffer for inbound, half for outbound */
-    avail /= 2;
-    urh->in_buffer_size = avail;
-    urh->out_buffer_size = avail;
+    urh->in_buffer_size = avail / 2;
+    urh->out_buffer_size = avail - urh->in_buffer_size;
     urh->in_buffer = buf;
-    urh->out_buffer = &buf[avail];
-    /* hand over internal socket to application */
-    response->upgrade_handler (response->upgrade_handler_cls,
-                               connection,
-                               connection->client_context,
-                               connection->read_buffer,
-                               rbo,
-                               urh->app.socket,
-                               urh);
+    urh->out_buffer = &buf[urh->in_buffer_size];
 #ifdef EPOLL_SUPPORT
     /* Launch IO processing by the event loop */
     if (0 != (daemon->options & MHD_USE_EPOLL))
@@ -909,10 +900,6 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
 #endif /* EPOLL_SUPPORT */
     if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
       {
-        /* As far as MHD's event loops are concerned, this connection
-           is suspended; it will be resumed once we are done in the
-           #MHD_upgrade_action() function */
-        MHD_suspend_connection (connection);
         /* This takes care of further processing for most event loops:
            simply add to DLL for bi-direcitonal processing */
         DLL_insert (daemon->urh_head,
@@ -921,20 +908,18 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
         /* Keep reference for later removal from the DLL */
         connection->urh = urh;
       }
-    else
-      {
-        /* Our caller will set 'connection->state' to
-           MHD_CONNECTION_UPGRADE, thereby triggering the main method
-           of the thread to switch to bi-directional forwarding. */
-        connection->urh = urh;
-      }
-    return MHD_YES;
   }
-  urh->app.socket = MHD_INVALID_SOCKET;
-  urh->mhd.socket = MHD_INVALID_SOCKET;
+  else
+    {
+      urh->app.socket = MHD_INVALID_SOCKET;
+      urh->mhd.socket = MHD_INVALID_SOCKET;
+    }
 #endif
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
     {
+      /* Our caller will set 'connection->state' to
+         MHD_CONNECTION_UPGRADE, thereby triggering the main method
+         of the thread to switch to bi-directional forwarding or exit. */
       connection->urh = urh;
     }
   else
@@ -944,12 +929,14 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
          #MHD_upgrade_action() function */
       MHD_suspend_connection (connection);
     }
+  /* hand over socket to application */
   response->upgrade_handler (response->upgrade_handler_cls,
                              connection,
                              connection->client_context,
                              connection->read_buffer,
                              rbo,
-                             connection->socket_fd,
+                             (0 == (daemon->options & MHD_USE_TLS) ) ?
+                             connection->socket_fd : urh->app.socket,
                              urh);
   return MHD_YES;
 }


hooks/post-receive
-- 
GNU libmicrohttpd



reply via email to

[Prev in Thread] Current Thread [Next in Thread]