exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

mhd_run.c (5512B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2019-2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file mhd_run.c
     18  * @brief API for running an MHD daemon with the
     19  *        GNUnet scheduler
     20  * @author Christian Grothoff
     21  */
     22 #include <gnunet/gnunet_util_lib.h>
     23 #include <gnunet/gnunet_json_lib.h>
     24 #include <jansson.h>
     25 #include <microhttpd.h>
     26 #include "taler/taler_util.h"
     27 #include "taler/taler_mhd_lib.h"
     28 
     29 
     30 /**
     31  * Entry in list of HTTP servers we are running.
     32  */
     33 struct DaemonEntry
     34 {
     35   /**
     36    * Kept in a DLL.
     37    */
     38   struct DaemonEntry *next;
     39 
     40   /**
     41    * Kept in a DLL.
     42    */
     43   struct DaemonEntry *prev;
     44 
     45   /**
     46    * The actual daemon.
     47    */
     48   struct MHD_Daemon *mhd;
     49 
     50   /**
     51    * Task running the HTTP server.
     52    */
     53   struct GNUNET_SCHEDULER_Task *mhd_task;
     54 
     55   /**
     56    * Set to true if we should immediately MHD_run() again.
     57    */
     58   bool triggered;
     59 
     60 };
     61 
     62 
     63 /**
     64  * Head of list of HTTP servers.
     65  */
     66 static struct DaemonEntry *mhd_head;
     67 
     68 /**
     69  * Tail of list of HTTP servers.
     70  */
     71 static struct DaemonEntry *mhd_tail;
     72 
     73 
     74 /**
     75  * Function that queries MHD's select sets and
     76  * starts the task waiting for them.
     77  *
     78  * @param[in,out] de daemon to start tasks for
     79  */
     80 static void
     81 prepare_daemon (struct DaemonEntry *de);
     82 
     83 
     84 /**
     85  * Call MHD to process pending requests and then go back
     86  * and schedule the next run.
     87  *
     88  * @param cls our `struct DaemonEntry *`
     89  */
     90 static void
     91 run_daemon (void *cls)
     92 {
     93   struct DaemonEntry *de = cls;
     94 
     95   de->mhd_task = NULL;
     96   do {
     97     de->triggered = false;
     98     GNUNET_assert (MHD_YES ==
     99                    MHD_run (de->mhd));
    100   } while (de->triggered);
    101   prepare_daemon (de);
    102 }
    103 
    104 
    105 static void
    106 prepare_daemon (struct DaemonEntry *de)
    107 {
    108   fd_set rs;
    109   fd_set ws;
    110   fd_set es;
    111   struct GNUNET_NETWORK_FDSet *wrs;
    112   struct GNUNET_NETWORK_FDSet *wws;
    113   int max;
    114   MHD_UNSIGNED_LONG_LONG timeout;
    115   int haveto;
    116   struct GNUNET_TIME_Relative tv;
    117 
    118   FD_ZERO (&rs);
    119   FD_ZERO (&ws);
    120   FD_ZERO (&es);
    121   wrs = GNUNET_NETWORK_fdset_create ();
    122   wws = GNUNET_NETWORK_fdset_create ();
    123   max = -1;
    124   GNUNET_assert (MHD_YES ==
    125                  MHD_get_fdset (de->mhd,
    126                                 &rs,
    127                                 &ws,
    128                                 &es,
    129                                 &max));
    130   haveto = MHD_get_timeout (de->mhd,
    131                             &timeout);
    132   if (haveto == MHD_YES)
    133     tv = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
    134                                         timeout);
    135   else
    136     tv = GNUNET_TIME_UNIT_FOREVER_REL;
    137   GNUNET_NETWORK_fdset_copy_native (wrs,
    138                                     &rs,
    139                                     max + 1);
    140   GNUNET_NETWORK_fdset_copy_native (wws,
    141                                     &ws,
    142                                     max + 1);
    143   de->mhd_task
    144     = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
    145                                    tv,
    146                                    wrs,
    147                                    wws,
    148                                    &run_daemon,
    149                                    de);
    150   GNUNET_NETWORK_fdset_destroy (wrs);
    151   GNUNET_NETWORK_fdset_destroy (wws);
    152 }
    153 
    154 
    155 void
    156 TALER_MHD_daemon_start (struct MHD_Daemon *daemon)
    157 {
    158   struct DaemonEntry *de;
    159 
    160   de = GNUNET_new (struct DaemonEntry);
    161   de->mhd = daemon;
    162   GNUNET_CONTAINER_DLL_insert (mhd_head,
    163                                mhd_tail,
    164                                de);
    165   prepare_daemon (de);
    166 }
    167 
    168 
    169 void
    170 TALER_MHD_daemons_halt (void)
    171 {
    172   for (struct DaemonEntry *de = mhd_head;
    173        NULL != de;
    174        de = de->next)
    175   {
    176     if (NULL != de->mhd_task)
    177     {
    178       GNUNET_SCHEDULER_cancel (de->mhd_task);
    179       de->mhd_task = NULL;
    180     }
    181     de->triggered = false;
    182   }
    183 }
    184 
    185 
    186 void
    187 TALER_MHD_daemons_quiesce (void)
    188 {
    189   for (struct DaemonEntry *de = mhd_head;
    190        NULL != de;
    191        de = de->next)
    192   {
    193     int fd;
    194 
    195     if (NULL != de->mhd_task)
    196     {
    197       GNUNET_SCHEDULER_cancel (de->mhd_task);
    198       de->mhd_task = NULL;
    199     }
    200     de->triggered = false;
    201     fd = MHD_quiesce_daemon  (de->mhd);
    202     GNUNET_break (0 == close (fd));
    203   }
    204 }
    205 
    206 
    207 void
    208 TALER_MHD_daemons_destroy (void)
    209 {
    210   struct DaemonEntry *de;
    211 
    212   while (NULL != (de = mhd_head))
    213   {
    214     struct MHD_Daemon *mhd = de->mhd;
    215 
    216     if (NULL != de->mhd_task)
    217     {
    218       GNUNET_SCHEDULER_cancel (de->mhd_task);
    219       de->mhd_task = NULL;
    220     }
    221     MHD_stop_daemon (mhd);
    222     GNUNET_CONTAINER_DLL_remove (mhd_head,
    223                                  mhd_tail,
    224                                  de);
    225     GNUNET_free (de);
    226   }
    227 }
    228 
    229 
    230 void
    231 TALER_MHD_daemon_trigger (void)
    232 {
    233   for (struct DaemonEntry *de = mhd_head;
    234        NULL != de;
    235        de = de->next)
    236   {
    237     if (NULL != de->mhd_task)
    238     {
    239       GNUNET_SCHEDULER_cancel (de->mhd_task);
    240       de->mhd_task = GNUNET_SCHEDULER_add_now (&run_daemon,
    241                                                de);
    242     }
    243     else
    244     {
    245       de->triggered = true;
    246     }
    247   }
    248 }
    249 
    250 
    251 /* end of mhd_run.c */