libmicrohttpd2

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

daemon_funcs.c (7914B)


      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 #include "daemon_logger.h"
     56 
     57 
     58 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
     59 MHD_FN_MUST_CHECK_RESULT_ struct MHD_Daemon *
     60 mhd_daemon_get_master_daemon (struct MHD_Daemon *restrict d)
     61 {
     62 #ifdef MHD_SUPPORT_THREADS
     63   if (mhd_D_HAS_MASTER (d))
     64     return d->threading.hier.master;
     65 #endif /* MHD_SUPPORT_THREADS */
     66   return d;
     67 }
     68 
     69 
     70 #ifdef MHD_SUPPORT_THREADS
     71 
     72 MHD_INTERNAL bool
     73 mhd_daemon_trigger_itc (struct MHD_Daemon *restrict d)
     74 {
     75   mhd_assert (mhd_ITC_IS_VALID (d->threading.itc));
     76   if (! mhd_itc_activate (d->threading.itc))
     77   {
     78     mhd_LOG_MSG (d, MHD_SC_ITC_USE_FAILED, \
     79                  "Failed to communicate by ITC with the daemon thread.");
     80     return false;
     81   }
     82   return true;
     83 }
     84 
     85 
     86 #endif /* MHD_SUPPORT_THREADS */
     87 
     88 
     89 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
     90 MHD_FN_MUST_CHECK_RESULT_ bool
     91 mhd_daemon_claim_lbuf (struct MHD_Daemon *restrict d,
     92                        size_t requested_size)
     93 {
     94   bool ret;
     95   struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d);
     96   mhd_assert (0 != requested_size);
     97   if (0 == masterd->req_cfg.large_buf.space_left)
     98     return false; /* Shortcut for typical use without large buffer */
     99 
    100   ret = false;
    101   mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock));
    102   if (masterd->req_cfg.large_buf.space_left >= requested_size)
    103   {
    104     masterd->req_cfg.large_buf.space_left -= requested_size;
    105     ret = true;
    106   }
    107   mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock));
    108   return ret;
    109 }
    110 
    111 
    112 static MHD_FN_PAR_NONNULL_ALL_
    113 MHD_FN_MUST_CHECK_RESULT_ size_t
    114 mhd_daemon_claim_lbuf_up_to (struct MHD_Daemon *d,
    115                              size_t requested_size)
    116 {
    117   size_t ret;
    118   struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d);
    119   mhd_assert (0 != requested_size);
    120   if (0 == masterd->req_cfg.large_buf.space_left)
    121     return false; /* Shortcut for typical use without large buffer */
    122 
    123   mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock));
    124   if (masterd->req_cfg.large_buf.space_left >= requested_size)
    125   {
    126     ret = requested_size;
    127     masterd->req_cfg.large_buf.space_left -= requested_size;
    128   }
    129   else
    130   {
    131     ret = masterd->req_cfg.large_buf.space_left;
    132     masterd->req_cfg.large_buf.space_left = 0;
    133   }
    134   mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock));
    135   return ret;
    136 }
    137 
    138 
    139 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
    140 mhd_daemon_reclaim_lbuf (struct MHD_Daemon *restrict d,
    141                          size_t reclaimed_size)
    142 {
    143   struct MHD_Daemon *const masterd = mhd_daemon_get_master_daemon (d);
    144   mhd_assert (0 != reclaimed_size);
    145   mhd_mutex_lock_chk (&(masterd->req_cfg.large_buf.lock));
    146   masterd->req_cfg.large_buf.space_left += reclaimed_size;
    147   mhd_mutex_unlock_chk (&(masterd->req_cfg.large_buf.lock));
    148 }
    149 
    150 
    151 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
    152 MHD_FN_PAR_OUT_ (3) bool
    153 mhd_daemon_get_lbuf (struct MHD_Daemon *restrict d,
    154                      size_t requested_size,
    155                      struct mhd_Buffer *restrict buf)
    156 {
    157   if (! mhd_daemon_claim_lbuf (d, requested_size))
    158   {
    159     buf->size = 0;
    160     buf->data = NULL;
    161     return false;
    162   }
    163   buf->data = (char *) malloc (requested_size);
    164   if (NULL == buf->data)
    165   {
    166     buf->size = 0;
    167     mhd_daemon_reclaim_lbuf (d, requested_size);
    168     return false;
    169   }
    170   buf->size = requested_size;
    171   return true;
    172 }
    173 
    174 
    175 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
    176 MHD_FN_PAR_INOUT_ (3) bool
    177 mhd_daemon_grow_lbuf (struct MHD_Daemon *restrict d,
    178                       size_t grow_size,
    179                       struct mhd_Buffer *restrict buf)
    180 {
    181   void *new_alloc;
    182   mhd_assert (NULL != buf->data || 0 == buf->size);
    183   mhd_assert (0 != buf->size || NULL == buf->data);
    184 
    185   if (! mhd_daemon_claim_lbuf (d, grow_size))
    186     return false;
    187 
    188   if (NULL == buf->data)
    189     new_alloc = malloc (grow_size);
    190   else
    191     new_alloc = realloc (buf->data, buf->size + grow_size);
    192   if (NULL == new_alloc)
    193   {
    194     mhd_daemon_reclaim_lbuf (d, grow_size);
    195     return false;
    196   }
    197 
    198   buf->data = (char *) new_alloc;
    199   buf->size += grow_size;
    200 
    201   return true;
    202 }
    203 
    204 
    205 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
    206 MHD_FN_PAR_INOUT_ (3) size_t
    207 mhd_daemon_extend_lbuf_up_to (struct MHD_Daemon *restrict d,
    208                               size_t desired_grow_size,
    209                               struct mhd_Buffer *restrict buf)
    210 {
    211   void *new_alloc;
    212   size_t grow_size;
    213   mhd_assert (NULL != buf->data || 0 == buf->size);
    214   mhd_assert (0 != buf->size || NULL == buf->data);
    215   mhd_assert (0 != desired_grow_size);
    216 
    217   grow_size = mhd_daemon_claim_lbuf_up_to (d, desired_grow_size);
    218 
    219   new_alloc = NULL;
    220   if (NULL == buf->data)
    221   {
    222     while ((0 != grow_size) &&
    223            (NULL == (new_alloc = malloc (grow_size))))
    224     {
    225       size_t reduce = grow_size / 2;
    226       if (sizeof(void *) >= (grow_size - reduce))
    227         reduce = grow_size;
    228       mhd_daemon_reclaim_lbuf (d,
    229                                reduce);
    230       grow_size -= reduce;
    231     }
    232   }
    233   else
    234   {
    235     while ((0 != grow_size) &&
    236            (NULL == (new_alloc = realloc (buf->data,
    237                                           buf->size + grow_size))))
    238     {
    239       size_t reduce = grow_size / 2;
    240       if (sizeof(void *) >= (grow_size - reduce))
    241         reduce = grow_size;
    242       mhd_daemon_reclaim_lbuf (d,
    243                                reduce);
    244       grow_size -= reduce;
    245     }
    246   }
    247 
    248   if (NULL != new_alloc)
    249   {
    250     mhd_assert (0 != grow_size);
    251     buf->data = (char *) new_alloc;
    252     buf->size += grow_size;
    253   }
    254 
    255   return grow_size;
    256 }
    257 
    258 
    259 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    260 MHD_FN_PAR_INOUT_ (2) void
    261 mhd_daemon_free_lbuf (struct MHD_Daemon *restrict d,
    262                       struct mhd_Buffer *restrict buf)
    263 {
    264   if (0 == buf->size)
    265   {
    266     mhd_assert (NULL == buf->data);
    267     return;
    268   }
    269   free (buf->data);
    270   buf->data = NULL;
    271   mhd_daemon_reclaim_lbuf (d, buf->size);
    272   buf->size = 0;
    273 }