libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

mhd_opt_matrix.h (12673B)


      1 /*
      2      This file is part of GNU libmicrohttpd
      3      Copyright (C) 2026 Christian Grothoff
      4 
      5      GNU libmicrohttpd is free software; you can redistribute it and/or
      6      modify it under the terms of the GNU Lesser General Public
      7      License as published by the Free Software Foundation; either
      8      version 2.1 of the License, or (at your option) any later version.
      9 
     10      This library is distributed in the hope that it will be useful,
     11      but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      Lesser General Public License for more details.
     14 
     15      You should have received a copy of the GNU Lesser General Public
     16      License along with GNU libmicrohttpd.
     17      If not, see <http://www.gnu.org/licenses/>.
     18 */
     19 
     20 /**
     21  * @file microhttpd/mhd_opt_matrix.h
     22  * @brief  The environment-driven daemon option matrix shared by the tests
     23  * @author Christian Grothoff
     24  *
     25  * This header must be included *after* "platform.h" and <microhttpd.h>.
     26  *
     27  * ## What this is
     28  *
     29  * Almost every test in this directory starts its daemon with one hard-coded
     30  * set of options, so the whole test suite only ever exercises a single point
     31  * of a large configuration space.  This helper turns that space into a small
     32  * table of named *profiles* and lets the profile be selected from the
     33  * environment, so that an already built test binary can be re-run across the
     34  * whole matrix without recompiling anything (see contrib/run-option-matrix.sh).
     35  *
     36  * The dimensions of the matrix are:
     37  *
     38  * * #MHD_OPTION_CONNECTION_MEMORY_LIMIT in
     39  *   {64, 128, 256, 512, 1024, 2048, 3072, 4096, library default}.  64 is the
     40  *   smallest value MHD accepts (anything below is rounded up to 64, see
     41  *   daemon.c).  Everything up to 2048 keeps the read buffer below
     42  *   #MHD_BUF_INC_SIZE (1500) resp. small enough to unlock the read-buffer
     43  *   "shift back" path fixed by commit 29eaa56b, 3072 and 4096 do not, so both
     44  *   sides of that boundary are in the sweep;
     45  * * #MHD_OPTION_CLIENT_DISCIPLINE_LVL in {-3 ... 3};
     46  * * #MHD_OPTION_STRICT_FOR_CLIENT, the older two-valued form of the same
     47  *   knob, so that its translation code is covered as well.  Beware: that
     48  *   option maps *every* value of -1 or below to client discipline level -3,
     49  *   the most permissive one (daemon.c:7102-7106), so an application asking
     50  *   for "slightly lenient" in fact selects the most lenient mode;
     51  * * the threading mode: external polling, internal polling thread,
     52  *   thread-per-connection and thread pool;
     53  * * the polling backend: select(), poll() and epoll.  Profiles asking for a
     54  *   backend that this build does not provide are reported as unsupported by
     55  *   mhd_opt_matrix_profile_supported().
     56  *
     57  * #MHD_OPTION_SERVER_INSANITY is deliberately *not* a dimension: in this MHD
     58  * version `enum MHD_DisableSanityCheck` has exactly one member,
     59  * #MHD_DSC_SANE (zero), so the option cannot disable anything.
     60  *
     61  * ## Environment variables
     62  *
     63  * * #MHD_OPT_MATRIX_PROFILE_ENV ("MHD_TEST_PROFILE") - the profile to use,
     64  *   given either by name ("mem-512") or by index ("4").  The special value
     65  *   "list" is not handled here; contrib/run-option-matrix.sh knows the names.
     66  * * #MHD_OPT_MATRIX_MEM_ENV ("MHD_TEST_MEM_LIMIT") - override the connection
     67  *   memory limit of the selected profile.  "0" or "default" selects the
     68  *   library default.
     69  * * #MHD_OPT_MATRIX_DISCP_ENV ("MHD_TEST_DISCIPLINE") - override the client
     70  *   discipline level (-3 ... 3) and use #MHD_OPTION_CLIENT_DISCIPLINE_LVL.
     71  * * #MHD_OPT_MATRIX_STRICT_ENV ("MHD_TEST_STRICT_FOR_CLIENT") - override the
     72  *   same knob but use the deprecated #MHD_OPTION_STRICT_FOR_CLIENT instead.
     73  * * #MHD_OPT_MATRIX_THREADING_ENV ("MHD_TEST_THREADING") - one of
     74  *   "external", "internal", "per-connection", "pool".
     75  * * #MHD_OPT_MATRIX_POLL_ENV ("MHD_TEST_POLL") - one of "select", "poll",
     76  *   "epoll".
     77  *
     78  * If *none* of these variables is set, mhd_opt_matrix_from_env()
     79  * returns NULL and every test keeps its previous, hard-coded behaviour.  This
     80  * is what a stock "make check" does, so nothing regresses.
     81  */
     82 
     83 #ifndef MHD_OPT_MATRIX_H
     84 #define MHD_OPT_MATRIX_H 1
     85 
     86 #include <stddef.h>
     87 #include <microhttpd.h>
     88 
     89 /**
     90  * The name of the environment variable selecting the profile.
     91  */
     92 #define MHD_OPT_MATRIX_PROFILE_ENV "MHD_TEST_PROFILE"
     93 
     94 /**
     95  * The name of the environment variable overriding the memory limit.
     96  */
     97 #define MHD_OPT_MATRIX_MEM_ENV "MHD_TEST_MEM_LIMIT"
     98 
     99 /**
    100  * The name of the environment variable overriding the discipline level.
    101  */
    102 #define MHD_OPT_MATRIX_DISCP_ENV "MHD_TEST_DISCIPLINE"
    103 
    104 /**
    105  * The name of the environment variable overriding the discipline level via
    106  * the deprecated #MHD_OPTION_STRICT_FOR_CLIENT option.
    107  */
    108 #define MHD_OPT_MATRIX_STRICT_ENV "MHD_TEST_STRICT_FOR_CLIENT"
    109 
    110 /**
    111  * The name of the environment variable overriding the threading mode.
    112  */
    113 #define MHD_OPT_MATRIX_THREADING_ENV "MHD_TEST_THREADING"
    114 
    115 /**
    116  * The name of the environment variable overriding the polling backend.
    117  */
    118 #define MHD_OPT_MATRIX_POLL_ENV "MHD_TEST_POLL"
    119 
    120 /**
    121  * The threading mode of a profile.
    122  */
    123 enum MHD_OptMatrixThreading
    124 {
    125   /**
    126    * External polling: the application drives the daemon with MHD_run().
    127    */
    128   MHD_OPT_MATRIX_THR_EXTERNAL = 0,
    129 
    130   /**
    131    * One internal polling thread for all connections.
    132    */
    133   MHD_OPT_MATRIX_THR_INTERNAL = 1,
    134 
    135   /**
    136    * One internal thread per connection.
    137    */
    138   MHD_OPT_MATRIX_THR_PER_CONNECTION = 2,
    139 
    140   /**
    141    * A pool of internal polling threads.
    142    */
    143   MHD_OPT_MATRIX_THR_POOL = 3
    144 };
    145 
    146 
    147 /**
    148  * The polling backend of a profile.
    149  */
    150 enum MHD_OptMatrixPoll
    151 {
    152   /**
    153    * Use select().
    154    */
    155   MHD_OPT_MATRIX_POLL_SELECT = 0,
    156 
    157   /**
    158    * Use poll(), needs #MHD_FEATURE_POLL.
    159    */
    160   MHD_OPT_MATRIX_POLL_POLL = 1,
    161 
    162   /**
    163    * Use epoll, needs #MHD_FEATURE_EPOLL.
    164    */
    165   MHD_OPT_MATRIX_POLL_EPOLL = 2
    166 };
    167 
    168 
    169 /**
    170  * One point of the daemon option matrix.
    171  *
    172  * A caller may copy the structure and modify the copy, e.g. with
    173  * mhd_opt_matrix_raise_mem_limit(); the tables returned by
    174  * mhd_opt_matrix_profile() must not be modified.
    175  */
    176 struct MHD_OptMatrixProfile
    177 {
    178   /**
    179    * Human readable name of the profile, used for logging and for
    180    * #MHD_OPT_MATRIX_PROFILE_ENV.
    181    */
    182   const char *name;
    183 
    184   /**
    185    * The value for #MHD_OPTION_CONNECTION_MEMORY_LIMIT.
    186    * Zero means "keep the MHD default".
    187    */
    188   size_t mem_limit;
    189 
    190   /**
    191    * The value for #MHD_OPTION_CLIENT_DISCIPLINE_LVL or, when
    192    * @a use_legacy_strict is set, for #MHD_OPTION_STRICT_FOR_CLIENT.
    193    * Zero means "keep the MHD default" and adds no option at all.
    194    */
    195   int discipline_lvl;
    196 
    197   /**
    198    * If non-zero, the deprecated #MHD_OPTION_STRICT_FOR_CLIENT option is used
    199    * instead of #MHD_OPTION_CLIENT_DISCIPLINE_LVL, so that the legacy option
    200    * translation code is exercised as well.
    201    */
    202   int use_legacy_strict;
    203 
    204   /**
    205    * The threading mode.
    206    */
    207   enum MHD_OptMatrixThreading threading;
    208 
    209   /**
    210    * The polling backend.
    211    */
    212   enum MHD_OptMatrixPoll poll_backend;
    213 
    214   /**
    215    * The number of worker threads, only used with
    216    * #MHD_OPT_MATRIX_THR_POOL.
    217    */
    218   unsigned int thread_pool_size;
    219 };
    220 
    221 
    222 /**
    223  * The number of built-in profiles.
    224  */
    225 unsigned int
    226 mhd_opt_matrix_num_profiles (void);
    227 
    228 
    229 /**
    230  * Get the built-in profile number @a idx.
    231  *
    232  * Profile zero is the "default" profile: the library defaults for every
    233  * dimension plus one internal polling thread, i.e. the configuration the
    234  * tests of this directory used before the matrix was introduced.
    235  *
    236  * @param idx the index of the profile, wraps around
    237  * @return the profile, never NULL
    238  */
    239 const struct MHD_OptMatrixProfile *
    240 mhd_opt_matrix_profile (unsigned int idx);
    241 
    242 
    243 /**
    244  * Look up a profile by name or by decimal index.
    245  *
    246  * @param name_or_idx the name ("mem-512") or the index ("4")
    247  * @return the profile, or NULL if @a name_or_idx matches nothing
    248  */
    249 const struct MHD_OptMatrixProfile *
    250 mhd_opt_matrix_lookup (const char *name_or_idx);
    251 
    252 
    253 /**
    254  * Get the profile selected by the environment.
    255  *
    256  * @return NULL if the environment selects nothing, in which case the caller
    257  *         must keep its own, previous configuration; otherwise a pointer to
    258  *         a static profile that stays valid until the next call
    259  */
    260 const struct MHD_OptMatrixProfile *
    261 mhd_opt_matrix_from_env (void);
    262 
    263 
    264 /**
    265  * Get the client discipline level that MHD will *really* use for @a prof.
    266  *
    267  * This is not always @a prof->discipline_lvl: #MHD_OPTION_STRICT_FOR_CLIENT
    268  * only has two settings, and daemon.c:7102-7106 maps every value of -1 or
    269  * below to level -3 (the most permissive one) and every value of 1 or above
    270  * to level 1.  A caller that decides what a request must do therefore has to
    271  * ask for the effective level, not for the configured one - a test that
    272  * believes it asked for "slightly lenient" in fact runs at -3.
    273  *
    274  * @param prof the profile to inspect, may be NULL (0 is returned then)
    275  * @return the client discipline level in effect
    276  */
    277 int
    278 mhd_opt_matrix_effective_discipline (const struct MHD_OptMatrixProfile *prof);
    279 
    280 
    281 /**
    282  * Check whether @a prof can be used by this build at run time.
    283  *
    284  * @param prof the profile to check
    285  * @return non-zero if the profile is usable, zero if the required threading
    286  *         support or polling backend is missing
    287  */
    288 int
    289 mhd_opt_matrix_profile_supported (const struct MHD_OptMatrixProfile *prof);
    290 
    291 
    292 /**
    293  * Render a one-line, human readable description of @a prof.
    294  *
    295  * @param prof the profile to describe
    296  * @param[out] buf the buffer to write to
    297  * @param buf_size the size of @a buf
    298  * @return @a buf
    299  */
    300 const char *
    301 mhd_opt_matrix_describe (const struct MHD_OptMatrixProfile *prof,
    302                          char *buf,
    303                          size_t buf_size);
    304 
    305 
    306 /**
    307  * Fill @a ops with the options of @a prof.
    308  *
    309  * The array is terminated with an #MHD_OPTION_END element, so it can be
    310  * passed to MHD_start_daemon() as
    311  *
    312  *     MHD_start_daemon (flags, port, NULL, NULL, ahc, cls,
    313  *                       MHD_OPTION_ARRAY, ops,
    314  *                       ... other options ...,
    315  *                       MHD_OPTION_END);
    316  *
    317  * which works for a varargs call just as well as for a call that already
    318  * uses #MHD_OPTION_ARRAY.
    319  *
    320  * @param prof the profile to apply, may be NULL (only #MHD_OPTION_END is
    321  *             stored then)
    322  * @param[out] ops the array to fill
    323  * @param max_ops the number of elements of @a ops, at least 4
    324  * @return the number of elements used, including the terminating
    325  *         #MHD_OPTION_END; zero if @a ops is too small
    326  */
    327 unsigned int
    328 mhd_opt_matrix_fill_options (const struct MHD_OptMatrixProfile *prof,
    329                              struct MHD_OptionItem *ops,
    330                              unsigned int max_ops);
    331 
    332 
    333 /**
    334  * Combine the daemon flags required by @a prof with @a base_flags.
    335  *
    336  * @param prof the profile to apply, may be NULL (@a base_flags is returned)
    337  * @param base_flags the flags the caller wants in any case, e.g.
    338  *                   #MHD_USE_ERROR_LOG
    339  * @param allow_external if zero, a profile that asks for external polling is
    340  *                       served with an internal polling thread instead; use
    341  *                       this in tests whose client cannot call MHD_run()
    342  * @return the flags for MHD_start_daemon()
    343  */
    344 unsigned int
    345 mhd_opt_matrix_daemon_flags (const struct MHD_OptMatrixProfile *prof,
    346                              unsigned int base_flags,
    347                              int allow_external);
    348 
    349 
    350 /**
    351  * Check whether @a prof needs the application to drive MHD_run().
    352  *
    353  * @param prof the profile to check, may be NULL
    354  * @return non-zero if the daemon has no internal thread
    355  */
    356 int
    357 mhd_opt_matrix_is_external (const struct MHD_OptMatrixProfile *prof);
    358 
    359 
    360 /**
    361  * Raise the connection memory limit of @a prof to at least @a min_limit.
    362  *
    363  * Tests that cannot work with a tiny connection pool (because the requests
    364  * they must send do not fit into it) use this to keep the other dimensions of
    365  * the matrix while staying functional.  The change must be reported in the
    366  * test output so that the log stays truthful.
    367  *
    368  * @param[in,out] prof the profile to adjust, must be a caller-owned copy
    369  * @param min_limit the smallest acceptable limit, zero does nothing
    370  * @return non-zero if the limit was actually raised
    371  */
    372 int
    373 mhd_opt_matrix_raise_mem_limit (struct MHD_OptMatrixProfile *prof,
    374                                 size_t min_limit);
    375 
    376 
    377 /**
    378  * Print the one-line notice naming the profile in use and, if a profile is
    379  * selected, the profile.
    380  *
    381  * @param test_name the name of the calling test, used as the line prefix
    382  */
    383 void
    384 mhd_opt_matrix_print_notice (const char *test_name);
    385 
    386 
    387 #endif /* MHD_OPT_MATRIX_H */