libmicrohttpd2

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

microhttpd2_main.h.in (227722B)


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