Просмотр исходного кода

implementing thread_main_connection_upgrade

Christian Grothoff 8 лет назад
Родитель
Сommit
5c8fbeb97b
5 измененных файлов с 218 добавлено и 0 удалено
  1. 42 0
      src/lib/connection_add.c
  2. 60 0
      src/lib/daemon_poll.c
  3. 12 0
      src/lib/daemon_poll.h
  4. 92 0
      src/lib/daemon_select.c
  5. 12 0
      src/lib/daemon_select.h

+ 42 - 0
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 */
 
 
 /**

+ 60 - 0
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 */

+ 12 - 0
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

+ 92 - 0
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

+ 12 - 0
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