daemon_start.c (137985B)
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/daemon_start.c 41 * @brief The implementation of the MHD_daemon_start() 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #include "mhd_sys_options.h" 46 47 #include "mhd_assert.h" 48 #include "mhd_static_assert.h" 49 #include "mhd_unreachable.h" 50 #include "mhd_assume.h" 51 52 #include "mhd_constexpr.h" 53 54 #include "sys_bool_type.h" 55 #include "sys_base_types.h" 56 #include "sys_malloc.h" 57 #include "compat_calloc.h" 58 59 #include <string.h> 60 #include "sys_sockets_types.h" 61 #include "sys_sockets_headers.h" 62 #include "mhd_sockets_macros.h" 63 #include "sys_ip_headers.h" 64 65 #include "mhd_atomic_counter.h" 66 67 #ifdef MHD_SOCKETS_KIND_POSIX 68 # include "sys_errno.h" 69 #endif 70 #include "sys_select.h" 71 #include "sys_poll.h" 72 #ifdef MHD_SUPPORT_EPOLL 73 # include <sys/epoll.h> 74 #endif 75 #include "sys_kqueue.h" 76 77 #ifdef MHD_SOCKETS_KIND_POSIX 78 # include <fcntl.h> 79 #endif 80 81 #include "extr_events_funcs.h" 82 83 #include "mhd_dbg_print.h" 84 85 #include "mhd_limits.h" 86 87 #include "mhd_daemon.h" 88 #include "daemon_options.h" 89 90 #include "mhd_sockets_funcs.h" 91 92 #include "mhd_lib_init.h" 93 #include "daemon_logger.h" 94 95 #ifdef MHD_SUPPORT_HTTPS 96 # include "mhd_tls_common.h" 97 # include "mhd_tls_funcs.h" 98 # ifdef MHD_SUPPORT_ACME 99 # include "mhd_tls_acme_func.h" 100 # endif 101 #endif 102 103 #include "events_process.h" 104 105 #ifdef MHD_SUPPORT_THREADS 106 # include "mhd_itc.h" 107 # include "mhd_threads.h" 108 # include "daemon_funcs.h" 109 #endif 110 111 112 #include "mhd_public_api.h" 113 114 115 /** 116 * The default value for fastopen queue length (currently GNU/Linux only) 117 */ 118 #define MHD_TCP_FASTOPEN_DEF_QUEUE_LEN 64 119 120 /** 121 * Release any internally allocated pointers, then deallocate the settings. 122 * @param s the pointer to the settings to release 123 */ 124 static void 125 dsettings_release (struct DaemonOptions *s) 126 { 127 /* Release starting from the last member */ 128 if (NULL != s->random_entropy.v_buf) 129 free (s->random_entropy.v_buf); 130 if (NULL != s->tls_openssl_def_file.v_pathname) 131 free (s->tls_openssl_def_file.v_pathname); 132 if (NULL != s->tls_app_name.v_app_name) 133 free (s->tls_app_name.v_app_name); 134 if (NULL != s->tls_cert_key.v_mem_cert) 135 free (s->tls_cert_key.v_mem_cert); 136 if (MHD_INVALID_SOCKET != s->listen_socket) 137 mhd_socket_close (s->listen_socket); 138 if (NULL != s->bind_sa.v_sa) 139 free (s->bind_sa.v_sa); 140 free (s); 141 } 142 143 144 /** 145 * Set basic daemon parameters that not require additional initialisation. 146 * Mostly copy such parameters from the settings object to the daemon object. 147 * @param d the daemon object 148 * @param s the user settings 149 * @return MHD_SC_OK on success, 150 * the error code otherwise 151 */ 152 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 153 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 154 daemon_set_basic_settings (struct MHD_Daemon *restrict d, 155 struct DaemonOptions *restrict s) 156 { 157 mhd_constexpr uint_fast64_t max_timeout_ms_value = 1209600000u; 158 159 #ifdef MHD_SUPPORT_HTTP2 160 // TODO: make it configurable 161 d->http_cfg.http1x = true; 162 d->http_cfg.http2 = true; 163 #endif /* MHD_SUPPORT_HTTP2 */ 164 165 d->req_cfg.strictness = s->protocol_strict_level.v_sl; 166 167 #ifdef MHD_SUPPORT_COOKIES 168 d->req_cfg.disable_cookies = (MHD_NO != s->disable_cookies); 169 #endif 170 171 d->req_cfg.suppress_date = (MHD_NO != s->suppress_date_header); 172 173 d->conns.cfg.timeout_milsec = s->default_timeout_milsec; 174 if (max_timeout_ms_value < d->conns.cfg.timeout_milsec) 175 d->conns.cfg.timeout_milsec = max_timeout_ms_value; 176 177 d->conns.cfg.per_ip_limit = s->per_ip_limit; 178 179 return MHD_SC_OK; 180 } 181 182 183 /** 184 * Set the daemon work mode. 185 * This function also checks whether requested work mode is supported by 186 * current build and whether work mode is compatible with requested events 187 * polling technique. 188 * @param d the daemon object 189 * @param s the user settings 190 * @return MHD_SC_OK on success, 191 * the error code otherwise 192 */ 193 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 194 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 195 daemon_set_work_mode (struct MHD_Daemon *restrict d, 196 struct DaemonOptions *restrict s) 197 { 198 switch (s->work_mode.mode) 199 { 200 case MHD_WM_EXTERNAL_PERIODIC: 201 d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS; 202 break; 203 case MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL: 204 case MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE: 205 if (MHD_SPS_AUTO != s->poll_syscall) 206 { 207 mhd_LOG_MSG ( \ 208 d, MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID, \ 209 "The requested work mode is not compatible with setting " \ 210 "socket polling syscall."); 211 return MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID; 212 } 213 if (MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL == s->work_mode.mode) 214 d->wmode_int = mhd_WM_INT_EXTERNAL_EVENTS_LEVEL; 215 else 216 d->wmode_int = mhd_WM_INT_EXTERNAL_EVENTS_EDGE; 217 break; 218 case MHD_WM_EXTERNAL_SINGLE_FD_WATCH: 219 if ((MHD_SPS_AUTO != s->poll_syscall) 220 && (MHD_SPS_EPOLL != s->poll_syscall) 221 && (MHD_SPS_KQUEUE != s->poll_syscall)) 222 { 223 mhd_LOG_MSG ( \ 224 d, MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID, \ 225 "The requested work mode MHD_WM_EXTERNAL_SINGLE_FD_WATCH " \ 226 "is not compatible with requested socket polling syscall."); 227 return MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID; 228 } 229 #if !defined(MHD_SUPPORT_EPOLL) && !defined(MHD_SUPPORT_KQUEUE) 230 mhd_LOG_MSG ( \ 231 d, MHD_SC_FEATURE_DISABLED, \ 232 "The epoll or kqueue is required for the requested work mode " \ 233 "MHD_WM_EXTERNAL_SINGLE_FD_WATCH, but none is available on this " \ 234 "platform or MHD build."); 235 return MHD_SC_FEATURE_DISABLED; 236 #else 237 d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS; 238 #endif 239 break; 240 case MHD_WM_THREAD_PER_CONNECTION: 241 if (MHD_SPS_EPOLL == s->poll_syscall) 242 { 243 mhd_LOG_MSG ( \ 244 d, MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID, \ 245 "The requested work mode MHD_WM_THREAD_PER_CONNECTION " \ 246 "is not compatible with 'epoll' sockets polling."); 247 return MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID; 248 } 249 if (MHD_SPS_KQUEUE == s->poll_syscall) 250 { 251 mhd_LOG_MSG ( \ 252 d, MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID, \ 253 "The requested work mode MHD_WM_THREAD_PER_CONNECTION " \ 254 "is not compatible with 'kqueue' sockets polling."); 255 return MHD_SC_SYSCALL_WORK_MODE_COMBINATION_INVALID; 256 } 257 mhd_FALLTHROUGH; 258 /* Intentional fallthrough */ 259 case MHD_WM_WORKER_THREADS: 260 #ifndef MHD_SUPPORT_THREADS 261 mhd_LOG_MSG (d, MHD_SC_FEATURE_DISABLED, \ 262 "The internal threads modes are not supported by this " \ 263 "build of MHD."); 264 return MHD_SC_FEATURE_DISABLED; 265 #else /* MHD_SUPPORT_THREADS */ 266 if (MHD_WM_THREAD_PER_CONNECTION == s->work_mode.mode) 267 d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION; 268 else if (1 >= s->work_mode.params.num_worker_threads) /* && (MHD_WM_WORKER_THREADS == s->work_mode.mode) */ 269 d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD; 270 else 271 d->wmode_int = mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL; 272 #endif /* MHD_SUPPORT_THREADS */ 273 break; 274 default: 275 mhd_LOG_MSG (d, MHD_SC_CONFIGURATION_UNEXPECTED_WM, \ 276 "Wrong requested work mode."); 277 return MHD_SC_CONFIGURATION_UNEXPECTED_WM; 278 } 279 280 if ((mhd_WM_INT_EXTERNAL_EVENTS_LEVEL != d->wmode_int) 281 && (mhd_WM_INT_EXTERNAL_EVENTS_EDGE != d->wmode_int) 282 && (MHD_NO != s->reregister_all)) 283 { 284 mhd_LOG_MSG ( \ 285 d, \ 286 MHD_SC_EXTERNAL_EVENT_ONLY, \ 287 "The MHD_D_O_REREGISTER_ALL option can be used only with external " \ 288 "events work modes."); 289 return MHD_SC_EXTERNAL_EVENT_ONLY; 290 } 291 292 return MHD_SC_OK; 293 } 294 295 296 union mhd_SockaddrAny 297 { 298 struct sockaddr sa; 299 struct sockaddr_in sa_i4; 300 #ifdef HAVE_INET6 301 struct sockaddr_in6 sa_i6; 302 #endif /* HAVE_INET6 */ 303 struct sockaddr_storage sa_stor; 304 }; 305 306 307 /** 308 * The type of the socket to create 309 */ 310 enum mhd_CreateSktType 311 { 312 /** 313 * Unknown address family (could be IP or not IP) 314 */ 315 mhd_SKT_UNKNOWN = -4 316 , 317 /** 318 * The socket is not IP. 319 */ 320 mhd_SKT_NON_IP = -2 321 , 322 /** 323 * The socket is UNIX. 324 */ 325 mhd_SKT_UNIX = -1 326 , 327 /** 328 * No socket 329 */ 330 mhd_SKT_NO_SOCKET = MHD_AF_NONE 331 , 332 /** 333 * IPv4 only 334 */ 335 mhd_SKT_IP_V4_ONLY = MHD_AF_INET4 336 , 337 /** 338 * IPv6 only 339 */ 340 mhd_SKT_IP_V6_ONLY = MHD_AF_INET6 341 , 342 /** 343 * IPv6 with dual stack enabled 344 */ 345 mhd_SKT_IP_DUAL_REQUIRED = MHD_AF_DUAL 346 , 347 /** 348 * Try IPv6 with dual stack then IPv4 349 */ 350 mhd_SKT_IP_V4_WITH_V6_OPT = MHD_AF_DUAL_v6_OPTIONAL 351 , 352 /** 353 * IPv6 with optional dual stack 354 */ 355 mhd_SKT_IP_V6_WITH_V4_OPT = MHD_AF_DUAL_v4_OPTIONAL 356 , 357 /** 358 * Try IPv4 then IPv6 with optional dual stack 359 */ 360 mhd_SKT_IP_V4_WITH_FALLBACK = 16 361 }; 362 363 /** 364 * Create socket, bind to the address and start listening on the socket. 365 * 366 * The socket is assigned to the daemon as listening FD. 367 * @param d the daemon to use 368 * @param s the user settings 369 * @param v6_tried true if IPv6 has been tried already 370 * @param force_v6_any_dual true if IPv6 is forced with dual stack either 371 * enabled or not 372 * @param prev_bnd_lstn_err if this function was already tried with another and 373 * failed to bind or to start listening then 374 * this parameter must be set to respecting status 375 * code, otherwise this parameter must be #MHD_SC_OK 376 * @return #MHD_SC_OK on success, 377 * the error code otherwise (no error printed to log if result is 378 * #MHD_SC_LISTEN_SOCKET_BIND_FAILED or #MHD_SC_LISTEN_FAILURE) 379 */ 380 static enum MHD_StatusCode 381 create_bind_listen_stream_socket_inner (struct MHD_Daemon *restrict d, 382 struct DaemonOptions *restrict s, 383 bool v6_tried, 384 bool force_v6_any_dual, 385 enum MHD_StatusCode prev_bnd_lstn_err) 386 { 387 MHD_Socket sk; 388 enum mhd_CreateSktType sk_type; 389 bool sk_already_listening; 390 union mhd_SockaddrAny sa_all; 391 const struct sockaddr *p_use_sa; 392 socklen_t use_sa_size; 393 uint_least16_t sk_port; 394 bool is_non_block; 395 bool is_non_inhr; 396 enum MHD_StatusCode ret; 397 398 sk = MHD_INVALID_SOCKET; 399 sk_type = mhd_SKT_NO_SOCKET; 400 sk_already_listening = false; 401 p_use_sa = NULL; 402 use_sa_size = 0; 403 sk_port = 0; 404 405 #ifndef HAVE_INET6 406 mhd_assert (!v6_tried); 407 mhd_assert (!force_v6_any_dual); 408 #endif 409 mhd_assert (mhd_SKT_NO_SOCKET == sk_type); /* Mute analyser warning */ 410 411 if (MHD_INVALID_SOCKET != s->listen_socket) 412 { 413 mhd_assert (!v6_tried); 414 mhd_assert (!force_v6_any_dual); 415 /* Check for options conflicts */ 416 if (0 != s->bind_sa.v_sa_len) 417 { 418 mhd_LOG_MSG (d, MHD_SC_OPTIONS_CONFLICT, \ 419 "MHD_D_O_BIND_SA cannot be used together " \ 420 "with MHD_D_O_LISTEN_SOCKET"); 421 return MHD_SC_OPTIONS_CONFLICT; 422 } 423 else if (MHD_AF_NONE != s->bind_port.v_af) 424 { 425 mhd_LOG_MSG (d, MHD_SC_OPTIONS_CONFLICT, \ 426 "MHD_D_O_BIND_PORT cannot be used together " \ 427 "with MHD_D_O_LISTEN_SOCKET"); 428 return MHD_SC_OPTIONS_CONFLICT; 429 } 430 431 /* No options conflicts */ 432 sk = s->listen_socket; 433 s->listen_socket = MHD_INVALID_SOCKET; /* Prevent closing with settings cleanup */ 434 sk_type = mhd_SKT_UNKNOWN; 435 sk_already_listening = true; 436 } 437 else if ((0 != s->bind_sa.v_sa_len) || (MHD_AF_NONE != s->bind_port.v_af)) 438 { 439 if (0 != s->bind_sa.v_sa_len) 440 { 441 mhd_assert (!v6_tried); 442 mhd_assert (!force_v6_any_dual); 443 444 /* Check for options conflicts */ 445 if (MHD_AF_NONE != s->bind_port.v_af) 446 { 447 mhd_LOG_MSG (d, MHD_SC_OPTIONS_CONFLICT, \ 448 "MHD_D_O_BIND_SA cannot be used together " \ 449 "with MHD_D_O_BIND_PORT"); 450 return MHD_SC_OPTIONS_CONFLICT; 451 } 452 453 /* No options conflicts */ 454 switch (s->bind_sa.v_sa->sa_family) 455 { 456 case AF_INET: 457 sk_type = mhd_SKT_IP_V4_ONLY; 458 if (sizeof(sa_all.sa_i4) > s->bind_sa.v_sa_len) 459 { 460 mhd_LOG_MSG (d, MHD_SC_CONFIGURATION_WRONG_SA_SIZE, \ 461 "The size of the provided sockaddr does not match " 462 "used address family"); 463 return MHD_SC_CONFIGURATION_WRONG_SA_SIZE; 464 } 465 memcpy (&(sa_all.sa_i4), s->bind_sa.v_sa, sizeof(sa_all.sa_i4)); 466 sk_port = (uint_least16_t)ntohs (sa_all.sa_i4.sin_port); 467 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 468 mhd_STATIC_ASSERT_STMT ( 469 sizeof(sa_all.sa_i4) == (uint8_t)sizeof(sa_all.sa_i4), 470 "The sockaddr_in size must fit into uint8_t"); 471 sa_all.sa_i4.sin_len = (uint8_t)sizeof(sa_all.sa_i4); 472 #endif 473 p_use_sa = (struct sockaddr *)&(sa_all.sa_i4); 474 use_sa_size = (socklen_t)sizeof(sa_all.sa_i4); 475 break; 476 #ifdef HAVE_INET6 477 case AF_INET6: 478 sk_type = mhd_SKT_IP_V6_ONLY; 479 if (sizeof(sa_all.sa_i6) > s->bind_sa.v_sa_len) 480 { 481 mhd_LOG_MSG (d, MHD_SC_CONFIGURATION_WRONG_SA_SIZE, \ 482 "The size of the provided sockaddr does not match " 483 "used address family"); 484 return MHD_SC_CONFIGURATION_WRONG_SA_SIZE; 485 } 486 memcpy (&(sa_all.sa_i6), s->bind_sa.v_sa, s->bind_sa.v_sa_len); 487 sk_port = (uint_least16_t)ntohs (sa_all.sa_i6.sin6_port); 488 # ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 489 mhd_STATIC_ASSERT_STMT ( 490 sizeof(sa_all.sa_i6) == (uint8_t)sizeof(sa_all.sa_i6), 491 "The sockaddr_in6 size must fit into uint8_t"); 492 sa_all.sa_i6.sin6_len = (uint8_t)sizeof(sa_all.sa_i6); 493 # endif 494 p_use_sa = (struct sockaddr *)&(sa_all.sa_i6); 495 use_sa_size = (socklen_t)sizeof(sa_all.sa_i6); 496 break; 497 #endif /* HAVE_INET6 */ 498 #ifdef MHD_AF_UNIX 499 case MHD_AF_UNIX: 500 sk_type = mhd_SKT_UNIX; 501 p_use_sa = NULL; /* To be set below */ 502 break; 503 #endif /* MHD_AF_UNIX */ 504 default: 505 sk_type = mhd_SKT_UNKNOWN; 506 p_use_sa = NULL; /* To be set below */ 507 break; 508 } 509 510 if (s->bind_sa.v_dual) 511 { 512 if (mhd_SKT_IP_V6_ONLY != sk_type) 513 { 514 mhd_LOG_MSG (d, MHD_SC_LISTEN_DUAL_STACK_NOT_SUITABLE, \ 515 "IP dual stack is not possible for provided sockaddr"); 516 } 517 #ifdef HAVE_INET6 518 else 519 { 520 # ifdef HAVE_DCLR_IPV6_V6ONLY 521 sk_type = mhd_SKT_IP_DUAL_REQUIRED; 522 # else /* ! IPV6_V6ONLY */ 523 mhd_LOG_MSG (d, \ 524 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED, \ 525 "IP dual stack is not supported by this platform or " \ 526 "by this MHD build"); 527 # endif /* ! IPV6_V6ONLY */ 528 } 529 #endif /* HAVE_INET6 */ 530 } 531 532 if (NULL == p_use_sa) 533 { 534 #if defined(HAVE_STRUCT_SOCKADDR_SA_LEN) && \ 535 defined(HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN) 536 if ((((size_t)s->bind_sa.v_sa->sa_len) != s->bind_sa.v_sa_len) 537 && (sizeof(sa_all) >= s->bind_sa.v_sa_len)) 538 { 539 /* Fix embedded 'sa_len' member if possible */ 540 memcpy (&sa_all, s->bind_sa.v_sa, s->bind_sa.v_sa_len); 541 mhd_assert (s->bind_sa.v_sa_len == (uint8_t)s->bind_sa.v_sa_len); 542 sa_all.sa_stor.ss_len = (uint8_t)s->bind_sa.v_sa_len; 543 p_use_sa = (const struct sockaddr *)&(sa_all.sa_stor); 544 } 545 else 546 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN && HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ 547 p_use_sa = s->bind_sa.v_sa; 548 use_sa_size = (socklen_t)s->bind_sa.v_sa_len; 549 } 550 } 551 else /* if (MHD_AF_NONE != s->bind_port.v_af) */ 552 { 553 /* No options conflicts */ 554 switch (s->bind_port.v_af) 555 { 556 case MHD_AF_NONE: 557 mhd_assert (0); 558 mhd_UNREACHABLE (); 559 return MHD_SC_INTERNAL_ERROR; 560 case MHD_AF_AUTO: 561 #ifdef HAVE_INET6 562 # ifdef HAVE_DCLR_IPV6_V6ONLY 563 if (force_v6_any_dual) 564 sk_type = mhd_SKT_IP_V6_WITH_V4_OPT; 565 else if (v6_tried) 566 sk_type = mhd_SKT_IP_V4_WITH_FALLBACK; 567 else 568 sk_type = mhd_SKT_IP_V4_WITH_V6_OPT; 569 # else /* ! IPV6_V6ONLY */ 570 mhd_assert (!v6_tried); 571 if (force_v6_any_dual) 572 sk_type = mhd_SKT_IP_V6_ONLY; 573 else 574 sk_type = mhd_SKT_IP_V4_WITH_FALLBACK; 575 # endif /* ! IPV6_V6ONLY */ 576 #else /* ! HAVE_INET6 */ 577 sk_type = mhd_SKT_IP_V4_ONLY; 578 #endif /* ! HAVE_INET6 */ 579 break; 580 case MHD_AF_INET4: 581 mhd_assert (!v6_tried); 582 mhd_assert (!force_v6_any_dual); 583 sk_type = mhd_SKT_IP_V4_ONLY; 584 break; 585 case MHD_AF_INET6: 586 mhd_assert (!v6_tried); 587 mhd_assert (!force_v6_any_dual); 588 #ifdef HAVE_INET6 589 sk_type = mhd_SKT_IP_V6_ONLY; 590 #else /* ! HAVE_INET6 */ 591 mhd_LOG_MSG (d, MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD, \ 592 "IPv6 is not supported by this MHD build or " \ 593 "by this platform"); 594 return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD; 595 #endif /* ! HAVE_INET6 */ 596 break; 597 case MHD_AF_DUAL: 598 mhd_assert (!v6_tried); 599 mhd_assert (!force_v6_any_dual); 600 #ifdef HAVE_INET6 601 # ifdef HAVE_DCLR_IPV6_V6ONLY 602 sk_type = mhd_SKT_IP_DUAL_REQUIRED; 603 # else /* ! IPV6_V6ONLY */ 604 mhd_LOG_MSG (d, 605 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED, \ 606 "IP dual stack is not supported by this platform or " \ 607 "by this MHD build"); 608 sk_type = mhd_SKT_IP_V6_ONLY; 609 # endif /* ! IPV6_V6ONLY */ 610 #else /* ! HAVE_INET6 */ 611 mhd_LOG_MSG (d, MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD, \ 612 "IPv6 is not supported by this MHD build or " \ 613 "by this platform"); 614 return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD; 615 #endif /* ! HAVE_INET6 */ 616 break; 617 case MHD_AF_DUAL_v4_OPTIONAL: 618 mhd_assert (!v6_tried); 619 mhd_assert (!force_v6_any_dual); 620 #ifdef HAVE_INET6 621 # ifdef HAVE_DCLR_IPV6_V6ONLY 622 sk_type = mhd_SKT_IP_V6_WITH_V4_OPT; 623 # else /* ! IPV6_V6ONLY */ 624 sk_type = mhd_SKT_IP_V6_ONLY; 625 # endif /* ! IPV6_V6ONLY */ 626 #else /* ! HAVE_INET6 */ 627 mhd_LOG_MSG (d, MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD, \ 628 "IPv6 is not supported by this MHD build or " \ 629 "by this platform"); 630 return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD; 631 #endif /* ! HAVE_INET6 */ 632 break; 633 case MHD_AF_DUAL_v6_OPTIONAL: 634 mhd_assert (!force_v6_any_dual); 635 #ifdef HAVE_INET6 636 # ifdef HAVE_DCLR_IPV6_V6ONLY 637 sk_type = (!v6_tried) ? 638 mhd_SKT_IP_V4_WITH_V6_OPT : mhd_SKT_IP_V4_ONLY; 639 # else /* ! IPV6_V6ONLY */ 640 mhd_assert (!v6_tried); 641 sk_type = mhd_SKT_IP_V4_ONLY; 642 # endif /* ! IPV6_V6ONLY */ 643 #else /* ! HAVE_INET6 */ 644 mhd_assert (!v6_tried); 645 sk_type = mhd_SKT_IP_V4_ONLY; 646 #endif /* ! HAVE_INET6 */ 647 break; 648 default: 649 mhd_LOG_MSG (d, MHD_SC_AF_NOT_SUPPORTED_BY_BUILD, \ 650 "Unknown address family specified"); 651 return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD; 652 } 653 654 mhd_assert (mhd_SKT_NO_SOCKET < sk_type); 655 656 switch (sk_type) 657 { 658 case mhd_SKT_IP_V4_ONLY: 659 case mhd_SKT_IP_V4_WITH_FALLBACK: 660 /* Zeroing is not required, but may help on exotic platforms */ 661 memset (&(sa_all.sa_i4), 0, sizeof(sa_all.sa_i4)); 662 sa_all.sa_i4.sin_family = AF_INET; 663 sa_all.sa_i4.sin_port = htons (s->bind_port.v_port); 664 sa_all.sa_i4.sin_addr.s_addr = INADDR_ANY; 665 if (0 != INADDR_ANY) /* Optimised at compile time */ 666 sa_all.sa_i4.sin_addr.s_addr = htonl (INADDR_ANY); 667 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 668 sa_all.sa_i4.sin_len = (uint8_t)sizeof (sa_all.sa_i4); 669 #endif 670 p_use_sa = (const struct sockaddr *)&(sa_all.sa_i4); 671 use_sa_size = (socklen_t)sizeof (sa_all.sa_i4); 672 break; 673 case mhd_SKT_IP_V6_ONLY: 674 case mhd_SKT_IP_DUAL_REQUIRED: 675 case mhd_SKT_IP_V4_WITH_V6_OPT: 676 case mhd_SKT_IP_V6_WITH_V4_OPT: 677 #ifdef HAVE_INET6 678 if (1) 679 { 680 # ifdef IN6ADDR_ANY_INIT 681 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT; 682 # endif 683 /* Zeroing is required by POSIX */ 684 memset (&(sa_all.sa_i6), 0, sizeof(sa_all.sa_i6)); 685 sa_all.sa_i6.sin6_family = AF_INET6; 686 sa_all.sa_i6.sin6_port = htons (s->bind_port.v_port); 687 # ifdef IN6ADDR_ANY_INIT /* Optional assignment at the address is all zeros anyway */ 688 sa_all.sa_i6.sin6_addr = static_in6any; 689 # endif 690 # ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 691 sa_all.sa_i6.sin6_len = (uint8_t)sizeof (sa_all.sa_i6); 692 # endif 693 p_use_sa = (const struct sockaddr *)&(sa_all.sa_i6); 694 use_sa_size = (socklen_t)sizeof (sa_all.sa_i6); 695 } 696 break; 697 #endif /* HAVE_INET6 */ 698 case mhd_SKT_UNKNOWN: 699 case mhd_SKT_NON_IP: 700 case mhd_SKT_UNIX: 701 case mhd_SKT_NO_SOCKET: 702 default: 703 mhd_UNREACHABLE (); 704 return MHD_SC_INTERNAL_ERROR; 705 } 706 707 sk_port = s->bind_port.v_port; 708 709 } 710 } 711 else 712 { 713 /* No listen socket */ 714 d->net.listen.fd = MHD_INVALID_SOCKET; 715 d->net.listen.is_broken = false; 716 d->net.listen.type = mhd_SOCKET_TYPE_UNKNOWN; 717 d->net.listen.non_block = false; 718 d->net.listen.port = 0; 719 720 return MHD_SC_OK; 721 } 722 723 mhd_assert (mhd_SKT_NO_SOCKET != sk_type); 724 mhd_assert ((NULL != p_use_sa) || sk_already_listening); 725 mhd_assert ((MHD_INVALID_SOCKET == sk) || sk_already_listening); 726 727 if (MHD_INVALID_SOCKET == sk) 728 { 729 mhd_assert (NULL != p_use_sa); 730 #if defined(MHD_SOCKETS_KIND_WINSOCK) && defined(WSA_FLAG_NO_HANDLE_INHERIT) 731 /* May fail before Win7 SP1 */ 732 sk = WSASocketW (p_use_sa->sa_family, SOCK_STREAM, 0, 733 NULL, 0, WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); 734 735 if (MHD_INVALID_SOCKET == sk) 736 #endif /* MHD_SOCKETS_KIND_WINSOCK && WSA_FLAG_NO_HANDLE_INHERIT */ 737 sk = socket (p_use_sa->sa_family, 738 SOCK_STREAM | mhd_SOCK_NONBLOCK 739 | mhd_SOCK_CLOEXEC | mhd_SOCK_NOSIGPIPE, 0); 740 741 if (MHD_INVALID_SOCKET == sk) 742 { 743 #ifdef HAVE_INET6 744 if (mhd_SKT_IP_V4_WITH_FALLBACK == sk_type) 745 return create_bind_listen_stream_socket_inner (d, 746 s, 747 v6_tried, 748 true, 749 prev_bnd_lstn_err); 750 if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) 751 return create_bind_listen_stream_socket_inner (d, 752 s, 753 true, 754 false, 755 prev_bnd_lstn_err); 756 #endif /* HAVE_INET6 */ 757 758 if (MHD_SC_OK != prev_bnd_lstn_err) 759 return prev_bnd_lstn_err; 760 761 if (mhd_SCKT_LERR_IS_AF ()) 762 { 763 mhd_LOG_MSG (d, MHD_SC_AF_NOT_AVAILABLE, \ 764 "The requested socket address family is rejected " \ 765 "by the OS"); 766 return MHD_SC_AF_NOT_AVAILABLE; 767 } 768 mhd_LOG_MSG (d, MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET, \ 769 "Failed to open listen socket"); 770 771 return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET; 772 } 773 is_non_block = (0 != mhd_SOCK_NONBLOCK); 774 is_non_inhr = (0 != mhd_SOCK_CLOEXEC); 775 } 776 else 777 { 778 is_non_block = false; /* Try to set non-block */ 779 is_non_inhr = false; /* Try to set non-inheritable */ 780 } 781 782 /* The listen socket must be closed if error code returned 783 beyond this point */ 784 785 ret = MHD_SC_OK; 786 787 do 788 { /* The scope for automatic socket close for error returns */ 789 if (!mhd_FD_FITS_DAEMON (d, sk)) 790 { 791 mhd_LOG_MSG (d, MHD_SC_LISTEN_FD_OUTSIDE_OF_SET_RANGE, \ 792 "The listen FD value is higher than allowed"); 793 ret = MHD_SC_LISTEN_FD_OUTSIDE_OF_SET_RANGE; 794 break; 795 } 796 797 if (!is_non_inhr) 798 { 799 if (!mhd_socket_noninheritable (sk)) 800 mhd_LOG_MSG (d, MHD_SC_LISTEN_SOCKET_NOINHERIT_FAILED, \ 801 "OS refused to make the listen socket non-inheritable"); 802 } 803 804 if (!sk_already_listening) 805 { 806 #ifdef HAVE_INET6 807 # ifdef HAVE_DCLR_IPV6_V6ONLY 808 if ((mhd_SKT_IP_V6_ONLY == sk_type) 809 || (mhd_SKT_IP_DUAL_REQUIRED == sk_type) 810 || (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) 811 || (mhd_SKT_IP_V6_WITH_V4_OPT == sk_type) 812 || (mhd_SKT_UNKNOWN == sk_type)) 813 { 814 mhd_SCKT_OPT_BOOL no_dual_to_set; 815 bool use_dual; 816 817 use_dual = ((mhd_SKT_IP_DUAL_REQUIRED == sk_type) 818 || (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) 819 || (mhd_SKT_IP_V6_WITH_V4_OPT == sk_type)); 820 no_dual_to_set = use_dual ? 0 : 1; 821 822 if (0 != mhd_setsockopt (sk, IPPROTO_IPV6, IPV6_V6ONLY, 823 (void *)&no_dual_to_set, 824 sizeof (no_dual_to_set))) 825 { 826 mhd_SCKT_OPT_BOOL no_dual_current; 827 socklen_t opt_size; 828 bool state_unknown; 829 bool state_match; 830 831 no_dual_current = 0; 832 opt_size = sizeof(no_dual_current); 833 834 /* Some platforms forbid setting this options, but allow 835 reading. */ 836 if ((0 != mhd_getsockopt (sk, IPPROTO_IPV6, IPV6_V6ONLY, 837 (void *)&no_dual_current, &opt_size)) 838 || (((socklen_t)sizeof(no_dual_current)) < opt_size)) 839 { 840 state_unknown = true; 841 state_match = false; 842 } 843 else 844 { 845 state_unknown = false; 846 state_match = ((!!no_dual_current) == (!!no_dual_to_set)); 847 } 848 849 if (state_unknown || !state_match) 850 { 851 if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) 852 { 853 (void)mhd_socket_close (sk); 854 return create_bind_listen_stream_socket_inner (d, 855 s, 856 true, 857 false, 858 prev_bnd_lstn_err); 859 } 860 if (!state_unknown) 861 { 862 /* The dual-stack state is definitely wrong */ 863 if (mhd_SKT_IP_V6_ONLY == sk_type) 864 { 865 mhd_LOG_MSG ( \ 866 d, MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED, \ 867 "Failed to disable IP dual-stack configuration " \ 868 "for the listen socket"); 869 ret = (MHD_SC_OK == prev_bnd_lstn_err) ? 870 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED : 871 prev_bnd_lstn_err; 872 break; 873 } 874 else if (mhd_SKT_UNKNOWN != sk_type) 875 { 876 mhd_LOG_MSG ( \ 877 d, MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED, \ 878 "Cannot enable IP dual-stack configuration " \ 879 "for the listen socket"); 880 if (mhd_SKT_IP_DUAL_REQUIRED == sk_type) 881 { 882 ret = (MHD_SC_OK == prev_bnd_lstn_err) ? 883 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED : 884 prev_bnd_lstn_err; 885 break; 886 } 887 } 888 } 889 else 890 { 891 /* The dual-stack state is unknown */ 892 if (mhd_SKT_UNKNOWN != sk_type) 893 mhd_LOG_MSG ( 894 d, MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_UNKNOWN, \ 895 "Failed to set dual-stack (IPV6_ONLY) configuration " \ 896 "for the listen socket, using system defaults"); 897 } 898 } 899 } 900 } 901 # else /* ! IPV6_V6ONLY */ 902 mhd_assert (mhd_SKT_IP_DUAL_REQUIRED != sk_type); 903 mhd_assert (mhd_SKT_IP_V4_WITH_V6_OPT != sk_type); 904 mhd_assert (mhd_SKT_IP_V6_WITH_V4_OPT != sk_type); 905 # endif /* ! IPV6_V6ONLY */ 906 #endif /* HAVE_INET6 */ 907 908 if (MHD_FOM_AUTO <= d->settings->tcp_fastopen.v_option) 909 { 910 #if defined(HAVE_DCLR_TCP_FASTOPEN) 911 int fo_param; 912 # ifdef __linux__ 913 /* The parameter is the queue length */ 914 fo_param = (int)d->settings->tcp_fastopen.v_queue_length; 915 if (0 == fo_param) 916 fo_param = MHD_TCP_FASTOPEN_DEF_QUEUE_LEN; 917 # else /* ! __linux__ */ 918 fo_param = 1; /* The parameter is on/off type of setting */ 919 # endif /* ! __linux__ */ 920 if (0 != mhd_setsockopt (sk, IPPROTO_TCP, TCP_FASTOPEN, 921 (const void *)&fo_param, 922 sizeof (fo_param))) 923 { 924 mhd_LOG_MSG (d, MHD_SC_LISTEN_FAST_OPEN_FAILURE, \ 925 "OS refused to enable TCP Fast Open on " \ 926 "the listen socket"); 927 if (MHD_FOM_AUTO < d->settings->tcp_fastopen.v_option) 928 { 929 ret = MHD_SC_LISTEN_FAST_OPEN_FAILURE; 930 break; 931 } 932 } 933 #else /* ! TCP_FASTOPEN */ 934 if (MHD_FOM_AUTO < d->settings->tcp_fastopen.v_option) 935 { 936 mhd_LOG_MSG (d, MHD_SC_LISTEN_FAST_OPEN_FAILURE, \ 937 "The OS does not support TCP Fast Open"); 938 ret = MHD_SC_LISTEN_FAST_OPEN_FAILURE; 939 break; 940 } 941 #endif 942 } 943 944 if (MHD_D_OPTION_BIND_TYPE_NOT_SHARED >= d->settings->listen_addr_reuse) 945 { 946 #ifndef MHD_SOCKETS_KIND_WINSOCK 947 # ifdef HAVE_DCLR_SO_REUSEADDR 948 mhd_SCKT_OPT_BOOL on_val1 = 1; 949 if (0 != mhd_setsockopt (sk, SOL_SOCKET, SO_REUSEADDR, 950 (const void *)&on_val1, sizeof (on_val1))) 951 { 952 mhd_LOG_MSG (d, MHD_SC_LISTEN_PORT_REUSE_ENABLE_FAILED, \ 953 "OS refused to enable address reuse on " \ 954 "the listen socket"); 955 } 956 # else /* ! SO_REUSEADDR */ 957 mhd_LOG_MSG (d, MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED, \ 958 "The OS does not support address reuse for sockets"); 959 # endif /* ! SO_REUSEADDR */ 960 #endif /* ! MHD_SOCKETS_KIND_WINSOCK */ 961 if (MHD_D_OPTION_BIND_TYPE_NOT_SHARED > d->settings->listen_addr_reuse) 962 { 963 #if defined(HAVE_DCLR_SO_REUSEPORT) || defined(MHD_SOCKETS_KIND_WINSOCK) 964 int opt_name; 965 mhd_SCKT_OPT_BOOL on_val2 = 1; 966 # ifndef MHD_SOCKETS_KIND_WINSOCK 967 opt_name = SO_REUSEPORT; 968 # else /* ! MHD_SOCKETS_KIND_WINSOCK */ 969 opt_name = SO_REUSEADDR; /* On W32 it is the same as SO_REUSEPORT on other platforms */ 970 # endif /* ! MHD_SOCKETS_KIND_WINSOCK */ 971 if (0 != mhd_setsockopt (sk, \ 972 SOL_SOCKET, \ 973 opt_name, \ 974 (const void *)&on_val2, \ 975 sizeof (on_val2))) 976 { 977 mhd_LOG_MSG (d, MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED, \ 978 "OS refused to enable address sharing " \ 979 "on the listen socket"); 980 ret = MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED; 981 break; 982 } 983 #else /* ! SO_REUSEADDR && ! MHD_SOCKETS_KIND_WINSOCK */ 984 mhd_LOG_MSG (d, MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED, \ 985 "The OS does not support address sharing for sockets"); 986 ret = MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED; 987 break; 988 #endif /* ! SO_REUSEADDR && ! MHD_SOCKETS_KIND_WINSOCK */ 989 } 990 } 991 #if defined(SO_EXCLUSIVEADDRUSE) || defined(SO_EXCLBIND) 992 else if (MHD_D_OPTION_BIND_TYPE_EXCLUSIVE <= 993 d->settings->listen_addr_reuse) 994 { 995 int opt_name; 996 mhd_SCKT_OPT_BOOL on_val = 1; 997 # ifdef SO_EXCLUSIVEADDRUSE 998 opt_name = SO_EXCLUSIVEADDRUSE; 999 # else 1000 opt_name = SO_EXCLBIND; 1001 # endif 1002 if (0 != mhd_setsockopt (sk, \ 1003 SOL_SOCKET, \ 1004 opt_name, \ 1005 (const void *)&on_val, \ 1006 sizeof (on_val))) 1007 { 1008 mhd_LOG_MSG (d, MHD_SC_LISTEN_ADDRESS_EXCLUSIVE_ENABLE_FAILED, \ 1009 "OS refused to enable exclusive address use " \ 1010 "on the listen socket"); 1011 ret = MHD_SC_LISTEN_ADDRESS_EXCLUSIVE_ENABLE_FAILED; 1012 break; 1013 } 1014 } 1015 #endif /* SO_EXCLUSIVEADDRUSE || SO_EXCLBIND */ 1016 1017 mhd_assert (NULL != p_use_sa); 1018 mhd_assert (0 != use_sa_size); 1019 if (0 != bind (sk, p_use_sa, use_sa_size)) 1020 { 1021 ret = (MHD_SC_OK == prev_bnd_lstn_err) ? 1022 MHD_SC_LISTEN_SOCKET_BIND_FAILED : prev_bnd_lstn_err; 1023 #ifdef HAVE_INET6 1024 if (mhd_SKT_IP_V4_WITH_FALLBACK == sk_type) 1025 { 1026 (void)mhd_socket_close (sk); 1027 return create_bind_listen_stream_socket_inner (d, 1028 s, 1029 v6_tried, 1030 true, 1031 ret); 1032 } 1033 if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) 1034 { 1035 (void)mhd_socket_close (sk); 1036 return create_bind_listen_stream_socket_inner (d, 1037 s, 1038 true, 1039 false, 1040 ret); 1041 } 1042 #endif /* HAVE_INET6 */ 1043 break; 1044 } 1045 1046 if (1) 1047 { 1048 int accept_queue_len; 1049 accept_queue_len = (int)s->listen_backlog; 1050 if (0 > accept_queue_len) 1051 accept_queue_len = 0; 1052 if (0 == accept_queue_len) 1053 { 1054 #if defined(SOMAXCONN) || defined(HAVE_DCLR_SOMAXCONN) 1055 accept_queue_len = SOMAXCONN; 1056 #else /* ! SOMAXCONN */ 1057 accept_queue_len = 127; /* Should be the safe value */ 1058 #endif /* ! SOMAXCONN */ 1059 } 1060 if (0 != listen (sk, accept_queue_len)) 1061 { 1062 ret = MHD_SC_LISTEN_FAILURE; 1063 #ifdef HAVE_INET6 1064 if (mhd_SKT_IP_V4_WITH_FALLBACK == sk_type) 1065 { 1066 (void)mhd_socket_close (sk); 1067 return create_bind_listen_stream_socket_inner (d, 1068 s, 1069 v6_tried, 1070 true, 1071 ret); 1072 } 1073 if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type) 1074 { 1075 (void)mhd_socket_close (sk); 1076 return create_bind_listen_stream_socket_inner (d, 1077 s, 1078 true, 1079 false, 1080 ret); 1081 } 1082 #endif /* HAVE_INET6 */ 1083 break; 1084 } 1085 } 1086 } 1087 /* A valid listening socket is ready here */ 1088 1089 if (!is_non_block) 1090 { 1091 is_non_block = mhd_socket_nonblocking (sk); 1092 if (!is_non_block) 1093 mhd_LOG_MSG (d, MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE, \ 1094 "OS refused to make the listen socket non-blocking"); 1095 } 1096 1097 /* Set to the daemon only when the listening socket is fully ready */ 1098 d->net.listen.fd = sk; 1099 d->net.listen.is_broken = false; 1100 switch (sk_type) 1101 { 1102 case mhd_SKT_UNKNOWN: 1103 d->net.listen.type = mhd_SOCKET_TYPE_UNKNOWN; 1104 break; 1105 case mhd_SKT_NON_IP: 1106 d->net.listen.type = mhd_SOCKET_TYPE_NON_IP; 1107 break; 1108 case mhd_SKT_UNIX: 1109 d->net.listen.type = mhd_SOCKET_TYPE_UNIX; 1110 break; 1111 case mhd_SKT_IP_V4_ONLY: 1112 case mhd_SKT_IP_V6_ONLY: 1113 case mhd_SKT_IP_DUAL_REQUIRED: 1114 case mhd_SKT_IP_V4_WITH_V6_OPT: 1115 case mhd_SKT_IP_V6_WITH_V4_OPT: 1116 case mhd_SKT_IP_V4_WITH_FALLBACK: 1117 d->net.listen.type = mhd_SOCKET_TYPE_IP; 1118 break; 1119 case mhd_SKT_NO_SOCKET: 1120 default: 1121 mhd_UNREACHABLE (); 1122 return MHD_SC_INTERNAL_ERROR; 1123 } 1124 d->net.listen.non_block = is_non_block; 1125 d->net.listen.port = sk_port; 1126 1127 mhd_assert (ret == MHD_SC_OK); 1128 1129 return MHD_SC_OK; 1130 1131 } while (0); 1132 1133 mhd_assert (MHD_SC_OK != ret); /* This should be only error returns here */ 1134 mhd_assert (MHD_INVALID_SOCKET != sk); 1135 (void)mhd_socket_close (sk); 1136 return ret; 1137 } 1138 1139 1140 /** 1141 * Create socket, bind to the address and start listening on the socket. 1142 * 1143 * The socket is assigned to the daemon as listening FD. 1144 * 1145 * @param d the daemon to use 1146 * @param s the user settings 1147 * @return #MHD_SC_OK on success, 1148 * the error code otherwise (no error printed to log if result is 1149 * #MHD_SC_LISTEN_SOCKET_BIND_FAILED or #MHD_SC_LISTEN_FAILURE) 1150 */ 1151 static enum MHD_StatusCode 1152 create_bind_listen_stream_socket (struct MHD_Daemon *restrict d, 1153 struct DaemonOptions *restrict s) 1154 { 1155 enum MHD_StatusCode ret; 1156 1157 ret = create_bind_listen_stream_socket_inner (d, 1158 s, 1159 false, 1160 false, 1161 MHD_SC_OK); 1162 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY 1163 if (MHD_SC_LISTEN_SOCKET_BIND_FAILED == ret) 1164 mhd_LOG_MSG (d, MHD_SC_LISTEN_SOCKET_BIND_FAILED, \ 1165 "Failed to bind the listen socket"); 1166 else if (MHD_SC_LISTEN_FAILURE == ret) 1167 mhd_LOG_MSG (d, MHD_SC_LISTEN_FAILURE, \ 1168 "Failed to start listening on the listen socket"); 1169 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */ 1170 1171 return ret; 1172 } 1173 1174 1175 #ifdef MHD_USE_GETSOCKNAME 1176 /** 1177 * Detect and set the type and port of the listening socket 1178 * @param d the daemon to use 1179 */ 1180 static MHD_FN_PAR_NONNULL_ (1) void 1181 detect_listen_type_and_port (struct MHD_Daemon *restrict d) 1182 { 1183 union mhd_SockaddrAny sa_all; 1184 socklen_t sa_size; 1185 enum mhd_SocketType declared_type; 1186 1187 mhd_assert (MHD_INVALID_SOCKET != d->net.listen.fd); 1188 mhd_assert (0 == d->net.listen.port); 1189 memset (&sa_all, 0, sizeof(sa_all)); /* Actually not required */ 1190 sa_size = (socklen_t)sizeof(sa_all); 1191 1192 if (0 != getsockname (d->net.listen.fd, &(sa_all.sa), &sa_size)) 1193 { 1194 if (mhd_SOCKET_TYPE_IP == d->net.listen.type) 1195 mhd_LOG_MSG (d, MHD_SC_LISTEN_PORT_DETECT_FAILURE, \ 1196 "Failed to detect the port number on the listening socket"); 1197 return; 1198 } 1199 1200 declared_type = d->net.listen.type; 1201 if (0 == sa_size) 1202 { 1203 # ifndef __linux__ 1204 /* Used on some non-Linux platforms */ 1205 d->net.listen.type = mhd_SOCKET_TYPE_UNIX; 1206 d->net.listen.port = 0; 1207 # else /* ! __linux__ */ 1208 (void)0; 1209 # endif /* ! __linux__ */ 1210 } 1211 else 1212 { 1213 switch (sa_all.sa.sa_family) 1214 { 1215 case AF_INET: 1216 d->net.listen.type = mhd_SOCKET_TYPE_IP; 1217 d->net.listen.port = (uint_least16_t)ntohs (sa_all.sa_i4.sin_port); 1218 break; 1219 # ifdef HAVE_INET6 1220 case AF_INET6: 1221 d->net.listen.type = mhd_SOCKET_TYPE_IP; 1222 d->net.listen.port = (uint_least16_t)ntohs (sa_all.sa_i6.sin6_port); 1223 break; 1224 # endif /* HAVE_INET6 */ 1225 # ifdef MHD_AF_UNIX 1226 case MHD_AF_UNIX: 1227 d->net.listen.type = mhd_SOCKET_TYPE_UNIX; 1228 d->net.listen.port = 0; 1229 break; 1230 # endif /* MHD_AF_UNIX */ 1231 default: 1232 d->net.listen.type = mhd_SOCKET_TYPE_UNKNOWN; 1233 d->net.listen.port = 0; 1234 break; 1235 } 1236 } 1237 1238 if ((declared_type != d->net.listen.type) 1239 && (mhd_SOCKET_TYPE_IP == declared_type)) 1240 mhd_LOG_MSG (d, MHD_SC_UNEXPECTED_SOCKET_ERROR, \ 1241 "The type of listen socket is detected as non-IP, while " \ 1242 "the socket has been created as an IP socket"); 1243 } 1244 1245 1246 #else 1247 # define detect_listen_type_and_port(d) ((void) d) 1248 #endif 1249 1250 1251 #ifdef MHD_SUPPORT_EPOLL 1252 1253 /** 1254 * Initialise daemon's epoll FD 1255 * The could be performed early to probe for epoll FD presence 1256 * or, normally, during worker initialisation 1257 * @param d the daemon object 1258 * @param early_probing 'true' if this is early epoll probing 1259 * @param log_failures set to true if errors logging should be suppressed 1260 * when fallback options exist 1261 * @return #MHD_SC_OK on success, 1262 * the error code otherwise 1263 */ 1264 static MHD_FN_PAR_NONNULL_ (1) enum MHD_StatusCode 1265 init_epoll_fd (struct MHD_Daemon *restrict d, 1266 bool early_probing, 1267 bool log_failures) 1268 { 1269 int e_fd; 1270 mhd_ASSUME (early_probing || log_failures); 1271 mhd_assert ((mhd_POLL_TYPE_EPOLL == d->events.poll_type) 1272 || (mhd_POLL_TYPE_NOT_SET_YET == d->events.poll_type)); 1273 mhd_assert (!mhd_WM_INT_IS_THREAD_PER_CONN (d->wmode_int)); 1274 mhd_assert (early_probing || d->dbg.net_inited); 1275 mhd_assert (!early_probing || !d->dbg.net_inited); 1276 mhd_assert ((mhd_POLL_TYPE_EPOLL != d->events.poll_type) \ 1277 || (NULL == d->events.data.epoll.events)); 1278 1279 if (!early_probing) 1280 { 1281 /* Full events initialisation */ 1282 mhd_ASSUME (mhd_POLL_TYPE_EPOLL == d->events.poll_type); 1283 if (!mhd_D_HAS_MASTER (d)) 1284 { 1285 mhd_assert (0 < d->events.data.epoll.early_fd); 1286 /* Move early initialised epoll FD */ 1287 d->events.data.epoll.e_fd = d->events.data.epoll.early_fd; 1288 d->events.data.epoll.early_fd = MHD_INVALID_SOCKET; 1289 return MHD_SC_OK; 1290 } 1291 # ifdef MHD_SUPPORT_THREADS 1292 else 1293 { 1294 /* Worker daemon */ 1295 int early_fd; 1296 1297 early_fd = d->threading.hier.master->events.data.epoll.early_fd; 1298 1299 /* Move early initialised epoll FD if it is not yet taken */ 1300 if (MHD_INVALID_SOCKET != early_fd) 1301 { 1302 d->events.data.epoll.e_fd = early_fd; 1303 d->threading.hier.master->events.data.epoll.early_fd = 1304 MHD_INVALID_SOCKET; 1305 return MHD_SC_OK; 1306 } 1307 /* Process with new epoll FD creation */ 1308 } 1309 # endif /* MHD_SUPPORT_THREADS */ 1310 } 1311 else 1312 mhd_ASSUME (mhd_POLL_TYPE_NOT_SET_YET == d->events.poll_type); 1313 1314 # ifdef HAVE_EPOLL_CREATE1 1315 e_fd = epoll_create1 (EPOLL_CLOEXEC); 1316 # else /* ! HAVE_EPOLL_CREATE1 */ 1317 e_fd = epoll_create (128); /* The number is usually ignored */ 1318 if (0 <= e_fd) 1319 { 1320 if (!mhd_socket_noninheritable (e_fd)) 1321 mhd_LOG_MSG (d, MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED, \ 1322 "Failed to make epoll control FD non-inheritable"); 1323 } 1324 # endif /* ! HAVE_EPOLL_CREATE1 */ 1325 if (0 > e_fd) 1326 { 1327 if (log_failures) 1328 mhd_LOG_MSG (d, MHD_SC_EPOLL_CTL_CREATE_FAILED, \ 1329 "Failed to create epoll control FD"); 1330 return MHD_SC_EPOLL_CTL_CREATE_FAILED; /* Failure exit point */ 1331 } 1332 1333 if (!mhd_FD_FITS_DAEMON (d, e_fd)) 1334 { 1335 if (log_failures) 1336 mhd_LOG_MSG (d, MHD_SC_EPOLL_CTL_OUTSIDE_OF_SET_RANGE, \ 1337 "The epoll control FD value is higher than allowed"); 1338 (void)close (e_fd); 1339 return MHD_SC_EPOLL_CTL_OUTSIDE_OF_SET_RANGE; /* Failure exit point */ 1340 } 1341 1342 /* Needs to be set here as setting epoll data member 'early_fd' */ 1343 d->events.poll_type = mhd_POLL_TYPE_EPOLL; 1344 if (!early_probing) 1345 d->events.data.epoll.e_fd = e_fd; 1346 else 1347 d->events.data.epoll.early_fd = e_fd; 1348 1349 return MHD_SC_OK; /* Success exit point */ 1350 } 1351 1352 1353 /** 1354 * Deinitialise daemon's epoll FD 1355 * @param d the daemon object 1356 */ 1357 MHD_FN_PAR_NONNULL_ (1) static void 1358 deinit_epoll_fd (struct MHD_Daemon *restrict d) 1359 { 1360 mhd_assert (mhd_POLL_TYPE_EPOLL == d->events.poll_type); 1361 mhd_assert (MHD_INVALID_SOCKET != d->events.data.epoll.e_fd); 1362 mhd_assert (MHD_INVALID_SOCKET == d->events.data.epoll.early_fd); 1363 close (d->events.data.epoll.e_fd); 1364 } 1365 1366 1367 #endif /* MHD_SUPPORT_EPOLL */ 1368 1369 1370 /** 1371 * Choose sockets monitoring syscall and pre-initialise it 1372 * @param d the daemon object 1373 * @param s the user settings 1374 * @return #MHD_SC_OK on success, 1375 * the error code otherwise 1376 */ 1377 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) \ 1378 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1379 daemon_choose_and_preinit_events (struct MHD_Daemon *restrict d, 1380 struct DaemonOptions *restrict s) 1381 { 1382 enum mhd_IntPollType chosen_type; 1383 1384 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET == d->events.poll_type); 1385 1386 mhd_assert ((mhd_WM_INT_EXTERNAL_EVENTS_EDGE != d->wmode_int) \ 1387 || (mhd_WM_INT_EXTERNAL_EVENTS_LEVEL != d->wmode_int) \ 1388 || (MHD_SPS_AUTO == s->poll_syscall)); 1389 1390 /* Check whether the provided parameter is in the range of expected values. 1391 Reject unsupported or disabled values. */ 1392 switch (s->poll_syscall) 1393 { 1394 case MHD_SPS_AUTO: 1395 chosen_type = mhd_POLL_TYPE_NOT_SET_YET; 1396 break; 1397 case MHD_SPS_SELECT: 1398 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1399 #ifndef MHD_SUPPORT_SELECT 1400 mhd_LOG_MSG (d, MHD_SC_SELECT_SYSCALL_NOT_AVAILABLE, \ 1401 "'select()' is not supported by the platform or " \ 1402 "this MHD build"); 1403 return MHD_SC_SELECT_SYSCALL_NOT_AVAILABLE; 1404 #else /* MHD_SUPPORT_SELECT */ 1405 chosen_type = mhd_POLL_TYPE_SELECT; 1406 #endif /* MHD_SUPPORT_SELECT */ 1407 break; 1408 case MHD_SPS_POLL: 1409 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1410 #ifndef MHD_SUPPORT_POLL 1411 mhd_LOG_MSG (d, MHD_SC_POLL_SYSCALL_NOT_AVAILABLE, \ 1412 "'poll()' is not supported by the platform or " \ 1413 "this MHD build"); 1414 return MHD_SC_POLL_SYSCALL_NOT_AVAILABLE; 1415 #else /* MHD_SUPPORT_POLL */ 1416 chosen_type = mhd_POLL_TYPE_POLL; 1417 #endif /* MHD_SUPPORT_POLL */ 1418 break; 1419 case MHD_SPS_EPOLL: 1420 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1421 mhd_assert (!mhd_WM_INT_IS_THREAD_PER_CONN (d->wmode_int)); 1422 #ifndef MHD_SUPPORT_EPOLL 1423 mhd_LOG_MSG (d, MHD_SC_EPOLL_SYSCALL_NOT_AVAILABLE, \ 1424 "'epoll' is not supported by the platform or " \ 1425 "this MHD build"); 1426 return MHD_SC_EPOLL_SYSCALL_NOT_AVAILABLE; 1427 #else /* MHD_SUPPORT_EPOLL */ 1428 chosen_type = mhd_POLL_TYPE_EPOLL; 1429 #endif /* MHD_SUPPORT_EPOLL */ 1430 break; 1431 case MHD_SPS_KQUEUE: 1432 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1433 mhd_assert (!mhd_WM_INT_IS_THREAD_PER_CONN (d->wmode_int)); 1434 #ifndef MHD_SUPPORT_KQUEUE 1435 mhd_LOG_MSG (d, MHD_SC_KQUEUE_SYSCALL_NOT_AVAILABLE, \ 1436 "'kqueue' is not supported by the platform or " \ 1437 "this MHD build"); 1438 return MHD_SC_KQUEUE_SYSCALL_NOT_AVAILABLE; 1439 #else /* MHD_SUPPORT_EPOLL */ 1440 chosen_type = mhd_POLL_TYPE_KQUEUE; 1441 #endif /* MHD_SUPPORT_EPOLL */ 1442 break; 1443 default: 1444 mhd_LOG_MSG (d, MHD_SC_CONFIGURATION_UNEXPECTED_SPS, 1445 "Wrong socket polling syscall specified"); 1446 return MHD_SC_CONFIGURATION_UNEXPECTED_SPS; 1447 } 1448 1449 #ifdef MHD_SUPPORT_HTTPS 1450 if ((mhd_WM_INT_EXTERNAL_EVENTS_EDGE == (d)->wmode_int) 1451 || mhd_POLL_TYPE_INT_IS_EDGE_TRIG (chosen_type)) 1452 { /* Edge-triggered polling chosen */ 1453 if (MHD_TLS_BACKEND_NONE != s->tls) 1454 { 1455 if (!mhd_tls_is_edge_trigg_supported (s)) 1456 { 1457 # ifdef MHD_SUPPORT_LOG_FUNCTIONALITY 1458 if (MHD_TLS_BACKEND_ANY == s->tls) 1459 mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS, \ 1460 "Edge-triggered sockets polling cannot be used " 1461 "with available TLS backends"); 1462 else 1463 mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS, \ 1464 "Edge-triggered sockets polling cannot be used " 1465 "with selected TLS backend"); 1466 # endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */ 1467 return MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS; 1468 } 1469 } 1470 } 1471 #endif /* MHD_SUPPORT_HTTPS */ 1472 1473 mhd_assert (mhd_POLL_TYPE_EXT != chosen_type); 1474 mhd_ASSUME ((mhd_POLL_TYPE_NOT_SET_YET != chosen_type) \ 1475 || (MHD_SPS_AUTO == s->poll_syscall)); 1476 1477 if (mhd_POLL_TYPE_NOT_SET_YET == chosen_type) 1478 { 1479 if (mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)) 1480 chosen_type = mhd_POLL_TYPE_EXT; 1481 } 1482 1483 #if defined(MHD_SUPPORT_EPOLL) || defined(MHD_SUPPORT_KQUEUE) 1484 /* Try edge-triggered polling */ 1485 if ((mhd_POLL_TYPE_NOT_SET_YET == chosen_type) 1486 || mhd_POLL_TYPE_INT_IS_KQUEUE (chosen_type) 1487 || mhd_POLL_TYPE_INT_IS_EPOLL (chosen_type)) 1488 { 1489 bool et_allowed; 1490 1491 et_allowed = true; 1492 if (mhd_WM_INT_IS_THREAD_PER_CONN (d->wmode_int)) 1493 { 1494 mhd_assert (!mhd_POLL_TYPE_INT_IS_KQUEUE (chosen_type)); 1495 mhd_assert (!mhd_POLL_TYPE_INT_IS_EPOLL (chosen_type)); 1496 et_allowed = false; 1497 } 1498 # ifdef MHD_SUPPORT_HTTPS 1499 else if (MHD_TLS_BACKEND_NONE != s->tls) 1500 et_allowed = mhd_tls_is_edge_trigg_supported (s); 1501 # endif /* MHD_SUPPORT_HTTPS */ 1502 1503 if (et_allowed) 1504 { 1505 mhd_ASSUME ((mhd_POLL_TYPE_NOT_SET_YET == chosen_type) 1506 || mhd_POLL_TYPE_INT_IS_KQUEUE (chosen_type) 1507 || mhd_POLL_TYPE_INT_IS_EPOLL (chosen_type)); 1508 1509 # if defined(MHD_SUPPORT_KQUEUE) 1510 if ((mhd_POLL_TYPE_NOT_SET_YET == chosen_type) 1511 || mhd_POLL_TYPE_INT_IS_KQUEUE (chosen_type)) 1512 chosen_type = mhd_POLL_TYPE_KQUEUE; /* No need to perform additional checking here */ 1513 # endif /* MHD_SUPPORT_KQUEUE */ 1514 # ifdef MHD_SUPPORT_EPOLL 1515 if ((mhd_POLL_TYPE_NOT_SET_YET == chosen_type) 1516 || mhd_POLL_TYPE_INT_IS_EPOLL (chosen_type)) 1517 { 1518 /* epoll - need to be probed here as it can be disabled in kernel */ 1519 enum MHD_StatusCode epoll_res; 1520 epoll_res = init_epoll_fd (d, 1521 true, 1522 mhd_POLL_TYPE_INT_IS_EPOLL (chosen_type)); 1523 if (MHD_SC_OK != epoll_res) 1524 { 1525 if (mhd_POLL_TYPE_INT_IS_EPOLL (chosen_type)) 1526 return epoll_res; 1527 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET == chosen_type); 1528 } 1529 else 1530 chosen_type = mhd_POLL_TYPE_EPOLL; 1531 } 1532 # endif /* ! MHD_SUPPORT_EPOLL */ 1533 } 1534 else 1535 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET == chosen_type); 1536 } 1537 # ifdef MHD_SUPPORT_EPOLL 1538 mhd_assert ((mhd_POLL_TYPE_EPOLL != d->events.poll_type) \ 1539 || (0 < d->events.data.epoll.early_fd)); 1540 mhd_assert ((mhd_POLL_TYPE_EPOLL == d->events.poll_type) == \ 1541 (mhd_POLL_TYPE_EPOLL == chosen_type)); 1542 # endif /* ! MHD_SUPPORT_EPOLL */ 1543 #endif /* ! MHD_SUPPORT_EPOLL */ 1544 1545 if (mhd_POLL_TYPE_NOT_SET_YET == chosen_type) 1546 { 1547 #if defined(MHD_SUPPORT_POLL) 1548 chosen_type = mhd_POLL_TYPE_POLL; 1549 #elif defined(MHD_SUPPORT_SELECT) 1550 chosen_type = mhd_POLL_TYPE_SELECT; 1551 #else 1552 mhd_LOG_MSG (d, MHD_SC_FEATURE_DISABLED, \ 1553 "All suitable internal sockets polling technologies are " \ 1554 "disabled in this MHD build"); 1555 return MHD_SC_FEATURE_DISABLED; 1556 #endif 1557 } 1558 1559 switch (chosen_type) 1560 { 1561 case mhd_POLL_TYPE_EXT: 1562 mhd_assert ((MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL == s->work_mode.mode) \ 1563 || (MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE == s->work_mode.mode)); 1564 mhd_assert (mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1565 d->events.poll_type = mhd_POLL_TYPE_EXT; 1566 d->events.data.extr.cb_data.cb = 1567 s->work_mode.params.v_external_event_loop_cb.reg_cb; 1568 d->events.data.extr.cb_data.cls = 1569 s->work_mode.params.v_external_event_loop_cb.reg_cb_cls; 1570 d->events.data.extr.reg_all = (MHD_NO != s->reregister_all); 1571 #ifdef MHD_SUPPORT_THREADS 1572 d->events.data.extr.itc_data.app_cntx = NULL; 1573 #endif /* MHD_SUPPORT_THREADS */ 1574 d->events.data.extr.listen_data.app_cntx = NULL; 1575 break; 1576 #ifdef MHD_SUPPORT_SELECT 1577 case mhd_POLL_TYPE_SELECT: 1578 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1579 mhd_assert (MHD_WM_EXTERNAL_SINGLE_FD_WATCH != s->work_mode.mode); 1580 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL != s->work_mode.mode); 1581 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE != s->work_mode.mode); 1582 mhd_assert (MHD_NO == s->reregister_all); 1583 d->events.poll_type = mhd_POLL_TYPE_SELECT; 1584 d->events.data.select.rfds = NULL; /* Memory allocated during event and threads init */ 1585 d->events.data.select.wfds = NULL; /* Memory allocated during event and threads init */ 1586 d->events.data.select.efds = NULL; /* Memory allocated during event and threads init */ 1587 break; 1588 #endif /* MHD_SUPPORT_SELECT */ 1589 #ifdef MHD_SUPPORT_POLL 1590 case mhd_POLL_TYPE_POLL: 1591 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1592 mhd_assert (MHD_WM_EXTERNAL_SINGLE_FD_WATCH != s->work_mode.mode); 1593 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL != s->work_mode.mode); 1594 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE != s->work_mode.mode); 1595 mhd_assert (MHD_NO == s->reregister_all); 1596 d->events.poll_type = mhd_POLL_TYPE_POLL; 1597 d->events.data.poll.fds = NULL; /* Memory allocated during event and threads init */ 1598 d->events.data.poll.rel = NULL; /* Memory allocated during event and threads init */ 1599 break; 1600 #endif /* MHD_SUPPORT_POLL */ 1601 #ifdef MHD_SUPPORT_EPOLL 1602 case mhd_POLL_TYPE_EPOLL: 1603 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1604 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL != s->work_mode.mode); 1605 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE != s->work_mode.mode); 1606 mhd_assert (MHD_NO == s->reregister_all); 1607 /* Pre-initialised by init_epoll_fd() */ 1608 mhd_assert (mhd_POLL_TYPE_EPOLL == d->events.poll_type); 1609 mhd_assert (0 <= d->events.data.epoll.early_fd); 1610 d->events.data.epoll.events = NULL; /* Memory allocated during event and threads init */ 1611 d->events.data.epoll.num_elements = 0; 1612 break; 1613 #endif /* MHD_SUPPORT_EPOLL */ 1614 #ifdef MHD_SUPPORT_KQUEUE 1615 case mhd_POLL_TYPE_KQUEUE: 1616 mhd_assert (!mhd_WM_INT_HAS_EXT_EVENTS (d->wmode_int)); 1617 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL != s->work_mode.mode); 1618 mhd_assert (MHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE != s->work_mode.mode); 1619 mhd_assert (MHD_NO == s->reregister_all); 1620 d->events.poll_type = mhd_POLL_TYPE_KQUEUE; 1621 d->events.data.kq.kq_fd = -1; 1622 d->events.data.kq.kes = NULL; 1623 d->events.data.kq.num_elements = 0u; 1624 break; 1625 #endif /* MHD_SUPPORT_KQUEUE */ 1626 #ifndef MHD_SUPPORT_SELECT 1627 case mhd_POLL_TYPE_SELECT: 1628 #endif /* ! MHD_SUPPORT_SELECT */ 1629 #ifndef MHD_SUPPORT_POLL 1630 case mhd_POLL_TYPE_POLL: 1631 #endif /* ! MHD_SUPPORT_POLL */ 1632 case mhd_POLL_TYPE_NOT_SET_YET: 1633 default: 1634 mhd_UNREACHABLE (); 1635 return MHD_SC_INTERNAL_ERROR; 1636 } 1637 return MHD_SC_OK; 1638 } 1639 1640 1641 /** 1642 * Initialise network/sockets for the daemon. 1643 * Also choose events mode / sockets polling syscall. 1644 * @param d the daemon object 1645 * @param s the user settings 1646 * @return #MHD_SC_OK on success, 1647 * the error code otherwise 1648 */ 1649 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) \ 1650 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1651 daemon_init_net (struct MHD_Daemon *restrict d, 1652 struct DaemonOptions *restrict s) 1653 { 1654 enum MHD_StatusCode ret; 1655 1656 mhd_assert (!d->dbg.net_inited); 1657 mhd_assert (!d->dbg.net_deinited); 1658 #ifdef MHD_SOCKETS_KIND_POSIX 1659 d->net.cfg.max_fd_num = s->fd_number_limit; 1660 #endif /* MHD_SOCKETS_KIND_POSIX */ 1661 1662 ret = daemon_choose_and_preinit_events (d, s); 1663 if (MHD_SC_OK != ret) 1664 return ret; 1665 1666 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET != d->events.poll_type); 1667 1668 /* No direct return of error codes is allowed beyond this point. 1669 Deinit/cleanup must be performed before return of any error. */ 1670 1671 #if defined(MHD_SOCKETS_KIND_POSIX) && defined(MHD_SUPPORT_SELECT) 1672 if (mhd_POLL_TYPE_SELECT == d->events.poll_type) 1673 { 1674 if ((MHD_INVALID_SOCKET == d->net.cfg.max_fd_num) 1675 || (FD_SETSIZE < d->net.cfg.max_fd_num)) 1676 d->net.cfg.max_fd_num = FD_SETSIZE; 1677 } 1678 #endif /* MHD_SOCKETS_KIND_POSIX && MHD_SUPPORT_SELECT */ 1679 1680 if (MHD_SC_OK == ret) 1681 { 1682 ret = create_bind_listen_stream_socket (d, s); 1683 1684 if (MHD_SC_OK == ret) 1685 { 1686 if ((MHD_INVALID_SOCKET != d->net.listen.fd) 1687 && !d->net.listen.non_block 1688 && (mhd_D_HAS_EDGE_TRIGG (d) 1689 || mhd_WM_INT_IS_THREAD_POOL (d->wmode_int))) 1690 { 1691 mhd_LOG_MSG (d, MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE, \ 1692 "The selected daemon work mode requires listening socket " 1693 "in non-blocking mode"); 1694 ret = MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE; 1695 } 1696 1697 if (MHD_SC_OK == ret) 1698 { 1699 if ((MHD_INVALID_SOCKET != d->net.listen.fd) 1700 && ((0 == d->net.listen.port) 1701 || (mhd_SOCKET_TYPE_UNKNOWN == d->net.listen.type))) 1702 detect_listen_type_and_port (d); 1703 1704 #ifndef NDEBUG 1705 d->dbg.net_inited = true; 1706 #endif 1707 return MHD_SC_OK; /* Success exit point */ 1708 } 1709 1710 /* Below is a cleanup path */ 1711 if (MHD_INVALID_SOCKET != d->net.listen.fd) 1712 mhd_socket_close (d->net.listen.fd); 1713 } 1714 } 1715 1716 #ifdef MHD_SUPPORT_EPOLL 1717 /* Special case for epoll: epoll FD is probed early in events 1718 pre-initialisation and is not moved to events epoll FD therefore 1719 it needs cleanup here */ 1720 if (mhd_POLL_TYPE_EPOLL == d->events.poll_type) 1721 { 1722 mhd_assert (MHD_INVALID_SOCKET != d->events.data.epoll.early_fd); 1723 close (d->events.data.epoll.early_fd); 1724 } 1725 #endif /* MHD_SUPPORT_EPOLL */ 1726 1727 mhd_assert (MHD_SC_OK != ret); 1728 1729 return ret; 1730 } 1731 1732 1733 /** 1734 * Deinitialise daemon's network data 1735 * @param d the daemon object 1736 */ 1737 MHD_FN_PAR_NONNULL_ (1) static void 1738 daemon_deinit_net (struct MHD_Daemon *restrict d) 1739 { 1740 mhd_assert (d->dbg.net_inited); 1741 mhd_assert (!d->dbg.net_deinited); 1742 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET != d->events.poll_type); 1743 #ifdef MHD_SUPPORT_EPOLL 1744 /* Special case for epoll: epoll FD is probed early in events 1745 pre-initialisation and could be not moved yet to events epoll FD 1746 therefore it needs cleanup here */ 1747 if ((mhd_POLL_TYPE_EPOLL == d->events.poll_type) 1748 && (MHD_INVALID_SOCKET != d->events.data.epoll.early_fd)) 1749 { 1750 mhd_assert (0 < d->events.data.epoll.early_fd); 1751 close (d->events.data.epoll.early_fd); 1752 } 1753 #endif /* MHD_SUPPORT_EPOLL */ 1754 if (MHD_INVALID_SOCKET != d->net.listen.fd) 1755 mhd_socket_close (d->net.listen.fd); 1756 1757 #ifndef NDEBUG 1758 d->dbg.net_deinited = true; 1759 #endif 1760 } 1761 1762 1763 #if 0 1764 void 1765 dauth_init (struct MHD_Daemon *restrict d, 1766 struct DaemonOptions *restrict s) 1767 { 1768 mhd_assert ((NULL == s->random_entropy.v_buf) \ 1769 || (0 != s->random_entropy.v_buf_size)); 1770 mhd_assert ((0 == s->random_entropy.v_buf_size) \ 1771 || (NULL != s->random_entropy.v_buf)); 1772 } 1773 1774 1775 #endif 1776 1777 #ifdef MHD_SUPPORT_AUTH_DIGEST 1778 /** 1779 * Initialise daemon Digest Auth data 1780 * @param d the daemon object 1781 * @param s the user settings 1782 * @return #MHD_SC_OK on success, 1783 * the error code otherwise 1784 */ 1785 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) \ 1786 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1787 daemon_init_auth_digest (struct MHD_Daemon *restrict d, 1788 struct DaemonOptions *restrict s) 1789 { 1790 enum MHD_StatusCode ret; 1791 size_t nonces_num; 1792 1793 if (0 == s->random_entropy.v_buf_size) 1794 { 1795 /* No initialisation needed */ 1796 # ifndef HAVE_NULL_PTR_ALL_ZEROS 1797 d->auth_dg.entropy.data = NULL; 1798 d->auth_dg.nonces = NULL; 1799 # endif 1800 return MHD_SC_OK; 1801 } 1802 nonces_num = s->auth_digest_map_size; 1803 if (0 == nonces_num) 1804 nonces_num = 1000; 1805 d->auth_dg.nonces = (struct mhd_DaemonAuthDigestNonceData *) 1806 mhd_calloc (nonces_num, \ 1807 sizeof(struct mhd_DaemonAuthDigestNonceData)); 1808 if (NULL == d->auth_dg.nonces) 1809 { 1810 mhd_LOG_MSG (d, \ 1811 MHD_SC_DAEMON_MEM_ALLOC_FAILURE, \ 1812 "Failed to allocate memory for Digest Auth array"); 1813 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 1814 } 1815 d->auth_dg.cfg.nonces_num = nonces_num; 1816 1817 if (!mhd_mutex_init (&(d->auth_dg.nonces_lock))) 1818 { 1819 mhd_LOG_MSG (d, MHD_SC_MUTEX_INIT_FAILURE, \ 1820 "Failed to initialise mutex for the Digest Auth data"); 1821 ret = MHD_SC_MUTEX_INIT_FAILURE; 1822 } 1823 else 1824 { 1825 if (!mhd_atomic_counter_init (&(d->auth_dg.num_gen_nonces), 0)) 1826 { 1827 mhd_LOG_MSG (d, MHD_SC_MUTEX_INIT_FAILURE, \ 1828 "Failed to initialise mutex for the Digest Auth data"); 1829 ret = MHD_SC_MUTEX_INIT_FAILURE; 1830 } 1831 else 1832 { 1833 /* Move ownership of the entropy buffer */ 1834 d->auth_dg.entropy.data = (char *)s->random_entropy.v_buf; 1835 d->auth_dg.entropy.size = s->random_entropy.v_buf_size; 1836 s->random_entropy.v_buf = NULL; 1837 s->random_entropy.v_buf_size = 0; 1838 1839 d->auth_dg.cfg.nonce_tmout = s->auth_digest_nonce_timeout; 1840 if (0 == d->auth_dg.cfg.nonce_tmout) 1841 d->auth_dg.cfg.nonce_tmout = MHD_AUTH_DIGEST_DEF_TIMEOUT; 1842 d->auth_dg.cfg.def_max_nc = s->auth_digest_def_max_nc; 1843 if (0 == d->auth_dg.cfg.def_max_nc) 1844 d->auth_dg.cfg.def_max_nc = MHD_AUTH_DIGEST_DEF_MAX_NC; 1845 1846 return MHD_SC_OK; /* Success exit point */ 1847 } 1848 mhd_mutex_destroy_chk (&(d->auth_dg.nonces_lock)); 1849 } 1850 1851 free (d->auth_dg.nonces); 1852 mhd_assert (MHD_SC_OK != ret); 1853 return ret; /* Failure exit point */ 1854 } 1855 1856 1857 /** 1858 * Deinitialise daemon Digest Auth data 1859 * @param d the daemon object 1860 */ 1861 MHD_FN_PAR_NONNULL_ (1) static void 1862 daemon_deinit_auth_digest (struct MHD_Daemon *restrict d) 1863 { 1864 if (0 == d->auth_dg.entropy.size) 1865 return; /* Digest Auth not used, nothing to deinitialise */ 1866 1867 mhd_assert (NULL != d->auth_dg.entropy.data); 1868 free (d->auth_dg.entropy.data); 1869 mhd_atomic_counter_deinit (&(d->auth_dg.num_gen_nonces)); 1870 mhd_mutex_destroy_chk (&(d->auth_dg.nonces_lock)); 1871 mhd_assert (NULL != d->auth_dg.nonces); 1872 free (d->auth_dg.nonces); 1873 } 1874 1875 1876 #else /* MHD_SUPPORT_AUTH_DIGEST */ 1877 # define daemon_init_auth_digest(d, s) (MHD_SC_OK) 1878 # define daemon_deinit_auth_digest(d) ((void) 0) 1879 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 1880 1881 1882 /** 1883 * Initialise daemon TLS data 1884 * @param d the daemon object 1885 * @param s the user settings 1886 * @return #MHD_SC_OK on success, 1887 * the error code otherwise 1888 */ 1889 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) \ 1890 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1891 daemon_init_tls (struct MHD_Daemon *restrict d, 1892 struct DaemonOptions *restrict s) 1893 { 1894 #ifdef MHD_SUPPORT_HTTPS 1895 mhd_StatusCodeInt ret; 1896 #endif /* MHD_SUPPORT_HTTPS */ 1897 1898 mhd_assert (!d->dbg.tls_inited); 1899 #ifdef MHD_SUPPORT_HTTPS 1900 d->tls = NULL; 1901 #endif 1902 1903 if (MHD_TLS_BACKEND_NONE == s->tls) 1904 { 1905 #ifndef NDEBUG 1906 d->dbg.tls_inited = true; 1907 #endif 1908 return MHD_SC_OK; 1909 } 1910 #ifndef MHD_SUPPORT_HTTPS 1911 mhd_LOG_MSG (d, \ 1912 MHD_SC_TLS_DISABLED, \ 1913 "HTTPS is not supported by this MHD build"); 1914 return MHD_SC_TLS_DISABLED; 1915 #else /* MHD_SUPPORT_HTTPS */ 1916 if (1) 1917 { 1918 enum mhd_TlsBackendAvailable tls_avail; 1919 1920 tls_avail = mhd_tls_is_backend_available (s); 1921 if (mhd_TLS_BACKEND_AVAIL_NOT_SUPPORTED == tls_avail) 1922 { 1923 mhd_LOG_MSG (d, \ 1924 MHD_SC_TLS_BACKEND_UNSUPPORTED, \ 1925 "The requested TLS backend is not supported " \ 1926 "by this MHD build"); 1927 return MHD_SC_TLS_BACKEND_UNSUPPORTED; 1928 } 1929 else if (mhd_TLS_BACKEND_AVAIL_NOT_AVAILABLE == tls_avail) 1930 { 1931 mhd_LOG_MSG (d, \ 1932 MHD_SC_TLS_BACKEND_UNAVAILABLE, \ 1933 "The requested TLS backend is not available"); 1934 return MHD_SC_TLS_BACKEND_UNAVAILABLE; 1935 } 1936 } 1937 ret = mhd_tls_daemon_init (d, 1938 mhd_D_HAS_EDGE_TRIGG (d), 1939 s, 1940 &(d->tls)); 1941 mhd_assert ((MHD_SC_OK == ret) || (NULL == d->tls)); 1942 mhd_assert ((MHD_SC_OK != ret) || (NULL != d->tls)); 1943 # ifndef NDEBUG 1944 d->dbg.tls_inited = (MHD_SC_OK == ret); 1945 # endif 1946 return (enum MHD_StatusCode)ret; 1947 #endif /* MHD_SUPPORT_HTTPS */ 1948 } 1949 1950 1951 /** 1952 * Deinitialise daemon TLS data 1953 * @param d the daemon object 1954 */ 1955 MHD_FN_PAR_NONNULL_ (1) static void 1956 daemon_deinit_tls (struct MHD_Daemon *restrict d) 1957 { 1958 mhd_assert (d->dbg.tls_inited); 1959 #ifdef MHD_SUPPORT_HTTPS 1960 if (NULL != d->tls) 1961 { 1962 mhd_tls_thread_cleanup (d->tls); 1963 mhd_tls_daemon_deinit (d->tls); 1964 } 1965 #elif defined(NDEBUG) 1966 (void)d; /* Mute compiler warning */ 1967 #endif 1968 } 1969 1970 1971 /** 1972 * Initialise large buffer tracking. 1973 * @param d the daemon object 1974 * @param s the user settings 1975 * @return #MHD_SC_OK on success, 1976 * the error code otherwise 1977 */ 1978 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) \ 1979 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1980 daemon_init_large_buf (struct MHD_Daemon *restrict d, 1981 struct DaemonOptions *restrict s) 1982 { 1983 mhd_assert (!mhd_D_HAS_MASTER (d)); 1984 mhd_assert (0 != d->conns.cfg.count_limit); 1985 mhd_assert (0 != d->conns.cfg.mem_pool_size); 1986 1987 d->req_cfg.large_buf.space_left = s->large_pool_size; 1988 if (SIZE_MAX == d->req_cfg.large_buf.space_left) 1989 d->req_cfg.large_buf.space_left = 1990 (d->conns.cfg.count_limit * d->conns.cfg.mem_pool_size) / 32; /* Use ~3% of the maximum memory used by connections */ 1991 1992 #ifndef NDEBUG 1993 d->dbg.initial_lbuf_size = d->req_cfg.large_buf.space_left; 1994 #endif 1995 1996 if (!mhd_mutex_init_short (&(d->req_cfg.large_buf.lock))) 1997 { 1998 mhd_LOG_MSG (d, MHD_SC_MUTEX_INIT_FAILURE, \ 1999 "Failed to initialise mutex for the global large buffer."); 2000 return MHD_SC_MUTEX_INIT_FAILURE; 2001 } 2002 return MHD_SC_OK; 2003 } 2004 2005 2006 /** 2007 * Deinitialise large buffer tracking. 2008 * @param d the daemon object 2009 */ 2010 static MHD_FN_PAR_NONNULL_ (1) void 2011 daemon_deinit_large_buf (struct MHD_Daemon *restrict d) 2012 { 2013 /* All large buffer allocations must be freed / deallocated earlier */ 2014 mhd_assert (d->dbg.initial_lbuf_size == d->req_cfg.large_buf.space_left); 2015 mhd_mutex_destroy_chk (&(d->req_cfg.large_buf.lock)); 2016 } 2017 2018 2019 /** 2020 * Initialise ACME data. 2021 * @param d the daemon object 2022 * @param s the user settings 2023 * @return #MHD_SC_OK on success, 2024 * the error code otherwise 2025 */ 2026 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 2027 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 2028 daemon_init_acme (struct MHD_Daemon *restrict d, 2029 struct DaemonOptions *restrict s) 2030 { 2031 mhd_assert (!mhd_D_HAS_MASTER (d)); 2032 2033 #ifndef mhd_HAVE_TLS_ACME 2034 if (s->acme_alpn_required) 2035 { 2036 mhd_LOG_MSG (d, MHD_SC_FEATURE_DISABLED, 2037 "ACME ALPN challenge is not supported by this MHD build"); 2038 return MHD_SC_FEATURE_DISABLED; 2039 } 2040 #endif /* mhd_HAVE_TLS_ACME */ 2041 2042 #ifdef MHD_SUPPORT_ACME 2043 if (!mhd_D_HAS_TLS (d)) 2044 { 2045 if (s->acme_alpn_required) 2046 { 2047 mhd_LOG_MSG (d, MHD_SC_DAEMON_HAS_TLS_DISABLED, 2048 "ACME ALPN challenge requires TLS to be enabled"); 2049 return MHD_SC_DAEMON_HAS_TLS_DISABLED; 2050 } 2051 } 2052 # ifdef MHD_SUPPORT_HTTPS 2053 else 2054 { 2055 mhd_StatusCodeInt res_i; 2056 res_i = mhd_daemon_acme_certs_init (d); 2057 return (enum MHD_StatusCode)res_i; 2058 } 2059 # endif /* MHD_SUPPORT_HTTPS */ 2060 #else /* ! MHD_SUPPORT_ACME */ 2061 (void)d; /* Unused */ 2062 #endif /* ! MHD_SUPPORT_ACME */ 2063 2064 return MHD_SC_OK; /* Success exit point */ 2065 } 2066 2067 2068 #ifdef MHD_SUPPORT_ACME 2069 2070 /** 2071 * Deinitialise ACME data. 2072 * @param d the daemon object 2073 */ 2074 static MHD_FN_PAR_NONNULL_ (1) void 2075 daemon_deinit_acme (struct MHD_Daemon *restrict d) 2076 { 2077 mhd_assert (!mhd_D_HAS_MASTER (d)); 2078 2079 # ifdef MHD_SUPPORT_HTTPS 2080 if (mhd_D_HAS_TLS (d)) 2081 mhd_daemon_acme_certs_deinit (d); 2082 # else 2083 (void)d; /* Unused */ 2084 # endif 2085 } 2086 2087 2088 #else /* ! MHD_SUPPORT_ACME */ 2089 # define daemon_deinit_acme(d) ((void) d) 2090 #endif /* ! MHD_SUPPORT_ACME */ 2091 2092 #ifdef MHD_SUPPORT_KQUEUE 2093 2094 /** 2095 * Initialise daemon's kqueue FD 2096 * @param d the daemon object 2097 * @return #MHD_SC_OK on success, 2098 * the error code otherwise 2099 */ 2100 static MHD_FN_PAR_NONNULL_ (1) enum MHD_StatusCode 2101 init_kqueue_fd (struct MHD_Daemon *restrict d) 2102 { 2103 int kq_fd; 2104 mhd_assert (mhd_POLL_TYPE_KQUEUE == d->events.poll_type); 2105 mhd_assert (!mhd_WM_INT_IS_THREAD_PER_CONN (d->wmode_int)); 2106 mhd_assert (d->dbg.net_inited); 2107 mhd_assert (MHD_INVALID_SOCKET == d->events.data.kq.kq_fd); 2108 mhd_assert (NULL == d->events.data.kq.kes); 2109 mhd_assert (0u == d->events.data.kq.num_elements); 2110 2111 kq_fd = mhd_kqueue (); 2112 if (0 > kq_fd) 2113 { 2114 mhd_LOG_MSG (d, MHD_SC_KQUEUE_FD_CREATE_FAILED, \ 2115 "Failed to create kqueue FD"); 2116 return MHD_SC_KQUEUE_FD_CREATE_FAILED; /* Failure exit point */ 2117 } 2118 2119 if (!mhd_FD_FITS_DAEMON (d, kq_fd)) 2120 { 2121 mhd_LOG_MSG (d, MHD_SC_KQUEUE_FD_OUTSIDE_OF_SET_RANGE, \ 2122 "The kqueue FD value is higher than allowed"); 2123 (void)close (kq_fd); 2124 return MHD_SC_KQUEUE_FD_OUTSIDE_OF_SET_RANGE; /* Failure exit point */ 2125 } 2126 2127 if (!mhd_KQUEUE_HAS_CLOEXEC_SET ()) 2128 { 2129 if (!mhd_socket_noninheritable (kq_fd)) 2130 mhd_LOG_MSG (d, MHD_SC_KQUEUE_FD_SET_NOINHERIT_FAILED, \ 2131 "Failed to make kqueue FD non-inheritable"); 2132 } 2133 d->events.data.kq.kq_fd = kq_fd; 2134 2135 return MHD_SC_OK; /* Success exit point */ 2136 } 2137 2138 2139 /** 2140 * Deinitialise daemon's kqueue FD 2141 * @param d the daemon object 2142 */ 2143 MHD_FN_PAR_NONNULL_ (1) static void 2144 deinit_kqueue_fd (struct MHD_Daemon *restrict d) 2145 { 2146 mhd_assert (mhd_POLL_TYPE_KQUEUE == d->events.poll_type); 2147 mhd_assert (0 < d->events.data.kq.kq_fd); 2148 close (d->events.data.kq.kq_fd); 2149 } 2150 2151 2152 #endif /* MHD_SUPPORT_KQUEUE */ 2153 2154 2155 /** 2156 * Initialise daemon's events polling FD (if used by polling function) 2157 * @param d the daemon object 2158 * @return #MHD_SC_OK on success, 2159 * the error code otherwise 2160 */ 2161 static MHD_FN_PAR_NONNULL_ (1) 2162 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 2163 init_events_fd (struct MHD_Daemon *restrict d) 2164 { 2165 enum MHD_StatusCode res; 2166 2167 res = MHD_SC_OK; 2168 switch (d->events.poll_type) 2169 { 2170 case mhd_POLL_TYPE_EXT: 2171 break; 2172 #ifdef MHD_SUPPORT_SELECT 2173 case mhd_POLL_TYPE_SELECT: 2174 break; 2175 #endif /* MHD_SUPPORT_SELECT */ 2176 #ifdef MHD_SUPPORT_POLL 2177 case mhd_POLL_TYPE_POLL: 2178 break; 2179 #endif /* MHD_SUPPORT_POLL */ 2180 #ifdef MHD_SUPPORT_EPOLL 2181 case mhd_POLL_TYPE_EPOLL: 2182 res = init_epoll_fd (d, 2183 false, 2184 true); 2185 break; 2186 #endif /* MHD_SUPPORT_EPOLL */ 2187 #ifdef MHD_SUPPORT_KQUEUE 2188 case mhd_POLL_TYPE_KQUEUE: 2189 res = init_kqueue_fd (d); 2190 break; 2191 #endif /* MHD_SUPPORT_KQUEUE */ 2192 #ifndef MHD_SUPPORT_SELECT 2193 case mhd_POLL_TYPE_SELECT: 2194 #endif /* ! MHD_SUPPORT_SELECT */ 2195 #ifndef MHD_SUPPORT_POLL 2196 case mhd_POLL_TYPE_POLL: 2197 #endif /* ! MHD_SUPPORT_POLL */ 2198 case mhd_POLL_TYPE_NOT_SET_YET: 2199 default: 2200 mhd_UNREACHABLE (); 2201 return MHD_SC_INTERNAL_ERROR; 2202 } 2203 2204 #ifndef NDEBUG 2205 if (MHD_SC_OK == res) 2206 d->dbg.events_fd_inited = true; 2207 #endif /* ! NDEBUG */ 2208 2209 return res; 2210 } 2211 2212 2213 /** 2214 * Deinitialise daemon's events polling FD (if used by polling function) 2215 * @param d the daemon object 2216 */ 2217 static MHD_FN_PAR_NONNULL_ (1) void 2218 deinit_events_fd (struct MHD_Daemon *restrict d) 2219 { 2220 mhd_assert (d->dbg.events_fd_inited); 2221 2222 switch (d->events.poll_type) 2223 { 2224 case mhd_POLL_TYPE_EXT: 2225 return; 2226 #ifdef MHD_SUPPORT_SELECT 2227 case mhd_POLL_TYPE_SELECT: 2228 return; 2229 #endif /* MHD_SUPPORT_SELECT */ 2230 #ifdef MHD_SUPPORT_POLL 2231 case mhd_POLL_TYPE_POLL: 2232 return; 2233 #endif /* MHD_SUPPORT_POLL */ 2234 #ifdef MHD_SUPPORT_EPOLL 2235 case mhd_POLL_TYPE_EPOLL: 2236 deinit_epoll_fd (d); 2237 return; 2238 #endif /* MHD_SUPPORT_EPOLL */ 2239 #ifdef MHD_SUPPORT_KQUEUE 2240 case mhd_POLL_TYPE_KQUEUE: 2241 deinit_kqueue_fd (d); 2242 return; 2243 #endif /* MHD_SUPPORT_KQUEUE */ 2244 #ifndef MHD_SUPPORT_SELECT 2245 case mhd_POLL_TYPE_SELECT: 2246 #endif /* ! MHD_SUPPORT_SELECT */ 2247 #ifndef MHD_SUPPORT_POLL 2248 case mhd_POLL_TYPE_POLL: 2249 #endif /* ! MHD_SUPPORT_POLL */ 2250 case mhd_POLL_TYPE_NOT_SET_YET: 2251 default: 2252 mhd_UNREACHABLE (); 2253 } 2254 return; 2255 } 2256 2257 2258 /** 2259 * Finish initialisation of events processing 2260 * @param d the daemon object 2261 * @return #MHD_SC_OK on success, 2262 * the error code otherwise 2263 */ 2264 static MHD_FN_PAR_NONNULL_ (1) 2265 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 2266 allocate_events (struct MHD_Daemon *restrict d) 2267 { 2268 #if defined(MHD_SUPPORT_POLL) || defined(MHD_SUPPORT_EPOLL) 2269 /** 2270 * The number of elements to be monitored by sockets polling function 2271 */ 2272 unsigned int num_fd_elems; 2273 num_fd_elems = 0; 2274 # ifdef MHD_SUPPORT_THREADS 2275 ++num_fd_elems; /* For the ITC */ 2276 # endif 2277 if (MHD_INVALID_SOCKET != d->net.listen.fd) 2278 ++num_fd_elems; /* For the listening socket */ 2279 if (!mhd_D_HAS_THR_PER_CONN (d)) 2280 num_fd_elems += d->conns.cfg.count_limit; 2281 #endif /* MHD_SUPPORT_POLL || MHD_SUPPORT_EPOLL */ 2282 2283 mhd_assert (0 != d->conns.cfg.count_limit); 2284 mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); 2285 mhd_assert (!d->dbg.events_allocated); 2286 2287 mhd_DLINKEDL_INIT_LIST (&(d->events), proc_ready); 2288 2289 switch (d->events.poll_type) 2290 { 2291 case mhd_POLL_TYPE_EXT: 2292 mhd_assert (NULL != d->events.data.extr.cb_data.cb); 2293 /* Nothing to do: allocation is not needed */ 2294 #ifndef NDEBUG 2295 d->dbg.events_allocated = true; 2296 #endif 2297 return MHD_SC_OK; /* Success exit point */ 2298 break; 2299 #ifdef MHD_SUPPORT_SELECT 2300 case mhd_POLL_TYPE_SELECT: 2301 /* The pointers have been set to NULL during pre-initialisations of the events */ 2302 mhd_assert (NULL == d->events.data.select.rfds); 2303 mhd_assert (NULL == d->events.data.select.wfds); 2304 mhd_assert (NULL == d->events.data.select.efds); 2305 d->events.data.select.rfds = (fd_set *)malloc (sizeof(fd_set)); 2306 if (NULL != d->events.data.select.rfds) 2307 { 2308 d->events.data.select.wfds = (fd_set *)malloc (sizeof(fd_set)); 2309 if (NULL != d->events.data.select.wfds) 2310 { 2311 d->events.data.select.efds = (fd_set *)malloc (sizeof(fd_set)); 2312 if (NULL != d->events.data.select.efds) 2313 { 2314 # ifndef NDEBUG 2315 d->dbg.num_events_elements = FD_SETSIZE; 2316 d->dbg.events_allocated = true; 2317 # endif 2318 return MHD_SC_OK; /* Success exit point */ 2319 } 2320 2321 free (d->events.data.select.wfds); 2322 } 2323 free (d->events.data.select.rfds); 2324 } 2325 mhd_LOG_MSG (d, MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE, \ 2326 "Failed to allocate memory for fd_sets for the daemon"); 2327 return MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE; 2328 break; 2329 #endif /* MHD_SUPPORT_SELECT */ 2330 #ifdef MHD_SUPPORT_POLL 2331 case mhd_POLL_TYPE_POLL: 2332 /* The pointers have been set to NULL during pre-initialisations of the events */ 2333 mhd_assert (NULL == d->events.data.poll.fds); 2334 mhd_assert (NULL == d->events.data.poll.rel); 2335 if ((num_fd_elems > d->conns.cfg.count_limit) /* Check for value overflow */ 2336 || (mhd_D_HAS_THR_PER_CONN (d))) 2337 { 2338 d->events.data.poll.fds = 2339 (struct pollfd *)malloc (sizeof(struct pollfd) * num_fd_elems); 2340 if (NULL != d->events.data.poll.fds) 2341 { 2342 d->events.data.poll.rel = 2343 (union mhd_SocketRelation *)malloc (sizeof(union mhd_SocketRelation) 2344 * num_fd_elems); 2345 if (NULL != d->events.data.poll.rel) 2346 { 2347 # ifndef NDEBUG 2348 d->dbg.num_events_elements = num_fd_elems; 2349 d->dbg.events_allocated = true; 2350 # endif 2351 return MHD_SC_OK; /* Success exit point */ 2352 } 2353 free (d->events.data.poll.fds); 2354 } 2355 } 2356 mhd_LOG_MSG (d, MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE, \ 2357 "Failed to allocate memory for poll fds for the daemon"); 2358 return MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE; 2359 break; 2360 #endif /* MHD_SUPPORT_POLL */ 2361 #ifdef MHD_SUPPORT_EPOLL 2362 case mhd_POLL_TYPE_EPOLL: 2363 mhd_ASSUME (!mhd_D_HAS_THR_PER_CONN (d)); 2364 /* The event FD has been created by event FD initialisation */ 2365 mhd_assert (MHD_INVALID_SOCKET != d->events.data.epoll.e_fd); 2366 mhd_assert (MHD_INVALID_SOCKET == d->events.data.epoll.early_fd); 2367 /* The pointer has been set to NULL during pre-initialisation of the events */ 2368 mhd_assert (NULL == d->events.data.epoll.events); 2369 mhd_assert (0 == d->events.data.epoll.num_elements); 2370 if (1) 2371 { 2372 const unsigned int upper_limit = (sizeof(void *) >= 8) ? 4096u : 1024u; 2373 2374 mhd_assert (0 < (int)upper_limit); 2375 mhd_assert (upper_limit == (unsigned int)(size_t)upper_limit); 2376 2377 if (num_fd_elems < d->conns.cfg.count_limit) /* Check for value overflow */ 2378 num_fd_elems = upper_limit; 2379 /* Trade neglectable performance penalty for memory saving */ 2380 /* Very large amount of new events processed in batches */ 2381 else if (num_fd_elems > upper_limit) 2382 num_fd_elems = upper_limit; 2383 2384 d->events.data.epoll.events = 2385 (struct epoll_event *)malloc (sizeof(struct epoll_event) 2386 * num_fd_elems); 2387 if (NULL != d->events.data.epoll.events) 2388 { 2389 d->events.data.epoll.num_elements = num_fd_elems; 2390 # ifndef NDEBUG 2391 d->dbg.num_events_elements = num_fd_elems; 2392 d->dbg.events_allocated = true; 2393 # endif 2394 return MHD_SC_OK; /* Success exit point */ 2395 } 2396 } 2397 mhd_LOG_MSG (d, MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE, \ 2398 "Failed to allocate memory for epoll events for the daemon"); 2399 return MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE; 2400 break; 2401 #endif /* MHD_SUPPORT_EPOLL */ 2402 #ifdef MHD_SUPPORT_KQUEUE 2403 case mhd_POLL_TYPE_KQUEUE: 2404 mhd_ASSUME (!mhd_D_HAS_THR_PER_CONN (d)); 2405 /* The event FD has been created by event FD initialisation */ 2406 mhd_assert (0 < d->events.data.kq.kq_fd); 2407 /* The pointer has been set to NULL during pre-initialisation of the events */ 2408 mhd_assert (NULL == d->events.data.kq.kes); 2409 mhd_assert (0u == d->events.data.kq.num_elements); 2410 if (1) 2411 { 2412 const unsigned int upper_limit = (sizeof(void *) >= 8) ? 4096u : 1024u; 2413 unsigned int num_event_elems = 0; 2414 2415 mhd_assert (0 < (int)upper_limit); 2416 mhd_assert (upper_limit == (unsigned int)(size_t)upper_limit); 2417 2418 # ifdef MHD_SUPPORT_THREADS 2419 ++num_event_elems; /* For the ITC */ 2420 # endif 2421 if (MHD_INVALID_SOCKET != d->net.listen.fd) 2422 ++num_event_elems; /* For the listening socket */ 2423 2424 /* kqueue needs slots for individual combinations of FD + filter (send/recv) */ 2425 num_event_elems += 2 * d->conns.cfg.count_limit; 2426 if (d->conns.cfg.count_limit > (num_event_elems / 2)) /* Check for overflow */ 2427 num_event_elems = upper_limit; 2428 /* Trade neglectable performance penalty for memory saving */ 2429 /* Very large amount of new events processed in batches */ 2430 else if (upper_limit < num_event_elems) 2431 num_event_elems = upper_limit; 2432 2433 /* Make sure that run-time overflow check is easy */ 2434 mhd_assert (((int)num_event_elems) > 0); 2435 mhd_assert (((int)(num_event_elems + 1)) > 0); 2436 2437 d->events.data.kq.kes = 2438 (struct kevent *)malloc (sizeof(struct kevent) * num_event_elems); 2439 if (NULL != d->events.data.kq.kes) 2440 { 2441 d->events.data.kq.num_elements = num_event_elems; 2442 # ifndef NDEBUG 2443 d->dbg.num_events_elements = num_event_elems; 2444 d->dbg.events_allocated = true; 2445 # endif 2446 return MHD_SC_OK; /* Success exit point */ 2447 } 2448 } 2449 mhd_LOG_MSG (d, MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE, \ 2450 "Failed to allocate memory for kqueue events for the daemon"); 2451 return MHD_SC_EVENTS_MEMORY_ALLOCATE_FAILURE; 2452 break; 2453 #endif /* MHD_SUPPORT_KQUEUE */ 2454 #ifndef MHD_SUPPORT_SELECT 2455 case mhd_POLL_TYPE_SELECT: 2456 #endif /* ! MHD_SUPPORT_SELECT */ 2457 #ifndef MHD_SUPPORT_POLL 2458 case mhd_POLL_TYPE_POLL: 2459 #endif /* ! MHD_SUPPORT_POLL */ 2460 case mhd_POLL_TYPE_NOT_SET_YET: 2461 default: 2462 mhd_UNREACHABLE (); 2463 break; 2464 } 2465 mhd_UNREACHABLE (); 2466 return MHD_SC_INTERNAL_ERROR; 2467 } 2468 2469 2470 /** 2471 * Deallocate events data 2472 * @param d the daemon object 2473 */ 2474 static MHD_FN_PAR_NONNULL_ (1) void 2475 deallocate_events (struct MHD_Daemon *restrict d) 2476 { 2477 mhd_assert (d->dbg.events_allocated); 2478 mhd_assert (0 != d->conns.cfg.count_limit); 2479 mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); 2480 switch (d->events.poll_type) 2481 { 2482 case mhd_POLL_TYPE_EXT: 2483 break; 2484 #ifdef MHD_SUPPORT_SELECT 2485 case mhd_POLL_TYPE_SELECT: 2486 mhd_assert (NULL != d->events.data.select.efds); 2487 mhd_assert (NULL != d->events.data.select.wfds); 2488 mhd_assert (NULL != d->events.data.select.rfds); 2489 free (d->events.data.select.efds); 2490 free (d->events.data.select.wfds); 2491 free (d->events.data.select.rfds); 2492 break; 2493 #endif /* MHD_SUPPORT_SELECT */ 2494 #ifdef MHD_SUPPORT_POLL 2495 case mhd_POLL_TYPE_POLL: 2496 mhd_assert (NULL != d->events.data.poll.rel); 2497 mhd_assert (NULL != d->events.data.poll.fds); 2498 free (d->events.data.poll.rel); 2499 free (d->events.data.poll.fds); 2500 break; 2501 #endif /* MHD_SUPPORT_POLL */ 2502 #ifdef MHD_SUPPORT_EPOLL 2503 case mhd_POLL_TYPE_EPOLL: 2504 mhd_assert (0 != d->events.data.epoll.num_elements); 2505 mhd_assert (NULL != d->events.data.epoll.events); 2506 free (d->events.data.epoll.events); 2507 break; 2508 #endif /* MHD_SUPPORT_EPOLL */ 2509 #ifdef MHD_SUPPORT_KQUEUE 2510 case mhd_POLL_TYPE_KQUEUE: 2511 mhd_assert (0 != d->events.data.kq.num_elements); 2512 mhd_assert (NULL != d->events.data.kq.kes); 2513 free (d->events.data.kq.kes); 2514 break; 2515 #endif /* MHD_SUPPORT_KQUEUE */ 2516 #ifndef MHD_SUPPORT_SELECT 2517 case mhd_POLL_TYPE_SELECT: 2518 #endif /* ! MHD_SUPPORT_SELECT */ 2519 #ifndef MHD_SUPPORT_POLL 2520 case mhd_POLL_TYPE_POLL: 2521 #endif /* ! MHD_SUPPORT_POLL */ 2522 case mhd_POLL_TYPE_NOT_SET_YET: 2523 default: 2524 mhd_UNREACHABLE_D ("Wrong workflow"); 2525 } 2526 #ifndef NDEBUG 2527 d->dbg.events_allocated = false; 2528 #endif 2529 return; 2530 } 2531 2532 2533 /** 2534 * Initialise daemon's ITC 2535 * @param d the daemon object 2536 * @return #MHD_SC_OK on success, 2537 * the error code otherwise 2538 */ 2539 static MHD_FN_PAR_NONNULL_ (1) 2540 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 2541 init_itc (struct MHD_Daemon *restrict d) 2542 { 2543 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 2544 mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); 2545 #ifdef MHD_SUPPORT_THREADS 2546 // TODO: add and process "thread unsafe" daemon's option 2547 if (!mhd_itc_init (&(d->threading.itc))) 2548 { 2549 # if defined(MHD_ITC_EVENTFD_) 2550 mhd_LOG_MSG ( \ 2551 d, MHD_SC_ITC_INITIALIZATION_FAILED, \ 2552 "Failed to initialise eventFD for inter-thread communication"); 2553 # elif defined(MHD_ITC_PIPE_) 2554 mhd_LOG_MSG ( \ 2555 d, MHD_SC_ITC_INITIALIZATION_FAILED, \ 2556 "Failed to create a pipe for inter-thread communication"); 2557 # elif defined(MHD_ITC_SOCKETPAIR_) 2558 mhd_LOG_MSG ( \ 2559 d, MHD_SC_ITC_INITIALIZATION_FAILED, \ 2560 "Failed to create a socketpair for inter-thread communication"); 2561 # else 2562 # warning Missing expicit handling of the ITC type 2563 mhd_LOG_MSG ( \ 2564 d, MHD_SC_ITC_INITIALIZATION_FAILED, \ 2565 "Failed to initialise inter-thread communication"); 2566 # endif 2567 return MHD_SC_ITC_INITIALIZATION_FAILED; 2568 } 2569 if (!mhd_FD_FITS_DAEMON (d, mhd_itc_r_fd (d->threading.itc))) 2570 { 2571 mhd_LOG_MSG (d, MHD_SC_ITC_FD_OUTSIDE_OF_SET_RANGE, \ 2572 "The inter-thread communication FD value is " \ 2573 "higher than allowed"); 2574 (void)mhd_itc_destroy (d->threading.itc); 2575 mhd_itc_set_invalid (&(d->threading.itc)); 2576 return MHD_SC_ITC_FD_OUTSIDE_OF_SET_RANGE; 2577 } 2578 #else /* ! MHD_SUPPORT_THREADS */ 2579 (void)d; /* Unused */ 2580 #endif /* ! MHD_SUPPORT_THREADS */ 2581 return MHD_SC_OK; 2582 } 2583 2584 2585 /** 2586 * Deallocate events data 2587 * @param d the daemon object 2588 */ 2589 static MHD_FN_PAR_NONNULL_ (1) void 2590 deinit_itc (struct MHD_Daemon *restrict d) 2591 { 2592 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 2593 mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); 2594 #ifdef MHD_SUPPORT_THREADS 2595 // TODO: add and process "thread unsafe" daemon's option 2596 mhd_assert (!mhd_ITC_IS_INVALID (d->threading.itc)); 2597 (void)mhd_itc_destroy (d->threading.itc); 2598 #else /* ! MHD_SUPPORT_THREADS */ 2599 (void)d; /* Unused */ 2600 #endif /* ! MHD_SUPPORT_THREADS */ 2601 } 2602 2603 2604 /** 2605 * The final part of events initialisation: pre-add ITC and listening FD to 2606 * the monitored items (if supported by monitoring syscall). 2607 * @param d the daemon object 2608 * @return #MHD_SC_OK on success, 2609 * the error code otherwise 2610 */ 2611 static MHD_FN_PAR_NONNULL_ (1) 2612 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 2613 init_daemon_fds_monitoring (struct MHD_Daemon *restrict d) 2614 { 2615 mhd_assert (d->dbg.net_inited); 2616 mhd_assert (!d->dbg.net_deinited); 2617 mhd_assert (d->dbg.events_allocated); 2618 mhd_assert (!d->dbg.events_fully_inited); 2619 mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); 2620 #ifdef MHD_SUPPORT_THREADS 2621 mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); 2622 #endif 2623 2624 d->events.accept_pending = false; 2625 2626 switch (d->events.poll_type) 2627 { 2628 case mhd_POLL_TYPE_EXT: 2629 mhd_assert (NULL != d->events.data.extr.cb_data.cb); 2630 #ifdef MHD_SUPPORT_THREADS 2631 d->events.data.extr.itc_data.is_active = false; 2632 d->events.data.extr.itc_data.is_broken = false; 2633 #endif /* MHD_SUPPORT_THREADS */ 2634 if (!d->events.data.extr.reg_all) 2635 { 2636 bool itc_reg_succeed; 2637 2638 /* Register daemon's FDs now */ 2639 #ifdef MHD_SUPPORT_THREADS 2640 d->events.data.extr.itc_data.app_cntx = 2641 mhd_daemon_extr_event_reg (d, 2642 mhd_itc_r_fd (d->threading.itc), 2643 MHD_FD_STATE_RECV_EXCEPT, 2644 NULL, 2645 (struct MHD_EventUpdateContext *) 2646 mhd_SOCKET_REL_MARKER_ITC); 2647 itc_reg_succeed = (NULL != d->events.data.extr.itc_data.app_cntx); 2648 #else /* ! MHD_SUPPORT_THREADS */ 2649 itc_reg_succeed = true; 2650 #endif /* ! MHD_SUPPORT_THREADS */ 2651 if (itc_reg_succeed) 2652 { 2653 if (MHD_INVALID_SOCKET == d->net.listen.fd) 2654 { 2655 d->events.data.extr.listen_data.app_cntx = NULL; 2656 return MHD_SC_OK; /* Success exit point */ 2657 } 2658 2659 /* Need to register the listen FD */ 2660 d->events.data.extr.listen_data.app_cntx = 2661 mhd_daemon_extr_event_reg (d, 2662 d->net.listen.fd, 2663 MHD_FD_STATE_RECV_EXCEPT, 2664 NULL, 2665 (struct MHD_EventUpdateContext *) 2666 mhd_SOCKET_REL_MARKER_LISTEN); 2667 if (NULL != d->events.data.extr.listen_data.app_cntx) 2668 return MHD_SC_OK; /* Success exit point */ 2669 2670 /* Below is a clean-up path for 'case mhd_POLL_TYPE_EXT:' */ 2671 #ifdef MHD_SUPPORT_THREADS 2672 /* De-register ITC FD */ 2673 (void)mhd_daemon_extr_event_reg (d, 2674 mhd_itc_r_fd (d->threading.itc), 2675 MHD_FD_STATE_NONE, 2676 d->events.data.extr.itc_data.app_cntx, 2677 (struct MHD_EventUpdateContext *) 2678 mhd_SOCKET_REL_MARKER_ITC); 2679 d->events.data.extr.itc_data.app_cntx = NULL; 2680 #endif /* MHD_SUPPORT_THREADS */ 2681 } 2682 2683 mhd_LOG_MSG (d, MHD_SC_EXT_EVENT_REG_DAEMON_FDS_FAILURE, \ 2684 "Failed to register daemon FDs in the application " 2685 "(external events) monitoring."); 2686 return MHD_SC_EXT_EVENT_REG_DAEMON_FDS_FAILURE; 2687 } 2688 else 2689 { 2690 /* Daemons FDs are repeatedly registered every processing cycle */ 2691 #ifdef MHD_SUPPORT_THREADS 2692 d->events.data.extr.itc_data.app_cntx = NULL; 2693 #endif /* MHD_SUPPORT_THREADS */ 2694 d->events.data.extr.listen_data.app_cntx = NULL; 2695 return MHD_SC_OK; 2696 } 2697 break; 2698 #ifdef MHD_SUPPORT_SELECT 2699 case mhd_POLL_TYPE_SELECT: 2700 mhd_assert (NULL != d->events.data.select.rfds); 2701 mhd_assert (NULL != d->events.data.select.wfds); 2702 mhd_assert (NULL != d->events.data.select.efds); 2703 /* Nothing to do when using 'select()' */ 2704 return MHD_SC_OK; 2705 break; 2706 #endif /* MHD_SUPPORT_SELECT */ 2707 #ifdef MHD_SUPPORT_POLL 2708 case mhd_POLL_TYPE_POLL: 2709 mhd_assert (NULL != d->events.data.poll.fds); 2710 mhd_assert (NULL != d->events.data.poll.rel); 2711 if (1) 2712 { 2713 unsigned int i; 2714 i = 0; 2715 # ifdef MHD_SUPPORT_THREADS 2716 d->events.data.poll.fds[i].fd = mhd_itc_r_fd (d->threading.itc); 2717 d->events.data.poll.fds[i].events = POLLIN; 2718 d->events.data.poll.rel[i].fd_id = mhd_SOCKET_REL_MARKER_ITC; 2719 ++i; 2720 # endif 2721 if (MHD_INVALID_SOCKET != d->net.listen.fd) 2722 { 2723 d->events.data.poll.fds[i].fd = d->net.listen.fd; 2724 d->events.data.poll.fds[i].events = POLLIN; 2725 d->events.data.poll.rel[i].fd_id = mhd_SOCKET_REL_MARKER_LISTEN; 2726 } 2727 } 2728 return MHD_SC_OK; 2729 break; 2730 #endif /* MHD_SUPPORT_POLL */ 2731 #ifdef MHD_SUPPORT_EPOLL 2732 case mhd_POLL_TYPE_EPOLL: 2733 mhd_assert (MHD_INVALID_SOCKET != d->events.data.epoll.e_fd); 2734 mhd_assert (MHD_INVALID_SOCKET == d->events.data.epoll.early_fd); 2735 mhd_assert (NULL != d->events.data.epoll.events); 2736 mhd_assert (0 < d->events.data.epoll.num_elements); 2737 if (1) 2738 { 2739 struct epoll_event reg_event; 2740 # ifdef MHD_SUPPORT_THREADS 2741 reg_event.events = EPOLLIN | EPOLLET; 2742 reg_event.data.u64 = (uint64_t)mhd_SOCKET_REL_MARKER_ITC; /* uint64_t is used in the epoll header */ 2743 if (0 != epoll_ctl (d->events.data.epoll.e_fd, EPOLL_CTL_ADD, 2744 mhd_itc_r_fd (d->threading.itc), ®_event)) 2745 { 2746 mhd_LOG_MSG (d, MHD_SC_EVENTS_REG_DAEMON_FDS_FAILURE, \ 2747 "Failed to add ITC FD to the epoll monitoring."); 2748 return MHD_SC_EVENTS_REG_DAEMON_FDS_FAILURE; 2749 } 2750 mhd_dbg_print_fd_mon_req ("ITC", \ 2751 mhd_itc_r_fd (d->threading.itc), \ 2752 true, \ 2753 false, \ 2754 false); 2755 # endif 2756 if (MHD_INVALID_SOCKET != d->net.listen.fd) 2757 { 2758 reg_event.events = EPOLLIN; 2759 reg_event.data.u64 = (uint64_t)mhd_SOCKET_REL_MARKER_LISTEN; /* uint64_t is used in the epoll header */ 2760 if (0 != epoll_ctl (d->events.data.epoll.e_fd, EPOLL_CTL_ADD, 2761 d->net.listen.fd, ®_event)) 2762 { 2763 mhd_LOG_MSG (d, MHD_SC_EVENTS_REG_DAEMON_FDS_FAILURE, \ 2764 "Failed to add listening FD to the epoll monitoring."); 2765 return MHD_SC_EVENTS_REG_DAEMON_FDS_FAILURE; 2766 } 2767 mhd_dbg_print_fd_mon_req ("lstn", \ 2768 d->net.listen.fd, \ 2769 true, \ 2770 false, \ 2771 false); 2772 } 2773 } 2774 return MHD_SC_OK; 2775 break; 2776 #endif /* MHD_SUPPORT_EPOLL */ 2777 #ifdef MHD_SUPPORT_KQUEUE 2778 case mhd_POLL_TYPE_KQUEUE: 2779 mhd_assert (0 < d->events.data.kq.kq_fd); 2780 mhd_assert (NULL != d->events.data.kq.kes); 2781 mhd_assert (2u < d->events.data.kq.num_elements); 2782 if (1) 2783 { 2784 int num_elemnts; 2785 2786 num_elemnts = 0; 2787 # ifdef MHD_SUPPORT_THREADS 2788 mhd_KE_SET (d->events.data.kq.kes + num_elemnts, 2789 mhd_itc_r_fd (d->threading.itc), 2790 EVFILT_READ, 2791 EV_ADD, /* level trigger */ 2792 mhd_SOCKET_REL_PTRMARKER_ITC); 2793 mhd_dbg_print_kevent_change ("ITC", 2794 d->events.data.kq.kes + num_elemnts); 2795 ++num_elemnts; 2796 # endif 2797 if (MHD_INVALID_SOCKET != d->net.listen.fd) 2798 { 2799 mhd_KE_SET (d->events.data.kq.kes + num_elemnts, 2800 d->net.listen.fd, 2801 EVFILT_READ, 2802 EV_ADD, /* level trigger */ 2803 mhd_SOCKET_REL_PTRMARKER_LISTEN); 2804 2805 mhd_dbg_print_kevent_change ("lstn", 2806 d->events.data.kq.kes + num_elemnts); 2807 ++num_elemnts; 2808 } 2809 2810 if (0 != num_elemnts) 2811 { 2812 static const struct timespec zero_timeout = {0, 0}; 2813 int res; 2814 2815 # ifdef MHD_USE_TRACE_POLLING_FDS 2816 fprintf (stderr, 2817 "### (Starting) kevent(%d, changes, %d, [NULL], " 2818 "0, [0, 0])...\n", 2819 d->events.data.kq.kq_fd, 2820 num_elemnts); 2821 # endif /* MHD_USE_TRACE_POLLING_FDS */ 2822 res = kevent (d->events.data.kq.kq_fd, 2823 d->events.data.kq.kes, 2824 num_elemnts, 2825 NULL, 2826 0, 2827 &zero_timeout); 2828 # ifdef MHD_USE_TRACE_POLLING_FDS 2829 fprintf (stderr, 2830 "### (Finished) kevent(%d, changes, %d, [NULL], " 2831 "0, [0, 0]) -> %d\n", 2832 d->events.data.kq.kq_fd, 2833 num_elemnts, 2834 res); 2835 # endif /* MHD_USE_TRACE_POLLING_FDS */ 2836 if (0 != res) 2837 { 2838 mhd_LOG_MSG (d, MHD_SC_EVENTS_REG_DAEMON_FDS_FAILURE, \ 2839 "Failed to add ITC or listening FD to the " 2840 "kqueue monitoring."); 2841 return MHD_SC_EVENTS_REG_DAEMON_FDS_FAILURE; 2842 } 2843 } 2844 } 2845 return MHD_SC_OK; 2846 break; 2847 #endif /* MHD_SUPPORT_KQUEUE */ 2848 #ifndef MHD_SUPPORT_SELECT 2849 case mhd_POLL_TYPE_SELECT: 2850 #endif /* ! MHD_SUPPORT_SELECT */ 2851 #ifndef MHD_SUPPORT_POLL 2852 case mhd_POLL_TYPE_POLL: 2853 #endif /* ! MHD_SUPPORT_POLL */ 2854 case mhd_POLL_TYPE_NOT_SET_YET: 2855 default: 2856 mhd_UNREACHABLE (); 2857 break; 2858 } 2859 mhd_UNREACHABLE (); 2860 return MHD_SC_INTERNAL_ERROR; 2861 } 2862 2863 2864 /** 2865 * The initial part of events de-initialisation: remove ITC and listening FD 2866 * from the monitored items (if supported by monitoring syscall). 2867 * @param d the daemon object 2868 */ 2869 static MHD_FN_PAR_NONNULL_ (1) void 2870 deinit_daemon_fds_monitoring (struct MHD_Daemon *restrict d) 2871 { 2872 mhd_assert (d->dbg.events_fully_inited); 2873 2874 switch (d->events.poll_type) 2875 { 2876 case mhd_POLL_TYPE_EXT: 2877 if (NULL != d->events.data.extr.listen_data.app_cntx) 2878 (void)mhd_daemon_extr_event_reg ( 2879 d, 2880 d->net.listen.fd, 2881 MHD_FD_STATE_NONE, 2882 d->events.data.extr.listen_data.app_cntx, 2883 (struct MHD_EventUpdateContext *)mhd_SOCKET_REL_MARKER_LISTEN); 2884 #ifdef MHD_SUPPORT_THREADS 2885 if (NULL != d->events.data.extr.itc_data.app_cntx) 2886 (void)mhd_daemon_extr_event_reg (d, 2887 mhd_itc_r_fd (d->threading.itc), 2888 MHD_FD_STATE_NONE, 2889 d->events.data.extr.itc_data.app_cntx, 2890 (struct MHD_EventUpdateContext *) 2891 mhd_SOCKET_REL_MARKER_ITC); 2892 #endif /* MHD_SUPPORT_THREADS */ 2893 return; 2894 #ifdef MHD_SUPPORT_SELECT 2895 case mhd_POLL_TYPE_SELECT: 2896 /* Nothing to do when using 'select()' */ 2897 return; 2898 break; 2899 #endif /* MHD_SUPPORT_SELECT */ 2900 #ifdef MHD_SUPPORT_POLL 2901 case mhd_POLL_TYPE_POLL: 2902 /* Nothing to do when using 'poll()' */ 2903 return; 2904 break; 2905 #endif /* MHD_SUPPORT_POLL */ 2906 #ifdef MHD_SUPPORT_EPOLL 2907 case mhd_POLL_TYPE_EPOLL: 2908 /* Nothing to do when using epoll. 2909 Monitoring stopped by closing epoll FD. */ 2910 return; 2911 break; 2912 #endif /* MHD_SUPPORT_EPOLL */ 2913 #ifdef MHD_SUPPORT_KQUEUE 2914 case mhd_POLL_TYPE_KQUEUE: 2915 /* Nothing to do when using kqueue. 2916 Monitoring stopped by closing kqueue FD. */ 2917 return; 2918 break; 2919 #endif /* MHD_SUPPORT_EPOLL */ 2920 #ifndef MHD_SUPPORT_SELECT 2921 case mhd_POLL_TYPE_SELECT: 2922 #endif /* ! MHD_SUPPORT_SELECT */ 2923 #ifndef MHD_SUPPORT_POLL 2924 case mhd_POLL_TYPE_POLL: 2925 #endif /* ! MHD_SUPPORT_POLL */ 2926 case mhd_POLL_TYPE_NOT_SET_YET: 2927 default: 2928 mhd_UNREACHABLE (); 2929 break; 2930 } 2931 mhd_UNREACHABLE (); 2932 } 2933 2934 2935 /** 2936 * Initialise daemon connections' data. 2937 * @param d the daemon object 2938 * @param s the user settings 2939 * @return #MHD_SC_OK on success, 2940 * the error code otherwise 2941 */ 2942 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 2943 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 2944 init_individual_conns (struct MHD_Daemon *restrict d, 2945 struct DaemonOptions *restrict s) 2946 { 2947 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 2948 mhd_assert (0 != d->conns.cfg.count_limit); 2949 2950 mhd_DLINKEDL_INIT_LIST (&(d->conns), all_conn); 2951 mhd_DLINKEDL_INIT_LIST (&(d->conns), def_timeout); 2952 mhd_DLINKEDL_INIT_LIST (&(d->conns), cust_timeout); 2953 d->conns.count = 0; 2954 d->conns.block_new = false; 2955 2956 d->conns.cfg.mem_pool_size = s->conn_memory_limit; 2957 if (0 == d->conns.cfg.mem_pool_size) 2958 d->conns.cfg.mem_pool_size = 32 * 1024; 2959 else if (256 > d->conns.cfg.mem_pool_size) 2960 d->conns.cfg.mem_pool_size = 256; 2961 2962 switch (s->conn_buff_zeroing) 2963 { 2964 case MHD_CONN_BUFFER_ZEROING_DISABLED: 2965 d->conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_NEVER; 2966 break; 2967 case MHD_CONN_BUFFER_ZEROING_BASIC: 2968 d->conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_ON_RESET; 2969 break; 2970 case MHD_CONN_BUFFER_ZEROING_HEAVY: 2971 default: 2972 d->conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_ALWAYS; 2973 break; 2974 } 2975 2976 #ifdef MHD_SUPPORT_UPGRADE 2977 mhd_DLINKEDL_INIT_LIST (&(d->conns.upgr), upgr_cleanup); 2978 if (!mhd_mutex_init (&(d->conns.upgr.ucu_lock))) 2979 { 2980 mhd_LOG_MSG (d, MHD_SC_MUTEX_INIT_FAILURE, \ 2981 "Failed to initialise mutex for the upgraded " \ 2982 "connection list."); 2983 return MHD_SC_MUTEX_INIT_FAILURE; 2984 } 2985 #endif /* MHD_SUPPORT_UPGRADE */ 2986 2987 #ifndef NDEBUG 2988 d->dbg.connections_inited = true; 2989 #endif 2990 return MHD_SC_OK; 2991 } 2992 2993 2994 /** 2995 * Deinitialise daemon connections' data. 2996 * @param d the daemon object 2997 */ 2998 static MHD_FN_PAR_NONNULL_ (1) void 2999 deinit_individual_conns (struct MHD_Daemon *restrict d) 3000 { 3001 #ifdef MHD_SUPPORT_UPGRADE 3002 mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->conns.upgr), upgr_cleanup)); 3003 mhd_assert (NULL == mhd_DLINKEDL_GET_LAST (&(d->conns.upgr), upgr_cleanup)); 3004 3005 mhd_mutex_destroy_chk (&(d->conns.upgr.ucu_lock)); 3006 #endif /* MHD_SUPPORT_UPGRADE */ 3007 3008 mhd_assert (0 != d->conns.cfg.mem_pool_size); 3009 mhd_assert (0 == d->conns.count); 3010 mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->conns), cust_timeout)); 3011 mhd_assert (NULL == mhd_DLINKEDL_GET_LAST (&(d->conns), cust_timeout)); 3012 mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->conns), def_timeout)); 3013 mhd_assert (NULL == mhd_DLINKEDL_GET_LAST (&(d->conns), def_timeout)); 3014 mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->conns), all_conn)); 3015 mhd_assert (NULL == mhd_DLINKEDL_GET_LAST (&(d->conns), all_conn)); 3016 } 3017 3018 3019 /** 3020 * Prepare daemon-local (worker daemon for thread pool mode) threading data 3021 * and finish events initialising. 3022 * To be used only with non-master daemons. 3023 * Do not start the thread even if configured for the internal threads. 3024 * @param d the daemon object 3025 * @return #MHD_SC_OK on success, 3026 * the error code otherwise 3027 */ 3028 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 3029 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3030 init_individual_thread_data_events_conns (struct MHD_Daemon *restrict d, 3031 struct DaemonOptions *restrict s) 3032 { 3033 enum MHD_StatusCode res; 3034 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 3035 mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); 3036 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3037 mhd_assert (!d->dbg.connections_inited); 3038 3039 res = init_events_fd (d); 3040 if (MHD_SC_OK != res) 3041 return res; 3042 3043 res = allocate_events (d); 3044 if (MHD_SC_OK == res) 3045 { 3046 res = init_itc (d); 3047 if (MHD_SC_OK == res) 3048 { 3049 res = init_daemon_fds_monitoring (d); 3050 3051 if (MHD_SC_OK == res) 3052 { 3053 #ifndef NDEBUG 3054 d->dbg.events_fully_inited = true; 3055 #endif 3056 #ifdef MHD_SUPPORT_THREADS 3057 mhd_thread_handle_ID_set_invalid (&(d->threading.tid)); 3058 d->threading.stop_requested = false; 3059 #endif /* MHD_SUPPORT_THREADS */ 3060 #ifndef NDEBUG 3061 d->dbg.threading_inited = true; 3062 #endif 3063 3064 res = init_individual_conns (d, s); 3065 if (MHD_SC_OK == res) 3066 return MHD_SC_OK; 3067 3068 /* Below is a clean-up path */ 3069 3070 deinit_daemon_fds_monitoring (d); 3071 } 3072 deinit_itc (d); 3073 } 3074 deallocate_events (d); 3075 } 3076 deinit_events_fd (d); 3077 3078 mhd_assert (MHD_SC_OK != res); 3079 return res; 3080 } 3081 3082 3083 /** 3084 * Deinit daemon-local (worker daemon for thread pool mode) threading data 3085 * and deallocate events. 3086 * To be used only with non-master daemons. 3087 * The internal thread (is any) must be stopped already. 3088 * @param d the daemon object 3089 */ 3090 static MHD_FN_PAR_NONNULL_ (1) void 3091 deinit_individual_thread_data_events_conns (struct MHD_Daemon *restrict d) 3092 { 3093 deinit_individual_conns (d); 3094 deinit_daemon_fds_monitoring (d); 3095 deinit_itc (d); 3096 deallocate_events (d); 3097 deinit_events_fd (d); 3098 mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->conns), all_conn)); 3099 mhd_assert (NULL == mhd_DLINKEDL_GET_FIRST (&(d->events), proc_ready)); 3100 #ifndef NDEBUG 3101 d->dbg.events_fully_inited = false; 3102 #endif 3103 } 3104 3105 3106 /** 3107 * Initialise the data specific only for the worker daemon. 3108 * @param d the daemon object 3109 * @return #MHD_SC_OK on success, 3110 * the error code otherwise 3111 */ 3112 static MHD_FN_PAR_NONNULL_ (1) 3113 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3114 init_worker_only_data (struct MHD_Daemon *restrict d) 3115 { 3116 enum MHD_StatusCode res; 3117 struct mhd_DaemonExtAddedConnectionsWorker *worker_only_data = 3118 &(d->events.act_req.ext_added.worker); 3119 3120 mhd_assert (!mhd_D_HAS_WORKERS (d)); 3121 mhd_assert (d->dbg.net_inited); 3122 mhd_assert (!d->dbg.worker_only_inited); 3123 mhd_assert (mhd_D_HAS_MASTER (d) || !d->dbg.master_only_inited); 3124 mhd_assert (!mhd_D_HAS_MASTER (d) || d->dbg.master_only_inited); /* Copied from master daemon */ 3125 3126 #ifndef NDEBUG 3127 /* "master"-only data will be overwritten here without de-initialising */ 3128 d->dbg.master_only_inited = false; 3129 #endif /* ! NDEBUG */ 3130 3131 mhd_DLINKEDL_INIT_LIST (worker_only_data, queue); 3132 3133 if (!mhd_mutex_init (&(worker_only_data->q_lock))) 3134 { 3135 mhd_LOG_MSG (d, MHD_SC_MUTEX_INIT_FAILURE, \ 3136 "Failed to initialise mutex for externally added " 3137 "connections"); 3138 res = MHD_SC_MUTEX_INIT_FAILURE; 3139 } 3140 else 3141 res = MHD_SC_OK; 3142 3143 #ifndef NDEBUG 3144 if (MHD_SC_OK == res) 3145 d->dbg.worker_only_inited = true; 3146 #endif /* ! NDEBUG */ 3147 3148 return res; 3149 } 3150 3151 3152 /** 3153 * De-initialise the data specific only for the worker daemon. 3154 * @param d the daemon object 3155 */ 3156 static MHD_FN_PAR_NONNULL_ (1) void 3157 deinit_worker_only_data (struct MHD_Daemon *restrict d) 3158 { 3159 struct mhd_DaemonExtAddedConnectionsWorker *worker_only_data = 3160 &(d->events.act_req.ext_added.worker); 3161 struct mhd_DaemonExtAddedConn *q_e; 3162 3163 mhd_assert (!mhd_D_HAS_WORKERS (d)); 3164 mhd_assert (d->dbg.net_inited); 3165 mhd_assert (d->dbg.worker_only_inited); 3166 mhd_assert (!d->dbg.master_only_inited); 3167 3168 /* Clean-up all unprocessed entries */ 3169 3170 for (q_e = mhd_DLINKEDL_GET_FIRST (worker_only_data, queue); 3171 NULL != q_e; 3172 q_e = mhd_DLINKEDL_GET_FIRST (worker_only_data, queue)) 3173 { 3174 mhd_ASSUME (NULL == mhd_DLINKEDL_GET_PREV (q_e, queue)); 3175 mhd_DLINKEDL_DEL (worker_only_data, q_e, queue); 3176 mhd_socket_close (q_e->skt); 3177 3178 if (NULL != q_e->addr) 3179 free (q_e->addr); 3180 3181 free (q_e); 3182 } 3183 3184 mhd_mutex_destroy_chk (&(worker_only_data->q_lock)); 3185 3186 #ifndef NDEBUG 3187 d->dbg.worker_only_inited = false; 3188 #endif /* ! NDEBUG */ 3189 } 3190 3191 3192 /** 3193 * Initialise worker daemon (the only daemon or member of the worker pool) 3194 * worker-specific daemon data, individual thread data and finish events 3195 * initialising. 3196 * To be used only with non-master daemons. 3197 * Do not start the thread even if configured for the internal threads. 3198 * @param d the daemon object 3199 * @return #MHD_SC_OK on success, 3200 * the error code otherwise 3201 */ 3202 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 3203 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3204 init_worker (struct MHD_Daemon *restrict d, 3205 struct DaemonOptions *restrict s) 3206 { 3207 enum MHD_StatusCode res; 3208 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3209 3210 res = init_worker_only_data (d); 3211 3212 if (MHD_SC_OK == res) 3213 { 3214 res = init_individual_thread_data_events_conns (d, 3215 s); 3216 3217 if (MHD_SC_OK == res) 3218 return MHD_SC_OK; 3219 3220 /* Below is a clean-up path */ 3221 3222 deinit_worker_only_data (d); 3223 } 3224 3225 mhd_assert (MHD_SC_OK != res); 3226 3227 return res; 3228 } 3229 3230 3231 /** 3232 * De-initialise worker daemon (the only daemon or member of the worker pool) 3233 * worker-specific daemon data, individual thread data and finish events 3234 * initialising. 3235 * To be used only with non-master daemons. 3236 * The internal thread (is any) must be stopped already. 3237 * @param d the daemon object 3238 */ 3239 static MHD_FN_PAR_NONNULL_ (1) void 3240 deinit_worker (struct MHD_Daemon *restrict d) 3241 { 3242 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3243 3244 deinit_individual_thread_data_events_conns (d); 3245 3246 deinit_worker_only_data (d); 3247 } 3248 3249 3250 /** 3251 * Set the maximum number of handled connections for the daemon. 3252 * Works only for global limit, does not work for the worker daemon. 3253 * @param d the daemon object 3254 * @param s the user settings 3255 * @return #MHD_SC_OK on success, 3256 * the error code otherwise 3257 */ 3258 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 3259 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3260 set_connections_total_limits (struct MHD_Daemon *restrict d, 3261 struct DaemonOptions *restrict s) 3262 { 3263 unsigned int limit_by_conf; 3264 unsigned int limit_by_num; 3265 unsigned int limit_by_select; 3266 unsigned int resulting_limit; 3267 bool error_by_fd_setsize; 3268 unsigned int num_worker_daemons; 3269 3270 mhd_assert (!mhd_D_HAS_MASTER (d)); 3271 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 3272 3273 num_worker_daemons = 1; 3274 #ifdef MHD_SUPPORT_THREADS 3275 if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == d->wmode_int) 3276 { 3277 mhd_assert (MHD_WM_WORKER_THREADS == s->work_mode.mode); 3278 if ((0 != s->global_connection_limit) 3279 && (0 != s->work_mode.params.num_worker_threads) 3280 && (s->global_connection_limit < 3281 s->work_mode.params.num_worker_threads)) 3282 { 3283 mhd_LOG_MSG ( \ 3284 d, MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL, \ 3285 "The limit specified by MHD_D_O_GLOBAL_CONNECTION_LIMIT is smaller " \ 3286 "then the number of worker threads."); 3287 return MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL; 3288 } 3289 } 3290 if (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)) 3291 num_worker_daemons = s->work_mode.params.num_worker_threads; 3292 #endif /* MHD_SUPPORT_THREADS */ 3293 3294 limit_by_conf = s->global_connection_limit; 3295 limit_by_num = UINT_MAX; 3296 limit_by_select = UINT_MAX; 3297 mhd_assert (UINT_MAX == limit_by_num); /* Mute analyser warning */ 3298 3299 error_by_fd_setsize = false; 3300 #ifdef MHD_SOCKETS_KIND_POSIX 3301 if (1) 3302 { 3303 limit_by_num = (unsigned int)d->net.cfg.max_fd_num; 3304 if (0 != limit_by_num) 3305 { 3306 /* Find the upper limit. 3307 The real limit is lower, as any other process FDs will use the slots 3308 in the allowed numbers range */ 3309 limit_by_num -= 3; /* The numbers zero, one and two are used typically */ 3310 # ifdef MHD_SUPPORT_THREADS 3311 limit_by_num -= mhd_ITC_NUM_FDS * num_worker_daemons; 3312 # endif /* MHD_SUPPORT_THREADS */ 3313 if (MHD_INVALID_SOCKET != d->net.listen.fd) 3314 --limit_by_num; /* One FD is used for the listening socket */ 3315 if ((num_worker_daemons > limit_by_num) 3316 || (limit_by_num > 3317 (unsigned int)d->net.cfg.max_fd_num) /* Underflow */) 3318 { 3319 if (d->net.cfg.max_fd_num == s->fd_number_limit) 3320 { 3321 mhd_LOG_MSG ( \ 3322 d, MHD_SC_MAX_FD_NUMBER_LIMIT_TOO_STRICT, \ 3323 "The limit specified by MHD_D_O_FD_NUMBER_LIMIT is too strict " \ 3324 "for this daemon settings."); 3325 return MHD_SC_MAX_FD_NUMBER_LIMIT_TOO_STRICT; 3326 } 3327 else 3328 { 3329 mhd_assert (mhd_POLL_TYPE_SELECT == d->events.poll_type); 3330 error_by_fd_setsize = true; 3331 } 3332 } 3333 } 3334 else 3335 limit_by_num = (unsigned int)INT_MAX; 3336 } 3337 #elif defined(MHD_SOCKETS_KIND_WINSOCK) 3338 if (1) 3339 { 3340 # ifdef MHD_SUPPORT_SELECT 3341 if ((mhd_DAEMON_TYPE_SINGLE == d->threading.d_type) 3342 && (mhd_POLL_TYPE_SELECT == d->events.poll_type)) 3343 { 3344 /* W32 limits the total number (count) of sockets used for select() */ 3345 unsigned int limit_per_worker; 3346 3347 limit_per_worker = FD_SETSIZE; 3348 if (MHD_INVALID_SOCKET != d->net.listen.fd) 3349 --limit_per_worker; /* The slot for the listening socket */ 3350 # ifdef MHD_SUPPORT_THREADS 3351 --limit_per_worker; /* The slot for the ITC */ 3352 # endif /* MHD_SUPPORT_THREADS */ 3353 if ((0 == limit_per_worker) || (limit_per_worker > FD_SETSIZE)) 3354 error_by_fd_setsize = true; 3355 else 3356 { 3357 limit_by_select = limit_per_worker * num_worker_daemons; 3358 if (limit_by_select / limit_per_worker != num_worker_daemons) 3359 limit_by_select = UINT_MAX; 3360 } 3361 } 3362 # endif /* MHD_SUPPORT_SELECT */ 3363 (void)0; /* Mute compiler warning */ 3364 } 3365 #endif /* MHD_SOCKETS_KIND_POSIX */ 3366 if (error_by_fd_setsize) 3367 { 3368 mhd_LOG_MSG ( \ 3369 d, MHD_SC_SYS_FD_SETSIZE_TOO_STRICT, \ 3370 "The FD_SETSIZE is too strict to run daemon with the polling " \ 3371 "by select() and with the specified number of workers."); 3372 return MHD_SC_SYS_FD_SETSIZE_TOO_STRICT; 3373 } 3374 3375 if (0 != limit_by_conf) 3376 { 3377 /* The number has bet set explicitly */ 3378 resulting_limit = limit_by_conf; 3379 } 3380 else 3381 { 3382 /* No user configuration provided */ 3383 unsigned int suggested_limit; 3384 #ifndef MHD_SOCKETS_KIND_WINSOCK 3385 # define TYPICAL_NOFILES_LIMIT (1024) /* The usual limit for the number of open FDs */ 3386 suggested_limit = TYPICAL_NOFILES_LIMIT; 3387 suggested_limit -= 3; /* The numbers zero, one and two are used typically */ 3388 # ifdef MHD_SUPPORT_THREADS 3389 suggested_limit -= mhd_ITC_NUM_FDS * num_worker_daemons; 3390 # endif /* MHD_SUPPORT_THREADS */ 3391 if (MHD_INVALID_SOCKET != d->net.listen.fd) 3392 --suggested_limit; /* One FD is used for the listening socket */ 3393 if (suggested_limit > TYPICAL_NOFILES_LIMIT) 3394 suggested_limit = 0; /* Overflow */ 3395 #else /* MHD_SOCKETS_KIND_WINSOCK */ 3396 # ifdef _WIN64 3397 suggested_limit = 2048; 3398 # else 3399 suggested_limit = 1024; 3400 # endif 3401 #endif /* MHD_SOCKETS_KIND_WINSOCK */ 3402 if (suggested_limit < num_worker_daemons) 3403 { 3404 /* Use at least one connection for every worker daemon and 3405 let the system to restrict the new connections if they are above 3406 the system limits. */ 3407 suggested_limit = num_worker_daemons; 3408 } 3409 resulting_limit = suggested_limit; 3410 } 3411 if (resulting_limit > limit_by_num) 3412 resulting_limit = limit_by_num; 3413 3414 if (resulting_limit > limit_by_select) 3415 resulting_limit = limit_by_select; 3416 3417 mhd_assert (resulting_limit >= num_worker_daemons); 3418 d->conns.cfg.count_limit = resulting_limit; 3419 if (d->conns.cfg.per_ip_limit <= d->conns.cfg.count_limit) 3420 d->conns.cfg.per_ip_limit = 0; /* Already enforced by global limit */ 3421 3422 return MHD_SC_OK; 3423 } 3424 3425 3426 /** 3427 * Set correct daemon threading type. 3428 * Set the number of workers for thread pool type. 3429 * @param d the daemon object 3430 * @return #MHD_SC_OK on success, 3431 * the error code otherwise 3432 */ 3433 MHD_FN_PAR_NONNULL_ (1) \ 3434 MHD_FN_MUST_CHECK_RESULT_ static inline enum MHD_StatusCode 3435 set_d_threading_type (struct MHD_Daemon *restrict d) 3436 { 3437 switch (d->wmode_int) 3438 { 3439 case mhd_WM_INT_EXTERNAL_EVENTS_EDGE: 3440 case mhd_WM_INT_EXTERNAL_EVENTS_LEVEL: 3441 mhd_assert (!mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3442 mhd_assert (mhd_POLL_TYPE_EXT == d->events.poll_type); 3443 mhd_assert (NULL != d->events.data.extr.cb_data.cb); 3444 #ifdef MHD_SUPPORT_THREADS 3445 d->threading.d_type = mhd_DAEMON_TYPE_SINGLE; 3446 #endif /* MHD_SUPPORT_THREADS */ 3447 return MHD_SC_OK; 3448 case mhd_WM_INT_INTERNAL_EVENTS_NO_THREADS: 3449 mhd_assert (!mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3450 mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); 3451 #ifdef MHD_SUPPORT_THREADS 3452 d->threading.d_type = mhd_DAEMON_TYPE_SINGLE; 3453 #endif /* MHD_SUPPORT_THREADS */ 3454 return MHD_SC_OK; 3455 #ifdef MHD_SUPPORT_THREADS 3456 case mhd_WM_INT_INTERNAL_EVENTS_ONE_THREAD: 3457 mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3458 mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); 3459 d->threading.d_type = mhd_DAEMON_TYPE_SINGLE; 3460 return MHD_SC_OK; 3461 case mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION: 3462 mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3463 mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); 3464 mhd_assert (!mhd_POLL_TYPE_INT_IS_EPOLL (d->events.poll_type)); 3465 mhd_assert (!mhd_POLL_TYPE_INT_IS_KQUEUE (d->events.poll_type)); 3466 d->threading.d_type = mhd_DAEMON_TYPE_LISTEN_ONLY; 3467 return MHD_SC_OK; 3468 case mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL: 3469 mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3470 mhd_assert (mhd_POLL_TYPE_EXT != d->events.poll_type); 3471 d->threading.d_type = mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY; 3472 return MHD_SC_OK; 3473 #endif /* MHD_SUPPORT_THREADS */ 3474 default: 3475 break; 3476 } 3477 mhd_UNREACHABLE (); 3478 return MHD_SC_INTERNAL_ERROR; 3479 } 3480 3481 3482 #ifdef MHD_SUPPORT_THREADS 3483 3484 /** 3485 * De-initialise workers pool, including workers daemons. 3486 * The threads must be not running. 3487 * @param d the daemon object 3488 * @param num_workers the number of workers to deinit 3489 */ 3490 static MHD_FN_PAR_NONNULL_ (1) void 3491 deinit_workers_pool (struct MHD_Daemon *restrict d, 3492 unsigned int num_workers) 3493 { 3494 unsigned int i; 3495 mhd_assert (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3496 mhd_assert (NULL != d->threading.hier.pool.workers); 3497 mhd_assert ((2 <= d->threading.hier.pool.num) \ 3498 || (mhd_DAEMON_STATE_STARTING == d->state)); 3499 mhd_assert ((num_workers == d->threading.hier.pool.num) \ 3500 || (mhd_DAEMON_STATE_STARTING == d->state)); 3501 mhd_assert ((mhd_DAEMON_STATE_STOPPING == d->state) \ 3502 || (mhd_DAEMON_STATE_STARTING == d->state)); 3503 3504 /* Deinitialise in reverse order */ 3505 for (i = num_workers - 1; num_workers > i; --i) 3506 { /* Note: loop exits after underflow of 'i' */ 3507 struct MHD_Daemon *const worker = d->threading.hier.pool.workers + i; 3508 deinit_worker (worker); 3509 } 3510 free (d->threading.hier.pool.workers); 3511 # ifndef NDEBUG 3512 d->dbg.thread_pool_inited = false; 3513 # endif 3514 } 3515 3516 3517 /** 3518 * Nullify worker daemon member that copied from master daemon but must not 3519 * be used in worker 3520 * @param d the daemon object 3521 */ 3522 static MHD_FN_PAR_NONNULL_ (1) void 3523 reset_master_only_areas (struct MHD_Daemon *restrict d) 3524 { 3525 # ifdef MHD_SUPPORT_EPOLL 3526 /* In release builds this is done mostly for safety as @a early_fd is used 3527 in workers only for asserts */ 3528 if (mhd_POLL_TYPE_EPOLL == d->events.poll_type) 3529 d->events.data.epoll.early_fd = MHD_INVALID_SOCKET; 3530 # endif /* MHD_SUPPORT_EPOLL */ 3531 3532 # ifdef MHD_SUPPORT_AUTH_DIGEST 3533 memset (&(d->auth_dg.nonces_lock), 3534 0x7F, 3535 sizeof(d->auth_dg.nonces_lock)); 3536 # endif 3537 /* Not needed. It is initialised later */ 3538 /* memset (&(d->req_cfg.large_buf), 0, sizeof(d->req_cfg.large_buf)); */ 3539 (void)d; 3540 } 3541 3542 3543 /** 3544 * Initialise workers pool, including workers daemons. 3545 * Do not start the threads. 3546 * @param d the daemon object 3547 * @param s the user settings 3548 * @return #MHD_SC_OK on success, 3549 * the error code otherwise 3550 */ 3551 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 3552 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3553 init_workers_pool (struct MHD_Daemon *restrict d, 3554 struct DaemonOptions *restrict s) 3555 { 3556 enum MHD_StatusCode res; 3557 size_t workers_pool_size; 3558 unsigned int conn_per_daemon; 3559 unsigned int num_workers; 3560 unsigned int conn_remainder; 3561 unsigned int i; 3562 3563 mhd_assert (d->dbg.net_inited); 3564 mhd_assert (!d->dbg.net_deinited); 3565 mhd_assert (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == d->wmode_int); 3566 mhd_assert (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3567 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET < d->events.poll_type); 3568 mhd_assert (1 < s->work_mode.params.num_worker_threads); 3569 mhd_assert (0 != d->conns.cfg.count_limit); 3570 mhd_assert (s->work_mode.params.num_worker_threads <= \ 3571 d->conns.cfg.count_limit); 3572 mhd_assert (!d->dbg.thread_pool_inited); 3573 3574 num_workers = s->work_mode.params.num_worker_threads; 3575 workers_pool_size = 3576 (sizeof(struct MHD_Daemon) * num_workers); 3577 if (workers_pool_size / num_workers != sizeof(struct MHD_Daemon)) 3578 { /* Overflow */ 3579 mhd_LOG_MSG ( \ 3580 d, MHD_SC_THREAD_POOL_MEM_ALLOC_FAILURE, \ 3581 "The size of the thread pool is too large."); 3582 return MHD_SC_THREAD_POOL_MEM_ALLOC_FAILURE; 3583 } 3584 3585 # ifndef NDEBUG 3586 mhd_itc_set_invalid (&(d->threading.itc)); 3587 mhd_thread_handle_ID_set_invalid (&(d->threading.tid)); 3588 # endif 3589 3590 d->threading.hier.pool.workers = (struct MHD_Daemon *) 3591 malloc (workers_pool_size); 3592 if (NULL == d->threading.hier.pool.workers) 3593 { 3594 mhd_LOG_MSG ( \ 3595 d, MHD_SC_THREAD_POOL_MEM_ALLOC_FAILURE, \ 3596 "Failed to allocate memory for the thread pool."); 3597 return MHD_SC_THREAD_POOL_MEM_ALLOC_FAILURE; 3598 } 3599 3600 conn_per_daemon = d->conns.cfg.count_limit / num_workers; 3601 conn_remainder = d->conns.cfg.count_limit % num_workers; 3602 res = MHD_SC_OK; 3603 for (i = 0; num_workers > i; ++i) 3604 { 3605 struct MHD_Daemon *restrict const worker = 3606 d->threading.hier.pool.workers + i; 3607 memcpy (worker, d, sizeof(struct MHD_Daemon)); 3608 reset_master_only_areas (worker); 3609 3610 worker->threading.d_type = mhd_DAEMON_TYPE_WORKER; 3611 worker->threading.hier.master = d; 3612 worker->conns.cfg.count_limit = conn_per_daemon; 3613 if (conn_remainder > i) 3614 worker->conns.cfg.count_limit++; /* Distribute the reminder */ 3615 # ifdef MHD_SUPPORT_EPOLL 3616 mhd_assert ((mhd_POLL_TYPE_EPOLL != worker->events.poll_type) 3617 || (0 != i) 3618 || (0 < d->events.data.epoll.early_fd)); 3619 mhd_assert ((mhd_POLL_TYPE_EPOLL != worker->events.poll_type) 3620 || (0 == i) 3621 || (MHD_INVALID_SOCKET == d->events.data.epoll.early_fd)); 3622 # endif /* MHD_SUPPORT_EPOLL */ 3623 res = init_worker (worker, 3624 s); 3625 if (MHD_SC_OK != res) 3626 break; 3627 } 3628 if (num_workers == i) 3629 { 3630 mhd_assert (MHD_SC_OK == res); 3631 # ifndef NDEBUG 3632 d->dbg.thread_pool_inited = true; 3633 d->dbg.threading_inited = true; 3634 # endif 3635 d->threading.hier.pool.num = num_workers; 3636 return MHD_SC_OK; 3637 } 3638 3639 /* Below is a clean-up */ 3640 3641 mhd_assert (MHD_SC_OK != res); 3642 deinit_workers_pool (d, i); 3643 return res; 3644 } 3645 3646 3647 /** 3648 * Initialise data specific only for the master daemon. 3649 * @param d the daemon object 3650 * @return #MHD_SC_OK on success, 3651 * the error code otherwise 3652 */ 3653 static MHD_FN_PAR_NONNULL_ (1) 3654 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3655 init_master_only_data (struct MHD_Daemon *restrict d) 3656 { 3657 enum MHD_StatusCode res; 3658 3659 mhd_assert (mhd_D_HAS_WORKERS (d)); 3660 mhd_assert (d->dbg.net_inited); 3661 mhd_assert (!d->dbg.master_only_inited); 3662 mhd_assert (!d->dbg.worker_only_inited); 3663 3664 if (!mhd_atomic_counter_init ( \ 3665 &(d->events.act_req.ext_added.master.next_d_idx), 3666 0)) 3667 { 3668 mhd_LOG_MSG (d, MHD_SC_MUTEX_INIT_FAILURE, \ 3669 "Failed to initialise atomic counter for externally added " 3670 "connections"); 3671 res = MHD_SC_MUTEX_INIT_FAILURE; 3672 } 3673 else 3674 res = MHD_SC_OK; 3675 3676 # ifndef NDEBUG 3677 if (MHD_SC_OK == res) 3678 d->dbg.master_only_inited = true; 3679 # endif /* ! NDEBUG */ 3680 3681 return res; 3682 } 3683 3684 3685 /** 3686 * De-initialise data specific only for the master daemon. 3687 * @param d the daemon object 3688 */ 3689 static MHD_FN_PAR_NONNULL_ (1) void 3690 deinit_master_only_data (struct MHD_Daemon *restrict d) 3691 { 3692 mhd_assert (mhd_D_HAS_WORKERS (d)); 3693 mhd_assert (d->dbg.master_only_inited); 3694 mhd_assert (!d->dbg.worker_only_inited); 3695 3696 mhd_atomic_counter_deinit (&(d->events.act_req.ext_added.master.next_d_idx)); 3697 3698 # ifndef NDEBUG 3699 d->dbg.master_only_inited = false; 3700 # endif /* ! NDEBUG */ 3701 } 3702 3703 3704 /** 3705 * Initialise individual events, connection data for the "master" daemon, 3706 * including master-only data, the workers pool, and the workers daemons, 3707 * including individual worker-specific threading and other data. 3708 * Do not start the threads. 3709 * @param d the daemon object 3710 * @param s the user settings 3711 * @return #MHD_SC_OK on success, 3712 * the error code otherwise 3713 */ 3714 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 3715 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3716 init_master (struct MHD_Daemon *restrict d, 3717 struct DaemonOptions *restrict s) 3718 { 3719 enum MHD_StatusCode res; 3720 mhd_assert (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3721 3722 res = init_master_only_data (d); 3723 if (MHD_SC_OK != res) 3724 return res; 3725 3726 res = init_workers_pool (d, 3727 s); 3728 if (MHD_SC_OK == res) 3729 { 3730 /* Copy some settings to the master daemon */ 3731 d->conns.cfg.mem_pool_size = 3732 d->threading.hier.pool.workers[0].conns.cfg.mem_pool_size; 3733 3734 return res; 3735 } 3736 3737 /* Below is a clean-up path */ 3738 3739 deinit_master_only_data (d); 3740 3741 mhd_assert (MHD_SC_OK != res); 3742 return res; 3743 } 3744 3745 3746 /** 3747 * De-initialise individual events, connection data for the "master" daemon, 3748 * including master-only data, the workers pool, and the workers daemons, 3749 * including individual worker-specific threading and other data. 3750 * The threads must be not running. 3751 * @param d the daemon object 3752 */ 3753 static MHD_FN_PAR_NONNULL_ (1) void 3754 deinit_master (struct MHD_Daemon *restrict d) 3755 { 3756 deinit_workers_pool (d, 3757 d->threading.hier.pool.num); 3758 3759 deinit_master_only_data (d); 3760 } 3761 3762 3763 #endif /* MHD_SUPPORT_THREADS */ 3764 3765 /** 3766 * Initialise threading and inter-thread communications. 3767 * Also finish initialisation of events processing and initialise daemon's 3768 * connection data. 3769 * Do not start the thread even if configured for the internal threads. 3770 * @param d the daemon object 3771 * @param s the user settings 3772 * @return #MHD_SC_OK on success, 3773 * the error code otherwise 3774 */ 3775 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 3776 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3777 daemon_init_threading_and_conn (struct MHD_Daemon *restrict d, 3778 struct DaemonOptions *restrict s) 3779 { 3780 enum MHD_StatusCode res; 3781 3782 mhd_assert (d->dbg.net_inited); 3783 mhd_assert (!d->dbg.net_deinited); 3784 mhd_assert (mhd_POLL_TYPE_NOT_SET_YET != d->events.poll_type); 3785 3786 res = set_d_threading_type (d); 3787 if (MHD_SC_OK != res) 3788 return res; 3789 3790 res = set_connections_total_limits (d, s); 3791 if (MHD_SC_OK != res) 3792 return res; 3793 3794 #ifdef MHD_SUPPORT_THREADS 3795 d->threading.cfg.stack_size = s->stack_size; 3796 #endif /* MHD_SUPPORT_THREADS */ 3797 3798 if (!mhd_D_HAS_WORKERS (d)) 3799 res = init_worker (d, 3800 s); 3801 #ifdef MHD_SUPPORT_THREADS 3802 else 3803 res = init_master (d, 3804 s); 3805 #endif /* MHD_SUPPORT_THREADS */ 3806 3807 if (MHD_SC_OK == res) 3808 { 3809 mhd_assert (d->dbg.events_allocated \ 3810 || mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3811 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type) \ 3812 || !d->dbg.events_allocated); 3813 mhd_assert (!d->dbg.thread_pool_inited \ 3814 || mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3815 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type) \ 3816 || d->dbg.thread_pool_inited); 3817 mhd_assert (!mhd_D_TYPE_IS_INTERNAL_ONLY (d->threading.d_type)); 3818 mhd_assert (!d->dbg.events_allocated || d->dbg.connections_inited); 3819 mhd_assert (!d->dbg.connections_inited || d->dbg.events_allocated); 3820 } 3821 return res; 3822 } 3823 3824 3825 /** 3826 * De-initialise threading and inter-thread communications. 3827 * Also deallocate events and de-initialise daemon's connection data. 3828 * No daemon-manged threads should be running. 3829 * @param d the daemon object 3830 */ 3831 static MHD_FN_PAR_NONNULL_ (1) void 3832 daemon_deinit_threading_and_conn (struct MHD_Daemon *restrict d) 3833 { 3834 mhd_assert (d->dbg.net_inited); 3835 mhd_assert (!d->dbg.net_deinited); 3836 mhd_assert (d->dbg.threading_inited); 3837 mhd_assert (!mhd_D_TYPE_IS_INTERNAL_ONLY (d->threading.d_type)); 3838 if (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)) 3839 { 3840 mhd_assert (!mhd_WM_INT_IS_THREAD_POOL (d->wmode_int)); 3841 mhd_assert (d->dbg.connections_inited); 3842 mhd_assert (d->dbg.events_allocated); 3843 mhd_assert (!d->dbg.thread_pool_inited); 3844 deinit_worker (d); 3845 } 3846 else 3847 { 3848 #ifdef MHD_SUPPORT_THREADS 3849 mhd_assert (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == d->wmode_int); 3850 mhd_assert (!d->dbg.connections_inited); 3851 mhd_assert (!d->dbg.events_allocated); 3852 mhd_assert (d->dbg.thread_pool_inited); 3853 deinit_master (d); 3854 #else /* ! MHD_SUPPORT_THREADS */ 3855 mhd_assert (0 && "Impossible value"); 3856 mhd_UNREACHABLE (); 3857 (void)0; 3858 #endif /* ! MHD_SUPPORT_THREADS */ 3859 } 3860 } 3861 3862 3863 #ifdef MHD_SUPPORT_THREADS 3864 3865 /** 3866 * Start the daemon individual single thread. 3867 * Works both for single thread daemons and for worker daemon for thread 3868 * pool mode. 3869 * Must be called only for daemons with internal threads. 3870 * @param d the daemon object, must be completely initialised 3871 * @return #MHD_SC_OK on success, 3872 * the error code otherwise 3873 */ 3874 static MHD_FN_PAR_NONNULL_ (1) 3875 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 3876 start_individual_daemon_thread (struct MHD_Daemon *restrict d) 3877 { 3878 mhd_assert (d->dbg.threading_inited); 3879 mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3880 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 3881 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3882 mhd_assert (!mhd_thread_handle_ID_is_valid_handle (d->threading.tid)); 3883 3884 if (mhd_DAEMON_TYPE_SINGLE == d->threading.d_type) 3885 { 3886 if (!mhd_create_named_thread ( \ 3887 &(d->threading.tid), "MHD-single", \ 3888 d->threading.cfg.stack_size, \ 3889 &mhd_worker_all_events, \ 3890 (void *)d)) 3891 { 3892 mhd_LOG_MSG (d, MHD_SC_THREAD_MAIN_LAUNCH_FAILURE, \ 3893 "Failed to start daemon main thread."); 3894 return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE; 3895 } 3896 } 3897 else if (mhd_DAEMON_TYPE_WORKER == d->threading.d_type) 3898 { 3899 if (!mhd_create_named_thread ( \ 3900 &(d->threading.tid), "MHD-worker", \ 3901 d->threading.cfg.stack_size, \ 3902 &mhd_worker_all_events, \ 3903 (void *)d)) 3904 { 3905 mhd_LOG_MSG (d, MHD_SC_THREAD_WORKER_LAUNCH_FAILURE, \ 3906 "Failed to start daemon worker thread."); 3907 return MHD_SC_THREAD_WORKER_LAUNCH_FAILURE; 3908 } 3909 } 3910 else if (mhd_DAEMON_TYPE_LISTEN_ONLY == d->threading.d_type) 3911 { 3912 if (!mhd_create_named_thread ( \ 3913 &(d->threading.tid), "MHD-listen", \ 3914 d->threading.cfg.stack_size, \ 3915 &mhd_worker_listening_only, \ 3916 (void *)d)) 3917 { 3918 mhd_LOG_MSG (d, MHD_SC_THREAD_LISTENING_LAUNCH_FAILURE, \ 3919 "Failed to start daemon listening thread."); 3920 return MHD_SC_THREAD_LISTENING_LAUNCH_FAILURE; 3921 } 3922 } 3923 else 3924 { 3925 mhd_assert (0 && "Impossible value"); 3926 mhd_UNREACHABLE (); 3927 return MHD_SC_INTERNAL_ERROR; 3928 } 3929 mhd_assert (mhd_thread_handle_ID_is_valid_handle (d->threading.tid)); 3930 return MHD_SC_OK; 3931 } 3932 3933 3934 /** 3935 * Stop the daemon individual single thread. 3936 * Works both for single thread daemons and for worker daemon for thread 3937 * pool mode. 3938 * Must be called only for daemons with internal threads. 3939 * @param d the daemon object, must be completely initialised 3940 */ 3941 MHD_FN_PAR_NONNULL_ (1) static void 3942 stop_individual_daemon_thread (struct MHD_Daemon *restrict d) 3943 { 3944 mhd_assert (d->dbg.threading_inited); 3945 mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); 3946 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 3947 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3948 mhd_assert ((mhd_DAEMON_STATE_STOPPING == d->state) \ 3949 || (mhd_DAEMON_STATE_STARTING == d->state)); 3950 mhd_assert (mhd_thread_handle_ID_is_valid_handle (d->threading.tid)); 3951 3952 d->threading.stop_requested = true; 3953 3954 mhd_daemon_trigger_itc (d); 3955 if (!mhd_thread_handle_ID_join_thread (d->threading.tid)) 3956 { 3957 mhd_LOG_MSG (d, MHD_SC_DAEMON_THREAD_STOP_ERROR, \ 3958 "Failed to stop daemon main thread."); 3959 } 3960 } 3961 3962 3963 /** 3964 * Stop all worker threads in the thread pool. 3965 * Must be called only for master daemons with thread pool. 3966 * @param d the daemon object, the workers threads must be running 3967 * @param num_workers the number of threads to stop 3968 */ 3969 static MHD_FN_PAR_NONNULL_ (1) void 3970 stop_worker_pool_threads (struct MHD_Daemon *restrict d, 3971 unsigned int num_workers) 3972 { 3973 unsigned int i; 3974 mhd_assert (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 3975 mhd_assert (NULL != d->threading.hier.pool.workers); 3976 mhd_assert (0 != d->threading.hier.pool.num); 3977 mhd_assert (d->dbg.thread_pool_inited); 3978 mhd_assert (2 <= d->threading.hier.pool.num); 3979 mhd_assert ((num_workers == d->threading.hier.pool.num) \ 3980 || (mhd_DAEMON_STATE_STARTING == d->state)); 3981 mhd_assert ((mhd_DAEMON_STATE_STOPPING == d->state) \ 3982 || (mhd_DAEMON_STATE_STARTING == d->state)); 3983 3984 /* Process all the threads in the reverse order */ 3985 3986 /* Trigger all threads */ 3987 for (i = num_workers - 1; num_workers > i; --i) 3988 { /* Note: loop exits after underflow of 'i' */ 3989 d->threading.hier.pool.workers[i].threading.stop_requested = true; 3990 mhd_assert (mhd_ITC_IS_VALID ( \ 3991 d->threading.hier.pool.workers[i].threading.itc)); 3992 mhd_daemon_trigger_itc (d->threading.hier.pool.workers + i); 3993 } 3994 3995 /* Collect all threads */ 3996 for (i = num_workers - 1; num_workers > i; --i) 3997 { /* Note: loop exits after underflow of 'i' */ 3998 struct MHD_Daemon *const restrict worker = 3999 d->threading.hier.pool.workers + i; 4000 mhd_assert (mhd_thread_handle_ID_is_valid_handle (worker->threading.tid)); 4001 if (!mhd_thread_handle_ID_join_thread (worker->threading.tid)) 4002 { 4003 mhd_LOG_MSG (d, MHD_SC_DAEMON_THREAD_STOP_ERROR, \ 4004 "Failed to stop a worker thread."); 4005 } 4006 } 4007 } 4008 4009 4010 /** 4011 * Start the workers pool threads. 4012 * Must be called only for master daemons with thread pool. 4013 * @param d the daemon object, must be completely initialised 4014 * @return #MHD_SC_OK on success, 4015 * the error code otherwise 4016 */ 4017 static MHD_FN_PAR_NONNULL_ (1) 4018 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 4019 start_worker_pool_threads (struct MHD_Daemon *restrict d) 4020 { 4021 enum MHD_StatusCode res; 4022 unsigned int i; 4023 4024 mhd_assert (d->dbg.threading_inited); 4025 mhd_assert (mhd_WM_INT_HAS_THREADS (d->wmode_int)); 4026 mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); 4027 mhd_assert (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 4028 mhd_assert (d->dbg.thread_pool_inited); 4029 mhd_assert (2 <= d->threading.hier.pool.num); 4030 4031 res = MHD_SC_OK; 4032 4033 for (i = 0; d->threading.hier.pool.num > i; ++i) 4034 { 4035 res = start_individual_daemon_thread (d->threading.hier.pool.workers + i); 4036 if (MHD_SC_OK != res) 4037 break; 4038 } 4039 if (d->threading.hier.pool.num == i) 4040 { 4041 mhd_assert (MHD_SC_OK == res); 4042 return MHD_SC_OK; 4043 } 4044 4045 stop_worker_pool_threads (d, i); 4046 mhd_assert (MHD_SC_OK != res); 4047 return res; 4048 } 4049 4050 4051 #endif /* MHD_SUPPORT_THREADS */ 4052 4053 /** 4054 * Start the daemon internal threads, if the daemon configured to use them. 4055 * @param d the daemon object, must be completely initialised 4056 * @return #MHD_SC_OK on success, 4057 * the error code otherwise 4058 */ 4059 static MHD_FN_PAR_NONNULL_ (1) 4060 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 4061 daemon_start_threads (struct MHD_Daemon *restrict d) 4062 { 4063 mhd_assert (d->dbg.net_inited); 4064 mhd_assert (!d->dbg.net_deinited); 4065 mhd_assert (d->dbg.threading_inited); 4066 mhd_assert (!mhd_D_TYPE_IS_INTERNAL_ONLY (d->threading.d_type)); 4067 if (mhd_WM_INT_HAS_THREADS (d->wmode_int)) 4068 { 4069 #ifdef MHD_SUPPORT_THREADS 4070 if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL != d->wmode_int) 4071 { 4072 mhd_assert (d->dbg.threading_inited); 4073 mhd_assert (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY != d->threading.d_type); 4074 return start_individual_daemon_thread (d); 4075 } 4076 else 4077 { 4078 mhd_assert (d->dbg.thread_pool_inited); 4079 mhd_assert (mhd_DAEMON_TYPE_MASTER_CONTROL_ONLY == d->threading.d_type); 4080 return start_worker_pool_threads (d); 4081 } 4082 #else /* ! MHD_SUPPORT_THREADS */ 4083 mhd_assert (0 && "Impossible value"); 4084 mhd_UNREACHABLE (); 4085 return MHD_SC_INTERNAL_ERROR; 4086 #endif /* ! MHD_SUPPORT_THREADS */ 4087 } 4088 return MHD_SC_OK; 4089 } 4090 4091 4092 /** 4093 * Stop the daemon internal threads, if the daemon configured to use them. 4094 * @param d the daemon object to stop threads 4095 */ 4096 static MHD_FN_PAR_NONNULL_ (1) void 4097 daemon_stop_threads (struct MHD_Daemon *restrict d) 4098 { 4099 mhd_assert (d->dbg.net_inited); 4100 mhd_assert (!d->dbg.net_deinited); 4101 mhd_assert (d->dbg.threading_inited); 4102 if (mhd_WM_INT_HAS_THREADS (d->wmode_int)) 4103 { 4104 #ifdef MHD_SUPPORT_THREADS 4105 if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL != d->wmode_int) 4106 { 4107 mhd_assert (d->dbg.threading_inited); 4108 mhd_assert (!mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 4109 stop_individual_daemon_thread (d); 4110 return; 4111 } 4112 else 4113 { 4114 mhd_assert (d->dbg.thread_pool_inited); 4115 mhd_assert (mhd_D_TYPE_HAS_WORKERS (d->threading.d_type)); 4116 stop_worker_pool_threads (d, d->threading.hier.pool.num); 4117 return; 4118 } 4119 #else /* ! MHD_SUPPORT_THREADS */ 4120 mhd_UNREACHABLE (); 4121 return; 4122 #endif /* ! MHD_SUPPORT_THREADS */ 4123 } 4124 } 4125 4126 4127 /** 4128 * Close all daemon connections for modes without internal threads 4129 * @param d the daemon object 4130 */ 4131 static MHD_FN_PAR_NONNULL_ (1) void 4132 daemon_close_connections (struct MHD_Daemon *restrict d) 4133 { 4134 if (mhd_WM_INT_HAS_THREADS (d->wmode_int)) 4135 { 4136 /* In these modes connections must be closed in the daemon thread */ 4137 mhd_assert (NULL == mhd_DLINKEDL_GET_LAST (&(d->conns), all_conn)); 4138 return; 4139 } 4140 4141 mhd_daemon_close_all_conns (d); 4142 } 4143 4144 4145 /** 4146 * Internal daemon initialisation function. 4147 * This function calls all required initialisation stages one-by-one. 4148 * @param d the daemon object 4149 * @param s the user settings 4150 * @return #MHD_SC_OK on success, 4151 * the error code otherwise 4152 */ 4153 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 4154 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 4155 daemon_start_internal (struct MHD_Daemon *restrict d, 4156 struct DaemonOptions *restrict s) 4157 { 4158 enum MHD_StatusCode res; 4159 4160 res = daemon_set_basic_settings (d, s); 4161 if (MHD_SC_OK != res) 4162 return res; 4163 4164 res = daemon_set_work_mode (d, s); 4165 if (MHD_SC_OK != res) 4166 return res; 4167 4168 res = daemon_init_net (d, s); 4169 if (MHD_SC_OK != res) 4170 return res; 4171 4172 mhd_assert (d->dbg.net_inited); 4173 4174 res = daemon_init_auth_digest (d, s); 4175 4176 if (MHD_SC_OK == res) 4177 { 4178 res = daemon_init_tls (d, s); 4179 if (MHD_SC_OK == res) 4180 { 4181 mhd_assert (d->dbg.tls_inited); 4182 res = daemon_init_threading_and_conn (d, s); 4183 if (MHD_SC_OK == res) 4184 { 4185 mhd_assert (d->dbg.threading_inited); 4186 mhd_assert (!mhd_D_TYPE_IS_INTERNAL_ONLY (d->threading.d_type)); 4187 4188 res = daemon_init_large_buf (d, s); 4189 if (MHD_SC_OK == res) 4190 { 4191 res = daemon_init_acme (d, s); 4192 if (MHD_SC_OK == res) 4193 { 4194 res = daemon_start_threads (d); 4195 if (MHD_SC_OK == res) 4196 { 4197 return MHD_SC_OK; /* Success exit point */ 4198 } 4199 4200 /* Below is a clean-up path */ 4201 daemon_deinit_acme (d); 4202 } 4203 daemon_deinit_large_buf (d); 4204 } 4205 daemon_deinit_threading_and_conn (d); 4206 } 4207 daemon_deinit_tls (d); 4208 } 4209 daemon_deinit_auth_digest (d); 4210 } 4211 daemon_deinit_net (d); 4212 mhd_assert (MHD_SC_OK != res); 4213 return res; /* Failure exit point */ 4214 } 4215 4216 4217 MHD_EXTERN_ 4218 MHD_FN_PAR_NONNULL_ (1) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 4219 MHD_daemon_start (struct MHD_Daemon *daemon) 4220 { 4221 struct MHD_Daemon *const d = daemon; /* a short alias */ 4222 struct DaemonOptions *const s = daemon->settings; /* a short alias */ 4223 enum MHD_StatusCode res; 4224 4225 if (mhd_DAEMON_STATE_NOT_STARTED != daemon->state) 4226 return MHD_SC_TOO_LATE; 4227 4228 mhd_assert (NULL != s); 4229 4230 d->state = mhd_DAEMON_STATE_STARTING; 4231 res = daemon_start_internal (d, s); 4232 4233 d->settings = NULL; 4234 dsettings_release (s); 4235 4236 d->state = 4237 (MHD_SC_OK == res) ? mhd_DAEMON_STATE_STARTED : mhd_DAEMON_STATE_FAILED; 4238 4239 return res; 4240 } 4241 4242 4243 MHD_EXTERN_ MHD_FN_PAR_NONNULL_ALL_ void 4244 MHD_daemon_destroy (struct MHD_Daemon *daemon) 4245 { 4246 bool not_yet_started = (mhd_DAEMON_STATE_NOT_STARTED == daemon->state); 4247 bool has_failed = (mhd_DAEMON_STATE_FAILED == daemon->state); 4248 mhd_assert (mhd_DAEMON_STATE_STOPPING > daemon->state); 4249 mhd_assert (mhd_DAEMON_STATE_STARTING != daemon->state); 4250 4251 daemon->state = mhd_DAEMON_STATE_STOPPING; 4252 if (not_yet_started) 4253 { 4254 mhd_assert (NULL != daemon->settings); 4255 dsettings_release (daemon->settings); 4256 } 4257 else if (!has_failed) 4258 { 4259 mhd_assert (NULL == daemon->settings); 4260 mhd_assert (daemon->dbg.threading_inited); 4261 4262 daemon_stop_threads (daemon); 4263 4264 daemon_close_connections (daemon); 4265 4266 daemon_deinit_threading_and_conn (daemon); 4267 4268 daemon_deinit_acme (daemon); 4269 4270 daemon_deinit_large_buf (daemon); 4271 4272 daemon_deinit_tls (daemon); 4273 4274 daemon_deinit_auth_digest (daemon); 4275 4276 daemon_deinit_net (daemon); 4277 } 4278 daemon->state = mhd_DAEMON_STATE_STOPPED; /* Useful only for debugging */ 4279 4280 free (daemon); 4281 4282 mhd_lib_deinit_global_if_needed (); 4283 }