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 */