gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [libmicrohttpd] branch master updated: Rewritten logic of h


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated: Rewritten logic of handling "upgraded" TLS connections in epoll mode.
Date: Sun, 19 Mar 2017 12:17:48 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new e3ce8fdf Rewritten logic of handling "upgraded" TLS connections in 
epoll mode.
e3ce8fdf is described below

commit e3ce8fdf5739928c5250863bb2132f041d4cab64
Author: Evgeny Grin (Karlson2k) <address@hidden>
AuthorDate: Sun Mar 12 23:24:37 2017 +0300

    Rewritten logic of handling "upgraded" TLS connections in epoll mode.
---
 ChangeLog                   |   9 +++-
 src/microhttpd/connection.c |   7 +++
 src/microhttpd/daemon.c     | 120 ++++++++++++++++++++++++++++++++++++--------
 src/microhttpd/internal.h   |  31 +++++++++++-
 src/microhttpd/response.c   |   8 ++-
 5 files changed, 149 insertions(+), 26 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 75bd5ff9..6e9ee2b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,11 @@
-Thu Mar 17 10:45:31 MSK 2017
+Sun Mar 19 13:57:30 MSK 2017
+       Rewritten logic of handling "upgraded" TLS connections in epoll mode:
+       used edge trigger instead of level trigger,
+       upgraded "ready" connection are stored in DL-list,
+       fixed handling of more than 128 ready connections,
+       fixed busy-waiting for idle "upgraded" TLS connections. -EG
+
+Fri Mar 17 10:45:31 MSK 2017
        If read buffer is full, MHD need to receive remote data and application
        suspended connection, do not fail while connection is suspended and give
        application one more chance to read data from buffer once connection is
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 5c1a8611..36c05716 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -593,6 +593,13 @@ MHD_connection_finish_forward_ (struct MHD_Connection 
*connection)
     {
       MHD_PANIC (_("Failed to remove FD from epoll set\n"));
     }
+  if (urh->in_eready_list)
+    {
+      EDLL_remove (daemon->eready_urh_head,
+                  daemon->eready_urh_tail,
+                  urh);
+      urh->in_eready_list = false;
+    }
 #endif /* EPOLL_SUPPORT */
   if (MHD_INVALID_SOCKET != urh->mhd.socket)
     {
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 03266204..991577b1 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -3252,7 +3252,11 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
 
 #ifdef EPOLL_SUPPORT
   if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
-       (NULL != daemon->eready_head) )
+       ((NULL != daemon->eready_head)
+#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
+        || (NULL != daemon->eready_urh_head)
+#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
+        ) )
     {
          /* Some connection(s) already have some data pending. */
       *timeout = 0;
@@ -3972,6 +3976,47 @@ MHD_poll (struct MHD_Daemon *daemon,
 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
 
 /**
+ * Checks whether @a urh has some data to process.
+ *
+ * @param urh upgrade handler to analyse
+ * @return 'true' if @a urh has some data to process,
+ *         'false' otherwise
+ */
+static bool
+is_urh_ready(struct MHD_UpgradeResponseHandle * const urh)
+{
+  const struct MHD_Connection * const connection = urh->connection;
+
+  if ( (0 == urh->in_buffer_size) &&
+       (0 == urh->out_buffer_size) &&
+       (0 == urh->in_buffer_used) &&
+       (0 == urh->out_buffer_used) )
+    return false;
+
+  if (connection->daemon->shutdown)
+    return true;
+
+  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
+         (connection->tls_read_ready) ) &&
+       (urh->in_buffer_used < urh->in_buffer_size) )
+    return true;
+
+  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
+       (urh->out_buffer_used < urh->out_buffer_size) )
+    return true;
+
+  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
+       (urh->out_buffer_used > 0) )
+    return true;
+
+  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
+         (urh->in_buffer_used > 0) )
+    return true;
+
+  return false;
+}
+
+/**
  * Do epoll()-based processing for TLS connections that have been
  * upgraded.  This requires a separate epoll() invocation as we
  * cannot use the `struct MHD_Connection` data structures for
@@ -3984,6 +4029,8 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
 {
   struct epoll_event events[MAX_EVENTS];
   int num_events;
+  struct MHD_UpgradeResponseHandle * pos;
+  struct MHD_UpgradeResponseHandle * prev;
 
   num_events = MAX_EVENTS;
   while (MAX_EVENTS == num_events)
@@ -4006,45 +4053,74 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
 #endif
          return MHD_NO;
        }
-      for (i=0;i<(unsigned int) num_events;i++)
+      for (i = 0; i < (unsigned int) num_events; i++)
        {
           struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
           struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
+          bool new_err_state = false;
 
-          /* Each MHD_UpgradeResponseHandle can be processed two times:
-           * one time for TLS data and one time for socketpair data.
-           * If forwarding was finished on first time, second time must
-           * be skipped as urh must not be used anymore. */
           if (urh->clean_ready)
             continue;
 
-          /* Update our state based on what is ready according to epoll() */
+          /* Update ueh state based on what is ready according to epoll() */
           if (0 != (events[i].events & EPOLLIN))
             ueh->celi |= MHD_EPOLL_STATE_READ_READY;
           if (0 != (events[i].events & EPOLLOUT))
             ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
           if (0 != (events[i].events & EPOLLHUP))
             ueh->celi |= MHD_EPOLL_STATE_READ_READY | 
MHD_EPOLL_STATE_WRITE_READY;
-          if (0 != (events[i].events & (EPOLLERR | EPOLLPRI)))
-            ueh->celi |= MHD_EPOLL_STATE_ERROR;
 
-          process_urh (urh);
-          /* Finished forwarding? */
-          if ( (0 == urh->in_buffer_size) &&
-               (0 == urh->out_buffer_size) &&
-               (0 == urh->in_buffer_used) &&
-               (0 == urh->out_buffer_used) )
+          if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
+               (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
+           {
+              /* Process new error state only one time
+               * and avoid continuously marking this connection
+               * as 'ready'. */
+              ueh->celi |= MHD_EPOLL_STATE_ERROR;
+              new_err_state = true;
+           }
+
+          if (! urh->in_eready_list)
             {
-              MHD_connection_finish_forward_ (urh->connection);
-              urh->clean_ready = true;
-              /* If 'urh->was_closed' set to true, connection will be
-               * moved immediately to cleanup list. Otherwise connection
-               * will stay in suspended list until 'urh' will be marked
-               * with 'was_closed' by application. */
-              MHD_resume_connection(urh->connection);
+              if (new_err_state ||
+                 is_urh_ready(urh))
+               {
+                 EDLL_insert (daemon->eready_urh_head,
+                              daemon->eready_urh_tail,
+                              urh);
+                 urh->in_eready_list = true;
+               }
             }
         }
     }
+  prev = daemon->eready_urh_tail;
+  while (NULL != (pos = prev))
+    {
+      prev = pos->prevE;
+      process_urh (pos);
+      if (! is_urh_ready(pos))
+       {
+         EDLL_remove (daemon->eready_urh_head,
+                      daemon->eready_urh_tail,
+                      pos);
+         pos->in_eready_list = false;
+       }
+      /* Finished forwarding? */
+      if ( (0 == pos->in_buffer_size) &&
+           (0 == pos->out_buffer_size) &&
+           (0 == pos->in_buffer_used) &&
+           (0 == pos->out_buffer_used) )
+        {
+          MHD_connection_finish_forward_ (pos->connection);
+          pos->clean_ready = true;
+          /* If 'pos->was_closed' already was set to true, connection
+           * will be moved immediately to cleanup list. Otherwise
+           * connection will stay in suspended list until 'pos' will
+           * be marked with 'was_closed' by application. */
+          MHD_resume_connection(pos->connection);
+        }
+    }
+
   return MHD_YES;
 }
 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 44590878..5350c013 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -1026,6 +1026,23 @@ struct MHD_UpgradeResponseHandle
    */
   struct MHD_UpgradeResponseHandle *prev;
 
+#ifdef EPOLL_SUPPORT
+  /**
+   * Next pointer for the EDLL listing urhs that are epoll-ready.
+   */
+  struct MHD_UpgradeResponseHandle *nextE;
+
+  /**
+   * Previous pointer for the EDLL listing urhs that are epoll-ready.
+   */
+  struct MHD_UpgradeResponseHandle *prevE;
+
+  /**
+   * Specifies whether urh already in EDLL list of ready connections.
+   */
+  bool in_eready_list;
+#endif
+
   /**
    * The buffer for receiving data from TLS to
    * be passed to the application.  Contains @e in_buffer_size
@@ -1217,7 +1234,19 @@ struct MHD_Daemon
    * Tail of EDLL of connections ready for processing (in epoll mode)
    */
   struct MHD_Connection *eready_tail;
-#endif
+
+#ifdef UPGRADE_SUPPORT
+  /**
+   * Head of EDLL of upgraded connections ready for processing (in epoll mode).
+   */
+  struct MHD_UpgradeResponseHandle *eready_urh_head;
+
+  /**
+   * Tail of EDLL of upgraded connections ready for processing (in epoll mode)
+   */
+  struct MHD_UpgradeResponseHandle *eready_urh_tail;
+#endif /* UPGRADE_SUPPORT */
+#endif /* EPOLL_SUPPORT */
 
   /**
    * Head of the XDLL of ALL connections with a default ('normal')
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 9004013f..e8707480 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -851,7 +851,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
 
         EXTRA_CHECK (-1 != daemon->epoll_upgrade_fd);
         /* First, add network socket */
-        event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
+        event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
         event.data.ptr = &urh->app;
         if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
                             EPOLL_CTL_ADD,
@@ -870,7 +870,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
        }
 
         /* Second, add our end of the UNIX socketpair() */
-        event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
+        event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
         event.data.ptr = &urh->mhd;
         if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
                             EPOLL_CTL_ADD,
@@ -894,6 +894,10 @@ MHD_response_execute_upgrade_ (struct MHD_Response 
*response,
           free (urh);
           return MHD_NO;
        }
+       EDLL_insert (daemon->eready_urh_head,
+                    daemon->eready_urh_tail,
+                    urh);
+       urh->in_eready_list = true;
       }
 #endif /* EPOLL_SUPPORT */
     if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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