gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd] branch master updated: Implemented new API function MHD_


From: gnunet
Subject: [libmicrohttpd] branch master updated: Implemented new API function MHD_run_wait().
Date: Thu, 01 Apr 2021 16:54:24 +0200

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 bf25ee3a Implemented new API function MHD_run_wait().
bf25ee3a is described below

commit bf25ee3a3220596b83b6530b06d4106f2f0bfda1
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Thu Apr 1 17:52:08 2021 +0300

    Implemented new API function MHD_run_wait().
---
 ChangeLog                    |   5 +
 src/include/microhttpd.h     |  35 ++++++-
 src/microhttpd/daemon.c      | 201 +++++++++++++++++++++++++-----------
 src/testcurl/.gitignore      |   2 +
 src/testcurl/Makefile.am     |  20 ++++
 src/testcurl/test_get_wait.c | 238 +++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 439 insertions(+), 62 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0a0ddf39..e9a8a28f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu 01 Apr 2021 17:46:00 MSK
+    Added new function MHD_run_wait() useful for single-threaded applications
+    without other network activity.
+    Added tests for the new function. -EG
+
 Wed 17 Mar 2021 20:53:33 MSK
     Re-factored startup log parameters processing. Warn user if wrong logger
     could be used potentially.
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 59170dfe..a4ba9bf1 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -135,7 +135,7 @@ typedef intptr_t ssize_t;
  * they are parsed as decimal numbers.
  * Example: 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00097205
+#define MHD_VERSION 0x00097206
 
 /**
  * Operational results from MHD calls.
@@ -2698,6 +2698,39 @@ _MHD_EXTERN enum MHD_Result
 MHD_run (struct MHD_Daemon *daemon);
 
 
+/**
+ * Run websever operation with possible blocking.
+ * This function do the following: waits for any network event not more than
+ * specified number of milliseconds, processes all incoming and outgoing
+ * data, processes new connections, processes any timed-out connection, and
+ * do other things required to run webserver.
+ * Once all connections are processed, function returns.
+ * This function is useful for quick and simple webserver implementation if
+ * application needs to run a single thread only and does not have any other
+ * network activity.
+ * @param daemon the daemon to run
+ * @param millisec the maximum time in milliseconds to wait for network and
+ *                 other events. Note: there is no guarantee that function
+ *                 blocks for specified amount of time. The real processing
+ *                 time can be shorter (if some data comes earlier) or
+ *                 longer (if data processing requires more time, especially
+ *                 in the user callbacks).
+ *                 If set to '0' then function does not block and processes
+ *                 only already available data (if any).
+ *                 If set to '-1' then function waits for events
+ *                 indefinitely (blocks until next network activity).
+ * @return #MHD_YES on success, #MHD_NO if this
+ *         daemon was not started with the right
+ *         options for this call or some serious
+ *         unrecoverable error occurs.
+ * @note Available since #MHD_VERSION 0x00097206
+ * @ingroup event
+ */
+enum MHD_Result
+MHD_run_wait (struct MHD_Daemon *daemon,
+              int32_t millisec);
+
+
 /**
  * Run webserver operations. This method should be called by clients
  * in combination with #MHD_get_fdset and #MHD_get_timeout() if the
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0fe47228..59eaf953 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -101,16 +101,17 @@ close_all_connections (struct MHD_Daemon *daemon);
 #ifdef EPOLL_SUPPORT
 
 /**
- * Do epoll()-based processing (this function is allowed to
- * block if @a may_block is set to #MHD_YES).
+ * Do epoll()-based processing.
  *
  * @param daemon daemon to run poll loop for
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
+ * @param millisec the maximum time in milliseconds to wait for events,
+ *                 set to '0' for non-blocking processing,
+ *                 set to '-1' to wait indefinitely.
  * @return #MHD_NO on serious errors, #MHD_YES on success
  */
 static enum MHD_Result
 MHD_epoll (struct MHD_Daemon *daemon,
-           int may_block);
+           int32_t millisec);
 
 #endif /* EPOLL_SUPPORT */
 
@@ -3834,6 +3835,35 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
 }
 
 
+/**
+ * Obtain timeout value for polling function for this daemon.
+ * @remark To be called only from the thread that processes
+ * daemon's select()/poll()/etc.
+ *
+ * @param daemon the daemon to query for timeout
+ * @param max_timeout the maximum return value (in milliseconds),
+ *                    ignored if set to '-1'
+ * @return timeout value in milliseconds or -1 if no timeout is expected.
+ */
+static int
+get_timeout_millisec_ (struct MHD_Daemon *daemon,
+                       int32_t max_timeout)
+{
+  MHD_UNSIGNED_LONG_LONG ulltimeout;
+  if (0 == max_timeout)
+    return 0;
+
+  if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
+    return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
+
+  if ( (0 > max_timeout) ||
+       ((uint32_t) max_timeout > ulltimeout) )
+    return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
+
+  return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
+}
+
+
 /**
  * Internal version of #MHD_run_from_select().
  *
@@ -3978,7 +4008,7 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
   {
 #ifdef EPOLL_SUPPORT
     enum MHD_Result ret = MHD_epoll (daemon,
-                                     MHD_NO);
+                                     0);
 
     MHD_cleanup_connections (daemon);
     return ret;
@@ -4003,12 +4033,14 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
  * and then #internal_run_from_select with the result.
  *
  * @param daemon daemon to run select() loop for
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
+ * @param millisec the maximum time in milliseconds to wait for events,
+ *                 set to '0' for non-blocking processing,
+ *                 set to '-1' to wait indefinitely.
  * @return #MHD_NO on serious errors, #MHD_YES on success
  */
 static enum MHD_Result
 MHD_select (struct MHD_Daemon *daemon,
-            int may_block)
+            int32_t millisec)
 {
   int num_ready;
   fd_set rs;
@@ -4017,7 +4049,6 @@ MHD_select (struct MHD_Daemon *daemon,
   MHD_socket maxsock;
   struct timeval timeout;
   struct timeval *tv;
-  MHD_UNSIGNED_LONG_LONG ltimeout;
   int err_state;
   MHD_socket ls;
 
@@ -4033,7 +4064,7 @@ MHD_select (struct MHD_Daemon *daemon,
   if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
        (MHD_NO != resume_suspended_connections (daemon)) &&
        (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
-    may_block = MHD_NO;
+    millisec = 0;
 
   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
   {
@@ -4118,25 +4149,47 @@ MHD_select (struct MHD_Daemon *daemon,
     FD_CLR (ls,
             &rs);
   }
-  tv = NULL;
+
   if (MHD_NO != err_state)
-    may_block = MHD_NO;
-  if (MHD_NO == may_block)
+    millisec = 0;
+  tv = NULL;
+  if (0 == millisec)
   {
     timeout.tv_usec = 0;
     timeout.tv_sec = 0;
     tv = &timeout;
   }
-  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
-            (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
+  else
   {
-    /* ltimeout is in ms */
-    timeout.tv_usec = (ltimeout % 1000) * 1000;
-    if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
-      timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
-    else
-      timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
-    tv = &timeout;
+    MHD_UNSIGNED_LONG_LONG ltimeout;
+
+    if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
+         (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
+    {
+      tv = &timeout; /* have timeout value */
+      if ( (0 < millisec) &&
+           (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
+        ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
+    }
+    else if (0 < millisec)
+    {
+      tv = &timeout; /* have timeout value */
+      ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
+    }
+
+    if (NULL != tv)
+    { /* have timeout value */
+      if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
+      {
+        timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
+        timeout.tv_usec = 0;
+      }
+      else
+      {
+        timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
+        timeout.tv_usec = (ltimeout % 1000) * 1000;
+      }
+    }
   }
   num_ready = MHD_SYS_select_ (maxsock + 1,
                                &rs,
@@ -4172,12 +4225,14 @@ MHD_select (struct MHD_Daemon *daemon,
  * socket using poll().
  *
  * @param daemon daemon to run poll loop for
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
+ * @param millisec the maximum time in milliseconds to wait for events,
+ *                 set to '0' for non-blocking processing,
+ *                 set to '-1' to wait indefinitely.
  * @return #MHD_NO on serious errors, #MHD_YES on success
  */
 static enum MHD_Result
 MHD_poll_all (struct MHD_Daemon *daemon,
-              int may_block)
+              int32_t millisec)
 {
   unsigned int num_connections;
   struct MHD_Connection *pos;
@@ -4189,7 +4244,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
 
   if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
        (MHD_NO != resume_suspended_connections (daemon)) )
-    may_block = MHD_NO;
+    millisec = 0;
 
   /* count number of connections and thus determine poll set size */
   num_connections = 0;
@@ -4200,7 +4255,6 @@ MHD_poll_all (struct MHD_Daemon *daemon,
     num_connections += 2;
 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
   {
-    MHD_UNSIGNED_LONG_LONG ltimeout;
     unsigned int i;
     int timeout;
     unsigned int poll_server;
@@ -4243,14 +4297,8 @@ MHD_poll_all (struct MHD_Daemon *daemon,
       poll_itc_idx = (int) poll_server;
       poll_server++;
     }
-    if (may_block == MHD_NO)
-      timeout = 0;
-    else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
-              (MHD_NO == MHD_get_timeout (daemon,
-                                          &ltimeout)) )
-      timeout = -1;
-    else
-      timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
+
+    timeout = get_timeout_millisec_ (daemon, millisec);
 
     i = 0;
     for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
@@ -4494,7 +4542,7 @@ MHD_poll (struct MHD_Daemon *daemon,
     return MHD_NO;
   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
     return MHD_poll_all (daemon,
-                         may_block);
+                         may_block ? -1 : 0);
   return MHD_poll_listen_socket (daemon,
                                  may_block);
 #else
@@ -4685,16 +4733,17 @@ static const char *const epoll_itc_marker = 
"itc_marker";
 
 
 /**
- * Do epoll()-based processing (this function is allowed to
- * block if @a may_block is set to #MHD_YES).
+ * Do epoll()-based processing.
  *
  * @param daemon daemon to run poll loop for
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
+ * @param millisec the maximum time in milliseconds to wait for events,
+ *                 set to '0' for non-blocking processing,
+ *                 set to '-1' to wait indefinitely.
  * @return #MHD_NO on serious errors, #MHD_YES on success
  */
 static enum MHD_Result
 MHD_epoll (struct MHD_Daemon *daemon,
-           int may_block)
+           int32_t millisec)
 {
 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
   static const char *const upgrade_marker = "upgrade_ptr";
@@ -4704,7 +4753,6 @@ MHD_epoll (struct MHD_Daemon *daemon,
   struct epoll_event events[MAX_EVENTS];
   struct epoll_event event;
   int timeout_ms;
-  MHD_UNSIGNED_LONG_LONG timeout_ll;
   int num_events;
   unsigned int i;
   MHD_socket ls;
@@ -4790,23 +4838,9 @@ MHD_epoll (struct MHD_Daemon *daemon,
 
   if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
        (MHD_NO != resume_suspended_connections (daemon)) )
-    may_block = MHD_NO;
+    millisec = 0;
 
-  if (MHD_NO != may_block)
-  {
-    if (MHD_NO != MHD_get_timeout (daemon,
-                                   &timeout_ll))
-    {
-      if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
-        timeout_ms = INT_MAX;
-      else
-        timeout_ms = (int) timeout_ll;
-    }
-    else
-      timeout_ms = -1;
-  }
-  else
-    timeout_ms = 0;
+  timeout_ms = get_timeout_millisec_ (daemon, millisec);
 
   /* Reset. New value will be set when connections are processed. */
   /* Note: Used mostly for uniformity here as same situation is
@@ -5026,24 +5060,69 @@ MHD_run (struct MHD_Daemon *daemon)
   if ( (daemon->shutdown) ||
        (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
     return MHD_NO;
+
+  (void) MHD_run_wait (daemon, 0);
+  return MHD_YES;
+}
+
+
+/**
+ * Run websever operation with possible blocking.
+ * This function do the following: waits for any network event not more than
+ * specified number of milliseconds, processes all incoming and outgoing
+ * data, processes new connections, processes any timed-out connection, and
+ * do other things required to run webserver.
+ * Once all connections are processed, function returns.
+ * This function is useful for quick and simple webserver implementation if
+ * application needs to run a single thread only and does not have any other
+ * network activity.
+ * @param daemon the daemon to run
+ * @param millisec the maximum time in milliseconds to wait for network and
+ *                 other events. Note: there is no guarantee that function
+ *                 blocks for specified amount of time. The real processing
+ *                 time can be shorter (if some data comes earlier) or
+ *                 longer (if data processing requires more time, especially
+ *                 in the user callbacks).
+ *                 If set to '0' then function does not block and processes
+ *                 only already available data (if any).
+ *                 If set to '-1' then function waits for events
+ *                 indefinitely (blocks until next network activity).
+ * @return #MHD_YES on success, #MHD_NO if this
+ *         daemon was not started with the right
+ *         options for this call or some serious
+ *         unrecoverable error occurs.
+ * @note Available since #MHD_VERSION 0x00097206
+ * @ingroup event
+ */
+enum MHD_Result
+MHD_run_wait (struct MHD_Daemon *daemon,
+              int32_t millisec)
+{
+  enum MHD_Result res;
+  if ( (daemon->shutdown) ||
+       (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
+    return MHD_NO;
+
+  if (0 > millisec)
+    millisec = -1;
   if (0 != (daemon->options & MHD_USE_POLL))
   {
-    MHD_poll (daemon, MHD_NO);
+    res = MHD_poll_all (daemon, millisec);
     MHD_cleanup_connections (daemon);
   }
 #ifdef EPOLL_SUPPORT
   else if (0 != (daemon->options & MHD_USE_EPOLL))
   {
-    MHD_epoll (daemon, MHD_NO);
+    res = MHD_epoll (daemon, millisec);
     MHD_cleanup_connections (daemon);
   }
 #endif
   else
   {
-    MHD_select (daemon, MHD_NO);
+    res = MHD_select (daemon, millisec);
     /* MHD_select does MHD_cleanup_connections already */
   }
-  return MHD_YES;
+  return res;
 }
 
 
@@ -5139,10 +5218,10 @@ MHD_polling_thread (void *cls)
       MHD_poll (daemon, MHD_YES);
 #ifdef EPOLL_SUPPORT
     else if (0 != (daemon->options & MHD_USE_EPOLL))
-      MHD_epoll (daemon, MHD_YES);
+      MHD_epoll (daemon, -1);
 #endif
     else
-      MHD_select (daemon, MHD_YES);
+      MHD_select (daemon, -1);
     MHD_cleanup_connections (daemon);
   }
 
diff --git a/src/testcurl/.gitignore b/src/testcurl/.gitignore
index 008262bd..bbc1b2a9 100644
--- a/src/testcurl/.gitignore
+++ b/src/testcurl/.gitignore
@@ -118,3 +118,5 @@ test_patch11
 core
 /test_get_iovec
 /test_get_iovec11
+/test_get_wait
+/test_get_wait11
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index d0580554..66aebe3e 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -46,6 +46,8 @@ THREAD_ONLY_TESTS += \
 endif
 
 THREAD_ONLY_TESTS += \
+  test_get_wait \
+  test_get_wait11 \
   test_quiesce \
   $(EMPTY_ITEM)
 
@@ -232,6 +234,24 @@ test_get_sendfile_LDADD = \
   $(top_builddir)/src/microhttpd/libmicrohttpd.la \
   @LIBCURL@
 
+test_get_wait_SOURCES = \
+  test_get_wait.c \
+  mhd_has_in_name.h
+test_get_wait_CFLAGS = \
+  $(PTHREAD_CFLAGS) $(AM_CFLAGS)
+test_get_wait_LDADD = \
+  $(top_builddir)/src/microhttpd/libmicrohttpd.la \
+  $(PTHREAD_LIBS) @LIBCURL@
+
+test_get_wait11_SOURCES = \
+  test_get_wait.c \
+  mhd_has_in_name.h
+test_get_wait11_CFLAGS = \
+  $(PTHREAD_CFLAGS) $(AM_CFLAGS)
+test_get_wait11_LDADD = \
+  $(top_builddir)/src/microhttpd/libmicrohttpd.la \
+  $(PTHREAD_LIBS) @LIBCURL@
+
 test_urlparse_SOURCES = \
   test_urlparse.c mhd_has_in_name.h
 test_urlparse_LDADD = \
diff --git a/src/testcurl/test_get_wait.c b/src/testcurl/test_get_wait.c
new file mode 100644
index 00000000..cfabd2d1
--- /dev/null
+++ b/src/testcurl/test_get_wait.c
@@ -0,0 +1,238 @@
+/*
+     This file is part of libmicrohttpd
+     Copyright (C) 2007, 2009, 2011 Christian Grothoff
+     Copyright (C) 2016-2021 Karlson2k (Evgeny Grin)
+
+     libmicrohttpd is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     libmicrohttpd is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with libmicrohttpd; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file test_get_wait.c
+ * @brief Test 'MHD_run_wait()' function.
+ * @author Christian Grothoff
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "MHD_config.h"
+#include "platform.h"
+#include <curl/curl.h>
+#include <microhttpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <pthread.h>
+#include "mhd_has_in_name.h"
+
+#if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 2
+#undef MHD_CPU_COUNT
+#endif
+#if ! defined(MHD_CPU_COUNT)
+#define MHD_CPU_COUNT 2
+#endif
+
+/**
+ * How many rounds of operations do we do for each
+ * test.
+ * Check all three types of requests for HTTP/1.1:
+ * * first request, new connection;
+ * * "middle" request, existing connection with stay-alive;
+ * * final request, no data processed after.
+ */
+#define ROUNDS 3
+
+/**
+ * Do we use HTTP 1.1?
+ */
+static int oneone;
+
+/**
+ * Response to return (re-used).
+ */
+static struct MHD_Response *response;
+
+/**
+ * Set to 1 if the worker threads are done.
+ */
+static volatile int signal_done;
+
+
+static size_t
+copyBuffer (void *ptr,
+            size_t size, size_t nmemb,
+            void *ctx)
+{
+  (void) ptr; (void) ctx;          /* Unused. Silent compiler warning. */
+  return size * nmemb;
+}
+
+
+static enum MHD_Result
+ahc_echo (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *version,
+          const char *upload_data, size_t *upload_data_size,
+          void **unused)
+{
+  static int ptr;
+  const char *me = cls;
+  enum MHD_Result ret;
+  (void) url; (void) version;                      /* Unused. Silent compiler 
warning. */
+  (void) upload_data; (void) upload_data_size;     /* Unused. Silent compiler 
warning. */
+
+  if (0 != strcmp (me, method))
+    return MHD_NO;              /* unexpected method */
+  if (&ptr != *unused)
+  {
+    *unused = &ptr;
+    return MHD_YES;
+  }
+  *unused = NULL;
+  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+  if (ret == MHD_NO)
+    abort ();
+  return ret;
+}
+
+
+static void *
+thread_gets (void *param)
+{
+  CURL *c;
+  CURLcode errornum;
+  unsigned int i;
+  char url[64];
+  int port = (int) (intptr_t) param;
+
+  snprintf (url,
+            sizeof (url),
+            "http://127.0.0.1:%d/hello_world";,
+            port);
+
+  c = curl_easy_init ();
+  if (NULL == c)
+    _exit (99);
+  curl_easy_setopt (c, CURLOPT_URL, url);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, NULL);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 15L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
+  for (i = 0; i < ROUNDS; i++)
+  {
+    if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      signal_done = 1;
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      abort ();
+    }
+  }
+  curl_easy_cleanup (c);
+  signal_done = 1;
+
+  return NULL;
+}
+
+
+static int
+testRunWaitGet (int port, int poll_flag)
+{
+  pthread_t get_tid;
+  struct MHD_Daemon *d;
+  const char *const test_desc = ((poll_flag & MHD_USE_AUTO) ?
+                                 "MHD_USE_AUTO" :
+                                 (poll_flag & MHD_USE_POLL) ?
+                                 "MHD_USE_POLL" :
+                                 (poll_flag & MHD_USE_EPOLL) ?
+                                 "MHD_USE_EPOLL" :
+                                 "select()");
+
+  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
+    port = 0;
+
+  printf ("Starting MHD_run_wait() test with MHD in %s polling mode.\n",
+          test_desc);
+  signal_done = 0;
+  d = MHD_start_daemon (MHD_USE_ERROR_LOG | poll_flag,
+                        port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
+  if (d == NULL)
+    abort ();
+  if (0 == port)
+  {
+    const union MHD_DaemonInfo *dinfo;
+    dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+    if ((NULL == dinfo) || (0 == dinfo->port) )
+      abort ();
+    port = (int) dinfo->port;
+  }
+
+  if (0 != pthread_create (&get_tid, NULL,
+                           &thread_gets, (void*) (intptr_t) port))
+    _exit (99);
+
+  /* As another thread sets "done" flag after ending of network
+   * activity, it's required to set positive timeout value for MHD_run_wait().
+   * Alternatively, to use timeout value "-1" here, another thread should start
+   * additional connection to wake MHD after setting "done" flag. */
+  do
+  {
+    if (MHD_NO == MHD_run_wait (d, 50))
+      abort ();
+  } while (0 == signal_done);
+
+  if (0 != pthread_join (get_tid, NULL))
+    _exit (99);
+
+  MHD_stop_daemon (d);
+  printf ("Test succeeded.\n");
+  return 0;
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+  int port = 1675;
+  (void) argc;   /* Unused. Silent compiler warning. */
+
+  if ((NULL == argv) || (0 == argv[0]))
+    return 99;
+  oneone = has_in_name (argv[0], "11");
+  if (oneone)
+    port += 5;
+  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    return 2;
+  response = MHD_create_response_from_buffer (strlen ("/hello_world"),
+                                              "/hello_world",
+                                              MHD_RESPMEM_MUST_COPY);
+  testRunWaitGet (port++, 0);
+  if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_EPOLL))
+    testRunWaitGet (port++, MHD_USE_EPOLL);
+  testRunWaitGet (port++, MHD_USE_AUTO);
+
+  MHD_destroy_response (response);
+  curl_global_cleanup ();
+  return 0; /* Errors produce abort() or _exit() */
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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