summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac32
-rw-r--r--m4/ax_have_epoll.m4104
-rw-r--r--src/bank-lib/fakebank.c62
3 files changed, 195 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 810c437b4..3c7151ae1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,6 +88,38 @@ AC_MSG_RESULT($enable_expensive)
AM_CONDITIONAL([HAVE_EXPENSIVE_TESTS], [test "x$enable_expensive" = "xyes"])
+AC_ARG_ENABLE([[epoll]],
+ [AS_HELP_STRING([[--enable-epoll[=ARG]]], [enable epoll support (yes, no, auto) [auto]])],
+ [enable_epoll=${enableval}],
+ [enable_epoll='auto']
+ )
+
+AS_IF([test "$enable_epoll" != "no"],
+ [AX_HAVE_EPOLL
+ AS_IF([test "${ax_cv_have_epoll}" = "yes"],
+ [AC_DEFINE([[EPOLL_SUPPORT]],[[1]],[Define to 1 to enable epoll support])
+ enable_epoll='yes'],
+ [AS_IF([test "$enable_epoll" = "yes"],
+ AC_MSG_ERROR([[Support for epoll was explicitly requested but cannot be enabled on this platform.]]))
+ enable_epoll='no'])])
+
+AM_CONDITIONAL([MHD_HAVE_EPOLL], [[test "x$enable_epoll" = xyes]])
+
+AS_IF([test "x$enable_epoll" = "xyes"],
+ AC_CACHE_CHECK([for epoll_create1()],
+ [mhd_cv_have_epoll_create1], [
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <sys/epoll.h>
+ ]], [[
+int fd;
+fd = epoll_create1(EPOLL_CLOEXEC);]])],
+ [mhd_cv_have_epoll_create1=yes],
+ [mhd_cv_have_epoll_create1=no])])
+ AS_IF([test "x$mhd_cv_have_epoll_create1" = "xyes"],[
+ AC_DEFINE([[HAVE_EPOLL_CREATE1]], [[1]], [Define if you have epoll_create1 function.])]))
+
+
if test "$wallet_only" != yes
then
diff --git a/m4/ax_have_epoll.m4 b/m4/ax_have_epoll.m4
new file mode 100644
index 000000000..9d9bc8736
--- /dev/null
+++ b/m4/ax_have_epoll.m4
@@ -0,0 +1,104 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_have_epoll.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_HAVE_EPOLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# AX_HAVE_EPOLL_PWAIT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# This macro determines whether the system supports the epoll I/O event
+# interface. A neat usage example would be:
+#
+# AX_HAVE_EPOLL(
+# [AX_CONFIG_FEATURE_ENABLE(epoll)],
+# [AX_CONFIG_FEATURE_DISABLE(epoll)])
+# AX_CONFIG_FEATURE(
+# [epoll], [This platform supports epoll(7)],
+# [HAVE_EPOLL], [This platform supports epoll(7).])
+#
+# The epoll interface was added to the Linux kernel in version 2.5.45, and
+# the macro verifies that a kernel newer than this is installed. This
+# check is somewhat unreliable if <linux/version.h> doesn't match the
+# running kernel, but it is necessary regardless, because glibc comes with
+# stubs for the epoll_create(), epoll_wait(), etc. that allow programs to
+# compile and link even if the kernel is too old; the problem would then
+# be detected only at runtime.
+#
+# Linux kernel version 2.6.19 adds the epoll_pwait() call in addition to
+# epoll_wait(). The availability of that function can be tested with the
+# second macro. Generally speaking, it is safe to assume that
+# AX_HAVE_EPOLL would succeed if AX_HAVE_EPOLL_PWAIT has, but not the
+# other way round.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Peter Simons <simons@cryp.to>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 11
+
+AC_DEFUN([AX_HAVE_EPOLL], [dnl
+ ax_have_epoll_cppflags="${CPPFLAGS}"
+ AC_CHECK_HEADER([linux/version.h], [CPPFLAGS="${CPPFLAGS} -DHAVE_LINUX_VERSION_H"])
+ AC_MSG_CHECKING([for Linux epoll(7) interface])
+ AC_CACHE_VAL([ax_cv_have_epoll], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM([dnl
+#include <sys/epoll.h>
+#ifdef HAVE_LINUX_VERSION_H
+# include <linux/version.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45)
+# error linux kernel version is too old to have epoll
+# endif
+#endif
+], [dnl
+int fd, rc;
+struct epoll_event ev;
+fd = epoll_create(128);
+rc = epoll_wait(fd, &ev, 1, 0);])],
+ [ax_cv_have_epoll=yes],
+ [ax_cv_have_epoll=no])])
+ CPPFLAGS="${ax_have_epoll_cppflags}"
+ AS_IF([test "${ax_cv_have_epoll}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl
+
+AC_DEFUN([AX_HAVE_EPOLL_PWAIT], [dnl
+ ax_have_epoll_cppflags="${CPPFLAGS}"
+ AC_CHECK_HEADER([linux/version.h],
+ [CPPFLAGS="${CPPFLAGS} -DHAVE_LINUX_VERSION_H"])
+ AC_MSG_CHECKING([for Linux epoll(7) interface with signals extension])
+ AC_CACHE_VAL([ax_cv_have_epoll_pwait], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM([dnl
+#ifdef HAVE_LINUX_VERSION_H
+# include <linux/version.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+# error linux kernel version is too old to have epoll_pwait
+# endif
+#endif
+#include <sys/epoll.h>
+#include <signal.h>
+], [dnl
+int fd, rc;
+struct epoll_event ev;
+fd = epoll_create(128);
+rc = epoll_wait(fd, &ev, 1, 0);
+rc = epoll_pwait(fd, &ev, 1, 0, (sigset_t const *)(0));])],
+ [ax_cv_have_epoll_pwait=yes],
+ [ax_cv_have_epoll_pwait=no])])
+ CPPFLAGS="${ax_have_epoll_cppflags}"
+ AS_IF([test "${ax_cv_have_epoll_pwait}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index 2a8164684..6f9959ab8 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2016, 2017 Inria and GNUnet e.V.
+ (C) 2016, 2017, 2018 Inria and GNUnet e.V.
TALER 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
@@ -19,7 +19,6 @@
* @brief library that fakes being a Taler bank for testcases
* @author Christian Grothoff <christian@grothoff.org>
*/
-
#include "platform.h"
#include "taler_fakebank_lib.h"
#include "taler_bank_service.h"
@@ -125,6 +124,18 @@ struct TALER_FAKEBANK_Handle
* Number of transactions.
*/
uint64_t serial_counter;
+
+#if EPOLL_SUPPORT
+ /**
+ * Boxed @e mhd_fd.
+ */
+ struct GNUNET_NETWORK_Handle *mhd_rfd;
+
+ /**
+ * File descriptor to use to wait for MHD.
+ */
+ int mhd_fd;
+#endif
};
@@ -328,6 +339,9 @@ TALER_FAKEBANK_stop (struct TALER_FAKEBANK_Handle *h)
GNUNET_SCHEDULER_cancel (h->mhd_task);
h->mhd_task = NULL;
}
+#if EPOLL_SUPPORT
+ GNUNET_NETWORK_socket_free_memory_only_ (h->mhd_rfd);
+#endif
if (NULL != h->mhd_bank)
{
MHD_stop_daemon (h->mhd_bank);
@@ -976,10 +990,42 @@ static void
run_mhd (void *cls);
+#if EPOLL_SUPPORT
+/**
+ * Schedule MHD. This function should be called initially when an
+ * MHD is first getting its client socket, and will then automatically
+ * always be called later whenever there is work to be done.
+ *
+ * @param h fakebank handle to schedule MHD for
+ */
+static void
+schedule_httpd (struct TALER_FAKEBANK_Handle *h)
+{
+ int haveto;
+ MHD_UNSIGNED_LONG_LONG timeout;
+ struct GNUNET_TIME_Relative tv;
+
+ haveto = MHD_get_timeout (h->mhd_bank,
+ &timeout);
+ if (MHD_YES == haveto)
+ tv.rel_value_us = (uint64_t) timeout * 1000LL;
+ else
+ tv = GNUNET_TIME_UNIT_FOREVER_REL;
+ if (NULL != h->mhd_task)
+ GNUNET_SCHEDULER_cancel (h->mhd_task);
+ h->mhd_task =
+ GNUNET_SCHEDULER_add_read_net (tv,
+ h->mhd_rfd,
+ &run_mhd,
+ h);
+}
+#else
/**
* Schedule MHD. This function should be called initially when an
* MHD is first getting its client socket, and will then automatically
* always be called later whenever there is work to be done.
+ *
+ * @param h fakebank handle to schedule MHD for
*/
static void
schedule_httpd (struct TALER_FAKEBANK_Handle *h)
@@ -1033,6 +1079,7 @@ schedule_httpd (struct TALER_FAKEBANK_Handle *h)
if (NULL != wws)
GNUNET_NETWORK_fdset_destroy (wws);
}
+#endif
/**
@@ -1063,7 +1110,11 @@ TALER_FAKEBANK_start (uint16_t port)
struct TALER_FAKEBANK_Handle *h;
h = GNUNET_new (struct TALER_FAKEBANK_Handle);
- h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_DUAL_STACK,
+ h->mhd_bank = MHD_start_daemon (MHD_USE_DEBUG
+#if EPOLL_SUPPORT
+ | MHD_USE_EPOLL
+#endif
+ | MHD_USE_DUAL_STACK,
port,
NULL, NULL,
&handle_mhd_request, h,
@@ -1075,6 +1126,11 @@ TALER_FAKEBANK_start (uint16_t port)
GNUNET_free (h);
return NULL;
}
+#if EPOLL_SUPPORT
+ h->mhd_fd = MHD_get_daemon_info (h->mhd_bank,
+ MHD_DAEMON_INFO_EPOLL_FD)->epoll_fd;
+ h->mhd_rfd = GNUNET_NETWORK_socket_box_native (h->mhd_fd);
+#endif
schedule_httpd (h);
return h;
}