libmicrohttpd2

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

mhd_daemon.h (35150B)


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