libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

daemon_funcs.c (8221B)


      1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
      2 /*
      3   This file is part of GNU libmicrohttpd.
      4   Copyright (C) 2024 Evgeny Grin (Karlson2k)
      5 
      6   GNU libmicrohttpd is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU Lesser General Public
      8   License as published by the Free Software Foundation; either
      9   version 2.1 of the License, or (at your option) any later version.
     10 
     11   GNU libmicrohttpd is distributed in the hope that it will be useful,
     12   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   Lesser General Public License for more details.
     15 
     16   Alternatively, you can redistribute GNU libmicrohttpd and/or
     17   modify it under the terms of the GNU General Public License as
     18   published by the Free Software Foundation; either version 2 of
     19   the License, or (at your option) any later version, together
     20   with the eCos exception, as follows:
     21 
     22     As a special exception, if other files instantiate templates or
     23     use macros or inline functions from this file, or you compile this
     24     file and link it with other works to produce a work based on this
     25     file, this file does not by itself cause the resulting work to be
     26     covered by the GNU General Public License. However the source code
     27     for this file must still be made available in accordance with
     28     section (3) of the GNU General Public License v2.
     29 
     30     This exception does not invalidate any other reasons why a work
     31     based on this file might be covered by the GNU General Public
     32     License.
     33 
     34   You should have received copies of the GNU Lesser General Public
     35   License and the GNU General Public License along with this library;
     36   if not, see <https://www.gnu.org/licenses/>.
     37 */
     38 
     39 /**
     40  * @file src/mhd2/daemon_funcs.c
     41  * @brief  The implementation of internal daemon-related functions
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #include "mhd_sys_options.h"
     46 
     47 #include "daemon_funcs.h"
     48 
     49 #include "sys_base_types.h"
     50 #include "sys_malloc.h"
     51 
     52 #include "mhd_assert.h"
     53 #include "mhd_itc.h"
     54 #include "mhd_daemon.h"
     55 
     56 #include "daemon_logger.h"
     57 #include "mhd_mono_clock.h"
     58 
     59 
     60 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
     61 MHD_FN_MUST_CHECK_RESULT_ struct MHD_Daemon *
     62 mhd_daemon_get_master_daemon (struct MHD_Daemon *restrict d)
     63 {
     64 #ifdef MHD_SUPPORT_THREADS
     65   if (mhd_D_HAS_MASTER (d))
     66     return d->threading.hier.master;
     67 #endif /* MHD_SUPPORT_THREADS */
     68   return d;
     69 }
     70 
     71 
     72 #ifdef MHD_SUPPORT_THREADS
     73 
     74 MHD_INTERNAL bool
     75 mhd_daemon_trigger_itc (struct MHD_Daemon *restrict d)
     76 {
     77   mhd_assert (mhd_ITC_IS_VALID (d->threading.itc));
     78   if (! mhd_itc_activate (d->threading.itc))
     79   {
     80     mhd_LOG_MSG (d, MHD_SC_ITC_USE_FAILED, \
     81                  "Failed to communicate by ITC with the daemon thread.");
     82     return false;
     83   }
     84   return true;
     85 }
     86 
     87 
     88 #endif /* MHD_SUPPORT_THREADS */
     89 
     90 
     91 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
     92 MHD_FN_MUST_CHECK_RESULT_ bool
     93 mhd_daemon_claim_lbuf (struct MHD_Daemon *restrict d,
     94                        size_t requested_size)
     95 {
     96   bool ret;
     97   struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d);
     98   mhd_assert (0 != requested_size);
     99   if (0 == masterd->req_cfg.large_buf.space_left)
    100     return false; /* Shortcut for typical use without large buffer */
    101 
    102   ret = false;
    103   mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock));
    104   if (masterd->req_cfg.large_buf.space_left >= requested_size)
    105   {
    106     masterd->req_cfg.large_buf.space_left -= requested_size;
    107     ret = true;
    108   }
    109   mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock));
    110   return ret;
    111 }
    112 
    113 
    114 static MHD_FN_PAR_NONNULL_ALL_
    115 MHD_FN_MUST_CHECK_RESULT_ size_t
    116 mhd_daemon_claim_lbuf_up_to (struct MHD_Daemon *d,
    117                              size_t requested_size)
    118 {
    119   size_t ret;
    120   struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d);
    121   mhd_assert (0 != requested_size);
    122   if (0 == masterd->req_cfg.large_buf.space_left)
    123     return false; /* Shortcut for typical use without large buffer */
    124 
    125   mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock));
    126   if (masterd->req_cfg.large_buf.space_left >= requested_size)
    127   {
    128     ret = requested_size;
    129     masterd->req_cfg.large_buf.space_left -= requested_size;
    130   }
    131   else
    132   {
    133     ret = masterd->req_cfg.large_buf.space_left;
    134     masterd->req_cfg.large_buf.space_left = 0;
    135   }
    136   mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock));
    137   return ret;
    138 }
    139 
    140 
    141 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
    142 mhd_daemon_reclaim_lbuf (struct MHD_Daemon *restrict d,
    143                          size_t reclaimed_size)
    144 {
    145   struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d);
    146   mhd_assert (0 != reclaimed_size);
    147   mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock));
    148   masterd->req_cfg.large_buf.space_left += reclaimed_size;
    149   mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock));
    150 }
    151 
    152 
    153 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
    154 MHD_FN_PAR_OUT_ (3) bool
    155 mhd_daemon_get_lbuf (struct MHD_Daemon *restrict d,
    156                      size_t requested_size,
    157                      struct mhd_Buffer *restrict buf)
    158 {
    159   if (! mhd_daemon_claim_lbuf (d, requested_size))
    160   {
    161     buf->size = 0;
    162     buf->data = NULL;
    163     return false;
    164   }
    165   buf->data = (char *) malloc (requested_size);
    166   if (NULL == buf->data)
    167   {
    168     buf->size = 0;
    169     mhd_daemon_reclaim_lbuf (d, requested_size);
    170     return false;
    171   }
    172   buf->size = requested_size;
    173   return true;
    174 }
    175 
    176 
    177 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
    178 MHD_FN_PAR_INOUT_ (3) bool
    179 mhd_daemon_grow_lbuf (struct MHD_Daemon *restrict d,
    180                       size_t grow_size,
    181                       struct mhd_Buffer *restrict buf)
    182 {
    183   void *new_alloc;
    184   mhd_assert (NULL != buf->data || 0 == buf->size);
    185   mhd_assert (0 != buf->size || NULL == buf->data);
    186 
    187   if (! mhd_daemon_claim_lbuf (d, grow_size))
    188     return false;
    189 
    190   if (NULL == buf->data)
    191     new_alloc = malloc (grow_size);
    192   else
    193     new_alloc = realloc (buf->data, buf->size + grow_size);
    194   if (NULL == new_alloc)
    195   {
    196     mhd_daemon_reclaim_lbuf (d, grow_size);
    197     return false;
    198   }
    199 
    200   buf->data = (char *) new_alloc;
    201   buf->size += grow_size;
    202 
    203   return true;
    204 }
    205 
    206 
    207 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
    208 MHD_FN_PAR_INOUT_ (3) size_t
    209 mhd_daemon_extend_lbuf_up_to (struct MHD_Daemon *restrict d,
    210                               size_t desired_grow_size,
    211                               struct mhd_Buffer *restrict buf)
    212 {
    213   void *new_alloc;
    214   size_t grow_size;
    215   mhd_assert (NULL != buf->data || 0 == buf->size);
    216   mhd_assert (0 != buf->size || NULL == buf->data);
    217   mhd_assert (0 != desired_grow_size);
    218 
    219   grow_size = mhd_daemon_claim_lbuf_up_to (d, desired_grow_size);
    220 
    221   new_alloc = NULL;
    222   if (NULL == buf->data)
    223   {
    224     while ((0 != grow_size) &&
    225            (NULL == (new_alloc = malloc (grow_size))))
    226     {
    227       size_t reduce = grow_size / 2;
    228       if (sizeof(void *) >= (grow_size - reduce))
    229         reduce = grow_size;
    230       mhd_daemon_reclaim_lbuf (d,
    231                                reduce);
    232       grow_size -= reduce;
    233     }
    234   }
    235   else
    236   {
    237     while ((0 != grow_size) &&
    238            (NULL == (new_alloc = realloc (buf->data,
    239                                           buf->size + grow_size))))
    240     {
    241       size_t reduce = grow_size / 2;
    242       if (sizeof(void *) >= (grow_size - reduce))
    243         reduce = grow_size;
    244       mhd_daemon_reclaim_lbuf (d,
    245                                reduce);
    246       grow_size -= reduce;
    247     }
    248   }
    249 
    250   if (NULL != new_alloc)
    251   {
    252     mhd_assert (0 != grow_size);
    253     buf->data = (char *) new_alloc;
    254     buf->size += grow_size;
    255   }
    256 
    257   return grow_size;
    258 }
    259 
    260 
    261 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    262 MHD_FN_PAR_INOUT_ (2) void
    263 mhd_daemon_free_lbuf (struct MHD_Daemon *restrict d,
    264                       struct mhd_Buffer *restrict buf)
    265 {
    266   if (0 == buf->size)
    267   {
    268     mhd_assert (NULL == buf->data);
    269     return;
    270   }
    271   free (buf->data);
    272   buf->data = NULL;
    273   mhd_daemon_reclaim_lbuf (d, buf->size);
    274   buf->size = 0;
    275 }
    276 
    277 
    278 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ uint_fast64_t
    279 mhd_daemon_get_milsec_counter (struct MHD_Daemon *restrict d)
    280 {
    281   if (! d->events.time.is_set)
    282   {
    283     d->events.time.cur = mhd_monotonic_msec_counter ();
    284     d->events.time.is_set = true;
    285   }
    286 
    287   return d->events.time.cur;
    288 }