libmicrohttpd2

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

microhttpd2_main.h.in (228340B)


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