LCOV - code coverage report
Current view: top level - mhd - mhd_run.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 80.3 % 71 57
Test Date: 2026-04-14 15:39:31 Functions: 85.7 % 7 6

            Line data    Source code
       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         2518 : run_daemon (void *cls)
      92              : {
      93         2518 :   struct DaemonEntry *de = cls;
      94              : 
      95         2518 :   de->mhd_task = NULL;
      96              :   do {
      97         2518 :     de->triggered = false;
      98         2518 :     GNUNET_assert (MHD_YES ==
      99              :                    MHD_run (de->mhd));
     100         2518 :   } while (de->triggered);
     101         2518 :   prepare_daemon (de);
     102         2518 : }
     103              : 
     104              : 
     105              : static void
     106         2564 : 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        43588 :   FD_ZERO (&rs);
     119        43588 :   FD_ZERO (&ws);
     120        43588 :   FD_ZERO (&es);
     121         2564 :   wrs = GNUNET_NETWORK_fdset_create ();
     122         2564 :   wws = GNUNET_NETWORK_fdset_create ();
     123         2564 :   max = -1;
     124         2564 :   GNUNET_assert (MHD_YES ==
     125              :                  MHD_get_fdset (de->mhd,
     126              :                                 &rs,
     127              :                                 &ws,
     128              :                                 &es,
     129              :                                 &max));
     130         2564 :   haveto = MHD_get_timeout (de->mhd,
     131              :                             &timeout);
     132         2564 :   if (haveto == MHD_YES)
     133         1777 :     tv = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
     134              :                                         timeout);
     135              :   else
     136          787 :     tv = GNUNET_TIME_UNIT_FOREVER_REL;
     137         2564 :   GNUNET_NETWORK_fdset_copy_native (wrs,
     138              :                                     &rs,
     139              :                                     max + 1);
     140         2564 :   GNUNET_NETWORK_fdset_copy_native (wws,
     141              :                                     &ws,
     142              :                                     max + 1);
     143              :   de->mhd_task
     144         2564 :     = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
     145              :                                    tv,
     146              :                                    wrs,
     147              :                                    wws,
     148              :                                    &run_daemon,
     149              :                                    de);
     150         2564 :   GNUNET_NETWORK_fdset_destroy (wrs);
     151         2564 :   GNUNET_NETWORK_fdset_destroy (wws);
     152         2564 : }
     153              : 
     154              : 
     155              : void
     156           46 : TALER_MHD_daemon_start (struct MHD_Daemon *daemon)
     157              : {
     158              :   struct DaemonEntry *de;
     159              : 
     160           46 :   de = GNUNET_new (struct DaemonEntry);
     161           46 :   de->mhd = daemon;
     162           46 :   GNUNET_CONTAINER_DLL_insert (mhd_head,
     163              :                                mhd_tail,
     164              :                                de);
     165           46 :   prepare_daemon (de);
     166           46 : }
     167              : 
     168              : 
     169              : void
     170           23 : TALER_MHD_daemons_halt (void)
     171              : {
     172           23 :   for (struct DaemonEntry *de = mhd_head;
     173           69 :        NULL != de;
     174           46 :        de = de->next)
     175              :   {
     176           46 :     if (NULL != de->mhd_task)
     177              :     {
     178           46 :       GNUNET_SCHEDULER_cancel (de->mhd_task);
     179           46 :       de->mhd_task = NULL;
     180              :     }
     181           46 :     de->triggered = false;
     182              :   }
     183           23 : }
     184              : 
     185              : 
     186              : void
     187            0 : TALER_MHD_daemons_quiesce (void)
     188              : {
     189            0 :   for (struct DaemonEntry *de = mhd_head;
     190            0 :        NULL != de;
     191            0 :        de = de->next)
     192              :   {
     193              :     int fd;
     194              : 
     195            0 :     if (NULL != de->mhd_task)
     196              :     {
     197            0 :       GNUNET_SCHEDULER_cancel (de->mhd_task);
     198            0 :       de->mhd_task = NULL;
     199              :     }
     200            0 :     de->triggered = false;
     201            0 :     fd = MHD_quiesce_daemon  (de->mhd);
     202            0 :     GNUNET_break (0 == close (fd));
     203              :   }
     204            0 : }
     205              : 
     206              : 
     207              : void
     208           23 : TALER_MHD_daemons_destroy (void)
     209              : {
     210              :   struct DaemonEntry *de;
     211              : 
     212           69 :   while (NULL != (de = mhd_head))
     213              :   {
     214           46 :     struct MHD_Daemon *mhd = de->mhd;
     215              : 
     216           46 :     if (NULL != de->mhd_task)
     217              :     {
     218            0 :       GNUNET_SCHEDULER_cancel (de->mhd_task);
     219            0 :       de->mhd_task = NULL;
     220              :     }
     221           46 :     MHD_stop_daemon (mhd);
     222           46 :     GNUNET_CONTAINER_DLL_remove (mhd_head,
     223              :                                  mhd_tail,
     224              :                                  de);
     225           46 :     GNUNET_free (de);
     226              :   }
     227           23 : }
     228              : 
     229              : 
     230              : void
     231          222 : TALER_MHD_daemon_trigger (void)
     232              : {
     233          222 :   for (struct DaemonEntry *de = mhd_head;
     234          666 :        NULL != de;
     235          444 :        de = de->next)
     236              :   {
     237          444 :     if (NULL != de->mhd_task)
     238              :     {
     239          444 :       GNUNET_SCHEDULER_cancel (de->mhd_task);
     240          444 :       de->mhd_task = GNUNET_SCHEDULER_add_now (&run_daemon,
     241              :                                                de);
     242              :     }
     243              :     else
     244              :     {
     245            0 :       de->triggered = true;
     246              :     }
     247              :   }
     248          222 : }
     249              : 
     250              : 
     251              : /* end of mhd_run.c */
        

Generated by: LCOV version 2.0-1