libmicrohttpd2

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

microhttpd2_main.h.in (229194B)


      1 /**
      2  * Create parameter for #MHD_daemon_set_options() for work mode with
      3  * no internal threads.
      4  * The application periodically calls #MHD_daemon_process_blocking(), where
      5  * MHD internally checks all sockets automatically.
      6  * This is the default mode.
      7  * @return the object of struct MHD_DaemonOptionAndValue with requested values
      8  */
      9 #define MHD_D_OPTION_WM_EXTERNAL_PERIODIC() \
     10         MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_EXTERNAL_PERIODIC ())
     11 
     12 /**
     13 * Create parameter for #MHD_daemon_set_options() for work mode with
     14 * an external event loop with level triggers.
     15 * Application uses #MHD_SocketRegistrationUpdateCallback, level triggered
     16 * sockets polling (like select() or poll()) and #MHD_daemon_event_update().
     17 * @param cb_val the callback for sockets registration
     18 * @param cb_cls_val the closure for the @a cv_val callback
     19 * @return the object of struct MHD_DaemonOptionAndValue with requested values
     20 */
     21 #define MHD_D_OPTION_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL(cb_val, cb_cls_val) \
     22         MHD_D_OPTION_WORK_MODE ( \
     23           MHD_WM_OPTION_EXTERNAL_EVENT_LOOP_CB_LEVEL ((cb_val),(cb_cls_val)))
     24 
     25 /**
     26  * Create parameter for #MHD_daemon_set_options() for work mode with
     27  * an external event loop with edge triggers.
     28  * Application uses #MHD_SocketRegistrationUpdateCallback, edge triggered
     29  * sockets polling (like epoll with EPOLLET) and #MHD_daemon_event_update().
     30  * @param cb_val the callback for sockets registration
     31  * @param cb_cls_val the closure for the @a cv_val callback
     32  * @return the object of struct MHD_DaemonOptionAndValue with requested values
     33  */
     34 #define MHD_D_OPTION_WM_EXTERNAL_EVENT_LOOP_CB_EDGE(cb_val, cb_cls_val) \
     35         MHD_D_OPTION_WORK_MODE ( \
     36           MHD_WM_OPTION_EXTERNAL_EVENT_LOOP_CB_EDGE ((cb_val),(cb_cls_val)))
     37 
     38 /**
     39  * Create parameter for #MHD_daemon_set_options() for work mode with
     40  * no internal threads and aggregate watch FD.
     41  * Application uses #MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD to get single FD
     42  * that gets triggered by any MHD event.
     43  * This FD can be watched as an aggregate indicator for all MHD events.
     44  * This mode is available only on selected platforms (currently
     45  * GNU/Linux only), see #MHD_LIB_INFO_FIXED_HAS_AGGREGATE_FD.
     46  * When the FD is triggered, #MHD_daemon_process_nonblocking() should
     47  * be called.
     48  * @return the object of struct MHD_DaemonOptionAndValue with requested values
     49  */
     50 #define MHD_D_OPTION_WM_EXTERNAL_SINGLE_FD_WATCH() \
     51         MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_EXTERNAL_SINGLE_FD_WATCH ())
     52 
     53 /**
     54  * Create parameter for #MHD_daemon_set_options() for work mode with
     55  * one or more worker threads.
     56  * If number of threads is one, then daemon starts with single worker thread
     57  * that handles all connections.
     58  * If number of threads is larger than one, then that number of worker threads,
     59  * and handling of connection is distributed among the workers.
     60  * @param num_workers the number of worker threads, zero is treated as one
     61  * @return the object of struct MHD_DaemonOptionAndValue with requested values
     62  */
     63 #define MHD_D_OPTION_WM_WORKER_THREADS(num_workers) \
     64         MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_WORKER_THREADS (num_workers))
     65 
     66 /**
     67  * Create parameter for #MHD_daemon_set_options() for work mode with
     68  * one internal thread for listening and additional threads per every
     69  * connection.  Use this if handling requests is CPU-intensive or blocking,
     70  * your application is thread-safe and you have plenty of memory (per
     71  * connection).
     72  * @return the object of struct MHD_DaemonOptionAndValue with requested values
     73  */
     74 #define MHD_D_OPTION_WM_THREAD_PER_CONNECTION() \
     75         MHD_D_OPTION_WORK_MODE (MHD_WM_OPTION_THREAD_PER_CONNECTION ())
     76 
     77 /**
     78  * Set the requested options for the daemon.
     79  *
     80  * If any option fail other options may be or may be not applied.
     81  * @param daemon the daemon to set the options
     82  * @param[in] options the pointer to the array with the options;
     83  *                    the array processing stops at the first ::MHD_D_O_END
     84  *                    option, but not later than after processing
     85  *                    @a options_max_num entries
     86  * @param options_max_num the maximum number of entries in the @a options,
     87  *                        use #MHD_OPTIONS_ARRAY_MAX_SIZE if options processing
     88  *                        must stop only at zero-termination option
     89  * @return ::MHD_SC_OK on success,
     90  *         error code otherwise
     91  */
     92 MHD_EXTERN_ enum MHD_StatusCode
     93 MHD_daemon_set_options (
     94   struct MHD_Daemon *MHD_RESTRICT daemon,
     95   const struct MHD_DaemonOptionAndValue *MHD_RESTRICT options,
     96   size_t options_max_num)
     97 MHD_FN_PAR_NONNULL_ALL_;
     98 
     99 
    100 /**
    101  * Set the requested single option for the daemon.
    102  *
    103  * @param daemon the daemon to set the option
    104  * @param[in] option_ptr the pointer to the option
    105  * @return ::MHD_SC_OK on success,
    106  *         error code otherwise
    107  */
    108 #define MHD_daemon_set_option(daemon, option_ptr) \
    109         MHD_daemon_set_options (daemon, option_ptr, 1)
    110 
    111 
    112 /* *INDENT-OFF* */
    113 #ifdef MHD_USE_VARARG_MACROS
    114 MHD_NOWARN_VARIADIC_MACROS_
    115 #  if defined(MHD_USE_COMPOUND_LITERALS) && \
    116   defined(MHD_USE_COMP_LIT_FUNC_PARAMS)
    117 /**
    118  * Set the requested options for the daemon.
    119  *
    120  * If any option fail other options may be or may be not applied.
    121  *
    122  * It should be used with helpers that creates required options, for example:
    123  *
    124  * MHD_DAEMON_SET_OPTIONS(d, MHD_D_OPTION_SUPPRESS_DATE_HEADER(MHD_YES),
    125  *                        MHD_D_OPTION_SOCK_ADDR(sa_len, sa))
    126  *
    127  * @param daemon the daemon to set the options
    128  * @param ... the list of the options, each option must be created
    129  *            by helpers MHD_D_OPTION_NameOfOption(option_value)
    130  * @return ::MHD_SC_OK on success,
    131  *         error code otherwise
    132  */
    133 #    define MHD_DAEMON_SET_OPTIONS(daemon,...)          \
    134             MHD_NOWARN_COMPOUND_LITERALS_                   \
    135             MHD_NOWARN_AGGR_DYN_INIT_                       \
    136             MHD_daemon_set_options (                        \
    137               daemon,                                       \
    138               ((const struct MHD_DaemonOptionAndValue[])    \
    139                {__VA_ARGS__, MHD_D_OPTION_TERMINATE ()}),   \
    140               MHD_OPTIONS_ARRAY_MAX_SIZE)                   \
    141             MHD_RESTORE_WARN_AGGR_DYN_INIT_                 \
    142             MHD_RESTORE_WARN_COMPOUND_LITERALS_
    143 #  elif defined(MHD_USE_CPP_INIT_LIST)
    144 MHD_C_DECLARATIONS_FINISH_HERE_
    145 #    include <vector>
    146 MHD_C_DECLARATIONS_START_HERE_
    147 /**
    148  * Set the requested options for the daemon.
    149  *
    150  * If any option fail other options may be or may be not applied.
    151  *
    152  * It should be used with helpers that creates required options, for example:
    153  *
    154  * MHD_DAEMON_SET_OPTIONS(d, MHD_D_OPTION_SUPPRESS_DATE_HEADER(MHD_YES),
    155  *                        MHD_D_OPTION_SOCK_ADDR(sa_len, sa))
    156  *
    157  * @param daemon the daemon to set the options
    158  * @param ... the list of the options, each option must be created
    159  *            by helpers MHD_D_OPTION_NameOfOption(option_value)
    160  * @return ::MHD_SC_OK on success,
    161  *         error code otherwise
    162  */
    163 #    define MHD_DAEMON_SET_OPTIONS(daemon,...)                  \
    164             MHD_NOWARN_CPP_INIT_LIST_                               \
    165             MHD_daemon_set_options (                                \
    166               daemon,                                               \
    167               (std::vector<struct MHD_DaemonOptionAndValue>         \
    168                {__VA_ARGS__,MHD_D_OPTION_TERMINATE ()}).data (),    \
    169               MHD_OPTIONS_ARRAY_MAX_SIZE)                           \
    170             MHD_RESTORE_WARN_CPP_INIT_LIST_
    171 #  endif
    172 MHD_RESTORE_WARN_VARIADIC_MACROS_
    173 #endif /* MHD_USE_VARARG_MACROS && MHD_USE_COMP_LIT_FUNC_PARAMS */
    174 /* *INDENT-ON* */
    175 
    176 
    177 /* ******************* Event loop ************************ */
    178 
    179 
    180 /**
    181  * Run websever operation with possible blocking.
    182  *
    183  * Supported only in #MHD_WM_EXTERNAL_PERIODIC and
    184  * #MHD_WM_EXTERNAL_SINGLE_FD_WATCH modes.
    185  *
    186  * This function does the following: waits for any network event not more than
    187  * specified number of microseconds, processes all incoming and outgoing data,
    188  * processes new connections, processes any timed-out connection, and does
    189  * other things required to run webserver.
    190  * Once all connections are processed, function returns.
    191  *
    192  * This function is useful for quick and simple (lazy) webserver implementation
    193  * if application needs to run a single thread only and does not have any other
    194  * network activity.
    195  *
    196  * In #MHD_WM_EXTERNAL_PERIODIC mode if @a microsec parameter is not zero
    197  * this function determines the internal daemon timeout and use returned value
    198  * as maximum wait time if it less than value of @a microsec parameter.
    199  *
    200  * @param daemon the daemon to run
    201  * @param microsec the maximum time in microseconds to wait for network and
    202  *                 other events. Note: there is no guarantee that function
    203  *                 blocks for the specified amount of time. The real processing
    204  *                 time can be shorter (if some data or connection timeout
    205  *                 comes earlier) or longer (if data processing requires more
    206  *                 time, especially in user callbacks).
    207  *                 If set to '0' then function does not block and processes
    208  *                 only already available data (if any). Zero value is
    209  *                 recommended when used in #MHD_WM_EXTERNAL_SINGLE_FD_WATCH
    210  *                 and the watched FD has been triggered.
    211  *                 If set to #MHD_WAIT_INDEFINITELY then function waits
    212  *                 for events indefinitely (blocks until next network activity
    213  *                 or connection timeout).
    214  *                 Always used as zero value in
    215  *                 #MHD_WM_EXTERNAL_SINGLE_FD_WATCH mode.
    216  * @return #MHD_SC_OK on success, otherwise
    217  *         an error code
    218  * @ingroup event
    219  */
    220 MHD_EXTERN_ enum MHD_StatusCode
    221 MHD_daemon_process_blocking (struct MHD_Daemon *daemon,
    222                              uint_fast64_t microsec)
    223 MHD_FN_PAR_NONNULL_ (1);
    224 
    225 /**
    226  * Run webserver operations (without blocking unless in client
    227  * callbacks).
    228  *
    229  * Supported only in #MHD_WM_EXTERNAL_SINGLE_FD_WATCH mode.
    230  *
    231  * This function does the following: processes all incoming and outgoing data,
    232  * processes new connections, processes any timed-out connection, and does
    233  * other things required to run webserver.
    234  * Once all connections are processed, function returns.
    235  *
    236  * @param daemon the daemon to run
    237  * @return #MHD_SC_OK on success, otherwise
    238  *         an error code
    239  * @ingroup event
    240  */
    241 #define MHD_daemon_process_nonblocking(daemon) \
    242         MHD_daemon_process_blocking (daemon, 0)
    243 
    244 
    245 /**
    246  * Add another client connection to the set of connections managed by
    247  * MHD.  This API is usually not needed (since MHD will accept inbound
    248  * connections on the server socket).  Use this API in special cases,
    249  * for example if your HTTP server is behind NAT and needs to connect
    250  * out to the HTTP client, or if you are building a proxy.
    251  *
    252  * The given client socket will be managed (and closed!) by MHD after
    253  * this call and must no longer be used directly by the application
    254  * afterwards.
    255  * The client socket will be closed by MHD even if error returned.
    256  *
    257  * @param daemon daemon that manages the connection
    258  * @param new_socket socket to manage (MHD will expect to receive an
    259                      HTTP request from this socket next).
    260  * @param addr_size number of bytes in @a addr
    261  * @param addr IP address of the client, ignored when @a addrlen is zero
    262  * @param connection_cntx meta data the application wants to
    263  *        associate with the new connection object
    264  * @return #MHD_SC_OK on success,
    265  *         error on failure (the @a new_socket is closed)
    266  * @ingroup specialized
    267  */
    268 MHD_EXTERN_ enum MHD_StatusCode
    269 MHD_daemon_add_connection (struct MHD_Daemon *MHD_RESTRICT daemon,
    270                            MHD_Socket new_socket,
    271                            size_t addr_size,
    272                            const struct sockaddr *MHD_RESTRICT addr,
    273                            void *connection_cntx)
    274 MHD_FN_PAR_NONNULL_ (1)
    275 MHD_FN_PAR_IN_ (4);
    276 
    277 
    278 /* ********************* connection options ************** */
    279 
    280 enum MHD_FIXED_ENUM_APP_SET_ MHD_ConnectionOption
    281 {
    282   /**
    283    * Not a real option.
    284    * Should not be used directly.
    285    * This value indicates the end of the list of the options.
    286    */
    287   MHD_C_O_END = 0
    288   ,
    289   /**
    290    * Set custom timeout for the given connection.
    291    * Specified as the number of seconds.  Use zero for no timeout.
    292    * Setting this option resets connection timeout timer.
    293    */
    294   MHD_C_O_TIMEOUT = 1
    295   ,
    296 
    297 
    298   /* * Sentinel * */
    299   /**
    300    * The sentinel value.
    301    * This value enforces specific underlying integer type for the enum.
    302    * Do not use.
    303    */
    304   MHD_C_O_SENTINEL = 65535
    305 };
    306 
    307 
    308 /**
    309  * Dummy-struct for space allocation.
    310  * Do not use in application logic.
    311  */
    312 struct MHD_ReservedStruct
    313 {
    314   uint_fast64_t reserved1;
    315   void *reserved2;
    316 };
    317 
    318 
    319 /**
    320  * Parameters for MHD connection options
    321  */
    322 union MHD_ConnectionOptionValue
    323 {
    324   /**
    325    * Value for #MHD_C_O_TIMEOUT
    326    */
    327   unsigned int v_timeout;
    328   /**
    329    * Reserved member. Do not use.
    330    */
    331   struct MHD_ReservedStruct reserved;
    332 };
    333 
    334 /**
    335  * Combination of MHD connection option with parameters values
    336  */
    337 struct MHD_ConnectionOptionAndValue
    338 {
    339   /**
    340    * The connection configuration option
    341    */
    342   enum MHD_ConnectionOption opt;
    343   /**
    344    * The value for the @a opt option
    345    */
    346   union MHD_ConnectionOptionValue val;
    347 };
    348 
    349 #if defined(MHD_USE_COMPOUND_LITERALS) && defined(MHD_USE_DESIG_NEST_INIT)
    350 /**
    351  * Set custom timeout for the given connection.
    352  * Specified as the number of seconds.  Use zero for no timeout.
    353  * Setting this option resets connection timeout timer.
    354  * @param timeout the in seconds, zero for no timeout
    355  * @return the object of struct MHD_ConnectionOptionAndValue with the requested
    356  *         values
    357  */
    358 #  define MHD_C_OPTION_TIMEOUT(timeout)         \
    359           MHD_NOWARN_COMPOUND_LITERALS_                 \
    360             (const struct MHD_ConnectionOptionAndValue) \
    361           {                                             \
    362             .opt = (MHD_C_O_TIMEOUT),                   \
    363             .val.v_timeout = (timeout)                  \
    364           }                                             \
    365           MHD_RESTORE_WARN_COMPOUND_LITERALS_
    366 
    367 /**
    368  * Terminate the list of the options
    369  * @return the terminating object of struct MHD_ConnectionOptionAndValue
    370  */
    371 #  define MHD_C_OPTION_TERMINATE()              \
    372           MHD_NOWARN_COMPOUND_LITERALS_                 \
    373             (const struct MHD_ConnectionOptionAndValue) \
    374           {                                             \
    375             .opt = (MHD_C_O_END)                        \
    376           }                                             \
    377           MHD_RESTORE_WARN_COMPOUND_LITERALS_
    378 
    379 #else  /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */
    380 MHD_NOWARN_UNUSED_FUNC_
    381 
    382 /**
    383  * Set custom timeout for the given connection.
    384  * Specified as the number of seconds.  Use zero for no timeout.
    385  * Setting this option resets connection timeout timer.
    386  * @param timeout the in seconds, zero for no timeout
    387  * @return the object of struct MHD_ConnectionOptionAndValue with the requested
    388  *         values
    389  */
    390 static MHD_INLINE struct MHD_ConnectionOptionAndValue
    391 MHD_C_OPTION_TIMEOUT (unsigned int timeout)
    392 {
    393   struct MHD_ConnectionOptionAndValue opt_val;
    394 
    395   opt_val.opt = MHD_C_O_TIMEOUT;
    396   opt_val.val.v_timeout = timeout;
    397 
    398   return opt_val;
    399 }
    400 
    401 
    402 /**
    403  * Terminate the list of the options
    404  * @return the terminating object of struct MHD_ConnectionOptionAndValue
    405  */
    406 static MHD_INLINE struct MHD_ConnectionOptionAndValue
    407 MHD_C_OPTION_TERMINATE (void)
    408 {
    409   struct MHD_ConnectionOptionAndValue opt_val;
    410 
    411   opt_val.opt = MHD_C_O_END;
    412 
    413   return opt_val;
    414 }
    415 
    416 
    417 MHD_RESTORE_WARN_UNUSED_FUNC_
    418 #endif /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */
    419 
    420 /**
    421  * Set the requested options for the connection.
    422  *
    423  * If any option fail other options may be or may be not applied.
    424  * @param connection the connection to set the options
    425  * @param[in] options the pointer to the array with the options;
    426  *                    the array processing stops at the first ::MHD_D_O_END
    427  *                    option, but not later than after processing
    428  *                    @a options_max_num entries
    429  * @param options_max_num the maximum number of entries in the @a options,
    430  *                        use #MHD_OPTIONS_ARRAY_MAX_SIZE if options processing
    431  *                        must stop only at zero-termination option
    432  * @return ::MHD_SC_OK on success,
    433  *         error code otherwise
    434  */
    435 MHD_EXTERN_ enum MHD_StatusCode
    436 MHD_connection_set_options (
    437   struct MHD_Connection *MHD_RESTRICT connection,
    438   const struct MHD_ConnectionOptionAndValue *MHD_RESTRICT options,
    439   size_t options_max_num)
    440 MHD_FN_PAR_NONNULL_ALL_;
    441 
    442 
    443 /**
    444  * Set the requested single option for the connection.
    445  *
    446  * @param connection the connection to set the options
    447  * @param[in] option_ptr the pointer to the option
    448  * @return ::MHD_SC_OK on success,
    449  *         error code otherwise
    450  */
    451 #define MHD_connection_set_option(connection, option_ptr) \
    452         MHD_connection_set_options (connection, options_ptr, 1)
    453 
    454 
    455 /* *INDENT-OFF* */
    456 #ifdef MHD_USE_VARARG_MACROS
    457 MHD_NOWARN_VARIADIC_MACROS_
    458 #  if defined(MHD_USE_COMPOUND_LITERALS) && defined(MHD_USE_COMP_LIT_FUNC_PARAMS \
    459                                                     )
    460 /**
    461  * Set the requested options for the connection.
    462  *
    463  * If any option fail other options may be or may be not applied.
    464  *
    465  * It should be used with helpers that creates required options, for example:
    466  *
    467  * MHD_CONNECTION_SET_OPTIONS(d, MHD_C_OPTION_TIMEOUT(30))
    468  *
    469  * @param connection the connection to set the options
    470  * @param ... the list of the options, each option must be created
    471  *            by helpers MHD_C_OPTION_NameOfOption(option_value)
    472  * @return ::MHD_SC_OK on success,
    473  *         error code otherwise
    474  */
    475 #    define MHD_CONNECTION_SET_OPTIONS(connection,...)          \
    476             MHD_NOWARN_COMPOUND_LITERALS_                           \
    477             MHD_connection_set_options (                            \
    478               daemon,                                               \
    479               ((const struct MHD_ConnectionOptionAndValue [])       \
    480                {__VA_ARGS__, MHD_C_OPTION_TERMINATE ()}),           \
    481               MHD_OPTIONS_ARRAY_MAX_SIZE)                           \
    482             MHD_RESTORE_WARN_COMPOUND_LITERALS_
    483 #  elif defined(MHD_USE_CPP_INIT_LIST)
    484 MHD_C_DECLARATIONS_FINISH_HERE_
    485 #    include <vector>
    486 MHD_C_DECLARATIONS_START_HERE_
    487 /**
    488  * Set the requested options for the connection.
    489  *
    490  * If any option fail other options may be or may be not applied.
    491  *
    492  * It should be used with helpers that creates required options, for example:
    493  *
    494  * MHD_CONNECTION_SET_OPTIONS(d, MHD_C_OPTION_TIMEOUT(30))
    495  *
    496  * @param connection the connection to set the options
    497  * @param ... the list of the options, each option must be created
    498  *            by helpers MHD_C_OPTION_NameOfOption(option_value)
    499  * @return ::MHD_SC_OK on success,
    500  *         error code otherwise
    501  */
    502 #    define MHD_CONNECTION_SET_OPTIONS(daemon,...)              \
    503             MHD_NOWARN_CPP_INIT_LIST_                               \
    504             MHD_daemon_set_options (                                \
    505               daemon,                                               \
    506               (std::vector<struct MHD_ConnectionOptionAndValue>     \
    507                {__VA_ARGS__,MHD_C_OPTION_TERMINATE ()}).data (),    \
    508               MHD_OPTIONS_ARRAY_MAX_SIZE)                           \
    509             MHD_RESTORE_WARN_CPP_INIT_LIST_
    510 #  endif
    511 MHD_RESTORE_WARN_VARIADIC_MACROS_
    512 #endif /* MHD_USE_VARARG_MACROS && MHD_USE_COMP_LIT_FUNC_PARAMS */
    513 /* *INDENT-ON* */
    514 
    515 
    516 /* **************** Request handling functions ***************** */
    517 
    518 
    519 /**
    520  * The `enum MHD_ValueKind` specifies the source of
    521  * the name-value pairs in the HTTP protocol.
    522  */
    523 enum MHD_FLAGS_ENUM_ MHD_ValueKind
    524 {
    525 
    526   /**
    527    * HTTP header.
    528    * The 'value' for this kind is mandatory.
    529    */
    530   MHD_VK_HEADER = (1u << 0)
    531   ,
    532   /**
    533    * Cookies.  Note that the original HTTP header containing
    534    * the cookie(s) will still be available and intact.
    535    * The 'value' for this kind is optional.
    536    */
    537   MHD_VK_COOKIE = (1u << 1)
    538   ,
    539   /**
    540    * URI query parameter.
    541    * The 'value' for this kind is optional.
    542    */
    543   MHD_VK_URI_QUERY_PARAM = (1u << 2)
    544   ,
    545   /**
    546    * POST data.
    547    * This is available only if #MHD_action_parse_post() action is used,
    548    * a content encoding is supported by MHD, and only if the posted content
    549    * fits within the specified memory buffers.
    550    *
    551    * @warning The encoding "multipart/form-data" has more fields than just
    552    * "name" and "value". See #MHD_request_get_post_data_cb() and
    553    * #MHD_request_get_post_data_list(). In particular it could be important
    554    * to check used "Transfer-Encoding". While it is deprecated and not used
    555    * by modern clients, formally it can be used.
    556    */
    557   MHD_VK_POSTDATA = (1u << 3)
    558   ,
    559   /**
    560    * HTTP trailer (only for HTTP 1.1 chunked encodings, "footer").
    561    * The 'value' for this kind is mandatory.
    562    */
    563   MHD_VK_TRAILER = (1u << 4)
    564   ,
    565   /**
    566    * Header and trailer values.
    567    */
    568   MHD_VK_HEADER_TRAILER = MHD_VK_HEADER | MHD_VK_TRAILER
    569   ,
    570   /**
    571    * Values from URI query parameters or post data.
    572    */
    573   MHD_VK_URI_QUERY_POST = MHD_VK_POSTDATA | MHD_VK_URI_QUERY_PARAM
    574 };
    575 
    576 /**
    577  * Name with value pair
    578  */
    579 struct MHD_NameAndValue
    580 {
    581   /**
    582    * The name (key) of the field.
    583    * The pointer to the C string must never be NULL.
    584    * Some types (kinds) allow empty strings.
    585    */
    586   struct MHD_String name;
    587   /**
    588    * The value of the field.
    589    * Some types (kinds) allow absence of the value. The absence is indicated
    590    * by NULL pointer to the C string.
    591    */
    592   struct MHD_StringNullable value;
    593 };
    594 
    595 /**
    596  * Name, value and kind (type) of data
    597  */
    598 struct MHD_NameValueKind
    599 {
    600   /**
    601    * The name and the value of the field
    602    */
    603   struct MHD_NameAndValue nv;
    604   /**
    605    * The kind (type) of the field
    606    */
    607   enum MHD_ValueKind kind;
    608 };
    609 
    610 /**
    611  * Iterator over name-value pairs.  This iterator can be used to
    612  * iterate over all of the cookies, headers, footers or POST-data fields
    613  * of a request.
    614  *
    615  * The @a nv pointer is valid only until return from this function.
    616  *
    617  * The strings in @a nv are valid until any MHD_Action or MHD_UploadAction
    618  * is provided.
    619  * If the data is needed beyond this point, it should be copied.
    620  *
    621  * @param cls closure
    622  * @param nv the name and the value of the element, the pointer is valid only until
    623  *           return from this function
    624  * @param kind the type (kind) of the element
    625  * @return #MHD_YES to continue iterating,
    626  *         #MHD_NO to abort the iteration
    627  * @ingroup request
    628  */
    629 typedef enum MHD_Bool
    630 (MHD_FN_PAR_NONNULL_ (3)
    631  *MHD_NameValueIterator)(void *cls,
    632                          enum MHD_ValueKind kind,
    633                          const struct MHD_NameAndValue *nv);
    634 
    635 
    636 /**
    637  * Get all of the headers (or other kind of request data) via callback.
    638  *
    639  * @param[in,out] request request to get values from
    640  * @param kind types of values to iterate over, can be a bitmask
    641  * @param iterator callback to call on each header;
    642  *        maybe NULL (then just count headers)
    643  * @param iterator_cls extra argument to @a iterator
    644  * @return number of entries iterated over
    645  * @ingroup request
    646  */
    647 MHD_EXTERN_ size_t
    648 MHD_request_get_values_cb (struct MHD_Request *request,
    649                            enum MHD_ValueKind kind,
    650                            MHD_NameValueIterator iterator,
    651                            void *iterator_cls)
    652 MHD_FN_PAR_NONNULL_ (1);
    653 
    654 
    655 /**
    656  * Get all of the headers (or other kind of request data) from the request.
    657  *
    658  * The pointers to the strings in @a elements are valid until any
    659  * MHD_Action or MHD_UploadAction is provided. If the data is needed beyond
    660  * this point, it should be copied.
    661  *
    662  * @param[in] request request to get values from
    663  * @param kind the types of values to get, can be a bitmask
    664  * @param num_elements the number of elements in @a elements array
    665  * @param[out] elements the array of @a num_elements strings to be filled with
    666  *                      the key-value pairs; if @a request has more elements
    667  *                      than @a num_elements than any @a num_elements are
    668  *                      stored
    669  * @return the number of elements stored in @a elements, the
    670  *         number cannot be larger then @a num_elements,
    671  *         zero if there is no such values or any error occurs
    672  */
    673 MHD_EXTERN_ size_t
    674 MHD_request_get_values_list (
    675   struct MHD_Request *request,
    676   enum MHD_ValueKind kind,
    677   size_t num_elements,
    678   struct MHD_NameValueKind elements[MHD_FN_PAR_DYN_ARR_SIZE_ (num_elements)])
    679 MHD_FN_PAR_NONNULL_ (1)
    680 MHD_FN_PAR_NONNULL_ (4) MHD_FN_PAR_OUT_SIZE_ (4, 3);
    681 
    682 
    683 /**
    684  * Get a particular header (or other kind of request data) value.
    685  * If multiple values match the kind, return any one of them.
    686  *
    687  * The data in the @a value_out is valid until any MHD_Action or
    688  * MHD_UploadAction is provided. If the data is needed beyond this point,
    689  * it should be copied.
    690  *
    691  * @param request request to get values from
    692  * @param kind what kind of value are we looking for
    693  * @param key the name of the value looking for (used for case-insensetive
    694  *            match), empty to lookup 'trailing' value without a key
    695  * @param[out] value_out set to the value of the header if succeed,
    696  *                       the @a cstr pointer could be NULL even if succeed
    697  *                       if the requested item found, but has no value
    698  * @return #MHD_YES if succeed, the @a value_out is set;
    699  *         #MHD_NO if no such item was found, the @a value_out string pointer
    700  *                 set to NULL
    701  * @ingroup request
    702  */
    703 MHD_EXTERN_ enum MHD_Bool
    704 MHD_request_get_value (struct MHD_Request *MHD_RESTRICT request,
    705                        enum MHD_ValueKind kind,
    706                        const char *MHD_RESTRICT key,
    707                        struct MHD_StringNullable *MHD_RESTRICT value_out)
    708 MHD_FN_PAR_NONNULL_ (1)
    709 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_CSTR_ (3)
    710 MHD_FN_PAR_OUT_ (4);
    711 
    712 
    713 /**
    714  * @brief Status codes defined for HTTP responses.
    715  *
    716  * @defgroup httpcode HTTP response codes
    717  * @{
    718  */
    719 /* Registry export date: 2023-09-29 */
    720 /* See http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml */
    721 enum MHD_FIXED_ENUM_APP_SET_ MHD_HTTP_StatusCode
    722 {
    723   /* 100 "Continue".            RFC9110, Section 15.2.1. */
    724   MHD_HTTP_STATUS_CONTINUE =                    100
    725   ,
    726   /* 101 "Switching Protocols". RFC9110, Section 15.2.2. */
    727   MHD_HTTP_STATUS_SWITCHING_PROTOCOLS =         101
    728   ,
    729   /* 102 "Processing".          RFC2518. */
    730   MHD_HTTP_STATUS_PROCESSING =                  102
    731   ,
    732   /* 103 "Early Hints".         RFC8297. */
    733   MHD_HTTP_STATUS_EARLY_HINTS =                 103
    734   ,
    735 
    736   /* 200 "OK".                  RFC9110, Section 15.3.1. */
    737   MHD_HTTP_STATUS_OK =                          200
    738   ,
    739   /* 201 "Created".             RFC9110, Section 15.3.2. */
    740   MHD_HTTP_STATUS_CREATED =                     201
    741   ,
    742   /* 202 "Accepted".            RFC9110, Section 15.3.3. */
    743   MHD_HTTP_STATUS_ACCEPTED =                    202
    744   ,
    745   /* 203 "Non-Authoritative Information". RFC9110, Section 15.3.4. */
    746   MHD_HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203
    747   ,
    748   /* 204 "No Content".          RFC9110, Section 15.3.5. */
    749   MHD_HTTP_STATUS_NO_CONTENT =                  204
    750   ,
    751   /* 205 "Reset Content".       RFC9110, Section 15.3.6. */
    752   MHD_HTTP_STATUS_RESET_CONTENT =               205
    753   ,
    754   /* 206 "Partial Content".     RFC9110, Section 15.3.7. */
    755   MHD_HTTP_STATUS_PARTIAL_CONTENT =             206
    756   ,
    757   /* 207 "Multi-Status".        RFC4918. */
    758   MHD_HTTP_STATUS_MULTI_STATUS =                207
    759   ,
    760   /* 208 "Already Reported".    RFC5842. */
    761   MHD_HTTP_STATUS_ALREADY_REPORTED =            208
    762   ,
    763 
    764   /* 226 "IM Used".             RFC3229. */
    765   MHD_HTTP_STATUS_IM_USED =                     226
    766   ,
    767 
    768   /* 300 "Multiple Choices".    RFC9110, Section 15.4.1. */
    769   MHD_HTTP_STATUS_MULTIPLE_CHOICES =            300
    770   ,
    771   /* 301 "Moved Permanently".   RFC9110, Section 15.4.2. */
    772   MHD_HTTP_STATUS_MOVED_PERMANENTLY =           301
    773   ,
    774   /* 302 "Found".               RFC9110, Section 15.4.3. */
    775   MHD_HTTP_STATUS_FOUND =                       302
    776   ,
    777   /* 303 "See Other".           RFC9110, Section 15.4.4. */
    778   MHD_HTTP_STATUS_SEE_OTHER =                   303
    779   ,
    780   /* 304 "Not Modified".        RFC9110, Section 15.4.5. */
    781   MHD_HTTP_STATUS_NOT_MODIFIED =                304
    782   ,
    783   /* 305 "Use Proxy".           RFC9110, Section 15.4.6. */
    784   MHD_HTTP_STATUS_USE_PROXY =                   305
    785   ,
    786   /* 306 "Switch Proxy".        Not used! RFC9110, Section 15.4.7. */
    787   MHD_HTTP_STATUS_SWITCH_PROXY =                306
    788   ,
    789   /* 307 "Temporary Redirect".  RFC9110, Section 15.4.8. */
    790   MHD_HTTP_STATUS_TEMPORARY_REDIRECT =          307
    791   ,
    792   /* 308 "Permanent Redirect".  RFC9110, Section 15.4.9. */
    793   MHD_HTTP_STATUS_PERMANENT_REDIRECT =          308
    794   ,
    795 
    796   /* 400 "Bad Request".         RFC9110, Section 15.5.1. */
    797   MHD_HTTP_STATUS_BAD_REQUEST =                 400
    798   ,
    799   /* 401 "Unauthorized".        RFC9110, Section 15.5.2. */
    800   MHD_HTTP_STATUS_UNAUTHORIZED =                401
    801   ,
    802   /* 402 "Payment Required".    RFC9110, Section 15.5.3. */
    803   MHD_HTTP_STATUS_PAYMENT_REQUIRED =            402
    804   ,
    805   /* 403 "Forbidden".           RFC9110, Section 15.5.4. */
    806   MHD_HTTP_STATUS_FORBIDDEN =                   403
    807   ,
    808   /* 404 "Not Found".           RFC9110, Section 15.5.5. */
    809   MHD_HTTP_STATUS_NOT_FOUND =                   404
    810   ,
    811   /* 405 "Method Not Allowed".  RFC9110, Section 15.5.6. */
    812   MHD_HTTP_STATUS_METHOD_NOT_ALLOWED =          405
    813   ,
    814   /* 406 "Not Acceptable".      RFC9110, Section 15.5.7. */
    815   MHD_HTTP_STATUS_NOT_ACCEPTABLE =              406
    816   ,
    817   /* 407 "Proxy Authentication Required". RFC9110, Section 15.5.8. */
    818   MHD_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407
    819   ,
    820   /* 408 "Request Timeout".     RFC9110, Section 15.5.9. */
    821   MHD_HTTP_STATUS_REQUEST_TIMEOUT =             408
    822   ,
    823   /* 409 "Conflict".            RFC9110, Section 15.5.10. */
    824   MHD_HTTP_STATUS_CONFLICT =                    409
    825   ,
    826   /* 410 "Gone".                RFC9110, Section 15.5.11. */
    827   MHD_HTTP_STATUS_GONE =                        410
    828   ,
    829   /* 411 "Length Required".     RFC9110, Section 15.5.12. */
    830   MHD_HTTP_STATUS_LENGTH_REQUIRED =             411
    831   ,
    832   /* 412 "Precondition Failed". RFC9110, Section 15.5.13. */
    833   MHD_HTTP_STATUS_PRECONDITION_FAILED =         412
    834   ,
    835   /* 413 "Content Too Large".   RFC9110, Section 15.5.14. */
    836   MHD_HTTP_STATUS_CONTENT_TOO_LARGE =           413
    837   ,
    838   /* 414 "URI Too Long".        RFC9110, Section 15.5.15. */
    839   MHD_HTTP_STATUS_URI_TOO_LONG =                414
    840   ,
    841   /* 415 "Unsupported Media Type". RFC9110, Section 15.5.16. */
    842   MHD_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE =      415
    843   ,
    844   /* 416 "Range Not Satisfiable". RFC9110, Section 15.5.17. */
    845   MHD_HTTP_STATUS_RANGE_NOT_SATISFIABLE =       416
    846   ,
    847   /* 417 "Expectation Failed".  RFC9110, Section 15.5.18. */
    848   MHD_HTTP_STATUS_EXPECTATION_FAILED =          417
    849   ,
    850 
    851 
    852   /* 421 "Misdirected Request". RFC9110, Section 15.5.20. */
    853   MHD_HTTP_STATUS_MISDIRECTED_REQUEST =         421
    854   ,
    855   /* 422 "Unprocessable Content". RFC9110, Section 15.5.21. */
    856   MHD_HTTP_STATUS_UNPROCESSABLE_CONTENT =       422
    857   ,
    858   /* 423 "Locked".              RFC4918. */
    859   MHD_HTTP_STATUS_LOCKED =                      423
    860   ,
    861   /* 424 "Failed Dependency".   RFC4918. */
    862   MHD_HTTP_STATUS_FAILED_DEPENDENCY =           424
    863   ,
    864   /* 425 "Too Early".           RFC8470. */
    865   MHD_HTTP_STATUS_TOO_EARLY =                   425
    866   ,
    867   /* 426 "Upgrade Required".    RFC9110, Section 15.5.22. */
    868   MHD_HTTP_STATUS_UPGRADE_REQUIRED =            426
    869   ,
    870 
    871   /* 428 "Precondition Required". RFC6585. */
    872   MHD_HTTP_STATUS_PRECONDITION_REQUIRED =       428
    873   ,
    874   /* 429 "Too Many Requests".   RFC6585. */
    875   MHD_HTTP_STATUS_TOO_MANY_REQUESTS =           429
    876   ,
    877 
    878   /* 431 "Request Header Fields Too Large". RFC6585. */
    879   MHD_HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
    880   ,
    881 
    882   /* 451 "Unavailable For Legal Reasons". RFC7725. */
    883   MHD_HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451
    884   ,
    885 
    886   /* 500 "Internal Server Error". RFC9110, Section 15.6.1. */
    887   MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR =       500
    888   ,
    889   /* 501 "Not Implemented".     RFC9110, Section 15.6.2. */
    890   MHD_HTTP_STATUS_NOT_IMPLEMENTED =             501
    891   ,
    892   /* 502 "Bad Gateway".         RFC9110, Section 15.6.3. */
    893   MHD_HTTP_STATUS_BAD_GATEWAY =                 502
    894   ,
    895   /* 503 "Service Unavailable". RFC9110, Section 15.6.4. */
    896   MHD_HTTP_STATUS_SERVICE_UNAVAILABLE =         503
    897   ,
    898   /* 504 "Gateway Timeout".     RFC9110, Section 15.6.5. */
    899   MHD_HTTP_STATUS_GATEWAY_TIMEOUT =             504
    900   ,
    901   /* 505 "HTTP Version Not Supported". RFC9110, Section 15.6.6. */
    902   MHD_HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED =  505
    903   ,
    904   /* 506 "Variant Also Negotiates". RFC2295. */
    905   MHD_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES =     506
    906   ,
    907   /* 507 "Insufficient Storage". RFC4918. */
    908   MHD_HTTP_STATUS_INSUFFICIENT_STORAGE =        507
    909   ,
    910   /* 508 "Loop Detected".       RFC5842. */
    911   MHD_HTTP_STATUS_LOOP_DETECTED =               508
    912   ,
    913 
    914   /* 510 "Not Extended".        (OBSOLETED) RFC2774; status-change-http-experiments-to-historic. */
    915   MHD_HTTP_STATUS_NOT_EXTENDED =                510
    916   ,
    917   /* 511 "Network Authentication Required". RFC6585. */
    918   MHD_HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511
    919   ,
    920 
    921 
    922   /* Not registered non-standard codes */
    923   /* 449 "Reply With".          MS IIS extension. */
    924   MHD_HTTP_STATUS_RETRY_WITH =                  449
    925   ,
    926 
    927   /* 450 "Blocked by Windows Parental Controls". MS extension. */
    928   MHD_HTTP_STATUS_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS = 450
    929   ,
    930 
    931   /* 509 "Bandwidth Limit Exceeded". Apache extension. */
    932   MHD_HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED =    509
    933 };
    934 
    935 
    936 /**
    937  * Returns the string status for a response code.
    938  *
    939  * This function works for @b HTTP status code, not for @b MHD error codes/
    940  * @param code the HTTP code to get text representation for
    941  * @return the pointer to the text representation,
    942  *         NULL if HTTP status code in not known.
    943  */
    944 MHD_EXTERN_ const struct MHD_String *
    945 MHD_HTTP_status_code_to_string (enum MHD_HTTP_StatusCode code)
    946 MHD_FN_CONST_;
    947 
    948 /**
    949  * Get the pointer to the C string for the HTTP response code, never NULL.
    950  */
    951 #define MHD_HTTP_status_code_to_string_lazy(code) \
    952         (MHD_HTTP_status_code_to_string ((code)) ? \
    953          ((MHD_HTTP_status_code_to_string (code))->cstr) : ("[No status]") )
    954 
    955 
    956 /** @} */ /* end of group httpcode */
    957 
    958 #ifndef MHD_HTTP_PROTOCOL_VER_DEFINED
    959 
    960 /**
    961  * @brief HTTP protocol versions
    962  * @defgroup versions HTTP versions
    963  * @{
    964  */
    965 enum MHD_FIXED_ENUM_MHD_SET_ MHD_HTTP_ProtocolVersion
    966 {
    967   MHD_HTTP_VERSION_INVALID = 0  /**< Invalid/unrecognised HTTP version */
    968   ,
    969   MHD_HTTP_VERSION_1_0 = 10     /**< HTTP/1.0 */
    970   ,
    971   MHD_HTTP_VERSION_1_1 = 11     /**< HTTP/1.1 */
    972   ,
    973   MHD_HTTP_VERSION_1_2P = 19    /**< HTTP/1.2 - HTTP/1.9 */
    974   ,
    975   MHD_HTTP_VERSION_2 = 20       /**< HTTP/2 */
    976   ,
    977   MHD_HTTP_VERSION_3 = 30       /**< HTTP/3 */
    978   ,
    979   MHD_HTTP_VERSION_FUTURE = 255 /**< Future HTTP version */
    980 };
    981 
    982 #  define MHD_HTTP_PROTOCOL_VER_DEFINED 1
    983 #endif /* ! MHD_HTTP_PROTOCOL_VER_DEFINED */
    984 
    985 /**
    986  * Return the string representation of the requested HTTP version.
    987  * Note: this is suitable mainly for logging and similar purposes as
    988  * HTTP/2 (and later) is not used inside the HTTP protocol.
    989  * @param pv the protocol version
    990  * @return the string representation of the protocol version,
    991  *         NULL for invalid values
    992  */
    993 MHD_EXTERN_ const struct MHD_String *
    994 MHD_protocol_version_to_string (enum MHD_HTTP_ProtocolVersion pv)
    995 MHD_FN_CONST_;
    996 
    997 /**
    998  * HTTP/1.0 identification string
    999  */
   1000 #define MHD_HTTP_VERSION_1_0_STR "HTTP/1.0"
   1001 /**
   1002  * HTTP/1.1 identification string
   1003  */
   1004 #define MHD_HTTP_VERSION_1_1_STR "HTTP/1.1"
   1005 /**
   1006  * Identification string for clients claiming HTTP/1.2 - HTTP/1.9
   1007  * Not used by the HTTP protocol, useful for logs and similar purposes.
   1008  */
   1009 #define MHD_HTTP_VERSION_1_2P_STR "HTTP/1.2+"
   1010 /**
   1011  * HTTP/2 identification string.
   1012  * Not used by the HTTP protocol (except non-TLS handshake), useful for logs and
   1013  * similar purposes.
   1014  */
   1015 #define MHD_HTTP_VERSION_2_STR "HTTP/2"
   1016 /**
   1017  * HTTP/3 identification string.
   1018  * Not used by the HTTP protocol, useful for logs and similar purposes.
   1019  */
   1020 #define MHD_HTTP_VERSION_3_STR "HTTP/3"
   1021 
   1022 /** @} */ /* end of group versions */
   1023 
   1024 
   1025 /**
   1026  * Resume handling of network data for suspended request.
   1027  * It is safe to resume a suspended request at any time.
   1028  * Calling this function on a request that was not previously suspended will
   1029  * result in undefined behaviour.
   1030  *
   1031  * @param[in,out] request the request to resume
   1032  */
   1033 MHD_EXTERN_ void
   1034 MHD_request_resume (struct MHD_Request *request)
   1035 MHD_FN_PAR_NONNULL_ALL_;
   1036 
   1037 
   1038 /* ************** Action and Response manipulation functions **************** */
   1039 
   1040 /**
   1041  * @defgroup response Response objects control
   1042  */
   1043 
   1044 
   1045 /**
   1046  * Name with value pair as C strings
   1047  */
   1048 struct MHD_NameValueCStr
   1049 {
   1050   /**
   1051    * The name (key) of the field.
   1052    * Must never be NULL.
   1053    * Some types (kinds) allow empty strings.
   1054    */
   1055   const char *name;
   1056   /**
   1057    * The value of the field.
   1058    * Some types (kinds) allow absence of the value. The absence is indicated
   1059    * by NULL pointer.
   1060    */
   1061   const char *value;
   1062 };
   1063 
   1064 /**
   1065  * Data transmitted in response to an HTTP request.
   1066  * Usually the final action taken in response to
   1067  * receiving a request.
   1068  */
   1069 struct MHD_Response;
   1070 
   1071 
   1072 /**
   1073  * Suspend handling of network data for a given request.  This can
   1074  * be used to dequeue a request from MHD's event loop for a while.
   1075  *
   1076  * Suspended requests continue to count against the total number of
   1077  * requests allowed (per daemon, as well as per IP, if such limits
   1078  * are set).  Suspended requests will NOT time out; timeouts will
   1079  * restart when the request handling is resumed.  While a
   1080  * request is suspended, MHD may not detect disconnects by the
   1081  * client.
   1082  *
   1083  * At most one action can be created for any request.
   1084  *
   1085  * @param[in,out] request the request for which the action is generated
   1086  * @return action to cause a request to be suspended,
   1087  *         NULL if any action has been already created for the @a request
   1088  * @ingroup action
   1089  */
   1090 MHD_EXTERN_ const struct MHD_Action *
   1091 MHD_action_suspend (struct MHD_Request *request)
   1092 MHD_FN_PAR_NONNULL_ALL_;
   1093 
   1094 
   1095 /**
   1096  * Converts a @a response to an action.  If #MHD_R_O_REUSABLE
   1097  * is not set, the reference to the @a response is consumed
   1098  * by the conversion. If #MHD_R_O_REUSABLE is #MHD_YES,
   1099  * then the @a response can be used again to create actions in
   1100  * the future.
   1101  * However, the @a response is frozen by this step and
   1102  * must no longer be modified (i.e. by setting headers).
   1103  *
   1104  * At most one action can be created for any request.
   1105  *
   1106  * @param request the request to create the action for
   1107  * @param[in] response the response to convert,
   1108  *                     if NULL then this function is equivalent to
   1109  *                     #MHD_action_abort_connection() call
   1110  * @return pointer to the action, the action must be consumed
   1111  *         otherwise response object may leak;
   1112  *         NULL if failed (no memory) or if any action has been already
   1113  *         created for the @a request;
   1114  *         when failed the response object is consumed and need not
   1115  *         to be "destroyed"
   1116  * @ingroup action
   1117  */
   1118 MHD_EXTERN_ const struct MHD_Action *
   1119 MHD_action_from_response (struct MHD_Request *MHD_RESTRICT request,
   1120                           struct MHD_Response *MHD_RESTRICT response)
   1121 MHD_FN_PAR_NONNULL_ (1);
   1122 
   1123 
   1124 /**
   1125  * Action telling MHD to close the connection hard
   1126  * (kind-of breaking HTTP specification).
   1127  *
   1128  * @param req the request to make an action
   1129  * @return action operation, always NULL
   1130  * @ingroup action
   1131  */
   1132 #define MHD_action_abort_request(req) \
   1133         MHD_STATIC_CAST_ (const struct MHD_Action *, NULL)
   1134 
   1135 
   1136 /**
   1137  * Set the requested options for the response.
   1138  *
   1139  * If any option fail other options may be or may be not applied.
   1140  * @param response the response to set the options
   1141  * @param[in] options the pointer to the array with the options;
   1142  *                    the array processing stops at the first ::MHD_D_O_END
   1143  *                    option, but not later than after processing
   1144  *                    @a options_max_num entries
   1145  * @param options_max_num the maximum number of entries in the @a options,
   1146  *                        use #MHD_OPTIONS_ARRAY_MAX_SIZE if options processing
   1147  *                        must stop only at zero-termination option
   1148  * @return ::MHD_SC_OK on success,
   1149  *         error code otherwise
   1150  */
   1151 MHD_EXTERN_ enum MHD_StatusCode
   1152 MHD_response_set_options (
   1153   struct MHD_Response *MHD_RESTRICT response,
   1154   const struct MHD_ResponseOptionAndValue *MHD_RESTRICT options,
   1155   size_t options_max_num)
   1156 MHD_FN_PAR_NONNULL_ALL_;
   1157 
   1158 
   1159 /**
   1160  * Set the requested single option for the response.
   1161  *
   1162  * @param response the response to set the option
   1163  * @param[in] option_ptr the pointer to the option
   1164  * @return ::MHD_SC_OK on success,
   1165  *         error code otherwise
   1166  * @ingroup response
   1167  */
   1168 #define MHD_response_set_option(response, option_ptr) \
   1169         MHD_response_set_options (response,option_ptr,1)
   1170 
   1171 
   1172 /* *INDENT-OFF* */
   1173 #ifdef MHD_USE_VARARG_MACROS
   1174 MHD_NOWARN_VARIADIC_MACROS_
   1175 #  if defined(MHD_USE_COMPOUND_LITERALS) && \
   1176   defined(MHD_USE_COMP_LIT_FUNC_PARAMS)
   1177 /**
   1178  * Set the requested options for the response.
   1179  *
   1180  * If any option fail other options may be or may be not applied.
   1181  *
   1182  * It should be used with helpers that creates required options, for example:
   1183  *
   1184  * MHD_RESPONSE_SET_OPTIONS(r, MHD_R_OPTION_REUSABLE(MHD_YES),
   1185  *                          MHD_R_OPTION_TERMINATION_CALLBACK(func, cls))
   1186  *
   1187  * @param response the response to set the option
   1188  * @param ... the list of the options, each option must be created
   1189  *            by helpers MHD_RESPONSE_OPTION_NameOfOption(option_value)
   1190  * @return ::MHD_SC_OK on success,
   1191  *         error code otherwise
   1192  */
   1193 #    define MHD_RESPONSE_SET_OPTIONS(response,...)              \
   1194             MHD_NOWARN_COMPOUND_LITERALS_                           \
   1195             MHD_response_set_options (                              \
   1196               response,                                             \
   1197               ((const struct MHD_ResponseOptionAndValue[])          \
   1198                {__VA_ARGS__, MHD_R_OPTION_TERMINATE ()}),           \
   1199               MHD_OPTIONS_ARRAY_MAX_SIZE)                           \
   1200             MHD_RESTORE_WARN_COMPOUND_LITERALS_
   1201 #  elif defined(MHD_USE_CPP_INIT_LIST)
   1202 MHD_C_DECLARATIONS_FINISH_HERE_
   1203 #    include <vector>
   1204 MHD_C_DECLARATIONS_START_HERE_
   1205 /**
   1206  * Set the requested options for the response.
   1207  *
   1208  * If any option fail other options may be or may be not applied.
   1209  *
   1210  * It should be used with helpers that creates required options, for example:
   1211  *
   1212  * MHD_RESPONSE_SET_OPTIONS(r, MHD_R_OPTION_REUSABLE(MHD_YES),
   1213  *                          MHD_R_OPTION_TERMINATION_CALLBACK(func, cls))
   1214  *
   1215  * @param response the response to set the option
   1216  * @param ... the list of the options, each option must be created
   1217  *            by helpers MHD_RESPONSE_OPTION_NameOfOption(option_value)
   1218  * @return ::MHD_SC_OK on success,
   1219  *         error code otherwise
   1220  */
   1221 #    define MHD_RESPONSE_SET_OPTIONS(response,...)              \
   1222             MHD_NOWARN_CPP_INIT_LIST_                               \
   1223             MHD_response_set_options (                              \
   1224               response,                                             \
   1225               (std::vector<struct MHD_ResponseOptionAndValue>       \
   1226                {__VA_ARGS__,MHD_R_OPTION_TERMINATE ()}).data (),    \
   1227               MHD_OPTIONS_ARRAY_MAX_SIZE)                           \
   1228             MHD_RESTORE_WARN_CPP_INIT_LIST_
   1229 #  endif
   1230 MHD_RESTORE_WARN_VARIADIC_MACROS_
   1231 #endif /* MHD_USE_VARARG_MACROS && MHD_USE_COMP_LIT_FUNC_PARAMS */
   1232 /* *INDENT-ON* */
   1233 
   1234 #ifndef MHD_FREECALLBACK_DEFINED
   1235 
   1236 /**
   1237  * This method is called by libmicrohttpd when response with dynamic content
   1238  * is being destroyed.  It should be used to free resources associated
   1239  * with the dynamic content.
   1240  *
   1241  * @param[in] free_cls closure
   1242  * @ingroup response
   1243  */
   1244 typedef void
   1245 (*MHD_FreeCallback)(void *free_cls);
   1246 
   1247 #  define MHD_FREECALLBACK_DEFINED 1
   1248 #endif /* ! MHD_FREECALLBACK_DEFINED */
   1249 #ifndef MHD_DYNCONTENTZCIOVEC_DEFINED
   1250 
   1251 
   1252 /**
   1253  * Structure for iov type of the response.
   1254  * Used for zero-copy response content data.
   1255  */
   1256 struct MHD_DynContentZCIoVec
   1257 {
   1258   /**
   1259    * The number of elements in @a iov
   1260    */
   1261   unsigned int iov_count;
   1262   /**
   1263    * The pointer to the array with @a iov_count elements.
   1264    */
   1265   const struct MHD_IoVec *iov;
   1266   /**
   1267    * The callback to free resources.
   1268    * It is called once the full array of iov elements is sent.
   1269    * No callback is called if NULL.
   1270    */
   1271   MHD_FreeCallback iov_fcb;
   1272   /**
   1273    * The parameter for @a iov_fcb
   1274    */
   1275   void *iov_fcb_cls;
   1276 };
   1277 
   1278 #  define MHD_DYNCONTENTZCIOVEC_DEFINED 1
   1279 #endif /* ! MHD_DYNCONTENTZCIOVEC_DEFINED */
   1280 
   1281 /**
   1282  * The action type returned by Dynamic Content Creator callback
   1283  */
   1284 struct MHD_DynamicContentCreatorAction;
   1285 
   1286 /**
   1287  * The context used for Dynamic Content Creator callback
   1288  */
   1289 struct MHD_DynamicContentCreatorContext;
   1290 
   1291 
   1292 /**
   1293  * Create "continue processing" action with optional chunk-extension.
   1294  * The data is provided in the buffer and/or in the zero-copy @a iov_data.
   1295  *
   1296  * If data is provided both in the buffer and @a ivo_data then
   1297  * data in the buffer sent first, following the iov data.
   1298  * The total size of the data in the buffer and in @a iov_data must
   1299  * be non-zero.
   1300  * If response content size is known and total size of content provided earlier
   1301  * for this request combined with the size provided by this action is larger
   1302  * then known response content size, then NULL is returned.
   1303  *
   1304  * At most one DCC action can be created for one content callback.
   1305  *
   1306  * @param[in,out] ctx the pointer the context as provided to the callback
   1307  * @param data_size the amount of the data placed to the provided buffer,
   1308  *                  cannot be larger than provided buffer size,
   1309  *                  must be non-zero if @a iov_data is NULL or has no data,
   1310  * @param iov_data the optional pointer to the iov data,
   1311  *                 must not be NULL and have non-zero size data if @a data_size
   1312  *                 is zero,
   1313  * @param chunk_ext the optional pointer to chunk extension string,
   1314  *                  can be NULL to not use chunk extension,
   1315  *                  ignored if chunked encoding is not used
   1316  * @return the pointer to the action if succeed,
   1317  *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
   1318  */
   1319 MHD_EXTERN_ const struct MHD_DynamicContentCreatorAction *
   1320 MHD_DCC_action_continue_zc (
   1321   struct MHD_DynamicContentCreatorContext *ctx,
   1322   size_t data_size,
   1323   const struct MHD_DynContentZCIoVec *iov_data,
   1324   const char *MHD_RESTRICT chunk_ext)
   1325 MHD_FN_PAR_NONNULL_ (1)
   1326 MHD_FN_PAR_CSTR_ (4);
   1327 
   1328 
   1329 /**
   1330  * Create "continue processing" action with optional chunk-extension.
   1331  * The data is provided in the buffer.
   1332  *
   1333  * At most one DCC action can be created for one content callback.
   1334  *
   1335  * @param[in,out] ctx the pointer the context as provided to the callback
   1336  * @param data_size the amount of the data placed to the provided buffer (not @a iov_data),
   1337  *                  cannot be larger than provided buffer size,
   1338  *                  must be non-zero.
   1339  * @param chunk_ext the optional pointer to chunk extension string,
   1340  *                  can be NULL to not use chunk extension,
   1341  *                  ignored if chunked encoding is not used
   1342  * @return the pointer to the action if succeed,
   1343  *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
   1344  */
   1345 #define MHD_DCC_action_continue_ce(ctx, data_size, chunk_ext) \
   1346         MHD_DCC_action_continue_zc ((ctx), (data_size), NULL, (chunk_ext))
   1347 
   1348 
   1349 /**
   1350  * Create "continue processing" action, the data is provided in the buffer.
   1351  *
   1352  * At most one DCC action can be created for one content callback.
   1353  *
   1354  * @param[in,out] ctx the pointer the context as provided to the callback
   1355  * @param data_size the amount of the data placed to the provided buffer;
   1356  *                  cannot be larger than provided buffer size,
   1357  *                  must be non-zero.
   1358  *
   1359  * @return the pointer to the action if succeed,
   1360  *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
   1361  */
   1362 #define MHD_DCC_action_continue(ctx, data_size) \
   1363         MHD_DCC_action_continue_ce ((ctx), (data_size), NULL)
   1364 
   1365 
   1366 /**
   1367  * Create "finished" action with optional footers.
   1368  * If function failed for any reason, the action is automatically
   1369  * set to "stop with error".
   1370  *
   1371  * At most one DCC action can be created for one content callback.
   1372  *
   1373  * @param[in,out] ctx the pointer the context as provided to the callback
   1374  * @param num_footers number of elements in the @a footers array,
   1375  *                    must be zero if @a footers is NULL
   1376  * @param footers the optional pointer to the array of the footers (the strings
   1377  *                are copied and does not need to be valid after return from
   1378  *                this function),
   1379  *                can be NULL if @a num_footers is zero
   1380  * @return the pointer to the action if succeed,
   1381  *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
   1382  */
   1383 MHD_EXTERN_ const struct MHD_DynamicContentCreatorAction *
   1384 MHD_DCC_action_finish_with_footer (
   1385   struct MHD_DynamicContentCreatorContext *ctx,
   1386   size_t num_footers,
   1387   const struct MHD_NameValueCStr *MHD_RESTRICT footers)
   1388 MHD_FN_PAR_NONNULL_ (1);
   1389 
   1390 
   1391 /**
   1392  * Create "finished" action.
   1393  * If function failed for any reason, the action is automatically
   1394  * set to "stop with error".
   1395  *
   1396  * At most one DCC action can be created for one content callback.
   1397  *
   1398  * @param[in,out] ctx the pointer the context as provided to the callback
   1399  * @return the pointer to the action if succeed,
   1400  *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
   1401  */
   1402 #define MHD_DCC_action_finish(ctx) \
   1403         MHD_DCC_action_finish_with_footer ((ctx), 0, NULL)
   1404 
   1405 
   1406 /**
   1407  * Create "suspend" action.
   1408  * If function failed for any reason, the action is automatically
   1409  * set to "stop with error".
   1410  *
   1411  * At most one DCC action can be created for one content callback.
   1412  *
   1413  * @param[in,out] ctx the pointer the context as provided to the callback
   1414  * @return the pointer to the action if succeed,
   1415  *         NULL (equivalent of MHD_DCC_action_abort())in case of any error
   1416  */
   1417 MHD_EXTERN_ const struct MHD_DynamicContentCreatorAction *
   1418 MHD_DCC_action_suspend (struct MHD_DynamicContentCreatorContext *ctx)
   1419 MHD_FN_PAR_NONNULL_ (1);
   1420 
   1421 /**
   1422  * Create "stop with error" action.
   1423  * @param[in,out] ctx the pointer the context as provided to the callback
   1424  * @return always NULL (the action "stop with error")
   1425  */
   1426 #define MHD_DCC_action_abort(ctx) \
   1427         MHD_STATIC_CAST_ (const struct MHD_DynamicContentCreatorAction *, NULL)
   1428 
   1429 /**
   1430  * Callback used by libmicrohttpd in order to obtain content.  The
   1431  * callback is to copy at most @a max bytes of content into @a buf or
   1432  * provide zero-copy data for #MHD_DCC_action_continue_zc().
   1433  *
   1434  * @param dyn_cont_cls closure argument to the callback
   1435  * @param ctx the context to produce the action to return,
   1436  *            the pointer is only valid until the callback returns
   1437  * @param pos position in the datastream to access;
   1438  *        note that if a `struct MHD_Response` object is re-used,
   1439  *        it is possible for the same content reader to
   1440  *        be queried multiple times for the same data;
   1441  *        however, if a `struct MHD_Response` is not re-used,
   1442  *        libmicrohttpd guarantees that "pos" will be
   1443  *        the sum of all data sizes provided by this callback
   1444  * @param[out] buf where to copy the data
   1445  * @param max maximum number of bytes to copy to @a buf (size of @a buf),
   1446               if the size of the content of the response is known then size
   1447               of the buffer is never larger than amount of the content left
   1448  * @return action to use,
   1449  *         NULL in case of any error (the response will be aborted)
   1450  */
   1451 typedef const struct MHD_DynamicContentCreatorAction *
   1452 (MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (4)
   1453  *MHD_DynamicContentCreator)(void *dyn_cont_cls,
   1454                              struct MHD_DynamicContentCreatorContext *ctx,
   1455                              uint_fast64_t pos,
   1456                              void *buf,
   1457                              size_t max);
   1458 
   1459 
   1460 /**
   1461  * Create a response.  The response object can be extended with
   1462  * header information.
   1463  *
   1464  * @param sc status code to return
   1465  * @param size size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown
   1466  * @param dyn_cont callback to use to obtain response data
   1467  * @param dyn_cont_cls extra argument to @p dyn_cont
   1468  * @param free_cb callback to call to free @p dyn_cont_cls resources,
   1469  *                can be NULL
   1470  * @param free_cb_cls the parameter for @p free_cb
   1471  * @return new response object on success,
   1472  *         NULL on failure (i.e. invalid arguments, out of memory),
   1473  *         @p free_cb is called automatically in case of failure
   1474  * @ingroup response
   1475  */
   1476 MHD_EXTERN_ struct MHD_Response *
   1477 MHD_response_from_callback_2cls (enum MHD_HTTP_StatusCode sc,
   1478                                  uint_fast64_t size,
   1479                                  MHD_DynamicContentCreator dyn_cont,
   1480                                  void *dyn_cont_cls,
   1481                                  MHD_FreeCallback free_cb,
   1482                                  void *free_cb_cls);
   1483 
   1484 
   1485 /**
   1486  * Create a response.  The response object can be extended with
   1487  * header information.
   1488  *
   1489  * @param sc status code to return
   1490  * @param s size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown
   1491  * @param d callback to use to obtain response data
   1492  * @param dc extra argument to @p d, evaluated twice!
   1493  * @param f callback to call to free @p dc resources
   1494  * @return new response object on success,
   1495  *         NULL on failure (i.e. invalid arguments, out of memory),
   1496  *         the cleanup callback @p f is called automatically in case
   1497  *         of failure
   1498  * @warning The @p dc parameter is evaluated twice; avoid expressions
   1499  *          with side effects. Alternatively, just call function
   1500  *          #MHD_response_from_callback_2cls() directly.
   1501  * @ingroup response
   1502  */
   1503 #define MHD_response_from_callback(sc, s, d, dc, f) \
   1504         MHD_response_from_callback_2cls((sc),(s),(d),(dc),(f),(dc))
   1505 
   1506 
   1507 /**
   1508  * Create a response object.  The response object can be extended with
   1509  * header information.
   1510  *
   1511  * @param sc status code to use for the response;
   1512  *           #MHD_HTTP_STATUS_NO_CONTENT is only valid if @a size is 0;
   1513  * @param buffer_size the size of the data portion of the response
   1514  * @param buffer the @a size bytes containing the response's data portion,
   1515  *               needs to be valid while the response is used
   1516  * @param free_cb the callback to free any allocated data, called
   1517  *                when response is being destroyed, can be NULL
   1518  *                to skip the free/cleanup callback;
   1519  * @param free_cb_cls the parameter for @a free_cb
   1520  * @return new response object on success,
   1521  *         NULL on failure (i.e. invalid arguments, out of memory),
   1522  *         @p free_cb is called automatically in case of failure
   1523  * @ingroup response
   1524  */
   1525 MHD_EXTERN_ struct MHD_Response *
   1526 MHD_response_from_buffer (
   1527   enum MHD_HTTP_StatusCode sc,
   1528   size_t buffer_size,
   1529   const char *buffer,
   1530   MHD_FreeCallback free_cb,
   1531   void *free_cb_cls)
   1532 MHD_FN_PAR_IN_SIZE_ (3, 2);
   1533 
   1534 
   1535 /**
   1536  * Create a response object with body that is a
   1537  * statically allocated buffer that never needs to
   1538  * be freed as its lifetime exceeds that of the
   1539  * daemon.
   1540  *
   1541  * The response object can be extended with header information and then be used
   1542  * any number of times.
   1543  * @param sc status code to use for the response
   1544  * @param len number of bytes in @a buf
   1545  * @param buf buffer with response payload
   1546  * @return new response object on success,
   1547  *         NULL on failure (i.e. invalid arguments, out of memory)
   1548  */
   1549 #define MHD_response_from_buffer_static(sc, len, buf)       \
   1550         MHD_response_from_buffer (sc, len, buf, NULL, NULL)
   1551 
   1552 
   1553 /**
   1554  * Create a response object with empty (zero size) body.
   1555  *
   1556  * The response object can be extended with header information and then be used
   1557  * any number of times.
   1558  * @param sc status code to use for the response
   1559  * @return new response object on success,
   1560  *         NULL on failure (i.e. invalid arguments, out of memory)
   1561  */
   1562 #define MHD_response_from_empty(sc) \
   1563         MHD_response_from_buffer_static (sc, 0, "")
   1564 
   1565 
   1566 /**
   1567  * Create a response object.  The response object can be extended with
   1568  * header information.
   1569  *
   1570  * @param sc status code to use for the response
   1571  * @param buffer_size the size of the data portion of the response
   1572  * @param buffer the @a size bytes containing the response's data portion,
   1573  *               an internal copy will be made, there is no need to
   1574  *               keep this data after return from this function
   1575  * @return new response object on success,
   1576  *         NULL on failure (i.e. invalid arguments, out of memory)
   1577  * @ingroup response
   1578  */
   1579 MHD_EXTERN_ struct MHD_Response *
   1580 MHD_response_from_buffer_copy (
   1581   enum MHD_HTTP_StatusCode sc,
   1582   size_t buffer_size,
   1583   const char buffer[MHD_FN_PAR_DYN_ARR_SIZE_ (buffer_size)])
   1584 MHD_FN_PAR_IN_SIZE_ (3, 2);
   1585 
   1586 
   1587 /**
   1588  * I/O vector type. Provided for use with #MHD_response_from_iovec().
   1589  * @ingroup response
   1590  */
   1591 struct MHD_IoVec
   1592 {
   1593   /**
   1594    * The pointer to the memory region for I/O.
   1595    */
   1596   const void *iov_base;
   1597 
   1598   /**
   1599    * The size in bytes of the memory region for I/O.
   1600    */
   1601   size_t iov_len;
   1602 };
   1603 
   1604 
   1605 /**
   1606  * Create a response object with an array of memory buffers
   1607  * used as the response body.
   1608  *
   1609  * The response object can be extended with header information.
   1610  *
   1611  * If response object is used to answer HEAD request then the body
   1612  * of the response is not used, while all headers (including automatic
   1613  * headers) are used.
   1614  *
   1615  * @param sc status code to use for the response
   1616  * @param iov_count the number of elements in @a iov
   1617  * @param iov the array for response data buffers, an internal copy of this
   1618  *        will be made
   1619  * @param free_cb the callback to clean up any data associated with @a iov when
   1620  *        the response is destroyed.
   1621  * @param free_cb_cls the argument passed to @a free_cb
   1622  * @return new response object on success,
   1623  *         NULL on failure (i.e. invalid arguments, out of memory),
   1624  *         @p free_cb is called automatically in case of failure
   1625  * @ingroup response
   1626  */
   1627 MHD_EXTERN_ struct MHD_Response *
   1628 MHD_response_from_iovec (
   1629   enum MHD_HTTP_StatusCode sc,
   1630   unsigned int iov_count,
   1631   const struct MHD_IoVec iov[MHD_FN_PAR_DYN_ARR_SIZE_ (iov_count)],
   1632   MHD_FreeCallback free_cb,
   1633   void *free_cb_cls);
   1634 
   1635 
   1636 /**
   1637  * Create a response object based on an @a fd from which
   1638  * data is read.  The response object can be extended with
   1639  * header information.
   1640  *
   1641  * @param sc status code to return
   1642  * @param fd file descriptor referring to a file on disk with the
   1643  *           data; will be closed when response is destroyed;
   1644  *           fd should be in 'blocking' mode
   1645  * @param offset offset to start reading from in the file,
   1646  *               must not be #MHD_SIZE_UNKNOWN;
   1647  *               reading file beyond 2 GiB may be not supported by OS or
   1648  *               MHD build; see #MHD_LIB_INFO_FIXED_HAS_LARGE_FILE
   1649  * @param size size of the data portion of the response,
   1650  *             #MHD_SIZE_UNKNOWN to send the file to its end; with the
   1651  *             unknown size and @p offset beyond the end of the file the
   1652  *             body is empty;
   1653  *             sizes larger than 2 GiB may be not supported by OS or
   1654  *             MHD build; see #MHD_LIB_INFO_FIXED_HAS_LARGE_FILE
   1655  * @return new response object on success,
   1656  *         NULL on failure (i.e. invalid arguments, out of memory),
   1657  *         @p fd is closed automatically in case of failure
   1658  * @ingroup response
   1659  */
   1660 MHD_EXTERN_ struct MHD_Response *
   1661 MHD_response_from_fd (enum MHD_HTTP_StatusCode sc,
   1662                       int fd,
   1663                       uint_fast64_t offset,
   1664                       uint_fast64_t size)
   1665 MHD_FN_PAR_FD_READ_ (2);
   1666 
   1667 /**
   1668  * Create a response object with the response body created by reading
   1669  * the provided pipe.
   1670  *
   1671  * The response object can be extended with header information and
   1672  * then be used ONLY ONCE.
   1673  *
   1674  * If response object is used to answer HEAD request then the body
   1675  * of the response is not used, while all headers (including automatic
   1676  * headers) are used.
   1677  *
   1678  * @param sc status code to use for the response
   1679  * @param fd file descriptor referring to a read-end of a pipe with the
   1680  *        data; will be closed when response is destroyed;
   1681  *        fd should be in 'blocking' mode
   1682  * @return new response object on success,
   1683  *         NULL on failure (i.e. invalid arguments, out of memory),
   1684  *         @p fd is closed automatically in case of failure
   1685  * @ingroup response
   1686  */
   1687 MHD_EXTERN_ struct MHD_Response *
   1688 MHD_response_from_pipe (enum MHD_HTTP_StatusCode sc,
   1689                         int fd)
   1690 MHD_FN_PAR_FD_READ_ (2);
   1691 
   1692 
   1693 /**
   1694  * Destroy response.
   1695  * Should be called if response was created but not consumed.
   1696  * Also must be called if response has #MHD_R_O_REUSABLE set.
   1697  * The actual destroy can be happen later, if the response
   1698  * is still being used in any request.
   1699  * The function does not block.
   1700  *
   1701  * @param[in] response the response to destroy
   1702  * @ingroup response
   1703  */
   1704 MHD_EXTERN_ void
   1705 MHD_response_destroy (struct MHD_Response *response)
   1706 MHD_FN_PAR_NONNULL_ (1);
   1707 
   1708 
   1709 /**
   1710  * Add a header line to the response.
   1711  *
   1712  * @param response response to add a header to, NULL is tolerated
   1713  * @param name the name of the header to add,
   1714  *             an internal copy of the string will be made
   1715  * @param value the value of the header to add,
   1716  *              an internal copy of the string will be made
   1717  * @return #MHD_SC_OK on success,
   1718  *         error code otherwise
   1719  * @ingroup response
   1720  */
   1721 MHD_EXTERN_ enum MHD_StatusCode
   1722 MHD_response_add_header (struct MHD_Response *MHD_RESTRICT response,
   1723                          const char *MHD_RESTRICT name,
   1724                          const char *MHD_RESTRICT value)
   1725 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
   1726 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_CSTR_ (3);
   1727 
   1728 
   1729 /**
   1730  * Add a header with predefined (standard) name to the response.
   1731  *
   1732  * @param response response to add a header to
   1733  * @param stk the code of the predefined header
   1734  * @param content the value of the header to add,
   1735  *              an internal copy of the string will be made
   1736  * @return #MHD_SC_OK on success,
   1737  *         error code otherwise
   1738  * @ingroup response
   1739  */
   1740 MHD_EXTERN_ enum MHD_StatusCode
   1741 MHD_response_add_predef_header (struct MHD_Response *MHD_RESTRICT response,
   1742                                 enum MHD_PredefinedHeader stk,
   1743                                 const char *MHD_RESTRICT content)
   1744 MHD_FN_PAR_NONNULL_ (1)
   1745 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_CSTR_ (3);
   1746 
   1747 
   1748 /* ************ (b) Upload and PostProcessor functions ********************** */
   1749 
   1750 
   1751 /**
   1752  * Suspend handling of network data for a given request.  This can
   1753  * be used to dequeue a request from MHD's event loop for a while.
   1754  *
   1755  * Suspended requests continue to count against the total number of
   1756  * requests allowed (per daemon, as well as per IP, if such limits
   1757  * are set).  Suspended requests will NOT time out; timeouts will
   1758  * restart when the request handling is resumed.  While a
   1759  * request is suspended, MHD may not detect disconnects by the
   1760  * client.
   1761  *
   1762  * At most one upload action can be created for one upload callback.
   1763  *
   1764  * @param[in,out] request the request for which the action is generated
   1765  * @return action to cause a request to be suspended,
   1766  *         NULL if any action has been already created for the @a request
   1767  * @ingroup action
   1768  */
   1769 MHD_EXTERN_ const struct MHD_UploadAction *
   1770 MHD_upload_action_suspend (struct MHD_Request *request)
   1771 MHD_FN_PAR_NONNULL_ALL_;
   1772 
   1773 /**
   1774  * Converts a @a response to an action.  If #MHD_R_O_REUSABLE
   1775  * is not set, the reference to the @a response is consumed
   1776  * by the conversion. If #MHD_R_O_REUSABLE is #MHD_YES,
   1777  * then the @a response can be used again to create actions in
   1778  * the future.
   1779  * However, the @a response is frozen by this step and
   1780  * must no longer be modified (i.e. by setting headers).
   1781  *
   1782  * At most one upload action can be created for one upload callback.
   1783  *
   1784  * @param request the request to create the action for
   1785  * @param[in] response the response to convert,
   1786  *                     if NULL then this function is equivalent to
   1787  *                     #MHD_upload_action_abort_request() call
   1788  * @return pointer to the action, the action must be consumed
   1789  *         otherwise response object may leak;
   1790  *         NULL if failed (no memory) or if any action has been already
   1791  *         created for the @a request;
   1792  *         when failed the response object is consumed and need not
   1793  *         to be "destroyed"
   1794  * @ingroup action
   1795  */
   1796 MHD_EXTERN_ const struct MHD_UploadAction *
   1797 MHD_upload_action_from_response (struct MHD_Request *MHD_RESTRICT request,
   1798                                  struct MHD_Response *MHD_RESTRICT response)
   1799 MHD_FN_PAR_NONNULL_ (1);
   1800 
   1801 /**
   1802  * Action telling MHD to continue processing the upload.
   1803  * Valid only for incremental upload processing.
   1804  * Works as #MHD_upload_action_abort_request() if used for full upload callback
   1805  * or for the final (with zero data) incremental callback.
   1806  *
   1807  * At most one upload action can be created for one upload callback.
   1808  *
   1809  * @param request the request to make an action
   1810  * @return action operation,
   1811  *         NULL if any action has been already created for the @a request
   1812  * @ingroup action
   1813  */
   1814 MHD_EXTERN_ const struct MHD_UploadAction *
   1815 MHD_upload_action_continue (struct MHD_Request *request)
   1816 MHD_FN_PAR_NONNULL_ (1);
   1817 
   1818 
   1819 /**
   1820  * Action telling MHD to close the connection hard
   1821  * (kind-of breaking HTTP specification).
   1822  *
   1823  * @param req the request to make an action
   1824  * @return action operation, always NULL
   1825  * @ingroup action
   1826  */
   1827 #define MHD_upload_action_abort_request(req) \
   1828         MHD_STATIC_CAST_ (const struct MHD_UploadAction *, NULL)
   1829 
   1830 #ifndef MHD_UPLOADCALLBACK_DEFINED
   1831 
   1832 /**
   1833  * Function to process data uploaded by a client.
   1834  *
   1835  * @param upload_cls the argument given together with the function
   1836  *                   pointer when the handler was registered with MHD
   1837  * @param request the request is being processed
   1838  * @param content_data_size the size of the @a content_data,
   1839  *                          zero when all data have been processed
   1840  * @param[in] content_data the uploaded content data,
   1841  *                         may be modified in the callback,
   1842  *                         valid only until return from the callback,
   1843  *                         NULL when all data have been processed
   1844  * @return action specifying how to proceed:
   1845  *         #MHD_upload_action_continue() to continue upload (for incremental
   1846  *         upload processing only),
   1847  *         #MHD_upload_action_suspend() to stop reading the upload until
   1848  *         the request is resumed,
   1849  *         #MHD_upload_action_abort_request() to close the socket,
   1850  *         or a response to discard the rest of the upload and transmit
   1851  *         the response
   1852  * @ingroup action
   1853  */
   1854 typedef const struct MHD_UploadAction *
   1855 (MHD_FN_PAR_NONNULL_ (2)  MHD_FN_PAR_INOUT_SIZE_ (4, 3)
   1856  *MHD_UploadCallback)(void *upload_cls,
   1857                       struct MHD_Request *request,
   1858                       size_t content_data_size,
   1859                       void *content_data);
   1860 
   1861 #  define MHD_UPLOADCALLBACK_DEFINED 1
   1862 #endif /* ! MHD_UPLOADCALLBACK_DEFINED */
   1863 
   1864 /**
   1865  * Create an action that handles an upload.
   1866  *
   1867  * If @a uc_inc is NULL and upload cannot fit the allocated buffer
   1868  * then request is aborted without response.
   1869  *
   1870  * At most one action can be created for any request.
   1871  *
   1872  * @param request the request to create action for
   1873  * @param large_buffer_size how large should the upload buffer be.
   1874  *                          May allocate memory from the shared "large"
   1875  *                          memory pool if necessary and non-zero is given.
   1876  *                          Must be zero if @a uc_full is NULL.
   1877  * @param uc_full the function to call when complete upload
   1878  *                is received (only if fit @a upload_buffer_size),
   1879  *                can be NULL if uc_inc is not NULL,
   1880  *                must be NULL is @a upload_buffer_size is zero.
   1881  * @param uc_full_cls closure for @a uc_full
   1882  * @param uc_inc the function to incrementally process the upload data
   1883  *               if the upload if larger than @a upload_buffer_size or
   1884  *               @a upload_buffer_size cannot be allocated or
   1885  *               @a uc_full is NULL,
   1886  *               can be NULL if uc_full is not NULL
   1887  * @param uc_inc_cls closure for @a uc_inc
   1888  * @return NULL on error (out of memory, invalid parameters)
   1889  * @return pointer to the action,
   1890  *         NULL if failed (no memory) or if any action has been already
   1891  *         created for the @a request.
   1892  * @sa #MHD_D_OPTION_LARGE_POOL_SIZE()
   1893  * @ingroup action
   1894  */
   1895 MHD_EXTERN_ const struct MHD_Action *
   1896 MHD_action_process_upload (
   1897   struct MHD_Request *request,
   1898   size_t large_buffer_size,
   1899   MHD_UploadCallback uc_full,
   1900   void *uc_full_cls,
   1901   MHD_UploadCallback uc_inc,
   1902   void *uc_inc_cls)
   1903 MHD_FN_PAR_NONNULL_ (1);
   1904 
   1905 /**
   1906  * Create an action that handles an upload as full upload data.
   1907  *
   1908  * @param request the request to create action for
   1909  * @param buff_size how large should the upload buffer be. May allocate memory
   1910  *                  from the large memory pool if necessary. Must not be zero.
   1911  * @param uc the function to call when complete upload
   1912  *           is received (only if fit @a upload_buffer_size)
   1913  * @param uc_cls closure for @a uc
   1914  * @return NULL on error (out of memory. both @a uc is NULL)
   1915  * @ingroup action
   1916  */
   1917 #define MHD_action_process_upload_full(request, buff_size, uc, uc_cls) \
   1918         MHD_action_process_upload (request, buff_size, uc, uc_cls, NULL, NULL)
   1919 
   1920 /**
   1921  * Create an action that handles an upload incrementally.
   1922  *
   1923  * @param request the request to create action for
   1924  * @param uc the function to incrementally process the upload data
   1925  * @param uc_cls closure for @a uc
   1926  * @return NULL on error (out of memory. both @a uc is NULL)
   1927  * @ingroup action
   1928  */
   1929 #define MHD_action_process_upload_inc(request, uc, uc_cls) \
   1930         MHD_action_process_upload (request, 0, NULL, NULL, uc, uc_cls)
   1931 
   1932 #ifndef MHD_POST_PARSE_RESULT_DEFINED
   1933 
   1934 /**
   1935  * The result of POST data parsing
   1936  */
   1937 enum MHD_FIXED_ENUM_MHD_SET_ MHD_PostParseResult
   1938 {
   1939   /**
   1940    * The POST data parsed successfully and completely.
   1941    */
   1942   MHD_POST_PARSE_RES_OK = 0
   1943   ,
   1944   /**
   1945    * The POST request has no content or zero-length content.
   1946    */
   1947   MHD_POST_PARSE_RES_REQUEST_EMPTY = 1
   1948   ,
   1949   /**
   1950    * The POST data parsed successfully, but has missing or incorrect
   1951    * termination.
   1952    * The last parsed field may have incorrect data.
   1953    */
   1954   MHD_POST_PARSE_RES_OK_BAD_TERMINATION = 2
   1955   ,
   1956   /**
   1957    * Parsing of the POST data is incomplete because client used incorrect
   1958    * format of POST encoding.
   1959    * The last parsed field may have incorrect data.
   1960    * Some POST data is available or has been provided via callback.
   1961    */
   1962   MHD_POST_PARSE_RES_PARTIAL_INVALID_POST_FORMAT = 3
   1963   ,
   1964   /**
   1965    * The POST data cannot be parsed completely because the stream has
   1966    * no free pool memory.
   1967    * Some POST data may be parsed.
   1968    */
   1969   MHD_POST_PARSE_RES_FAILED_NO_POOL_MEM = 60
   1970   ,
   1971   /**
   1972    * The POST data cannot be parsed completely because no "large shared buffer"
   1973    * space is available.
   1974    * Some POST data may be parsed.
   1975    */
   1976   MHD_POST_PARSE_RES_FAILED_NO_LARGE_BUF_MEM = 61
   1977   ,
   1978   /**
   1979    * The POST data cannot be parsed because 'Content-Type:' is unknown.
   1980    */
   1981   MHD_POST_PARSE_RES_FAILED_UNKNOWN_CNTN_TYPE = 80
   1982   ,
   1983   /**
   1984    * The POST data cannot be parsed because 'Content-Type:' header is not set.
   1985    */
   1986   MHD_POST_PARSE_RES_FAILED_NO_CNTN_TYPE = 81
   1987   ,
   1988   /**
   1989    * The POST data cannot be parsed because "Content-Type:" request header has
   1990    * no "boundary" parameter for "multipart/form-data"
   1991    */
   1992   MHD_POST_PARSE_RES_FAILED_HEADER_NO_BOUNDARY = 82
   1993   ,
   1994   /**
   1995    * The POST data cannot be parsed because "Content-Type: multipart/form-data"
   1996    * request header is misformed
   1997    */
   1998   MHD_POST_PARSE_RES_FAILED_HEADER_MISFORMED = 83
   1999   ,
   2000   /**
   2001    * The application set POST encoding to "multipart/form-data", but the request
   2002    * has no "Content-Type: multipart/form-data" header which is required
   2003    * to find "boundary" used in this encoding
   2004    */
   2005   MHD_POST_PARSE_RES_FAILED_HEADER_NOT_MPART = 84
   2006   ,
   2007   /**
   2008    * The POST data cannot be parsed because client used incorrect format
   2009    * of POST encoding.
   2010    */
   2011   MHD_POST_PARSE_RES_FAILED_INVALID_POST_FORMAT = 90
   2012 
   2013 };
   2014 
   2015 #  define MHD_POST_PARSE_RESULT_DEFINED 1
   2016 #endif /* ! MHD_POST_PARSE_RESULT_DEFINED */
   2017 
   2018 #ifndef MHD_POST_DATA_READER_DEFINED
   2019 
   2020 /**
   2021  * "Stream" reader for POST data.
   2022  * This callback is called to incrementally process parsed POST data sent by
   2023  * the client.
   2024  * The pointers to the MHD_String and MHD_StringNullable are valid only until
   2025  * return from this callback.
   2026  * The pointers to the strings and the @a data are valid only until return from
   2027  * this callback.
   2028  *
   2029  * @param req the request
   2030  * @param cls user-specified closure
   2031  * @param name the name of the POST field
   2032  * @param filename the name of the uploaded file, @a cstr member is NULL if not
   2033  *                 known / not provided
   2034  * @param content_type the mime-type of the data, cstr member is NULL if not
   2035  *                     known / not provided
   2036  * @param encoding the encoding of the data, cstr member is NULL if not known /
   2037  *                 not provided
   2038  * @param size the number of bytes in @a data available, may be zero if
   2039  *             the @a final_data is #MHD_YES
   2040  * @param data the pointer to @a size bytes of data at the specified
   2041  *             @a off offset, NOT zero-terminated
   2042  * @param off the offset of @a data in the overall value, always equal to
   2043  *            the sum of sizes of previous calls for the same field / file;
   2044  *            client may provide more than one field with the same name and
   2045  *            the same filename, the new filed (or file) is indicated by zero
   2046  *            value of @a off (and the end is indicated by @a final_data)
   2047  * @param final_data if set to #MHD_YES then full field data is provided,
   2048  *                   if set to #MHD_NO then more field data may be provided
   2049  * @return action specifying how to proceed:
   2050  *         #MHD_upload_action_continue() if all is well,
   2051  *         #MHD_upload_action_suspend() to stop reading the upload until
   2052  *         the request is resumed,
   2053  *         #MHD_upload_action_abort_request() to close the socket,
   2054  *         or a response to discard the rest of the upload and transmit
   2055  *         the response
   2056  * @ingroup action
   2057  */
   2058 typedef const struct MHD_UploadAction *
   2059 (MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_NONNULL_ (4)
   2060  MHD_FN_PAR_NONNULL_ (5) MHD_FN_PAR_NONNULL_ (6)
   2061  *MHD_PostDataReader) (struct MHD_Request *req,
   2062                        void *cls,
   2063                        const struct MHD_String *name,
   2064                        const struct MHD_StringNullable *filename,
   2065                        const struct MHD_StringNullable *content_type,
   2066                        const struct MHD_StringNullable *encoding,
   2067                        size_t size,
   2068                        const void *data,
   2069                        uint_fast64_t off,
   2070                        enum MHD_Bool final_data);
   2071 
   2072 
   2073 /**
   2074  * The callback to be called when finished with processing
   2075  * of the postprocessor upload data.
   2076  * @param req the request
   2077  * @param cls the closure
   2078  * @param parsing_result the result of POST data parsing
   2079  * @return the action to proceed
   2080  */
   2081 typedef const struct MHD_UploadAction *
   2082 (MHD_FN_PAR_NONNULL_ (1)
   2083  *MHD_PostDataFinished) (struct MHD_Request *req,
   2084                          void *cls,
   2085                          enum MHD_PostParseResult parsing_result);
   2086 
   2087 #  define MHD_POST_DATA_READER_DEFINED 1
   2088 #endif /* ! MHD_POST_DATA_READER_DEFINED */
   2089 
   2090 /**
   2091  * Create an action to parse the POSTed content from the client.
   2092  *
   2093  * The action starts parsing of the POST data. Any value that does not fit
   2094  * @a buffer_size or larger that @a auto_stream_size is given to
   2095  * @a stream_reader (if it is not NULL).
   2096  *
   2097  * If @a buffer_size is zero, then buffers will be limited to the connection's
   2098  * memory pool. To force all POST data process via @a stream_reader
   2099  * set @a auto_stream_size to zero.
   2100  *
   2101  * At most one action can be created for any request.
   2102  *
   2103  * @param request the request to create action for
   2104  * @param buffer_size the maximum size allowed for the buffers to parse this
   2105  *                    request POST data. Within the set limit the buffer is
   2106  *                    allocated automatically from the "large" shared memory
   2107  *                    pool if necessary.
   2108  * @param max_nonstream_size the size of the field (in encoded form) above which
   2109  *                           values are not buffered and provided for
   2110  *                           the @a steam_reader automatically;
   2111  *                           useful to have large data (like file uploads)
   2112  *                           processed incrementally, while keeping buffer space
   2113  *                           for small fields only;
   2114  *                           ignored if @a stream_reader is NULL
   2115  * @param enc the data encoding to use,
   2116  *            use #MHD_HTTP_POST_ENCODING_OTHER to detect automatically
   2117  * @param stream_reader the function to call for "oversize" values in
   2118  *                      the stream; can be NULL if @a auto_stream_size is
   2119  *                      not zero
   2120  * @param reader_cls the closure for the @a stream_reader
   2121  * @param done_cb called once all data has been processed for
   2122  *   the final action; values smaller than @a auto_stream_size that
   2123  *   fit into @a buffer_size will be available via
   2124  *   #MHD_request_get_values_cb(), #MHD_request_get_values_list() and
   2125  *   #MHD_request_get_post_data_cb(), #MHD_request_get_post_data_list()
   2126  * @param done_cb_cls the closure for the @a done_cb
   2127  * @return pointer to the action,
   2128  *         NULL if failed (no memory) or if any action has been already
   2129  *         created for the @a request.
   2130  * @sa #MHD_D_OPTION_LARGE_POOL_SIZE()
   2131  * @ingroup action
   2132  */
   2133 MHD_EXTERN_ const struct MHD_Action *
   2134 MHD_action_parse_post (struct MHD_Request *request,
   2135                        size_t buffer_size,
   2136                        size_t max_nonstream_size,
   2137                        enum MHD_HTTP_PostEncoding enc,
   2138                        MHD_PostDataReader stream_reader,
   2139                        void *reader_cls,
   2140                        MHD_PostDataFinished done_cb,
   2141                        void *done_cb_cls)
   2142 MHD_FN_PAR_NONNULL_ (1);
   2143 
   2144 
   2145 #ifndef MHD_POSTFILED_DEFINED
   2146 
   2147 /**
   2148  * Post data element.
   2149  * If any member is not provided/set then pointer to C string is NULL.
   2150  * If any member is set to empty string then pointer to C string not NULL,
   2151  * but the length is zero.
   2152  */
   2153 struct MHD_PostField
   2154 {
   2155   /**
   2156    * The name of the field
   2157    */
   2158   struct MHD_String name;
   2159   /**
   2160    * The field data
   2161    * If not set or defined then to C string is NULL.
   2162    * If set to empty string then pointer to C string not NULL,
   2163    * but the length is zero.
   2164    */
   2165   struct MHD_StringNullable value;
   2166   /**
   2167    * The filename if provided (only for "multipart/form-data")
   2168    * If not set or defined then to C string is NULL.
   2169    * If set to empty string then pointer to C string not NULL,
   2170    * but the length is zero.
   2171    */
   2172   struct MHD_StringNullable filename;
   2173   /**
   2174    * The Content-Type if provided (only for "multipart/form-data")
   2175    * If not set or defined then to C string is NULL.
   2176    * If set to empty string then pointer to C string not NULL,
   2177    * but the length is zero.
   2178    */
   2179   struct MHD_StringNullable content_type;
   2180   /**
   2181    * The Transfer-Encoding if provided (only for "multipart/form-data")
   2182    * If not set or defined then to C string is NULL.
   2183    * If set to empty string then pointer to C string not NULL,
   2184    * but the length is zero.
   2185    */
   2186   struct MHD_StringNullable transfer_encoding;
   2187 };
   2188 
   2189 #  define MHD_POSTFILED_DEFINED 1
   2190 #endif /* ! MHD_POSTFILED_DEFINED */
   2191 
   2192 
   2193 /**
   2194  * Iterator over POST data.
   2195  *
   2196  * The @a data pointer is valid only until return from this function.
   2197  *
   2198  * The pointers to the strings in @a data are valid until any MHD_UploadAction
   2199  * is provided. If the data is needed beyond this point, it should be copied.
   2200  *
   2201  * @param cls closure
   2202  * @param data the element of the post data, the pointer is valid only until
   2203  *             return from this function
   2204  * @return #MHD_YES to continue iterating,
   2205  *         #MHD_NO to abort the iteration
   2206  * @ingroup request
   2207  */
   2208 typedef enum MHD_Bool
   2209 (MHD_FN_PAR_NONNULL_ (2)
   2210  *MHD_PostDataIterator)(void *cls,
   2211                         const struct MHD_PostField *data);
   2212 
   2213 /**
   2214  * Get all of the post data from the request via request.
   2215  *
   2216  * @param request the request to get data for
   2217  * @param iterator callback to call on each header;
   2218  *        maybe NULL (then just count headers)
   2219  * @param iterator_cls extra argument to @a iterator
   2220  * @return number of entries iterated over
   2221  * @ingroup request
   2222  */
   2223 MHD_EXTERN_ size_t
   2224 MHD_request_get_post_data_cb (struct MHD_Request *request,
   2225                               MHD_PostDataIterator iterator,
   2226                               void *iterator_cls)
   2227 MHD_FN_PAR_NONNULL_ (1);
   2228 
   2229 /**
   2230  * Get all of the post data from the request.
   2231  *
   2232  * The pointers to the strings in @a elements are valid until any
   2233  * MHD_UploadAction is provided. If the data is needed beyond this point,
   2234  * it should be copied.
   2235  * @param request the request to get data for
   2236  * @param num_elements the number of elements in @a elements array
   2237  * @param[out] elements the array of @a num_elements to get the data
   2238  * @return the number of elements stored in @a elements,
   2239  *         zero if no data or postprocessor was not used.
   2240  * @ingroup request
   2241  */
   2242 MHD_EXTERN_ size_t
   2243 MHD_request_get_post_data_list (
   2244   struct MHD_Request *request,
   2245   size_t num_elements,
   2246   struct MHD_PostField elements[MHD_FN_PAR_DYN_ARR_SIZE_ (num_elements)])
   2247 MHD_FN_PAR_NONNULL_ (1)
   2248 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_SIZE_ (3, 2);
   2249 
   2250 /* ***************** (c) WebSocket support ********** */
   2251 
   2252 /**
   2253  * Handle given to the application to manage special
   2254  * actions relating to MHD responses that "upgrade"
   2255  * the HTTP protocol (i.e. to WebSockets).
   2256  */
   2257 struct MHD_UpgradedHandle;
   2258 
   2259 
   2260 #ifndef MHD_UPGRADEHANDLER_DEFINED
   2261 
   2262 /**
   2263  * Function called after a protocol "upgrade" response was sent successfully
   2264  * and the connection is being switched to other protocol.
   2265  *
   2266  * The newly provided handle @a urh can be used to send and receive the data
   2267  * by #MHD_upgraded_send() and #MHD_upgraded_recv(). The handle must be closed
   2268  * by #MHD_upgraded_close() before destroying the daemon.
   2269  *
   2270  * "Upgraded" connection will not time out, but still counted for daemon
   2271  * global connections limit and for per-IP limit (if set).
   2272  *
   2273  * Except when in 'thread-per-connection' mode, implementations
   2274  * of this function should never block (as it will still be called
   2275  * from within the main event loop).
   2276  *
   2277  * @param cls closure, whatever was given to #MHD_action_upgrade().
   2278  * @param request original HTTP request handle,
   2279  *                giving the function a last chance
   2280  *                to inspect the original HTTP request
   2281  * @param urh argument for #MHD_upgrade_operation() on this @a response.
   2282  *        Applications must eventually use this callback to (indirectly)
   2283  *        perform the close() action on the @a sock.
   2284  */
   2285 typedef void
   2286 (MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (3)
   2287  *MHD_UpgradeHandler)(void *cls,
   2288                       struct MHD_Request *MHD_RESTRICT request,
   2289                       struct MHD_UpgradedHandle *MHD_RESTRICT urh);
   2290 
   2291 #  define MHD_UPGRADEHANDLER_DEFINED 1
   2292 #endif /* ! MHD_UPGRADEHANDLER_DEFINED */
   2293 
   2294 
   2295 /**
   2296  * Create a action object that can be used for 101 Upgrade
   2297  * responses, for example to implement WebSockets.  After sending the
   2298  * response, control over the data stream is given to the callback (which
   2299  * can then, for example, start some bi-directional communication).
   2300  * The callback will ONLY be called after the response header was successfully
   2301  * passed to the OS; if there are communication errors before, the usual MHD
   2302  * connection error handling code will be performed.
   2303  *
   2304  * At most one action can be created for any request.
   2305  *
   2306  * @param request the request to create action for
   2307  * @param upgrade_hdr_value the value of the "Upgrade:" header, mandatory
   2308                             string
   2309  * @param upgrade_handler function to call with the "upgraded" socket
   2310  * @param upgrade_handler_cls closure for @a upgrade_handler
   2311  * @param num_headers number of elements in the @a headers array,
   2312  *                    must be zero if @a headers is NULL
   2313  * @param headers the optional pointer to the array of the headers (the strings
   2314  *                are copied and does not need to be valid after return from
   2315  *                this function),
   2316  *                can be NULL if @a num_headers is zero
   2317  * @return NULL on error (i.e. invalid arguments, out of memory)
   2318  * @ingroup action
   2319  */
   2320 MHD_EXTERN_ const struct MHD_Action *
   2321 MHD_action_upgrade (struct MHD_Request *MHD_RESTRICT request,
   2322                     const char *MHD_RESTRICT upgrade_hdr_value,
   2323                     MHD_UpgradeHandler upgrade_handler,
   2324                     void *upgrade_handler_cls,
   2325                     size_t num_headers,
   2326                     const struct MHD_NameValueCStr *MHD_RESTRICT headers)
   2327 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
   2328 MHD_FN_PAR_IN_SIZE_ (6, 5);
   2329 
   2330 
   2331 /**
   2332  * Create a action object that can be used for 101 Upgrade
   2333  * responses, for example to implement WebSockets.  After sending the
   2334  * response, control over the data stream is given to the callback (which
   2335  * can then, for example, start some bi-directional communication).
   2336  * The callback will ONLY be called after the response header was successfully
   2337  * passed to the OS; if there are communication errors before, the usual MHD
   2338  * connection error handling code will be performed.
   2339  *
   2340  * At most one action can be created for any request.
   2341  *
   2342  * @param request the request to create action for
   2343  * @param upgrade_hdr_value the value of the "Upgrade:" header, mandatory
   2344                             string
   2345  * @param upgrade_handler function to call with the "upgraded" socket
   2346  * @param upgrade_handler_cls closure for @a upgrade_handler
   2347  * @param num_headers number of elements in the @a headers array,
   2348  *                    must be zero if @a headers is NULL
   2349  * @param headers the optional pointer to the array of the headers (the strings
   2350  *                are copied and does not need to be valid after return from
   2351  *                this function),
   2352  *                can be NULL if @a num_headers is zero
   2353  * @return NULL on error (i.e. invalid arguments, out of memory)
   2354  * @ingroup action
   2355  */
   2356 MHD_EXTERN_ const struct MHD_UploadAction *
   2357 MHD_upload_action_upgrade (
   2358   struct MHD_Request *MHD_RESTRICT request,
   2359   const char *MHD_RESTRICT upgrade_hdr_value,
   2360   MHD_UpgradeHandler upgrade_handler,
   2361   void *upgrade_handler_cls,
   2362   size_t num_headers,
   2363   const struct MHD_NameValueCStr *MHD_RESTRICT headers)
   2364 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
   2365 MHD_FN_PAR_IN_SIZE_ (6, 5);
   2366 
   2367 
   2368 /**
   2369  * Receive data on the HTTP-Upgraded connection.
   2370  *
   2371  * The function finished if one of the following happens:
   2372  * + ANY amount of data has been received,
   2373  * + timeout reached,
   2374  * + network error occurs
   2375  *
   2376  * @param urh the HTTP-Upgraded handle
   2377  * @param recv_buf_size the size of the @a recv_buf
   2378  * @param recv_buf the buffer to receive the data
   2379  * @param received_size the pointer to variable to get amount of received data
   2380  * @param max_wait_millisec the maximum wait time for the data,
   2381  *                          non-blocking operation if set to zero,
   2382  *                          wait indefinitely if larger or equal to
   2383  *                          #MHD_WAIT_INDEFINITELY,
   2384  *                          the function may return earlier if waiting is
   2385  *                          interrupted or by other reasons
   2386  * @return #MHD_SC_OK if ANY data received (check the @a received_size) or
   2387  *                    remote shut down send side (indicated by @a received_size
   2388  *                    set to zero),
   2389  *         #MHD_SC_UPGRADED_NET_TIMEOUT if NO data received but timeout expired,
   2390  *         #MHD_SC_UPGRADED_NET_CONN_CLOSED if network connection has been
   2391  *                                          closed,
   2392  *         #MHD_SC_UPGRADED_NET_CONN_BROKEN if broken network connection has
   2393  *                                          been detected,
   2394  *         #MHD_SC_UPGRADED_TLS_ERROR if TLS error occurs (only for TLS),
   2395  *         #MHD_SC_UPGRADED_NET_HARD_ERROR if any other network or sockets
   2396  *                                         unrecoverable error occurs,
   2397  *         #MHD_SC_UPGRADED_HANDLE_INVALID if @a urh is invalid,
   2398  *         #MHD_SC_UPGRADED_WAITING_NOT_SUPPORTED if timed wait is not supported
   2399  *                                                by this MHD build or platform
   2400  */
   2401 MHD_EXTERN_ enum MHD_StatusCode
   2402 MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh,
   2403                    size_t recv_buf_size,
   2404                    void *MHD_RESTRICT recv_buf,
   2405                    size_t *MHD_RESTRICT received_size,
   2406                    uint_fast64_t max_wait_millisec)
   2407 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_SIZE_ (3, 2)
   2408 MHD_FN_PAR_OUT_ (4);
   2409 
   2410 
   2411 /**
   2412  * Send data on the HTTP-Upgraded connection.
   2413  *
   2414  * The function finished if one of the following happens:
   2415  * + ALL provided data has been sent,
   2416  * + timeout reached,
   2417  * + network error occurs
   2418  *
   2419  * Parameter @a more_data_to_come controls network buffering. When set to
   2420  * #MHD_YES, the OS waits shortly for additional data and tries to use
   2421  * the network more effeciently delaying the last network packet, if it is
   2422  * incomplete, to combine it with the next data provided.
   2423  *
   2424  * @param urh the HTTP-Upgraded handle
   2425  * @param send_buf_size the amount of data in the @a send_buf
   2426  * @param send_buf the buffer with the data to send
   2427  * @param sent_size the pointer to get the amout of sent data
   2428  * @param max_wait_millisec the maximum wait time for the data,
   2429  *                          non-blocking operation if set to zero,
   2430  *                          wait indefinitely if larger or equal to
   2431  *                          #MHD_WAIT_INDEFINITELY
   2432  * @param more_data_to_come set to #MHD_YES if the provided data in
   2433  *                          the @a send_buf is part of a larger data package,
   2434  *                          like an incomplete message or streamed
   2435  *                          (not the final) part of some file, and more data
   2436  *                          expected to be sent soon over the same connection,
   2437  *                          set to #MHD_NO the data in the @a send_buf is
   2438  *                          the complete message or the final part of
   2439  *                          the message (or file) and it should be pushed
   2440  *                          to the network (and to the client) as soon
   2441  *                          as possible
   2442  * @return #MHD_SC_OK if ANY data sent (check the @a sent_size),
   2443  *         #MHD_SC_UPGRADED_NET_TIMEOUT if NO data sent but timeout expired,
   2444  *         #MHD_SC_UPGRADED_NET_CONN_CLOSED if network connection has been
   2445  *                                          closed,
   2446  *         #MHD_SC_UPGRADED_NET_CONN_BROKEN if broken network connection has
   2447  *                                          been detected,
   2448  *         #MHD_SC_UPGRADED_TLS_ERROR if TLS error occurs (only for TLS),
   2449  *         #MHD_SC_UPGRADED_NET_HARD_ERROR if any other network or sockets
   2450  *                                         unrecoverable error occurs,
   2451  *         #MHD_SC_UPGRADED_HANDLE_INVALID if @a urh is invalid,
   2452  *         #MHD_SC_UPGRADED_WAITING_NOT_SUPPORTED if timed wait is not supported
   2453  *                                                by this MHD build or platform
   2454  */
   2455 MHD_EXTERN_ enum MHD_StatusCode
   2456 MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh,
   2457                    size_t send_buf_size,
   2458                    const void *MHD_RESTRICT send_buf,
   2459                    size_t *MHD_RESTRICT sent_size,
   2460                    uint_fast64_t max_wait_millisec,
   2461                    enum MHD_Bool more_data_to_come)
   2462 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3, 2)
   2463 MHD_FN_PAR_OUT_ (4);
   2464 
   2465 
   2466 /**
   2467  * Close HTTP-Upgraded connection handle.
   2468  *
   2469  * The handle cannot be used after successful return from this function.
   2470  *
   2471  * The function cannot fail if called correctly (the daemon is not destroyed
   2472  * and the upgraded connection has not been closed yet).
   2473  *
   2474  * @param urh the handle to close
   2475  * @return #MHD_SC_OK on success,
   2476  *         error code otherwise
   2477  */
   2478 MHD_EXTERN_ enum MHD_StatusCode
   2479 MHD_upgraded_close (struct MHD_UpgradedHandle *urh)
   2480 MHD_FN_PAR_NONNULL_ (1);
   2481 
   2482 
   2483 /* ********************** (e) Client auth ********************** */
   2484 
   2485 
   2486 /**
   2487  * Length of the binary output of the MD5 hash function.
   2488  * @sa #MHD_digest_get_hash_size()
   2489  * @ingroup authentication
   2490  */
   2491 #define MHD_MD5_DIGEST_SIZE 16
   2492 
   2493 /**
   2494  * Length of the binary output of the SHA-256 hash function.
   2495  * @sa #MHD_digest_get_hash_size()
   2496  * @ingroup authentication
   2497  */
   2498 #define MHD_SHA256_DIGEST_SIZE 32
   2499 
   2500 /**
   2501  * Length of the binary output of the SHA-512/256 hash function.
   2502  * @warning While this value is the same as the #MHD_SHA256_DIGEST_SIZE,
   2503  *          the calculated digests for SHA-256 and SHA-512/256 are different.
   2504  * @sa #MHD_digest_get_hash_size()
   2505  * @ingroup authentication
   2506  */
   2507 #define MHD_SHA512_256_DIGEST_SIZE 32
   2508 
   2509 /**
   2510  * Base type of hash calculation.
   2511  * Used as part of #MHD_DigestAuthAlgo values.
   2512  *
   2513  * @warning Not used directly by MHD API.
   2514  */
   2515 enum MHD_FIXED_ENUM_MHD_APP_SET_ MHD_DigestBaseAlgo
   2516 {
   2517   /**
   2518    * Invalid hash algorithm value
   2519    */
   2520   MHD_DIGEST_BASE_ALGO_INVALID = 0
   2521   ,
   2522   /**
   2523    * MD5 hash algorithm.
   2524    * As specified by RFC1321
   2525    */
   2526   MHD_DIGEST_BASE_ALGO_MD5 = (1u << 0)
   2527   ,
   2528   /**
   2529    * SHA-256 hash algorithm.
   2530    * As specified by FIPS PUB 180-4
   2531    */
   2532   MHD_DIGEST_BASE_ALGO_SHA256 = (1u << 1)
   2533   ,
   2534   /**
   2535    * SHA-512/256 hash algorithm.
   2536    * As specified by FIPS PUB 180-4
   2537    */
   2538   MHD_DIGEST_BASE_ALGO_SHA512_256 = (1u << 2)
   2539 };
   2540 
   2541 /**
   2542  * The flag indicating non-session algorithm types,
   2543  * like 'MD5', 'SHA-256' or 'SHA-512-256'.
   2544  */
   2545 #define MHD_DIGEST_AUTH_ALGO_NON_SESSION    (1u << 6)
   2546 
   2547 /**
   2548  * The flag indicating session algorithm types,
   2549  * like 'MD5-sess', 'SHA-256-sess' or 'SHA-512-256-sess'.
   2550  */
   2551 #define MHD_DIGEST_AUTH_ALGO_SESSION        (1u << 7)
   2552 
   2553 /**
   2554  * Digest algorithm identification
   2555  */
   2556 enum MHD_FIXED_ENUM_MHD_APP_SET_ MHD_DigestAuthAlgo
   2557 {
   2558   /**
   2559    * Unknown or wrong algorithm type.
   2560    * Used in struct MHD_AuthDigestInfo to indicate client value that
   2561    * cannot by identified.
   2562    */
   2563   MHD_DIGEST_AUTH_ALGO_INVALID = 0
   2564   ,
   2565   /**
   2566    * The 'MD5' algorithm, non-session version.
   2567    */
   2568   MHD_DIGEST_AUTH_ALGO_MD5 =
   2569     MHD_DIGEST_BASE_ALGO_MD5 | MHD_DIGEST_AUTH_ALGO_NON_SESSION
   2570   ,
   2571   /**
   2572    * The 'MD5-sess' algorithm.
   2573    * Not supported by MHD for authentication.
   2574    */
   2575   MHD_DIGEST_AUTH_ALGO_MD5_SESSION =
   2576     MHD_DIGEST_BASE_ALGO_MD5 | MHD_DIGEST_AUTH_ALGO_SESSION
   2577   ,
   2578   /**
   2579    * The 'SHA-256' algorithm, non-session version.
   2580    */
   2581   MHD_DIGEST_AUTH_ALGO_SHA256 =
   2582     MHD_DIGEST_BASE_ALGO_SHA256 | MHD_DIGEST_AUTH_ALGO_NON_SESSION
   2583   ,
   2584   /**
   2585    * The 'SHA-256-sess' algorithm.
   2586    * Not supported by MHD for authentication.
   2587    */
   2588   MHD_DIGEST_AUTH_ALGO_SHA256_SESSION =
   2589     MHD_DIGEST_BASE_ALGO_SHA256 | MHD_DIGEST_AUTH_ALGO_SESSION
   2590   ,
   2591   /**
   2592    * The 'SHA-512-256' (SHA-512/256) algorithm.
   2593    */
   2594   MHD_DIGEST_AUTH_ALGO_SHA512_256 =
   2595     MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO_NON_SESSION
   2596   ,
   2597   /**
   2598    * The 'SHA-512-256-sess' (SHA-512/256 session) algorithm.
   2599    * Not supported by MHD for authentication.
   2600    */
   2601   MHD_DIGEST_AUTH_ALGO_SHA512_256_SESSION =
   2602     MHD_DIGEST_BASE_ALGO_SHA512_256 | MHD_DIGEST_AUTH_ALGO_SESSION
   2603 };
   2604 
   2605 
   2606 /**
   2607  * Get digest size in bytes for specified algorithm.
   2608  *
   2609  * The size of the digest specifies the size of the userhash, userdigest
   2610  * and other parameters which size depends on used hash algorithm.
   2611  * @param algo the algorithm to check
   2612  * @return the size (in bytes) of the digest (either #MHD_MD5_DIGEST_SIZE or
   2613  *         #MHD_SHA256_DIGEST_SIZE/MHD_SHA512_256_DIGEST_SIZE)
   2614  *         or zero if the input value is not supported or not valid
   2615  * @sa #MHD_digest_auth_calc_userdigest()
   2616  * @sa #MHD_digest_auth_calc_userhash(), #MHD_digest_auth_calc_userhash_hex()
   2617  * @ingroup authentication
   2618  */
   2619 MHD_EXTERN_ size_t
   2620 MHD_digest_get_hash_size (enum MHD_DigestAuthAlgo algo)
   2621 MHD_FN_CONST_;
   2622 
   2623 /**
   2624  * Digest algorithm identification, allow multiple selection.
   2625  *
   2626  * #MHD_DigestAuthAlgo always can be casted to #MHD_DigestAuthMultiAlgo, but
   2627  * not vice versa.
   2628  */
   2629 enum MHD_FIXED_ENUM_MHD_APP_SET_ MHD_DigestAuthMultiAlgo
   2630 {
   2631   /**
   2632    * Unknown or wrong algorithm type.
   2633    */
   2634   MHD_DIGEST_AUTH_MULT_ALGO_INVALID = MHD_DIGEST_AUTH_ALGO_INVALID
   2635   ,
   2636   /**
   2637    * The 'MD5' algorithm, non-session version.
   2638    */
   2639   MHD_DIGEST_AUTH_MULT_ALGO_MD5 = MHD_DIGEST_AUTH_ALGO_MD5
   2640   ,
   2641   /**
   2642    * The 'MD5-sess' algorithm.
   2643    * Not supported by MHD for authentication.
   2644    * Reserved value.
   2645    */
   2646   MHD_DIGEST_AUTH_MULT_ALGO_MD5_SESSION = MHD_DIGEST_AUTH_ALGO_MD5_SESSION
   2647   ,
   2648   /**
   2649    * The 'SHA-256' algorithm, non-session version.
   2650    */
   2651   MHD_DIGEST_AUTH_MULT_ALGO_SHA256 = MHD_DIGEST_AUTH_ALGO_SHA256
   2652   ,
   2653   /**
   2654    * The 'SHA-256-sess' algorithm.
   2655    * Not supported by MHD for authentication.
   2656    * Reserved value.
   2657    */
   2658   MHD_DIGEST_AUTH_MULT_ALGO_SHA256_SESSION =
   2659     MHD_DIGEST_AUTH_ALGO_SHA256_SESSION
   2660   ,
   2661   /**
   2662    * The 'SHA-512-256' (SHA-512/256) algorithm, non-session version.
   2663    */
   2664   MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256 = MHD_DIGEST_AUTH_ALGO_SHA512_256
   2665   ,
   2666   /**
   2667    * The 'SHA-512-256-sess' (SHA-512/256 session) algorithm.
   2668    * Not supported by MHD for authentication.
   2669    * Reserved value.
   2670    */
   2671   MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256_SESSION =
   2672     MHD_DIGEST_AUTH_ALGO_SHA512_256_SESSION
   2673   ,
   2674   /**
   2675    * SHA-256 or SHA-512/256 non-session algorithm, MHD will choose
   2676    * the preferred or the matching one.
   2677    */
   2678   MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_NON_SESSION =
   2679     MHD_DIGEST_AUTH_ALGO_SHA256 | MHD_DIGEST_AUTH_ALGO_SHA512_256
   2680   ,
   2681   /**
   2682    * Any non-session algorithm, MHD will choose the preferred or
   2683    * the matching one.
   2684    */
   2685   MHD_DIGEST_AUTH_MULT_ALGO_ANY_NON_SESSION =
   2686     (0x3F) | MHD_DIGEST_AUTH_ALGO_NON_SESSION
   2687   ,
   2688   /**
   2689    * The SHA-256 or SHA-512/256 session algorithm.
   2690    * Not supported by MHD.
   2691    * Reserved value.
   2692    */
   2693   MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_SESSION =
   2694     MHD_DIGEST_AUTH_ALGO_SHA256_SESSION
   2695     | MHD_DIGEST_AUTH_ALGO_SHA512_256_SESSION
   2696   ,
   2697   /**
   2698    * Any session algorithm.
   2699    * Not supported by MHD.
   2700    * Reserved value.
   2701    */
   2702   MHD_DIGEST_AUTH_MULT_ALGO_ANY_SESSION =
   2703     (0x3F) | MHD_DIGEST_AUTH_ALGO_SESSION
   2704   ,
   2705   /**
   2706    * The MD5 algorithm, session or non-session.
   2707    * Currently supported as non-session only.
   2708    */
   2709   MHD_DIGEST_AUTH_MULT_ALGO_MD5_ANY =
   2710     MHD_DIGEST_AUTH_MULT_ALGO_MD5 | MHD_DIGEST_AUTH_MULT_ALGO_MD5_SESSION
   2711   ,
   2712   /**
   2713    * The SHA-256 algorithm, session or non-session.
   2714    * Currently supported as non-session only.
   2715    */
   2716   MHD_DIGEST_AUTH_MULT_ALGO_SHA256_ANY =
   2717     MHD_DIGEST_AUTH_MULT_ALGO_SHA256
   2718     | MHD_DIGEST_AUTH_MULT_ALGO_SHA256_SESSION
   2719   ,
   2720   /**
   2721    * The SHA-512/256 algorithm, session or non-session.
   2722    * Currently supported as non-session only.
   2723    */
   2724   MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256_ANY =
   2725     MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256
   2726     | MHD_DIGEST_AUTH_MULT_ALGO_SHA512_256_SESSION
   2727   ,
   2728   /**
   2729    * The SHA-256 or SHA-512/256 algorithm, session or non-session.
   2730    * Currently supported as non-session only.
   2731    */
   2732   MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_ANY =
   2733     MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_NON_SESSION
   2734     | MHD_DIGEST_AUTH_MULT_ALGO_SHA_ANY_SESSION
   2735   ,
   2736   /**
   2737    * Any algorithm, MHD will choose the preferred or the matching one.
   2738    */
   2739   MHD_DIGEST_AUTH_MULT_ALGO_ANY =
   2740     (0x3F) | MHD_DIGEST_AUTH_ALGO_NON_SESSION | MHD_DIGEST_AUTH_ALGO_SESSION
   2741 };
   2742 
   2743 
   2744 /**
   2745  * Calculate "userhash", return it as binary data.
   2746  *
   2747  * The "userhash" is the hash of the string "username:realm".
   2748  *
   2749  * The "userhash" could be used to avoid sending username in cleartext in Digest
   2750  * Authorization client's header.
   2751  *
   2752  * Userhash is not designed to hide the username in local database or files,
   2753  * as username in cleartext is required for #MHD_digest_auth_check() function
   2754  * to check the response, but it can be used to hide username in HTTP headers.
   2755  *
   2756  * This function could be used when the new username is added to the username
   2757  * database to save the "userhash" alongside with the username (preferably) or
   2758  * when loading list of the usernames to generate the userhash for every loaded
   2759  * username (this will cause delays at the start with the long lists).
   2760  *
   2761  * Once "userhash" is generated it could be used to identify users by clients
   2762  * with "userhash" support.
   2763  * Avoid repetitive usage of this function for the same username/realm
   2764  * combination as it will cause excessive CPU load; save and reuse the result
   2765  * instead.
   2766  *
   2767  * @param algo the algorithm for userhash calculations
   2768  * @param username the username
   2769  * @param realm the realm
   2770  * @param[out] userhash_bin the output buffer for userhash as binary data;
   2771  *                          if this function succeeds, then this buffer has
   2772  *                          #MHD_digest_get_hash_size() bytes of userhash
   2773  *                          upon return
   2774  * @param bin_buf_size the size of the @a userhash_bin buffer, must be
   2775  *                     at least #MHD_digest_get_hash_size() bytes long
   2776  * @return #MHD_SC_OK on success,
   2777  *         #MHD_SC_OUT_BUFF_TOO_SMALL if @a bin_buf_size is too small,
   2778  *         #MHD_SC_HASH_FAILED if hashing failed,
   2779  *         #MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED if requested @a algo is
   2780  *                                                unknown or unsupported.
   2781  * @sa #MHD_digest_auth_calc_userhash_hex()
   2782  * @ingroup authentication
   2783  */
   2784 MHD_EXTERN_ enum MHD_StatusCode
   2785 MHD_digest_auth_calc_userhash (enum MHD_DigestAuthAlgo algo,
   2786                                const char *MHD_RESTRICT username,
   2787                                const char *MHD_RESTRICT realm,
   2788                                size_t bin_buf_size,
   2789                                void *MHD_RESTRICT userhash_bin)
   2790 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_CSTR_ (2)
   2791 MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_OUT_SIZE_ (5, 4);
   2792 
   2793 
   2794 /**
   2795  * Calculate "userhash", return it as hexadecimal string.
   2796  *
   2797  * The "userhash" is the hash of the string "username:realm".
   2798  *
   2799  * The "userhash" could be used to avoid sending username in cleartext in Digest
   2800  * Authorization client's header.
   2801  *
   2802  * Userhash is not designed to hide the username in local database or files,
   2803  * as username in cleartext is required for #MHD_digest_auth_check() function
   2804  * to check the response, but it can be used to hide username in HTTP headers.
   2805  *
   2806  * This function could be used when the new username is added to the username
   2807  * database to save the "userhash" alongside with the username (preferably) or
   2808  * when loading list of the usernames to generate the userhash for every loaded
   2809  * username (this will cause delays at the start with the long lists).
   2810  *
   2811  * Once "userhash" is generated it could be used to identify users by clients
   2812  * with "userhash" support.
   2813  * Avoid repetitive usage of this function for the same username/realm
   2814  * combination as it will cause excessive CPU load; save and reuse the result
   2815  * instead.
   2816  *
   2817  * @param algo the algorithm for userhash calculations
   2818  * @param username the username
   2819  * @param realm the realm
   2820  * @param hex_buf_size the size of the @a userhash_hex buffer, must be
   2821  *                     at least #MHD_digest_get_hash_size()*2+1 chars long
   2822  * @param[out] userhash_hex the output buffer for userhash as hex string;
   2823  *                          if this function succeeds, then this buffer has
   2824  *                          #MHD_digest_get_hash_size()*2 chars long
   2825  *                          userhash string plus one zero-termination char
   2826  * @return #MHD_SC_OK on success,
   2827  *         #MHD_SC_OUT_BUFF_TOO_SMALL if @a bin_buf_size is too small,
   2828  *         #MHD_SC_HASH_FAILED if hashing failed,
   2829  *         #MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED if requested @a algo is
   2830  *                                                unknown or unsupported.
   2831  * @sa #MHD_digest_auth_calc_userhash()
   2832  * @ingroup authentication
   2833  */
   2834 MHD_EXTERN_ enum MHD_StatusCode
   2835 MHD_digest_auth_calc_userhash_hex (
   2836   enum MHD_DigestAuthAlgo algo,
   2837   const char *MHD_RESTRICT username,
   2838   const char *MHD_RESTRICT realm,
   2839   size_t hex_buf_size,
   2840   char userhash_hex[MHD_FN_PAR_DYN_ARR_SIZE_ (hex_buf_size)])
   2841 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_CSTR_ (2)
   2842 MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_OUT_SIZE_ (5, 4);
   2843 
   2844 
   2845 /**
   2846  * The type of username used by client in Digest Authorization header
   2847  *
   2848  * Values are sorted so simplified checks could be used.
   2849  * For example:
   2850  * * (value <= MHD_DIGEST_AUTH_UNAME_TYPE_INVALID) is true if no valid username
   2851  *   is provided by the client (not used currently)
   2852  * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH) is true if username is
   2853  *   provided in any form
   2854  * * (value >= MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD) is true if username is
   2855  *   provided in clear text (no userhash matching is needed)
   2856  */
   2857 enum MHD_FIXED_ENUM_MHD_SET_ MHD_DigestAuthUsernameType
   2858 {
   2859   /**
   2860    * No username parameter is in Digest Authorization header.
   2861    * Not used currently. Value #MHD_SC_REQ_AUTH_DATA_BROKEN is returned
   2862    * by #MHD_request_get_info_dynamic_sz() if the request has no username.
   2863    */
   2864   MHD_DIGEST_AUTH_UNAME_TYPE_MISSING = 0
   2865   ,
   2866   /**
   2867    * The 'username' parameter is used to specify the username.
   2868    */
   2869   MHD_DIGEST_AUTH_UNAME_TYPE_STANDARD = (1u << 2)
   2870   ,
   2871   /**
   2872    * The username is specified by 'username*' parameter with
   2873    * the extended notation (see RFC 5987, section 3.2.1).
   2874    * The only difference between standard and extended types is
   2875    * the way how username value is encoded in the header.
   2876    */
   2877   MHD_DIGEST_AUTH_UNAME_TYPE_EXTENDED = (1u << 3)
   2878   ,
   2879   /**
   2880    * The username provided in form of 'userhash' as
   2881    * specified by RFC 7616, section 3.4.4.
   2882    * @sa #MHD_digest_auth_calc_userhash_hex(), #MHD_digest_auth_calc_userhash()
   2883    */
   2884   MHD_DIGEST_AUTH_UNAME_TYPE_USERHASH = (1u << 1)
   2885   ,
   2886   /**
   2887    * The invalid combination of username parameters are used by client.
   2888    * Either:
   2889    * + both 'username' and 'username*' are used
   2890    * + 'username*' is used with 'userhash=true'
   2891    * + 'username*' used with invalid extended notation
   2892    * + 'username' is not hexadecimal string, while 'userhash' set to 'true'
   2893    * Not used currently. Value #MHD_SC_REQ_AUTH_DATA_BROKEN is returned
   2894    * by #MHD_request_get_info_dynamic_sz() if the request has broken username.
   2895    */
   2896   MHD_DIGEST_AUTH_UNAME_TYPE_INVALID = (1u << 0)
   2897 };
   2898 
   2899 /**
   2900  * The QOP ('quality of protection') types.
   2901  */
   2902 enum MHD_FIXED_ENUM_MHD_APP_SET_ MHD_DigestAuthQOP
   2903 {
   2904   /**
   2905    * Invalid/unknown QOP.
   2906    * Used in struct MHD_AuthDigestInfo to indicate client value that
   2907    * cannot by identified.
   2908    */
   2909   MHD_DIGEST_AUTH_QOP_INVALID = 0
   2910   ,
   2911   /**
   2912    * No QOP parameter.
   2913    * As described in old RFC 2069 original specification.
   2914    * This mode is not allowed by latest RFCs and should be used only to
   2915    * communicate with clients that do not support more modern modes (with QOP
   2916    * parameter).
   2917    * This mode is less secure than other modes and inefficient.
   2918    */
   2919   MHD_DIGEST_AUTH_QOP_NONE = (1u << 0)
   2920   ,
   2921   /**
   2922    * The 'auth' QOP type.
   2923    */
   2924   MHD_DIGEST_AUTH_QOP_AUTH = (1u << 1)
   2925   ,
   2926   /**
   2927    * The 'auth-int' QOP type.
   2928    * Not supported by MHD for authentication.
   2929    */
   2930   MHD_DIGEST_AUTH_QOP_AUTH_INT = (1u << 2)
   2931 };
   2932 
   2933 /**
   2934  * The QOP ('quality of protection') types, multiple selection.
   2935  *
   2936  * #MHD_DigestAuthQOP always can be casted to #MHD_DigestAuthMultiQOP, but
   2937  * not vice versa.
   2938  */
   2939 enum MHD_FIXED_ENUM_MHD_APP_SET_ MHD_DigestAuthMultiQOP
   2940 {
   2941   /**
   2942    * Invalid/unknown QOP.
   2943    */
   2944   MHD_DIGEST_AUTH_MULT_QOP_INVALID = MHD_DIGEST_AUTH_QOP_INVALID
   2945   ,
   2946   /**
   2947    * No QOP parameter.
   2948    * As described in old RFC 2069 original specification.
   2949    * This mode is not allowed by latest RFCs and should be used only to
   2950    * communicate with clients that do not support more modern modes (with QOP
   2951    * parameter).
   2952    * This mode is less secure than other modes and inefficient.
   2953    */
   2954   MHD_DIGEST_AUTH_MULT_QOP_NONE = MHD_DIGEST_AUTH_QOP_NONE
   2955   ,
   2956   /**
   2957    * The 'auth' QOP type.
   2958    */
   2959   MHD_DIGEST_AUTH_MULT_QOP_AUTH = MHD_DIGEST_AUTH_QOP_AUTH
   2960   ,
   2961   /**
   2962    * The 'auth-int' QOP type.
   2963    * Not supported by MHD.
   2964    * Reserved value.
   2965    */
   2966   MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT = MHD_DIGEST_AUTH_QOP_AUTH_INT
   2967   ,
   2968   /**
   2969    * The 'auth' QOP type OR the old RFC2069 (no QOP) type.
   2970    * In other words: any types except 'auth-int'.
   2971    * RFC2069-compatible mode is allowed, thus this value should be used only
   2972    * when it is really necessary.
   2973    */
   2974   MHD_DIGEST_AUTH_MULT_QOP_ANY_NON_INT =
   2975     MHD_DIGEST_AUTH_QOP_NONE | MHD_DIGEST_AUTH_QOP_AUTH
   2976   ,
   2977   /**
   2978    * Any 'auth' QOP type ('auth' or 'auth-int').
   2979    * Currently supported as 'auth' QOP type only.
   2980    */
   2981   MHD_DIGEST_AUTH_MULT_QOP_AUTH_ANY =
   2982     MHD_DIGEST_AUTH_QOP_AUTH | MHD_DIGEST_AUTH_QOP_AUTH_INT
   2983 };
   2984 
   2985 /**
   2986  * The type of 'nc' (nonce count) value provided in the request
   2987  */
   2988 enum MHD_FIXED_ENUM_MHD_SET_ MHD_DigestAuthNC
   2989 {
   2990   /**
   2991    * Readable hexdecimal non-zero number.
   2992    * The decoded value is placed in @a nc member of struct MHD_AuthDigestInfo
   2993    */
   2994   MHD_DIGEST_AUTH_NC_NUMBER = 1
   2995   ,
   2996   /**
   2997    * Readable zero number.
   2998    * Compliant clients should not use such values.
   2999    * Can be treated as invalid request.
   3000    */
   3001   MHD_DIGEST_AUTH_NC_ZERO = 2
   3002   ,
   3003   /**
   3004    * 'nc' value is not provided by the client.
   3005    * Unless old RFC 2069 mode is allowed, this should be treated as invalid
   3006    * request.
   3007    */
   3008   MHD_DIGEST_AUTH_NC_NONE = 3
   3009   ,
   3010   /**
   3011    * 'nc' value is too long to be decoded.
   3012    * Compliant clients should not use such values.
   3013    * Can be treated as invalid request.
   3014    */
   3015   MHD_DIGEST_AUTH_NC_TOO_LONG = 4
   3016   ,
   3017   /**
   3018    * 'nc' value is too large for uint32_t.
   3019    * Compliant clients should not use such values.
   3020    * Can be treated as request with a stale nonce or as invalid request.
   3021    */
   3022   MHD_DIGEST_AUTH_NC_TOO_LARGE = 5
   3023 };
   3024 
   3025 
   3026 /**
   3027  * Information from Digest Authorization client's header.
   3028  *
   3029  * @see #MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO
   3030  */
   3031 struct MHD_AuthDigestInfo
   3032 {
   3033   /**
   3034    * The algorithm as defined by client.
   3035    * Set automatically to MD5 if not specified by client.
   3036    */
   3037   enum MHD_DigestAuthAlgo algo;
   3038 
   3039   /**
   3040    * The type of username used by client.
   3041    */
   3042   enum MHD_DigestAuthUsernameType uname_type;
   3043 
   3044   /**
   3045    * The username string.
   3046    * Used only if username type is standard or extended, always NULL otherwise.
   3047    * If extended notation is used, this string is pct-decoded string
   3048    * with charset and language tag removed (i.e. it is original username
   3049    * extracted from the extended notation).
   3050    * When userhash is used by the client, the string pointer is NULL and
   3051    * @a userhash_hex and @a userhash_bin are set.
   3052    */
   3053   struct MHD_StringNullable username;
   3054 
   3055   /**
   3056    * The userhash string.
   3057    * Valid only if username type is userhash.
   3058    * This is unqoted string without decoding of the hexadecimal
   3059    * digits (as provided by the client).
   3060    * @sa #MHD_digest_auth_calc_userhash_hex()
   3061    */
   3062   struct MHD_StringNullable userhash_hex;
   3063 
   3064   /**
   3065    * The userhash decoded to binary form.
   3066    * Used only if username type is userhash, always NULL otherwise.
   3067    * When not NULL, this points to binary sequence @a userhash_bin_size bytes
   3068    * long.
   3069    * The valid size should be #MHD_digest_get_hash_size() bytes.
   3070    * @warning This is a binary data, no zero termination.
   3071    * @warning To avoid buffer overruns, always check the size of the data before
   3072    *          use, because @a userhash_bin can point even to zero-sized
   3073    *          data.
   3074    * @sa #MHD_digest_auth_calc_userhash()
   3075    */
   3076   const uint8_t *userhash_bin;
   3077 
   3078   /**
   3079    * The size of the data pointed by @a userhash_bin.
   3080    * Always zero when @a userhash_bin is NULL.
   3081    */
   3082   size_t userhash_bin_size;
   3083 
   3084   /**
   3085    * The 'opaque' parameter value, as specified by client.
   3086    * If not specified by client then string pointer is NULL.
   3087    */
   3088   struct MHD_StringNullable opaque;
   3089 
   3090   /**
   3091    * The 'realm' parameter value, as specified by client.
   3092    * If not specified by client then string pointer is NULL.
   3093    */
   3094   struct MHD_StringNullable realm;
   3095 
   3096   /**
   3097    * The 'qop' parameter value.
   3098    */
   3099   enum MHD_DigestAuthQOP qop;
   3100 
   3101   /**
   3102    * The length of the 'cnonce' parameter value, including possible
   3103    * backslash-escape characters.
   3104    * 'cnonce' is used in hash calculation, which is CPU-intensive procedure.
   3105    * An application may want to reject too large cnonces to limit the CPU load.
   3106    * A few kilobytes is a reasonable limit, typically cnonce is just 32-160
   3107    * characters long.
   3108    */
   3109   size_t cnonce_len;
   3110 
   3111   /**
   3112    * The type of 'nc' (nonce count) value provided in the request.
   3113    */
   3114   enum MHD_DigestAuthNC nc_type;
   3115 
   3116   /**
   3117    * The nc (nonce count) parameter value.
   3118    * Can be used by application to limit the number of nonce re-uses. If @a nc
   3119    * is higher than application wants to allow, then "auth required" response
   3120    * with 'stale=true' could be used to force client to retry with the fresh
   3121    * 'nonce'.
   3122    * Set to zero when @a nc_type is not set to #MHD_DIGEST_AUTH_NC_NUMBER.
   3123    */
   3124   uint_fast32_t nc;
   3125 };
   3126 
   3127 /**
   3128  * The result of digest authentication of the client.
   3129  *
   3130  * All error values are zero or negative.
   3131  */
   3132 enum MHD_FIXED_ENUM_MHD_SET_ MHD_DigestAuthResult
   3133 {
   3134   /**
   3135    * Authentication OK.
   3136    */
   3137   MHD_DAUTH_OK = 1
   3138   ,
   3139   /**
   3140    * General error, like "out of memory".
   3141    * Authentication may be valid, but cannot be checked.
   3142    */
   3143   MHD_DAUTH_ERROR = 0
   3144   ,
   3145   /**
   3146    * No "Authorization" header for Digest Authentication.
   3147    */
   3148   MHD_DAUTH_HEADER_MISSING = -1
   3149   ,
   3150   /**
   3151    * Wrong format of the header.
   3152    * Also returned if required parameters in Authorization header are missing
   3153    * or broken (in invalid format).
   3154    */
   3155   MHD_DAUTH_HEADER_BROKEN = -9
   3156   ,
   3157   /**
   3158    * Unsupported algorithm.
   3159    */
   3160   MHD_DAUTH_UNSUPPORTED_ALGO = -10
   3161   ,
   3162   /**
   3163    * Unsupported 'qop'.
   3164    */
   3165   MHD_DAUTH_UNSUPPORTED_QOP = -11
   3166   ,
   3167   /**
   3168    * Incorrect userdigest size.
   3169    */
   3170   MHD_DAUTH_INVALID_USERDIGEST_SIZE = -15
   3171   ,
   3172   /**
   3173    * Wrong 'username'.
   3174    */
   3175   MHD_DAUTH_WRONG_USERNAME = -17
   3176   ,
   3177   /**
   3178    * Wrong 'realm'.
   3179    */
   3180   MHD_DAUTH_WRONG_REALM = -18
   3181   ,
   3182   /**
   3183    * Wrong 'URI' (or URI parameters).
   3184    */
   3185   MHD_DAUTH_WRONG_URI = -19
   3186   ,
   3187   /**
   3188    * Wrong 'qop'.
   3189    */
   3190   MHD_DAUTH_WRONG_QOP = -20
   3191   ,
   3192   /**
   3193    * Wrong 'algorithm'.
   3194    */
   3195   MHD_DAUTH_WRONG_ALGO = -21
   3196   ,
   3197   /**
   3198    * Too large (>64 KiB) Authorization parameter value.
   3199    */
   3200   MHD_DAUTH_TOO_LARGE = -22
   3201   ,
   3202   /* The different form of naming is intentionally used for the results below,
   3203    * as they are more important */
   3204 
   3205   /**
   3206    * The 'nonce' is too old. Suggest the client to retry with the same
   3207    * username and password to get the fresh 'nonce'.
   3208    * The validity of the 'nonce' may be not checked.
   3209    */
   3210   MHD_DAUTH_NONCE_STALE = -25
   3211   ,
   3212   /**
   3213    * The 'nonce' is wrong. May indicate an attack attempt.
   3214    */
   3215   MHD_DAUTH_NONCE_WRONG = -33
   3216   ,
   3217   /**
   3218    * The 'response' is wrong. May indicate a wrong password used or
   3219    * an attack attempt.
   3220    */
   3221   MHD_DAUTH_RESPONSE_WRONG = -34
   3222 };
   3223 
   3224 
   3225 /**
   3226  * Authenticates the authorization header sent by the client.
   3227  *
   3228  * If RFC2069 mode is allowed by setting bit #MHD_DIGEST_AUTH_QOP_NONE in
   3229  * @a mqop and the client uses this mode, then server generated nonces are
   3230  * used as one-time nonces because nonce-count is not supported in this old RFC.
   3231  * Communication in this mode is very inefficient, especially if the client
   3232  * requests several resources one-by-one as for every request a new nonce must
   3233  * be generated and client repeats all requests twice (first time to get a new
   3234  * nonce and second time to perform an authorised request).
   3235  *
   3236  * @param request the request
   3237  * @param realm the realm for authorization of the client
   3238  * @param username the username to be authenticated, must be in clear text
   3239  *                 even if userhash is used by the client
   3240  * @param password the password matching the @a username (and the @a realm)
   3241  * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
   3242  *               exceeds the specified value then MHD_DAUTH_NONCE_STALE is
   3243  *               returned;
   3244  *               if zero is specified then daemon default value is used.
   3245  * @param mqop the QOP to use
   3246  * @param malgo digest algorithms allowed to use, fail if algorithm used
   3247  *               by the client is not allowed by this parameter
   3248  * @return #MHD_DAUTH_OK if authenticated,
   3249  *         the error code otherwise
   3250  * @ingroup authentication
   3251  */
   3252 MHD_EXTERN_ enum MHD_DigestAuthResult
   3253 MHD_digest_auth_check (struct MHD_Request *MHD_RESTRICT request,
   3254                        const char *MHD_RESTRICT realm,
   3255                        const char *MHD_RESTRICT username,
   3256                        const char *MHD_RESTRICT password,
   3257                        uint_fast32_t max_nc,
   3258                        enum MHD_DigestAuthMultiQOP mqop,
   3259                        enum MHD_DigestAuthMultiAlgo malgo)
   3260 MHD_FN_PAR_NONNULL_ALL_
   3261 MHD_FN_PAR_CSTR_ (2) MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4);
   3262 
   3263 
   3264 /**
   3265  * Calculate userdigest, return it as a binary data.
   3266  *
   3267  * The "userdigest" is the hash of the "username:realm:password" string.
   3268  *
   3269  * The "userdigest" can be used to avoid storing the password in clear text
   3270  * in database/files
   3271  *
   3272  * This function is designed to improve security of stored credentials,
   3273  * the "userdigest" does not improve security of the authentication process.
   3274  *
   3275  * The results can be used to store username & userdigest pairs instead of
   3276  * username & password pairs. To further improve security, application may
   3277  * store username & userhash & userdigest triplets.
   3278  *
   3279  * @param algo the digest algorithm
   3280  * @param username the username
   3281  * @param realm the realm
   3282  * @param password the password
   3283  * @param bin_buf_size the size of the @a userdigest_bin buffer, must be
   3284  *                     at least #MHD_digest_get_hash_size() bytes long
   3285  * @param[out] userdigest_bin the output buffer for userdigest;
   3286  *                            if this function succeeds, then this buffer has
   3287  *                            #MHD_digest_get_hash_size() bytes of
   3288  *                            userdigest upon return
   3289  * @return #MHD_SC_OK on success,
   3290  *         #MHD_SC_OUT_BUFF_TOO_SMALL if @a bin_buf_size is too small,
   3291  *         #MHD_SC_HASH_FAILED if hashing failed,
   3292  *         #MHD_SC_AUTH_DIGEST_ALGO_NOT_SUPPORTED if requested @a algo is
   3293  *                                                unknown or unsupported.
   3294  * @sa #MHD_digest_auth_check_digest()
   3295  * @ingroup authentication
   3296  */
   3297 MHD_EXTERN_ enum MHD_StatusCode
   3298 MHD_digest_auth_calc_userdigest (enum MHD_DigestAuthAlgo algo,
   3299                                  const char *MHD_RESTRICT username,
   3300                                  const char *MHD_RESTRICT realm,
   3301                                  const char *MHD_RESTRICT password,
   3302                                  size_t bin_buf_size,
   3303                                  void *MHD_RESTRICT userdigest_bin)
   3304 MHD_FN_PAR_NONNULL_ALL_
   3305 MHD_FN_PAR_CSTR_ (2)
   3306 MHD_FN_PAR_CSTR_ (3)
   3307 MHD_FN_PAR_CSTR_ (4)
   3308 MHD_FN_PAR_OUT_SIZE_ (6, 5);
   3309 
   3310 
   3311 /**
   3312  * Authenticates the authorization header sent by the client by using
   3313  * hash of "username:realm:password".
   3314  *
   3315  * If RFC2069 mode is allowed by setting bit #MHD_DIGEST_AUTH_QOP_NONE in
   3316  * @a mqop and the client uses this mode, then server generated nonces are
   3317  * used as one-time nonces because nonce-count is not supported in this old RFC.
   3318  * Communication in this mode is very inefficient, especially if the client
   3319  * requests several resources one-by-one as for every request a new nonce must
   3320  * be generated and client repeats all requests twice (first time to get a new
   3321  * nonce and second time to perform an authorised request).
   3322  *
   3323  * @param request the request
   3324  * @param realm the realm for authorization of the client
   3325  * @param username the username to be authenticated, must be in clear text
   3326  *                 even if userhash is used by the client
   3327  * @param userdigest_size the size of the @a userdigest in bytes, must match the
   3328  *                        hashing algorithm (see #MHD_MD5_DIGEST_SIZE,
   3329  *                        #MHD_SHA256_DIGEST_SIZE, #MHD_SHA512_256_DIGEST_SIZE,
   3330  *                        #MHD_digest_get_hash_size())
   3331  * @param userdigest the precalculated binary hash of the string
   3332  *                   "username:realm:password",
   3333  *                   see #MHD_digest_auth_calc_userdigest()
   3334  * @param max_nc the maximum allowed nc (Nonce Count) value, if client's nc
   3335  *               exceeds the specified value then MHD_DAUTH_NONCE_STALE is
   3336  *               returned;
   3337  *               if zero is specified then daemon default value is used.
   3338  * @param mqop the QOP to use
   3339  * @param malgo digest algorithms allowed to use, fail if algorithm used
   3340  *              by the client is not allowed by this parameter;
   3341  *              more than one base algorithms (MD5, SHA-256, SHA-512/256)
   3342  *              cannot be used at the same time for this function
   3343  *              as @a userdigest must match specified algorithm
   3344  * @return #MHD_DAUTH_OK if authenticated,
   3345  *         the error code otherwise
   3346  * @sa #MHD_digest_auth_calc_userdigest()
   3347  * @ingroup authentication
   3348  */
   3349 MHD_EXTERN_ enum MHD_DigestAuthResult
   3350 MHD_digest_auth_check_digest (struct MHD_Request *MHD_RESTRICT request,
   3351                               const char *MHD_RESTRICT realm,
   3352                               const char *MHD_RESTRICT username,
   3353                               size_t userdigest_size,
   3354                               const void *MHD_RESTRICT userdigest,
   3355                               uint_fast32_t max_nc,
   3356                               enum MHD_DigestAuthMultiQOP mqop,
   3357                               enum MHD_DigestAuthMultiAlgo malgo)
   3358 MHD_FN_PAR_NONNULL_ALL_
   3359 MHD_FN_PAR_CSTR_ (2)
   3360 MHD_FN_PAR_CSTR_ (3)
   3361 MHD_FN_PAR_IN_SIZE_ (5, 4);
   3362 
   3363 
   3364 /**
   3365  * Add Digest Authentication "challenge" to the response.
   3366  *
   3367  * The response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3368  *
   3369  * If @a mqop allows both RFC 2069 (#MHD_DIGEST_AUTH_QOP_NONE) and other QOP
   3370  * values, then the "challenge" is formed like if MHD_DIGEST_AUTH_QOP_NONE bit
   3371  * was not set, because such "challenge" should be backward-compatible with
   3372  * RFC 2069.
   3373  *
   3374  * If @a mqop allows only MHD_DIGEST_AUTH_MULT_QOP_NONE, then the response is
   3375  * formed in strict accordance with RFC 2069 (no 'qop', no 'userhash', no
   3376  * 'charset'). For better compatibility with clients, it is recommended (but
   3377  * not required) to set @a domain to NULL in this mode.
   3378  *
   3379  * New nonces are generated each time when the resulting response is used.
   3380  *
   3381  * See RFC 7616, section 3.3 for details.
   3382  *
   3383  * @param response the response to update; should contain the "access denied"
   3384  *                 body;
   3385  *                 note: this function sets the "WWW Authenticate" header and
   3386  *                 the caller should not set this header;
   3387  *                 the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3388  *                 code;
   3389  *                 the NULL is tolerated (the result is
   3390  *                 #MHD_SC_RESP_POINTER_NULL)
   3391  * @param realm the realm presented to the client
   3392  * @param opaque the string for opaque value, can be NULL, but NULL is
   3393  *               not recommended for better compatibility with clients;
   3394  *               the recommended format is hex or Base64 encoded string
   3395  * @param domain the optional space-separated list of URIs for which the
   3396  *               same authorisation could be used, URIs can be in form
   3397  *               "path-absolute" (the path for the same host with initial slash)
   3398  *               or in form "absolute-URI" (the full path with protocol), in
   3399  *               any case client may assume that URI is in the same "protection
   3400  *               space" if it starts with any of values specified here;
   3401  *               could be NULL (clients typically assume that the same
   3402  *               credentials could be used for any URI on the same host);
   3403  *               this list provides information for the client only and does
   3404  *               not actually restrict anything on the server side
   3405  * @param indicate_stale if set to #MHD_YES then indication of stale nonce used
   3406  *                       in the client's request is indicated by adding
   3407  *                       'stale=true' to the authentication header, this
   3408  *                       instructs the client to retry immediately with the new
   3409  *                       nonce and the same credentials, without asking user
   3410  *                       for the new password
   3411  * @param mqop the QOP to use
   3412  * @param malgo digest algorithm to use; if several algorithms are allowed
   3413  *              then one challenge for each allowed algorithm is added
   3414  * @param userhash_support if set to #MHD_YES then support of userhash is
   3415  *                         indicated, allowing client to provide
   3416  *                         hash("username:realm") instead of the username in
   3417  *                         clear text;
   3418  *                         note that clients are allowed to provide the username
   3419  *                         in cleartext even if this parameter set to non-zero;
   3420  *                         when userhash is used, application must be ready to
   3421  *                         identify users by provided userhash value instead of
   3422  *                         username; see #MHD_digest_auth_calc_userhash() and
   3423  *                         #MHD_digest_auth_calc_userhash_hex()
   3424  * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
   3425  *                    added, indicating for the client that UTF-8 encoding for
   3426  *                    the username is preferred
   3427  * @return #MHD_SC_OK if succeed,
   3428  *         #MHD_SC_TOO_LATE if the response has been already "frozen" (used to
   3429  *         create an action),
   3430  *         #MHD_SC_RESP_HEADERS_CONFLICT if Digest Authentication "challenge"
   3431  *         has been added already,
   3432  *         #MHD_SC_RESP_POINTER_NULL if @a response is NULL,
   3433  *         #MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE is response status code is wrong,
   3434  *         #MHD_SC_RESP_HEADER_VALUE_INVALID if @a realm, @a opaque or @a domain
   3435  *         have wrong characters or zero length (for @a realm),
   3436  *         #MHD_SC_RESP_HEADER_MEM_ALLOC_FAILED if memory allocation failed,
   3437  *         or other error code if failed
   3438  * @ingroup authentication
   3439  */
   3440 MHD_EXTERN_ enum MHD_StatusCode
   3441 MHD_response_add_auth_digest_challenge (
   3442   struct MHD_Response *MHD_RESTRICT response,
   3443   const char *MHD_RESTRICT realm,
   3444   const char *MHD_RESTRICT opaque,
   3445   const char *MHD_RESTRICT domain,
   3446   enum MHD_Bool indicate_stale,
   3447   enum MHD_DigestAuthMultiQOP mqop,
   3448   enum MHD_DigestAuthMultiAlgo malgo,
   3449   enum MHD_Bool userhash_support,
   3450   enum MHD_Bool prefer_utf8)
   3451 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
   3452 MHD_FN_PAR_CSTR_ (3) MHD_FN_PAR_CSTR_ (4);
   3453 
   3454 
   3455 /* Application may define MHD_NO_STATIC_INLINE macro before including
   3456    libmicrohttpd headers to disable static inline functions in the headers. */
   3457 #ifndef MHD_NO_STATIC_INLINE
   3458 
   3459 /**
   3460  * Create action to reply with Digest Authentication "challenge".
   3461  *
   3462  * The @a response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3463  *
   3464  * See RFC 7616, section 3.3 for details.
   3465  *
   3466  * @param request the request to create the action for
   3467  * @param realm the realm presented to the client
   3468  * @param opaque the string for opaque value, can be NULL, but NULL is
   3469  *               not recommended for better compatibility with clients;
   3470  *               the recommended format is hex or Base64 encoded string
   3471  * @param domain the optional space-separated list of URIs for which the
   3472  *               same authorisation could be used, URIs can be in form
   3473  *               "path-absolute" (the path for the same host with initial slash)
   3474  *               or in form "absolute-URI" (the full path with protocol), in
   3475  *               any case client may assume that URI is in the same "protection
   3476  *               space" if it starts with any of values specified here;
   3477  *               could be NULL (clients typically assume that the same
   3478  *               credentials could be used for any URI on the same host);
   3479  *               this list provides information for the client only and does
   3480  *               not actually restrict anything on the server side
   3481  * @param indicate_stale if set to #MHD_YES then indication of stale nonce used
   3482  *                       in the client's request is indicated by adding
   3483  *                       'stale=true' to the authentication header, this
   3484  *                       instructs the client to retry immediately with the new
   3485  *                       nonce and the same credentials, without asking user
   3486  *                       for the new password
   3487  * @param mqop the QOP to use
   3488  * @param malgo digest algorithm to use; if several algorithms are allowed
   3489  *              then one challenge for each allowed algorithm is added
   3490  * @param userhash_support if set to #MHD_YES then support of userhash is
   3491  *                         indicated, allowing client to provide
   3492  *                         hash("username:realm") instead of the username in
   3493  *                         clear text;
   3494  *                         note that clients are allowed to provide the username
   3495  *                         in cleartext even if this parameter set to non-zero;
   3496  *                         when userhash is used, application must be ready to
   3497  *                         identify users by provided userhash value instead of
   3498  *                         username; see #MHD_digest_auth_calc_userhash() and
   3499  *                         #MHD_digest_auth_calc_userhash_hex()
   3500  * @param prefer_utf8 if not set to #MHD_NO, parameter 'charset=UTF-8' is
   3501  *                    added, indicating for the client that UTF-8 encoding for
   3502  *                    the username is preferred
   3503  * @param response the response to update; should contain the "access denied"
   3504  *                 body;
   3505  *                 note: this function sets the "WWW Authenticate" header and
   3506  *                 the caller should not set this header;
   3507  *                 the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3508  *                 code;
   3509  *                 the NULL is tolerated (the result is
   3510  *                 #MHD_SC_RESP_POINTER_NULL)
   3511  * @param abort_if_failed if set to #MHD_NO the response will be used even if
   3512  *                        failed to add Basic Authentication "challenge",
   3513  *                        if not set to #MHD_NO the request will be aborted
   3514  *                        if the "challenge" could not be added.
   3515  * @return pointer to the action, the action must be consumed
   3516  *         otherwise response object may leak;
   3517  *         NULL if failed or if any action has been already created for
   3518  *         the @a request;
   3519  *         when failed the response object is consumed and need not
   3520  *         to be "destroyed"
   3521  * @ingroup authentication
   3522  */
   3523 MHD_STATIC_INLINE_
   3524 MHD_FN_PAR_NONNULL_ (1)
   3525 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
   3526 const struct MHD_Action *
   3527 MHD_action_digest_auth_challenge (struct MHD_Request *MHD_RESTRICT request,
   3528                                   const char *MHD_RESTRICT realm,
   3529                                   const char *MHD_RESTRICT opaque,
   3530                                   const char *MHD_RESTRICT domain,
   3531                                   enum MHD_Bool indicate_stale,
   3532                                   enum MHD_DigestAuthMultiQOP mqop,
   3533                                   enum MHD_DigestAuthMultiAlgo malgo,
   3534                                   enum MHD_Bool userhash_support,
   3535                                   enum MHD_Bool prefer_utf8,
   3536                                   struct MHD_Response *MHD_RESTRICT response,
   3537                                   enum MHD_Bool abort_if_failed)
   3538 {
   3539   if ((MHD_SC_OK !=
   3540        MHD_response_add_auth_digest_challenge (response, realm, opaque, domain,
   3541                                                indicate_stale, mqop, malgo,
   3542                                                userhash_support, prefer_utf8))
   3543       && (MHD_NO != abort_if_failed))
   3544   {
   3545     MHD_response_destroy (response);
   3546     return MHD_action_abort_request (request);
   3547   }
   3548   return MHD_action_from_response (request, response);
   3549 }
   3550 
   3551 
   3552 MHD_STATIC_INLINE_END_
   3553 
   3554 /**
   3555  * Create action to reply with Digest Authentication "challenge".
   3556  *
   3557  * The @a r response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3558  *
   3559  * If the @a r response object cannot be extended with the "challenge",
   3560  * the @a r response is used to reply without the "challenge".
   3561  *
   3562  * @param rq the request to create the action for
   3563  * @param l the realm presented to the client
   3564  * @param o the string for opaque value, can be NULL, but NULL is
   3565  *          not recommended for better compatibility with clients;
   3566  *          the recommended format is hex or Base64 encoded string
   3567  * @param d the optional space-separated list of URIs for which the
   3568  *          same authorisation could be used, URIs can be in form
   3569  *          "path-absolute" (the path for the same host with initial slash)
   3570  *          or in form "absolute-URI" (the full path with protocol), in
   3571  *          any case client may assume that URI is in the same "protection
   3572  *          space" if it starts with any of values specified here;
   3573  *          could be NULL (clients typically assume that the same
   3574  *          credentials could be used for any URI on the same host);
   3575  *          this list provides information for the client only and does
   3576  *          not actually restrict anything on the server side
   3577  * @param s if set to #MHD_YES then indication of stale nonce used
   3578  *          in the client's request is indicated by adding
   3579  *          'stale=true' to the authentication header, this
   3580  *          instructs the client to retry immediately with the new
   3581  *          nonce and the same credentials, without asking user
   3582  *          for the new password
   3583  * @param q the QOP to use
   3584  * @param a digest algorithm to use; if several algorithms are allowed
   3585  *          then one challenge for each allowed algorithm is added
   3586  * @param h if set to #MHD_YES then support of userhash is
   3587  *          indicated, allowing client to provide
   3588  *          hash("username:realm") instead of the username in
   3589  *          clear text;
   3590  *          note that clients are allowed to provide the username
   3591  *          in cleartext even if this parameter set to non-zero;
   3592  *          when userhash is used, application must be ready to
   3593  *          identify users by provided userhash value instead of
   3594  *          username; see #MHD_digest_auth_calc_userhash() and
   3595  *          #MHD_digest_auth_calc_userhash_hex()
   3596  * @param u if not set to #MHD_NO, parameter 'charset=UTF-8' is
   3597  *          added, indicating for the client that UTF-8 encoding for
   3598  *          the username is preferred
   3599  * @param r the response to update; should contain the "access denied"
   3600  *          body;
   3601  *          note: this function sets the "WWW Authenticate" header and
   3602  *          the caller should not set this header;
   3603  *          the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3604  *          code;
   3605  *          the NULL is tolerated (the result is
   3606  *          #MHD_SC_RESP_POINTER_NULL)
   3607  * @return pointer to the action, the action must be consumed
   3608  *         otherwise response object may leak;
   3609  *         NULL if failed or if any action has been already created for
   3610  *         the @a rq request;
   3611  *         when failed the response object is consumed and need not
   3612  *         to be "destroyed"
   3613  * @ingroup authentication
   3614  */
   3615 #  define MHD_action_digest_auth_challenge_p(rq, l, o, d, s, q, a, h, u, r) \
   3616           MHD_action_digest_auth_challenge ((rq),(l),(o),(d),(s),(q), \
   3617                                             (a),(h),(u),(r),MHD_NO)
   3618 
   3619 
   3620 /**
   3621  * Create action to reply with Digest Authentication "challenge".
   3622  *
   3623  * The @a r response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3624  *
   3625  * If the @a r response object cannot be extended with the "challenge",
   3626  * the @a r response is aborted.
   3627  *
   3628  * @param rq the request to create the action for
   3629  * @param l the realm presented to the client
   3630  * @param o the string for opaque value, can be NULL, but NULL is
   3631  *          not recommended for better compatibility with clients;
   3632  *          the recommended format is hex or Base64 encoded string
   3633  * @param d the optional space-separated list of URIs for which the
   3634  *          same authorisation could be used, URIs can be in form
   3635  *          "path-absolute" (the path for the same host with initial slash)
   3636  *          or in form "absolute-URI" (the full path with protocol), in
   3637  *          any case client may assume that URI is in the same "protection
   3638  *          space" if it starts with any of values specified here;
   3639  *          could be NULL (clients typically assume that the same
   3640  *          credentials could be used for any URI on the same host);
   3641  *          this list provides information for the client only and does
   3642  *          not actually restrict anything on the server side
   3643  * @param s if set to #MHD_YES then indication of stale nonce used
   3644  *          in the client's request is indicated by adding
   3645  *          'stale=true' to the authentication header, this
   3646  *          instructs the client to retry immediately with the new
   3647  *          nonce and the same credentials, without asking user
   3648  *          for the new password
   3649  * @param q the QOP to use
   3650  * @param a digest algorithm to use; if several algorithms are allowed
   3651  *          then one challenge for each allowed algorithm is added
   3652  * @param h if set to #MHD_YES then support of userhash is
   3653  *          indicated, allowing client to provide
   3654  *          hash("username:realm") instead of the username in
   3655  *          clear text;
   3656  *          note that clients are allowed to provide the username
   3657  *          in cleartext even if this parameter set to non-zero;
   3658  *          when userhash is used, application must be ready to
   3659  *          identify users by provided userhash value instead of
   3660  *          username; see #MHD_digest_auth_calc_userhash() and
   3661  *          #MHD_digest_auth_calc_userhash_hex()
   3662  * @param u if not set to #MHD_NO, parameter 'charset=UTF-8' is
   3663  *          added, indicating for the client that UTF-8 encoding for
   3664  *          the username is preferred
   3665  * @param r the response to update; should contain the "access denied"
   3666  *          body;
   3667  *          note: this function sets the "WWW Authenticate" header and
   3668  *          the caller should not set this header;
   3669  *          the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3670  *          code;
   3671  *          the NULL is tolerated (the result is
   3672  *          #MHD_SC_RESP_POINTER_NULL)
   3673  * @return pointer to the action, the action must be consumed
   3674  *         otherwise response object may leak;
   3675  *         NULL if failed or if any action has been already created for
   3676  *         the @a rq request;
   3677  *         when failed the response object is consumed and need not
   3678  *         to be "destroyed"
   3679  * @ingroup authentication
   3680  */
   3681 #  define MHD_action_digest_auth_challenge_a(rq, l, o, d, s, q, a, h, u, r) \
   3682           MHD_action_digest_auth_challenge ((rq),(l),(o),(d),(s),(q), \
   3683                                             (a),(h),(u),(r),MHD_YES)
   3684 
   3685 #endif /* ! MHD_NO_STATIC_INLINE */
   3686 
   3687 
   3688 /**
   3689  * Add Basic Authentication "challenge" to the response.
   3690  *
   3691  * The response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3692  *
   3693  * If access to any resource should be limited to specific users, authenticated
   3694  * by Basic Authentication mechanism, and the request for this resource does not
   3695  * have Basic Authentication information (see #MHD_AuthBasicCreds), then response
   3696  * with Basic Authentication "challenge" should be sent. This works as
   3697  * an indication that Basic Authentication should be used for the access.
   3698  *
   3699  * See RFC 7617, section 2 for details.
   3700  *
   3701  * @param response the reply to send; should contain the "access denied"
   3702  *                 body;
   3703  *                 note: this function sets the "WWW Authenticate" header and
   3704  *                 the caller should not set this header;
   3705  *                 the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3706  *                 code;
   3707  *                 the NULL is tolerated (the result is
   3708  *                 #MHD_SC_RESP_POINTER_NULL)
   3709  * @param realm the realm presented to the client
   3710  * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
   3711  *                    be added, indicating for client that UTF-8 encoding
   3712  *                    is preferred
   3713  * @return #MHD_SC_OK if succeed,
   3714  *         #MHD_SC_TOO_LATE if the response has been already "frozen" (used to
   3715  *         create an action),
   3716  *         #MHD_SC_RESP_HEADERS_CONFLICT if Basic Authentication "challenge"
   3717  *         has been added already,
   3718  *         #MHD_SC_RESP_POINTER_NULL if @a response is NULL,
   3719  *         #MHD_SC_RESP_HTTP_CODE_NOT_SUITABLE is response status code is wrong,
   3720  *         #MHD_SC_RESP_HEADER_VALUE_INVALID if realm is zero-length or has CR
   3721  *         or LF characters,
   3722  *         #MHD_SC_RESP_HEADER_MEM_ALLOC_FAILED if memory allocation failed,
   3723  *         or other error code if failed
   3724  * @ingroup authentication
   3725  */
   3726 MHD_EXTERN_ enum MHD_StatusCode
   3727 MHD_response_add_auth_basic_challenge (
   3728   struct MHD_Response *MHD_RESTRICT response,
   3729   const char *MHD_RESTRICT realm,
   3730   enum MHD_Bool prefer_utf8)
   3731 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2);
   3732 
   3733 /* Application may define MHD_NO_STATIC_INLINE macro before including
   3734    libmicrohttpd headers to disable static inline functions in the headers. */
   3735 #ifndef MHD_NO_STATIC_INLINE
   3736 
   3737 /**
   3738  * Create action to reply with Basic Authentication "challenge".
   3739  *
   3740  * The @a response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3741  *
   3742  * If access to any resource should be limited to specific users, authenticated
   3743  * by Basic Authentication mechanism, and the request for this resource does not
   3744  * have Basic Authentication information (see #MHD_AuthBasicCreds), then response
   3745  * with Basic Authentication "challenge" should be sent. This works as
   3746  * an indication that Basic Authentication should be used for the access.
   3747  *
   3748  * See RFC 7617, section 2 for details.
   3749  *
   3750  * @param request the request to create the action for
   3751  * @param realm the realm presented to the client
   3752  * @param prefer_utf8 if not set to #MHD_NO, parameter'charset="UTF-8"' will
   3753  *                    be added, indicating for client that UTF-8 encoding
   3754  *                    is preferred
   3755  * @param response the reply to send; should contain the "access denied"
   3756  *                 body;
   3757  *                 note: this function adds the "WWW Authenticate" header in
   3758  *                 the response and the caller should not set this header;
   3759  *                 the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3760  *                 code;
   3761  *                 the NULL is tolerated (the result is
   3762  *                 #MHD_action_abort_request())
   3763  * @param abort_if_failed if set to #MHD_NO the response will be used even if
   3764  *                        failed to add Basic Authentication "challenge",
   3765  *                        if not set to #MHD_NO the request will be aborted
   3766  *                        if the "challenge" could not be added.
   3767  * @return pointer to the action, the action must be consumed
   3768  *         otherwise response object may leak;
   3769  *         NULL if failed or if any action has been already created for
   3770  *         the @a request;
   3771  *         when failed the response object is consumed and need not
   3772  *         to be "destroyed"
   3773  * @ingroup authentication
   3774  */
   3775 MHD_STATIC_INLINE_
   3776 MHD_FN_PAR_NONNULL_ (1)
   3777 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2)
   3778 const struct MHD_Action *
   3779 MHD_action_basic_auth_challenge (struct MHD_Request *MHD_RESTRICT request,
   3780                                  const char *MHD_RESTRICT realm,
   3781                                  enum MHD_Bool prefer_utf8,
   3782                                  struct MHD_Response *MHD_RESTRICT response,
   3783                                  enum MHD_Bool abort_if_failed)
   3784 {
   3785   if ((MHD_SC_OK !=
   3786        MHD_response_add_auth_basic_challenge (response, realm, prefer_utf8))
   3787       && (MHD_NO != abort_if_failed))
   3788   {
   3789     MHD_response_destroy (response);
   3790     return MHD_action_abort_request (request);
   3791   }
   3792   return MHD_action_from_response (request, response);
   3793 }
   3794 
   3795 
   3796 MHD_STATIC_INLINE_END_
   3797 
   3798 
   3799 /**
   3800  * Create action to reply with Basic Authentication "challenge".
   3801  *
   3802  * The @a r response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3803  *
   3804  * If the @a r response object cannot be extended with the "challenge",
   3805  * the @a r response will be used to reply without the "challenge".
   3806  *
   3807  * @param rq the request to create the action for
   3808  * @param l the realm presented to the client
   3809  * @param u if not set to #MHD_NO, parameter'charset="UTF-8"' will
   3810  *          be added, indicating for client that UTF-8 encoding
   3811  *          is preferred
   3812  * @param r the reply to send; should contain the "access denied"
   3813  *          body;
   3814  *          note: this function adds the "WWW Authenticate" header in
   3815  *          the response and the caller should not set this header;
   3816  *          the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3817  *          code;
   3818  *          the NULL is tolerated (the result is
   3819  *          #MHD_action_abort_request())
   3820  * @return pointer to the action, the action must be consumed
   3821  *         otherwise response object may leak;
   3822  *         NULL if failed or if any action has been already created for
   3823  *         the @a rq request;
   3824  *         when failed the response object is consumed and need not
   3825  *         to be "destroyed"
   3826  * @ingroup authentication
   3827  */
   3828 #  define MHD_action_basic_auth_challenge_p(rq, l, u, r) \
   3829           MHD_action_basic_auth_challenge ((rq), (l), (u), (r), MHD_NO)
   3830 
   3831 /**
   3832  * Create action to reply with Basic Authentication "challenge".
   3833  *
   3834  * The @a r response must have #MHD_HTTP_STATUS_UNAUTHORIZED status code.
   3835  *
   3836  * If the @a r response object cannot be extended with the "challenge",
   3837  * the request will be aborted.
   3838  *
   3839  * @param rq the request to create the action for
   3840  * @param l the realm presented to the client
   3841  * @param u if not set to #MHD_NO, parameter'charset="UTF-8"' will
   3842  *          be added, indicating for client that UTF-8 encoding
   3843  *          is preferred
   3844  * @param r the reply to send; should contain the "access denied"
   3845  *          body;
   3846  *          note: this function adds the "WWW Authenticate" header in
   3847  *          the response and the caller should not set this header;
   3848  *          the response must have #MHD_HTTP_STATUS_UNAUTHORIZED status
   3849  *          code;
   3850  *          the NULL is tolerated (the result is
   3851  *          #MHD_action_abort_request())
   3852  * @return pointer to the action, the action must be consumed
   3853  *         otherwise response object may leak;
   3854  *         NULL if failed or if any action has been already created for
   3855  *         the @a rq request;
   3856  *         when failed the response object is consumed and need not
   3857  *         to be "destroyed"
   3858  * @ingroup authentication
   3859  */
   3860 #  define MHD_action_basic_auth_challenge_a(rq, l, u, r) \
   3861           MHD_action_basic_auth_challenge ((rq), (l), (u), (r), MHD_YES)
   3862 
   3863 #endif /* ! MHD_NO_STATIC_INLINE */
   3864 
   3865 
   3866 /**
   3867  * Information decoded from Basic Authentication client's header.
   3868  *
   3869  * @see #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS
   3870  */
   3871 struct MHD_AuthBasicCreds
   3872 {
   3873   /**
   3874    * The username
   3875    */
   3876   struct MHD_String username;
   3877 
   3878   /**
   3879    * The password, string pointer may be NULL if password is not encoded
   3880    * by the client.
   3881    */
   3882   struct MHD_StringNullable password;
   3883 };
   3884 
   3885 /* ********************** (f) Introspection ********************** */
   3886 
   3887 
   3888 /**
   3889  * Types of information about MHD, used by #MHD_lib_get_info_fixed_sz().
   3890  * This information is not changed at run-time.
   3891  */
   3892 enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoFixed
   3893 {
   3894   /* * Basic MHD information * */
   3895 
   3896   /**
   3897    * Get the MHD version as a number.
   3898    * The result is placed in @a v_version_num_uint32 member.
   3899    */
   3900   MHD_LIB_INFO_FIXED_VERSION_NUM = 0
   3901   ,
   3902   /**
   3903    * Get the MHD version as a string.
   3904    * The result is placed in @a v_version_string member.
   3905    */
   3906   MHD_LIB_INFO_FIXED_VERSION_STRING = 1
   3907   ,
   3908 
   3909   /* * Basic MHD features, buid-time configurable * */
   3910   /* These features should be always available unless the library was
   3911    * not compiled specifically for some embedded project.
   3912    * Exceptions are marked explicitly in the description. */
   3913 
   3914   /**
   3915    * Get whether messages are supported. If supported then messages can be
   3916    * printed to stderr or to an external logger.
   3917    * The result is placed in @a v_support_log_messages_bool member.
   3918    */
   3919   MHD_LIB_INFO_FIXED_SUPPORT_LOG_MESSAGES = 11
   3920   ,
   3921   /**
   3922    * Get whether detailed automatic HTTP reply messages are supported.
   3923    * If supported then automatic responses have bodies with text explaining
   3924    * the error details.
   3925    * Automatic responses are sent by MHD automatically when client is violating
   3926    * HTTP specification, for example, the request header has whitespace in
   3927    * header name or request's "Content-Length" header has non-number value.
   3928    * The result is placed in @a v_support_auto_replies_bodies_bool member.
   3929    */
   3930   MHD_LIB_INFO_FIXED_SUPPORT_AUTO_REPLIES_BODIES = 12
   3931   ,
   3932   /**
   3933    * Get whether MHD was built with debug asserts disabled.
   3934    * These asserts enabled only on special debug builds.
   3935    * For debug builds the error log is always enabled.
   3936    * The result is placed in @a v_is_non_debug_bool member.
   3937    */
   3938   MHD_LIB_INFO_FIXED_IS_NON_DEBUG = 13
   3939   ,
   3940   /**
   3941    * Get whether MHD supports threads.
   3942    * The result is placed in @a v_support_threads_bool member.
   3943    */
   3944   MHD_LIB_INFO_FIXED_SUPPORT_THREADS = 14
   3945   ,
   3946   /**
   3947    * Get whether automatic parsing of HTTP Cookie header is supported.
   3948    * If disabled, no #MHD_VK_COOKIE will be generated by MHD.
   3949    * The result is placed in @a v_support_cookie_parser_bool member.
   3950    */
   3951   MHD_LIB_INFO_FIXED_SUPPORT_COOKIE_PARSER = 15
   3952   ,
   3953   /**
   3954    * Get whether postprocessor is supported. If supported then
   3955    * #MHD_action_post_processor() can be used.
   3956    * The result is placed in @a v_support_post_parser_bool member.
   3957    */
   3958   MHD_LIB_INFO_FIXED_SUPPORT_POST_PARSER = 16
   3959   ,
   3960   /**
   3961    * Get whether HTTP "Upgrade" is supported.
   3962    * If supported then #MHD_action_upgrade() can be used.
   3963    * The result is placed in @a v_support_upgrade_bool member.
   3964    */
   3965   MHD_LIB_INFO_FIXED_SUPPORT_UPGRADE = 17
   3966   ,
   3967   /**
   3968    * Get whether HTTP Basic authorization is supported. If supported
   3969    * then functions #MHD_action_basic_auth_required_response ()
   3970    * and #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS can be used.
   3971    * The result is placed in @a v_support_auth_basic_bool member.
   3972    */
   3973   MHD_LIB_INFO_FIXED_SUPPORT_AUTH_BASIC = 20
   3974   ,
   3975   /**
   3976    * Get whether HTTP Digest authorization is supported. If
   3977    * supported then options #MHD_D_O_RANDOM_ENTROPY,
   3978    * #MHD_D_O_DAUTH_MAP_SIZE and functions
   3979    * #MHD_action_digest_auth_required_response () and
   3980    * #MHD_digest_auth_check() can be used.
   3981    * The result is placed in @a v_support_auth_digest_bool member.
   3982    */
   3983   MHD_LIB_INFO_FIXED_SUPPORT_AUTH_DIGEST = 21
   3984   ,
   3985   /**
   3986    * Get whether the early version the Digest Authorization (RFC 2069) is
   3987    * supported (digest authorisation without QOP parameter).
   3988    * Currently it is always supported if Digest Auth module is built.
   3989    * The result is placed in @a v_support_digest_auth_rfc2069_bool member.
   3990    */
   3991   MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_RFC2069 = 22
   3992   ,
   3993   /**
   3994    * Get whether the MD5-based hashing algorithms are supported for Digest
   3995    * Authorization and the type of the implementation if supported.
   3996    * Currently it is always supported if Digest Auth module is built
   3997    * unless manually disabled in a custom build.
   3998    * The result is placed in @a v_type_digest_auth_md5_algo_type member.
   3999    */
   4000   MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_MD5 = 23
   4001   ,
   4002   /**
   4003    * Get whether the SHA-256-based hashing algorithms are supported for Digest
   4004    * Authorization and the type of the implementation if supported.
   4005    * Currently it is always supported if Digest Auth module is built
   4006    * unless manually disabled in a custom build.
   4007    * The result is placed in @a v_type_digest_auth_sha256_algo_type member.
   4008    */
   4009   MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_SHA256 = 24
   4010   ,
   4011   /**
   4012    * Get whether the SHA-512/256-based hashing algorithms are supported
   4013    * Authorization and the type of the implementation if supported.
   4014    * Currently it is always supported if Digest Auth module is built
   4015    * unless manually disabled in a custom build.
   4016    * The result is placed in @a v_type_digest_auth_sha512_256_algo_type member.
   4017    */
   4018   MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_SHA512_256 = 25
   4019   ,
   4020   /**
   4021    * Get whether QOP with value 'auth-int' (authentication with integrity
   4022    * protection) is supported for Digest Authorization.
   4023    * Currently it is always not supported.
   4024    * The result is placed in @a v_support_digest_auth_auth_int_bool member.
   4025    */
   4026   MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_AUTH_INT = 28
   4027   ,
   4028   /**
   4029    * Get whether 'session' algorithms (like 'MD5-sess') are supported for Digest
   4030    * Authorization.
   4031    * Currently it is always not supported.
   4032    * The result is placed in @a v_support_digest_auth_algo_session_bool member.
   4033    */
   4034   MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_ALGO_SESSION = 29
   4035   ,
   4036   /**
   4037    * Get whether 'userhash' is supported for Digest Authorization.
   4038    * Currently it is always supported if Digest Auth module is built.
   4039    * The result is placed in @a v_support_digest_auth_userhash_bool member.
   4040    */
   4041   MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_USERHASH = 30
   4042   ,
   4043 
   4044   /* * Platform-dependent features, some are configurable at build-time * */
   4045   /* These features depends on the platform, third-party libraries and
   4046    * the toolchain.
   4047    * Some of the features can be disabled or selected at build-time. */
   4048   /**
   4049    * Get sockets polling functions/techniques supported by this MHD build.
   4050    * Some functions can be disabled (like epoll) in kernel, this is not
   4051    * checked.
   4052    * The result is placed in @a v_types_sockets_polling member.
   4053    */
   4054   MHD_LIB_INFO_FIXED_TYPES_SOCKETS_POLLING = 60
   4055   ,
   4056   /**
   4057    * Get whether aggregate FD external polling is supported.
   4058    * The result is placed in @a v_support_aggregate_fd_bool member.
   4059    */
   4060   MHD_LIB_INFO_FIXED_SUPPORT_AGGREGATE_FD = 61
   4061   ,
   4062   /**
   4063    * Get whether IPv6 is supported on the platform and IPv6-only listen socket
   4064    * can be used.
   4065    * The result is placed in @a v_ipv6 member.
   4066    * @note The platform may have disabled IPv6 at run-time, it is not checked
   4067    *       by this information type.
   4068    */
   4069   MHD_LIB_INFO_FIXED_TYPE_IPV6 = 62
   4070   ,
   4071   /**
   4072    * Get whether TCP Fast Open is supported by MHD build.
   4073    * If supported then option #MHD_D_O_TCP_FASTOPEN can be used.
   4074    * The result is placed in @a v_support_tcp_fastopen_bool member.
   4075    */
   4076   MHD_LIB_INFO_FIXED_SUPPORT_TCP_FASTOPEN = 64
   4077   ,
   4078   /**
   4079    * Get whether MHD support automatic detection of bind port number.
   4080    * @sa #MHD_D_O_BIND_PORT
   4081    * The result is placed in @a v_has_autodetect_bind_port_bool member.
   4082    */
   4083   MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT = 65
   4084   ,
   4085   /**
   4086    * Get whether MHD use system's sendfile() function to send
   4087    * file-FD based responses over non-TLS connections.
   4088    * The result is placed in @a v_has_sendfile_bool member.
   4089    */
   4090   MHD_LIB_INFO_FIXED_HAS_SENDFILE = 66
   4091   ,
   4092   /**
   4093    * Get whether MHD supports automatic SIGPIPE suppression within internal
   4094    * events loop (MHD's managed threads).
   4095    * If SIGPIPE suppression is not supported, application must handle
   4096    * SIGPIPE signal by itself whem using MHD with internal events loop.
   4097    * If the platform does not have SIGPIPE the result is #MHD_YES.
   4098    * The result is placed in @a v_has_autosuppress_sigpipe_int_bool member.
   4099    */
   4100   MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_INT = 80
   4101   ,
   4102   /**
   4103    * Get whether MHD supports automatic SIGPIPE suppression when used with
   4104    * extenal events loop (in application thread).
   4105    * If SIGPIPE suppression is not supported, application must handle
   4106    * SIGPIPE signal by itself whem using MHD with external events loop.
   4107    * If the platform does not have SIGPIPE the result is #MHD_YES.
   4108    * The result is placed in @a v_has_autosuppress_sigpipe_ext_bool member.
   4109    */
   4110   MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_EXT = 81
   4111   ,
   4112   /**
   4113    * Get whether MHD sets names on generated threads.
   4114    * The result is placed in @a v_has_thread_names_bool member.
   4115    */
   4116   MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES = 82
   4117   ,
   4118   /**
   4119    * Get the type of supported inter-thread communication.
   4120    * The result is placed in @a v_type_itc member.
   4121    */
   4122   MHD_LIB_INFO_FIXED_TYPE_ITC = 83
   4123   ,
   4124   /**
   4125    * Get whether reading files beyond 2 GiB boundary is supported.
   4126    * If supported then #MHD_response_from_fd() can be used with sizes and
   4127    * offsets larger than 2 GiB. If not supported value of size+offset could be
   4128    * limited to 2 GiB.
   4129    * The result is placed in @a v_support_large_file_bool member.
   4130    */
   4131   MHD_LIB_INFO_FIXED_SUPPORT_LARGE_FILE = 84
   4132   ,
   4133 
   4134   /* * Platform-dependent features, some set on startup and some are
   4135    *   configurable at build-time * */
   4136   /* These features depends on the platform, third-party libraries availability
   4137    * and configuration. The features can be enabled/disabled during startup
   4138    * of the library depending on conditions.
   4139    * Some of the features can be disabled or selected at build-time. */
   4140   /**
   4141    * Get whether HTTPS and which types of TLS backend(s) supported by
   4142    * this build.
   4143    * The result is placed in @a v_tls_backends member.
   4144    */
   4145   MHD_LIB_INFO_FIXED_TLS_BACKENDS = 100
   4146   ,
   4147   /**
   4148   * Get whether password encrypted private key for HTTPS daemon is
   4149   * supported by TLS backends.
   4150   * If supported then option #MHD_D_OPTION_TLS_KEY_CERT can be used with
   4151   * non-NULL @a mem_pass.
   4152   * The result is placed in @a v_tls_key_password_backends member.
   4153   */
   4154   MHD_LIB_INFO_FIXED_TLS_KEY_PASSWORD_BACKENDS = 102
   4155   ,
   4156 
   4157   /* * Sentinel * */
   4158   /**
   4159    * The sentinel value.
   4160    * This value enforces specific underlying integer type for the enum.
   4161    * Do not use.
   4162    */
   4163   MHD_LIB_INFO_FIXED_SENTINEL = 65535
   4164 };
   4165 
   4166 /**
   4167  * The type of the data for digest algorithm implementations.
   4168  */
   4169 enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedDigestAlgoType
   4170 {
   4171   /**
   4172    * The algorithm is not implemented or disabled at the build time.
   4173    */
   4174   MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_NOT_AVAILABLE = 0
   4175   ,
   4176   /**
   4177    * The algorithm is implemented by MHD internal code.
   4178    * MHD implementation of hashing can never fail.
   4179    */
   4180   MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_BUILT_IN = 1
   4181   ,
   4182   /**
   4183    * The algorithm is implemented by external code that never fails.
   4184    */
   4185   MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_NEVER_FAIL = 2
   4186   ,
   4187   /**
   4188    * The algorithm is implemented by external code that may hypothetically fail.
   4189    */
   4190   MHD_LIB_INFO_FIXED_DIGEST_ALGO_TYPE_EXTERNAL_MAY_FAIL = 3
   4191 };
   4192 
   4193 /**
   4194  * The types of the sockets polling functions/techniques supported
   4195  */
   4196 struct MHD_LibInfoFixedPollingFunc
   4197 {
   4198   /**
   4199    * select() function for sockets polling
   4200    */
   4201   enum MHD_Bool func_select;
   4202   /**
   4203    * poll() function for sockets polling
   4204    */
   4205   enum MHD_Bool func_poll;
   4206   /**
   4207    * epoll technique for sockets polling
   4208    */
   4209   enum MHD_Bool tech_epoll;
   4210   /**
   4211    * kqueue technique for sockets polling
   4212    */
   4213   enum MHD_Bool tech_kqueue;
   4214 };
   4215 
   4216 /**
   4217  * The types of IPv6 supported
   4218  */
   4219 enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedIPv6Type
   4220 {
   4221   /**
   4222    * IPv6 is not supported by this MHD build
   4223    */
   4224   MHD_LIB_INFO_FIXED_IPV6_TYPE_NONE = 0
   4225   ,
   4226   /**
   4227    * IPv6 is supported only as "dual stack".
   4228    * IPv4 connections can be received by IPv6 listen socket.
   4229    */
   4230   MHD_LIB_INFO_FIXED_IPV6_TYPE_DUAL_ONLY = 1
   4231   ,
   4232   /**
   4233    * IPv6 can be used as IPv6-only (without getting IPv4 incoming connections).
   4234    * The platform may support "dual stack" too.
   4235    */
   4236   MHD_LIB_INFO_FIXED_IPV6_TYPE_IPV6_PURE = 2
   4237 };
   4238 
   4239 /**
   4240  * The types of inter-thread communication
   4241  * @note the enum can be extended in future versions with new values
   4242  */
   4243 enum MHD_FIXED_ENUM_MHD_SET_ MHD_LibInfoFixedITCType
   4244 {
   4245   /**
   4246    * No ITC used.
   4247    * This value is returned if MHD is built without threads support
   4248    */
   4249   MHD_LIB_INFO_FIXED_ITC_TYPE_NONE = 0
   4250   ,
   4251   /**
   4252    * The pair of sockets are used as inter-thread communication.
   4253    * The is the least efficient method of communication.
   4254    */
   4255   MHD_LIB_INFO_FIXED_ITC_TYPE_SOCKETPAIR = 1
   4256   ,
   4257   /**
   4258    * The pipe is used as inter-thread communication.
   4259    */
   4260   MHD_LIB_INFO_FIXED_ITC_TYPE_PIPE = 2
   4261   ,
   4262   /**
   4263    * The EventFD is used as inter-thread communication.
   4264    * This is the most efficient method of communication.
   4265    */
   4266   MHD_LIB_INFO_FIXED_ITC_TYPE_EVENTFD = 3
   4267 };
   4268 
   4269 
   4270 /**
   4271  * The types of the TLS (or TLS feature) backend supported/available/enabled
   4272  * @note the enum can be extended in future versions with new members
   4273  */
   4274 struct MHD_LibInfoTLSType
   4275 {
   4276   /**
   4277    * The TLS (or TLS feature) is supported/enabled.
   4278    * Set to #MHD_YES if any other member is #MHD_YES.
   4279    */
   4280   enum MHD_Bool tls_supported;
   4281   /**
   4282    * The GnuTLS backend is supported/available/enabled.
   4283    */
   4284   enum MHD_Bool backend_gnutls;
   4285   /**
   4286    * The OpenSSL backend is supported/available/enabled.
   4287    */
   4288   enum MHD_Bool backend_openssl;
   4289   /**
   4290    * The MbedTLS backend is supported/available/enabled.
   4291    */
   4292   enum MHD_Bool backend_mbedtls;
   4293 };
   4294 
   4295 /**
   4296  * The data provided by #MHD_lib_get_info_fixed_sz()
   4297  */
   4298 union MHD_LibInfoFixedData
   4299 {
   4300   /**
   4301    * The data for the #MHD_LIB_INFO_FIXED_VERSION_NUM query
   4302    */
   4303   uint_fast32_t v_version_num_uint32;
   4304   /**
   4305    * The data for the #MHD_LIB_INFO_FIXED_VERSION_STR query
   4306    */
   4307   struct MHD_String v_version_string;
   4308   /**
   4309    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_LOG_MESSAGES query
   4310    */
   4311   enum MHD_Bool v_support_log_messages_bool;
   4312   /**
   4313    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_AUTO_REPLIES_BODIES query
   4314    */
   4315   enum MHD_Bool v_support_auto_replies_bodies_bool;
   4316   /**
   4317    * The data for the #MHD_LIB_INFO_FIXED_IS_NON_DEBUG query
   4318    */
   4319   enum MHD_Bool v_is_non_debug_bool;
   4320   /**
   4321    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_THREADS query
   4322    */
   4323   enum MHD_Bool v_support_threads_bool;
   4324   /**
   4325    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_COOKIE_PARSER query
   4326    */
   4327   enum MHD_Bool v_support_cookie_parser_bool;
   4328   /**
   4329    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_POST_PARSER query
   4330    */
   4331   enum MHD_Bool v_support_post_parser_bool;
   4332   /**
   4333    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_UPGRADE query
   4334    */
   4335   enum MHD_Bool v_support_upgrade_bool;
   4336   /**
   4337    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_AUTH_BASIC query
   4338    */
   4339   enum MHD_Bool v_support_auth_basic_bool;
   4340   /**
   4341    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_AUTH_DIGEST query
   4342    */
   4343   enum MHD_Bool v_support_auth_digest_bool;
   4344   /**
   4345    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_RFC2069 query
   4346    */
   4347   enum MHD_Bool v_support_digest_auth_rfc2069_bool;
   4348   /**
   4349    * The data for the #MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_MD5 query
   4350    */
   4351   enum MHD_LibInfoFixedDigestAlgoType v_type_digest_auth_md5_algo_type;
   4352   /**
   4353    * The data for the #MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_SHA256 query
   4354    */
   4355   enum MHD_LibInfoFixedDigestAlgoType v_type_digest_auth_sha256_algo_type;
   4356   /**
   4357    * The data for the #MHD_LIB_INFO_FIXED_TYPE_DIGEST_AUTH_SHA512_256 query
   4358    */
   4359   enum MHD_LibInfoFixedDigestAlgoType v_type_digest_auth_sha512_256_algo_type;
   4360   /**
   4361    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_AUTH_INT query
   4362    */
   4363   enum MHD_Bool v_support_digest_auth_auth_int_bool;
   4364   /**
   4365    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_ALGO_SESSION query
   4366    */
   4367   enum MHD_Bool v_support_digest_auth_algo_session_bool;
   4368   /**
   4369    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_DIGEST_AUTH_USERHASH query
   4370    */
   4371   enum MHD_Bool v_support_digest_auth_userhash_bool;
   4372   /**
   4373    * The data for the #MHD_LIB_INFO_FIXED_TYPES_SOCKETS_POLLING query
   4374    */
   4375   struct MHD_LibInfoFixedPollingFunc v_types_sockets_polling;
   4376   /**
   4377    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_AGGREGATE_FD query
   4378    */
   4379   enum MHD_Bool v_support_aggregate_fd_bool;
   4380   /**
   4381    * The data for the #MHD_LIB_INFO_FIXED_TYPE_IPV6 query
   4382    */
   4383   enum MHD_LibInfoFixedIPv6Type v_ipv6;
   4384   /**
   4385    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_TCP_FASTOPEN query
   4386    */
   4387   enum MHD_Bool v_support_tcp_fastopen_bool;
   4388   /**
   4389    * The data for the #MHD_LIB_INFO_FIXED_HAS_AUTODETECT_BIND_PORT query
   4390    */
   4391   enum MHD_Bool v_has_autodetect_bind_port_bool;
   4392   /**
   4393    * The data for the #MHD_LIB_INFO_FIXED_HAS_SENDFILE query
   4394    */
   4395   enum MHD_Bool v_has_sendfile_bool;
   4396   /**
   4397    * The data for the #MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_INT query
   4398    */
   4399   enum MHD_Bool v_has_autosuppress_sigpipe_int_bool;
   4400   /**
   4401    * The data for the #MHD_LIB_INFO_FIXED_HAS_AUTOSUPPRESS_SIGPIPE_EXT query
   4402    */
   4403   enum MHD_Bool v_has_autosuppress_sigpipe_ext_bool;
   4404   /**
   4405    * The data for the #MHD_LIB_INFO_FIXED_HAS_THREAD_NAMES query
   4406    */
   4407   enum MHD_Bool v_has_thread_names_bool;
   4408   /**
   4409    * The data for the #MHD_LIB_INFO_FIXED_TYPE_ITC query
   4410    */
   4411   enum MHD_LibInfoFixedITCType v_type_itc;
   4412   /**
   4413    * The data for the #MHD_LIB_INFO_FIXED_SUPPORT_LARGE_FILE query
   4414    */
   4415   enum MHD_Bool v_support_large_file_bool;
   4416   /**
   4417    * The data for the #MHD_LIB_INFO_FIXED_TLS_BACKENDS query
   4418    */
   4419   struct MHD_LibInfoTLSType v_tls_backends;
   4420   /**
   4421    * The data for the #MHD_LIB_INFO_FIXED_TLS_KEY_PASSWORD_BACKENDS query
   4422    */
   4423   struct MHD_LibInfoTLSType v_tls_key_password_backends;
   4424 };
   4425 
   4426 /**
   4427  * Get fixed information about MHD that is not changed at run-time.
   4428  * The returned information can be cached by application as it will be not
   4429  * changed at run-time.
   4430  *
   4431  * For any valid @a info_type the only possible returned error value is
   4432  * #MHD_SC_INFO_GET_BUFF_TOO_SMALL. If the buffer is large enough and
   4433  * the requested type of information is valid, the function always succeeds
   4434  * and returns #MHD_SC_OK.
   4435  *
   4436  * The wrapper macro #MHD_lib_get_info_fixed() may be more convenient.
   4437  *
   4438  * @param info_type the type of requested information
   4439  * @param[out] output_buf the pointer to union to be set to the requested
   4440  *                        information
   4441  * @param output_buf_size the size of the memory area pointed by @a output_buf
   4442  *                        (provided by the caller for storing the requested
   4443  *                        information), in bytes
   4444  * @return #MHD_SC_OK if succeed,
   4445  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4446  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small
   4447  * @ingroup specialized
   4448  */
   4449 MHD_EXTERN_ enum MHD_StatusCode
   4450 MHD_lib_get_info_fixed_sz (enum MHD_LibInfoFixed info_type,
   4451                            union MHD_LibInfoFixedData *MHD_RESTRICT output_buf,
   4452                            size_t output_buf_size)
   4453 MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2);
   4454 
   4455 /**
   4456  * Get fixed information about MHD that is not changed at run-time.
   4457  * The returned information can be cached by application as it will be not
   4458  * changed at run-time.
   4459  *
   4460  * @param info the type of requested information
   4461  * @param[out] output_buf the pointer to union to be set to the requested
   4462  *                        information
   4463  * @return #MHD_SC_OK if succeed,
   4464  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4465  *         or other error code
   4466  * @ingroup specialized
   4467  */
   4468 #define MHD_lib_get_info_fixed(info, output_buf) \
   4469         MHD_lib_get_info_fixed_sz ((info),(output_buf),sizeof(*(output_buf)))
   4470 
   4471 /* Application may define MHD_NO_STATIC_INLINE macro before including
   4472    libmicrohttpd headers to disable static inline functions in the headers. */
   4473 #ifndef MHD_NO_STATIC_INLINE
   4474 
   4475 /*
   4476  * A helper below can be used in a simple check preventing use of downgraded
   4477  * library version.
   4478  * As new library version may introduce new functionality, and the application
   4479  * may detect some functionality available at application build-time, use of
   4480  * previous versions may lead to run-time failures.
   4481  * To prevent run-time failures, application may use a check like:
   4482 
   4483  if (MHD_lib_get_info_ver_num() < ((uint_fast32_t) MHD_VERSION))
   4484    handle_init_failure();
   4485 
   4486  */
   4487 /**
   4488  * Get the library version number.
   4489  * @return the library version number.
   4490  */
   4491 MHD_STATIC_INLINE_ MHD_FN_PURE_ uint_fast32_t
   4492 MHD_lib_get_info_ver_num (void)
   4493 {
   4494   union MHD_LibInfoFixedData data;
   4495   data.v_version_num_uint32 = 0; /* Not really necessary */
   4496   (void)MHD_lib_get_info_fixed (MHD_LIB_INFO_FIXED_VERSION_NUM, \
   4497                                 &data);  /* Never fail */
   4498   return data.v_version_num_uint32;
   4499 }
   4500 
   4501 
   4502 MHD_STATIC_INLINE_END_
   4503 
   4504 #endif /* ! MHD_NO_STATIC_INLINE */
   4505 
   4506 /**
   4507  * Types of information about MHD, used by #MHD_lib_get_info_dynamic_sz().
   4508  * This information may vary over time.
   4509  */
   4510 enum MHD_FIXED_ENUM_APP_SET_ MHD_LibInfoDynamic
   4511 {
   4512   /* * Basic MHD information * */
   4513 
   4514   /**
   4515    * Get whether MHD has been successfully fully initialised.
   4516    * MHD uses lazy initialisation: a minimal initialisation is performed at
   4517    * startup, complete initialisation is performed when any daemon is created
   4518    * (or when called some function which requires full initialisation).
   4519    * The result is #MHD_NO when the library has been not yet initialised
   4520    * completely since startup.
   4521    * The result is placed in @a v_inited_fully_once_bool member.
   4522    */
   4523   MHD_LIB_INFO_DYNAMIC_INITED_FULLY_ONCE = 0
   4524   ,
   4525   /**
   4526    * Get whether MHD is fully initialised.
   4527    * MHD uses lazy initialisation: a minimal initialisation is performed at
   4528    * startup, complete initialisation is perfromed when any daemon is created
   4529    * (or when called some function which requires full initialisation).
   4530    * The result is #MHD_YES if library is initialised state now (meaning
   4531    * that at least one daemon is created and not destroyed or some function
   4532    * required full initialisation is running).
   4533    * The result is placed in @a v_inited_fully_now_bool member.
   4534    */
   4535   MHD_LIB_INFO_DYNAMIC_INITED_FULLY_NOW = 1
   4536   ,
   4537 
   4538   /**
   4539    * Get whether HTTPS and which types of TLS backend(s) currently available.
   4540    * If any MHD daemons active (created and not destroyed, not necessary
   4541    * running) the result reflects the current backends availability.
   4542    * If no MHD daemon is active, then this function would try to temporarily
   4543    * enable backends to check for their availability.
   4544    * If global library initialisation failed, the function returns
   4545    * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE error code.
   4546    * The result is placed in @a v_tls_backends member.
   4547    */
   4548   MHD_LIB_INFO_DYNAMIC_TYPE_TLS = 100
   4549   ,
   4550 
   4551   /* * Sentinel * */
   4552   /**
   4553    * The sentinel value.
   4554    * This value enforces specific underlying integer type for the enum.
   4555    * Do not use.
   4556    */
   4557   MHD_LIB_INFO_DYNAMIC_SENTINEL = 65535
   4558 };
   4559 
   4560 
   4561 /**
   4562  * The data provided by #MHD_lib_get_info_dynamic_sz().
   4563  * The resulting value may vary over time.
   4564  */
   4565 union MHD_LibInfoDynamicData
   4566 {
   4567   /**
   4568    * The data for the #MHD_LIB_INFO_DYNAMIC_INITED_FULLY_ONCE query
   4569    */
   4570   enum MHD_Bool v_inited_fully_once_bool;
   4571 
   4572   /**
   4573    * The data for the #MHD_LIB_INFO_DYNAMIC_INITED_FULLY_NOW query
   4574    */
   4575   enum MHD_Bool v_inited_fully_now_bool;
   4576 
   4577   /**
   4578    * The data for the #MHD_LIB_INFO_DYNAMIC_TYPE_TLS query
   4579    */
   4580   struct MHD_LibInfoTLSType v_tls_backends;
   4581 
   4582   /**
   4583    * Unused member.
   4584    * Help enforcing future-proof alignment of the union.
   4585    * Do not use.
   4586    */
   4587   void *reserved;
   4588 };
   4589 
   4590 /**
   4591  * Get dynamic information about MHD that may be changed at run-time.
   4592  * The wrapper macro #MHD_lib_get_info_dynamic() could be more convenient.
   4593  *
   4594  * @param info_type the type of requested information
   4595  * @param[out] output_buf the pointer to union to be set to the requested
   4596  *                        information
   4597  * @param output_buf_size the size of the memory area pointed by @a output_buf
   4598  *                        (provided by the caller for storing the requested
   4599  *                        information), in bytes
   4600  * @return #MHD_SC_OK if succeed,
   4601  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4602  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   4603  *         or other error code
   4604  * @ingroup specialized
   4605  */
   4606 MHD_EXTERN_ enum MHD_StatusCode
   4607 MHD_lib_get_info_dynamic_sz (
   4608   enum MHD_LibInfoDynamic info_type,
   4609   union MHD_LibInfoDynamicData *MHD_RESTRICT output_buf,
   4610   size_t output_buf_size)
   4611 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_OUT_ (2);
   4612 
   4613 /**
   4614  * Get dynamic information about MHD that may be changed at run-time.
   4615  *
   4616  * @param info the type of requested information
   4617  * @param[out] output_buf the pointer to union to be set to the requested
   4618  *                        information
   4619  * @return #MHD_SC_OK if succeed,
   4620  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4621  *         or other error code
   4622  * @ingroup specialized
   4623  */
   4624 #define MHD_lib_get_info_dynamic(info, output_buf) \
   4625         MHD_lib_get_info_dynamic_sz ((info),(output_buf),sizeof(*(output_buf)))
   4626 
   4627 
   4628 /**
   4629  * Values of this enum are used to specify what information about a daemon is
   4630  * requested.
   4631  * These types of information do not change after the start of the daemon
   4632  * until the daemon is destroyed.
   4633  */
   4634 enum MHD_DaemonInfoFixedType
   4635 {
   4636 
   4637   /**
   4638    * Get the type of system call used for sockets polling.
   4639    * The value #MHD_SPS_AUTO is never set in the returned data.
   4640    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon
   4641    * does not use internal sockets polling.
   4642    * The result is placed in @a v_poll_syscall member.
   4643    */
   4644   MHD_DAEMON_INFO_FIXED_POLL_SYSCALL = 41
   4645   ,
   4646   /**
   4647    * Get the file descriptor for the single FD that triggered when
   4648    * any MHD event happens.
   4649    * This FD can be watched as aggregate indicator for all MHD events.
   4650    * The provided socket must be used as 'read-only': only select() or similar
   4651    * functions should be used. Any modifications (changing socket attributes,
   4652    * calling accept(), closing it etc.) will lead to undefined behaviour.
   4653    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_SUPP_BY_BUILD if the library
   4654    * does not support mode with agregate FD.
   4655    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon
   4656    * is not configured to use this mode.
   4657    * The result is placed in @a v_aggreagate_fd member.
   4658    */
   4659   MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD = 46
   4660   ,
   4661   /**
   4662    * Get the number of worker threads when used in MHD_WM_WORKER_THREADS mode.
   4663    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon
   4664    * does not use worker threads mode.
   4665    * The result is placed in @a v_num_work_threads_uint member.
   4666    */
   4667   MHD_DAEMON_INFO_FIXED_NUM_WORK_THREADS = 47
   4668   ,
   4669   /**
   4670    * Get the port number of daemon's listen socket.
   4671    * Note: if port '0' (auto port) was specified for #MHD_D_OPTION_BIND_PORT(),
   4672    * returned value will be the real port number.
   4673    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon
   4674    * does not have listening socket or if listening socket is non-IP.
   4675    * The function returns #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the port number
   4676    * detection failed or not supported by the platform.
   4677    * If the function succeed, the returned port number is never zero.
   4678    * The result is placed in @a v_bind_port_uint16 member.
   4679    */
   4680   MHD_DAEMON_INFO_FIXED_BIND_PORT = 80
   4681   ,
   4682   /**
   4683    * Get the file descriptor for the listening socket.
   4684    * The provided socket must be used as 'read-only': only select() or similar
   4685    * functions should be used. Any modifications (changing socket attributes,
   4686    * calling accept(), closing it etc.) will lead to undefined behaviour.
   4687    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon
   4688    * does not have listening socket.
   4689    * The result is placed in @a v_listen_socket member.
   4690    */
   4691   MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET = 82
   4692   ,
   4693   /**
   4694    * Get the TLS backend used by the daemon.
   4695    * The value #MHD_TLS_BACKEND_ANY is never set in the returned data.
   4696    * The value #MHD_TLS_BACKEND_NONE is set if the daemon does not use TLS.
   4697    * If MHD built without TLS support then #MHD_TLS_BACKEND_NONE is always set.
   4698    * The result is placed in @a v_tls_backend member.
   4699    */
   4700   MHD_DAEMON_INFO_FIXED_TLS_BACKEND = 120
   4701   ,
   4702   /**
   4703    * Get the default inactivity timeout for connections in milliseconds.
   4704    * The result is placed in @a v_default_timeout_milsec_uint32 member.
   4705    */
   4706   MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC = 160
   4707   ,
   4708   /**
   4709    * Get the limit of number of simutaneous network connections served by
   4710    * the daemon.
   4711    * The result is placed in @a v_global_connection_limit_uint member.
   4712    */
   4713   MHD_DAEMON_INFO_FIXED_GLOBAL_CONNECTION_LIMIT = 161
   4714   ,
   4715   /**
   4716    * Get the limit of number of simutaneous network connections served by
   4717    * the daemon for any single IP address.
   4718    * The result is placed in @a v_per_ip_limit_uint member.
   4719    */
   4720   MHD_DAEMON_INFO_FIXED_PER_IP_LIMIT = 162
   4721   ,
   4722   /**
   4723    * Get the setting for suppression of the 'Date:' header in replies.
   4724    * The result is placed in @a v_suppress_date_header_bool member.
   4725    */
   4726   MHD_DAEMON_INFO_FIXED_SUPPRESS_DATE_HEADER = 240
   4727   ,
   4728   /**
   4729    * Get the size of buffer unsed per connection.
   4730    * The result is placed in @a v_conn_memory_limit_sizet member.
   4731    */
   4732   MHD_DAEMON_INFO_FIXED_CONN_MEMORY_LIMIT = 280
   4733   ,
   4734   /**
   4735    * Get the limit of maximum FD value for the daemon.
   4736    * The daemon rejects (closes) any sockets with FD equal or higher
   4737    * the resulting number.
   4738    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon
   4739    * is built for W32.
   4740    * The result is placed in @a v_fd_number_limit_uint member.
   4741    */
   4742   MHD_DAEMON_INFO_FIXED_FD_NUMBER_LIMIT = 283
   4743   ,
   4744 
   4745   /* * Sentinel * */
   4746   /**
   4747    * The sentinel value.
   4748    * This value enforces specific underlying integer type for the enum.
   4749    * Do not use.
   4750    */
   4751   MHD_DAEMON_INFO_FIXED_SENTINEL = 65535
   4752 
   4753 };
   4754 
   4755 
   4756 /**
   4757  * Information about an MHD daemon.
   4758  */
   4759 union MHD_DaemonInfoFixedData
   4760 {
   4761   /**
   4762    * The data for the #MHD_DAEMON_INFO_FIXED_POLL_SYSCALL query
   4763    */
   4764   enum MHD_SockPollSyscall v_poll_syscall;
   4765 
   4766   /**
   4767    * The data for the #MHD_DAEMON_INFO_FIXED_NUM_WORK_THREADS query
   4768    */
   4769   unsigned int v_num_work_threads_uint;
   4770 
   4771   /**
   4772    * The data for the #MHD_DAEMON_INFO_FIXED_BIND_PORT query
   4773    */
   4774   uint_least16_t v_bind_port_uint16;
   4775 
   4776   /**
   4777    * The data for the #MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET query
   4778    */
   4779   MHD_Socket v_listen_socket;
   4780 
   4781   /**
   4782    * The data for the #MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD query
   4783    */
   4784   int v_aggreagate_fd;
   4785 
   4786   /**
   4787    * The data for the #MHD_DAEMON_INFO_FIXED_TLS_BACKEND query
   4788    */
   4789   enum MHD_TlsBackend v_tls_backend;
   4790 
   4791   /**
   4792    * The data for the #MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC query
   4793    */
   4794   uint_fast32_t v_default_timeout_milsec_uint32;
   4795 
   4796   /**
   4797    * The data for the #MHD_DAEMON_INFO_FIXED_GLOBAL_CONNECTION_LIMIT query
   4798    */
   4799   unsigned int v_global_connection_limit_uint;
   4800 
   4801   /**
   4802    * The data for the #MHD_DAEMON_INFO_FIXED_PER_IP_LIMIT query
   4803    */
   4804   unsigned int v_per_ip_limit_uint;
   4805 
   4806   /**
   4807    * The data for the #MHD_DAEMON_INFO_FIXED_SUPPRESS_DATE_HEADER query
   4808    */
   4809   enum MHD_Bool v_suppress_date_header_bool;
   4810 
   4811   /**
   4812    * The data for the #MHD_DAEMON_INFO_FIXED_CONN_MEMORY_LIMIT query
   4813    */
   4814   size_t v_conn_memory_limit_sizet;
   4815 
   4816   /**
   4817    * The data for the #MHD_DAEMON_INFO_FIXED_FD_NUMBER_LIMIT query
   4818    */
   4819   MHD_Socket v_fd_number_limit_socket;
   4820 
   4821   /**
   4822    * Unused member.
   4823    * Help enforcing future-proof alignment of the union.
   4824    * Do not use.
   4825    */
   4826   void *reserved;
   4827 };
   4828 
   4829 
   4830 /**
   4831  * Obtain fixed information about the given daemon.
   4832  * This information is not changed at after start of the daemon until
   4833  * the daemon is destroyed.
   4834  * The wrapper macro #MHD_daemon_get_info_fixed() may be more convenient.
   4835  *
   4836  * @param daemon the daemon to get information about
   4837  * @param info_type the type of information requested
   4838  * @param[out] output_buf pointer to union where requested information will
   4839  *                        be stored
   4840  * @param output_buf_size the size of the memory area pointed by @a output_buf
   4841  *                        (provided by the caller for storing the requested
   4842  *                        information), in bytes
   4843  * @return #MHD_SC_OK if succeed,
   4844  *         #MHD_SC_TOO_EARLY if the daemon has not been started yet,
   4845  *         #MHD_SC_TOO_LATE if the daemon is being stopped or has failed,
   4846  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4847  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   4848  *                                              is not available for this
   4849  *                                              daemon due to the daemon
   4850  *                                              configuration/mode,
   4851  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   4852  *                                            should be available for
   4853  *                                            the daemon, but cannot be provided
   4854  *                                            due to some error or other
   4855  *                                            reasons,
   4856  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   4857  *         other error codes in case of other errors
   4858  * @ingroup specialized
   4859  */
   4860 MHD_EXTERN_ enum MHD_StatusCode
   4861 MHD_daemon_get_info_fixed_sz (
   4862   struct MHD_Daemon *MHD_RESTRICT daemon,
   4863   enum MHD_DaemonInfoFixedType info_type,
   4864   union MHD_DaemonInfoFixedData *MHD_RESTRICT output_buf,
   4865   size_t output_buf_size)
   4866 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   4867 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   4868 
   4869 /**
   4870  * Obtain fixed information about the given daemon.
   4871  * This types of information are not changed at after start of the daemon until
   4872  * the daemon is destroyed.
   4873  *
   4874  * @param daemon the daemon to get information about
   4875  * @param info_type the type of information requested
   4876  * @param[out] output_buf pointer to union where requested information will
   4877  *                          be stored
   4878  * @return #MHD_SC_OK if succeed,
   4879  *         #MHD_SC_TOO_EARLY if the daemon has not been started yet,
   4880  *         #MHD_SC_TOO_LATE if the daemon is being stopped or has failed,
   4881  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4882  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   4883  *                                              is not available for this
   4884  *                                              daemon due to the daemon
   4885  *                                              configuration/mode,
   4886  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   4887  *                                            should be available for
   4888  *                                            the daemon, but cannot be provided
   4889  *                                            due to some error or other
   4890  *                                            reasons,
   4891  *         other error codes in case of other errors
   4892  * @ingroup specialized
   4893  */
   4894 #define MHD_daemon_get_info_fixed(daemon, info_type, output_buf) \
   4895         MHD_daemon_get_info_fixed_sz ((daemon), (info_type), (output_buf), \
   4896                                       sizeof(*(output_buf)))
   4897 
   4898 
   4899 /**
   4900  * Values of this enum are used to specify what
   4901  * information about a daemon is desired.
   4902  * This types of information may be changed after the start of the daemon.
   4903  */
   4904 enum MHD_DaemonInfoDynamicType
   4905 {
   4906   /**
   4907    * The the maximum number of millisecond from the current moment until
   4908    * the mandatory call of the daemon data processing function (like
   4909    * #MHD_daemon_process_reg_events(), #MHD_daemon_process_blocking()).
   4910    * If resulting value is zero then daemon data processing function should be
   4911    * called as soon as possible as some data processing is already pending.
   4912    * The data processing function can also be called earlier as well.
   4913    * Available only for daemons stated in #MHD_WM_EXTERNAL_PERIODIC,
   4914    * #MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL, #MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE
   4915    * or #MHD_WM_EXTERNAL_SINGLE_FD_WATCH modes.
   4916    * The function returns #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the daemon has
   4917    * internal handling of events (internal threads).
   4918    * The result is placed in @a v_max_time_to_wait_uint64 member.
   4919    */
   4920   MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT = 1
   4921   ,
   4922   /**
   4923    * Check whether the daemon has any connected network clients.
   4924    * The result is placed in @a v_has_connections_bool member.
   4925    */
   4926   MHD_DAEMON_INFO_DYNAMIC_HAS_CONNECTIONS = 20
   4927   ,
   4928   /* * Sentinel * */
   4929   /**
   4930    * The sentinel value.
   4931    * This value enforces specific underlying integer type for the enum.
   4932    * Do not use.
   4933    */
   4934   MHD_DAEMON_INFO_DYNAMIC_SENTINEL = 65535
   4935 };
   4936 
   4937 
   4938 /**
   4939  * Information about an MHD daemon.
   4940  */
   4941 union MHD_DaemonInfoDynamicData
   4942 {
   4943   /**
   4944    * The data for the #MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT query
   4945    */
   4946   uint_fast64_t v_max_time_to_wait_uint64;
   4947 
   4948   /**
   4949    * The data for the #MHD_DAEMON_INFO_DYNAMIC_HAS_CONNECTIONS query
   4950    */
   4951   enum MHD_Bool v_has_connections_bool;
   4952 
   4953   /**
   4954    * Unused member.
   4955    * Help enforcing future-proof alignment of the union.
   4956    * Do not use.
   4957    */
   4958   void *reserved;
   4959 };
   4960 
   4961 
   4962 /**
   4963  * Obtain dynamic information about the given daemon.
   4964  * This information may be changed after the start of the daemon.
   4965  * The wrapper macro #MHD_daemon_get_info_dynamic() could be more convenient.
   4966  *
   4967  * @param daemon the daemon to get information about
   4968  * @param info_type the type of information requested
   4969  * @param[out] output_buf the pointer to union to be set to the requested
   4970  *                        information
   4971  * @param output_buf_size the size of the memory area pointed by @a output_buf
   4972  *                        (provided by the caller for storing the requested
   4973  *                        information), in bytes
   4974  * @return #MHD_SC_OK if succeed,
   4975  *         #MHD_SC_TOO_EARLY if the daemon has not been started yet,
   4976  *         #MHD_SC_TOO_LATE if the daemon is being stopped or has failed,
   4977  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   4978  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   4979  *                                              is not available for this
   4980  *                                              daemon due to the daemon
   4981  *                                              configuration/mode,
   4982  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   4983  *                                            should be available for
   4984  *                                            the daemon, but cannot be provided
   4985  *                                            due to some error or other
   4986  *                                            reasons,
   4987  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   4988  *         other error codes in case of other errors
   4989  * @ingroup specialized
   4990  */
   4991 MHD_EXTERN_ enum MHD_StatusCode
   4992 MHD_daemon_get_info_dynamic_sz (
   4993   struct MHD_Daemon *MHD_RESTRICT daemon,
   4994   enum MHD_DaemonInfoDynamicType info_type,
   4995   union MHD_DaemonInfoDynamicData *MHD_RESTRICT output_buf,
   4996   size_t output_buf_size)
   4997 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   4998 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   4999 
   5000 /**
   5001  * Obtain dynamic information about the given daemon.
   5002  * This types of information may be changed after the start of the daemon.
   5003  *
   5004  * @param daemon the daemon to get information about
   5005  * @param info_type the type of information requested
   5006  * @param[out] output_buf the pointer to union to be set to the requested
   5007  *                        information
   5008  * @return #MHD_SC_OK if succeed,
   5009  *         #MHD_SC_TOO_EARLY if the daemon has not been started yet,
   5010  *         #MHD_SC_TOO_LATE if the daemon is being stopped or has failed,
   5011  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5012  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   5013  *                                              is not available for this
   5014  *                                              daemon due to the daemon
   5015  *                                              configuration/mode,
   5016  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   5017  *                                            should be available for
   5018  *                                            the daemon, but cannot be provided
   5019  *                                            due to some error or other
   5020  *                                            reasons,
   5021  *         other error codes in case of other errors
   5022  * @ingroup specialized
   5023  */
   5024 #define MHD_daemon_get_info_dynamic(daemon, info_type, output_buf) \
   5025         MHD_daemon_get_info_dynamic_sz ((daemon), (info_type), (output_buf), \
   5026                                         sizeof(*(output_buf)))
   5027 
   5028 
   5029 /**
   5030  * Select which fixed information about connection is desired.
   5031  * This information is not changed during the lifetime of the connection.
   5032  */
   5033 enum MHD_ConnectionInfoFixedType
   5034 {
   5035   /**
   5036    * Get the network address of the client.
   5037    * If the connection does not have known remote address (was not provided
   5038    * by the system or by the application in case of externally added
   5039    * connection) then error code #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is
   5040    * returned if connection is IP type or unknown type or error code
   5041    * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if connection type is non-IP.
   5042    * The @a sa pointer is never NULL if the function succeed (#MHD_SC_OK
   5043    * returned).
   5044    * The result is placed in @a v_client_address_sa_info member.
   5045    * @ingroup request
   5046    */
   5047   MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS = 1
   5048   ,
   5049   /**
   5050    * Get the file descriptor for the connection socket.
   5051    * The provided socket must be used as 'read-only': only select() or similar
   5052    * functions should be used. Any modifications (changing socket attributes,
   5053    * calling send() or recv(), closing it etc.) will lead to undefined
   5054    * behaviour.
   5055    * The result is placed in @a v_connection_socket member.
   5056    * @ingroup request
   5057    */
   5058   MHD_CONNECTION_INFO_FIXED_CONNECTION_SOCKET = 2
   5059   ,
   5060   /**
   5061    * Get the `struct MHD_Daemon *` responsible for managing this connection.
   5062    * The result is placed in @a v_daemon member.
   5063    * @ingroup request
   5064    */
   5065   MHD_CONNECTION_INFO_FIXED_DAEMON = 20
   5066   ,
   5067   /**
   5068    * Returns the pointer to a variable pointing to connection-specific
   5069    * application context data that was (possibly) set during
   5070    * a #MHD_NotifyConnectionCallback or provided via @a connection_cntx
   5071    * parameter of #MHD_daemon_add_connection().
   5072    * By using provided pointer application may get or set the pointer to
   5073    * any data specific for the particular connection.
   5074    * Note: resulting data is NOT the context pointer itself.
   5075    * The result is placed in @a v_app_context_ppvoid member.
   5076    * @ingroup request
   5077    */
   5078   MHD_CONNECTION_INFO_FIXED_APP_CONTEXT = 30
   5079   ,
   5080 
   5081   /* * Sentinel * */
   5082   /**
   5083    * The sentinel value.
   5084    * This value enforces specific underlying integer type for the enum.
   5085    * Do not use.
   5086    */
   5087   MHD_CONNECTION_INFO_FIXED_SENTINEL = 65535
   5088 };
   5089 
   5090 /**
   5091  * Socket address information data
   5092  */
   5093 struct MHD_ConnInfoFixedSockAddr
   5094 {
   5095   /**
   5096    * The size of the @a sa
   5097    */
   5098   size_t sa_size;
   5099 
   5100   /**
   5101    * Socket Address type
   5102    */
   5103   const struct sockaddr *sa;
   5104 };
   5105 
   5106 /**
   5107  * Information about a connection.
   5108  */
   5109 union MHD_ConnectionInfoFixedData
   5110 {
   5111 
   5112   /**
   5113    * The data for the #MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS query
   5114    */
   5115   struct MHD_ConnInfoFixedSockAddr v_client_address_sa_info;
   5116 
   5117   /**
   5118    * The data for the #MHD_CONNECTION_INFO_FIXED_CONNECTION_SOCKET query
   5119    */
   5120   MHD_Socket v_connection_socket;
   5121 
   5122   /**
   5123    * The data for the #MHD_CONNECTION_INFO_FIXED_DAEMON query
   5124    */
   5125   struct MHD_Daemon *v_daemon;
   5126 
   5127   /**
   5128    * The data for the #MHD_CONNECTION_INFO_FIXED_APP_CONTEXT query
   5129    */
   5130   void **v_app_context_ppvoid;
   5131 };
   5132 
   5133 
   5134 /**
   5135  * Obtain fixed information about the given connection.
   5136  * This information is not changed for the lifetime of the connection.
   5137  * The wrapper macro #MHD_connection_get_info_fixed() may be more convenient.
   5138  *
   5139  * @param connection the connection to get information about
   5140  * @param info_type the type of information requested
   5141  * @param[out] output_buf the pointer to union to be set to the requested
   5142  *                        information
   5143  * @param output_buf_size the size of the memory area pointed by @a output_buf
   5144  *                        (provided by the caller for storing the requested
   5145  *                        information), in bytes
   5146  * @return #MHD_SC_OK if succeed,
   5147  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5148  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   5149  *                                              is not available for this
   5150  *                                              connection due to the connection
   5151  *                                              configuration/mode,
   5152  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   5153  *                                            should be available for
   5154  *                                            the connection, but cannot be
   5155  *                                            provided due to some error or
   5156  *                                            other reasons,
   5157  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   5158  *         other error codes in case of other errors
   5159  * @ingroup specialized
   5160  */
   5161 MHD_EXTERN_ enum MHD_StatusCode
   5162 MHD_connection_get_info_fixed_sz (
   5163   struct MHD_Connection *MHD_RESTRICT connection,
   5164   enum MHD_ConnectionInfoFixedType info_type,
   5165   union MHD_ConnectionInfoFixedData *MHD_RESTRICT output_buf,
   5166   size_t output_buf_size)
   5167 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   5168 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   5169 
   5170 
   5171 /**
   5172  * Obtain fixed information about the given connection.
   5173  * This information is not changed for the lifetime of the connection.
   5174  *
   5175  * @param connection the connection to get information about
   5176  * @param info_type the type of information requested
   5177  * @param[out] output_buf the pointer to union to be set to the requested
   5178  *                        information
   5179  * @return #MHD_SC_OK if succeed,
   5180  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5181  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   5182  *                                              is not available for this
   5183  *                                              connection due to the connection
   5184  *                                              configuration/mode,
   5185  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   5186  *                                            should be available for
   5187  *                                            the connection, but cannot be
   5188  *                                            provided due to some error or
   5189  *                                            other reasons,
   5190  *         other error codes in case of other errors
   5191  * @ingroup specialized
   5192  */
   5193 #define MHD_connection_get_info_fixed(connection, info_type, output_buf) \
   5194         MHD_connection_get_info_fixed_sz ((connection),(info_type), \
   5195                                           (output_buf), sizeof(*(output_buf)))
   5196 
   5197 
   5198 /**
   5199  * Select which dynamic information about connection is desired.
   5200  * This information may be changed during the lifetime of the connection.
   5201  */
   5202 enum MHD_ConnectionInfoDynamicType
   5203 {
   5204   /**
   5205    * Get current version of HTTP protocol used for connection.
   5206    * If connection is handling HTTP/1.x requests the function may return
   5207    * error code #MHD_SC_TOO_EARLY if the full request line has not been received
   5208    * yet for the current request.
   5209    * The result is placed in @a v_http_ver member.
   5210    * @ingroup request
   5211    */
   5212   MHD_CONNECTION_INFO_DYNAMIC_HTTP_VER = 1
   5213   ,
   5214   /**
   5215    * Get connection timeout value.
   5216    * This is the total number of milliseconds after which the idle
   5217    * connection is automatically disconnected.
   5218    * Note: the value set is NOT the number of milliseconds left before
   5219    * automatic disconnection.
   5220    * The result is placed in @a v_connection_timeout_uint32 member.
   5221    * @ingroup request
   5222    */
   5223   MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_TIMEOUT_MILSEC = 10
   5224   ,
   5225   /**
   5226    * Check whether the connection is suspended.
   5227    * The result is placed in @a v_connection_suspended_bool member.
   5228    * @ingroup request
   5229    */
   5230   MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_SUSPENDED = 11
   5231   ,
   5232   /**
   5233    * Get current version of TLS transport protocol used for connection
   5234    * If plain TCP connection is used then #MHD_TLS_VERSION_NO_TLS set in
   5235    * the data.
   5236    * It TLS handshake is not yet finished then error code #MHD_SC_TOO_EARLY is
   5237    * returned. If TLS has failed or being closed then #MHD_SC_TOO_LATE error
   5238    * code is returned.
   5239    * If TLS version cannot be detected for any reason then error code
   5240    * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is returned.
   5241    * The result is placed in @a v_tls_ver member.
   5242    * @ingroup request
   5243    */
   5244   MHD_CONNECTION_INFO_DYNAMIC_TLS_VER = 105
   5245   ,
   5246   /**
   5247    * Get the TLS backend session handle.
   5248    * If plain TCP connection is used then the function returns error code
   5249    * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE.
   5250    * The resulting union has only one valid member.
   5251    * The result is placed in @a v_tls_session member.
   5252    * @ingroup request
   5253    */
   5254   MHD_CONNECTION_INFO_DYNAMIC_TLS_SESSION = 140
   5255   ,
   5256 
   5257   /* * Sentinel * */
   5258   /**
   5259    * The sentinel value.
   5260    * This value enforces specific underlying integer type for the enum.
   5261    * Do not use.
   5262    */
   5263   MHD_CONNECTION_INFO_DYNAMIC_SENTINEL = 65535
   5264 };
   5265 
   5266 
   5267 /**
   5268  * The versions of TLS protocol
   5269  */
   5270 enum MHD_FIXED_ENUM_MHD_SET_ MHD_TlsVersion
   5271 {
   5272 
   5273   /**
   5274    * No TLS / plain socket connection
   5275    */
   5276   MHD_TLS_VERSION_NO_TLS = 0
   5277   ,
   5278   /**
   5279    * Not supported/failed to negotiate/failed to handshake TLS
   5280    */
   5281   MHD_TLS_VERSION_BROKEN = 1
   5282   ,
   5283   /**
   5284    * TLS version 1.0
   5285    */
   5286   MHD_TLS_VERSION_1_0 = 2
   5287   ,
   5288   /**
   5289    * TLS version 1.1
   5290    */
   5291   MHD_TLS_VERSION_1_1 = 3
   5292   ,
   5293   /**
   5294    * TLS version 1.2
   5295    */
   5296   MHD_TLS_VERSION_1_2 = 4
   5297   ,
   5298   /**
   5299    * TLS version 1.3
   5300    */
   5301   MHD_TLS_VERSION_1_3 = 5
   5302   ,
   5303   /**
   5304    * Some unknown TLS version.
   5305    * The TLS version is supported by TLS backend, but unknown to MHD.
   5306    */
   5307   MHD_TLS_VERSION_UNKNOWN = 1999
   5308 };
   5309 
   5310 /**
   5311  * Connection TLS session information.
   5312  * Only one member is valid. Use #MHD_DAEMON_INFO_FIXED_TLS_TYPE to find out
   5313  * which member should be used.
   5314  */
   5315 union MHD_ConnInfoDynamicTlsSess
   5316 {
   5317   /* Include <gnutls/gnutls.h> before this header to get a better type safety */
   5318   /**
   5319    * GnuTLS session handle, of type "gnutls_session_t".
   5320    */
   5321 #if defined(GNUTLS_VERSION_MAJOR) && GNUTLS_VERSION_MAJOR >= 3
   5322   gnutls_session_t v_gnutls_session;
   5323 #else
   5324   void * /* gnutls_session_t */ v_gnutls_session;
   5325 #endif
   5326 
   5327   /* Include <openssl/types.h> or <openssl/crypto.h> before this header to get
   5328      a better type safety */
   5329   /**
   5330    * OpenSSL session handle, of type "SSL*".
   5331    */
   5332 #if defined(OPENSSL_TYPES_H) && OPENSSL_VERSION_MAJOR >= 3
   5333   SSL *v_openssl_session;
   5334 #else
   5335   void /* SSL */ *v_openssl_session;
   5336 #endif
   5337 
   5338   /* Include <mbedtls/ssl.h> before this header to get a better type safety */
   5339   /**
   5340    * MbedTLS session handle, of type "mbedtls_ssl_context*".
   5341    */
   5342 #if defined(MBEDTLS_SSL_H)
   5343   mbedtls_ssl_context *v_mbedtls_session;
   5344 #else
   5345   void /* mbedtls_ssl_context */ *v_mbedtls_session;
   5346 #endif
   5347 };
   5348 
   5349 /**
   5350  * Information about a connection.
   5351  */
   5352 union MHD_ConnectionInfoDynamicData
   5353 {
   5354   /**
   5355    * The data for the #MHD_CONNECTION_INFO_DYNAMIC_HTTP_VER query
   5356    */
   5357   enum MHD_HTTP_ProtocolVersion v_http_ver;
   5358 
   5359   /**
   5360    * The data for the #MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_TIMEOUT_MILSEC
   5361    * query
   5362    */
   5363   uint_fast32_t v_connection_timeout_uint32;
   5364 
   5365   /**
   5366    * The data for the #MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_SUSPENDED query
   5367    */
   5368   enum MHD_Bool v_connection_suspended_bool;
   5369 
   5370   /**
   5371    * The data for the #MHD_CONNECTION_INFO_DYNAMIC_CONNECTION_SUSPENDED query
   5372    */
   5373   enum MHD_TlsVersion v_tls_ver;
   5374 
   5375   /**
   5376    * Connection TLS session information.
   5377    * Only one member is valid. Use #MHD_DAEMON_INFO_FIXED_TLS_TYPE to find out
   5378    * which member should be used.
   5379    */
   5380   union MHD_ConnInfoDynamicTlsSess v_tls_session;
   5381 };
   5382 
   5383 /**
   5384  * Obtain dynamic information about the given connection.
   5385  * This information may be changed during the lifetime of the connection.
   5386  *
   5387  * The wrapper macro #MHD_connection_get_info_dynamic() may be more convenient.
   5388  *
   5389  * @param connection the connection to get information about
   5390  * @param info_type the type of information requested
   5391  * @param[out] output_buf the pointer to union to be set to the requested
   5392  *                        information
   5393  * @param output_buf_size the size of the memory area pointed by @a output_buf
   5394  *                        (provided by the caller for storing the requested
   5395  *                        information), in bytes
   5396  * @return #MHD_SC_OK if succeed,
   5397  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5398  *         #MHD_SC_TOO_EARLY if the connection has not reached yet required
   5399  *                           state,
   5400  *         #MHD_SC_TOO_LATE if the connection is already in state where
   5401  *                          the requested information is not available,
   5402  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   5403  *                                              is not available for this
   5404  *                                              connection due to the connection
   5405  *                                              configuration/mode,
   5406  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   5407  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   5408  *                                            should be available for
   5409  *                                            the connection, but cannot be
   5410  *                                            provided due to some error or
   5411  *                                            other reasons,
   5412  *         other error codes in case of other errors
   5413  * @ingroup specialized
   5414  */
   5415 MHD_EXTERN_ enum MHD_StatusCode
   5416 MHD_connection_get_info_dynamic_sz (
   5417   struct MHD_Connection *MHD_RESTRICT connection,
   5418   enum MHD_ConnectionInfoDynamicType info_type,
   5419   union MHD_ConnectionInfoDynamicData *MHD_RESTRICT output_buf,
   5420   size_t output_buf_size)
   5421 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   5422 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   5423 
   5424 
   5425 /**
   5426  * Obtain dynamic information about the given connection.
   5427  * This information may be changed during the lifetime of the connection.
   5428  *
   5429  * @param connection the connection to get information about
   5430  * @param info_type the type of information requested
   5431  * @param[out] output_buf the pointer to union to be set to the requested
   5432  *                        information
   5433  * @return #MHD_SC_OK if succeed,
   5434  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5435  *         #MHD_SC_TOO_EARLY if the connection has not reached yet required
   5436  *                           state,
   5437  *         #MHD_SC_TOO_LATE if the connection is already in state where
   5438  *                          the requested information is not available,
   5439  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information
   5440  *                                              is not available for this
   5441  *                                              connection due to the connection
   5442  *                                              configuration/mode,
   5443  *         #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information
   5444  *                                            should be available for
   5445  *                                            the connection, but cannot be
   5446  *                                            provided due to some error or
   5447  *                                            other reasons,
   5448  *         other error codes in case of other errors
   5449  * @ingroup specialized
   5450  */
   5451 #define MHD_connection_get_info_dynamic(connection, info_type, output_buf) \
   5452         MHD_connection_get_info_dynamic_sz ((connection),(info_type), \
   5453                                             (output_buf),sizeof(*(output_buf)))
   5454 
   5455 
   5456 /**
   5457  * Select which fixed information about stream is desired.
   5458  * This information is not changed during the lifetime of the connection.
   5459  */
   5460 enum MHD_FIXED_ENUM_APP_SET_ MHD_StreamInfoFixedType
   5461 {
   5462   /**
   5463    * Get the `struct MHD_Daemon *` responsible for managing connection which
   5464    * is responsible for this stream.
   5465    * The result is placed in @a v_daemon member.
   5466    * @ingroup request
   5467    */
   5468   MHD_STREAM_INFO_FIXED_DAEMON = 20
   5469   ,
   5470   /**
   5471    * Get the `struct MHD_Connection *` responsible for managing this stream.
   5472    * The result is placed in @a v_connection member.
   5473    * @ingroup request
   5474    */
   5475   MHD_STREAM_INFO_FIXED_CONNECTION = 21
   5476   ,
   5477 
   5478   /* * Sentinel * */
   5479   /**
   5480    * The sentinel value.
   5481    * This value enforces specific underlying integer type for the enum.
   5482    * Do not use.
   5483    */
   5484   MHD_STREAM_INFO_FIXED_SENTINEL = 65535
   5485 };
   5486 
   5487 
   5488 /**
   5489  * Fixed information about a stream.
   5490  */
   5491 union MHD_StreamInfoFixedData
   5492 {
   5493   /**
   5494    * The data for the #MHD_STREAM_INFO_FIXED_DAEMON query
   5495    */
   5496   struct MHD_Daemon *v_daemon;
   5497   /**
   5498    * The data for the #MHD_STREAM_INFO_FIXED_CONNECTION query
   5499    */
   5500   struct MHD_Connection *v_connection;
   5501 };
   5502 
   5503 
   5504 /**
   5505  * Obtain fixed information about the given stream.
   5506  * This information is not changed for the lifetime of the stream.
   5507  *
   5508  * The wrapper macro #MHD_stream_get_info_fixed() may be more convenient.
   5509  *
   5510  * @param stream the stream to get information about
   5511  * @param info_type the type of information requested
   5512  * @param[out] output_buf the pointer to union to be set to the requested
   5513  *                        information
   5514  * @param output_buf_size the size of the memory area pointed by @a output_buf
   5515  *                        (provided by the caller for storing the requested
   5516  *                        information), in bytes
   5517  * @return #MHD_SC_OK if succeed,
   5518  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5519  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   5520  *         other error codes in case of other errors
   5521  * @ingroup specialized
   5522  */
   5523 MHD_EXTERN_ enum MHD_StatusCode
   5524 MHD_stream_get_info_fixed_sz (
   5525   struct MHD_Stream *MHD_RESTRICT stream,
   5526   enum MHD_StreamInfoFixedType info_type,
   5527   union MHD_StreamInfoFixedData *MHD_RESTRICT output_buf,
   5528   size_t output_buf_size)
   5529 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   5530 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   5531 
   5532 
   5533 /**
   5534  * Obtain fixed information about the given stream.
   5535  * This information is not changed for the lifetime of the tream.
   5536  *
   5537  * @param stream the stream to get information about
   5538  * @param info_type the type of information requested
   5539  * @param[out] output_buf the pointer to union to be set to the requested
   5540  *                        information
   5541  * @return #MHD_SC_OK if succeed,
   5542  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5543  *         other error codes in case of other errors
   5544  * @ingroup specialized
   5545  */
   5546 #define MHD_stream_get_info_fixed(stream, info_type, output_buf) \
   5547         MHD_stream_get_info_fixed_sz ((stream),(info_type),(output_buf), \
   5548                                       sizeof(*(output_buf)))
   5549 
   5550 
   5551 /**
   5552  * Select which fixed information about stream is desired.
   5553  * This information may be changed during the lifetime of the stream.
   5554  */
   5555 enum MHD_FIXED_ENUM_APP_SET_ MHD_StreamInfoDynamicType
   5556 {
   5557   /**
   5558    * Get the `struct MHD_Request *` for current request processed by the stream.
   5559    * If no request is being processed, the error code #MHD_SC_TOO_EARLY is
   5560    * returned.
   5561    * The result is placed in @a v_request member.
   5562    * @ingroup request
   5563    */
   5564   MHD_STREAM_INFO_DYNAMIC_REQUEST = 20
   5565   ,
   5566 
   5567   /* * Sentinel * */
   5568   /**
   5569    * The sentinel value.
   5570    * This value enforces specific underlying integer type for the enum.
   5571    * Do not use.
   5572    */
   5573   MHD_STREAM_INFO_DYNAMIC_SENTINEL = 65535
   5574 };
   5575 
   5576 
   5577 /**
   5578  * Dynamic information about stream.
   5579  * This information may be changed during the lifetime of the connection.
   5580  */
   5581 union MHD_StreamInfoDynamicData
   5582 {
   5583   /**
   5584    * The data for the #MHD_STREAM_INFO_DYNAMIC_REQUEST query
   5585    */
   5586   struct MHD_Request *v_request;
   5587 };
   5588 
   5589 /**
   5590  * Obtain dynamic information about the given stream.
   5591  * This information may be changed during the lifetime of the stream.
   5592  *
   5593  * The wrapper macro #MHD_stream_get_info_dynamic() may be more convenient.
   5594  *
   5595  * @param stream the stream to get information about
   5596  * @param info_type the type of information requested
   5597  * @param[out] output_buf the pointer to union to be set to the requested
   5598  *                        information
   5599  * @param output_buf_size the size of the memory area pointed by @a output_buf
   5600  *                        (provided by the caller for storing the requested
   5601  *                        information), in bytes
   5602  * @return #MHD_SC_OK if succeed,
   5603  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5604  *         #MHD_SC_TOO_EARLY if the stream has not reached yet required state,
   5605  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   5606  *         other error codes in case of other errors
   5607  * @ingroup specialized
   5608  */
   5609 MHD_EXTERN_ enum MHD_StatusCode
   5610 MHD_stream_get_info_dynamic_sz (
   5611   struct MHD_Stream *MHD_RESTRICT stream,
   5612   enum MHD_StreamInfoDynamicType info_type,
   5613   union MHD_StreamInfoDynamicData *MHD_RESTRICT output_buf,
   5614   size_t output_buf_size)
   5615 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   5616 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   5617 
   5618 
   5619 /**
   5620  * Obtain dynamic information about the given stream.
   5621  * This information may be changed during the lifetime of the stream.
   5622  *
   5623  * @param stream the stream to get information about
   5624  * @param info_type the type of information requested
   5625  * @param[out] output_buf the pointer to union to be set to the requested
   5626  *                        information
   5627  * @return #MHD_SC_OK if succeed,
   5628  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5629  *         #MHD_SC_TOO_EARLY if the stream has not reached yet required state,
   5630  *         other error codes in case of other errors
   5631  * @ingroup specialized
   5632  */
   5633 #define MHD_stream_get_info_dynamic(stream, info_type, output_buf) \
   5634         MHD_stream_get_info_dynamic_sz ((stream),(info_type),(output_buf), \
   5635                                         sizeof(*(output_buf)))
   5636 
   5637 
   5638 /**
   5639  * Select which fixed information about request is desired.
   5640  * This information is not changed during the lifetime of the request.
   5641  */
   5642 enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoFixedType
   5643 {
   5644   /**
   5645    * Get the version of HTTP protocol used for the request.
   5646    * If request line has not been fully received yet then #MHD_SC_TOO_EARLY
   5647    * error code is returned.
   5648    * The result is placed in @a v_http_ver member.
   5649    * @ingroup request
   5650    */
   5651   MHD_REQUEST_INFO_FIXED_HTTP_VER = 1
   5652   ,
   5653   /**
   5654    * Get the HTTP method used for the request (as a enum).
   5655    * The result is placed in @a v_http_method member.
   5656    * @sa #MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STR
   5657    * @ingroup request
   5658    */
   5659   MHD_REQUEST_INFO_FIXED_HTTP_METHOD = 2
   5660   ,
   5661   /**
   5662    * Return MHD daemon to which the request belongs to.
   5663    * The result is placed in @a v_daemon member.
   5664    */
   5665   MHD_REQUEST_INFO_FIXED_DAEMON = 20
   5666   ,
   5667   /**
   5668    * Return which connection is associated with the stream which is associated
   5669    * with the request.
   5670    * The result is placed in @a v_connection member.
   5671    */
   5672   MHD_REQUEST_INFO_FIXED_CONNECTION = 21
   5673   ,
   5674   /**
   5675    * Return which stream the request is associated with.
   5676    * The result is placed in @a v_stream member.
   5677    */
   5678   MHD_REQUEST_INFO_FIXED_STREAM = 22
   5679   ,
   5680   /**
   5681    * Returns the pointer to a variable pointing to request-specific
   5682    * application context data. The same data is provided for
   5683    * #MHD_EarlyUriLogCallback and #MHD_RequestTerminationCallback.
   5684    * By using provided pointer application may get or set the pointer to
   5685    * any data specific for the particular request.
   5686    * Note: resulting data is NOT the context pointer itself.
   5687    * The result is placed in @a v_app_context_ppvoid member.
   5688    * @ingroup request
   5689    */
   5690   MHD_REQUEST_INFO_FIXED_APP_CONTEXT = 30
   5691   ,
   5692 
   5693   /* * Sentinel * */
   5694   /**
   5695    * The sentinel value.
   5696    * This value enforces specific underlying integer type for the enum.
   5697    * Do not use.
   5698    */
   5699   MHD_REQUEST_INFO_FIXED_SENTINEL = 65535
   5700 };
   5701 
   5702 
   5703 /**
   5704  * Fixed information about a request.
   5705  */
   5706 union MHD_RequestInfoFixedData
   5707 {
   5708 
   5709   /**
   5710    * The data for the #MHD_REQUEST_INFO_FIXED_HTTP_VER query
   5711    */
   5712   enum MHD_HTTP_ProtocolVersion v_http_ver;
   5713 
   5714   /**
   5715    * The data for the #MHD_REQUEST_INFO_FIXED_HTTP_METHOD query
   5716    */
   5717   enum MHD_HTTP_Method v_http_method;
   5718 
   5719   /**
   5720    * The data for the #MHD_REQUEST_INFO_FIXED_DAEMON query
   5721    */
   5722   struct MHD_Daemon *v_daemon;
   5723 
   5724   /**
   5725    * The data for the #MHD_REQUEST_INFO_FIXED_CONNECTION query
   5726    */
   5727   struct MHD_Connection *v_connection;
   5728 
   5729   /**
   5730    * The data for the #MHD_REQUEST_INFO_FIXED_STREAM query
   5731    */
   5732   struct MHD_Stream *v_stream;
   5733 
   5734   /**
   5735    * The data for the #MHD_REQUEST_INFO_FIXED_APP_CONTEXT query
   5736    */
   5737   void **v_app_context_ppvoid;
   5738 };
   5739 
   5740 /**
   5741  * Obtain fixed information about the given request.
   5742  * This information is not changed for the lifetime of the request.
   5743  *
   5744  * The wrapper macro #MHD_request_get_info_fixed() may be more convenient.
   5745  *
   5746  * @param request the request to get information about
   5747  * @param info_type the type of information requested
   5748  * @param[out] output_buf the pointer to union to be set to the requested
   5749  *                        information
   5750  * @param output_buf_size the size of the memory area pointed by @a output_buf
   5751  *                        (provided by the caller for storing the requested
   5752  *                        information), in bytes
   5753  * @return #MHD_SC_OK if succeed,
   5754  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5755  *         #MHD_SC_TOO_EARLY if the request processing has not reached yet
   5756  *                           the required state,
   5757  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   5758  *         other error codes in case of other errors
   5759  * @ingroup specialized
   5760  */
   5761 MHD_EXTERN_ enum MHD_StatusCode
   5762 MHD_request_get_info_fixed_sz (
   5763   struct MHD_Request *MHD_RESTRICT request,
   5764   enum MHD_RequestInfoFixedType info_type,
   5765   union MHD_RequestInfoFixedData *MHD_RESTRICT output_buf,
   5766   size_t output_buf_size)
   5767 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   5768 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   5769 
   5770 
   5771 /**
   5772  * Obtain fixed information about the given request.
   5773  * This information is not changed for the lifetime of the request.
   5774  *
   5775  * @param request the request to get information about
   5776  * @param info_type the type of information requested
   5777  * @param[out] output_buf the pointer to union to be set to the requested
   5778  *                        information
   5779  * @return #MHD_SC_OK if succeed,
   5780  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown,
   5781  *         #MHD_SC_TOO_EARLY if the request processing has not reached yet
   5782  *                           the required state,
   5783  *         other error codes in case of other errors
   5784  * @ingroup specialized
   5785  */
   5786 #define MHD_request_get_info_fixed(request, info_type, output_buf) \
   5787         MHD_request_get_info_fixed_sz ((request), (info_type), (output_buf), \
   5788                                        sizeof(*(output_buf)))
   5789 
   5790 
   5791 /**
   5792  * Select which dynamic information about request is desired.
   5793  * This information may be changed during the lifetime of the request.
   5794  * Any returned string pointers are valid only until a response is provided.
   5795  */
   5796 enum MHD_FIXED_ENUM_APP_SET_ MHD_RequestInfoDynamicType
   5797 {
   5798   /**
   5799    * Get the HTTP method used for the request (as a MHD_String).
   5800    * The resulting string pointer in valid only until a response is provided.
   5801    * The result is placed in @a v_http_method_string member.
   5802    * @sa #MHD_REQUEST_INFO_FIXED_HTTP_METHOD
   5803    * @ingroup request
   5804    */
   5805   MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STRING = 1
   5806   ,
   5807   /**
   5808    * Get the URI used for the request (as a MHD_String), excluding
   5809    * the parameter part (anything after '?').
   5810    * The resulting string pointer in valid only until a response is provided.
   5811    * The result is placed in @a v_uri_string member.
   5812    * @ingroup request
   5813    */
   5814   MHD_REQUEST_INFO_DYNAMIC_URI = 2
   5815   ,
   5816   /**
   5817    * Get the number of URI parameters (the decoded part of the original
   5818    * URI string after '?'). Sometimes it is called "GET parameters".
   5819    * The result is placed in @a v_number_uri_params_sizet member.
   5820    * @ingroup request
   5821    */
   5822   MHD_REQUEST_INFO_DYNAMIC_NUMBER_URI_PARAMS = 3
   5823   ,
   5824   /**
   5825    * Get the number of cookies in the request.
   5826    * The result is placed in @a v_number_cookies_sizet member.
   5827    * If cookies parsing is disabled in MHD build then the function returns
   5828    * error code #MHD_SC_FEATURE_DISABLED.
   5829    * If cookies parsing is disabled this daemon then the function returns
   5830    * error code #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE.
   5831    * @ingroup request
   5832    */
   5833   MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES = 4
   5834   ,
   5835   /**
   5836    * Return length of the client's HTTP request header.
   5837    * This is a total raw size of the header (after TLS decipher if any)
   5838    * The result is placed in @a v_header_size_sizet member.
   5839    * @ingroup request
   5840    */
   5841   MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE = 5
   5842   ,
   5843   /**
   5844    * Get the number of decoded POST entries in the request.
   5845    * The result is placed in @a v_number_post_params_sizet member.
   5846    * @ingroup request
   5847    */
   5848   MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS = 6
   5849   ,
   5850   /**
   5851    * Get whether the upload content is present in the request.
   5852    * The result is #MHD_YES if any upload content is present, even
   5853    * if the upload content size is zero.
   5854    * The result is placed in @a v_upload_present_bool member.
   5855    * @ingroup request
   5856    */
   5857   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT = 10
   5858   ,
   5859   /**
   5860    * Get whether the chunked upload content is present in the request.
   5861    * The result is #MHD_YES if chunked upload content is present.
   5862    * The result is placed in @a v_upload_chunked_bool member.
   5863    * @ingroup request
   5864    */
   5865   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED = 11
   5866   ,
   5867   /**
   5868    * Get the total content upload size.
   5869    * Resulted in zero if no content upload or upload content size is zero,
   5870    * #MHD_SIZE_UNKNOWN if size is not known (chunked upload).
   5871    * The result is placed in @a v_upload_size_total_uint64 member.
   5872    * @ingroup request
   5873    */
   5874   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL = 12
   5875   ,
   5876   /**
   5877    * Get the total size of the content upload already received from the client.
   5878    * This is the total size received, could be not yet fully processed by the
   5879    * application.
   5880    * The result is placed in @a v_upload_size_recieved_uint64 member.
   5881    * @ingroup request
   5882    */
   5883   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED = 13
   5884   ,
   5885   /**
   5886    * Get the total size of the content upload left to be received from
   5887    * the client.
   5888    * Resulted in #MHD_SIZE_UNKNOWN if total size is not known (chunked upload).
   5889    * The result is placed in @a v_upload_size_to_recieve_uint64 member.
   5890    * @ingroup request
   5891    */
   5892   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE = 14
   5893   ,
   5894   /**
   5895    * Get the total size of the content upload already processed (upload callback
   5896    * called and completed (if any)).
   5897    * If the value is requested from #MHD_UploadCallback, then result does NOT
   5898    * include the current data being processed by the callback.
   5899    * The result is placed in @a v_upload_size_processed_uint64 member.
   5900    * @ingroup request
   5901    */
   5902   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED = 15
   5903   ,
   5904   /**
   5905    * Get the total size of the content upload left to be processed.
   5906    * The resulting value includes the size of the data not yet received from
   5907    * the client.
   5908    * If the value is requested from #MHD_UploadCallback, then result includes
   5909    * the current data being processed by the callback.
   5910    * Resulted in #MHD_SIZE_UNKNOWN if total size is not known (chunked upload).
   5911    * The result is placed in @a v_upload_size_to_process_uint64 member.
   5912    * @ingroup request
   5913    */
   5914   MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS = 16
   5915   ,
   5916   /**
   5917    * Returns pointer to information about digest auth in client request.
   5918    * The resulting pointer is NULL if no digest auth header is set by
   5919    * the client or the format of the digest auth header is broken.
   5920    * Pointers in the returned structure (if any) are valid until response
   5921    * is provided for the request.
   5922    * The result is placed in @a v_auth_digest_info member.
   5923    */
   5924   MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO = 42
   5925   ,
   5926   /**
   5927    * Returns information about Basic Authentication credentials in the request.
   5928    * Pointers in the returned structure (if any) are valid until any MHD_Action
   5929    * or MHD_UploadAction is provided. If the data is needed beyond this point,
   5930    * it should be copied.
   5931    * If #MHD_request_get_info_dynamic_sz() returns #MHD_SC_OK then
   5932    * @a v_auth_basic_creds is NOT NULL and at least the username data
   5933    * is provided.
   5934    * The result is placed in @a v_auth_basic_creds member.
   5935    */
   5936   MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS = 51
   5937   ,
   5938   /* * Sentinel * */
   5939   /**
   5940    * The sentinel value.
   5941    * This value enforces specific underlying integer type for the enum.
   5942    * Do not use.
   5943    */
   5944   MHD_REQUEST_INFO_DYNAMIC_SENTINEL = 65535
   5945 };
   5946 
   5947 
   5948 /**
   5949  * Dynamic information about a request.
   5950  */
   5951 union MHD_RequestInfoDynamicData
   5952 {
   5953 
   5954   /**
   5955    * The data for the #MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STRING query
   5956    */
   5957   struct MHD_String v_http_method_string;
   5958 
   5959   /**
   5960    * The data for the #MHD_REQUEST_INFO_DYNAMIC_URI query
   5961    */
   5962   struct MHD_String v_uri_string;
   5963 
   5964   /**
   5965    * The data for the #MHD_REQUEST_INFO_DYNAMIC_NUMBER_URI_PARAMS query
   5966    */
   5967   size_t v_number_uri_params_sizet;
   5968 
   5969   /**
   5970    * The data for the #MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES query
   5971    */
   5972   size_t v_number_cookies_sizet;
   5973 
   5974   /**
   5975    * The data for the #MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE query
   5976    */
   5977   size_t v_header_size_sizet;
   5978 
   5979   /**
   5980    * The data for the #MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS query
   5981    */
   5982   size_t v_number_post_params_sizet;
   5983 
   5984   /**
   5985    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT query
   5986    */
   5987   enum MHD_Bool v_upload_present_bool;
   5988 
   5989   /**
   5990    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED query
   5991    */
   5992   enum MHD_Bool v_upload_chunked_bool;
   5993 
   5994   /**
   5995    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL query
   5996    */
   5997   uint_fast64_t v_upload_size_total_uint64;
   5998 
   5999   /**
   6000    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED query
   6001    */
   6002   uint_fast64_t v_upload_size_recieved_uint64;
   6003 
   6004   /**
   6005    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_RECIEVE query
   6006    */
   6007   uint_fast64_t v_upload_size_to_recieve_uint64;
   6008 
   6009   /**
   6010    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_PROCESSED query
   6011    */
   6012   uint_fast64_t v_upload_size_processed_uint64;
   6013 
   6014   /**
   6015    * The data for the #MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TO_PROCESS query
   6016    */
   6017   uint_fast64_t v_upload_size_to_process_uint64;
   6018 
   6019   /**
   6020    * The data for the #MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO query
   6021    */
   6022   const struct MHD_AuthDigestInfo *v_auth_digest_info;
   6023 
   6024   /**
   6025    * The data for the #MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS query
   6026    */
   6027   const struct MHD_AuthBasicCreds *v_auth_basic_creds;
   6028 };
   6029 
   6030 
   6031 /**
   6032  * Obtain dynamic information about the given request.
   6033  * This information may be changed during the lifetime of the request.
   6034  * Most of the data provided is available only when the request line or complete
   6035  * request headers are processed and not available if responding has been
   6036  * started.
   6037  *
   6038  * The wrapper macro #MHD_request_get_info_dynamic() may be more convenient.
   6039  *
   6040  * Any pointers in the returned data are valid until any MHD_Action or
   6041  * MHD_UploadAction is provided. If the data is needed beyond this point,
   6042  * it should be copied.
   6043  *
   6044  * @param request the request to get information about
   6045  * @param info_type the type of information requested
   6046  * @param[out] output_buf the pointer to union to be set to the requested
   6047  *                        information
   6048  * @param output_buf_size the size of the memory area pointed by @a output_buf
   6049  *                        (provided by the caller for storing the requested
   6050  *                        information), in bytes
   6051  * @return #MHD_SC_OK if succeed,
   6052  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is
   6053  *                                       not recognized by MHD,
   6054  *         #MHD_SC_TOO_LATE if request is already being closed or the response
   6055  *                          is being sent
   6056  *         #MHD_SC_TOO_EARLY if requested data is not yet ready (for example,
   6057  *                           headers are not yet received),
   6058  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information is
   6059  *                                              not available for this request
   6060  *                                              due to used configuration/mode,
   6061  *         #MHD_SC_FEATURE_DISABLED if requested functionality is not supported
   6062  *                                  by this MHD build,
   6063  *         #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small,
   6064  *         #MHD_SC_AUTH_ABSENT if request does not have particular Auth data,
   6065  *         #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool
   6066  *                                                  has no space to put decoded
   6067  *                                                  authentication data,
   6068  *         #MHD_SC_REQ_AUTH_DATA_BROKEN if the format of authentication data is
   6069  *                                      incorrect or broken,
   6070  *         other error codes in case of other errors
   6071  * @ingroup specialized
   6072  */
   6073 MHD_EXTERN_ enum MHD_StatusCode
   6074 MHD_request_get_info_dynamic_sz (
   6075   struct MHD_Request *MHD_RESTRICT request,
   6076   enum MHD_RequestInfoDynamicType info_type,
   6077   union MHD_RequestInfoDynamicData *MHD_RESTRICT output_buf,
   6078   size_t output_buf_size)
   6079 MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   6080 MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3);
   6081 
   6082 
   6083 /**
   6084  * Obtain dynamic information about the given request.
   6085  * This information may be changed during the lifetime of the request.
   6086  * Most of the data provided is available only when the request line or complete
   6087  * request headers are processed and not available if responding has been
   6088  * started.
   6089  *
   6090  * Any pointers in the returned data are valid until any MHD_Action or
   6091  * MHD_UploadAction is provided. If the data is needed beyond this point,
   6092  * it should be copied.
   6093  *
   6094  * @param request the request to get information about
   6095  * @param info_type the type of information requested
   6096  * @param[out] output_buf the pointer to union to be set to the requested
   6097  *                        information
   6098  * @return #MHD_SC_OK if succeed,
   6099  *         #MHD_SC_INFO_GET_TYPE_UNKNOWN if requested information type is
   6100  *                                       not recognized by MHD,
   6101  *         #MHD_SC_TOO_LATE if request is already being closed or the response
   6102  *                          is being sent
   6103  *         #MHD_SC_TOO_EARLY if requested data is not yet ready (for example,
   6104  *                           headers are not yet received),
   6105  *         #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information is
   6106  *                                              not available for this request
   6107  *                                              due to used configuration/mode,
   6108  *         #MHD_SC_FEATURE_DISABLED if requested functionality is not supported
   6109  *                                  by this MHD build,
   6110  *         #MHD_SC_AUTH_ABSENT if request does not have particular Auth data,
   6111  *         #MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA if connection memory pool
   6112  *                                                  has no space to put decoded
   6113  *                                                  authentication data,
   6114  *         #MHD_SC_REQ_AUTH_DATA_BROKEN if the format of authentication data is
   6115  *                                      incorrect or broken,
   6116  *         other error codes in case of other errors
   6117  * @ingroup specialized
   6118  */
   6119 #define MHD_request_get_info_dynamic(request, info_type, output_buf) \
   6120         MHD_request_get_info_dynamic_sz ((request), (info_type), \
   6121                                          (output_buf), \
   6122                                          sizeof(*(output_buf)))
   6123 
   6124 /**
   6125  * Callback for serious error condition. The default action is to print
   6126  * an error message and `abort()`.
   6127  * The callback should not return.
   6128  * Some parameters could be empty strings (the strings with zero-termination at
   6129  * zero position) if MHD built without log messages (only for embedded
   6130  * projects).
   6131  *
   6132  * @param cls user specified value
   6133  * @param file where the error occurred, could be empty
   6134  * @param func the name of the function, where the error occurred, may be empty
   6135  * @param line where the error occurred
   6136  * @param message the error details, could be empty
   6137  * @ingroup logging
   6138  */
   6139 typedef void
   6140 (*MHD_PanicCallback)(void *cls,
   6141                      const char *file,
   6142                      const char *func,
   6143                      unsigned int line,
   6144                      const char *message);
   6145 
   6146 
   6147 /**
   6148  * Sets the global error handler to a different implementation.
   6149  * The @a cb will only be called in the case of typically fatal, serious
   6150  * internal consistency issues.
   6151  * These issues should only arise in the case of serious memory corruption or
   6152  * similar problems with the architecture.
   6153  * The @a cb should not return.
   6154  *
   6155  * The default implementation that is used if no panic function is set
   6156  * simply prints an error message and calls `abort()`.  Alternative
   6157  * implementations might call `exit()` or other similar functions.
   6158  *
   6159  * @param cb new error handler, NULL to reset to default handler
   6160  * @param cls passed to @a cb
   6161  * @ingroup logging
   6162  */
   6163 MHD_EXTERN_ void
   6164 MHD_lib_set_panic_func (MHD_PanicCallback cb,
   6165                         void *cls);
   6166 
   6167 #define MHD_lib_set_panic_func_default() \
   6168         MHD_lib_set_panic_func (MHD_STATIC_CAST_ (MHD_PanicCallback,NULL),NULL)