mhd_daemon.h (30891B)
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 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 80 #include "mempool_types.h" 81 82 #include "mhd_public_api.h" 83 84 struct DaemonOptions; /* Forward declaration */ 85 struct MHD_Connection; /* Forward declaration */ 86 87 /** 88 * The helper struct for the connections list 89 */ 90 mhd_DLINKEDL_LIST_DEF (MHD_Connection); 91 92 /** 93 * The current phase of the daemon life 94 */ 95 enum MHD_FIXED_ENUM_ mhd_DaemonState 96 { 97 /** 98 * The daemon has been created, but not yet started. 99 * Setting configuration options is possible. 100 */ 101 mhd_DAEMON_STATE_NOT_STARTED = 0 102 , 103 /** 104 * The daemon is being started. 105 */ 106 mhd_DAEMON_STATE_STARTING 107 , 108 /** 109 * The daemon has been started. 110 * Normal operations. 111 */ 112 mhd_DAEMON_STATE_STARTED 113 , 114 /** 115 * The daemon has failed to start 116 */ 117 mhd_DAEMON_STATE_FAILED 118 , 119 /** 120 * The daemon is being stopped. 121 */ 122 mhd_DAEMON_STATE_STOPPING 123 , 124 /** 125 * The daemon is stopped. 126 * The state should rarely visible as daemon should be destroyed when stopped. 127 */ 128 mhd_DAEMON_STATE_STOPPED 129 }; 130 131 132 /** 133 * Internal version of the daemon work mode type 134 */ 135 enum MHD_FIXED_ENUM_ mhd_WorkModeIntType 136 { 137 /** 138 * Network edge-triggered events are monitored and provided by application. 139 * Receiving, sending and processing of the network data if performed when 140 * special MHD function is called by application. 141 * No threads managed by the daemon. 142 */ 143 mhd_WM_INT_EXTERNAL_EVENTS_EDGE 144 , 145 /** 146 * Network level-triggered events are monitored and provided by application. 147 * Receiving, sending and processing of the network data if performed when 148 * special MHD function is called by application. 149 * No threads managed by the daemon. 150 */ 151 mhd_WM_INT_EXTERNAL_EVENTS_LEVEL 152 , 153 /** 154 * The daemon checks for the network events, receives, sends and process 155 * the network data when special MHD function is called by application. 156 * No threads managed by the daemon. 157 */ 158 mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS 159 #ifdef MHD_SUPPORT_THREADS 160 , 161 /** 162 * The daemon runs its own single thread, where the daemon monitors 163 * all network events, receives, sends and process the network data. 164 */ 165 mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD 166 , 167 /** 168 * The daemon runs its own single thread, where the daemon monitors 169 * the new incoming connections, and runs individual thread for each 170 * established connection, where the daemon monitors connection, receives, 171 * sends and process the network data. 172 */ 173 mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION 174 , 175 /** 176 * The daemon runs its fixed number of threads, all threads monitors the 177 * new incoming connections and each thread handles own subset of the network 178 * connections (monitors connections network events, receives, sends and 179 * process the network data). 180 */ 181 mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL 182 #endif 183 }; 184 185 #ifdef MHD_SUPPORT_THREADS 186 /** 187 * Check whether given mhd_WorkModeIntType value should have internal threads, 188 * either directly controlled or indirectly, via additional workers daemons. 189 */ 190 # define mhd_WM_INT_HAS_THREADS(wm_i) \ 191 (mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD <= wm_i) 192 /** 193 * Check whether given mhd_WorkModeIntType value equals "thread-per-connection" 194 */ 195 # define mhd_WM_INT_IS_THREAD_PER_CONN(wm_i) \ 196 (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == wm_i) 197 /** 198 * Check whether given mhd_WorkModeIntType value equals "thread pool" 199 */ 200 # define mhd_WM_INT_IS_THREAD_POOL(wm_i) \ 201 (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == wm_i) 202 #else /* ! MHD_SUPPORT_THREADS */ 203 # define mhd_WM_INT_HAS_THREADS(wm_i) (0) 204 # define mhd_WM_INT_IS_THREAD_PER_CONN(wm_i) (0) 205 # define mhd_WM_INT_IS_THREAD_POOL(wm_i) (0) 206 #endif /* ! MHD_SUPPORT_THREADS */ 207 208 /** 209 * Check whether given mhd_WorkModeIntType value has external events 210 */ 211 #define mhd_WM_INT_HAS_EXT_EVENTS(wm_i) \ 212 (mhd_WM_INT_EXTERNAL_EVENTS_LEVEL >= wm_i) 213 214 215 /** 216 * Sockets polling internal syscalls used by MHD. 217 * 218 * The same value used as by #MHD_SockPollSyscall, however instead of "auto" 219 * method this enum uses "not yet set" and enum is extended with an additional 220 * "external" value. 221 */ 222 enum MHD_FIXED_ENUM_ mhd_IntPollType 223 { 224 /** 225 * External sockets polling is used. 226 */ 227 mhd_POLL_TYPE_EXT = -1 228 , 229 /** 230 * Internal sockets polling syscall has not been selected yet. 231 */ 232 mhd_POLL_TYPE_NOT_SET_YET = MHD_SPS_AUTO 233 , 234 /** 235 * Use select(). 236 */ 237 mhd_POLL_TYPE_SELECT = MHD_SPS_SELECT 238 , 239 /** 240 * Use poll(). 241 */ 242 mhd_POLL_TYPE_POLL = MHD_SPS_POLL 243 #ifdef MHD_SUPPORT_EPOLL 244 , 245 /** 246 * Use epoll. 247 */ 248 mhd_POLL_TYPE_EPOLL = MHD_SPS_EPOLL 249 #endif /* MHD_SUPPORT_EPOLL */ 250 }; 251 252 253 #ifdef MHD_SUPPORT_EPOLL 254 /** 255 * Check whether provided mhd_IntPollType value is "epoll" 256 */ 257 # define mhd_POLL_TYPE_INT_IS_EPOLL(poll_type) \ 258 (mhd_POLL_TYPE_EPOLL == poll_type) 259 #else 260 # define mhd_POLL_TYPE_INT_IS_EPOLL(poll_type) (0) 261 #endif 262 263 #if defined(HAVE_UINTPTR_T) 264 typedef uintptr_t mhd_SockRelMarker; 265 #else 266 typedef unsigned char *mhd_SockRelMarker; 267 #endif 268 269 270 #define mhd_SOCKET_REL_MARKER_EMPTY ((mhd_SockRelMarker) (0)) 271 272 #define mhd_SOCKET_REL_MARKER_ITC ((mhd_SockRelMarker) (-1)) 273 274 #define mhd_SOCKET_REL_MARKER_LISTEN (mhd_SOCKET_REL_MARKER_ITC - 1) 275 /** 276 * Identifier of the FD related to event 277 */ 278 union mhd_SocketRelation 279 { 280 /** 281 * Identifier of the FD. 282 * Only valid when it is equal to #mhd_SOCKET_REL_MARKER_EMPTY, 283 * #mhd_SOCKET_REL_MARKER_ITC or #mhd_SOCKET_REL_MARKER_LISTEN. 284 */ 285 mhd_SockRelMarker fd_id; 286 /** 287 * This is a connection's FD. 288 * This is valid only when @a fd_id is not valid. 289 */ 290 struct MHD_Connection *connection; 291 }; 292 293 #ifdef MHD_SUPPORT_SELECT 294 295 /** 296 * Daemon's pointers to the preallocated arrays for running sockets monitoring 297 * by poll(). 298 */ 299 struct mhd_DaemonEventsSelectData 300 { 301 /** 302 * Set of sockets monitored for read (receive) readiness. 303 */ 304 fd_set *rfds; 305 /** 306 * Set of sockets monitored for write (send) readiness. 307 */ 308 fd_set *wfds; 309 /** 310 * Set of sockets monitored for exception (error) readiness. 311 */ 312 fd_set *efds; 313 }; 314 315 #endif /* MHD_SUPPORT_SELECT */ 316 317 #ifdef MHD_SUPPORT_POLL 318 319 /** 320 * Daemon's pointers to the preallocated arrays for running sockets monitoring 321 * by poll(). 322 */ 323 struct mhd_DaemonEventsPollData 324 { 325 /** 326 * Array of sockets monitored for read (receive) readiness. 327 * The size of the array is maximum number of connections per this daemon plus 328 * two (one for the listen socket and one for ITC). 329 * ITC FDs and the listening are always the first (and the second), if used. 330 * The number of elements is always two plus maximum number of connections 331 * allowed for the daemon. 332 */ 333 struct pollfd *fds; 334 /** 335 * Array of the @a fds identifications. 336 * Each slot matches the slot with the same number in @a fds. 337 * Up to two first positions reserved for the ITC and the listening. 338 * The number of elements is always two plus maximum number of connections 339 * allowed for the daemon. 340 */ 341 union mhd_SocketRelation *rel; 342 }; 343 344 #endif /* MHD_SUPPORT_POLL */ 345 346 #ifdef MHD_SUPPORT_EPOLL 347 /** 348 * Daemon's parameters and pointers to the preallocated memory for running 349 * sockets monitoring by epoll. 350 */ 351 struct mhd_DaemonEventsEPollData 352 { 353 /** 354 * The epoll control FD. 355 */ 356 int e_fd; 357 /** 358 * The array of events reported by epoll. 359 */ 360 struct epoll_event *events; 361 362 /** 363 * The number of elements in the allocated @a events arrays. 364 */ 365 size_t num_elements; 366 }; 367 368 #endif 369 370 /** 371 * Daemon's data for external events callback. 372 * Internal version of struct MHD_WorkModeExternalEventLoopCBParam. 373 */ 374 struct mhd_DaemonEventsExternalCallback 375 { 376 /** 377 * Socket registration callback 378 */ 379 MHD_SocketRegistrationUpdateCallback cb; 380 /** 381 * Closure for the @a cb 382 */ 383 void *cls; 384 }; 385 386 387 #ifdef MHD_SUPPORT_THREADS 388 /** 389 * External events data for ITC FD 390 */ 391 struct mhd_DaemonEventsExternalDaemonItcData 392 { 393 /** 394 * Application context for ITC FD 395 */ 396 void *app_cntx; 397 398 /** 399 * Set to 'true' when active state was detected on ITC by 400 * external polling 401 */ 402 bool is_active; 403 404 /** 405 * Set to 'true' when error state was detected on ITC by 406 * external polling. 407 * The daemon may become non-functional. 408 */ 409 bool is_broken; 410 }; 411 #endif /* MHD_SUPPORT_THREADS */ 412 413 /** 414 * External events data for the listen socket 415 */ 416 struct mhd_DaemonEventsExternalDaemonListenData 417 { 418 /** 419 * Application context for ITC FD 420 */ 421 void *app_cntx; 422 }; 423 424 /** 425 * Daemon's data for external events for sockets monitoring. 426 */ 427 struct mhd_DaemonEventsExternal 428 { 429 /** 430 * Daemon's data for external events callback. 431 * Internal version of struct MHD_WorkModeExternalEventLoopCBParam. 432 */ 433 struct mhd_DaemonEventsExternalCallback cb_data; 434 435 #ifdef MHD_SUPPORT_THREADS 436 /** 437 * External events data for ITC FD 438 */ 439 struct mhd_DaemonEventsExternalDaemonItcData itc_data; 440 #endif /* MHD_SUPPORT_THREADS */ 441 442 /** 443 * External events data for the listen socket 444 */ 445 struct mhd_DaemonEventsExternalDaemonListenData listen_data; 446 447 /** 448 * If set to 'true' then all FDs must be registered each round. 449 * If set to 'false' then only changed FDs must be registered. 450 */ 451 bool reg_all; 452 }; 453 454 /** 455 * Type-specific events monitoring data 456 */ 457 union mhd_DaemonEventMonitoringTypeSpecificData 458 { 459 #ifdef MHD_SUPPORT_SELECT 460 /** 461 * Daemon's pointers to the preallocated arrays for running sockets monitoring 462 * by poll(). 463 */ 464 struct mhd_DaemonEventsSelectData select; 465 #endif /* MHD_SUPPORT_SELECT */ 466 467 #ifdef MHD_SUPPORT_POLL 468 /** 469 * Daemon's pointers to the preallocated arrays for running sockets monitoring 470 * by poll(). 471 */ 472 struct mhd_DaemonEventsPollData poll; 473 #endif /* MHD_SUPPORT_POLL */ 474 475 #ifdef MHD_SUPPORT_EPOLL 476 /** 477 * Daemon's parameters and pointers to the preallocated memory for running 478 * sockets monitoring by epoll. 479 */ 480 struct mhd_DaemonEventsEPollData epoll; 481 #endif 482 483 /** 484 * Daemon's data for external events for sockets monitoring. 485 */ 486 struct mhd_DaemonEventsExternal extr; 487 }; 488 489 490 /** 491 * The required actions for the daemon 492 */ 493 struct mhd_DaemonEventActionRequired 494 { 495 /** 496 * If 'true' connection resuming is required. 497 * TODO: implement resuming 498 * TODO: add initialisation 499 */ 500 bool resume; 501 }; 502 503 504 /** 505 * The data for events monitoring 506 */ 507 struct mhd_DaemonEventMonitoringData 508 { 509 /** 510 * Sockets polling type used by the daemon. 511 */ 512 enum mhd_IntPollType poll_type; 513 514 /** 515 * Type-specific events monitoring data 516 */ 517 union mhd_DaemonEventMonitoringTypeSpecificData data; 518 519 /** 520 * The required actions for the daemon. 521 * If daemon has internal thread, this should be changed only inside 522 * the daemon's thread. 523 */ 524 struct mhd_DaemonEventActionRequired act_req; 525 526 /** 527 * When set to 'true' the listen socket has new incoming connection(s). 528 */ 529 bool accept_pending; 530 531 /** 532 * The list of the daemon's connections that need processing 533 */ 534 mhd_DLNKDL_LIST (MHD_Connection,proc_ready); 535 536 }; 537 538 539 /** 540 * The type of the socket 541 */ 542 enum MHD_FIXED_ENUM_ mhd_SocketType 543 { 544 /** 545 * The socket type is some non-IP type. 546 */ 547 mhd_SOCKET_TYPE_NON_IP = -2 548 , 549 /** 550 * The socket type is UNIX (LOCAL) 551 */ 552 mhd_SOCKET_TYPE_UNIX = -1 553 , 554 /** 555 * The socket is unknown yet. It can be IP or non-IP. 556 */ 557 mhd_SOCKET_TYPE_UNKNOWN = 0 558 , 559 /** 560 * The socket is definitely IP. 561 */ 562 mhd_SOCKET_TYPE_IP = 1 563 }; 564 565 /** 566 * Listen socket data 567 */ 568 struct mhd_ListenSocket 569 { 570 /** 571 * The listening socket 572 */ 573 MHD_Socket fd; 574 /** 575 * Set to 'true' when unrecoverable error is detected on the listen socket. 576 * If set to 'true', but @a fd is not #MHD_INVALID_SOCKET then "broken" state 577 * has not yet processed by MHD. 578 */ 579 bool is_broken; 580 /** 581 * The type of the listening socket @a fd 582 */ 583 enum mhd_SocketType type; 584 /** 585 * 'true' if @a fd is non-blocking 586 */ 587 bool non_block; 588 /** 589 * The port number for @a fd 590 * 591 * Zero if unknown and for non-IP socket. 592 */ 593 uint_least16_t port; 594 }; 595 596 /** 597 * Configured settings for the daemon's network data 598 */ 599 struct mhd_DaemonNetworkSettings 600 { 601 #ifdef MHD_SOCKETS_KIND_POSIX 602 /** 603 * The maximum number for the network FDs. 604 * The valid FD number must be less then @a max_fd_num. 605 */ 606 MHD_Socket max_fd_num; 607 #else 608 int dummy; /* mute compiler warning */ 609 #endif 610 }; 611 612 /** 613 * The daemon network/sockets data 614 * 615 * This structure holds mostly static information -- typically initialised once 616 * when the daemon starts, and possibly updated once later (e.g., if the 617 * listening socket fails or is closed). 618 * 619 * It does NOT contain any operational states. 620 */ 621 struct mhd_DaemonNetwork 622 { 623 /** 624 * The listening socket 625 */ 626 struct mhd_ListenSocket listen; 627 628 #ifdef MHD_SUPPORT_EPOLL 629 /** 630 * The epoll FD. 631 * Set to '-1' when epoll is not used. 632 */ 633 int epoll_fd; 634 #endif 635 /** 636 * Configured settings for the daemon's network data 637 */ 638 struct mhd_DaemonNetworkSettings cfg; 639 }; 640 641 #ifdef MHD_SUPPORT_AUTH_DIGEST 642 643 /** 644 * Digest Auth nonce data 645 */ 646 struct mhd_DaemonAuthDigestNonceData 647 { 648 /** 649 * The nonce value in the binary form, excluding validity tail 650 */ 651 uint8_t nonce[mhd_AUTH_DIGEST_NONCE_RAND_BIN_SIZE]; 652 653 /** 654 * The nonce validity time 655 */ 656 uint_fast32_t valid_time; 657 658 /** 659 * The largest last received 'nc' value. 660 * This 'nc' value has been already used by the client. 661 */ 662 uint_fast32_t max_recvd_nc; 663 664 /** 665 * Bitmask over the previous 64 nc values (down to to nc-64). 666 * Used to allow out-of-order 'nc'. 667 * If bit in the bitmask is set to one, then this 'nc' value was already used 668 * by the client. 669 */ 670 uint_fast64_t nmask; 671 }; 672 673 /** 674 * Digest Auth daemon configuration data 675 */ 676 struct mhd_DaemonAuthDigestCfg 677 { 678 /** 679 * The number of elements in the nonces array 680 */ 681 size_t nonces_num; 682 683 /** 684 * The nonce validity time (in seconds) 685 */ 686 unsigned int nonce_tmout; 687 688 /** 689 * The default maximum value of nc 690 */ 691 uint_fast32_t def_max_nc; 692 }; 693 694 /** 695 * The Digest Auth daemon's data 696 */ 697 struct mhd_DaemonAuthDigestData 698 { 699 /** 700 * The entropy data used for Digests generation 701 */ 702 struct mhd_Buffer entropy; 703 704 /** 705 * The array of generated nonce and related nc 706 */ 707 struct mhd_DaemonAuthDigestNonceData *nonces; 708 709 /** 710 * Number of nonces has been generated. 711 * Used as addition for the nonce source data to ensure unique nonce value. 712 * TODO: remove and directly use random generator for nonce generation. 713 */ 714 struct mhd_AtomicCounter num_gen_nonces; 715 716 #ifdef MHD_SUPPORT_THREADS 717 /** 718 * The mutex to change or access the @a nonces data 719 */ 720 mhd_mutex nonces_lock; 721 #endif 722 723 /** 724 * Digest Auth daemon configuration data 725 */ 726 struct mhd_DaemonAuthDigestCfg cfg; 727 }; 728 729 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 730 731 #ifdef MHD_SUPPORT_THREADS 732 733 /** 734 * The type of the daemon 735 */ 736 enum MHD_FIXED_ENUM_ mhd_DaemonType 737 { 738 /** 739 * A single daemon, performing all the work. 740 * 741 * This daemon may have a optional single thread, managed by MHD. 742 */ 743 mhd_DAEMON_TYPE_SINGLE 744 #ifndef NDEBUG 745 = 1 746 #endif 747 #ifdef MHD_SUPPORT_THREADS 748 , 749 /** 750 * A master daemon, only controlling worker daemons. 751 * 752 * This daemon never handle any network activity directly. 753 */ 754 mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY 755 , 756 /** 757 * A daemon with single internal thread for listening and multiple threads 758 * handling connections with the clients, one thread per connection. 759 */ 760 mhd_DAEMON_TYPE_LISTEN_ONLY 761 , 762 /** 763 * A worker daemon, performing the same work as a single daemon, but 764 * controlled by master daemon. 765 * 766 * This type of daemon always have single internal tread and never exposed 767 * to application directly. 768 */ 769 mhd_DAEMON_TYPE_WORKER 770 #endif /* MHD_SUPPORT_THREADS */ 771 }; 772 773 /** 774 * Check whether the daemon type is allowed to have internal thread with 775 * direct control 776 */ 777 #define mhd_D_TYPE_IS_VALID(t) \ 778 ((mhd_DAEMON_TYPE_SINGLE <= (t)) && (mhd_DAEMON_TYPE_WORKER >= (t))) 779 780 /** 781 * Check whether the daemon type must not be exposed to the application 782 */ 783 #define mhd_D_TYPE_IS_INTERNAL_ONLY(t) \ 784 (mhd_DAEMON_TYPE_WORKER == (t)) 785 786 /** 787 * Check whether the daemon type is allowed to process the network data 788 */ 789 #define mhd_D_TYPE_HAS_EVENTS_PROCESSING(t) \ 790 (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY != (t)) 791 792 /** 793 * Check whether the daemon type must not be exposed to the application 794 */ 795 #define mhd_D_TYPE_HAS_WORKERS(t) \ 796 (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY == (t)) 797 798 /** 799 * Check whether the daemon type has master (controlling) daemon 800 */ 801 #define mhd_D_TYPE_HAS_MASTER_DAEMON(t) \ 802 (mhd_DAEMON_TYPE_WORKER == (t)) 803 804 /** 805 * Check whether the daemon is listening only (with connection data 806 * processed in separate threads) 807 */ 808 #define mhd_D_TYPE_IS_LISTEN_ONLY(t) \ 809 (mhd_DAEMON_TYPE_LISTEN_ONLY == (t)) 810 811 #else /* ! MHD_SUPPORT_THREADS */ 812 813 /** 814 * Check whether the daemon type is allowed to have internal thread with 815 * direct control 816 */ 817 #define mhd_D_TYPE_IS_VALID(t) (! 0) 818 819 /** 820 * Check whether the daemon type must not be exposed to the application 821 */ 822 #define mhd_D_TYPE_IS_INTERNAL_ONLY(t) (0) 823 824 /** 825 * Check whether the daemon type is allowed to process the network data 826 */ 827 #define mhd_D_TYPE_HAS_EVENTS_PROCESSING(t) (! 0) 828 829 /** 830 * Check whether the daemon type must not be exposed to the application 831 */ 832 #define mhd_D_TYPE_HAS_WORKERS(t) (0) 833 834 /** 835 * Check whether the daemon type has master (controlling) daemon 836 */ 837 #define mhd_D_TYPE_HAS_MASTER_DAEMON(t) (0) 838 839 /** 840 * Check whether the daemon is listening only (with connection data 841 * processed in separate threads) 842 */ 843 #define mhd_D_TYPE_IS_LISTEN_ONLY(t) (0) 844 845 #endif /* ! MHD_SUPPORT_THREADS */ 846 847 #ifdef MHD_SUPPORT_THREADS 848 849 /** 850 * Workers pool data 851 */ 852 struct mhd_DaemonWorkerPoolData 853 { 854 /** 855 * Array of worker daemons 856 */ 857 struct MHD_Daemon *workers; 858 859 /** 860 * The number of workers in the @a workers array 861 */ 862 unsigned int num; 863 }; 864 865 /** 866 * Hierarchy data for the daemon 867 */ 868 union mhd_DaemonHierarchyData 869 { 870 /** 871 * The pointer to the master daemon 872 * Only for #mhd_DAEMON_TYPE_WORKER daemons. 873 */ 874 struct MHD_Daemon *master; 875 876 /** 877 * Workers pool data. 878 * Only for #mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY daemons. 879 */ 880 struct mhd_DaemonWorkerPoolData pool; 881 }; 882 883 /** 884 * Configured settings for threading 885 */ 886 struct mhd_DaemonThreadingDataSettings 887 { 888 /** 889 * The size of the stack. 890 * Zero to use system's defaults. 891 */ 892 size_t stack_size; 893 }; 894 895 /** 896 * Threading and Inter-Thread Communication data 897 */ 898 struct mhd_DaemonThreadingData 899 { 900 /** 901 * The type of this daemon 902 */ 903 enum mhd_DaemonType d_type; 904 905 /** 906 * Inter-Thread Communication channel. 907 * Used to trigger processing of the command or the data provided or updated 908 * by the application. 909 */ 910 struct mhd_itc itc; 911 912 /** 913 * 'True' if stop has been requested. 914 * The daemon thread should stop all connections and then close. 915 */ 916 volatile bool stop_requested; 917 918 /** 919 * The handle of the daemon's thread (if managed by the daemon) 920 */ 921 mhd_thread_handle_ID tid; 922 923 /** 924 * The hierarchy data for the daemon. 925 * Used only when @a d_type is #mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY or 926 * #mhd_DAEMON_TYPE_WORKER. 927 */ 928 union mhd_DaemonHierarchyData hier; 929 930 /** 931 * Configured settings for threading 932 */ 933 struct mhd_DaemonThreadingDataSettings cfg; 934 }; 935 936 #endif /* MHD_SUPPORT_THREADS */ 937 938 /** 939 * Configured settings for the daemon's connections 940 */ 941 struct mhd_DaemonConnectionsSettings 942 { 943 /** 944 * The maximum number of connections handled by the daemon 945 */ 946 unsigned int count_limit; 947 948 /** 949 * The maximum number of connections per any IP handled by the daemon 950 */ 951 unsigned int per_ip_limit; 952 953 /** 954 * Connection's default timeout value (in milliseconds) 955 */ 956 uint_fast64_t timeout_ms; 957 958 /** 959 * Connection's memory pool size 960 */ 961 size_t mem_pool_size; 962 963 /** 964 * Memory pool zeroing mode 965 */ 966 enum mhd_MemPoolZeroing mem_pool_zeroing; 967 }; 968 969 #ifdef MHD_SUPPORT_UPGRADE 970 971 /** 972 * The data for HTTP-Upgraded connections 973 */ 974 struct mhd_DaemonConnectionsUpgraded 975 { 976 /** 977 * The list of HTTP-Upgraded connection closed by application and 978 * queued for cleanup 979 */ 980 mhd_DLNKDL_LIST (MHD_Connection,upgr_cleanup); 981 982 #ifdef MHD_SUPPORT_THREADS 983 /** 984 * The mutex to change or check the @a upgr_cleanup list values 985 */ 986 mhd_mutex ucu_lock; 987 #endif 988 }; 989 990 #endif /* MHD_SUPPORT_UPGRADE */ 991 992 /** 993 * Connections handling data 994 */ 995 struct mhd_DaemonConnections 996 { 997 998 /** 999 * The list of all daemon's connections. 1000 * All connection are listed here, expect connection in @a to_clean list. 1001 */ 1002 mhd_DLNKDL_LIST (MHD_Connection,all_conn); 1003 1004 /** 1005 * The list of connections sorted by last activity 1006 */ 1007 mhd_DLNKDL_LIST (MHD_Connection,def_timeout); 1008 1009 /** 1010 * The list of connections with custom timeouts 1011 */ 1012 mhd_DLNKDL_LIST (MHD_Connection,cust_timeout); 1013 1014 /** 1015 * The current number of connections handled by the daemon 1016 */ 1017 unsigned int count; 1018 1019 /** 1020 * If set to 'true' then no new connection is allowed. 1021 * New connection may be blocked because of various system limits, when 1022 * additional connection would fail anyway. This flag should be cleared 1023 * when any already processing connection closed. 1024 * Can be checked from other threads 1025 */ 1026 volatile bool block_new; 1027 1028 /** 1029 * Configured settings for the daemon's connections 1030 */ 1031 struct mhd_DaemonConnectionsSettings cfg; 1032 1033 #ifdef MHD_SUPPORT_UPGRADE 1034 /** 1035 * The data for HTTP-Upgraded connections 1036 */ 1037 struct mhd_DaemonConnectionsUpgraded upgr; 1038 #endif /* MHD_SUPPORT_UPGRADE */ 1039 }; 1040 1041 /** 1042 * Early URI callback 1043 */ 1044 struct mhd_DaemonRequestUriCB 1045 { 1046 /** 1047 * The callback 1048 */ 1049 MHD_EarlyUriLogCallback cb; 1050 /** 1051 * The callback closure 1052 */ 1053 void *cls; 1054 }; 1055 1056 /** 1057 * Shared large buffer data 1058 */ 1059 struct mhd_DaemonLargeBuffer 1060 { 1061 /** 1062 * The amount of memory left allowed to be allocated for the large buffer 1063 */ 1064 size_t space_left; 1065 1066 #ifdef MHD_SUPPORT_THREADS 1067 /** 1068 * The mutex to change or check the @a space_left value 1069 */ 1070 mhd_mutex lock; 1071 #endif 1072 }; 1073 1074 #ifdef MHD_SUPPORT_HTTP2 1075 1076 /** 1077 * Generic settings for HTTP layer communication handling. 1078 * 1079 * These settings do not include specific settings for requests processing. 1080 */ 1081 struct mhd_DaemonHttpSettings 1082 { 1083 /** 1084 * 'true' if HTTP/1.x communication is allowed 1085 */ 1086 bool http1x; 1087 /** 1088 * 'true' if HTTP/2 communication is allowed 1089 */ 1090 bool http2; 1091 }; 1092 1093 #endif /* MHD_SUPPORT_HTTP2 */ 1094 1095 /** 1096 * Settings for requests processing 1097 */ 1098 struct mhd_DaemonRequestProcessingSettings 1099 { 1100 /** 1101 * Request callback. 1102 * The main request processing callback. 1103 */ 1104 MHD_RequestCallback cb; 1105 1106 /** 1107 * The closure for @a req_cb 1108 */ 1109 void *cb_cls; 1110 1111 /** 1112 * Protocol strictness enforced by MHD on clients. 1113 */ 1114 enum MHD_ProtocolStrictLevel strictness; 1115 1116 #ifdef MHD_SUPPORT_COOKIES 1117 /** 1118 * Disable automatic cookies parsing 1119 */ 1120 bool disable_cookies; 1121 #endif 1122 1123 /** 1124 * Early URI callback 1125 */ 1126 struct mhd_DaemonRequestUriCB uri_cb; // TODO: set from settings 1127 1128 /** 1129 * Shared large buffer data 1130 */ 1131 struct mhd_DaemonLargeBuffer large_buf; // TODO: set from settings 1132 1133 /** 1134 * Suppress "Date:" header in responses 1135 */ 1136 bool suppress_date; 1137 }; 1138 1139 1140 /** 1141 * Get whether bare LF in HTTP header and other protocol elements 1142 * should be treated as the line termination depending on the configured 1143 * strictness level. 1144 * RFC 9112, section 2.2 1145 */ 1146 #define mhd_ALLOW_BARE_LF_AS_CRLF(strictness) (0 >= strictness) 1147 1148 1149 #ifndef NDEBUG 1150 /** 1151 * Various debugging data 1152 */ 1153 struct mhd_daemon_debug 1154 { 1155 bool net_inited; 1156 bool net_deinited; 1157 bool tls_inited; 1158 bool events_allocated; 1159 unsigned int num_events_elements; 1160 bool events_fully_inited; 1161 bool thread_pool_inited; 1162 bool threading_inited; 1163 bool connections_inited; 1164 bool avoid_accept4; 1165 size_t initial_lbuf_size; 1166 }; 1167 #endif /* NDEBUG */ 1168 1169 1170 struct MHD_Daemon 1171 { 1172 /* General data */ 1173 1174 /** 1175 * The daemon state 1176 */ 1177 enum mhd_DaemonState state; 1178 1179 /** 1180 * The daemon work mode (private version) 1181 */ 1182 enum mhd_WorkModeIntType wmode_int; 1183 1184 /* Events/sockets monitoring/polling data */ 1185 1186 /** 1187 * The data for events monitoring 1188 */ 1189 struct mhd_DaemonEventMonitoringData events; 1190 1191 /* Network/sockets data */ 1192 1193 /** 1194 * The daemon network/sockets data 1195 * 1196 * This structure holds mostly static information -- typically initialised 1197 * once when the daemon starts, and possibly updated once later (e.g., if the 1198 * listening socket fails or is closed). 1199 * 1200 * It does NOT contain any operational states. 1201 */ 1202 struct mhd_DaemonNetwork net; 1203 1204 #ifdef MHD_SUPPORT_AUTH_DIGEST 1205 /** 1206 * The Digest Auth daemon's data 1207 */ 1208 struct mhd_DaemonAuthDigestData auth_dg; 1209 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 1210 1211 #ifdef MHD_SUPPORT_HTTPS 1212 /** 1213 * The pointer to the daemon TLS data. 1214 * If set to non-NULL then HTTPS protocol is used, if set to NULL then 1215 * plain HTTP protocol used. 1216 */ 1217 struct mhd_TlsDaemonData *tls; 1218 #endif 1219 1220 #ifdef MHD_SUPPORT_THREADS 1221 /* Threading data */ 1222 1223 /** 1224 * The daemon threading and Inter-Thread Communication data 1225 */ 1226 struct mhd_DaemonThreadingData threading; 1227 #endif 1228 1229 /* Connections handling */ 1230 1231 /** 1232 * The connections handling data 1233 */ 1234 struct mhd_DaemonConnections conns; 1235 1236 1237 /* HTTP communication layer */ 1238 #ifdef MHD_SUPPORT_HTTP2 1239 /** 1240 * Generic settings for HTTP layer communication handling. 1241 * 1242 * These settings do not include specific settings for requests processing. 1243 */ 1244 struct mhd_DaemonHttpSettings http_cfg; 1245 #endif /* MHD_SUPPORT_HTTP2 */ 1246 1247 1248 /* Request processing data */ 1249 1250 /** 1251 * Settings for requests processing 1252 */ 1253 struct mhd_DaemonRequestProcessingSettings req_cfg; 1254 1255 /* Other data */ 1256 1257 /** 1258 * Daemon logging parameters 1259 */ 1260 struct MHD_DaemonOptionValueLog log_params; 1261 1262 1263 /* Temporal data */ 1264 1265 /** 1266 * User settings, before applied to the daemon itself 1267 */ 1268 struct DaemonOptions *settings; 1269 1270 #ifndef NDEBUG 1271 /* Debug data */ 1272 1273 struct mhd_daemon_debug dbg; 1274 #endif 1275 }; 1276 1277 1278 #ifdef MHD_SOCKETS_KIND_POSIX 1279 /** 1280 * Checks whether @a fd socket number fits limitations for the @a d_ptr daemon 1281 */ 1282 # define mhd_FD_FITS_DAEMON(d_ptr,fd) \ 1283 ((MHD_INVALID_SOCKET == d_ptr->net.cfg.max_fd_num) || \ 1284 (d_ptr->net.cfg.max_fd_num > fd)) 1285 #else 1286 # define mhd_FD_FITS_DAEMON(d_ptr,fd) (! 0) 1287 #endif 1288 1289 #ifdef MHD_SUPPORT_EPOLL 1290 # define mhd_D_IS_USING_EPOLL(d) \ 1291 (mhd_POLL_TYPE_EPOLL == ((d)->events.poll_type)) 1292 #else 1293 # define mhd_D_IS_USING_EPOLL(d) (0) 1294 #endif 1295 1296 /** 1297 * Check whether the daemon has edge-triggered sockets polling 1298 */ 1299 #define mhd_D_HAS_EDGE_TRIGG(d) \ 1300 ((mhd_WM_INT_EXTERNAL_EVENTS_EDGE == (d)->wmode_int) || \ 1301 mhd_D_IS_USING_EPOLL (d)) 1302 1303 #ifdef MHD_SUPPORT_THREADS 1304 # define mhd_D_HAS_THREADS(d) mhd_WM_INT_HAS_THREADS ((d)->wmode_int) 1305 #else 1306 # define mhd_D_HAS_THREADS(d) (0) 1307 #endif 1308 1309 #ifdef MHD_SUPPORT_THREADS 1310 # define mhd_D_HAS_THR_PER_CONN(d) \ 1311 (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION == \ 1312 ((d)->wmode_int)) 1313 #else 1314 # define mhd_D_HAS_THR_PER_CONN(d) (0) 1315 #endif 1316 1317 #ifdef MHD_SUPPORT_THREADS 1318 # define mhd_D_HAS_STOP_REQ(d) (d->threading.stop_requested) 1319 #else 1320 # define mhd_D_HAS_STOP_REQ(d) (0) 1321 #endif 1322 1323 #define mhd_D_HAS_WORKERS(d) mhd_D_TYPE_HAS_WORKERS ((d)->threading.d_type) 1324 1325 #define mhd_D_HAS_MASTER(d) mhd_D_TYPE_HAS_MASTER_DAEMON ((d)->threading.d_type) 1326 1327 #define mhd_D_IS_INTERNAL_ONLY(d) \ 1328 mhd_D_TYPE_IS_INTERNAL_ONLY ((d)->threading.d_type) 1329 1330 #define mhd_D_IS_USING_EDGE_TRIG(d) \ 1331 (mhd_D_IS_USING_EPOLL (d) || \ 1332 (mhd_WM_INT_EXTERNAL_EVENTS_EDGE ==((d)->wmode_int))) 1333 1334 #ifdef MHD_SUPPORT_HTTPS 1335 /** 1336 * Returns non-zero if daemon has TLS enabled or zero otherwise 1337 */ 1338 # define mhd_D_HAS_TLS(d) (((d)->tls) ? (! 0) : (0)) 1339 #else 1340 /** 1341 * Returns non-zero if daemon has TLS enabled or zero otherwise 1342 */ 1343 # define mhd_D_HAS_TLS(d) (0) 1344 #endif 1345 1346 /* 1347 * Check whether the daemon support Digest Auth 1348 */ 1349 #ifdef MHD_SUPPORT_AUTH_DIGEST 1350 # define mhd_D_HAS_AUTH_DIGEST(d) (NULL != (d)->auth_dg.nonces) 1351 #else 1352 # define mhd_D_HAS_AUTH_DIGEST(d) (! ! 0) 1353 #endif 1354 1355 #ifdef MHD_SUPPORT_HTTP2 1356 # define mhd_D_IS_HTTP1_ENABLED(d) (d->http_cfg.http1x) 1357 # define mhd_D_IS_HTTP2_ENABLED(d) (d->http_cfg.http2) 1358 #else /* ! MHD_SUPPORT_HTTP2 */ 1359 # define mhd_D_IS_HTTP1_ENABLED(d) (! 0) 1360 # define mhd_D_IS_HTTP2_ENABLED(d) (! ! 0) 1361 #endif /* ! MHD_SUPPORT_HTTP2 */ 1362 1363 1364 #endif /* ! MHD_DAEMON_H */