libmicrohttpd2

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

mhd_daemon.h (33244B)


      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/mhd_daemon.h
     41  * @brief  The header for declaration of struct MHD_Daemon
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #ifndef MHD_DAEMON_H
     46 #define MHD_DAEMON_H 1
     47 
     48 #include "mhd_sys_options.h"
     49 
     50 #include "sys_bool_type.h"
     51 #include "sys_base_types.h"
     52 
     53 #include "mhd_dlinked_list.h"
     54 
     55 #include "mhd_buffer.h"
     56 #include "mhd_socket_type.h"
     57 #include "mhd_atomic_counter.h"
     58 
     59 #ifdef MHD_SUPPORT_AUTH_DIGEST
     60 #  include "mhd_digest_auth_data.h"
     61 #endif
     62 
     63 #ifdef MHD_SUPPORT_HTTPS
     64 #  include "mhd_tls_choice.h"
     65 #endif
     66 
     67 #ifdef MHD_SUPPORT_THREADS
     68 #  include "mhd_threads.h"
     69 #  include "mhd_itc_types.h"
     70 #endif
     71 
     72 #include "mhd_locks.h"
     73 
     74 #include "sys_select.h"
     75 #include "sys_poll.h"
     76 #ifdef MHD_SUPPORT_EPOLL
     77 #  include <sys/epoll.h>
     78 #endif
     79 
     80 #include "mempool_types.h"
     81 
     82 #include "mhd_public_api.h"
     83 
     84 struct DaemonOptions; /* Forward declaration */
     85 struct MHD_Connection; /* Forward declaration */
     86 struct sockaddr_storage; /* Forward declaration */
     87 
     88 /**
     89  * The helper struct for the connections list
     90  */
     91 mhd_DLINKEDL_LIST_DEF (MHD_Connection);
     92 
     93 /**
     94  * The current phase of the daemon life
     95  */
     96 enum MHD_FIXED_ENUM_ mhd_DaemonState
     97 {
     98   /**
     99    * The daemon has been created, but not yet started.
    100    * Setting configuration options is possible.
    101    */
    102   mhd_DAEMON_STATE_NOT_STARTED = 0
    103   ,
    104   /**
    105    * The daemon is being started.
    106    */
    107   mhd_DAEMON_STATE_STARTING
    108   ,
    109   /**
    110    * The daemon has been started.
    111    * Normal operations.
    112    */
    113   mhd_DAEMON_STATE_STARTED
    114   ,
    115   /**
    116    * The daemon has failed to start
    117    */
    118   mhd_DAEMON_STATE_FAILED
    119   ,
    120   /**
    121    * The daemon is being stopped.
    122    */
    123   mhd_DAEMON_STATE_STOPPING
    124   ,
    125   /**
    126    * The daemon is stopped.
    127    * The state should rarely visible as daemon should be destroyed when stopped.
    128    */
    129   mhd_DAEMON_STATE_STOPPED
    130 };
    131 
    132 
    133 /**
    134  * Internal version of the daemon work mode type
    135  */
    136 enum MHD_FIXED_ENUM_ mhd_WorkModeIntType
    137 {
    138   /**
    139    * Network edge-triggered events are monitored and provided by application.
    140    * Receiving, sending and processing of the network data if performed when
    141    * special MHD function is called by application.
    142    * No threads managed by the daemon.
    143    */
    144   mhd_WM_INT_EXTERNAL_EVENTS_EDGE
    145   ,
    146   /**
    147    * Network level-triggered events are monitored and provided by application.
    148    * Receiving, sending and processing of the network data if performed when
    149    * special MHD function is called by application.
    150    * No threads managed by the daemon.
    151    */
    152   mhd_WM_INT_EXTERNAL_EVENTS_LEVEL
    153   ,
    154   /**
    155    * The daemon checks for the network events, receives, sends and process
    156    * the network data when special MHD function is called by application.
    157    * No threads managed by the daemon.
    158    */
    159   mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS
    160 #ifdef MHD_SUPPORT_THREADS
    161   ,
    162   /**
    163    * The daemon runs its own single thread, where the daemon monitors
    164    * all network events, receives, sends and process the network data.
    165    */
    166   mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD
    167   ,
    168   /**
    169    * The daemon runs its own single thread, where the daemon monitors
    170    * the new incoming connections, and runs individual thread for each
    171    * established connection, where the daemon monitors connection, receives,
    172    * sends and process the network data.
    173    */
    174   mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION
    175   ,
    176   /**
    177    * The daemon runs its fixed number of threads, all threads monitors the
    178    * new incoming connections and each thread handles own subset of the network
    179    * connections (monitors connections network events, receives, sends and
    180    * process the network data).
    181    */
    182   mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL
    183 #endif
    184 };
    185 
    186 #ifdef MHD_SUPPORT_THREADS
    187 /**
    188  * Check whether given mhd_WorkModeIntType value should have internal threads,
    189  * either directly controlled or indirectly, via additional workers daemons.
    190  */
    191 #  define mhd_WM_INT_HAS_THREADS(wm_i) \
    192         (mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD <= wm_i)
    193 /**
    194  * Check whether given mhd_WorkModeIntType value equals "thread-per-connection"
    195  */
    196 #  define mhd_WM_INT_IS_THREAD_PER_CONN(wm_i) \
    197         (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == wm_i)
    198 /**
    199  * Check whether given mhd_WorkModeIntType value equals "thread pool"
    200  */
    201 #  define mhd_WM_INT_IS_THREAD_POOL(wm_i) \
    202         (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == wm_i)
    203 #else  /* ! MHD_SUPPORT_THREADS */
    204 #  define mhd_WM_INT_HAS_THREADS(wm_i)          (0)
    205 #  define mhd_WM_INT_IS_THREAD_PER_CONN(wm_i)   (0)
    206 #  define mhd_WM_INT_IS_THREAD_POOL(wm_i)       (0)
    207 #endif /* ! MHD_SUPPORT_THREADS */
    208 
    209 /**
    210  * Check whether given mhd_WorkModeIntType value has external events
    211  */
    212 #define mhd_WM_INT_HAS_EXT_EVENTS(wm_i) \
    213         (mhd_WM_INT_EXTERNAL_EVENTS_LEVEL >= wm_i)
    214 
    215 
    216 /**
    217  * Sockets polling internal syscalls used by MHD.
    218  *
    219  * The same value used as by #MHD_SockPollSyscall, however instead of "auto"
    220  * method this enum uses "not yet set" and enum is extended with an additional
    221  * "external" value.
    222  */
    223 enum MHD_FIXED_ENUM_ mhd_IntPollType
    224 {
    225   /**
    226    * External sockets polling is used.
    227    */
    228   mhd_POLL_TYPE_EXT = -1
    229   ,
    230   /**
    231    * Internal sockets polling syscall has not been selected yet.
    232    */
    233   mhd_POLL_TYPE_NOT_SET_YET = MHD_SPS_AUTO
    234   ,
    235   /**
    236    * Use select().
    237    */
    238   mhd_POLL_TYPE_SELECT = MHD_SPS_SELECT
    239   ,
    240   /**
    241    * Use poll().
    242    */
    243   mhd_POLL_TYPE_POLL = MHD_SPS_POLL
    244 #ifdef MHD_SUPPORT_EPOLL
    245   ,
    246   /**
    247    * Use epoll.
    248    */
    249   mhd_POLL_TYPE_EPOLL = MHD_SPS_EPOLL
    250 #endif /* MHD_SUPPORT_EPOLL */
    251 };
    252 
    253 
    254 #ifdef MHD_SUPPORT_EPOLL
    255 /**
    256  * Check whether provided mhd_IntPollType value is "epoll"
    257  */
    258 #  define mhd_POLL_TYPE_INT_IS_EPOLL(poll_type) \
    259         (mhd_POLL_TYPE_EPOLL == poll_type)
    260 #else
    261 #  define mhd_POLL_TYPE_INT_IS_EPOLL(poll_type) (0)
    262 #endif
    263 
    264 #if defined(HAVE_UINTPTR_T)
    265 typedef uintptr_t mhd_SockRelMarker;
    266 #else
    267 typedef unsigned char *mhd_SockRelMarker;
    268 #endif
    269 
    270 
    271 #define mhd_SOCKET_REL_MARKER_EMPTY    ((mhd_SockRelMarker) (0))
    272 
    273 #define mhd_SOCKET_REL_MARKER_ITC      ((mhd_SockRelMarker) (-1))
    274 
    275 #define mhd_SOCKET_REL_MARKER_LISTEN   (mhd_SOCKET_REL_MARKER_ITC - 1)
    276 /**
    277  * Identifier of the FD related to event
    278  */
    279 union mhd_SocketRelation
    280 {
    281   /**
    282    * Identifier of the FD.
    283    * Only valid when it is equal to #mhd_SOCKET_REL_MARKER_EMPTY,
    284    * #mhd_SOCKET_REL_MARKER_ITC or #mhd_SOCKET_REL_MARKER_LISTEN.
    285    */
    286   mhd_SockRelMarker fd_id;
    287   /**
    288    * This is a connection's FD.
    289    * This is valid only when @a fd_id is not valid.
    290    */
    291   struct MHD_Connection *connection;
    292 };
    293 
    294 #ifdef MHD_SUPPORT_SELECT
    295 
    296 /**
    297  * Daemon's pointers to the preallocated arrays for running sockets monitoring
    298  * by poll().
    299  */
    300 struct mhd_DaemonEventsSelectData
    301 {
    302   /**
    303    * Set of sockets monitored for read (receive) readiness.
    304    */
    305   fd_set *rfds;
    306   /**
    307    * Set of sockets monitored for write (send) readiness.
    308    */
    309   fd_set *wfds;
    310   /**
    311    * Set of sockets monitored for exception (error) readiness.
    312    */
    313   fd_set *efds;
    314 };
    315 
    316 #endif /* MHD_SUPPORT_SELECT */
    317 
    318 #ifdef MHD_SUPPORT_POLL
    319 
    320 /**
    321  * Daemon's pointers to the preallocated arrays for running sockets monitoring
    322  * by poll().
    323  */
    324 struct mhd_DaemonEventsPollData
    325 {
    326   /**
    327    * Array of sockets monitored for read (receive) readiness.
    328    * The size of the array is maximum number of connections per this daemon plus
    329    * two (one for the listen socket and one for ITC).
    330    * ITC FDs and the listening are always the first (and the second), if used.
    331    * The number of elements is always two plus maximum number of connections
    332    * allowed for the daemon.
    333    */
    334   struct pollfd *fds;
    335   /**
    336    * Array of the @a fds identifications.
    337    * Each slot matches the slot with the same number in @a fds.
    338    * Up to two first positions reserved for the ITC and the listening.
    339    * The number of elements is always two plus maximum number of connections
    340    * allowed for the daemon.
    341    */
    342   union mhd_SocketRelation *rel;
    343 };
    344 
    345 #endif /* MHD_SUPPORT_POLL */
    346 
    347 #ifdef MHD_SUPPORT_EPOLL
    348 /**
    349  * Daemon's parameters and pointers to the preallocated memory for running
    350  * sockets monitoring by epoll.
    351  */
    352 struct mhd_DaemonEventsEPollData
    353 {
    354   /**
    355    * The epoll control FD.
    356    */
    357   int e_fd;
    358   /**
    359    * The array of events reported by epoll.
    360    */
    361   struct epoll_event *events;
    362 
    363   /**
    364    * The number of elements in the allocated @a events arrays.
    365    */
    366   size_t num_elements;
    367 };
    368 
    369 #endif
    370 
    371 /**
    372  * Daemon's data for external events callback.
    373  * Internal version of struct MHD_WorkModeExternalEventLoopCBParam.
    374  */
    375 struct mhd_DaemonEventsExternalCallback
    376 {
    377   /**
    378    * Socket registration callback
    379    */
    380   MHD_SocketRegistrationUpdateCallback cb;
    381   /**
    382    * Closure for the @a cb
    383    */
    384   void *cls;
    385 };
    386 
    387 
    388 #ifdef MHD_SUPPORT_THREADS
    389 /**
    390  * External events data for ITC FD
    391  */
    392 struct mhd_DaemonEventsExternalDaemonItcData
    393 {
    394   /**
    395    * Application context for ITC FD
    396    */
    397   void *app_cntx;
    398 
    399   /**
    400    * Set to 'true' when active state was detected on ITC by
    401    * external polling
    402    */
    403   bool is_active;
    404 
    405   /**
    406    * Set to 'true' when error state was detected on ITC by
    407    * external polling.
    408    * The daemon may become non-functional.
    409    */
    410   bool is_broken;
    411 };
    412 #endif /* MHD_SUPPORT_THREADS */
    413 
    414 /**
    415  * External events data for the listen socket
    416  */
    417 struct mhd_DaemonEventsExternalDaemonListenData
    418 {
    419   /**
    420    * Application context for ITC FD
    421    */
    422   void *app_cntx;
    423 };
    424 
    425 /**
    426  * Daemon's data for external events for sockets monitoring.
    427  */
    428 struct mhd_DaemonEventsExternal
    429 {
    430   /**
    431    * Daemon's data for external events callback.
    432    * Internal version of struct MHD_WorkModeExternalEventLoopCBParam.
    433    */
    434   struct mhd_DaemonEventsExternalCallback cb_data;
    435 
    436 #ifdef MHD_SUPPORT_THREADS
    437   /**
    438    * External events data for ITC FD
    439    */
    440   struct mhd_DaemonEventsExternalDaemonItcData itc_data;
    441 #endif /* MHD_SUPPORT_THREADS */
    442 
    443   /**
    444    * External events data for the listen socket
    445    */
    446   struct mhd_DaemonEventsExternalDaemonListenData listen_data;
    447 
    448   /**
    449    * If set to 'true' then all FDs must be registered each round.
    450    * If set to 'false' then only changed FDs must be registered.
    451    */
    452   bool reg_all;
    453 };
    454 
    455 /**
    456  * Type-specific events monitoring data
    457  */
    458 union mhd_DaemonEventMonitoringTypeSpecificData
    459 {
    460 #ifdef MHD_SUPPORT_SELECT
    461   /**
    462    * Daemon's pointers to the preallocated arrays for running sockets monitoring
    463    * by poll().
    464    */
    465   struct mhd_DaemonEventsSelectData select;
    466 #endif /* MHD_SUPPORT_SELECT */
    467 
    468 #ifdef MHD_SUPPORT_POLL
    469   /**
    470    * Daemon's pointers to the preallocated arrays for running sockets monitoring
    471    * by poll().
    472    */
    473   struct mhd_DaemonEventsPollData poll;
    474 #endif /* MHD_SUPPORT_POLL */
    475 
    476 #ifdef MHD_SUPPORT_EPOLL
    477   /**
    478    * Daemon's parameters and pointers to the preallocated memory for running
    479    * sockets monitoring by epoll.
    480    */
    481   struct mhd_DaemonEventsEPollData epoll;
    482 #endif
    483 
    484   /**
    485    * Daemon's data for external events for sockets monitoring.
    486    */
    487   struct mhd_DaemonEventsExternal extr;
    488 };
    489 
    490 
    491 struct mhd_DaemonExtAddedConn; /* Forward declaration */
    492 mhd_DLINKEDL_STRUCTS_DEFS (mhd_DaemonExtAddedConn);
    493 
    494 /**
    495  * Information about externally added connection
    496  */
    497 struct mhd_DaemonExtAddedConn
    498 {
    499   /**
    500    * The links to the other externally added connections in the queue
    501    */
    502   mhd_DLNKDL_LINKS (mhd_DaemonExtAddedConn, queue);
    503 
    504   /**
    505    * The socket of the externally added connection
    506    */
    507   MHD_Socket skt;
    508 
    509   /**
    510    * The size of the data pointed by @a addr.
    511    * Zero fi @a addr is NULL.
    512    */
    513   size_t addr_size;
    514 
    515   /**
    516    * Pointer to socket address.
    517    * Allocated by malloc(), must be freed;
    518    * May be NULL.
    519    */
    520   struct sockaddr_storage *addr;
    521 
    522   /**
    523    * 'true' if @a skt is non-blocking
    524    */
    525   bool is_nonblock;
    526 
    527   /**
    528    * 'true' if @a skt has SIGPIPE suppressed
    529    */
    530   bool has_spipe_suppr;
    531 };
    532 
    533 
    534 /**
    535  * Information about externally added connections for the worker daemon
    536  */
    537 struct mhd_DaemonExtAddedConnectionsWorker
    538 {
    539   /**
    540    * The lock to access @a queue list
    541    */
    542   mhd_mutex q_lock;
    543 
    544   /**
    545    * The list with the queue of externally added connections
    546    */
    547   mhd_DLNKDL_LIST (mhd_DaemonExtAddedConn, queue);
    548 };
    549 
    550 #ifdef MHD_SUPPORT_THREADS
    551 /**
    552  * Information about externally added connections for the master daemon
    553  */
    554 struct mhd_DaemonExtAddedConnectionsMaster
    555 {
    556   /**
    557    * The index (modulo number of workers) of the next worker daemon to add
    558    * connection
    559    */
    560   struct mhd_AtomicCounter next_d_idx;
    561 };
    562 #endif /* MHD_SUPPORT_THREADS */
    563 
    564 /**
    565  * Information about externally added connections
    566  */
    567 union mhd_DaemonExtAddedConnections
    568 {
    569 #ifdef MHD_SUPPORT_THREADS
    570   /**
    571    * Information about externally added connections for the master daemon
    572    */
    573   struct mhd_DaemonExtAddedConnectionsMaster master;
    574 #endif /* MHD_SUPPORT_THREADS */
    575   /**
    576    * Information about externally added connections for the worker daemon
    577    */
    578   struct mhd_DaemonExtAddedConnectionsWorker worker;
    579 };
    580 
    581 
    582 /**
    583  * The required actions for the daemon
    584  */
    585 struct mhd_DaemonEventActionRequired
    586 {
    587   /**
    588    * If 'true' connection resuming is required.
    589    */
    590   bool resume;
    591 
    592   /**
    593    * Information about externally added connections
    594    */
    595   union mhd_DaemonExtAddedConnections ext_added;
    596 };
    597 
    598 /**
    599  * The daemon's time data
    600  */
    601 struct mhd_DaemonEventsCurTime
    602 {
    603   /**
    604    * 'true' if @a cur is set
    605    */
    606   bool is_set;
    607   /**
    608    * Current value of monotonic milliseconds counter.
    609    * Valid only if @a is_set is 'true'.
    610    * Updated once per processing round.
    611    */
    612   uint_fast64_t cur;
    613 };
    614 
    615 /**
    616  * The data for events monitoring
    617  */
    618 struct mhd_DaemonEventMonitoringData
    619 {
    620   /**
    621    * Sockets polling type used by the daemon.
    622    */
    623   enum mhd_IntPollType poll_type;
    624 
    625   /**
    626    * Type-specific events monitoring data
    627    */
    628   union mhd_DaemonEventMonitoringTypeSpecificData data;
    629 
    630   /**
    631    * The required actions for the daemon.
    632    */
    633   struct mhd_DaemonEventActionRequired act_req;
    634 
    635   /**
    636    * When set to 'true' the listen socket has new incoming connection(s).
    637    */
    638   bool accept_pending;
    639 
    640   /**
    641    * The list of the daemon's connections that need processing
    642    */
    643   mhd_DLNKDL_LIST (MHD_Connection,proc_ready);
    644 
    645   /**
    646    * The daemon's time data
    647    */
    648   struct mhd_DaemonEventsCurTime time;
    649 };
    650 
    651 
    652 /**
    653  * The type of the socket
    654  */
    655 enum MHD_FIXED_ENUM_ mhd_SocketType
    656 {
    657   /**
    658    * The socket type is some non-IP type.
    659    */
    660   mhd_SOCKET_TYPE_NON_IP = -2
    661   ,
    662   /**
    663    * The socket type is UNIX (LOCAL)
    664    */
    665   mhd_SOCKET_TYPE_UNIX = -1
    666   ,
    667   /**
    668    * The socket is unknown yet. It can be IP or non-IP.
    669    */
    670   mhd_SOCKET_TYPE_UNKNOWN = 0
    671   ,
    672   /**
    673    * The socket is definitely IP.
    674    */
    675   mhd_SOCKET_TYPE_IP = 1
    676 };
    677 
    678 /**
    679  * Listen socket data
    680  */
    681 struct mhd_ListenSocket
    682 {
    683   /**
    684    * The listening socket
    685    */
    686   MHD_Socket fd;
    687   /**
    688    * Set to 'true' when unrecoverable error is detected on the listen socket.
    689    * If set to 'true', but @a fd is not #MHD_INVALID_SOCKET then "broken" state
    690    * has not yet processed by MHD.
    691    */
    692   bool is_broken;
    693   /**
    694    * The type of the listening socket @a fd
    695    */
    696   enum mhd_SocketType type;
    697   /**
    698    * 'true' if @a fd is non-blocking
    699    */
    700   bool non_block;
    701   /**
    702    * The port number for @a fd
    703    *
    704    * Zero if unknown and for non-IP socket.
    705    */
    706   uint_least16_t port;
    707 };
    708 
    709 /**
    710  * Configured settings for the daemon's network data
    711  */
    712 struct mhd_DaemonNetworkSettings
    713 {
    714 #ifdef MHD_SOCKETS_KIND_POSIX
    715   /**
    716    * The maximum number for the network FDs.
    717    * The valid FD number must be less then @a max_fd_num.
    718    */
    719   MHD_Socket max_fd_num;
    720 #else
    721   int dummy; /* mute compiler warning */
    722 #endif
    723 };
    724 
    725 /**
    726  * The daemon network/sockets data
    727  *
    728  * This structure holds mostly static information -- typically initialised once
    729  * when the daemon starts, and possibly updated once later (e.g., if the
    730  * listening socket fails or is closed).
    731  *
    732  * It does NOT contain any operational states.
    733  */
    734 struct mhd_DaemonNetwork
    735 {
    736   /**
    737    * The listening socket
    738    */
    739   struct mhd_ListenSocket listen;
    740 
    741 #ifdef MHD_SUPPORT_EPOLL
    742   /**
    743    * The epoll FD.
    744    * Set to '-1' when epoll is not used.
    745    */
    746   int epoll_fd;
    747 #endif
    748   /**
    749    * Configured settings for the daemon's network data
    750    */
    751   struct mhd_DaemonNetworkSettings cfg;
    752 };
    753 
    754 #ifdef MHD_SUPPORT_AUTH_DIGEST
    755 
    756 /**
    757  * Digest Auth nonce data
    758  */
    759 struct mhd_DaemonAuthDigestNonceData
    760 {
    761   /**
    762    * The nonce value in the binary form, excluding validity tail
    763    */
    764   uint8_t nonce[mhd_AUTH_DIGEST_NONCE_RAND_BIN_SIZE];
    765 
    766   /**
    767    * The nonce validity time
    768    */
    769   uint_fast32_t valid_time;
    770 
    771   /**
    772    * The largest last received 'nc' value.
    773    * This 'nc' value has been already used by the client.
    774    */
    775   uint_fast32_t max_recvd_nc;
    776 
    777   /**
    778    * Bitmask over the previous 64 nc values (down to to nc-64).
    779    * Used to allow out-of-order 'nc'.
    780    * If bit in the bitmask is set to one, then this 'nc' value was already used
    781    * by the client.
    782    */
    783   uint_fast64_t nmask;
    784 };
    785 
    786 /**
    787  * Digest Auth daemon configuration data
    788  */
    789 struct mhd_DaemonAuthDigestCfg
    790 {
    791   /**
    792    * The number of elements in the nonces array
    793    */
    794   size_t nonces_num;
    795 
    796   /**
    797    * The nonce validity time (in seconds)
    798    */
    799   unsigned int nonce_tmout;
    800 
    801   /**
    802    * The default maximum value of nc
    803    */
    804   uint_fast32_t def_max_nc;
    805 };
    806 
    807 /**
    808  * The Digest Auth daemon's data
    809  */
    810 struct mhd_DaemonAuthDigestData
    811 {
    812   /**
    813    * The entropy data used for Digests generation
    814    */
    815   struct mhd_Buffer entropy;
    816 
    817   /**
    818    * The array of generated nonce and related nc
    819    */
    820   struct mhd_DaemonAuthDigestNonceData *nonces;
    821 
    822   /**
    823    * Number of nonces has been generated.
    824    * Used as addition for the nonce source data to ensure unique nonce value.
    825    * TODO: remove and directly use random generator for nonce generation.
    826    */
    827   struct mhd_AtomicCounter num_gen_nonces;
    828 
    829 #ifdef MHD_SUPPORT_THREADS
    830   /**
    831    * The mutex to change or access the @a nonces data
    832    */
    833   mhd_mutex nonces_lock;
    834 #endif
    835 
    836   /**
    837    * Digest Auth daemon configuration data
    838    */
    839   struct mhd_DaemonAuthDigestCfg cfg;
    840 };
    841 
    842 #endif /* MHD_SUPPORT_AUTH_DIGEST */
    843 
    844 #ifdef MHD_SUPPORT_THREADS
    845 
    846 /**
    847  * The type of the daemon
    848  */
    849 enum MHD_FIXED_ENUM_ mhd_DaemonType
    850 {
    851   /**
    852    * A single daemon, performing all the work.
    853    *
    854    * This daemon may have a optional single thread, managed by MHD.
    855    */
    856   mhd_DAEMON_TYPE_SINGLE
    857 #ifndef NDEBUG
    858     = 1
    859 #endif
    860 #ifdef MHD_SUPPORT_THREADS
    861   ,
    862   /**
    863    * A master daemon, only controlling worker daemons.
    864    *
    865    * This daemon never handle any network activity directly.
    866    */
    867   mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY
    868   ,
    869   /**
    870    * A daemon with single internal thread for listening and multiple threads
    871    * handling connections with the clients, one thread per connection.
    872    */
    873   mhd_DAEMON_TYPE_LISTEN_ONLY
    874   ,
    875   /**
    876    * A worker daemon, performing the same work as a single daemon, but
    877    * controlled by master daemon.
    878    *
    879    * This type of daemon always have single internal tread and never exposed
    880    * to application directly.
    881    */
    882   mhd_DAEMON_TYPE_WORKER
    883 #endif /* MHD_SUPPORT_THREADS */
    884 };
    885 
    886 /**
    887  * Check whether the daemon type is allowed to have internal thread with
    888  * direct control
    889  */
    890 #define mhd_D_TYPE_IS_VALID(t) \
    891         ((mhd_DAEMON_TYPE_SINGLE <= (t)) && (mhd_DAEMON_TYPE_WORKER >= (t)))
    892 
    893 /**
    894  * Check whether the daemon type must not be exposed to the application
    895  */
    896 #define mhd_D_TYPE_IS_INTERNAL_ONLY(t) \
    897         (mhd_DAEMON_TYPE_WORKER == (t))
    898 
    899 /**
    900  * Check whether the daemon type is allowed to process the network data
    901  */
    902 #define mhd_D_TYPE_HAS_EVENTS_PROCESSING(t) \
    903         (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY != (t))
    904 
    905 /**
    906  * Check whether the daemon type must not be exposed to the application
    907  */
    908 #define mhd_D_TYPE_HAS_WORKERS(t) \
    909         (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY == (t))
    910 
    911 /**
    912  * Check whether the daemon type has master (controlling) daemon
    913  */
    914 #define mhd_D_TYPE_HAS_MASTER_DAEMON(t) \
    915         (mhd_DAEMON_TYPE_WORKER == (t))
    916 
    917 /**
    918  * Check whether the daemon is listening only (with connection data
    919  * processed in separate threads)
    920  */
    921 #define mhd_D_TYPE_IS_LISTEN_ONLY(t) \
    922         (mhd_DAEMON_TYPE_LISTEN_ONLY == (t))
    923 
    924 #else  /* ! MHD_SUPPORT_THREADS */
    925 
    926 /**
    927  * Check whether the daemon type is allowed to have internal thread with
    928  * direct control
    929  */
    930 #define mhd_D_TYPE_IS_VALID(t) (! 0)
    931 
    932 /**
    933  * Check whether the daemon type must not be exposed to the application
    934  */
    935 #define mhd_D_TYPE_IS_INTERNAL_ONLY(t) (0)
    936 
    937 /**
    938  * Check whether the daemon type is allowed to process the network data
    939  */
    940 #define mhd_D_TYPE_HAS_EVENTS_PROCESSING(t) (! 0)
    941 
    942 /**
    943  * Check whether the daemon type must not be exposed to the application
    944  */
    945 #define mhd_D_TYPE_HAS_WORKERS(t) (0)
    946 
    947 /**
    948  * Check whether the daemon type has master (controlling) daemon
    949  */
    950 #define mhd_D_TYPE_HAS_MASTER_DAEMON(t)  (0)
    951 
    952 /**
    953  * Check whether the daemon is listening only (with connection data
    954  * processed in separate threads)
    955  */
    956 #define mhd_D_TYPE_IS_LISTEN_ONLY(t)    (0)
    957 
    958 #endif /* ! MHD_SUPPORT_THREADS */
    959 
    960 #ifdef MHD_SUPPORT_THREADS
    961 
    962 /**
    963  * Workers pool data
    964  */
    965 struct mhd_DaemonWorkerPoolData
    966 {
    967   /**
    968    * Array of worker daemons
    969    */
    970   struct MHD_Daemon *workers;
    971 
    972   /**
    973    * The number of workers in the @a workers array
    974    */
    975   unsigned int num;
    976 };
    977 
    978 /**
    979  * Hierarchy data for the daemon
    980  */
    981 union mhd_DaemonHierarchyData
    982 {
    983   /**
    984    * The pointer to the master daemon
    985    * Only for #mhd_DAEMON_TYPE_WORKER daemons.
    986    */
    987   struct MHD_Daemon *master;
    988 
    989   /**
    990    * Workers pool data.
    991    * Only for #mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY daemons.
    992    */
    993   struct mhd_DaemonWorkerPoolData pool;
    994 };
    995 
    996 /**
    997  * Configured settings for threading
    998  */
    999 struct mhd_DaemonThreadingDataSettings
   1000 {
   1001   /**
   1002    * The size of the stack.
   1003    * Zero to use system's defaults.
   1004    */
   1005   size_t stack_size;
   1006 };
   1007 
   1008 /**
   1009  * Threading and Inter-Thread Communication data
   1010  */
   1011 struct mhd_DaemonThreadingData
   1012 {
   1013   /**
   1014    * The type of this daemon
   1015    */
   1016   enum mhd_DaemonType d_type;
   1017 
   1018   /**
   1019    * Inter-Thread Communication channel.
   1020    * Used to trigger processing of the command or the data provided or updated
   1021    * by the application.
   1022    */
   1023   struct mhd_itc itc;
   1024 
   1025   /**
   1026    * 'True' if stop has been requested.
   1027    * The daemon thread should stop all connections and then close.
   1028    */
   1029   volatile bool stop_requested;
   1030 
   1031   /**
   1032    * The handle of the daemon's thread (if managed by the daemon)
   1033    */
   1034   mhd_thread_handle_ID tid;
   1035 
   1036   /**
   1037    * The hierarchy data for the daemon.
   1038    * Used only when @a d_type is #mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY or
   1039    * #mhd_DAEMON_TYPE_WORKER.
   1040    */
   1041   union mhd_DaemonHierarchyData hier;
   1042 
   1043   /**
   1044    * Configured settings for threading
   1045    */
   1046   struct mhd_DaemonThreadingDataSettings cfg;
   1047 };
   1048 
   1049 #endif /* MHD_SUPPORT_THREADS */
   1050 
   1051 /**
   1052  * Configured settings for the daemon's connections
   1053  */
   1054 struct mhd_DaemonConnectionsSettings
   1055 {
   1056   /**
   1057    * The maximum number of connections handled by the daemon
   1058    */
   1059   unsigned int count_limit;
   1060 
   1061   /**
   1062    * The maximum number of connections per any IP handled by the daemon
   1063    */
   1064   unsigned int per_ip_limit;
   1065 
   1066   /**
   1067    * Connection's default timeout value (in milliseconds)
   1068    */
   1069   uint_fast32_t timeout_milsec;
   1070 
   1071   /**
   1072    * Connection's memory pool size
   1073    */
   1074   size_t mem_pool_size;
   1075 
   1076   /**
   1077    * Memory pool zeroing mode
   1078    */
   1079   enum mhd_MemPoolZeroing mem_pool_zeroing;
   1080 };
   1081 
   1082 #ifdef MHD_SUPPORT_UPGRADE
   1083 
   1084 /**
   1085  * The data for HTTP-Upgraded connections
   1086  */
   1087 struct mhd_DaemonConnectionsUpgraded
   1088 {
   1089   /**
   1090    * The list of HTTP-Upgraded connection closed by application and
   1091    * queued for cleanup
   1092    */
   1093   mhd_DLNKDL_LIST (MHD_Connection,upgr_cleanup);
   1094 
   1095 #ifdef MHD_SUPPORT_THREADS
   1096   /**
   1097    * The mutex to change or check the @a upgr_cleanup list values
   1098    */
   1099   mhd_mutex ucu_lock;
   1100 #endif
   1101 };
   1102 
   1103 #endif /* MHD_SUPPORT_UPGRADE */
   1104 
   1105 /**
   1106  * Connections handling data
   1107  */
   1108 struct mhd_DaemonConnections
   1109 {
   1110 
   1111   /**
   1112    * The list of all daemon's connections.
   1113    * All connection are listed here, expect connection in @a to_clean list.
   1114    */
   1115   mhd_DLNKDL_LIST (MHD_Connection,all_conn);
   1116 
   1117   /**
   1118    * The list of connections sorted by last activity
   1119    */
   1120   mhd_DLNKDL_LIST (MHD_Connection,def_timeout);
   1121 
   1122   /**
   1123    * The list of connections with custom timeouts
   1124    */
   1125   mhd_DLNKDL_LIST (MHD_Connection,cust_timeout);
   1126 
   1127   /**
   1128    * The current number of connections handled by the daemon
   1129    */
   1130   unsigned int count;
   1131 
   1132   /**
   1133    * If set to 'true' then no new connection is allowed.
   1134    * New connection may be blocked because of various system limits, when
   1135    * additional connection would fail anyway. This flag should be cleared
   1136    * when any already processing connection closed.
   1137    * Can be checked from other threads
   1138    */
   1139   volatile bool block_new;
   1140 
   1141   /**
   1142    * Configured settings for the daemon's connections
   1143    */
   1144   struct mhd_DaemonConnectionsSettings cfg;
   1145 
   1146 #ifdef MHD_SUPPORT_UPGRADE
   1147   /**
   1148    * The data for HTTP-Upgraded connections
   1149    */
   1150   struct mhd_DaemonConnectionsUpgraded upgr;
   1151 #endif /* MHD_SUPPORT_UPGRADE */
   1152 };
   1153 
   1154 /**
   1155  * Early URI callback
   1156  */
   1157 struct mhd_DaemonRequestUriCB
   1158 {
   1159   /**
   1160    * The callback
   1161    */
   1162   MHD_EarlyUriLogCallback cb;
   1163   /**
   1164    * The callback closure
   1165    */
   1166   void *cls;
   1167 };
   1168 
   1169 /**
   1170  * Shared large buffer data
   1171  */
   1172 struct mhd_DaemonLargeBuffer
   1173 {
   1174   /**
   1175    * The amount of memory left allowed to be allocated for the large buffer
   1176    */
   1177   size_t space_left;
   1178 
   1179 #ifdef MHD_SUPPORT_THREADS
   1180   /**
   1181    * The mutex to change or check the @a space_left value
   1182    */
   1183   mhd_mutex lock;
   1184 #endif
   1185 };
   1186 
   1187 #ifdef MHD_SUPPORT_HTTP2
   1188 
   1189 /**
   1190  * Generic settings for HTTP layer communication handling.
   1191  *
   1192  * These settings do not include specific settings for requests processing.
   1193  */
   1194 struct mhd_DaemonHttpSettings
   1195 {
   1196   /**
   1197    * 'true' if HTTP/1.x communication is allowed
   1198    */
   1199   bool http1x;
   1200   /**
   1201    * 'true' if HTTP/2 communication is allowed
   1202    */
   1203   bool http2;
   1204 };
   1205 
   1206 #endif /* MHD_SUPPORT_HTTP2 */
   1207 
   1208 /**
   1209  * Settings for requests processing
   1210  */
   1211 struct mhd_DaemonRequestProcessingSettings
   1212 {
   1213   /**
   1214    * Request callback.
   1215    * The main request processing callback.
   1216    */
   1217   MHD_RequestCallback cb;
   1218 
   1219   /**
   1220    * The closure for @a req_cb
   1221    */
   1222   void *cb_cls;
   1223 
   1224   /**
   1225    * Protocol strictness enforced by MHD on clients.
   1226    */
   1227   enum MHD_ProtocolStrictLevel strictness;
   1228 
   1229 #ifdef MHD_SUPPORT_COOKIES
   1230   /**
   1231    * Disable automatic cookies parsing
   1232    */
   1233   bool disable_cookies;
   1234 #endif
   1235 
   1236   /**
   1237    * Early URI callback
   1238    */
   1239   struct mhd_DaemonRequestUriCB uri_cb; // TODO: set from settings
   1240 
   1241   /**
   1242    * Shared large buffer data
   1243    */
   1244   struct mhd_DaemonLargeBuffer large_buf; // TODO: set from settings
   1245 
   1246   /**
   1247    * Suppress "Date:" header in responses
   1248    */
   1249   bool suppress_date;
   1250 };
   1251 
   1252 
   1253 /**
   1254  * Get whether bare LF in HTTP header and other protocol elements
   1255  * should be treated as the line termination depending on the configured
   1256  * strictness level.
   1257  * RFC 9112, section 2.2
   1258  */
   1259 #define mhd_ALLOW_BARE_LF_AS_CRLF(strictness) (0 >= strictness)
   1260 
   1261 
   1262 #ifndef NDEBUG
   1263 /**
   1264  * Various debugging data
   1265  */
   1266 struct mhd_daemon_debug
   1267 {
   1268   bool net_inited;
   1269   bool net_deinited;
   1270   bool master_only_inited;
   1271   bool worker_only_inited;
   1272   bool tls_inited;
   1273   bool events_allocated;
   1274   unsigned int num_events_elements;
   1275   bool events_fully_inited;
   1276   bool thread_pool_inited;
   1277   bool threading_inited;
   1278   bool connections_inited;
   1279   bool avoid_accept4;
   1280   size_t initial_lbuf_size;
   1281 };
   1282 #endif /* NDEBUG */
   1283 
   1284 
   1285 struct MHD_Daemon
   1286 {
   1287   /* General data */
   1288 
   1289   /**
   1290    * The daemon state
   1291    */
   1292   enum mhd_DaemonState state;
   1293 
   1294   /**
   1295    * The daemon work mode (private version)
   1296    */
   1297   enum mhd_WorkModeIntType wmode_int;
   1298 
   1299   /* Events/sockets monitoring/polling data */
   1300 
   1301   /**
   1302    * The data for events monitoring
   1303    */
   1304   struct mhd_DaemonEventMonitoringData events;
   1305 
   1306   /* Network/sockets data */
   1307 
   1308   /**
   1309    * The daemon network/sockets data
   1310    *
   1311    * This structure holds mostly static information -- typically initialised
   1312    * once when the daemon starts, and possibly updated once later (e.g., if the
   1313    * listening socket fails or is closed).
   1314    *
   1315    * It does NOT contain any operational states.
   1316    */
   1317   struct mhd_DaemonNetwork net;
   1318 
   1319 #ifdef MHD_SUPPORT_AUTH_DIGEST
   1320   /**
   1321    * The Digest Auth daemon's data
   1322    */
   1323   struct mhd_DaemonAuthDigestData auth_dg;
   1324 #endif /* MHD_SUPPORT_AUTH_DIGEST */
   1325 
   1326 #ifdef MHD_SUPPORT_HTTPS
   1327   /**
   1328    * The pointer to the daemon TLS data.
   1329    * If set to non-NULL then HTTPS protocol is used, if set to NULL then
   1330    * plain HTTP protocol used.
   1331    */
   1332   struct mhd_TlsDaemonData *tls;
   1333 #endif
   1334 
   1335 #ifdef MHD_SUPPORT_THREADS
   1336   /* Threading data */
   1337 
   1338   /**
   1339    * The daemon threading and Inter-Thread Communication data
   1340    */
   1341   struct mhd_DaemonThreadingData threading;
   1342 #endif
   1343 
   1344   /* Connections handling */
   1345 
   1346   /**
   1347    * The connections handling data
   1348    */
   1349   struct mhd_DaemonConnections conns;
   1350 
   1351 
   1352   /* HTTP communication layer */
   1353 #ifdef MHD_SUPPORT_HTTP2
   1354   /**
   1355    * Generic settings for HTTP layer communication handling.
   1356    *
   1357    * These settings do not include specific settings for requests processing.
   1358    */
   1359   struct mhd_DaemonHttpSettings http_cfg;
   1360 #endif /* MHD_SUPPORT_HTTP2 */
   1361 
   1362 
   1363   /* Request processing data */
   1364 
   1365   /**
   1366    * Settings for requests processing
   1367    */
   1368   struct mhd_DaemonRequestProcessingSettings req_cfg;
   1369 
   1370   /* Other data */
   1371 
   1372   /**
   1373    * Daemon logging parameters
   1374    */
   1375   struct MHD_DaemonOptionValueLog log_params;
   1376 
   1377 
   1378   /* Temporal data */
   1379 
   1380   /**
   1381    * User settings, before applied to the daemon itself
   1382    */
   1383   struct DaemonOptions *settings;
   1384 
   1385 #ifndef NDEBUG
   1386   /* Debug data */
   1387 
   1388   struct mhd_daemon_debug dbg;
   1389 #endif
   1390 };
   1391 
   1392 
   1393 #ifdef MHD_SOCKETS_KIND_POSIX
   1394 /**
   1395  * Checks whether @a fd socket number fits limitations for the @a d_ptr daemon
   1396  */
   1397 #  define mhd_FD_FITS_DAEMON(d_ptr,fd) \
   1398         ((MHD_INVALID_SOCKET == d_ptr->net.cfg.max_fd_num) || \
   1399          (d_ptr->net.cfg.max_fd_num > fd))
   1400 #else
   1401 #  define mhd_FD_FITS_DAEMON(d_ptr,fd) (! 0)
   1402 #endif
   1403 
   1404 #ifdef MHD_SUPPORT_EPOLL
   1405 #  define mhd_D_IS_USING_EPOLL(d) \
   1406         (mhd_POLL_TYPE_EPOLL == ((d)->events.poll_type))
   1407 #else
   1408 #  define mhd_D_IS_USING_EPOLL(d) (0)
   1409 #endif
   1410 
   1411 /**
   1412  * Check whether the daemon has edge-triggered sockets polling
   1413  */
   1414 #define mhd_D_HAS_EDGE_TRIGG(d) \
   1415         ((mhd_WM_INT_EXTERNAL_EVENTS_EDGE == (d)->wmode_int) || \
   1416          mhd_D_IS_USING_EPOLL (d))
   1417 
   1418 #ifdef MHD_SUPPORT_THREADS
   1419 #  define mhd_D_HAS_THREADS(d) mhd_WM_INT_HAS_THREADS ((d)->wmode_int)
   1420 #else
   1421 #  define mhd_D_HAS_THREADS(d) (0)
   1422 #endif
   1423 
   1424 #ifdef MHD_SUPPORT_THREADS
   1425 #  define mhd_D_HAS_THR_PER_CONN(d) \
   1426         (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == \
   1427          ((d)->wmode_int))
   1428 #else
   1429 #  define mhd_D_HAS_THR_PER_CONN(d) (0)
   1430 #endif
   1431 
   1432 #ifdef MHD_SUPPORT_THREADS
   1433 #  define mhd_D_HAS_STOP_REQ(d)         (d->threading.stop_requested)
   1434 #else
   1435 #  define mhd_D_HAS_STOP_REQ(d)         (0)
   1436 #endif
   1437 
   1438 #define mhd_D_HAS_WORKERS(d) mhd_D_TYPE_HAS_WORKERS ((d)->threading.d_type)
   1439 
   1440 #define mhd_D_HAS_MASTER(d) mhd_D_TYPE_HAS_MASTER_DAEMON ((d)->threading.d_type)
   1441 
   1442 #define mhd_D_IS_INTERNAL_ONLY(d) \
   1443         mhd_D_TYPE_IS_INTERNAL_ONLY ((d)->threading.d_type)
   1444 
   1445 #define mhd_D_IS_USING_EDGE_TRIG(d) \
   1446         (mhd_D_IS_USING_EPOLL (d) || \
   1447          (mhd_WM_INT_EXTERNAL_EVENTS_EDGE ==((d)->wmode_int)))
   1448 
   1449 #ifdef MHD_SUPPORT_HTTPS
   1450 /**
   1451  * Returns non-zero if daemon has TLS enabled or zero otherwise
   1452  */
   1453 #  define mhd_D_HAS_TLS(d) (((d)->tls) ? (! 0) : (0))
   1454 #else
   1455 /**
   1456  * Returns non-zero if daemon has TLS enabled or zero otherwise
   1457  */
   1458 #  define mhd_D_HAS_TLS(d) (0)
   1459 #endif
   1460 
   1461 /*
   1462  * Check whether the daemon support Digest Auth
   1463  */
   1464 #ifdef MHD_SUPPORT_AUTH_DIGEST
   1465 #  define mhd_D_HAS_AUTH_DIGEST(d) (NULL != (d)->auth_dg.nonces)
   1466 #else
   1467 #  define mhd_D_HAS_AUTH_DIGEST(d) (! ! 0)
   1468 #endif
   1469 
   1470 #ifdef MHD_SUPPORT_HTTP2
   1471 #  define mhd_D_IS_HTTP1_ENABLED(d)     (d->http_cfg.http1x)
   1472 #  define mhd_D_IS_HTTP2_ENABLED(d)     (d->http_cfg.http2)
   1473 #else  /* ! MHD_SUPPORT_HTTP2 */
   1474 #  define mhd_D_IS_HTTP1_ENABLED(d)     (! 0)
   1475 #  define mhd_D_IS_HTTP2_ENABLED(d)     (! ! 0)
   1476 #endif /* ! MHD_SUPPORT_HTTP2 */
   1477 
   1478 
   1479 #endif /* ! MHD_DAEMON_H */