libmicrohttpd2

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

microhttpd2_main.h.in (229038B)


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