From c559b1c935a93c4cdec442beeac59264d483c824 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 23 Aug 2021 00:00:32 +0200 Subject: complete implementation of long-polling for reserve status; remove support for multi-threaded exchange httpd --- src/mhd/Makefile.am | 3 +- src/mhd/mhd_config.c | 47 ++++++++++++++ src/mhd/mhd_run.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 src/mhd/mhd_run.c (limited to 'src/mhd') diff --git a/src/mhd/Makefile.am b/src/mhd/Makefile.am index 059c275cc..f7f052d51 100644 --- a/src/mhd/Makefile.am +++ b/src/mhd/Makefile.am @@ -13,7 +13,8 @@ libtalermhd_la_SOURCES = \ mhd_config.c \ mhd_legal.c \ mhd_parsing.c \ - mhd_responses.c + mhd_responses.c \ + mhd_run.c libtalermhd_la_LDFLAGS = \ -version-info 0:0:0 \ -no-undefined diff --git a/src/mhd/mhd_config.c b/src/mhd/mhd_config.c index a619bba11..d6e1a25cf 100644 --- a/src/mhd/mhd_config.c +++ b/src/mhd/mhd_config.c @@ -322,6 +322,53 @@ TALER_MHD_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, char *bind_to; struct GNUNET_NETWORK_Handle *nh; + /* try systemd passing first */ + { + const char *listen_pid; + const char *listen_fds; + + /* check for systemd-style FD passing */ + listen_pid = getenv ("LISTEN_PID"); + listen_fds = getenv ("LISTEN_FDS"); + if ( (NULL != listen_pid) && + (NULL != listen_fds) && + (getpid () == strtol (listen_pid, + NULL, + 10)) && + (1 == strtoul (listen_fds, + NULL, + 10)) ) + { + int fh; + int flags; + + fh = 3; + flags = fcntl (fh, + F_GETFD); + if ( (-1 == flags) && + (EBADF == errno) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Bad listen socket passed, ignored\n"); + fh = -1; + } + flags |= FD_CLOEXEC; + if ( (-1 != fh) && + (0 != fcntl (fh, + F_SETFD, + flags)) ) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "fcntl"); + if (-1 != fh) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Successfully obtained listen socket from hypervisor\n"); + return fh; + } + } + } + + /* now try configuration file */ *port = 0; { char *serve_unixpath; diff --git a/src/mhd/mhd_run.c b/src/mhd/mhd_run.c new file mode 100644 index 000000000..8a3c369b9 --- /dev/null +++ b/src/mhd/mhd_run.c @@ -0,0 +1,174 @@ +/* + This file is part of TALER + Copyright (C) 2019-2021 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see +*/ +/** + * @file mhd_run.c + * @brief API for running an MHD daemon with the + * GNUnet scheduler + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include +#include +#include "taler_util.h" +#include "taler_mhd_lib.h" + + +/** + * Set if we should immediately #MHD_run again. + */ +static int triggered; + +/** + * Task running the HTTP server. + */ +static struct GNUNET_SCHEDULER_Task *mhd_task; + +/** + * The MHD daemon we are running. + */ +static struct MHD_Daemon *mhd; + + +/** + * Function that queries MHD's select sets and + * starts the task waiting for them. + */ +static struct GNUNET_SCHEDULER_Task * +prepare_daemon (void); + + +/** + * Call MHD to process pending requests and then go back + * and schedule the next run. + * + * @param cls NULL + */ +static void +run_daemon (void *cls) +{ + mhd_task = NULL; + do { + triggered = 0; + GNUNET_assert (MHD_YES == + MHD_run (mhd)); + } while (0 != triggered); + mhd_task = prepare_daemon (); +} + + +/** + * Function that queries MHD's select sets and starts the task waiting for + * them. + * + * @return task handle for the MHD task. + */ +static struct GNUNET_SCHEDULER_Task * +prepare_daemon (void) +{ + struct GNUNET_SCHEDULER_Task *ret; + fd_set rs; + fd_set ws; + fd_set es; + struct GNUNET_NETWORK_FDSet *wrs; + struct GNUNET_NETWORK_FDSet *wws; + int max; + MHD_UNSIGNED_LONG_LONG timeout; + int haveto; + struct GNUNET_TIME_Relative tv; + + FD_ZERO (&rs); + FD_ZERO (&ws); + FD_ZERO (&es); + wrs = GNUNET_NETWORK_fdset_create (); + wws = GNUNET_NETWORK_fdset_create (); + max = -1; + GNUNET_assert (MHD_YES == + MHD_get_fdset (mhd, + &rs, + &ws, + &es, + &max)); + haveto = MHD_get_timeout (mhd, + &timeout); + if (haveto == MHD_YES) + tv = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, + timeout); + else + tv = GNUNET_TIME_UNIT_FOREVER_REL; + GNUNET_NETWORK_fdset_copy_native (wrs, + &rs, + max + 1); + GNUNET_NETWORK_fdset_copy_native (wws, + &ws, + max + 1); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding run_daemon select task\n"); + ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, + tv, + wrs, + wws, + &run_daemon, + NULL); + GNUNET_NETWORK_fdset_destroy (wrs); + GNUNET_NETWORK_fdset_destroy (wws); + return ret; +} + + +void +TALER_MHD_daemon_start (struct MHD_Daemon *daemon) +{ + GNUNET_assert (NULL == mhd); + mhd = daemon; + mhd_task = prepare_daemon (); +} + + +struct MHD_Daemon * +TALER_MHD_daemon_stop (void) +{ + struct MHD_Daemon *ret; + + if (NULL != mhd_task) + { + GNUNET_SCHEDULER_cancel (mhd_task); + mhd_task = NULL; + } + ret = mhd; + mhd = NULL; + return ret; +} + + +void +TALER_MHD_daemon_trigger (void) +{ + if (NULL != mhd_task) + { + GNUNET_SCHEDULER_cancel (mhd_task); + mhd_task = NULL; + run_daemon (NULL); + } + else + { + triggered = 1; + } +} + + +/* end of mhd_run.c */ -- cgit v1.2.3