libmicrohttpd2

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

microhttpd2_main.h.in (230742B)


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