mhd_daemon.h (35880B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2024-2026 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/mhd_daemon.h 41 * @brief The header for declaration of struct MHD_Daemon 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #ifndef MHD_DAEMON_H 46 #define MHD_DAEMON_H 1 47 48 #include "mhd_sys_options.h" 49 50 #include "sys_bool_type.h" 51 #include "sys_base_types.h" 52 53 #include "mhd_dlinked_list.h" 54 55 #include "mhd_buffer.h" 56 #include "mhd_socket_type.h" 57 #include "mhd_atomic_counter.h" 58 59 #ifdef MHD_SUPPORT_AUTH_DIGEST 60 # include "mhd_digest_auth_data.h" 61 #endif 62 63 #ifdef MHD_SUPPORT_HTTPS 64 # include "mhd_tls_choice.h" 65 #endif 66 67 #ifdef MHD_SUPPORT_THREADS 68 # include "mhd_threads.h" 69 # include "mhd_itc_types.h" 70 #endif 71 72 #include "mhd_locks.h" 73 74 #include "sys_select.h" 75 #include "sys_poll.h" 76 #ifdef MHD_SUPPORT_EPOLL 77 # include <sys/epoll.h> 78 #endif 79 #include "sys_kqueue.h" 80 81 #include "mempool_types.h" 82 83 #ifdef mhd_HAVE_TLS_ACME 84 # include "mhd_tls_certs_list.h" 85 #endif 86 87 #include "mhd_public_api.h" 88 89 struct DaemonOptions; /* Forward declaration */ 90 struct MHD_Connection; /* Forward declaration */ 91 struct sockaddr_storage; /* Forward declaration */ 92 93 /** 94 * The helper struct for the connections list 95 */ 96 mhd_DLINKEDL_LIST_DEF (MHD_Connection); 97 98 /** 99 * The current phase of the daemon life 100 */ 101 enum MHD_FIXED_ENUM_ mhd_DaemonState 102 { 103 /** 104 * The daemon has been created, but not yet started. 105 * Setting configuration options is possible. 106 */ 107 mhd_DAEMON_STATE_NOT_STARTED = 0 108 , 109 /** 110 * The daemon is being started. 111 */ 112 mhd_DAEMON_STATE_STARTING 113 , 114 /** 115 * The daemon has been started. 116 * Normal operations. 117 */ 118 mhd_DAEMON_STATE_STARTED 119 , 120 /** 121 * The daemon has failed to start 122 */ 123 mhd_DAEMON_STATE_FAILED 124 , 125 /** 126 * The daemon is being stopped. 127 */ 128 mhd_DAEMON_STATE_STOPPING 129 , 130 /** 131 * The daemon is stopped. 132 * The state should rarely visible as daemon should be destroyed when stopped. 133 */ 134 mhd_DAEMON_STATE_STOPPED 135 }; 136 137 138 /** 139 * Internal version of the daemon work mode type 140 */ 141 enum MHD_FIXED_ENUM_ mhd_WorkModeIntType 142 { 143 /** 144 * Network edge-triggered events are monitored and provided by application. 145 * Receiving, sending and processing of the network data if performed when 146 * special MHD function is called by application. 147 * No threads managed by the daemon. 148 */ 149 mhd_WM_INT_EXTERNAL_EVENTS_EDGE 150 , 151 /** 152 * Network level-triggered events are monitored and provided by application. 153 * Receiving, sending and processing of the network data if performed when 154 * special MHD function is called by application. 155 * No threads managed by the daemon. 156 */ 157 mhd_WM_INT_EXTERNAL_EVENTS_LEVEL 158 , 159 /** 160 * The daemon checks for the network events, receives, sends and process 161 * the network data when special MHD function is called by application. 162 * No threads managed by the daemon. 163 */ 164 mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS 165 #ifdef MHD_SUPPORT_THREADS 166 , 167 /** 168 * The daemon runs its own single thread, where the daemon monitors 169 * all network events, receives, sends and process the network data. 170 */ 171 mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD 172 , 173 /** 174 * The daemon runs its own single thread, where the daemon monitors 175 * the new incoming connections, and runs individual thread for each 176 * established connection, where the daemon monitors connection, receives, 177 * sends and process the network data. 178 */ 179 mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION 180 , 181 /** 182 * The daemon runs its fixed number of threads, all threads monitors the 183 * new incoming connections and each thread handles own subset of the network 184 * connections (monitors connections network events, receives, sends and 185 * process the network data). 186 */ 187 mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL 188 #endif 189 }; 190 191 #ifdef MHD_SUPPORT_THREADS 192 /** 193 * Check whether given mhd_WorkModeIntType value should have internal threads, 194 * either directly controlled or indirectly, via additional workers daemons. 195 */ 196 # define mhd_WM_INT_HAS_THREADS(wm_i) \ 197 (mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD <= wm_i) 198 /** 199 * Check whether given mhd_WorkModeIntType value equals "thread-per-connection" 200 */ 201 # define mhd_WM_INT_IS_THREAD_PER_CONN(wm_i) \ 202 (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == wm_i) 203 /** 204 * Check whether given mhd_WorkModeIntType value equals "thread pool" 205 */ 206 # define mhd_WM_INT_IS_THREAD_POOL(wm_i) \ 207 (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == wm_i) 208 #else /* ! MHD_SUPPORT_THREADS */ 209 # define mhd_WM_INT_HAS_THREADS(wm_i) (0) 210 # define mhd_WM_INT_IS_THREAD_PER_CONN(wm_i) (0) 211 # define mhd_WM_INT_IS_THREAD_POOL(wm_i) (0) 212 #endif /* ! MHD_SUPPORT_THREADS */ 213 214 /** 215 * Check whether given mhd_WorkModeIntType value has external events 216 */ 217 #define mhd_WM_INT_HAS_EXT_EVENTS(wm_i) \ 218 (mhd_WM_INT_EXTERNAL_EVENTS_LEVEL >= wm_i) 219 220 221 /** 222 * Sockets polling internal syscalls used by MHD. 223 * 224 * The same value used as by #MHD_SockPollSyscall, however instead of "auto" 225 * method this enum uses "not yet set" and enum is extended with an additional 226 * "external" value. 227 */ 228 enum MHD_FIXED_ENUM_ mhd_IntPollType 229 { 230 /** 231 * External sockets polling is used. 232 */ 233 mhd_POLL_TYPE_EXT = -1 234 , 235 /** 236 * Internal sockets polling syscall has not been selected yet. 237 */ 238 mhd_POLL_TYPE_NOT_SET_YET = MHD_SPS_AUTO 239 , 240 /** 241 * Use select(). 242 */ 243 mhd_POLL_TYPE_SELECT = MHD_SPS_SELECT 244 , 245 /** 246 * Use poll(). 247 */ 248 mhd_POLL_TYPE_POLL = MHD_SPS_POLL 249 #ifdef MHD_SUPPORT_EPOLL 250 , 251 /** 252 * Use epoll. 253 */ 254 mhd_POLL_TYPE_EPOLL = MHD_SPS_EPOLL 255 #endif /* MHD_SUPPORT_EPOLL */ 256 #ifdef MHD_SUPPORT_KQUEUE 257 , 258 /** 259 * Use kqueue. 260 */ 261 mhd_POLL_TYPE_KQUEUE = MHD_SPS_KQUEUE 262 #endif /* MHD_SUPPORT_KQUEUE */ 263 }; 264 265 266 #ifdef MHD_SUPPORT_EPOLL 267 /** 268 * Check whether provided mhd_IntPollType value is "epoll" 269 */ 270 # define mhd_POLL_TYPE_INT_IS_EPOLL(poll_type) \ 271 (mhd_POLL_TYPE_EPOLL == (poll_type)) 272 #else 273 # define mhd_POLL_TYPE_INT_IS_EPOLL(poll_type) (0) 274 #endif 275 276 #ifdef MHD_SUPPORT_KQUEUE 277 /** 278 * Check whether provided mhd_IntPollType value is "kqueue" 279 */ 280 # define mhd_POLL_TYPE_INT_IS_KQUEUE(poll_type) \ 281 (mhd_POLL_TYPE_KQUEUE == (poll_type)) 282 #else 283 # define mhd_POLL_TYPE_INT_IS_KQUEUE(poll_type) (0) 284 #endif 285 286 #define mhd_POLL_TYPE_INT_IS_EDGE_TRIG(poll_type) \ 287 (mhd_POLL_TYPE_INT_IS_EPOLL (poll_type) \ 288 || mhd_POLL_TYPE_INT_IS_KQUEUE (poll_type)) 289 290 #if defined(HAVE_UINTPTR_T) 291 typedef uintptr_t mhd_SockRelMarker; 292 #else 293 typedef unsigned char *mhd_SockRelMarker; 294 #endif 295 296 /** The marker of the empty position */ 297 #define mhd_SOCKET_REL_MARKER_EMPTY ((mhd_SockRelMarker) (0)) 298 299 /** The marker of the ITC slot */ 300 #define mhd_SOCKET_REL_MARKER_ITC ((mhd_SockRelMarker) (-1)) 301 302 /** The marker of the listen socket slot */ 303 #define mhd_SOCKET_REL_MARKER_LISTEN (mhd_SOCKET_REL_MARKER_ITC - 1) 304 305 /* Pointer version of the markers */ 306 307 /** The marker of the empty position */ 308 #define mhd_SOCKET_REL_PTRMARKER_EMPTY ((void*) mhd_SOCKET_REL_MARKER_EMPTY) 309 310 /** The marker of the ITC slot */ 311 #define mhd_SOCKET_REL_PTRMARKER_ITC ((void*) mhd_SOCKET_REL_MARKER_ITC) 312 313 /** The marker of the listen socket slot */ 314 #define mhd_SOCKET_REL_PTRMARKER_LISTEN ((void*) mhd_SOCKET_REL_MARKER_LISTEN) 315 316 /** 317 * Identifier of the FD related to event 318 */ 319 union mhd_SocketRelation 320 { 321 /** 322 * Identifier of the FD. 323 * Only valid when it is equal to #mhd_SOCKET_REL_MARKER_EMPTY, 324 * #mhd_SOCKET_REL_MARKER_ITC or #mhd_SOCKET_REL_MARKER_LISTEN. 325 */ 326 mhd_SockRelMarker fd_id; 327 /** 328 * This is a connection's FD. 329 * This is valid only when @a fd_id is not valid. 330 */ 331 struct MHD_Connection *connection; 332 }; 333 334 #ifdef MHD_SUPPORT_SELECT 335 336 /** 337 * Daemon's pointers to the preallocated arrays for running sockets monitoring 338 * by poll(). 339 */ 340 struct mhd_DaemonEventsSelectData 341 { 342 /** 343 * Set of sockets monitored for read (receive) readiness. 344 */ 345 fd_set *rfds; 346 /** 347 * Set of sockets monitored for write (send) readiness. 348 */ 349 fd_set *wfds; 350 /** 351 * Set of sockets monitored for exception (error) readiness. 352 */ 353 fd_set *efds; 354 }; 355 356 #endif /* MHD_SUPPORT_SELECT */ 357 358 #ifdef MHD_SUPPORT_POLL 359 360 /** 361 * Daemon's pointers to the preallocated arrays for running sockets monitoring 362 * by poll(). 363 */ 364 struct mhd_DaemonEventsPollData 365 { 366 /** 367 * Array of sockets monitored for read (receive) readiness. 368 * The size of the array is maximum number of connections per this daemon plus 369 * two (one for the listen socket and one for ITC). 370 * ITC FDs and the listening are always the first (and the second), if used. 371 * The number of elements is always two plus maximum number of connections 372 * allowed for the daemon. 373 */ 374 struct pollfd *fds; 375 /** 376 * Array of the @a fds identifications. 377 * Each slot matches the slot with the same number in @a fds. 378 * Up to two first positions reserved for the ITC and the listening. 379 * The number of elements is always two plus maximum number of connections 380 * allowed for the daemon. 381 */ 382 union mhd_SocketRelation *rel; 383 }; 384 385 #endif /* MHD_SUPPORT_POLL */ 386 387 #ifdef MHD_SUPPORT_EPOLL 388 /** 389 * Daemon's parameters and pointers to the preallocated memory for running 390 * sockets monitoring by epoll. 391 */ 392 struct mhd_DaemonEventsEPollData 393 { 394 /** 395 * The epoll control FD. 396 */ 397 int e_fd; 398 /** 399 * The array of events reported by epoll. 400 */ 401 struct epoll_event *events; 402 /** 403 * The number of elements in the allocated @a events arrays. 404 */ 405 size_t num_elements; 406 /** 407 * The epoll control FD, created by probing during early daemon 408 * initialisation. 409 * Temporal location. 410 * Must be moved to @a e_fd with events initialisation. 411 */ 412 int early_fd; 413 }; 414 415 #endif 416 417 #ifdef MHD_SUPPORT_KQUEUE 418 /** 419 * Daemon's parameters and pointers to the preallocated memory for running 420 * sockets monitoring by kqueue. 421 */ 422 struct mhd_DaemonEventsKQueueData 423 { 424 /** 425 * The kqueue FD. 426 */ 427 int kq_fd; 428 429 /** 430 * The array of kevents used for both registering filters and getting events 431 */ 432 struct kevent *kes; 433 434 /** 435 * The number of elements in the allocated @a kes array. 436 * 437 * Note: kqueue API uses 'int' for the number of elements 438 */ 439 unsigned int num_elements; 440 }; 441 442 #endif /* MHD_SUPPORT_KQUEUE */ 443 444 /** 445 * Daemon's data for external events callback. 446 * Internal version of struct MHD_WorkModeExternalEventLoopCBParam. 447 */ 448 struct mhd_DaemonEventsExternalCallback 449 { 450 /** 451 * Socket registration callback 452 */ 453 MHD_SocketRegistrationUpdateCallback cb; 454 /** 455 * Closure for the @a cb 456 */ 457 void *cls; 458 }; 459 460 461 #ifdef MHD_SUPPORT_THREADS 462 /** 463 * External events data for ITC FD 464 */ 465 struct mhd_DaemonEventsExternalDaemonItcData 466 { 467 /** 468 * Application context for ITC FD 469 */ 470 void *app_cntx; 471 472 /** 473 * Set to 'true' when active state was detected on ITC by 474 * external polling 475 */ 476 bool is_active; 477 478 /** 479 * Set to 'true' when error state was detected on ITC by 480 * external polling. 481 * The daemon may become non-functional. 482 */ 483 bool is_broken; 484 }; 485 #endif /* MHD_SUPPORT_THREADS */ 486 487 /** 488 * External events data for the listen socket 489 */ 490 struct mhd_DaemonEventsExternalDaemonListenData 491 { 492 /** 493 * Application context for ITC FD 494 */ 495 void *app_cntx; 496 }; 497 498 /** 499 * Daemon's data for external events for sockets monitoring. 500 */ 501 struct mhd_DaemonEventsExternal 502 { 503 /** 504 * Daemon's data for external events callback. 505 * Internal version of struct MHD_WorkModeExternalEventLoopCBParam. 506 */ 507 struct mhd_DaemonEventsExternalCallback cb_data; 508 509 #ifdef MHD_SUPPORT_THREADS 510 /** 511 * External events data for ITC FD 512 */ 513 struct mhd_DaemonEventsExternalDaemonItcData itc_data; 514 #endif /* MHD_SUPPORT_THREADS */ 515 516 /** 517 * External events data for the listen socket 518 */ 519 struct mhd_DaemonEventsExternalDaemonListenData listen_data; 520 521 /** 522 * If set to 'true' then all FDs must be registered each round. 523 * If set to 'false' then only changed FDs must be registered. 524 */ 525 bool reg_all; 526 }; 527 528 /** 529 * Type-specific events monitoring data 530 */ 531 union mhd_DaemonEventMonitoringTypeSpecificData 532 { 533 #ifdef MHD_SUPPORT_SELECT 534 /** 535 * Daemon's pointers to the preallocated arrays for running sockets monitoring 536 * by poll(). 537 */ 538 struct mhd_DaemonEventsSelectData select; 539 #endif /* MHD_SUPPORT_SELECT */ 540 541 #ifdef MHD_SUPPORT_POLL 542 /** 543 * Daemon's pointers to the preallocated arrays for running sockets monitoring 544 * by poll(). 545 */ 546 struct mhd_DaemonEventsPollData poll; 547 #endif /* MHD_SUPPORT_POLL */ 548 549 #ifdef MHD_SUPPORT_EPOLL 550 /** 551 * Daemon's parameters and pointers to the preallocated memory for running 552 * sockets monitoring by epoll. 553 */ 554 struct mhd_DaemonEventsEPollData epoll; 555 #endif 556 557 #ifdef MHD_SUPPORT_KQUEUE 558 /** 559 * Daemon's parameters and pointers to the preallocated memory for running 560 * sockets monitoring by kqueue. 561 */ 562 struct mhd_DaemonEventsKQueueData kq; 563 #endif 564 565 /** 566 * Daemon's data for external events for sockets monitoring. 567 */ 568 struct mhd_DaemonEventsExternal extr; 569 }; 570 571 572 struct mhd_DaemonExtAddedConn; /* Forward declaration */ 573 mhd_DLINKEDL_STRUCTS_DEFS (mhd_DaemonExtAddedConn); 574 575 /** 576 * Information about externally added connection 577 */ 578 struct mhd_DaemonExtAddedConn 579 { 580 /** 581 * The links to the other externally added connections in the queue 582 */ 583 mhd_DLNKDL_LINKS (mhd_DaemonExtAddedConn, queue); 584 585 /** 586 * The socket of the externally added connection 587 */ 588 MHD_Socket skt; 589 590 /** 591 * The size of the data pointed by @a addr. 592 * Zero fi @a addr is NULL. 593 */ 594 size_t addr_size; 595 596 /** 597 * Pointer to socket address. 598 * Allocated by malloc(), must be freed; 599 * May be NULL. 600 */ 601 struct sockaddr_storage *addr; 602 603 /** 604 * 'true' if @a skt is non-blocking 605 */ 606 bool is_nonblock; 607 608 /** 609 * 'true' if @a skt has SIGPIPE suppressed 610 */ 611 bool has_spipe_suppr; 612 }; 613 614 615 /** 616 * Information about externally added connections for the worker daemon 617 */ 618 struct mhd_DaemonExtAddedConnectionsWorker 619 { 620 #ifdef MHD_SUPPORT_THREADS 621 /** 622 * The lock to access @a queue list 623 */ 624 mhd_mutex q_lock; 625 #endif /* MHD_SUPPORT_THREADS */ 626 /** 627 * The list with the queue of externally added connections 628 */ 629 mhd_DLNKDL_LIST (mhd_DaemonExtAddedConn, queue); 630 }; 631 632 #ifdef MHD_SUPPORT_THREADS 633 /** 634 * Information about externally added connections for the master daemon 635 */ 636 struct mhd_DaemonExtAddedConnectionsMaster 637 { 638 /** 639 * The index (modulo number of workers) of the next worker daemon to add 640 * connection 641 */ 642 struct mhd_AtomicCounter next_d_idx; 643 }; 644 #endif /* MHD_SUPPORT_THREADS */ 645 646 /** 647 * Information about externally added connections 648 */ 649 union mhd_DaemonExtAddedConnections 650 { 651 #ifdef MHD_SUPPORT_THREADS 652 /** 653 * Information about externally added connections for the master daemon 654 */ 655 struct mhd_DaemonExtAddedConnectionsMaster master; 656 #endif /* MHD_SUPPORT_THREADS */ 657 /** 658 * Information about externally added connections for the worker daemon 659 */ 660 struct mhd_DaemonExtAddedConnectionsWorker worker; 661 }; 662 663 664 /** 665 * The required actions for the daemon 666 */ 667 struct mhd_DaemonEventActionRequired 668 { 669 /** 670 * If 'true' connection resuming is required. 671 */ 672 bool resume; 673 674 /** 675 * Information about externally added connections 676 */ 677 union mhd_DaemonExtAddedConnections ext_added; 678 }; 679 680 /** 681 * The daemon's time data 682 */ 683 struct mhd_DaemonEventsCurTime 684 { 685 /** 686 * 'true' if @a cur is set 687 */ 688 bool is_set; 689 /** 690 * Current value of monotonic milliseconds counter. 691 * Valid only if @a is_set is 'true'. 692 * Updated once per processing round. 693 */ 694 uint_fast64_t cur; 695 }; 696 697 /** 698 * The data for events monitoring 699 */ 700 struct mhd_DaemonEventMonitoringData 701 { 702 /** 703 * Sockets polling type used by the daemon. 704 */ 705 enum mhd_IntPollType poll_type; 706 707 /** 708 * Type-specific events monitoring data 709 */ 710 union mhd_DaemonEventMonitoringTypeSpecificData data; 711 712 /** 713 * The required actions for the daemon. 714 */ 715 struct mhd_DaemonEventActionRequired act_req; 716 717 /** 718 * When set to 'true' the listen socket has new incoming connection(s). 719 */ 720 bool accept_pending; 721 722 /** 723 * The list of the daemon's connections that need processing 724 */ 725 mhd_DLNKDL_LIST (MHD_Connection, proc_ready); 726 727 /** 728 * The daemon's time data 729 */ 730 struct mhd_DaemonEventsCurTime time; 731 }; 732 733 734 /** 735 * The type of the socket 736 */ 737 enum MHD_FIXED_ENUM_ mhd_SocketType 738 { 739 /** 740 * The socket type is some non-IP type. 741 */ 742 mhd_SOCKET_TYPE_NON_IP = -2 743 , 744 /** 745 * The socket type is UNIX (LOCAL) 746 */ 747 mhd_SOCKET_TYPE_UNIX = -1 748 , 749 /** 750 * The socket is unknown yet. It can be IP or non-IP. 751 */ 752 mhd_SOCKET_TYPE_UNKNOWN = 0 753 , 754 /** 755 * The socket is definitely IP. 756 */ 757 mhd_SOCKET_TYPE_IP = 1 758 }; 759 760 /** 761 * Listen socket data 762 */ 763 struct mhd_ListenSocket 764 { 765 /** 766 * The listening socket 767 */ 768 MHD_Socket fd; 769 /** 770 * Set to 'true' when unrecoverable error is detected on the listen socket. 771 * If set to 'true', but @a fd is not #MHD_INVALID_SOCKET then "broken" state 772 * has not yet processed by MHD. 773 */ 774 bool is_broken; 775 /** 776 * The type of the listening socket @a fd 777 */ 778 enum mhd_SocketType type; 779 /** 780 * 'true' if @a fd is non-blocking 781 */ 782 bool non_block; 783 /** 784 * The port number for @a fd 785 * 786 * Zero if unknown and for non-IP socket. 787 */ 788 uint_least16_t port; 789 }; 790 791 /** 792 * Configured settings for the daemon's network data 793 */ 794 struct mhd_DaemonNetworkSettings 795 { 796 #ifdef MHD_SOCKETS_KIND_POSIX 797 /** 798 * The maximum number for the network FDs. 799 * The valid FD number must be less then @a max_fd_num. 800 */ 801 MHD_Socket max_fd_num; 802 #else 803 int dummy; /* mute compiler warning */ 804 #endif 805 }; 806 807 /** 808 * The daemon network/sockets data 809 * 810 * This structure holds mostly static information -- typically initialised once 811 * when the daemon starts, and possibly updated once later (e.g., if the 812 * listening socket fails or is closed). 813 * 814 * It does NOT contain any operational states. 815 */ 816 struct mhd_DaemonNetwork 817 { 818 /** 819 * The listening socket 820 */ 821 struct mhd_ListenSocket listen; 822 /** 823 * Configured settings for the daemon's network data 824 */ 825 struct mhd_DaemonNetworkSettings cfg; 826 }; 827 828 #ifdef MHD_SUPPORT_AUTH_DIGEST 829 830 /** 831 * Digest Auth nonce data 832 */ 833 struct mhd_DaemonAuthDigestNonceData 834 { 835 /** 836 * The nonce value in the binary form, excluding validity tail 837 */ 838 uint8_t nonce[mhd_AUTH_DIGEST_NONCE_RAND_BIN_SIZE]; 839 840 /** 841 * The nonce validity time 842 */ 843 uint_fast32_t valid_time; 844 845 /** 846 * The largest last received 'nc' value. 847 * This 'nc' value has been already used by the client. 848 */ 849 uint_fast32_t max_recvd_nc; 850 851 /** 852 * Bitmask over the previous 64 nc values (down to to nc-64). 853 * Used to allow out-of-order 'nc'. 854 * If bit in the bitmask is set to one, then this 'nc' value was already used 855 * by the client. 856 */ 857 uint_fast64_t nmask; 858 }; 859 860 /** 861 * Digest Auth daemon configuration data 862 */ 863 struct mhd_DaemonAuthDigestCfg 864 { 865 /** 866 * The number of elements in the nonces array 867 */ 868 size_t nonces_num; 869 870 /** 871 * The nonce validity time (in seconds) 872 */ 873 unsigned int nonce_tmout; 874 875 /** 876 * The default maximum value of nc 877 */ 878 uint_fast32_t def_max_nc; 879 }; 880 881 /** 882 * The Digest Auth daemon's data 883 */ 884 struct mhd_DaemonAuthDigestData 885 { 886 /** 887 * The entropy data used for Digests generation 888 */ 889 struct mhd_Buffer entropy; 890 891 /** 892 * The array of generated nonce and related nc 893 */ 894 struct mhd_DaemonAuthDigestNonceData *nonces; 895 896 /** 897 * Number of nonces has been generated. 898 * Used as addition for the nonce source data to ensure unique nonce value. 899 * TODO: remove and directly use random generator for nonce generation. 900 */ 901 struct mhd_AtomicCounter num_gen_nonces; 902 903 # ifdef MHD_SUPPORT_THREADS 904 /** 905 * The mutex to change or access the @a nonces data 906 */ 907 mhd_mutex nonces_lock; 908 # endif 909 910 /** 911 * Digest Auth daemon configuration data 912 */ 913 struct mhd_DaemonAuthDigestCfg cfg; 914 }; 915 916 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 917 918 #ifdef MHD_SUPPORT_ACME 919 920 /** 921 * Daemon's ACME data 922 */ 923 struct mhd_DaemonAcmeData 924 { 925 # ifdef mhd_HAVE_TLS_ACME 926 /** 927 * Special certificates for ACME ALPN challenges 928 */ 929 struct mhd_TlsCertsList alpn; 930 # else 931 /** 932 * Unused 933 */ 934 int dummy; /* TODO: A placeholder. Remove after adding non-TLS data */ 935 # endif /* MHD_SUPPORT_HTTPS */ 936 }; 937 #endif /* MHD_SUPPORT_ACME */ 938 939 940 #ifdef MHD_SUPPORT_THREADS 941 942 /** 943 * The type of the daemon 944 */ 945 enum MHD_FIXED_ENUM_ mhd_DaemonType 946 { 947 /** 948 * A single daemon, performing all the work. 949 * 950 * This daemon may have a optional single thread, managed by MHD. 951 */ 952 mhd_DAEMON_TYPE_SINGLE 953 # ifndef NDEBUG 954 = 1 955 # endif 956 # ifdef MHD_SUPPORT_THREADS 957 , 958 /** 959 * A master daemon, only controlling worker daemons. 960 * 961 * This daemon never handle any network activity directly. 962 */ 963 mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY 964 , 965 /** 966 * A daemon with single internal thread for listening and multiple threads 967 * handling connections with the clients, one thread per connection. 968 */ 969 mhd_DAEMON_TYPE_LISTEN_ONLY 970 , 971 /** 972 * A worker daemon, performing the same work as a single daemon, but 973 * controlled by master daemon. 974 * 975 * This type of daemon always have single internal tread and never exposed 976 * to application directly. 977 */ 978 mhd_DAEMON_TYPE_WORKER 979 # endif /* MHD_SUPPORT_THREADS */ 980 }; 981 982 /** 983 * Check whether the daemon type is allowed to have internal thread with 984 * direct control 985 */ 986 # define mhd_D_TYPE_IS_VALID(t) \ 987 ((mhd_DAEMON_TYPE_SINGLE <= (t)) && (mhd_DAEMON_TYPE_WORKER >= (t))) 988 989 /** 990 * Check whether the daemon type must not be exposed to the application 991 */ 992 # define mhd_D_TYPE_IS_INTERNAL_ONLY(t) \ 993 (mhd_DAEMON_TYPE_WORKER == (t)) 994 /** 995 * Check whether the daemon type is allowed to process the network data 996 */ 997 # define mhd_D_TYPE_HAS_EVENTS_PROCESSING(t) \ 998 (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY != (t)) 999 1000 /** 1001 * Check whether the daemon type must not be exposed to the application 1002 */ 1003 # define mhd_D_TYPE_HAS_WORKERS(t) \ 1004 (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY == (t)) 1005 1006 /** 1007 * Check whether the daemon type has master (controlling) daemon 1008 */ 1009 # define mhd_D_TYPE_HAS_MASTER_DAEMON(t) \ 1010 (mhd_DAEMON_TYPE_WORKER == (t)) 1011 1012 /** 1013 * Check whether the daemon is listening only (with connection data 1014 * processed in separate threads) 1015 */ 1016 # define mhd_D_TYPE_IS_LISTEN_ONLY(t) \ 1017 (mhd_DAEMON_TYPE_LISTEN_ONLY == (t)) 1018 1019 #else /* ! MHD_SUPPORT_THREADS */ 1020 1021 /** 1022 * Check whether the daemon type is allowed to have internal thread with 1023 * direct control 1024 */ 1025 # define mhd_D_TYPE_IS_VALID(t) (! 0) 1026 1027 /** 1028 * Check whether the daemon type must not be exposed to the application 1029 */ 1030 # define mhd_D_TYPE_IS_INTERNAL_ONLY(t) (0) 1031 1032 /** 1033 * Check whether the daemon type is allowed to process the network data 1034 */ 1035 # define mhd_D_TYPE_HAS_EVENTS_PROCESSING(t) (! 0) 1036 1037 /** 1038 * Check whether the daemon type must not be exposed to the application 1039 */ 1040 # define mhd_D_TYPE_HAS_WORKERS(t) (0) 1041 1042 /** 1043 * Check whether the daemon type has master (controlling) daemon 1044 */ 1045 # define mhd_D_TYPE_HAS_MASTER_DAEMON(t) (0) 1046 1047 /** 1048 * Check whether the daemon is listening only (with connection data 1049 * processed in separate threads) 1050 */ 1051 # define mhd_D_TYPE_IS_LISTEN_ONLY(t) (0) 1052 1053 #endif /* ! MHD_SUPPORT_THREADS */ 1054 1055 #ifdef MHD_SUPPORT_THREADS 1056 1057 /** 1058 * Workers pool data 1059 */ 1060 struct mhd_DaemonWorkerPoolData 1061 { 1062 /** 1063 * Array of worker daemons 1064 */ 1065 struct MHD_Daemon *workers; 1066 1067 /** 1068 * The number of workers in the @a workers array 1069 */ 1070 unsigned int num; 1071 }; 1072 1073 /** 1074 * Hierarchy data for the daemon 1075 */ 1076 union mhd_DaemonHierarchyData 1077 { 1078 /** 1079 * The pointer to the master daemon 1080 * Only for #mhd_DAEMON_TYPE_WORKER daemons. 1081 */ 1082 struct MHD_Daemon *master; 1083 1084 /** 1085 * Workers pool data. 1086 * Only for #mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY daemons. 1087 */ 1088 struct mhd_DaemonWorkerPoolData pool; 1089 }; 1090 1091 /** 1092 * Configured settings for threading 1093 */ 1094 struct mhd_DaemonThreadingDataSettings 1095 { 1096 /** 1097 * The size of the stack. 1098 * Zero to use system's defaults. 1099 */ 1100 size_t stack_size; 1101 }; 1102 1103 /** 1104 * Threading and Inter-Thread Communication data 1105 */ 1106 struct mhd_DaemonThreadingData 1107 { 1108 /** 1109 * The type of this daemon 1110 */ 1111 enum mhd_DaemonType d_type; 1112 1113 /** 1114 * Inter-Thread Communication channel. 1115 * Used to trigger processing of the command or the data provided or updated 1116 * by the application. 1117 */ 1118 struct mhd_itc itc; 1119 1120 /** 1121 * 'True' if stop has been requested. 1122 * The daemon thread should stop all connections and then close. 1123 */ 1124 volatile bool stop_requested; 1125 1126 /** 1127 * The handle of the daemon's thread (if managed by the daemon) 1128 */ 1129 mhd_thread_handle_ID tid; 1130 1131 /** 1132 * The hierarchy data for the daemon. 1133 * Used only when @a d_type is #mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY or 1134 * #mhd_DAEMON_TYPE_WORKER. 1135 */ 1136 union mhd_DaemonHierarchyData hier; 1137 1138 /** 1139 * Configured settings for threading 1140 */ 1141 struct mhd_DaemonThreadingDataSettings cfg; 1142 }; 1143 1144 #endif /* MHD_SUPPORT_THREADS */ 1145 1146 /** 1147 * Configured settings for the daemon's connections 1148 */ 1149 struct mhd_DaemonConnectionsSettings 1150 { 1151 /** 1152 * The maximum number of connections handled by the daemon 1153 */ 1154 unsigned int count_limit; 1155 1156 /** 1157 * The maximum number of connections per any IP handled by the daemon 1158 */ 1159 unsigned int per_ip_limit; 1160 1161 /** 1162 * Connection's default timeout value (in milliseconds) 1163 */ 1164 uint_fast32_t timeout_milsec; 1165 1166 /** 1167 * Connection's memory pool size 1168 */ 1169 size_t mem_pool_size; 1170 1171 /** 1172 * Memory pool zeroing mode 1173 */ 1174 enum mhd_MemPoolZeroing mem_pool_zeroing; 1175 }; 1176 1177 #ifdef MHD_SUPPORT_UPGRADE 1178 1179 /** 1180 * The data for HTTP-Upgraded connections 1181 */ 1182 struct mhd_DaemonConnectionsUpgraded 1183 { 1184 /** 1185 * The list of HTTP-Upgraded connection closed by application and 1186 * queued for cleanup 1187 */ 1188 mhd_DLNKDL_LIST (MHD_Connection, upgr_cleanup); 1189 1190 # ifdef MHD_SUPPORT_THREADS 1191 /** 1192 * The mutex to change or check the @a upgr_cleanup list values 1193 */ 1194 mhd_mutex ucu_lock; 1195 # endif 1196 }; 1197 1198 #endif /* MHD_SUPPORT_UPGRADE */ 1199 1200 /** 1201 * Connections handling data 1202 */ 1203 struct mhd_DaemonConnections 1204 { 1205 1206 /** 1207 * The list of all daemon's connections. 1208 * All connection are listed here, expect connection in @a to_clean list. 1209 */ 1210 mhd_DLNKDL_LIST (MHD_Connection, all_conn); 1211 1212 /** 1213 * The list of connections sorted by last activity 1214 */ 1215 mhd_DLNKDL_LIST (MHD_Connection, def_timeout); 1216 1217 /** 1218 * The list of connections with custom timeouts 1219 */ 1220 mhd_DLNKDL_LIST (MHD_Connection, cust_timeout); 1221 1222 /** 1223 * The current number of connections handled by the daemon 1224 */ 1225 unsigned int count; 1226 1227 /** 1228 * If set to 'true' then no new connection is allowed. 1229 * New connection may be blocked because of various system limits, when 1230 * additional connection would fail anyway. This flag should be cleared 1231 * when any already processing connection closed. 1232 * Can be checked from other threads 1233 */ 1234 volatile bool block_new; 1235 1236 /** 1237 * Configured settings for the daemon's connections 1238 */ 1239 struct mhd_DaemonConnectionsSettings cfg; 1240 1241 #ifdef MHD_SUPPORT_UPGRADE 1242 /** 1243 * The data for HTTP-Upgraded connections 1244 */ 1245 struct mhd_DaemonConnectionsUpgraded upgr; 1246 #endif /* MHD_SUPPORT_UPGRADE */ 1247 }; 1248 1249 /** 1250 * Early URI callback 1251 */ 1252 struct mhd_DaemonRequestUriCB 1253 { 1254 /** 1255 * The callback 1256 */ 1257 MHD_EarlyUriLogCallback cb; 1258 /** 1259 * The callback closure 1260 */ 1261 void *cls; 1262 }; 1263 1264 /** 1265 * Shared large buffer data 1266 */ 1267 struct mhd_DaemonLargeBuffer 1268 { 1269 /** 1270 * The amount of memory left allowed to be allocated for the large buffer 1271 */ 1272 size_t space_left; 1273 1274 #ifdef MHD_SUPPORT_THREADS 1275 /** 1276 * The mutex to change or check the @a space_left value 1277 */ 1278 mhd_mutex lock; 1279 #endif 1280 }; 1281 1282 #ifdef MHD_SUPPORT_HTTP2 1283 1284 /** 1285 * Generic settings for HTTP layer communication handling. 1286 * 1287 * These settings do not include specific settings for requests processing. 1288 */ 1289 struct mhd_DaemonHttpSettings 1290 { 1291 /** 1292 * 'true' if HTTP/1.x communication is allowed 1293 */ 1294 bool http1x; 1295 /** 1296 * 'true' if HTTP/2 communication is allowed 1297 */ 1298 bool http2; 1299 }; 1300 1301 #endif /* MHD_SUPPORT_HTTP2 */ 1302 1303 /** 1304 * Settings for requests processing 1305 */ 1306 struct mhd_DaemonRequestProcessingSettings 1307 { 1308 /** 1309 * Request callback. 1310 * The main request processing callback. 1311 */ 1312 MHD_RequestCallback cb; 1313 1314 /** 1315 * The closure for @a req_cb 1316 */ 1317 void *cb_cls; 1318 1319 /** 1320 * Protocol strictness enforced by MHD on clients. 1321 */ 1322 enum MHD_ProtocolStrictLevel strictness; 1323 1324 #ifdef MHD_SUPPORT_COOKIES 1325 /** 1326 * Disable automatic cookies parsing 1327 */ 1328 bool disable_cookies; 1329 #endif 1330 1331 /** 1332 * Early URI callback 1333 */ 1334 struct mhd_DaemonRequestUriCB uri_cb; // TODO: set from settings 1335 1336 /** 1337 * Shared large buffer data 1338 */ 1339 struct mhd_DaemonLargeBuffer large_buf; // TODO: set from settings 1340 1341 /** 1342 * Suppress "Date:" header in responses 1343 */ 1344 bool suppress_date; 1345 }; 1346 1347 1348 /** 1349 * Get whether bare LF in HTTP header and other protocol elements 1350 * should be treated as the line termination depending on the configured 1351 * strictness level. 1352 * RFC 9112, section 2.2 1353 */ 1354 #define mhd_ALLOW_BARE_LF_AS_CRLF(strictness) (0 >= strictness) 1355 1356 1357 #ifndef NDEBUG 1358 /** 1359 * Various debugging data 1360 */ 1361 struct mhd_daemon_debug 1362 { 1363 bool net_inited; 1364 bool net_deinited; 1365 bool master_only_inited; 1366 bool worker_only_inited; 1367 bool events_fd_inited; 1368 bool tls_inited; 1369 bool events_allocated; 1370 unsigned int num_events_elements; 1371 bool events_fully_inited; 1372 bool thread_pool_inited; 1373 bool threading_inited; 1374 bool connections_inited; 1375 bool avoid_accept4; 1376 size_t initial_lbuf_size; 1377 }; 1378 #endif /* NDEBUG */ 1379 1380 1381 struct MHD_Daemon 1382 { 1383 /* General data */ 1384 1385 /** 1386 * The daemon state 1387 */ 1388 enum mhd_DaemonState state; 1389 1390 /** 1391 * The daemon work mode (private version) 1392 */ 1393 enum mhd_WorkModeIntType wmode_int; 1394 1395 /* Events/sockets monitoring/polling data */ 1396 1397 /** 1398 * The data for events monitoring 1399 */ 1400 struct mhd_DaemonEventMonitoringData events; 1401 1402 /* Network/sockets data */ 1403 1404 /** 1405 * The daemon network/sockets data 1406 * 1407 * This structure holds mostly static information -- typically initialised 1408 * once when the daemon starts, and possibly updated once later (e.g., if the 1409 * listening socket fails or is closed). 1410 * 1411 * It does NOT contain any operational states. 1412 */ 1413 struct mhd_DaemonNetwork net; 1414 1415 #ifdef MHD_SUPPORT_AUTH_DIGEST 1416 /** 1417 * The Digest Auth daemon's data 1418 */ 1419 struct mhd_DaemonAuthDigestData auth_dg; 1420 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 1421 1422 #ifdef MHD_SUPPORT_ACME 1423 /** 1424 * Daemon's ACME data 1425 */ 1426 struct mhd_DaemonAcmeData acme; 1427 #endif /* MHD_SUPPORT_ACME */ 1428 1429 #ifdef MHD_SUPPORT_HTTPS 1430 /** 1431 * The pointer to the daemon TLS data. 1432 * If set to non-NULL then HTTPS protocol is used, if set to NULL then 1433 * plain HTTP protocol used. 1434 */ 1435 struct mhd_TlsDaemonData *tls; 1436 #endif /* MHD_SUPPORT_HTTPS */ 1437 1438 #ifdef MHD_SUPPORT_THREADS 1439 /* Threading data */ 1440 1441 /** 1442 * The daemon threading and Inter-Thread Communication data 1443 */ 1444 struct mhd_DaemonThreadingData threading; 1445 #endif 1446 1447 /* Connections handling */ 1448 1449 /** 1450 * The connections handling data 1451 */ 1452 struct mhd_DaemonConnections conns; 1453 1454 1455 /* HTTP communication layer */ 1456 #ifdef MHD_SUPPORT_HTTP2 1457 /** 1458 * Generic settings for HTTP layer communication handling. 1459 * 1460 * These settings do not include specific settings for requests processing. 1461 */ 1462 struct mhd_DaemonHttpSettings http_cfg; 1463 #endif /* MHD_SUPPORT_HTTP2 */ 1464 1465 1466 /* Request processing data */ 1467 1468 /** 1469 * Settings for requests processing 1470 */ 1471 struct mhd_DaemonRequestProcessingSettings req_cfg; 1472 1473 /* Other data */ 1474 1475 /** 1476 * Daemon logging parameters 1477 */ 1478 struct MHD_DaemonOptionValueLog log_params; 1479 1480 1481 /* Temporal data */ 1482 1483 /** 1484 * User settings, before applied to the daemon itself 1485 */ 1486 struct DaemonOptions *settings; 1487 1488 #ifndef NDEBUG 1489 /* Debug data */ 1490 1491 struct mhd_daemon_debug dbg; 1492 #endif 1493 }; 1494 1495 1496 #ifdef MHD_SOCKETS_KIND_POSIX 1497 /** 1498 * Checks whether @a fd socket number fits limitations for the @a d_ptr daemon 1499 */ 1500 # define mhd_FD_FITS_DAEMON(d_ptr, fd) \ 1501 ((MHD_INVALID_SOCKET == d_ptr->net.cfg.max_fd_num) || \ 1502 (d_ptr->net.cfg.max_fd_num > fd)) 1503 #else 1504 # define mhd_FD_FITS_DAEMON(d_ptr, fd) (! 0) 1505 #endif 1506 1507 #define mhd_D_IS_USING_EPOLL(d) \ 1508 mhd_POLL_TYPE_INT_IS_EPOLL ((d)->events.poll_type) 1509 1510 #define mhd_D_IS_USING_KQUEUE(d) \ 1511 mhd_POLL_TYPE_INT_IS_KQUEUE ((d)->events.poll_type) 1512 1513 #define mhd_D_POLL_IS_EDGE_TRIG(d) \ 1514 mhd_POLL_TYPE_INT_IS_EDGE_TRIG ((d)->events.poll_type) 1515 1516 /** 1517 * Check whether the daemon has edge-triggered sockets polling 1518 */ 1519 #define mhd_D_HAS_EDGE_TRIGG(d) \ 1520 ((mhd_WM_INT_EXTERNAL_EVENTS_EDGE == (d)->wmode_int) || \ 1521 mhd_D_POLL_IS_EDGE_TRIG (d)) 1522 1523 #ifdef MHD_SUPPORT_THREADS 1524 # define mhd_D_HAS_THREADS(d) mhd_WM_INT_HAS_THREADS ((d)->wmode_int) 1525 #else 1526 # define mhd_D_HAS_THREADS(d) (0) 1527 #endif 1528 1529 #ifdef MHD_SUPPORT_THREADS 1530 # define mhd_D_HAS_THR_PER_CONN(d) \ 1531 (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == \ 1532 ((d)->wmode_int)) 1533 #else 1534 # define mhd_D_HAS_THR_PER_CONN(d) (0) 1535 #endif 1536 1537 #ifdef MHD_SUPPORT_THREADS 1538 # define mhd_D_HAS_STOP_REQ(d) (d->threading.stop_requested) 1539 #else 1540 # define mhd_D_HAS_STOP_REQ(d) (0) 1541 #endif 1542 1543 #define mhd_D_HAS_WORKERS(d) mhd_D_TYPE_HAS_WORKERS ((d)->threading.d_type) 1544 1545 #define mhd_D_HAS_MASTER(d) mhd_D_TYPE_HAS_MASTER_DAEMON ((d)->threading.d_type) 1546 1547 #define mhd_D_IS_INTERNAL_ONLY(d) \ 1548 mhd_D_TYPE_IS_INTERNAL_ONLY ((d)->threading.d_type) 1549 1550 #ifdef MHD_SUPPORT_HTTPS 1551 /** 1552 * Returns non-zero if daemon has TLS enabled or zero otherwise 1553 */ 1554 # define mhd_D_HAS_TLS(d) (((d)->tls) ? (! 0) : (0)) 1555 #else 1556 /** 1557 * Returns non-zero if daemon has TLS enabled or zero otherwise 1558 */ 1559 # define mhd_D_HAS_TLS(d) (0) 1560 #endif 1561 1562 /* 1563 * Check whether the daemon support Digest Auth 1564 */ 1565 #ifdef MHD_SUPPORT_AUTH_DIGEST 1566 # define mhd_D_HAS_AUTH_DIGEST(d) (NULL != (d)->auth_dg.nonces) 1567 #else 1568 # define mhd_D_HAS_AUTH_DIGEST(d) (! ! 0) 1569 #endif 1570 1571 #ifdef MHD_SUPPORT_HTTP2 1572 # define mhd_D_IS_HTTP1_ENABLED(d) (d->http_cfg.http1x) 1573 # define mhd_D_IS_HTTP2_ENABLED(d) (d->http_cfg.http2) 1574 #else /* ! MHD_SUPPORT_HTTP2 */ 1575 # define mhd_D_IS_HTTP1_ENABLED(d) (! 0) 1576 # define mhd_D_IS_HTTP2_ENABLED(d) (! ! 0) 1577 #endif /* ! MHD_SUPPORT_HTTP2 */ 1578 1579 1580 #endif /* ! MHD_DAEMON_H */