GNU libmicrohttpd 1.0.10
Loading...
Searching...
No Matches
daemon.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4 Copyright (C) 2015-2024 Evgeny Grin (Karlson2k)
5
6 This library 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 This library 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 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20*/
21
29#include "platform.h"
30#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
31#include "mhd_threads.h"
32#endif
33#include "internal.h"
34#include "response.h"
35#include "connection.h"
36#include "memorypool.h"
37#include "mhd_limits.h"
38#include "autoinit_funcs.h"
39#include "mhd_mono_clock.h"
40#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
41#include "mhd_locks.h"
42#endif
43#include "mhd_sockets.h"
44#include "mhd_itc.h"
45#include "mhd_compat.h"
46#include "mhd_send.h"
47#include "mhd_align.h"
48#include "mhd_str.h"
49
50#ifdef MHD_USE_SYS_TSEARCH
51#include <search.h>
52#else /* ! MHD_USE_SYS_TSEARCH */
53#include "tsearch.h"
54#endif /* ! MHD_USE_SYS_TSEARCH */
55
56#ifdef HTTPS_SUPPORT
57#include "connection_https.h"
58#ifdef MHD_HTTPS_REQUIRE_GCRYPT
59#include <gcrypt.h>
60#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
61#endif /* HTTPS_SUPPORT */
62
63#if defined(_WIN32) && ! defined(__CYGWIN__)
64#ifndef WIN32_LEAN_AND_MEAN
65#define WIN32_LEAN_AND_MEAN 1
66#endif /* !WIN32_LEAN_AND_MEAN */
67#include <windows.h>
68#endif
69
70#ifdef MHD_USE_POSIX_THREADS
71#ifdef HAVE_SIGNAL_H
72#include <signal.h>
73#endif /* HAVE_SIGNAL_H */
74#endif /* MHD_USE_POSIX_THREADS */
75
79#ifdef MHD_POSIX_SOCKETS
80#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 3 - 1 - MHD_ITC_NUM_FDS_)
81#else
82#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
83#endif
84
88#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
89
90
91/* Forward declarations. */
92
93
97void
98MHD_init (void);
99
103void
104MHD_fini (void);
105
114static void
115close_all_connections (struct MHD_Daemon *daemon);
116
117#ifdef EPOLL_SUPPORT
118
128static enum MHD_Result
129MHD_epoll (struct MHD_Daemon *daemon,
130 int32_t millisec);
131
132#endif /* EPOLL_SUPPORT */
133
134#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
139#define MHD_check_global_init_() (void) 0
140#else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
144volatile int global_init_count = 0;
145
146#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
147#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
151MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
152#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
153#endif
154
155
160void
162{
163#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
164#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
165 MHD_mutex_lock_chk_ (&global_init_mutex_);
166#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
167#endif
168 if (0 == global_init_count++)
169 MHD_init ();
170#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
171#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
172 MHD_mutex_unlock_chk_ (&global_init_mutex_);
173#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
174#endif
175}
176
177
178#endif /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
179
180#ifdef HAVE_MESSAGES
184static void
185MHD_default_logger_ (void *cls,
186 const char *fm,
187 va_list ap)
188{
189 vfprintf ((FILE *) cls, fm, ap);
190#ifdef _DEBUG
191 fflush ((FILE *) cls);
192#endif /* _DEBUG */
193}
194
195
196#endif /* HAVE_MESSAGES */
197
198
212_MHD_EXTERN void
213MHD_free (void *ptr)
214{
215 free (ptr);
216}
217
218
222struct MHD_IPCount
223{
227 int family;
228
232 union
233 {
237 struct in_addr ipv4;
238#ifdef HAVE_INET6
242 struct in6_addr ipv6;
243#endif
244 } addr;
245
249 unsigned int count;
250};
251
252
258static void
260{
261 mhd_assert (NULL == daemon->master);
262#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
263 MHD_mutex_lock_chk_ (&daemon->per_ip_connection_mutex);
264#else
265 (void) daemon;
266#endif
267}
268
269
275static void
277{
278 mhd_assert (NULL == daemon->master);
279#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
280 MHD_mutex_unlock_chk_ (&daemon->per_ip_connection_mutex);
281#else
282 (void) daemon;
283#endif
284}
285
286
296static int
297MHD_ip_addr_compare (const void *a1,
298 const void *a2)
299{
300 return memcmp (a1,
301 a2,
302 offsetof (struct MHD_IPCount,
303 count));
304}
305
306
315static enum MHD_Result
316MHD_ip_addr_to_key (const struct sockaddr_storage *addr,
317 socklen_t addrlen,
318 struct MHD_IPCount *key)
319{
320 memset (key,
321 0,
322 sizeof(*key));
323
324 /* IPv4 addresses */
325 if (sizeof (struct sockaddr_in) <= (size_t) addrlen)
326 {
327 if (AF_INET == addr->ss_family)
328 {
329 key->family = AF_INET;
330 memcpy (&key->addr.ipv4,
331 &((const struct sockaddr_in *) addr)->sin_addr,
332 sizeof(((const struct sockaddr_in *) NULL)->sin_addr));
333 return MHD_YES;
334 }
335 }
336
337#ifdef HAVE_INET6
338 if (sizeof (struct sockaddr_in6) <= (size_t) addrlen)
339 {
340 /* IPv6 addresses */
341 if (AF_INET6 == addr->ss_family)
342 {
343 key->family = AF_INET6;
344 memcpy (&key->addr.ipv6,
345 &((const struct sockaddr_in6 *) addr)->sin6_addr,
346 sizeof(((const struct sockaddr_in6 *) NULL)->sin6_addr));
347 return MHD_YES;
348 }
349 }
350#endif
351
352 /* Some other address */
353 return MHD_NO;
354}
355
356
368static enum MHD_Result
370 const struct sockaddr_storage *addr,
371 socklen_t addrlen)
372{
373 struct MHD_IPCount *newkeyp;
374 struct MHD_IPCount *keyp;
375 struct MHD_IPCount **nodep;
376 enum MHD_Result result;
377
378 daemon = MHD_get_master (daemon);
379 /* Ignore if no connection limit assigned */
380 if (0 == daemon->per_ip_connection_limit)
381 return MHD_YES;
382
383 newkeyp = (struct MHD_IPCount *) malloc (sizeof(struct MHD_IPCount));
384 if (NULL == newkeyp)
385 return MHD_NO;
386
387 /* Initialize key */
388 if (MHD_NO == MHD_ip_addr_to_key (addr,
389 addrlen,
390 newkeyp))
391 {
392 free (newkeyp);
393 return MHD_YES; /* Allow unhandled address types through */
394 }
395
396 MHD_ip_count_lock (daemon);
397
398 /* Search for the IP address */
399 nodep = (struct MHD_IPCount **) tsearch (newkeyp,
402 if (NULL == nodep)
403 {
404 MHD_ip_count_unlock (daemon);
405 free (newkeyp);
406#ifdef HAVE_MESSAGES
407 MHD_DLOG (daemon,
408 _ ("Failed to add IP connection count node.\n"));
409#endif
410 return MHD_NO;
411 }
412 keyp = *nodep;
413 /* Test if there is room for another connection; if so,
414 * increment count */
415 result = (keyp->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
416 if (MHD_NO != result)
417 ++keyp->count;
418 MHD_ip_count_unlock (daemon);
419
420 /* If we got an existing node back, free the one we created */
421 if (keyp != newkeyp)
422 free (newkeyp);
423
424 return result;
425}
426
427
436static void
438 const struct sockaddr_storage *addr,
439 socklen_t addrlen)
440{
441 struct MHD_IPCount search_key;
442 struct MHD_IPCount *found_key;
443 void **nodep;
444
445 daemon = MHD_get_master (daemon);
446 /* Ignore if no connection limit assigned */
447 if (0 == daemon->per_ip_connection_limit)
448 return;
449 /* Initialize search key */
450 if (MHD_NO == MHD_ip_addr_to_key (addr,
451 addrlen,
452 &search_key))
453 return;
454
455 MHD_ip_count_lock (daemon);
456
457 /* Search for the IP address */
458 if (NULL == (nodep = tfind (&search_key,
461 {
462 /* Something's wrong if we couldn't find an IP address
463 * that was previously added */
464 MHD_PANIC (_ ("Failed to find previously-added IP address.\n"));
465 }
466 found_key = (struct MHD_IPCount *) *nodep;
467 /* Validate existing count for IP address */
468 if (0 == found_key->count)
469 {
470 MHD_PANIC (_ ("Previously-added IP address had counter of zero.\n"));
471 }
472 /* Remove the node entirely if count reduces to 0 */
473 if (0 == --found_key->count)
474 {
475 tdelete (found_key,
478 MHD_ip_count_unlock (daemon);
479 free (found_key);
480 }
481 else
482 MHD_ip_count_unlock (daemon);
483}
484
485
486#ifdef HTTPS_SUPPORT
493static int
494MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
495{
496 gnutls_datum_t key;
497 gnutls_datum_t cert;
498 int ret;
499
500#if GNUTLS_VERSION_MAJOR >= 3
501 if (NULL != daemon->cert_callback)
502 {
503 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
504 daemon->cert_callback);
505 }
506#endif
507#if GNUTLS_VERSION_NUMBER >= 0x030603
508 else if (NULL != daemon->cert_callback2)
509 {
510 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
511 daemon->cert_callback2);
512 }
513#endif
514
515 if (NULL != daemon->https_mem_trust)
516 {
517 size_t paramlen;
518 paramlen = strlen (daemon->https_mem_trust);
519 if (UINT_MAX < paramlen)
520 {
521#ifdef HAVE_MESSAGES
522 MHD_DLOG (daemon,
523 _ ("Too long trust certificate.\n"));
524#endif
525 return -1;
526 }
527 cert.data = (unsigned char *) _MHD_DROP_CONST (daemon->https_mem_trust);
528 cert.size = (unsigned int) paramlen;
529 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
530 &cert,
531 GNUTLS_X509_FMT_PEM) < 0)
532 {
533#ifdef HAVE_MESSAGES
534 MHD_DLOG (daemon,
535 _ ("Bad trust certificate format.\n"));
536#endif
537 return -1;
538 }
539 }
540
541 if (daemon->have_dhparams)
542 {
543 gnutls_certificate_set_dh_params (daemon->x509_cred,
544 daemon->https_mem_dhparams);
545 }
546 /* certificate & key loaded from memory */
547 if ( (NULL != daemon->https_mem_cert) &&
548 (NULL != daemon->https_mem_key) )
549 {
550 size_t param1len;
551 size_t param2len;
552
553 param1len = strlen (daemon->https_mem_key);
554 param2len = strlen (daemon->https_mem_cert);
555 if ( (UINT_MAX < param1len) ||
556 (UINT_MAX < param2len) )
557 {
558#ifdef HAVE_MESSAGES
559 MHD_DLOG (daemon,
560 _ ("Too long key or certificate.\n"));
561#endif
562 return -1;
563 }
564 key.data = (unsigned char *) _MHD_DROP_CONST (daemon->https_mem_key);
565 key.size = (unsigned int) param1len;
566 cert.data = (unsigned char *) _MHD_DROP_CONST (daemon->https_mem_cert);
567 cert.size = (unsigned int) param2len;
568
569 if (NULL != daemon->https_key_password)
570 {
571#if GNUTLS_VERSION_NUMBER >= 0x030111
572 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
573 &cert,
574 &key,
575 GNUTLS_X509_FMT_PEM,
576 daemon->https_key_password,
577 0);
578#else
579#ifdef HAVE_MESSAGES
580 MHD_DLOG (daemon,
581 _ ("Failed to setup x509 certificate/key: pre 3.X.X version " \
582 "of GnuTLS does not support setting key password.\n"));
583#endif
584 return -1;
585#endif
586 }
587 else
588 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
589 &cert,
590 &key,
591 GNUTLS_X509_FMT_PEM);
592#ifdef HAVE_MESSAGES
593 if (0 != ret)
594 MHD_DLOG (daemon,
595 _ ("GnuTLS failed to setup x509 certificate/key: %s\n"),
596 gnutls_strerror (ret));
597#endif
598 return ret;
599 }
600#if GNUTLS_VERSION_MAJOR >= 3
601 if (NULL != daemon->cert_callback)
602 return 0;
603#endif
604#if GNUTLS_VERSION_NUMBER >= 0x030603
605 else if (NULL != daemon->cert_callback2)
606 return 0;
607#endif
608#ifdef HAVE_MESSAGES
609 MHD_DLOG (daemon,
610 _ ("You need to specify a certificate and key location.\n"));
611#endif
612 return -1;
613}
614
615
622static int
623MHD_TLS_init (struct MHD_Daemon *daemon)
624{
625 switch (daemon->cred_type)
626 {
627 case GNUTLS_CRD_CERTIFICATE:
628 if (0 !=
629 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
630 return GNUTLS_E_MEMORY_ERROR;
631 return MHD_init_daemon_certificate (daemon);
632 case GNUTLS_CRD_PSK:
633 if (0 !=
634 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
635 return GNUTLS_E_MEMORY_ERROR;
636 return 0;
637 case GNUTLS_CRD_ANON:
638 case GNUTLS_CRD_SRP:
639 case GNUTLS_CRD_IA:
640 default:
641#ifdef HAVE_MESSAGES
642 MHD_DLOG (daemon,
643 _ ("Error: invalid credentials type %d specified.\n"),
644 daemon->cred_type);
645#endif
646 return -1;
647 }
648}
649
650
664static void
665tls_cleanup_failed_start (struct MHD_Daemon *daemon)
666{
667 if (daemon->have_dhparams)
668 {
669 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
670 daemon->have_dhparams = false;
671 }
672 if (NULL != daemon->priority_cache)
673 {
674 gnutls_priority_deinit (daemon->priority_cache);
675 daemon->priority_cache = NULL;
676 }
677 if (NULL != daemon->x509_cred)
678 {
679 gnutls_certificate_free_credentials (daemon->x509_cred);
680 daemon->x509_cred = NULL;
681 }
682 if (NULL != daemon->psk_cred)
683 {
684 gnutls_psk_free_server_credentials (daemon->psk_cred);
685 daemon->psk_cred = NULL;
686 }
687}
688
689
690#endif /* HTTPS_SUPPORT */
691
692
693#undef MHD_get_fdset
694
727MHD_get_fdset (struct MHD_Daemon *daemon,
728 fd_set *read_fd_set,
729 fd_set *write_fd_set,
730 fd_set *except_fd_set,
731 MHD_socket *max_fd)
732{
733 return MHD_get_fdset2 (daemon,
734 read_fd_set,
735 write_fd_set,
736 except_fd_set,
737 max_fd,
738#ifdef HAS_FD_SETSIZE_OVERRIDABLE
739 daemon->fdset_size_set_by_app ?
740 ((unsigned int) daemon->fdset_size) :
741 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
742#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
743 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
744#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
745 );
746}
747
748
749#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
762static bool
763urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
764 fd_set *rs,
765 fd_set *ws,
766 fd_set *es,
767 MHD_socket *max_fd,
768 int fd_setsize)
769{
770 const MHD_socket conn_sckt = urh->connection->socket_fd;
771 const MHD_socket mhd_sckt = urh->mhd.socket;
772 bool res = true;
773
774#ifndef HAS_FD_SETSIZE_OVERRIDABLE
775 (void) fd_setsize; /* Mute compiler warning */
776 fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
777#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
778
779 /* Do not add to 'es' only if socket is closed
780 * or not used anymore. */
781 if (MHD_INVALID_SOCKET != conn_sckt)
782 {
783 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
784 (! MHD_add_to_fd_set_ (conn_sckt,
785 rs,
786 max_fd,
787 fd_setsize)) )
788 res = false;
789 if ( (0 != urh->out_buffer_used) &&
790 (! MHD_add_to_fd_set_ (conn_sckt,
791 ws,
792 max_fd,
793 fd_setsize)) )
794 res = false;
795 /* Do not monitor again for errors if error was detected before as
796 * error state is remembered. */
797 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
798 ((0 != urh->in_buffer_size) ||
799 (0 != urh->out_buffer_size) ||
800 (0 != urh->out_buffer_used))
801 && (NULL != es))
802 (void) MHD_add_to_fd_set_ (conn_sckt,
803 es,
804 max_fd,
805 fd_setsize);
806 }
807 if (MHD_INVALID_SOCKET != mhd_sckt)
808 {
809 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
810 (! MHD_add_to_fd_set_ (mhd_sckt,
811 rs,
812 max_fd,
813 fd_setsize)) )
814 res = false;
815 if ( (0 != urh->in_buffer_used) &&
816 (! MHD_add_to_fd_set_ (mhd_sckt,
817 ws,
818 max_fd,
819 fd_setsize)) )
820 res = false;
821 /* Do not monitor again for errors if error was detected before as
822 * error state is remembered. */
823 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
824 ((0 != urh->out_buffer_size) ||
825 (0 != urh->in_buffer_size) ||
826 (0 != urh->in_buffer_used))
827 && (NULL != es))
828 MHD_add_to_fd_set_ (mhd_sckt,
829 es,
830 max_fd,
831 fd_setsize);
832 }
833
834 return res;
835}
836
837
848static void
849urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
850 const fd_set *rs,
851 const fd_set *ws,
852 const fd_set *es,
853 int fd_setsize)
854{
855 const MHD_socket conn_sckt = urh->connection->socket_fd;
856 const MHD_socket mhd_sckt = urh->mhd.socket;
857
858 /* Reset read/write ready, preserve error state. */
859 urh->app.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
861 urh->mhd.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
863
864 mhd_assert (urh->connection->sk_nonblck);
865
866#ifndef HAS_FD_SETSIZE_OVERRIDABLE
867 (void) fd_setsize; /* Mute compiler warning */
868 mhd_assert (((int) FD_SETSIZE) <= fd_setsize);
869 fd_setsize = FD_SETSIZE; /* Help compiler to optimise */
870#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
871
872 if (MHD_INVALID_SOCKET != conn_sckt)
873 {
874 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (conn_sckt, NULL, fd_setsize))
875 {
876 if (FD_ISSET (conn_sckt, (fd_set *) _MHD_DROP_CONST (rs)))
877 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
878 if (FD_ISSET (conn_sckt, (fd_set *) _MHD_DROP_CONST (ws)))
879 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
880 if ((NULL != es) &&
881 FD_ISSET (conn_sckt, (fd_set *) _MHD_DROP_CONST (es)))
882 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
883 }
884 else
885 { /* Cannot check readiness. Force ready state is safe as socket is non-blocking */
886 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
887 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
888 }
889 }
890 if ((MHD_INVALID_SOCKET != mhd_sckt))
891 {
892 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (mhd_sckt, NULL, fd_setsize))
893 {
894 if (FD_ISSET (mhd_sckt, (fd_set *) _MHD_DROP_CONST (rs)))
895 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
896 if (FD_ISSET (mhd_sckt, (fd_set *) _MHD_DROP_CONST (ws)))
897 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
898 if ((NULL != es) &&
899 FD_ISSET (mhd_sckt, (fd_set *) _MHD_DROP_CONST (es)))
900 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
901 }
902 else
903 { /* Cannot check readiness. Force ready state is safe as socket is non-blocking */
904 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
905 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
906 }
907 }
908}
909
910
911#ifdef HAVE_POLL
912
921static void
922urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
923 struct pollfd p[2])
924{
925 p[0].events = 0;
926 p[1].events = 0;
927
928 if (urh->in_buffer_used < urh->in_buffer_size)
929 p[0].events |= POLLIN;
930 if (0 != urh->out_buffer_used)
931 p[0].events |= POLLOUT;
932
933 /* Do not monitor again for errors if error was detected before as
934 * error state is remembered. */
935 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
936 ((0 != urh->in_buffer_size) ||
937 (0 != urh->out_buffer_size) ||
938 (0 != urh->out_buffer_used)))
939 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
940
941 if (urh->out_buffer_used < urh->out_buffer_size)
942 p[1].events |= POLLIN;
943 if (0 != urh->in_buffer_used)
944 p[1].events |= POLLOUT;
945
946 /* Do not monitor again for errors if error was detected before as
947 * error state is remembered. */
948 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
949 ((0 != urh->out_buffer_size) ||
950 (0 != urh->in_buffer_size) ||
951 (0 != urh->in_buffer_used)))
952 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
953}
954
955
962static void
963urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
964 struct pollfd p[2])
965{
966 p[0].fd = urh->connection->socket_fd;
967 p[1].fd = urh->mhd.socket;
968 urh_update_pollfd (urh,
969 p);
970}
971
972
978static void
979urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
980 struct pollfd p[2])
981{
982 /* Reset read/write ready, preserve error state. */
983 urh->app.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
985 urh->mhd.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
987
988 if (0 != (p[0].revents & POLLIN))
989 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
990 if (0 != (p[0].revents & POLLOUT))
991 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
992 if (0 != (p[0].revents & POLLHUP))
994 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
995 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
996 if (0 != (p[1].revents & POLLIN))
997 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
998 if (0 != (p[1].revents & POLLOUT))
999 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
1000 if (0 != (p[1].revents & POLLHUP))
1002 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
1003 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
1004}
1005
1006
1007#endif /* HAVE_POLL */
1008#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1009
1010
1025static enum MHD_Result
1027 fd_set *read_fd_set,
1028 fd_set *write_fd_set,
1029 fd_set *except_fd_set,
1030 MHD_socket *max_fd,
1031 int fd_setsize)
1032{
1033 struct MHD_Connection *pos;
1034 struct MHD_Connection *posn;
1035 enum MHD_Result result = MHD_YES;
1036 MHD_socket ls;
1037 bool itc_added;
1038
1039#ifndef HAS_FD_SETSIZE_OVERRIDABLE
1040 (void) fd_setsize; /* Mute compiler warning */
1041 fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
1042#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
1043
1044 if (daemon->shutdown)
1045 return MHD_YES;
1046
1047 /* The order of FDs added is important for W32 sockets as W32 fd_set has
1048 limits for number of added FDs instead of the limit for the higher
1049 FD value. */
1050
1051 /* Add ITC FD first. The daemon must be able to respond on application
1052 commands issued in other threads. */
1053 itc_added = false;
1054 if (MHD_ITC_IS_VALID_ (daemon->itc))
1055 {
1056 itc_added = MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1057 read_fd_set,
1058 max_fd,
1059 fd_setsize);
1060 if (! itc_added)
1061 result = MHD_NO;
1062 }
1063
1065 if (! itc_added &&
1066 (MHD_INVALID_SOCKET != ls))
1067 {
1068 /* Add listen FD if ITC was not added. Listen FD could be used to signal
1069 the daemon shutdown. */
1070 if (MHD_add_to_fd_set_ (ls,
1071 read_fd_set,
1072 max_fd,
1073 fd_setsize))
1074 ls = MHD_INVALID_SOCKET; /* Already added */
1075 else
1076 result = MHD_NO;
1077 }
1078
1079 /* Add all sockets to 'except_fd_set' as well to watch for
1080 * out-of-band data. However, ignore errors if INFO_READ
1081 * or INFO_WRITE sockets will not fit 'except_fd_set'. */
1082 /* Start from oldest connections. Make sense for W32 FDSETs. */
1083 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1084 {
1085 posn = pos->prev;
1086
1087 switch (pos->event_loop_info)
1088 {
1091 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1092 read_fd_set,
1093 max_fd,
1094 fd_setsize))
1095 result = MHD_NO;
1096#ifdef MHD_POSIX_SOCKETS
1097 if (NULL != except_fd_set)
1098 (void) MHD_add_to_fd_set_ (pos->socket_fd,
1099 except_fd_set,
1100 max_fd,
1101 fd_setsize);
1102#endif /* MHD_POSIX_SOCKETS */
1103 break;
1105 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1106 write_fd_set,
1107 max_fd,
1108 fd_setsize))
1109 result = MHD_NO;
1110#ifdef MHD_POSIX_SOCKETS
1111 if (NULL != except_fd_set)
1112 (void) MHD_add_to_fd_set_ (pos->socket_fd,
1113 except_fd_set,
1114 max_fd,
1115 fd_setsize);
1116#endif /* MHD_POSIX_SOCKETS */
1117 break;
1119 if ( (NULL == except_fd_set) ||
1121 except_fd_set,
1122 max_fd,
1123 fd_setsize))
1124 result = MHD_NO;
1125 break;
1127 /* this should never happen */
1128 break;
1129 }
1130 }
1131#ifdef MHD_WINSOCK_SOCKETS
1132 /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
1133 * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
1134 * not be pushed out. */
1135 if (NULL != except_fd_set)
1136 {
1137 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1138 {
1139 posn = pos->prev;
1141 except_fd_set,
1142 max_fd,
1143 fd_setsize);
1144 }
1145 }
1146#endif /* MHD_WINSOCK_SOCKETS */
1147#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1148 if (1)
1149 {
1150 struct MHD_UpgradeResponseHandle *urh;
1151
1152 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
1153 {
1154 if (MHD_NO ==
1155 urh_to_fdset (urh,
1156 read_fd_set,
1157 write_fd_set,
1158 except_fd_set,
1159 max_fd,
1160 fd_setsize))
1161 result = MHD_NO;
1162 }
1163 }
1164#endif
1165
1166 if (MHD_INVALID_SOCKET != ls)
1167 {
1168 /* The listen socket is present and hasn't been added */
1169 if ((daemon->connections < daemon->connection_limit) &&
1170 ! daemon->at_limit)
1171 {
1172 if (! MHD_add_to_fd_set_ (ls,
1173 read_fd_set,
1174 max_fd,
1175 fd_setsize))
1176 result = MHD_NO;
1177 }
1178 }
1179
1180#if _MHD_DEBUG_CONNECT
1181#ifdef HAVE_MESSAGES
1182 if (NULL != max_fd)
1183 MHD_DLOG (daemon,
1184 _ ("Maximum socket in select set: %d\n"),
1185 *max_fd);
1186#endif
1187#endif
1188 return result;
1189}
1190
1191
1228 fd_set *read_fd_set,
1229 fd_set *write_fd_set,
1230 fd_set *except_fd_set,
1231 MHD_socket *max_fd,
1232 unsigned int fd_setsize)
1233{
1234 if ( (NULL == daemon) ||
1235 (NULL == read_fd_set) ||
1236 (NULL == write_fd_set) ||
1237 MHD_D_IS_USING_THREADS_ (daemon) ||
1238 MHD_D_IS_USING_POLL_ (daemon))
1239 return MHD_NO;
1240
1241#ifdef HAVE_MESSAGES
1242 if (NULL == except_fd_set)
1243 {
1244 MHD_DLOG (daemon,
1245 _ ("MHD_get_fdset2() called with except_fd_set "
1246 "set to NULL. Such behavior is unsupported.\n"));
1247 }
1248#endif
1249
1250#ifdef HAS_FD_SETSIZE_OVERRIDABLE
1251 if (0 == fd_setsize)
1252 return MHD_NO;
1253 else if (((unsigned int) INT_MAX) < fd_setsize)
1254 fd_setsize = (unsigned int) INT_MAX;
1255#ifdef HAVE_MESSAGES
1256 else if (daemon->fdset_size > ((int) fd_setsize))
1257 {
1258 if (daemon->fdset_size_set_by_app)
1259 {
1260 MHD_DLOG (daemon,
1261 _ ("%s() called with fd_setsize (%u) " \
1262 "less than value set by MHD_OPTION_APP_FD_SETSIZE (%d). " \
1263 "Some socket FDs may be not processed. " \
1264 "Use MHD_OPTION_APP_FD_SETSIZE with the correct value.\n"),
1265 "MHD_get_fdset2", fd_setsize, daemon->fdset_size);
1266 }
1267 else
1268 {
1269 MHD_DLOG (daemon,
1270 _ ("%s() called with fd_setsize (%u) " \
1271 "less than FD_SETSIZE used by MHD (%d). " \
1272 "Some socket FDs may be not processed. " \
1273 "Consider using MHD_OPTION_APP_FD_SETSIZE option.\n"),
1274 "MHD_get_fdset2", fd_setsize, daemon->fdset_size);
1275 }
1276 }
1277#endif /* HAVE_MESSAGES */
1278#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
1279 if (((unsigned int) FD_SETSIZE) > fd_setsize)
1280 {
1281#ifdef HAVE_MESSAGES
1282 MHD_DLOG (daemon,
1283 _ ("%s() called with fd_setsize (%u) " \
1284 "less than fixed FD_SETSIZE value (%d) used on the " \
1285 "platform.\n"),
1286 "MHD_get_fdset2", fd_setsize, (int) FD_SETSIZE);
1287#endif /* HAVE_MESSAGES */
1288 return MHD_NO;
1289 }
1290 fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
1291#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
1292
1293#ifdef EPOLL_SUPPORT
1294 if (MHD_D_IS_USING_EPOLL_ (daemon))
1295 {
1296 if (daemon->shutdown)
1297 return MHD_YES;
1298
1299 /* we're in epoll mode, use the epoll FD as a stand-in for
1300 the entire event set */
1301
1302 return MHD_add_to_fd_set_ (daemon->epoll_fd,
1303 read_fd_set,
1304 max_fd,
1305 (int) fd_setsize) ? MHD_YES : MHD_NO;
1306 }
1307#endif
1308
1309 return internal_get_fdset2 (daemon,
1310 read_fd_set,
1311 write_fd_set,
1312 except_fd_set,
1313 max_fd,
1314 (int) fd_setsize);
1315}
1316
1317
1331static enum MHD_Result
1333 bool read_ready,
1334 bool write_ready,
1335 bool force_close)
1336{
1337 enum MHD_Result ret;
1338 bool states_info_processed = false;
1339 /* Fast track flag */
1340 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1341 ret = MHD_YES;
1342
1343 mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1345 mhd_assert ((0 != (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1346 (! MHD_thread_handle_ID_is_valid_ID_ (con->tid)));
1347 mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1349
1350#ifdef HTTPS_SUPPORT
1351 if (con->tls_read_ready)
1352 read_ready = true;
1353#endif /* HTTPS_SUPPORT */
1354 if (con->resumed)
1355 {
1356 /* The connection was resumed since its states were last updated,
1357 so 'con->event_loop_info' still describes the state the
1358 connection was in before it was suspended -- see the field's
1359 description. Dispatching on it would, for instance, call
1360 MHD_connection_handle_write() on a connection whose content
1361 reader has just reported that it has no data yet, which is not a
1362 state the write handler has an action for. */
1363 con->resumed = false;
1364 ret = MHD_connection_handle_idle (con);
1365 if (MHD_NO == ret)
1366 return ret; /* Connection died and was cleaned up. */
1367 states_info_processed = true;
1368 }
1369 if ( (0 != (MHD_EVENT_LOOP_INFO_READ & con->event_loop_info)) &&
1370 (read_ready || (force_close && con->sk_nonblck)) )
1371 {
1372 MHD_connection_handle_read (con, force_close);
1373 /* MHD_connection_handle_read() closes the connection when
1374 @a force_close is set, but only once it gets far enough to try.
1375 It returns early, leaving 'con->state' untouched, in three cases,
1376 and all three are reachable from here:
1377 - the connection is suspended,
1378 - a TLS handshake is still in progress,
1379 - the read buffer has no free space at all. */
1380#ifdef HTTPS_SUPPORT
1381 mhd_assert ((! force_close) || \
1382 (MHD_CONNECTION_CLOSED == con->state) || \
1383 (con->suspended) || \
1384 ( (MHD_TLS_CONN_NO_TLS != con->tls_state) && \
1385 (MHD_TLS_CONN_CONNECTED > con->tls_state) ) || \
1386 (con->read_buffer_size == con->read_buffer_offset));
1387#else /* ! HTTPS_SUPPORT */
1388 mhd_assert ((! force_close) || \
1389 (MHD_CONNECTION_CLOSED == con->state) || \
1390 (con->suspended) || \
1391 (con->read_buffer_size == con->read_buffer_offset));
1392#endif /* ! HTTPS_SUPPORT */
1393 ret = MHD_connection_handle_idle (con);
1394 if (force_close)
1395 return ret;
1396 states_info_processed = true;
1397 }
1398 if (! force_close)
1399 {
1400 /* No need to check value of 'ret' here as closed connection
1401 * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1403 write_ready)
1404 {
1406 ret = MHD_connection_handle_idle (con);
1407 states_info_processed = true;
1408 }
1409 }
1410 else
1411 {
1414 return MHD_connection_handle_idle (con);
1415 }
1416
1417 if (! states_info_processed)
1418 { /* Connection is not read or write ready, but external conditions
1419 * may be changed and need to be processed. */
1420 ret = MHD_connection_handle_idle (con);
1421 }
1422 /* Fast track for fast connections. */
1423 /* If full request was read by single read_handler() invocation
1424 and headers were completely prepared by single MHD_connection_handle_idle()
1425 then try not to wait for next sockets polling and send response
1426 immediately.
1427 As writeability of socket was not checked and it may have
1428 some data pending in system buffers, use this optimization
1429 only for non-blocking sockets. */
1430 /* No need to check 'ret' as connection is always in
1431 * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1432 else if (on_fasttrack && con->sk_nonblck)
1433 {
1435 {
1437 /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1438 ret = MHD_connection_handle_idle (con);
1439 }
1440 /* If all headers were sent by single write_handler() and
1441 * response body is prepared by single MHD_connection_handle_idle()
1442 * call - continue. */
1445 {
1447 ret = MHD_connection_handle_idle (con);
1448 }
1449 }
1450
1451 /* All connection's data and states are processed for this turn.
1452 * If connection already has more data to be processed - use
1453 * zero timeout for next select()/poll(). */
1454 /* Thread-per-connection do not need global zero timeout as
1455 * connections are processed individually. */
1456 /* Note: no need to check for read buffer availability for
1457 * TLS read-ready connection in 'read info' state as connection
1458 * without space in read buffer will be marked as 'info block'. */
1459 if ( (! con->daemon->data_already_pending) &&
1461 {
1463 con->daemon->data_already_pending = true;
1464#ifdef HTTPS_SUPPORT
1465 else if ( (con->tls_read_ready) &&
1467 con->daemon->data_already_pending = true;
1468#endif /* HTTPS_SUPPORT */
1469 }
1470 return ret;
1471}
1472
1473
1474#ifdef UPGRADE_SUPPORT
1482static void
1483cleanup_upgraded_connection (struct MHD_Connection *connection)
1484{
1485 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1486
1487 if (NULL == urh)
1488 return;
1489#ifdef HTTPS_SUPPORT
1490 /* Signal remote client the end of TLS connection by
1491 * gracefully closing TLS session. */
1492 if (0 != (connection->daemon->options & MHD_USE_TLS))
1493 gnutls_bye (connection->tls_session,
1494 GNUTLS_SHUT_WR);
1495
1496 if (MHD_INVALID_SOCKET != urh->mhd.socket)
1497 MHD_socket_close_chk_ (urh->mhd.socket);
1498
1499 if (MHD_INVALID_SOCKET != urh->app.socket)
1500 MHD_socket_close_chk_ (urh->app.socket);
1501#endif /* HTTPS_SUPPORT */
1502 connection->urh = NULL;
1503 free (urh);
1504}
1505
1506
1507#endif /* UPGRADE_SUPPORT */
1508
1509
1510#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1519static void
1520process_urh (struct MHD_UpgradeResponseHandle *urh)
1521{
1522 /* Help compiler to optimize:
1523 * pointers to 'connection' and 'daemon' are not changed
1524 * during this processing, so no need to chain dereference
1525 * each time. */
1526 struct MHD_Connection *const connection = urh->connection;
1527 struct MHD_Daemon *const daemon = connection->daemon;
1528 /* Prevent data races: use same value of 'was_closed' throughout
1529 * this function. If 'was_closed' changed externally in the middle
1530 * of processing - it will be processed on next iteration. */
1531 bool was_closed;
1532
1533#ifdef MHD_USE_THREADS
1534 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
1535 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
1536#endif /* MHD_USE_THREADS */
1537
1538 mhd_assert (0 != (daemon->options & MHD_USE_TLS));
1539
1540 if (daemon->shutdown)
1541 {
1542 /* Daemon shutting down, application will not receive any more data. */
1543#ifdef HAVE_MESSAGES
1544 if (! urh->was_closed)
1545 {
1546 MHD_DLOG (daemon,
1547 _ ("Initiated daemon shutdown while \"upgraded\" " \
1548 "connection was not closed.\n"));
1549 }
1550#endif
1551 urh->was_closed = true;
1552 }
1553 was_closed = urh->was_closed;
1554 if (was_closed)
1555 {
1556 /* Application was closed connections: no more data
1557 * can be forwarded to application socket. */
1558 if (0 < urh->in_buffer_used)
1559 {
1560#ifdef HAVE_MESSAGES
1561 MHD_DLOG (daemon,
1562 _ ("Failed to forward to application %" PRIu64 \
1563 " bytes of data received from remote side: " \
1564 "application closed data forwarding.\n"),
1565 (uint64_t) urh->in_buffer_used);
1566#endif
1567
1568 }
1569 /* Discard any data received form remote. */
1570 urh->in_buffer_used = 0;
1571 /* Do not try to push data to application. */
1572 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1573 /* Reading from remote client is not required anymore. */
1574 urh->in_buffer_size = 0;
1575 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1576 connection->tls_read_ready = false;
1577 }
1578
1579 /* On some platforms (W32, possibly Darwin) failed send() (send() will
1580 * always fail after remote disconnect was detected) may discard data in
1581 * system buffers received by system but not yet read by recv(). So, before
1582 * trying send() on any socket, recv() must be performed at first otherwise
1583 * last part of incoming data may be lost. If disconnect or error was
1584 * detected - try to read from socket to dry data possibly pending is system
1585 * buffers. */
1586
1587 /*
1588 * handle reading from remote TLS client
1589 */
1591 & urh->app.celi)) ||
1592 (connection->tls_read_ready)) &&
1593 (urh->in_buffer_used < urh->in_buffer_size))
1594 {
1595 ssize_t res;
1596 size_t buf_size;
1597
1598 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1599 if (buf_size > SSIZE_MAX)
1600 buf_size = SSIZE_MAX;
1601
1602 res = gnutls_record_recv (connection->tls_session,
1603 &urh->in_buffer[urh->in_buffer_used],
1604 buf_size);
1605 if (0 >= res)
1606 {
1607 connection->tls_read_ready = false;
1608 if (GNUTLS_E_INTERRUPTED != res)
1609 {
1610 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1611 if ((GNUTLS_E_AGAIN != res) ||
1612 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)))
1613 {
1614 /* TLS unrecoverable error has been detected,
1615 socket error was detected and all data has been read,
1616 or socket was disconnected/shut down. */
1617 /* Stop trying to read from this TLS socket. */
1618 urh->in_buffer_size = 0;
1619 }
1620 }
1621 }
1622 else /* 0 < res */
1623 {
1624 urh->in_buffer_used += (size_t) res;
1625 connection->tls_read_ready =
1626 (0 < gnutls_record_check_pending (connection->tls_session));
1627 }
1628 }
1629
1630 /*
1631 * handle reading from application
1632 */
1633 /* If application signalled MHD about socket closure then
1634 * check for any pending data even if socket is not marked
1635 * as 'ready' (signal may arrive after poll()/select()).
1636 * Socketpair for forwarding is always in non-blocking mode
1637 * so no risk that recv() will block the thread. */
1639 & urh->mhd.celi))
1640 || was_closed) /* Force last reading from app if app has closed the connection */
1641 && (urh->out_buffer_used < urh->out_buffer_size))
1642 {
1643 ssize_t res;
1644 size_t buf_size;
1645
1646 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1647 if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1648 buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1649
1650 res = MHD_recv_ (urh->mhd.socket,
1651 &urh->out_buffer[urh->out_buffer_used],
1652 buf_size);
1653 if (0 >= res)
1654 {
1655 const int err = MHD_socket_get_error_ ();
1656 if ((0 == res) ||
1657 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1659 {
1660 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1661 if ((0 == res) ||
1662 (was_closed) ||
1663 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1664 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1665 {
1666 /* Socket disconnect/shutdown was detected;
1667 * Application signalled about closure of 'upgraded' socket and
1668 * all data has been read from application;
1669 * or persistent / unrecoverable error. */
1670 /* Do not try to pull more data from application. */
1671 urh->out_buffer_size = 0;
1672 }
1673 }
1674 }
1675 else /* 0 < res */
1676 {
1677 urh->out_buffer_used += (size_t) res;
1678 if (buf_size > (size_t) res)
1679 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1680 }
1681 }
1682
1683 /*
1684 * handle writing to remote HTTPS client
1685 */
1686 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1687 (urh->out_buffer_used > 0) )
1688 {
1689 ssize_t res;
1690 size_t data_size;
1691
1692 data_size = urh->out_buffer_used;
1693 if (data_size > SSIZE_MAX)
1694 data_size = SSIZE_MAX;
1695
1696 res = gnutls_record_send (connection->tls_session,
1697 urh->out_buffer,
1698 data_size);
1699 if (0 >= res)
1700 {
1701 if (GNUTLS_E_INTERRUPTED != res)
1702 {
1703 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1704 if (GNUTLS_E_AGAIN != res)
1705 {
1706 /* TLS connection shut down or
1707 * persistent / unrecoverable error. */
1708#ifdef HAVE_MESSAGES
1709 MHD_DLOG (daemon,
1710 _ ("Failed to forward to remote client %" PRIu64 \
1711 " bytes of data received from application: %s\n"),
1712 (uint64_t) urh->out_buffer_used,
1713 gnutls_strerror ((int) res));
1714#endif
1715 /* Discard any data unsent to remote. */
1716 urh->out_buffer_used = 0;
1717 /* Do not try to pull more data from application. */
1718 urh->out_buffer_size = 0;
1719 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1720 }
1721 }
1722 }
1723 else /* 0 < res */
1724 {
1725 const size_t next_out_buffer_used = urh->out_buffer_used - (size_t) res;
1726 if (0 != next_out_buffer_used)
1727 {
1728 memmove (urh->out_buffer,
1729 &urh->out_buffer[res],
1730 next_out_buffer_used);
1731 }
1732 urh->out_buffer_used = next_out_buffer_used;
1733 }
1734 if ( (0 == urh->out_buffer_used) &&
1735 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1736 {
1737 /* Unrecoverable error on socket was detected and all
1738 * pending data was sent to remote. */
1739 /* Do not try to send to remote anymore. */
1740 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1741 /* Do not try to pull more data from application. */
1742 urh->out_buffer_size = 0;
1743 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1744 }
1745 }
1746
1747 /*
1748 * handle writing to application
1749 */
1750 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1751 (urh->in_buffer_used > 0) )
1752 {
1753 ssize_t res;
1754 size_t data_size;
1755
1756 data_size = urh->in_buffer_used;
1757 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1758 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1759
1760 res = MHD_send_ (urh->mhd.socket,
1761 urh->in_buffer,
1762 data_size);
1763 if (0 >= res)
1764 {
1765 const int err = MHD_socket_get_error_ ();
1766 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1768 {
1769 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1770 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1771 {
1772 /* Socketpair connection shut down or
1773 * persistent / unrecoverable error. */
1774#ifdef HAVE_MESSAGES
1775 MHD_DLOG (daemon,
1776 _ ("Failed to forward to application %" PRIu64 \
1777 " bytes of data received from remote side: %s\n"),
1778 (uint64_t) urh->in_buffer_used,
1779 MHD_socket_strerr_ (err));
1780#endif
1781 /* Discard any data received from remote. */
1782 urh->in_buffer_used = 0;
1783 /* Reading from remote client is not required anymore. */
1784 urh->in_buffer_size = 0;
1785 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1786 connection->tls_read_ready = false;
1787 }
1788 }
1789 }
1790 else /* 0 < res */
1791 {
1792 const size_t next_in_buffer_used = urh->in_buffer_used - (size_t) res;
1793 if (0 != next_in_buffer_used)
1794 {
1795 memmove (urh->in_buffer,
1796 &urh->in_buffer[res],
1797 next_in_buffer_used);
1798 if (data_size > (size_t) res)
1799 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1800 }
1801 urh->in_buffer_used = next_in_buffer_used;
1802 }
1803 if ( (0 == urh->in_buffer_used) &&
1804 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1805 {
1806 /* Do not try to push data to application. */
1807 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1808 /* Reading from remote client is not required anymore. */
1809 urh->in_buffer_size = 0;
1810 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1811 connection->tls_read_ready = false;
1812 }
1813 }
1814
1815 /* Check whether data is present in TLS buffers
1816 * and incoming forward buffer have some space. */
1817 if ( (connection->tls_read_ready) &&
1818 (urh->in_buffer_used < urh->in_buffer_size) &&
1819 (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) )
1820 daemon->data_already_pending = true;
1821
1822 if ( (daemon->shutdown) &&
1823 ( (0 != urh->out_buffer_size) ||
1824 (0 != urh->out_buffer_used) ) )
1825 {
1826 /* Daemon shutting down, discard any remaining forward data. */
1827#ifdef HAVE_MESSAGES
1828 if (0 < urh->out_buffer_used)
1829 MHD_DLOG (daemon,
1830 _ ("Failed to forward to remote client %" PRIu64 \
1831 " bytes of data received from application: daemon shut down.\n"),
1832 (uint64_t) urh->out_buffer_used);
1833#endif
1834 /* Discard any data unsent to remote. */
1835 urh->out_buffer_used = 0;
1836 /* Do not try to sent to remote anymore. */
1837 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1838 /* Do not try to pull more data from application. */
1839 urh->out_buffer_size = 0;
1840 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1841 }
1842
1843 if (! was_closed && urh->was_closed)
1844 daemon->data_already_pending = true; /* Force processing again */
1845}
1846
1847
1848#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1849
1850#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1851#ifdef UPGRADE_SUPPORT
1860static void
1861thread_main_connection_upgrade (struct MHD_Connection *con)
1862{
1863#ifdef HTTPS_SUPPORT
1864 struct MHD_UpgradeResponseHandle *urh = con->urh;
1865 struct MHD_Daemon *daemon = con->daemon;
1866
1867 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
1869 /* Here, we need to bi-directionally forward
1870 until the application tells us that it is done
1871 with the socket; */
1872 if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1873 MHD_D_IS_USING_SELECT_ (daemon))
1874 {
1875 while ( (0 != urh->in_buffer_size) ||
1876 (0 != urh->out_buffer_size) ||
1877 (0 != urh->in_buffer_used) ||
1878 (0 != urh->out_buffer_used) )
1879 {
1880 /* use select */
1881 fd_set rs;
1882 fd_set ws;
1883 fd_set es;
1884 MHD_socket max_fd;
1885 int num_ready;
1886 bool result;
1887
1888 FD_ZERO (&rs);
1889 FD_ZERO (&ws);
1890 FD_ZERO (&es);
1891 max_fd = MHD_INVALID_SOCKET;
1892 result = urh_to_fdset (urh,
1893 &rs,
1894 &ws,
1895 &es,
1896 &max_fd,
1897 FD_SETSIZE);
1898 if (! result)
1899 {
1900#ifdef HAVE_MESSAGES
1901 MHD_DLOG (con->daemon,
1902 _ ("Error preparing select.\n"));
1903#endif
1904 break;
1905 }
1906 /* FIXME: does this check really needed? */
1907 if (MHD_INVALID_SOCKET != max_fd)
1908 {
1909 struct timeval *tvp;
1910 struct timeval tv;
1911 if (((con->tls_read_ready) &&
1912 (urh->in_buffer_used < urh->in_buffer_size)) ||
1913 (daemon->shutdown))
1914 { /* No need to wait if incoming data is already pending in TLS buffers. */
1915 tv.tv_sec = 0;
1916 tv.tv_usec = 0;
1917 tvp = &tv;
1918 }
1919 else
1920 tvp = NULL;
1921 num_ready = MHD_SYS_select_ (max_fd + 1,
1922 &rs,
1923 &ws,
1924 &es,
1925 tvp);
1926 }
1927 else
1928 num_ready = 0;
1929 if (num_ready < 0)
1930 {
1931 const int err = MHD_socket_get_error_ ();
1932
1933 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1934 continue;
1935#ifdef HAVE_MESSAGES
1936 MHD_DLOG (con->daemon,
1937 _ ("Error during select (%d): `%s'\n"),
1938 err,
1939 MHD_socket_strerr_ (err));
1940#endif
1941 break;
1942 }
1943 urh_from_fdset (urh,
1944 &rs,
1945 &ws,
1946 &es,
1947 (int) FD_SETSIZE);
1948 process_urh (urh);
1949 }
1950 }
1951#ifdef HAVE_POLL
1952 else if (0 != (daemon->options & MHD_USE_TLS))
1953 {
1954 /* use poll() */
1955 struct pollfd p[2];
1956 memset (p,
1957 0,
1958 sizeof (p));
1959 p[0].fd = urh->connection->socket_fd;
1960 p[1].fd = urh->mhd.socket;
1961
1962 while ( (0 != urh->in_buffer_size) ||
1963 (0 != urh->out_buffer_size) ||
1964 (0 != urh->in_buffer_used) ||
1965 (0 != urh->out_buffer_used) )
1966 {
1967 int timeout;
1968
1969 urh_update_pollfd (urh, p);
1970
1971 if (((con->tls_read_ready) &&
1972 (urh->in_buffer_used < urh->in_buffer_size)) ||
1973 (daemon->shutdown))
1974 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1975 else
1976 timeout = -1;
1977
1978 if (MHD_sys_poll_ (p,
1979 2,
1980 timeout) < 0)
1981 {
1982 const int err = MHD_socket_get_error_ ();
1983
1984 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1985 continue;
1986#ifdef HAVE_MESSAGES
1987 MHD_DLOG (con->daemon,
1988 _ ("Error during poll: `%s'\n"),
1989 MHD_socket_strerr_ (err));
1990#endif
1991 break;
1992 }
1993 urh_from_pollfd (urh,
1994 p);
1995 process_urh (urh);
1996 }
1997 }
1998 /* end POLL */
1999#endif
2000 /* end HTTPS */
2001#endif /* HTTPS_SUPPORT */
2002 /* TLS forwarding was finished. Cleanup socketpair. */
2004 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
2005 * in connection thread for a little while. */
2006}
2007
2008
2009#endif /* UPGRADE_SUPPORT */
2010
2011
2019static uint64_t
2020connection_get_wait (struct MHD_Connection *c)
2021{
2022 const uint64_t now = MHD_monotonic_msec_counter ();
2023 const uint64_t since_actv = now - c->last_activity;
2024 const uint64_t timeout = c->connection_timeout_ms;
2025 uint64_t mseconds_left;
2026
2027 mhd_assert (0 != timeout);
2028 /* Keep the next lines in sync with #connection_check_timedout() to avoid
2029 * undesired side-effects like busy-waiting. */
2030 if (timeout < since_actv)
2031 {
2032 if (UINT64_MAX / 2 < since_actv)
2033 {
2034 const uint64_t jump_back = c->last_activity - now;
2035 /* Very unlikely that it is more than quarter-million years pause.
2036 * More likely that system clock jumps back. */
2037 if (5000 >= jump_back)
2038 { /* Jump back is less than 5 seconds, try to recover. */
2039 return 100; /* Set wait time to 0.1 seconds */
2040 }
2041 /* Too large jump back */
2042 }
2043 return 0; /* Connection has timed out */
2044 }
2045 else if (since_actv == timeout)
2046 {
2047 /* Exact match for timeout and time from last activity.
2048 * Maybe this is just a precise match or this happens because the timer
2049 * resolution is too low.
2050 * Set wait time to 0.1 seconds to avoid busy-waiting with low
2051 * timer resolution as connection is not timed-out yet. */
2052 return 100;
2053 }
2054 mseconds_left = timeout - since_actv;
2055
2056 return mseconds_left;
2057}
2058
2059
2074static void
2075resume_connection_own_thread_ (struct MHD_Connection *connection)
2076{
2077 struct MHD_Daemon *const daemon = connection->daemon;
2078
2080 mhd_assert (! MHD_D_IS_USING_EPOLL_ (daemon));
2081#ifdef UPGRADE_SUPPORT
2082 mhd_assert (NULL == connection->urh);
2083#endif /* UPGRADE_SUPPORT */
2084#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2085 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2086#endif
2087 mhd_assert (connection->suspended);
2088 mhd_assert (connection->resuming);
2091 connection);
2092 connection->suspended = false;
2094 daemon->connections_tail,
2095 connection);
2096 connection->resuming = false;
2097#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2098 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2099#endif
2100 /* Drop the notification that led here, as well as any notification
2101 left over from a resume that was undone by a suspend before this
2102 thread got to see it. */
2103 MHD_itc_clear_ (connection->resume_itc);
2104}
2105
2106
2114static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
2115thread_main_handle_connection (void *data)
2116{
2117 struct MHD_Connection *con = data;
2118 struct MHD_Daemon *daemon = con->daemon;
2119 int num_ready;
2120 fd_set rs;
2121 fd_set ws;
2122 fd_set es;
2123 MHD_socket maxsock;
2124#ifdef WINDOWS
2125#ifdef HAVE_POLL
2126 unsigned int extra_slot;
2127#endif /* HAVE_POLL */
2128#define EXTRA_SLOTS 1
2129#else /* !WINDOWS */
2130#define EXTRA_SLOTS 0
2131#endif /* !WINDOWS */
2132#ifdef HAVE_POLL
2133 struct pollfd p[1 + EXTRA_SLOTS];
2134#endif
2135#undef EXTRA_SLOTS
2136#ifdef HAVE_POLL
2137 const bool use_poll = MHD_D_IS_USING_POLL_ (daemon);
2138#else /* ! HAVE_POLL */
2139 const bool use_poll = 0;
2140#endif /* ! HAVE_POLL */
2141 bool was_suspended = false;
2143
2144 while ( (! daemon->shutdown) &&
2145 (MHD_CONNECTION_CLOSED != con->state) )
2146 {
2147 bool use_zero_timeout;
2148#ifdef UPGRADE_SUPPORT
2149 struct MHD_UpgradeResponseHandle *const urh = con->urh;
2150#else /* ! UPGRADE_SUPPORT */
2151 static const void *const urh = NULL;
2152#endif /* ! UPGRADE_SUPPORT */
2153
2154 if ( (con->suspended) &&
2155 (NULL == urh) )
2156 {
2157 /* Connection was suspended, wait for resume. */
2158 was_suspended = true;
2159 if (con->resuming)
2160 {
2161 /* The application resumed this connection. Complete the resume
2162 right here: this thread is the only one that handles this
2163 connection, and doing it here is what keeps the wake-up below
2164 free of lost-notification races. */
2165 resume_connection_own_thread_ (con);
2166 continue;
2167 }
2168 mhd_assert (MHD_ITC_IS_VALID_ (con->resume_itc));
2169 if (! use_poll)
2170 {
2171 FD_ZERO (&rs);
2172 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (con->resume_itc),
2173 &rs,
2174 NULL,
2175 FD_SETSIZE))
2176 {
2177 #ifdef HAVE_MESSAGES
2178 MHD_DLOG (con->daemon,
2179 _ ("Failed to add FD to fd_set.\n"));
2180 #endif
2181 goto exit;
2182 }
2183 if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (con->resume_itc) + 1,
2184 &rs,
2185 NULL,
2186 NULL,
2187 NULL))
2188 {
2189 const int err = MHD_socket_get_error_ ();
2190
2191 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2192 continue;
2193#ifdef HAVE_MESSAGES
2194 MHD_DLOG (con->daemon,
2195 _ ("Error during select (%d): `%s'\n"),
2196 err,
2197 MHD_socket_strerr_ (err));
2198#endif
2199 break;
2200 }
2201 }
2202#ifdef HAVE_POLL
2203 else /* use_poll */
2204 {
2205 p[0].events = POLLIN;
2206 p[0].fd = MHD_itc_r_fd_ (con->resume_itc);
2207 p[0].revents = 0;
2208 if (0 > MHD_sys_poll_ (p,
2209 1,
2210 -1))
2211 {
2213 continue;
2214#ifdef HAVE_MESSAGES
2215 MHD_DLOG (con->daemon,
2216 _ ("Error during poll: `%s'\n"),
2218#endif
2219 break;
2220 }
2221 }
2222#endif /* HAVE_POLL */
2223 MHD_itc_clear_ (con->resume_itc);
2224 continue; /* Check again for resume. */
2225 } /* End of "suspended" branch. */
2226
2227 if (was_suspended)
2228 {
2229 MHD_update_last_activity_ (con); /* Reset timeout timer. */
2230 /* Process response queued during suspend and update states. */
2232 was_suspended = false;
2233 }
2234
2235 use_zero_timeout =
2237#ifdef HTTPS_SUPPORT
2238 || ( (con->tls_read_ready) &&
2240#endif /* HTTPS_SUPPORT */
2241 );
2242 if (! use_poll)
2243 {
2244 /* use select */
2245 bool err_state = false;
2246 struct timeval tv;
2247 struct timeval *tvp;
2248 if (use_zero_timeout)
2249 {
2250 tv.tv_sec = 0;
2251 tv.tv_usec = 0;
2252 tvp = &tv;
2253 }
2254 else if (con->connection_timeout_ms > 0)
2255 {
2256 const uint64_t mseconds_left = connection_get_wait (con);
2257#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
2258 if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
2259 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
2260 else
2261#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
2262 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
2263
2264 tv.tv_usec = ((uint16_t) (mseconds_left % 1000)) * ((int32_t) 1000);
2265 tvp = &tv;
2266 }
2267 else
2268 tvp = NULL;
2269
2270 FD_ZERO (&rs);
2271 FD_ZERO (&ws);
2272 FD_ZERO (&es);
2273 maxsock = MHD_INVALID_SOCKET;
2274 switch (con->event_loop_info)
2275 {
2278 if (! MHD_add_to_fd_set_ (con->socket_fd,
2279 &rs,
2280 &maxsock,
2281 FD_SETSIZE))
2282 err_state = true;
2283 break;
2285 if (! MHD_add_to_fd_set_ (con->socket_fd,
2286 &ws,
2287 &maxsock,
2288 FD_SETSIZE))
2289 err_state = true;
2290 break;
2292 if (! MHD_add_to_fd_set_ (con->socket_fd,
2293 &es,
2294 &maxsock,
2295 FD_SETSIZE))
2296 err_state = true;
2297 break;
2299 /* how did we get here!? */
2300 goto exit;
2301 }
2302#ifdef WINDOWS
2303 if (MHD_ITC_IS_VALID_ (daemon->itc) )
2304 {
2305 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2306 &rs,
2307 &maxsock,
2308 FD_SETSIZE))
2309 err_state = 1;
2310 }
2311#endif
2312 if (err_state)
2313 {
2314#ifdef HAVE_MESSAGES
2315 MHD_DLOG (con->daemon,
2316 _ ("Failed to add FD to fd_set.\n"));
2317#endif
2318 goto exit;
2319 }
2320
2321 num_ready = MHD_SYS_select_ (maxsock + 1,
2322 &rs,
2323 &ws,
2324 &es,
2325 tvp);
2326 if (num_ready < 0)
2327 {
2328 const int err = MHD_socket_get_error_ ();
2329
2330 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2331 continue;
2332#ifdef HAVE_MESSAGES
2333 MHD_DLOG (con->daemon,
2334 _ ("Error during select (%d): `%s'\n"),
2335 err,
2336 MHD_socket_strerr_ (err));
2337#endif
2338 break;
2339 }
2340#ifdef WINDOWS
2341 /* Clear ITC before other processing so additional
2342 * signals will trigger select() again */
2343 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2344 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2345 &rs)) )
2346 MHD_itc_clear_ (daemon->itc);
2347#endif
2348 if (MHD_NO ==
2349 call_handlers (con,
2350 FD_ISSET (con->socket_fd,
2351 &rs),
2352 FD_ISSET (con->socket_fd,
2353 &ws),
2354 FD_ISSET (con->socket_fd,
2355 &es)) )
2356 goto exit;
2357 }
2358#ifdef HAVE_POLL
2359 else
2360 {
2361 int timeout_val;
2362 /* use poll */
2363 if (use_zero_timeout)
2364 timeout_val = 0;
2365 else if (con->connection_timeout_ms > 0)
2366 {
2367 const uint64_t mseconds_left = connection_get_wait (con);
2368#if SIZEOF_UINT64_T >= SIZEOF_INT
2369 if (mseconds_left >= INT_MAX)
2370 timeout_val = INT_MAX;
2371 else
2372#endif /* SIZEOF_UINT64_T >= SIZEOF_INT */
2373 timeout_val = (int) mseconds_left;
2374 }
2375 else
2376 timeout_val = -1;
2377 memset (&p,
2378 0,
2379 sizeof (p));
2380 p[0].fd = con->socket_fd;
2381 switch (con->event_loop_info)
2382 {
2385 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2386 break;
2388 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2389 break;
2391 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2392 break;
2394 /* how did we get here!? */
2395 goto exit;
2396 }
2397#ifdef WINDOWS
2398 extra_slot = 0;
2399 if (MHD_ITC_IS_VALID_ (daemon->itc))
2400 {
2401 p[1].events |= POLLIN;
2402 p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2403 p[1].revents = 0;
2404 extra_slot = 1;
2405 }
2406#endif
2407 if (MHD_sys_poll_ (p,
2408#ifdef WINDOWS
2409 1 + extra_slot,
2410#else
2411 1,
2412#endif
2413 timeout_val) < 0)
2414 {
2416 continue;
2417#ifdef HAVE_MESSAGES
2418 MHD_DLOG (con->daemon,
2419 _ ("Error during poll: `%s'\n"),
2421#endif
2422 break;
2423 }
2424#ifdef WINDOWS
2425 /* Clear ITC before other processing so additional
2426 * signals will trigger poll() again */
2427 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2428 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2429 MHD_itc_clear_ (daemon->itc);
2430#endif
2431 if (MHD_NO ==
2432 call_handlers (con,
2433 (0 != (p[0].revents & POLLIN)),
2434 (0 != (p[0].revents & POLLOUT)),
2435 (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC)) ))
2436 goto exit;
2437 }
2438#endif
2439#ifdef UPGRADE_SUPPORT
2440 if (MHD_CONNECTION_UPGRADE == con->state)
2441 {
2442 /* Normal HTTP processing is finished,
2443 * notify application. */
2444 if ( (NULL != daemon->notify_completed) &&
2445 (con->rq.client_aware) )
2446 daemon->notify_completed (daemon->notify_completed_cls,
2447 con,
2448 &con->rq.client_context,
2450 con->rq.client_aware = false;
2451
2452 thread_main_connection_upgrade (con);
2453 /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2454
2455 /* "Upgraded" data will not be used in this thread from this point. */
2456 con->urh->clean_ready = true;
2457 /* If 'urh->was_closed' set to true, connection will be
2458 * moved immediately to cleanup list. Otherwise connection
2459 * will stay in suspended list until 'urh' will be marked
2460 * with 'was_closed' by application. */
2462
2463 /* skip usual clean up */
2464 return (MHD_THRD_RTRN_TYPE_) 0;
2465 }
2466#endif /* UPGRADE_SUPPORT */
2467 }
2468#if _MHD_DEBUG_CLOSE
2469#ifdef HAVE_MESSAGES
2470 MHD_DLOG (con->daemon,
2471 _ ("Processing thread terminating. Closing connection.\n"));
2472#endif
2473#endif
2474 if (MHD_CONNECTION_CLOSED != con->state)
2476 (daemon->shutdown) ?
2480exit:
2481 if (NULL != con->rp.response)
2482 {
2484 con->rp.response = NULL;
2485 }
2486
2487 if (MHD_INVALID_SOCKET != con->socket_fd)
2488 {
2489 shutdown (con->socket_fd,
2490 SHUT_WR);
2491 /* 'socket_fd' can be used in other thread to signal shutdown.
2492 * To avoid data races, do not close socket here. Daemon will
2493 * use more connections only after cleanup anyway. */
2494 }
2495 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2496 (! MHD_itc_activate_ (daemon->itc, "t")) )
2497 {
2498#ifdef HAVE_MESSAGES
2499 MHD_DLOG (daemon,
2500 _ ("Failed to signal thread termination via inter-thread " \
2501 "communication channel.\n"));
2502#endif
2503 }
2504 return (MHD_THRD_RTRN_TYPE_) 0;
2505}
2506
2507
2508#endif
2509
2510
2518static void
2519MHD_cleanup_connections (struct MHD_Daemon *daemon);
2520
2521#if defined(HTTPS_SUPPORT)
2522#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2523 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2524 ! defined(MHD_socket_nosignal_) && \
2525 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2531#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2532#endif /* MHD_SEND_SPIPE_SUPPRESS_NEEDED &&
2533 MHD_SEND_SPIPE_SUPPRESS_POSSIBLE &&
2534 ! MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) &&
2535 MSG_NOSIGNAL */
2536
2537#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2542static ssize_t
2543MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2544 const void *data,
2545 size_t data_size)
2546{
2547#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2548 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2549 data_size = MHD_SCKT_SEND_MAX_SIZE_;
2550#endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2551 return MHD_send_ ((MHD_socket) (intptr_t) (trnsp), data, data_size);
2552}
2553
2554
2555#endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2556
2557
2566#define MHD_PSK_MIN_SIZE 16
2567
2576static int
2577psk_gnutls_adapter (gnutls_session_t session,
2578 const char *username,
2579 gnutls_datum_t *key)
2580{
2581 struct MHD_Connection *connection;
2582 struct MHD_Daemon *daemon;
2583#if GNUTLS_VERSION_MAJOR >= 3
2584 void *app_psk;
2585 size_t app_psk_size;
2586#endif /* GNUTLS_VERSION_MAJOR >= 3 */
2587
2588 connection = gnutls_session_get_ptr (session);
2589 if (NULL == connection)
2590 {
2591#ifdef HAVE_MESSAGES
2592 /* Cannot use our logger, we don't even have "daemon" */
2593 MHD_PANIC (_ ("Internal server error. This should be impossible.\n"));
2594#endif
2595 return -1;
2596 }
2597 daemon = connection->daemon;
2598#if GNUTLS_VERSION_MAJOR >= 3
2599 if (NULL == daemon->cred_callback)
2600 {
2601#ifdef HAVE_MESSAGES
2602 MHD_DLOG (daemon,
2603 _ ("PSK not supported by this server.\n"));
2604#endif
2605 return -1;
2606 }
2607 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2608 connection,
2609 username,
2610 &app_psk,
2611 &app_psk_size))
2612 return -1;
2613 if (MHD_PSK_MIN_SIZE > app_psk_size)
2614 {
2615#ifdef HAVE_MESSAGES
2616 MHD_DLOG (daemon,
2617 _ ("PSK authentication failed: PSK too short.\n"));
2618#endif
2619 free (app_psk);
2620 return -1;
2621 }
2622 if (UINT_MAX < app_psk_size)
2623 {
2624#ifdef HAVE_MESSAGES
2625 MHD_DLOG (daemon,
2626 _ ("PSK authentication failed: PSK too long.\n"));
2627#endif
2628 free (app_psk);
2629 return -1;
2630 }
2631 /* @a app_psk_size is at least MHD_PSK_MIN_SIZE here, so this is never
2632 gnutls_malloc(0) -- whose result is implementation defined and would
2633 be reported below as an allocation failure. */
2634 if (NULL == (key->data = gnutls_malloc (app_psk_size)))
2635 {
2636#ifdef HAVE_MESSAGES
2637 MHD_DLOG (daemon,
2638 _ ("PSK authentication failed: gnutls_malloc failed to " \
2639 "allocate memory.\n"));
2640#endif
2641 free (app_psk);
2642 return -1;
2643 }
2644 key->size = (unsigned int) app_psk_size;
2645 memcpy (key->data,
2646 app_psk,
2647 app_psk_size);
2648 free (app_psk);
2649 return 0;
2650#else
2651 (void) username; (void) key; /* Mute compiler warning */
2652#ifdef HAVE_MESSAGES
2653 MHD_DLOG (daemon,
2654 _ ("PSK not supported by this server.\n"));
2655#endif
2656 return -1;
2657#endif
2658}
2659
2660
2661#endif /* HTTPS_SUPPORT */
2662
2663
2686static struct MHD_Connection *
2688 MHD_socket client_socket,
2689 const struct sockaddr_storage *addr,
2690 socklen_t addrlen,
2691 bool external_add,
2692 bool non_blck,
2693 bool sk_spipe_supprs,
2694 enum MHD_tristate sk_is_nonip)
2695{
2696 struct MHD_Connection *connection;
2697 int eno = 0;
2698
2699#ifdef HAVE_MESSAGES
2700#if _MHD_DEBUG_CONNECT
2701 MHD_DLOG (daemon,
2702 _ ("Accepted connection on socket %d.\n"),
2703 client_socket);
2704#endif
2705#endif
2708 addr,
2709 addrlen)) )
2710 {
2711 /* above connection limit - reject */
2712#ifdef HAVE_MESSAGES
2713 MHD_DLOG (daemon,
2714 _ ("Server reached connection limit. " \
2715 "Closing inbound connection.\n"));
2716#endif
2717 MHD_socket_close_chk_ (client_socket);
2718#if defined(ENFILE) && (ENFILE + 0 != 0)
2719 errno = ENFILE;
2720#endif
2721 return NULL;
2722 }
2723
2724 /* apply connection acceptance policy if present */
2725 if ( (NULL != daemon->apc) &&
2727 (const struct sockaddr *) addr,
2728 addrlen)) )
2729 {
2730#if _MHD_DEBUG_CLOSE
2731#ifdef HAVE_MESSAGES
2732 MHD_DLOG (daemon,
2733 _ ("Connection rejected by application. Closing connection.\n"));
2734#endif
2735#endif
2736 MHD_socket_close_chk_ (client_socket);
2738 addr,
2739 addrlen);
2740#if defined(EACCESS) && (EACCESS + 0 != 0)
2741 errno = EACCESS;
2742#endif
2743 return NULL;
2744 }
2745
2746 if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2747 {
2748 eno = errno;
2749#ifdef HAVE_MESSAGES
2750 MHD_DLOG (daemon,
2751 _ ("Error allocating memory: %s\n"),
2752 MHD_strerror_ (errno));
2753#endif
2754 MHD_socket_close_chk_ (client_socket);
2756 addr,
2757 addrlen);
2758 errno = eno;
2759 return NULL;
2760 }
2761
2762 if (! external_add)
2763 {
2764 connection->sk_corked = _MHD_OFF;
2765 connection->sk_nodelay = _MHD_OFF;
2766 }
2767 else
2768 {
2769 connection->sk_corked = _MHD_UNKNOWN;
2770 connection->sk_nodelay = _MHD_UNKNOWN;
2771 }
2772
2773 if (0 < addrlen)
2774 {
2775 if (NULL == (connection->addr = malloc ((size_t) addrlen)))
2776 {
2777 eno = errno;
2778#ifdef HAVE_MESSAGES
2779 MHD_DLOG (daemon,
2780 _ ("Error allocating memory: %s\n"),
2781 MHD_strerror_ (errno));
2782#endif
2783 MHD_socket_close_chk_ (client_socket);
2785 addr,
2786 addrlen);
2787 free (connection);
2788 errno = eno;
2789 return NULL;
2790 }
2791 memcpy (connection->addr,
2792 addr,
2793 (size_t) addrlen);
2794 }
2795 else
2796 connection->addr = NULL;
2797 connection->addr_len = addrlen;
2798 connection->socket_fd = client_socket;
2799 connection->sk_nonblck = non_blck;
2800 connection->is_nonip = sk_is_nonip;
2801 connection->sk_spipe_suppress = sk_spipe_supprs;
2802#ifdef MHD_USE_THREADS
2803 MHD_thread_handle_ID_set_invalid_ (&connection->tid);
2804#endif /* MHD_USE_THREADS */
2805 connection->daemon = daemon;
2808 if (0 != connection->connection_timeout_ms)
2810
2811 MHD_itc_set_invalid_ (connection->resume_itc);
2814 (! MHD_itc_init_ (connection->resume_itc)) )
2815 {
2816 eno = errno;
2817#ifdef HAVE_MESSAGES
2818 MHD_DLOG (daemon,
2819 _ ("Failed to create inter-thread communication channel " \
2820 "for the connection: %s\n"),
2821 MHD_itc_last_strerror_ ());
2822#endif
2823 MHD_socket_close_chk_ (client_socket);
2825 addr,
2826 addrlen);
2827 if (NULL != connection->addr)
2828 free (connection->addr);
2829 free (connection);
2830 errno = eno;
2831 return NULL;
2832 }
2833
2834 if (0 == (daemon->options & MHD_USE_TLS))
2835 {
2836 /* set default connection handlers */
2837 MHD_set_http_callbacks_ (connection);
2838 }
2839 else
2840 {
2841#ifdef HTTPS_SUPPORT
2842#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2843 gnutls_init_flags_t
2844#else
2845 unsigned int
2846#endif
2847 flags;
2848
2849 flags = GNUTLS_SERVER;
2850#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2851 flags |= GNUTLS_NO_SIGNAL;
2852#endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2853#if GNUTLS_VERSION_MAJOR >= 3
2854 flags |= GNUTLS_NONBLOCK;
2855#endif /* GNUTLS_VERSION_MAJOR >= 3*/
2856#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2858 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2859#endif
2860#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2862 flags |= GNUTLS_ENABLE_EARLY_DATA;
2863#endif
2864 connection->tls_state = MHD_TLS_CONN_INIT;
2865 MHD_set_https_callbacks (connection);
2866 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2867 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2868 daemon->priority_cache)))
2869 {
2870 if (NULL != connection->tls_session)
2871 gnutls_deinit (connection->tls_session);
2872 MHD_socket_close_chk_ (client_socket);
2874 addr,
2875 addrlen);
2876 if (NULL != connection->addr)
2877 free (connection->addr);
2878 free (connection);
2879#ifdef HAVE_MESSAGES
2880 MHD_DLOG (daemon,
2881 _ ("Failed to initialise TLS session.\n"));
2882#endif
2883#if defined(EPROTO) && (EPROTO + 0 != 0)
2884 errno = EPROTO;
2885#endif
2886 return NULL;
2887 }
2888#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2889 if (! daemon->disable_alpn)
2890 {
2891 static const char prt1[] = "http/1.1"; /* Registered code for HTTP/1.1 */
2892 static const char prt2[] = "http/1.0"; /* Registered code for HTTP/1.0 */
2893 static const gnutls_datum_t prts[2] =
2894 { {_MHD_DROP_CONST (prt1), MHD_STATICSTR_LEN_ (prt1)},
2895 {_MHD_DROP_CONST (prt2), MHD_STATICSTR_LEN_ (prt2)} };
2896
2897 if (GNUTLS_E_SUCCESS !=
2898 gnutls_alpn_set_protocols (connection->tls_session,
2899 prts,
2900 sizeof(prts) / sizeof(prts[0]),
2901 0 /* | GNUTLS_ALPN_SERVER_PRECEDENCE */))
2902 {
2903#ifdef HAVE_MESSAGES
2904 MHD_DLOG (daemon,
2905 _ ("Failed to set ALPN protocols.\n"));
2906#else /* ! HAVE_MESSAGES */
2907 (void) 0; /* Mute compiler warning */
2908#endif /* ! HAVE_MESSAGES */
2909 }
2910 }
2911#endif /* GNUTLS_VERSION_NUMBER >= 0x030200 */
2912 gnutls_session_set_ptr (connection->tls_session,
2913 connection);
2914 switch (daemon->cred_type)
2915 {
2916 /* set needed credentials for certificate authentication. */
2917 case GNUTLS_CRD_CERTIFICATE:
2918 gnutls_credentials_set (connection->tls_session,
2919 GNUTLS_CRD_CERTIFICATE,
2920 daemon->x509_cred);
2921 break;
2922 case GNUTLS_CRD_PSK:
2923 gnutls_credentials_set (connection->tls_session,
2924 GNUTLS_CRD_PSK,
2925 daemon->psk_cred);
2926 gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2927 &psk_gnutls_adapter);
2928 break;
2929 case GNUTLS_CRD_ANON:
2930 case GNUTLS_CRD_SRP:
2931 case GNUTLS_CRD_IA:
2932 default:
2933#ifdef HAVE_MESSAGES
2934 MHD_DLOG (daemon,
2935 _ ("Failed to setup TLS credentials: " \
2936 "unknown credential type %d.\n"),
2937 daemon->cred_type);
2938#endif
2939 gnutls_deinit (connection->tls_session);
2940 MHD_socket_close_chk_ (client_socket);
2942 addr,
2943 addrlen);
2944 if (NULL != connection->addr)
2945 free (connection->addr);
2946 free (connection);
2947 MHD_PANIC (_ ("Unknown credential type.\n"));
2948#if defined(EINVAL) && (EINVAL + 0 != 0)
2949 errno = EINVAL;
2950#endif
2951 return NULL;
2952 }
2953#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2954 gnutls_transport_set_int (connection->tls_session,
2955 (int) (client_socket));
2956#else /* GnuTLS before 3.1.9 or Win x64 */
2957 gnutls_transport_set_ptr (connection->tls_session,
2958 (gnutls_transport_ptr_t) \
2959 (intptr_t) client_socket);
2960#endif /* GnuTLS before 3.1.9 or Win x64 */
2961#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2962 gnutls_transport_set_push_function (connection->tls_session,
2963 MHD_tls_push_func_);
2964#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2965 if (daemon->https_mem_trust)
2966 gnutls_certificate_server_set_request (connection->tls_session,
2967 GNUTLS_CERT_REQUEST);
2968#else /* ! HTTPS_SUPPORT */
2969 MHD_socket_close_chk_ (client_socket);
2971 addr,
2972 addrlen);
2973 free (connection->addr);
2974 free (connection);
2975 MHD_PANIC (_ ("TLS connection on non-TLS daemon.\n"));
2976#if 0
2977 /* Unreachable code */
2978 eno = EINVAL;
2979 return NULL;
2980#endif
2981#endif /* ! HTTPS_SUPPORT */
2982 }
2983
2984 return connection;
2985}
2986
2987
2988#ifdef MHD_USE_THREADS
2994static void
2995new_connection_close_ (struct MHD_Daemon *daemon,
2996 struct MHD_Connection *connection)
2997{
2998 mhd_assert (connection->daemon == daemon);
2999 mhd_assert (! connection->in_cleanup);
3000 mhd_assert (NULL == connection->next);
3001 mhd_assert (NULL == connection->nextX);
3002#ifdef EPOLL_SUPPORT
3003 mhd_assert (NULL == connection->nextE);
3004#endif /* EPOLL_SUPPORT */
3005
3006#ifdef HTTPS_SUPPORT
3007 if (NULL != connection->tls_session)
3008 {
3010 gnutls_deinit (connection->tls_session);
3011 }
3012#endif /* HTTPS_SUPPORT */
3013 MHD_socket_close_chk_ (connection->socket_fd);
3014 if (MHD_ITC_IS_VALID_ (connection->resume_itc))
3015 MHD_itc_destroy_chk_ (connection->resume_itc);
3017 connection->addr,
3018 connection->addr_len);
3019 if (NULL != connection->addr)
3020 free (connection->addr);
3021 free (connection);
3022}
3023
3024
3025#endif /* MHD_USE_THREADS */
3026
3027
3038static enum MHD_Result
3040 struct MHD_Connection *connection)
3041{
3042 int eno = 0;
3043
3044 mhd_assert (connection->daemon == daemon);
3045
3046#ifdef MHD_USE_THREADS
3047 /* Function manipulate connection and timeout DL-lists,
3048 * must be called only within daemon thread. */
3051 mhd_assert (NULL == daemon->worker_pool);
3052#endif /* MHD_USE_THREADS */
3053
3054 /* Allocate memory pool in the processing thread so
3055 * intensively used memory area is allocated in "good"
3056 * (for the thread) memory region. It is important with
3057 * NUMA and/or complex cache hierarchy. */
3058 connection->pool = MHD_pool_create (daemon->pool_size);
3059 if (NULL == connection->pool)
3060 { /* 'pool' creation failed */
3061#ifdef HAVE_MESSAGES
3062 MHD_DLOG (daemon,
3063 _ ("Error allocating memory: %s\n"),
3064 MHD_strerror_ (errno));
3065#endif
3066#if defined(ENOMEM) && (ENOMEM + 0 != 0)
3067 eno = ENOMEM;
3068#endif
3069 (void) 0; /* Mute possible compiler warning */
3070 }
3071 else
3072 { /* 'pool' creation succeed */
3073 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3074 /* Firm check under lock. */
3076 { /* Connections limit */
3077 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3078#ifdef HAVE_MESSAGES
3079 MHD_DLOG (daemon,
3080 _ ("Server reached connection limit. "
3081 "Closing inbound connection.\n"));
3082#endif
3083#if defined(ENFILE) && (ENFILE + 0 != 0)
3084 eno = ENFILE;
3085#endif
3086 (void) 0; /* Mute possible compiler warning */
3087 }
3088 else
3089 { /* Have space for new connection */
3093 connection);
3095 {
3098 connection);
3099 }
3100 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3101
3103
3106 connection,
3107 &connection->socket_context,
3109#ifdef MHD_USE_THREADS
3111 {
3113 if (! MHD_create_named_thread_ (&connection->tid,
3114 "MHD-connection",
3115 daemon->thread_stack_size,
3116 &thread_main_handle_connection,
3117 connection))
3118 {
3119 eno = errno;
3120#ifdef HAVE_MESSAGES
3121#ifdef EAGAIN
3122 if (EAGAIN == eno)
3123 MHD_DLOG (daemon,
3124 _ ("Failed to create a new thread because it would "
3125 "have exceeded the system limit on the number of "
3126 "threads or no system resources available.\n"));
3127 else
3128#endif /* EAGAIN */
3129 MHD_DLOG (daemon,
3130 _ ("Failed to create a thread: %s\n"),
3131 MHD_strerror_ (eno));
3132#endif /* HAVE_MESSAGES */
3133 }
3134 else /* New thread has been created successfully */
3135 return MHD_YES; /* *** Function success exit point *** */
3136 }
3137 else
3138#else /* ! MHD_USE_THREADS */
3139 if (1)
3140#endif /* ! MHD_USE_THREADS */
3141 { /* No 'thread-per-connection' */
3142#ifdef MHD_USE_THREADS
3143 connection->tid = daemon->tid;
3144#endif /* MHD_USE_THREADS */
3145#ifdef EPOLL_SUPPORT
3147 {
3148 if (0 == (daemon->options & MHD_USE_TURBO))
3149 {
3150 struct epoll_event event;
3151
3152 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET | EPOLLRDHUP;
3153 event.data.ptr = connection;
3154 if (0 != epoll_ctl (daemon->epoll_fd,
3155 EPOLL_CTL_ADD,
3156 connection->socket_fd,
3157 &event))
3158 {
3159 eno = errno;
3160#ifdef HAVE_MESSAGES
3161 MHD_DLOG (daemon,
3162 _ ("Call to epoll_ctl failed: %s\n"),
3164#endif
3165 }
3166 else
3167 { /* 'socket_fd' has been added to 'epool' */
3168 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3169
3170 return MHD_YES; /* *** Function success exit point *** */
3171 }
3172 }
3173 else
3174 {
3175 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
3178 EDLL_insert (daemon->eready_head,
3179 daemon->eready_tail,
3180 connection);
3181
3182 return MHD_YES; /* *** Function success exit point *** */
3183 }
3184 }
3185 else /* No 'epoll' */
3186#endif /* EPOLL_SUPPORT */
3187 return MHD_YES; /* *** Function success exit point *** */
3188 }
3189
3190 /* ** Below is a cleanup path ** */
3191 if (NULL != daemon->notify_connection)
3193 connection,
3194 &connection->socket_context,
3196 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3197 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
3198 {
3200 daemon->normal_timeout_tail,
3201 connection);
3202 }
3204 daemon->connections_tail,
3205 connection);
3206 daemon->connections--;
3207 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3208 }
3209 MHD_pool_destroy (connection->pool);
3210 }
3211 /* Free resources allocated before the call of this functions */
3212#ifdef HTTPS_SUPPORT
3213 if (NULL != connection->tls_session)
3214 gnutls_deinit (connection->tls_session);
3215#endif /* HTTPS_SUPPORT */
3216 MHD_ip_limit_del (daemon,
3217 connection->addr,
3218 connection->addr_len);
3219 if (NULL != connection->addr)
3220 free (connection->addr);
3221 MHD_socket_close_chk_ (connection->socket_fd);
3222 free (connection);
3223 if (0 != eno)
3224 errno = eno;
3225#ifdef EINVAL
3226 else
3227 errno = EINVAL;
3228#endif /* EINVAL */
3229 return MHD_NO; /* *** Function failure exit point *** */
3230}
3231
3232
3261static enum MHD_Result
3263 MHD_socket client_socket,
3264 const struct sockaddr_storage *addr,
3265 socklen_t addrlen,
3266 bool external_add,
3267 bool non_blck,
3268 bool sk_spipe_supprs,
3269 enum MHD_tristate sk_is_nonip)
3270{
3271 struct MHD_Connection *connection;
3272
3273#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3274 /* Direct add to master daemon could never happen. */
3275 mhd_assert (NULL == daemon->worker_pool);
3276#endif
3277
3279 (! MHD_D_DOES_SCKT_FIT_FDSET_ (client_socket, daemon)) )
3280 {
3281#ifdef HAVE_MESSAGES
3282 MHD_DLOG (daemon,
3283 _ ("New connection socket descriptor (%d) is not less " \
3284 "than FD_SETSIZE (%d).\n"),
3285 (int) client_socket,
3287#endif
3288 MHD_socket_close_chk_ (client_socket);
3289#if defined(ENFILE) && (ENFILE + 0 != 0)
3290 errno = ENFILE;
3291#endif
3292 return MHD_NO;
3293 }
3294
3296 (! non_blck) )
3297 {
3298#ifdef HAVE_MESSAGES
3299 MHD_DLOG (daemon,
3300 _ ("Epoll mode supports only non-blocking sockets\n"));
3301#endif
3302 MHD_socket_close_chk_ (client_socket);
3303#if defined(EINVAL) && (EINVAL + 0 != 0)
3304 errno = EINVAL;
3305#endif
3306 return MHD_NO;
3307 }
3308
3309 connection = new_connection_prepare_ (daemon,
3310 client_socket,
3311 addr, addrlen,
3312 external_add,
3313 non_blck,
3314 sk_spipe_supprs,
3315 sk_is_nonip);
3316 if (NULL == connection)
3317 return MHD_NO;
3318
3319 if ((external_add) &&
3321 {
3322 /* Connection is added externally and MHD is thread safe mode. */
3323 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3326 connection);
3327 daemon->have_new = true;
3328 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3329
3330 /* The rest of connection processing must be handled in
3331 * the daemon thread. */
3332 if ((MHD_ITC_IS_VALID_ (daemon->itc)) &&
3333 (! MHD_itc_activate_ (daemon->itc, "n")))
3334 {
3335#ifdef HAVE_MESSAGES
3336 MHD_DLOG (daemon,
3337 _ ("Failed to signal new connection via inter-thread " \
3338 "communication channel.\n"));
3339#endif
3340 }
3341 return MHD_YES;
3342 }
3343
3344 return new_connection_process_ (daemon, connection);
3345}
3346
3347
3348static void
3350{
3351 struct MHD_Connection *local_head;
3352 struct MHD_Connection *local_tail;
3355
3356 /* Detach DL-list of new connections from the daemon for
3357 * following local processing. */
3358 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3360 local_head = daemon->new_connections_head;
3361 local_tail = daemon->new_connections_tail;
3364 daemon->have_new = false;
3365 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3366 (void) local_head; /* Mute compiler warning */
3367
3368 /* Process new connections in FIFO order. */
3369 do
3370 {
3371 struct MHD_Connection *c;
3372
3373 c = local_tail;
3374 DLL_remove (local_head,
3375 local_tail,
3376 c);
3377 mhd_assert (daemon == c->daemon);
3379 {
3380#ifdef HAVE_MESSAGES
3381 MHD_DLOG (daemon,
3382 _ ("Failed to start serving new connection.\n"));
3383#endif
3384 (void) 0;
3385 }
3386 } while (NULL != local_tail);
3387
3388}
3389
3390
3400void
3402{
3403 struct MHD_Daemon *daemon = connection->daemon;
3404 mhd_assert (NULL == daemon->worker_pool);
3405
3406#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3407 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
3410 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3411#endif
3412 if (connection->resuming)
3413 {
3414 /* suspending again while we didn't even complete resuming yet */
3415 connection->resuming = false;
3416#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3417 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3418#endif
3419 return;
3420 }
3421 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
3422 {
3423 if (connection->connection_timeout_ms == daemon->connection_timeout_ms)
3425 daemon->normal_timeout_tail,
3426 connection);
3427 else
3429 daemon->manual_timeout_tail,
3430 connection);
3431 }
3433 daemon->connections_tail,
3434 connection);
3435 mhd_assert (! connection->suspended);
3438 connection);
3439 connection->suspended = true;
3440#ifdef EPOLL_SUPPORT
3441 if (MHD_D_IS_USING_EPOLL_ (daemon))
3442 {
3443 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3444 {
3445 EDLL_remove (daemon->eready_head,
3446 daemon->eready_tail,
3447 connection);
3448 connection->epoll_state &=
3450 }
3451 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
3452 {
3453 if (0 != epoll_ctl (daemon->epoll_fd,
3454 EPOLL_CTL_DEL,
3455 connection->socket_fd,
3456 NULL))
3457 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3458 connection->epoll_state &=
3460 }
3461 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
3462 }
3463#endif
3464#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3465 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3466#endif
3467}
3468
3469
3498_MHD_EXTERN void
3500{
3501 struct MHD_Daemon *const daemon = connection->daemon;
3502
3503#ifdef MHD_USE_THREADS
3504 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
3507#endif /* MHD_USE_THREADS */
3508
3509 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3510 MHD_PANIC (_ ("Cannot suspend connections without " \
3511 "enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3512#ifdef UPGRADE_SUPPORT
3513 if (NULL != connection->urh)
3514 {
3515#ifdef HAVE_MESSAGES
3516 MHD_DLOG (daemon,
3517 _ ("Error: connection scheduled for \"upgrade\" cannot " \
3518 "be suspended.\n"));
3519#endif /* HAVE_MESSAGES */
3520 return;
3521 }
3522#endif /* UPGRADE_SUPPORT */
3523 internal_suspend_connection_ (connection);
3524}
3525
3526
3541_MHD_EXTERN void
3543{
3544 struct MHD_Daemon *daemon = connection->daemon;
3545 bool own_thread;
3546#if defined(MHD_USE_THREADS)
3547 mhd_assert (NULL == daemon->worker_pool);
3548#endif /* MHD_USE_THREADS */
3549
3550 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3551 MHD_PANIC (_ ("Cannot resume connections without enabling " \
3552 "MHD_ALLOW_SUSPEND_RESUME!\n"));
3553#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3554 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3555#endif
3556 connection->resuming = true;
3557 /* An "upgraded" connection is resumed only to be moved to the cleanup
3558 list, which is the daemon thread's job even with a thread per
3559 connection. */
3560 own_thread = MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)
3561#ifdef UPGRADE_SUPPORT
3562 && (NULL == connection->urh)
3563#endif /* UPGRADE_SUPPORT */
3564 ;
3565 if (! own_thread)
3566 daemon->resuming = true;
3567#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3568 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3569#endif
3570 if (own_thread)
3571 {
3572 /* Wake the connection's own thread. See the description of
3573 @e resume_itc for why the daemon-wide ITC will not do. */
3574 mhd_assert (MHD_ITC_IS_VALID_ (connection->resume_itc));
3575 if (! MHD_itc_activate_ (connection->resume_itc, "r"))
3576 {
3577#ifdef HAVE_MESSAGES
3578 MHD_DLOG (daemon,
3579 _ ("Failed to signal resume via the connection's " \
3580 "inter-thread communication channel.\n"));
3581#endif
3582 }
3583 }
3584 else if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3585 (! MHD_itc_activate_ (daemon->itc, "r")) )
3586 {
3587#ifdef HAVE_MESSAGES
3588 MHD_DLOG (daemon,
3589 _ ("Failed to signal resume via inter-thread " \
3590 "communication channel.\n"));
3591#endif
3592 }
3593}
3594
3595
3596#ifdef UPGRADE_SUPPORT
3604void
3605MHD_upgraded_connection_mark_app_closed_ (struct MHD_Connection *connection)
3606{
3607 /* Cache 'daemon' here to avoid data races */
3608 struct MHD_Daemon *const daemon = connection->daemon;
3609#if defined(MHD_USE_THREADS)
3610 mhd_assert (NULL == daemon->worker_pool);
3611#endif /* MHD_USE_THREADS */
3612 mhd_assert (NULL != connection->urh);
3614
3615 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3616 connection->urh->was_closed = true;
3617 connection->resuming = true;
3618 daemon->resuming = true;
3619 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3620 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3621 (! MHD_itc_activate_ (daemon->itc, "r")) )
3622 {
3623#ifdef HAVE_MESSAGES
3624 MHD_DLOG (daemon,
3625 _ ("Failed to signal resume via " \
3626 "inter-thread communication channel.\n"));
3627#endif
3628 }
3629}
3630
3631
3632#endif /* UPGRADE_SUPPORT */
3633
3643static enum MHD_Result
3645{
3646 struct MHD_Connection *pos;
3647 struct MHD_Connection *prev = NULL;
3648 enum MHD_Result ret;
3649 const bool used_thr_p_c = (0 != (daemon->options
3651#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3652 mhd_assert (NULL == daemon->worker_pool);
3655#endif
3656
3657 ret = MHD_NO;
3658#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3659 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3660#endif
3661
3662 if (daemon->resuming)
3663 {
3665 /* During shutdown check for resuming is forced. */
3666 mhd_assert ((NULL != prev) || (daemon->shutdown) || \
3667 (0 != (daemon->options & MHD_ALLOW_UPGRADE)));
3668 }
3669
3670 daemon->resuming = false;
3671
3672 while (NULL != (pos = prev))
3673 {
3674#ifdef UPGRADE_SUPPORT
3675 struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3676#else /* ! UPGRADE_SUPPORT */
3677 static const void *const urh = NULL;
3678#endif /* ! UPGRADE_SUPPORT */
3679 prev = pos->prev;
3680 if ( (! pos->resuming)
3681#ifdef UPGRADE_SUPPORT
3682 || ( (NULL != urh) &&
3683 ( (! urh->was_closed) ||
3684 (! urh->clean_ready) ) )
3685#endif /* UPGRADE_SUPPORT */
3686 )
3687 continue;
3688 ret = MHD_YES;
3689 mhd_assert (pos->suspended);
3692 pos);
3693 pos->suspended = false;
3694 if (NULL == urh)
3695 {
3697 daemon->connections_tail,
3698 pos);
3699 if (! used_thr_p_c)
3700 {
3701 /* The states of a suspended connection are not updated, so they
3702 are stale now that it is running again. Updating them here
3703 would mean running the state machine under the cleanup mutex,
3704 which is what 0ecf4f26e4c1a4c03d66e1d04bf4cae62bd236a0 backed
3705 out of; flag the connection instead and let call_handlers()
3706 update it before it acts on @e event_loop_info. Thread-per-
3707 connection does the same for itself, in
3708 thread_main_handle_connection(). */
3709 pos->resumed = true;
3710
3711 /* Reset timeout timer on resume. */
3712 if (0 != pos->connection_timeout_ms)
3714
3715 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
3717 daemon->normal_timeout_tail,
3718 pos);
3719 else
3721 daemon->manual_timeout_tail,
3722 pos);
3723 }
3724#ifdef EPOLL_SUPPORT
3725 if (MHD_D_IS_USING_EPOLL_ (daemon))
3726 {
3727 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3728 MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3729 /* we always mark resumed connections as ready, as we
3730 might have missed the edge poll event during suspension */
3731 EDLL_insert (daemon->eready_head,
3732 daemon->eready_tail,
3733 pos);
3734 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3737 pos->epoll_state &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_SUSPENDED);
3738 }
3739#endif
3740 }
3741#ifdef UPGRADE_SUPPORT
3742 else
3743 {
3744 /* Data forwarding was finished (for TLS connections) AND
3745 * application was closed upgraded connection.
3746 * Insert connection into cleanup list. */
3747 if ( (NULL != daemon->notify_completed) &&
3748 (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) &&
3749 (pos->rq.client_aware) )
3750 {
3751 daemon->notify_completed (daemon->notify_completed_cls,
3752 pos,
3753 &pos->rq.client_context,
3755 pos->rq.client_aware = false;
3756 }
3757 DLL_insert (daemon->cleanup_head,
3758 daemon->cleanup_tail,
3759 pos);
3760 daemon->data_already_pending = true;
3761 }
3762#endif /* UPGRADE_SUPPORT */
3763 pos->resuming = false;
3764 }
3765#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3766 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3767#endif
3768 if ( (used_thr_p_c) &&
3769 (MHD_NO != ret) )
3770 { /* Wake up suspended connections. */
3771 if (! MHD_itc_activate_ (daemon->itc,
3772 "w"))
3773 {
3774#ifdef HAVE_MESSAGES
3775 MHD_DLOG (daemon,
3776 _ ("Failed to signal resume of connection via " \
3777 "inter-thread communication channel.\n"));
3778#endif
3779 }
3780 }
3781 return ret;
3782}
3783
3784
3814 MHD_socket client_socket,
3815 const struct sockaddr *addr,
3816 socklen_t addrlen)
3817{
3818 bool sk_nonbl;
3819 bool sk_spipe_supprs;
3820 struct sockaddr_storage addrstorage;
3821
3822 /* TODO: fix atomic value reading */
3823 if ((! MHD_D_IS_THREAD_SAFE_ (daemon)) &&
3824 (daemon->connection_limit <= daemon->connections))
3825 MHD_cleanup_connections (daemon);
3826
3827#ifdef HAVE_MESSAGES
3828 if (MHD_D_IS_USING_THREADS_ (daemon) &&
3829 (0 == (daemon->options & MHD_USE_ITC)))
3830 {
3831 MHD_DLOG (daemon,
3832 _ ("MHD_add_connection() has been called for daemon started"
3833 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3834 " added connection until any activity occurs in already"
3835 " added sockets.\n"));
3836 }
3837#endif /* HAVE_MESSAGES */
3838 if (0 != addrlen)
3839 {
3840 if (AF_INET == addr->sa_family)
3841 {
3842 if (sizeof(struct sockaddr_in) > (size_t) addrlen)
3843 {
3844#ifdef HAVE_MESSAGES
3845 MHD_DLOG (daemon,
3846 _ ("MHD_add_connection() has been called with "
3847 "incorrect 'addrlen' value.\n"));
3848#endif /* HAVE_MESSAGES */
3849 return MHD_NO;
3850 }
3851#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3852 if ((0 != addr->sa_len) &&
3853 (sizeof(struct sockaddr_in) > (size_t) addr->sa_len) )
3854 {
3855#ifdef HAVE_MESSAGES
3856 MHD_DLOG (daemon,
3857 _ ("MHD_add_connection() has been called with " \
3858 "non-zero value of 'sa_len' member of " \
3859 "'struct sockaddr' which does not match 'sa_family'.\n"));
3860#endif /* HAVE_MESSAGES */
3861 return MHD_NO;
3862 }
3863#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
3864 }
3865#ifdef HAVE_INET6
3866 if (AF_INET6 == addr->sa_family)
3867 {
3868 if (sizeof(struct sockaddr_in6) > (size_t) addrlen)
3869 {
3870#ifdef HAVE_MESSAGES
3871 MHD_DLOG (daemon,
3872 _ ("MHD_add_connection() has been called with "
3873 "incorrect 'addrlen' value.\n"));
3874#endif /* HAVE_MESSAGES */
3875 return MHD_NO;
3876 }
3877#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3878 if ((0 != addr->sa_len) &&
3879 (sizeof(struct sockaddr_in6) > (size_t) addr->sa_len) )
3880 {
3881#ifdef HAVE_MESSAGES
3882 MHD_DLOG (daemon,
3883 _ ("MHD_add_connection() has been called with " \
3884 "non-zero value of 'sa_len' member of " \
3885 "'struct sockaddr' which does not match 'sa_family'.\n"));
3886#endif /* HAVE_MESSAGES */
3887 return MHD_NO;
3888 }
3889#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
3890 }
3891#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3892 if ((0 != addr->sa_len) &&
3893 (addrlen > addr->sa_len))
3894 addrlen = (socklen_t) addr->sa_len; /* Use safest value */
3895#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
3896#endif /* HAVE_INET6 */
3897 }
3898
3899 if (! MHD_socket_nonblocking_ (client_socket))
3900 {
3901#ifdef HAVE_MESSAGES
3902 MHD_DLOG (daemon,
3903 _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3905#endif
3906 sk_nonbl = false;
3907 }
3908 else
3909 sk_nonbl = true;
3910
3911#ifndef MHD_WINSOCK_SOCKETS
3912 sk_spipe_supprs = false;
3913#else /* MHD_WINSOCK_SOCKETS */
3914 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3915#endif /* MHD_WINSOCK_SOCKETS */
3916#if defined(MHD_socket_nosignal_)
3917 if (! sk_spipe_supprs)
3918 sk_spipe_supprs = MHD_socket_nosignal_ (client_socket);
3919 if (! sk_spipe_supprs)
3920 {
3921#ifdef HAVE_MESSAGES
3922 MHD_DLOG (daemon,
3923 _ ("Failed to suppress SIGPIPE on new client socket: %s\n"),
3925#else /* ! HAVE_MESSAGES */
3926 (void) 0; /* Mute compiler warning */
3927#endif /* ! HAVE_MESSAGES */
3928#ifndef MSG_NOSIGNAL
3929 /* Application expects that SIGPIPE will be suppressed,
3930 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3931 if (! daemon->sigpipe_blocked)
3932 {
3933 int err = MHD_socket_get_error_ ();
3934 MHD_socket_close_ (client_socket);
3936 return MHD_NO;
3937 }
3938#endif /* MSG_NOSIGNAL */
3939 }
3940#endif /* MHD_socket_nosignal_ */
3941
3942 if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3943 (! MHD_socket_noninheritable_ (client_socket)) )
3944 {
3945#ifdef HAVE_MESSAGES
3946 MHD_DLOG (daemon,
3947 _ ("Failed to set noninheritable mode on new client socket.\n"));
3948#endif
3949 }
3950
3951 /* Copy to sockaddr_storage structure to avoid alignment problems */
3952 if (0 < addrlen)
3953 memcpy (&addrstorage, addr, (size_t) addrlen);
3954#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
3955 addrstorage.ss_len = addrlen; /* Force set the right length */
3956#endif /* HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */
3957
3958#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3959 if (NULL != daemon->worker_pool)
3960 {
3961 unsigned int i;
3962 /* have a pool, try to find a pool with capacity; we use the
3963 socket as the initial offset into the pool for load
3964 balancing */
3965 for (i = 0; i < daemon->worker_pool_size; ++i)
3966 {
3967 struct MHD_Daemon *const worker =
3968 &daemon->worker_pool[(i + (unsigned int) client_socket)
3969 % daemon->worker_pool_size];
3970 if (worker->connections < worker->connection_limit)
3971 return internal_add_connection (worker,
3972 client_socket,
3973 &addrstorage,
3974 addrlen,
3975 true,
3976 sk_nonbl,
3977 sk_spipe_supprs,
3978 _MHD_UNKNOWN);
3979 }
3980 /* all pools are at their connection limit, must refuse */
3981 MHD_socket_close_chk_ (client_socket);
3982#if defined(ENFILE) && (ENFILE + 0 != 0)
3983 errno = ENFILE;
3984#endif
3985 return MHD_NO;
3986 }
3987#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
3988
3989 return internal_add_connection (daemon,
3990 client_socket,
3991 &addrstorage,
3992 addrlen,
3993 true,
3994 sk_nonbl,
3995 sk_spipe_supprs,
3996 _MHD_UNKNOWN);
3997}
3998
3999
4014static enum MHD_Result
4016{
4017 struct sockaddr_storage addrstorage;
4018 socklen_t addrlen;
4019 MHD_socket s;
4020 MHD_socket fd;
4021 bool sk_nonbl;
4022 bool sk_spipe_supprs;
4023 bool sk_cloexec;
4024 enum MHD_tristate sk_non_ip;
4025#if defined(_DEBUG) && defined (USE_ACCEPT4)
4026 const bool use_accept4 = ! daemon->avoid_accept4;
4027#elif defined (USE_ACCEPT4)
4028 static const bool use_accept4 = true;
4029#else /* ! USE_ACCEPT4 && ! _DEBUG */
4030 static const bool use_accept4 = false;
4031#endif /* ! USE_ACCEPT4 && ! _DEBUG */
4032
4033#ifdef MHD_USE_THREADS
4034 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
4036 mhd_assert (NULL == daemon->worker_pool);
4037#endif /* MHD_USE_THREADS */
4038
4039 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
4040 (daemon->was_quiesced) )
4041 return MHD_NO;
4042
4043 addrlen = (socklen_t) sizeof (addrstorage);
4044 memset (&addrstorage,
4045 0,
4046 (size_t) addrlen);
4047#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
4048 addrstorage.ss_len = addrlen;
4049#endif /* HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */
4050
4051 /* Initialise with default values to avoid compiler warnings */
4052 sk_nonbl = false;
4053 sk_spipe_supprs = false;
4054 sk_cloexec = false;
4056
4057#ifdef USE_ACCEPT4
4058 if (use_accept4 &&
4060 (s = accept4 (fd,
4061 (struct sockaddr *) &addrstorage,
4062 &addrlen,
4065 {
4066 sk_nonbl = (SOCK_NONBLOCK_OR_ZERO != 0);
4067#ifndef MHD_WINSOCK_SOCKETS
4068 sk_spipe_supprs = (SOCK_NOSIGPIPE_OR_ZERO != 0);
4069#else /* MHD_WINSOCK_SOCKETS */
4070 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
4071#endif /* MHD_WINSOCK_SOCKETS */
4072 sk_cloexec = (SOCK_CLOEXEC_OR_ZERO != 0);
4073 }
4074#endif /* USE_ACCEPT4 */
4075#if defined(_DEBUG) || ! defined(USE_ACCEPT4)
4076 if (! use_accept4 &&
4078 (s = accept (fd,
4079 (struct sockaddr *) &addrstorage,
4080 &addrlen))))
4081 {
4082#ifdef MHD_ACCEPT_INHERIT_NONBLOCK
4083 sk_nonbl = daemon->listen_nonblk;
4084#else /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
4085 sk_nonbl = false;
4086#endif /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
4087#ifndef MHD_WINSOCK_SOCKETS
4088 sk_spipe_supprs = false;
4089#else /* MHD_WINSOCK_SOCKETS */
4090 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
4091#endif /* MHD_WINSOCK_SOCKETS */
4092 sk_cloexec = false;
4093 }
4094#endif /* _DEBUG || !USE_ACCEPT4 */
4095
4096 if (MHD_INVALID_SOCKET == s)
4097 {
4098 const int err = MHD_socket_get_error_ ();
4099
4100 /* This could be a common occurrence with multiple worker threads */
4101 if (MHD_SCKT_ERR_IS_ (err,
4103 return MHD_NO; /* can happen during shutdown */
4105 return MHD_NO; /* do not print error if client just disconnected early */
4106#ifdef HAVE_MESSAGES
4107 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
4108 MHD_DLOG (daemon,
4109 _ ("Error accepting connection: %s\n"),
4110 MHD_socket_strerr_ (err));
4111#endif
4113 {
4114 /* system/process out of resources */
4115 if (0 == daemon->connections)
4116 {
4117#ifdef HAVE_MESSAGES
4118 /* Not setting 'at_limit' flag, as there is no way it
4119 would ever be cleared. Instead trying to produce
4120 bit fat ugly warning. */
4121 MHD_DLOG (daemon,
4122 _ ("Hit process or system resource limit at FIRST " \
4123 "connection. This is really bad as there is no sane " \
4124 "way to proceed. Will try busy waiting for system " \
4125 "resources to become magically available.\n"));
4126#endif
4127 }
4128 else
4129 {
4130#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4131 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
4132#endif
4133 daemon->at_limit = true;
4134#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4135 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
4136#endif
4137#ifdef HAVE_MESSAGES
4138 MHD_DLOG (daemon,
4139 _ ("Hit process or system resource limit at %u " \
4140 "connections, temporarily suspending accept(). " \
4141 "Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
4142 (unsigned int) daemon->connections);
4143#endif
4144 }
4145 }
4146 return MHD_NO;
4147 }
4148
4149 sk_non_ip = daemon->listen_is_unix;
4150 if (0 >= addrlen)
4151 {
4152#ifdef HAVE_MESSAGES
4153 if (_MHD_NO != daemon->listen_is_unix)
4154 MHD_DLOG (daemon,
4155 _ ("Accepted socket has zero-length address. "
4156 "Processing the new socket as a socket with " \
4157 "unknown type.\n"));
4158#endif
4159 addrlen = 0;
4160 sk_non_ip = _MHD_YES; /* IP-type addresses have non-zero length */
4161 }
4162 if (((socklen_t) sizeof (addrstorage)) < addrlen)
4163 {
4164 /* Should not happen as 'sockaddr_storage' must be large enough to
4165 * store any address supported by the system. */
4166#ifdef HAVE_MESSAGES
4167 MHD_DLOG (daemon,
4168 _ ("Accepted socket address is larger than expected by " \
4169 "system headers. Processing the new socket as a socket with " \
4170 "unknown type.\n"));
4171#endif
4172 addrlen = 0;
4173 sk_non_ip = _MHD_YES; /* IP-type addresses must fit */
4174 }
4175
4176 if (! sk_nonbl && ! MHD_socket_nonblocking_ (s))
4177 {
4178#ifdef HAVE_MESSAGES
4179 MHD_DLOG (daemon,
4180 _ ("Failed to set nonblocking mode on incoming connection " \
4181 "socket: %s\n"),
4183#else /* ! HAVE_MESSAGES */
4184 (void) 0; /* Mute compiler warning */
4185#endif /* ! HAVE_MESSAGES */
4186 }
4187 else
4188 sk_nonbl = true;
4189
4190 if (! sk_cloexec && ! MHD_socket_noninheritable_ (s))
4191 {
4192#ifdef HAVE_MESSAGES
4193 MHD_DLOG (daemon,
4194 _ ("Failed to set noninheritable mode on incoming connection " \
4195 "socket.\n"));
4196#else /* ! HAVE_MESSAGES */
4197 (void) 0; /* Mute compiler warning */
4198#endif /* ! HAVE_MESSAGES */
4199 }
4200
4201#if defined(MHD_socket_nosignal_)
4202 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
4203 {
4204#ifdef HAVE_MESSAGES
4205 MHD_DLOG (daemon,
4206 _ ("Failed to suppress SIGPIPE on incoming connection " \
4207 "socket: %s\n"),
4209#else /* ! HAVE_MESSAGES */
4210 (void) 0; /* Mute compiler warning */
4211#endif /* ! HAVE_MESSAGES */
4212#ifndef MSG_NOSIGNAL
4213 /* Application expects that SIGPIPE will be suppressed,
4214 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
4215 if (! daemon->sigpipe_blocked)
4216 {
4217 (void) MHD_socket_close_ (s);
4218 return MHD_NO;
4219 }
4220#endif /* MSG_NOSIGNAL */
4221 }
4222 else
4223 sk_spipe_supprs = true;
4224#endif /* MHD_socket_nosignal_ */
4225#ifdef HAVE_MESSAGES
4226#if _MHD_DEBUG_CONNECT
4227 MHD_DLOG (daemon,
4228 _ ("Accepted connection on socket %d\n"),
4229 s);
4230#endif
4231#endif
4232 (void) internal_add_connection (daemon,
4233 s,
4234 &addrstorage,
4235 addrlen,
4236 false,
4237 sk_nonbl,
4238 sk_spipe_supprs,
4239 sk_non_ip);
4240 return MHD_YES;
4241}
4242
4243
4253static void
4255{
4256 struct MHD_Connection *pos;
4257#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4260 mhd_assert (NULL == daemon->worker_pool);
4261
4262 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
4263#endif
4264 while (NULL != (pos = daemon->cleanup_tail))
4265 {
4268 pos);
4269#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4270 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
4272 (! pos->thread_joined) &&
4273 (! MHD_thread_handle_ID_join_thread_ (pos->tid)) )
4274 MHD_PANIC (_ ("Failed to join a thread.\n"));
4275#endif
4276#ifdef UPGRADE_SUPPORT
4277 cleanup_upgraded_connection (pos);
4278#endif /* UPGRADE_SUPPORT */
4279 MHD_pool_destroy (pos->pool);
4280#ifdef HTTPS_SUPPORT
4281 if (NULL != pos->tls_session)
4282 gnutls_deinit (pos->tls_session);
4283#endif /* HTTPS_SUPPORT */
4284
4285 /* clean up the connection */
4288 pos,
4289 &pos->socket_context,
4292 pos->addr,
4293 pos->addr_len);
4294#ifdef EPOLL_SUPPORT
4296 {
4297 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4298 {
4299 EDLL_remove (daemon->eready_head,
4300 daemon->eready_tail,
4301 pos);
4302 pos->epoll_state &=
4304 }
4305 if ( (-1 != daemon->epoll_fd) &&
4306 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
4307 {
4308 /* epoll documentation suggests that closing a FD
4309 automatically removes it from the epoll set; however,
4310 this is not true as if we fail to do manually remove it,
4311 we are still seeing an event for this fd in epoll,
4312 causing grief (use-after-free...) --- at least on my
4313 system. */
4314 if (0 != epoll_ctl (daemon->epoll_fd,
4315 EPOLL_CTL_DEL,
4316 pos->socket_fd,
4317 NULL))
4318 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
4319 pos->epoll_state &=
4320 ~((enum MHD_EpollState)
4322 }
4323 }
4324#endif
4325 if (NULL != pos->rp.response)
4326 {
4328 pos->rp.response = NULL;
4329 }
4330 if (MHD_INVALID_SOCKET != pos->socket_fd)
4332 if (MHD_ITC_IS_VALID_ (pos->resume_itc))
4334 if (NULL != pos->addr)
4335 free (pos->addr);
4336 free (pos);
4337
4338#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4339 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
4340#endif
4342 daemon->at_limit = false;
4343 }
4344#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4345 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
4346#endif
4347}
4348
4349
4386 MHD_UNSIGNED_LONG_LONG *timeout)
4387{
4388 uint64_t t64;
4389 if (MHD_NO == MHD_get_timeout64 (daemon, &t64))
4390 return MHD_NO;
4391
4392#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
4393 if (ULLONG_MAX <= t64)
4394 *timeout = ULLONG_MAX;
4395 else
4396#endif /* SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG */
4397 *timeout = (MHD_UNSIGNED_LONG_LONG) t64;
4398 return MHD_YES;
4399}
4400
4401
4440 uint64_t *timeout64)
4441{
4442 uint64_t earliest_deadline;
4443 struct MHD_Connection *pos;
4444 struct MHD_Connection *earliest_tmot_conn;
4445 bool resuming;
4446
4447#ifdef MHD_USE_THREADS
4450#endif /* MHD_USE_THREADS */
4451
4453 {
4454#ifdef HAVE_MESSAGES
4455 MHD_DLOG (daemon,
4456 _ ("Illegal call to MHD_get_timeout.\n"));
4457#endif
4458 return MHD_NO;
4459 }
4460 /* Unlike the other flags checked below, which are touched only by the
4461 thread that processes this daemon's polling, 'resuming' is set by
4462 #MHD_resume_connection(), which the application may legally call from
4463 any thread. It is guarded by 'cleanup_connection_mutex' everywhere. */
4464#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4465 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
4466#endif
4468#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4469 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
4470#endif
4472 || (NULL != daemon->cleanup_head)
4473 || resuming
4474 || daemon->have_new
4475 || daemon->shutdown)
4476 {
4477 /* Some data or connection statuses already waiting to be processed. */
4478 *timeout64 = 0;
4479 return MHD_YES;
4480 }
4481#ifdef EPOLL_SUPPORT
4483 ((NULL != daemon->eready_head)
4484#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
4485 || (NULL != daemon->eready_urh_head)
4486#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
4487 ) )
4488 {
4489 /* Some connection(s) already have some data pending. */
4490 *timeout64 = 0;
4491 return MHD_YES;
4492 }
4493#endif /* EPOLL_SUPPORT */
4494
4495 earliest_tmot_conn = NULL;
4496 earliest_deadline = 0; /* mute compiler warning */
4497 /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
4499 if ( (NULL != pos) &&
4500 (0 != pos->connection_timeout_ms) )
4501 {
4502 earliest_tmot_conn = pos;
4503 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
4504 }
4505
4506 for (pos = daemon->manual_timeout_tail;
4507 NULL != pos;
4508 pos = pos->prevX)
4509 {
4510 if (0 != pos->connection_timeout_ms)
4511 {
4512 if ( (NULL == earliest_tmot_conn) ||
4513 (earliest_deadline >
4515 {
4516 earliest_tmot_conn = pos;
4517 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
4518 }
4519 }
4520 }
4521
4522 if (NULL != earliest_tmot_conn)
4523 {
4524 *timeout64 = connection_get_wait (earliest_tmot_conn);
4525 return MHD_YES;
4526 }
4527 return MHD_NO;
4528}
4529
4530
4531#if defined(HAVE_POLL) || defined(EPOLL_SUPPORT)
4570_MHD_EXTERN int64_t
4572{
4573 uint64_t utimeout;
4574 if (MHD_NO == MHD_get_timeout64 (daemon, &utimeout))
4575 return -1;
4576 if (INT64_MAX < utimeout)
4577 return INT64_MAX;
4578
4579 return (int64_t) utimeout;
4580}
4581
4582
4622_MHD_EXTERN int
4624{
4625#if SIZEOF_INT >= SIZEOF_INT64_T
4626 return MHD_get_timeout64s (daemon);
4627#else /* SIZEOF_INT < SIZEOF_INT64_T */
4628 const int64_t to64 = MHD_get_timeout64s (daemon);
4629 if (INT_MAX >= to64)
4630 return (int) to64;
4631 return INT_MAX;
4632#endif /* SIZEOF_INT < SIZEOF_INT64_T */
4633}
4634
4635
4646static int64_t
4647get_timeout_millisec_ (struct MHD_Daemon *daemon,
4648 int32_t max_timeout)
4649{
4650 uint64_t d_timeout;
4651 mhd_assert (0 <= max_timeout || -1 == max_timeout);
4652 if (0 == max_timeout)
4653 return 0;
4654
4655 if (MHD_NO == MHD_get_timeout64 (daemon, &d_timeout))
4656 return max_timeout;
4657
4658 if ((0 < max_timeout) && ((uint64_t) max_timeout < d_timeout))
4659 return max_timeout;
4660
4661 if (INT64_MAX <= d_timeout)
4662 return INT64_MAX;
4663
4664 return (int64_t) d_timeout;
4665}
4666
4667
4679static int
4680get_timeout_millisec_int (struct MHD_Daemon *daemon,
4681 int32_t max_timeout)
4682{
4683 int64_t res;
4684
4685 res = get_timeout_millisec_ (daemon, max_timeout);
4686#if SIZEOF_INT < SIZEOF_INT64_T
4687 if (INT_MAX <= res)
4688 return INT_MAX;
4689#endif /* SIZEOF_INT < SIZEOF_INT64_T */
4690 return (int) res;
4691}
4692
4693
4694#endif /* HAVE_POLL || EPOLL_SUPPORT */
4695
4707static enum MHD_Result
4709 const fd_set *read_fd_set,
4710 const fd_set *write_fd_set,
4711 const fd_set *except_fd_set,
4712 int fd_setsize)
4713{
4714 MHD_socket ds;
4715#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4716 struct MHD_UpgradeResponseHandle *urh;
4717 struct MHD_UpgradeResponseHandle *urhn;
4718#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4719
4720 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4721 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4722 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4723 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4724 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4726
4727 mhd_assert (0 < fd_setsize);
4728 (void) fd_setsize; /* Mute compiler warning */
4729#ifndef HAS_FD_SETSIZE_OVERRIDABLE
4730 (void) fd_setsize; /* Mute compiler warning */
4731 mhd_assert (((int) FD_SETSIZE) <= fd_setsize);
4732 fd_setsize = FD_SETSIZE; /* Help compiler to optimise */
4733#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4734
4735 /* Clear ITC to avoid spinning select */
4736 /* Do it before any other processing so new signals
4737 will trigger select again and will be processed */
4738 if (MHD_ITC_IS_VALID_ (daemon->itc))
4739 { /* Have ITC */
4740 bool need_to_clear_itc = true; /* ITC is always non-blocking, it is safe to clear even if ITC not activated */
4741 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (MHD_itc_r_fd_ (daemon->itc),
4742 NULL, fd_setsize))
4743 need_to_clear_itc = FD_ISSET (MHD_itc_r_fd_ (daemon->itc), \
4744 (fd_set *) _MHD_DROP_CONST (read_fd_set)); /* Skip clearing, if not needed */
4745 if (need_to_clear_itc)
4746 MHD_itc_clear_ (daemon->itc);
4747 }
4748
4749 /* Reset. New value will be set when connections are processed. */
4750 /* Note: no-op for thread-per-connection as it is always false in that mode. */
4751 daemon->data_already_pending = false;
4752
4753 /* Process externally added connection if any */
4754 if (daemon->have_new)
4756
4757 /* select connection thread handling type */
4758 ds = daemon->listen_fd;
4759 if ( (MHD_INVALID_SOCKET != ds) &&
4760 (! daemon->was_quiesced) )
4761 {
4762 bool need_to_accept;
4763 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (ds, NULL, fd_setsize))
4764 need_to_accept = FD_ISSET (ds,
4765 (fd_set *) _MHD_DROP_CONST (read_fd_set));
4766 else /* Cannot check whether new connection are pending */
4767 need_to_accept = daemon->listen_nonblk; /* Try to accept if non-blocking */
4768
4769 if (need_to_accept)
4770 (void) MHD_accept_connection (daemon);
4771 }
4772
4773 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
4774 {
4775 /* do not have a thread per connection, process all connections now */
4776 struct MHD_Connection *pos;
4777 struct MHD_Connection *prev;
4778
4779 for (pos = daemon->connections_tail; NULL != pos; pos = prev)
4780 {
4781 MHD_socket cs;
4782 bool r_ready;
4783 bool w_ready;
4784 bool has_err;
4785
4786 prev = pos->prev;
4787 cs = pos->socket_fd;
4788 if (MHD_INVALID_SOCKET == cs)
4789 continue;
4790
4791 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (cs, NULL, fd_setsize))
4792 {
4793 r_ready = FD_ISSET (cs,
4794 (fd_set *) _MHD_DROP_CONST (read_fd_set));
4795 w_ready = FD_ISSET (cs,
4796 (fd_set *) _MHD_DROP_CONST (write_fd_set));
4797 has_err = (NULL != except_fd_set) &&
4798 FD_ISSET (cs,
4799 (fd_set *) _MHD_DROP_CONST (except_fd_set));
4800 }
4801 else
4802 { /* Cannot check the real readiness */
4803 r_ready = pos->sk_nonblck;
4804 w_ready = r_ready;
4805 has_err = false;
4806 }
4807 call_handlers (pos,
4808 r_ready,
4809 w_ready,
4810 has_err);
4811 }
4812 }
4813
4814#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4815 /* handle upgraded HTTPS connections */
4816 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4817 {
4818 urhn = urh->prev;
4819 /* update urh state based on select() output */
4820 urh_from_fdset (urh,
4821 read_fd_set,
4822 write_fd_set,
4823 except_fd_set,
4824 fd_setsize);
4825 /* call generic forwarding function for passing data */
4826 process_urh (urh);
4827 /* Finished forwarding? */
4828 if ( (0 == urh->in_buffer_size) &&
4829 (0 == urh->out_buffer_size) &&
4830 (0 == urh->in_buffer_used) &&
4831 (0 == urh->out_buffer_used) )
4832 {
4833 MHD_connection_finish_forward_ (urh->connection);
4834 urh->clean_ready = true;
4835 /* Resuming will move connection to cleanup list. */
4836 MHD_resume_connection (urh->connection);
4837 }
4838 }
4839#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4841 return MHD_YES;
4842}
4843
4844
4845#undef MHD_run_from_select
4846
4880 const fd_set *read_fd_set,
4881 const fd_set *write_fd_set,
4882 const fd_set *except_fd_set,
4883 unsigned int fd_setsize)
4884{
4887 return MHD_NO;
4888 if ((NULL == read_fd_set) || (NULL == write_fd_set))
4889 return MHD_NO;
4890#ifdef HAVE_MESSAGES
4891 if (NULL == except_fd_set)
4892 {
4893 MHD_DLOG (daemon,
4894 _ ("MHD_run_from_select() called with except_fd_set "
4895 "set to NULL. Such behavior is deprecated.\n"));
4896 }
4897#endif /* HAVE_MESSAGES */
4898
4899#ifdef HAS_FD_SETSIZE_OVERRIDABLE
4900 if (0 == fd_setsize)
4901 return MHD_NO;
4902 else if (((unsigned int) INT_MAX) < fd_setsize)
4903 fd_setsize = (unsigned int) INT_MAX;
4904#ifdef HAVE_MESSAGES
4905 else if (daemon->fdset_size > ((int) fd_setsize))
4906 {
4907 if (daemon->fdset_size_set_by_app)
4908 {
4909 MHD_DLOG (daemon,
4910 _ ("%s() called with fd_setsize (%u) " \
4911 "less than value set by MHD_OPTION_APP_FD_SETSIZE (%d). " \
4912 "Some socket FDs may be not processed. " \
4913 "Use MHD_OPTION_APP_FD_SETSIZE with the correct value.\n"),
4914 "MHD_run_from_select2", fd_setsize, daemon->fdset_size);
4915 }
4916 else
4917 {
4918 MHD_DLOG (daemon,
4919 _ ("%s() called with fd_setsize (%u) " \
4920 "less than FD_SETSIZE used by MHD (%d). " \
4921 "Some socket FDs may be not processed. " \
4922 "Consider using MHD_OPTION_APP_FD_SETSIZE option.\n"),
4923 "MHD_run_from_select2", fd_setsize, daemon->fdset_size);
4924 }
4925 }
4926#endif /* HAVE_MESSAGES */
4927#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4928 if (((unsigned int) FD_SETSIZE) > fd_setsize)
4929 {
4930#ifdef HAVE_MESSAGES
4931 MHD_DLOG (daemon,
4932 _ ("%s() called with fd_setsize (%u) " \
4933 "less than fixed FD_SETSIZE value (%d) used on the " \
4934 "platform.\n"),
4935 "MHD_run_from_select2", fd_setsize, (int) FD_SETSIZE);
4936#endif /* HAVE_MESSAGES */
4937 return MHD_NO;
4938 }
4939#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4940
4942 {
4943#ifdef EPOLL_SUPPORT
4944 enum MHD_Result ret = MHD_epoll (daemon,
4945 0);
4946
4948 return ret;
4949#else /* ! EPOLL_SUPPORT */
4950 return MHD_NO;
4951#endif /* ! EPOLL_SUPPORT */
4952 }
4953
4954 /* Resuming external connections when using an extern mainloop */
4957
4959 read_fd_set,
4960 write_fd_set,
4961 except_fd_set,
4962 (int) fd_setsize);
4963}
4964
4965
4994 const fd_set *read_fd_set,
4995 const fd_set *write_fd_set,
4996 const fd_set *except_fd_set)
4997{
4999 read_fd_set,
5000 write_fd_set,
5001 except_fd_set,
5002#ifdef HAS_FD_SETSIZE_OVERRIDABLE
5003 daemon->fdset_size_set_by_app ?
5004 ((unsigned int) daemon->fdset_size) :
5005 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
5006#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
5007 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
5008#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
5009 );
5010}
5011
5012
5023static enum MHD_Result
5025 int32_t millisec)
5026{
5027 int num_ready;
5028 fd_set rs;
5029 fd_set ws;
5030 fd_set es;
5031 MHD_socket maxsock;
5032 struct timeval timeout;
5033 struct timeval *tv;
5034 int err_state;
5035 MHD_socket ls;
5036
5037 timeout.tv_sec = 0;
5038 timeout.tv_usec = 0;
5039 if (daemon->shutdown)
5040 return MHD_NO;
5041 FD_ZERO (&rs);
5042 FD_ZERO (&ws);
5043 FD_ZERO (&es);
5044 maxsock = MHD_INVALID_SOCKET;
5045 err_state = MHD_NO;
5046 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
5047 (MHD_NO != resume_suspended_connections (daemon)) &&
5048 (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) )
5049 millisec = 0;
5050
5051 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
5052 {
5053 /* single-threaded, go over everything */
5054 if (MHD_NO ==
5055 internal_get_fdset2 (daemon,
5056 &rs,
5057 &ws,
5058 &es,
5059 &maxsock,
5060 (int) FD_SETSIZE))
5061 {
5062#ifdef HAVE_MESSAGES
5063 MHD_DLOG (daemon,
5064 _ ("Could not obtain daemon fdsets.\n"));
5065#endif
5066 err_state = MHD_YES;
5067 }
5068 }
5069 else
5070 {
5071 bool itc_added;
5072 /* accept only, have one thread per connection */
5073 itc_added = false;
5074 if (MHD_ITC_IS_VALID_ (daemon->itc))
5075 {
5076 itc_added = MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
5077 &rs,
5078 &maxsock,
5079 (int) FD_SETSIZE);
5080 if (! itc_added)
5081 {
5082#ifdef HAVE_MESSAGES
5083 MHD_DLOG (daemon, _ ("Could not add control inter-thread " \
5084 "communication channel FD to fdset.\n"));
5085#endif
5086 err_state = MHD_YES;
5087 }
5088 }
5089 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5090 (! daemon->was_quiesced) )
5091 {
5092 /* Stop listening if we are at the configured connection limit */
5093 /* If we're at the connection limit, no point in really
5094 accepting new connections; however, make sure we do not miss
5095 the shutdown OR the termination of an existing connection; so
5096 only do this optimisation if we have a signaling ITC in
5097 place. */
5098 if (! itc_added ||
5099 ((daemon->connections < daemon->connection_limit) &&
5100 ! daemon->at_limit))
5101 {
5102 if (! MHD_add_to_fd_set_ (ls,
5103 &rs,
5104 &maxsock,
5105 (int) FD_SETSIZE))
5106 {
5107#ifdef HAVE_MESSAGES
5108 MHD_DLOG (daemon,
5109 _ ("Could not add listen socket to fdset.\n"));
5110#endif
5111 err_state = MHD_YES;
5112 }
5113 }
5114 }
5115 }
5116
5117 if (MHD_NO != err_state)
5118 millisec = 0;
5119 if (0 == millisec)
5120 {
5121 timeout.tv_usec = 0;
5122 timeout.tv_sec = 0;
5123 tv = &timeout;
5124 }
5125 else
5126 {
5127 uint64_t mhd_tmo;
5128 uint64_t select_tmo;
5129
5130 if ( (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) &&
5131 (MHD_NO != MHD_get_timeout64 (daemon, &mhd_tmo)) )
5132 {
5133 if ( (0 < millisec) &&
5134 (mhd_tmo > (uint64_t) millisec) )
5135 select_tmo = (uint64_t) millisec;
5136 else
5137 select_tmo = mhd_tmo;
5138 tv = &timeout; /* have timeout value */
5139 }
5140 else if (0 < millisec)
5141 {
5142 select_tmo = (uint64_t) millisec;
5143 tv = &timeout; /* have timeout value */
5144 }
5145 else
5146 {
5147 select_tmo = 0; /* Not actually used, silent compiler warning */
5148 tv = NULL;
5149 }
5150
5151 if (NULL != tv)
5152 { /* have timeout value */
5153#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
5154 if (select_tmo / 1000 > TIMEVAL_TV_SEC_MAX)
5155 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
5156 else
5157#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
5158 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (select_tmo / 1000);
5159
5160 timeout.tv_usec = ((uint16_t) (select_tmo % 1000)) * ((int32_t) 1000);
5161 }
5162 }
5163 num_ready = MHD_SYS_select_ (maxsock + 1,
5164 &rs,
5165 &ws,
5166 &es,
5167 tv);
5168 if (daemon->shutdown)
5169 return MHD_NO;
5170 if (num_ready < 0)
5171 {
5172 const int err = MHD_socket_get_error_ ();
5173 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5174 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
5175#ifdef HAVE_MESSAGES
5176 MHD_DLOG (daemon,
5177 _ ("select failed: %s\n"),
5178 MHD_socket_strerr_ (err));
5179#endif
5180 return MHD_NO;
5181 }
5182 if (MHD_NO != internal_run_from_select (daemon,
5183 &rs,
5184 &ws,
5185 &es,
5186 (int) FD_SETSIZE))
5187 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
5188 return MHD_NO;
5189}
5190
5191
5192#ifdef HAVE_POLL
5203static enum MHD_Result
5204MHD_poll_all (struct MHD_Daemon *daemon,
5205 int32_t millisec)
5206{
5207 unsigned int num_connections;
5208 struct MHD_Connection *pos;
5209 struct MHD_Connection *prev;
5210#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5211 struct MHD_UpgradeResponseHandle *urh;
5212 struct MHD_UpgradeResponseHandle *urhn;
5213#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5214
5215 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5216 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5217 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5218 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5219 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5221
5222 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
5223 (MHD_NO != resume_suspended_connections (daemon)) )
5224 millisec = 0;
5225
5226 /* count number of connections and thus determine poll set size */
5227 num_connections = 0;
5228 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
5229 num_connections++;
5230#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5231 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
5232 num_connections += 2;
5233#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5234 {
5235 unsigned int i;
5236 int timeout;
5237 unsigned int poll_server;
5238 int poll_listen;
5239 int poll_itc_idx;
5240 struct pollfd *p;
5241 MHD_socket ls;
5242
5243 p = MHD_calloc_ ((2 + (size_t) num_connections),
5244 sizeof (struct pollfd));
5245 if (NULL == p)
5246 {
5247#ifdef HAVE_MESSAGES
5248 MHD_DLOG (daemon,
5249 _ ("Error allocating memory: %s\n"),
5250 MHD_strerror_ (errno));
5251#endif
5252 return MHD_NO;
5253 }
5254 poll_server = 0;
5255 poll_listen = -1;
5256 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5257 (! daemon->was_quiesced) &&
5258 (daemon->connections < daemon->connection_limit) &&
5259 (! daemon->at_limit) )
5260 {
5261 /* only listen if we are not at the connection limit */
5262 p[poll_server].fd = ls;
5263 p[poll_server].events = POLLIN;
5264 p[poll_server].revents = 0;
5265 poll_listen = (int) poll_server;
5266 poll_server++;
5267 }
5268 poll_itc_idx = -1;
5269 if (MHD_ITC_IS_VALID_ (daemon->itc))
5270 {
5271 p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
5272 p[poll_server].events = POLLIN;
5273 p[poll_server].revents = 0;
5274 poll_itc_idx = (int) poll_server;
5275 poll_server++;
5276 }
5277
5278 timeout = get_timeout_millisec_int (daemon, millisec);
5279
5280 i = 0;
5281 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
5282 {
5283 p[poll_server + i].fd = pos->socket_fd;
5284 switch (pos->event_loop_info)
5285 {
5288 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
5289 break;
5291 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
5292 break;
5294 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
5295 break;
5297 timeout = 0; /* clean up "pos" immediately */
5298 break;
5299 }
5300 i++;
5301 }
5302#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5303 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
5304 {
5305 urh_to_pollfd (urh, &(p[poll_server + i]));
5306 i += 2;
5307 }
5308#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5309 if (0 == poll_server + num_connections)
5310 {
5311 free (p);
5312 return MHD_YES;
5313 }
5314 if (MHD_sys_poll_ (p,
5315 poll_server + num_connections,
5316 timeout) < 0)
5317 {
5318 const int err = MHD_socket_get_error_ ();
5319 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5320 {
5321 free (p);
5322 return MHD_YES;
5323 }
5324#ifdef HAVE_MESSAGES
5325 MHD_DLOG (daemon,
5326 _ ("poll failed: %s\n"),
5327 MHD_socket_strerr_ (err));
5328#endif
5329 free (p);
5330 return MHD_NO;
5331 }
5332
5333 /* handle ITC FD */
5334 /* do it before any other processing so
5335 new signals will be processed in next loop */
5336 if ( (-1 != poll_itc_idx) &&
5337 (0 != (p[poll_itc_idx].revents & POLLIN)) )
5338 MHD_itc_clear_ (daemon->itc);
5339
5340 /* handle shutdown */
5341 if (daemon->shutdown)
5342 {
5343 free (p);
5344 return MHD_NO;
5345 }
5346
5347 /* Process externally added connection if any */
5348 if (daemon->have_new)
5350
5351 /* handle 'listen' FD */
5352 if ( (-1 != poll_listen) &&
5353 (0 != (p[poll_listen].revents & POLLIN)) )
5354 (void) MHD_accept_connection (daemon);
5355
5356 /* Reset. New value will be set when connections are processed. */
5357 daemon->data_already_pending = false;
5358
5359 i = 0;
5360 prev = daemon->connections_tail;
5361 while (NULL != (pos = prev))
5362 {
5363 prev = pos->prev;
5364 /* first, sanity checks */
5365 if (i >= num_connections)
5366 break; /* connection list changed somehow, retry later ... */
5367 if (p[poll_server + i].fd != pos->socket_fd)
5368 continue; /* fd mismatch, something else happened, retry later ... */
5369 call_handlers (pos,
5370 0 != (p[poll_server + i].revents & POLLIN),
5371 0 != (p[poll_server + i].revents & POLLOUT),
5372 0 != (p[poll_server + i].revents
5373 & MHD_POLL_REVENTS_ERR_DISC));
5374 i++;
5375 }
5376#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5377 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
5378 {
5379 if (i >= num_connections)
5380 break; /* connection list changed somehow, retry later ... */
5381
5382 /* Get next connection here as connection can be removed
5383 * from 'daemon->urh_head' list. */
5384 urhn = urh->prev;
5385 /* Check for fd mismatch. FIXME: required for safety? */
5386 if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
5387 (p[poll_server + i + 1].fd != urh->mhd.socket))
5388 break;
5389 urh_from_pollfd (urh,
5390 &p[poll_server + i]);
5391 i += 2;
5392 process_urh (urh);
5393 /* Finished forwarding? */
5394 if ( (0 == urh->in_buffer_size) &&
5395 (0 == urh->out_buffer_size) &&
5396 (0 == urh->in_buffer_used) &&
5397 (0 == urh->out_buffer_used) )
5398 {
5399 /* MHD_connection_finish_forward_() will remove connection from
5400 * 'daemon->urh_head' list. */
5401 MHD_connection_finish_forward_ (urh->connection);
5402 urh->clean_ready = true;
5403 /* If 'urh->was_closed' already was set to true, connection will be
5404 * moved immediately to cleanup list. Otherwise connection
5405 * will stay in suspended list until 'urh' will be marked
5406 * with 'was_closed' by application. */
5407 MHD_resume_connection (urh->connection);
5408 }
5409 }
5410#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5411
5412 free (p);
5413 }
5414 return MHD_YES;
5415}
5416
5417
5425static enum MHD_Result
5426MHD_poll_listen_socket (struct MHD_Daemon *daemon,
5427 int may_block)
5428{
5429 struct pollfd p[2];
5430 int timeout;
5431 unsigned int poll_count;
5432 int poll_listen;
5433 int poll_itc_idx;
5434 MHD_socket ls;
5435
5438
5439 memset (&p,
5440 0,
5441 sizeof (p));
5442 poll_count = 0;
5443 poll_listen = -1;
5444 poll_itc_idx = -1;
5445 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5446 (! daemon->was_quiesced) )
5447
5448 {
5449 p[poll_count].fd = ls;
5450 p[poll_count].events = POLLIN;
5451 p[poll_count].revents = 0;
5452 poll_listen = (int) poll_count;
5453 poll_count++;
5454 }
5455 if (MHD_ITC_IS_VALID_ (daemon->itc))
5456 {
5457 p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
5458 p[poll_count].events = POLLIN;
5459 p[poll_count].revents = 0;
5460 poll_itc_idx = (int) poll_count;
5461 poll_count++;
5462 }
5463
5464 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
5465 (void) resume_suspended_connections (daemon);
5466
5467 if (MHD_NO == may_block)
5468 timeout = 0;
5469 else
5470 timeout = -1;
5471 if (0 == poll_count)
5472 return MHD_YES;
5473 if (MHD_sys_poll_ (p,
5474 poll_count,
5475 timeout) < 0)
5476 {
5477 const int err = MHD_socket_get_error_ ();
5478
5479 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5480 return MHD_YES;
5481#ifdef HAVE_MESSAGES
5482 MHD_DLOG (daemon,
5483 _ ("poll failed: %s\n"),
5484 MHD_socket_strerr_ (err));
5485#endif
5486 return MHD_NO;
5487 }
5488 if ( (0 <= poll_itc_idx) &&
5489 (0 != (p[poll_itc_idx].revents & POLLIN)) )
5490 MHD_itc_clear_ (daemon->itc);
5491
5492 /* handle shutdown */
5493 if (daemon->shutdown)
5494 return MHD_NO;
5495
5496 /* Process externally added connection if any */
5497 if (daemon->have_new)
5499
5500 if ( (0 <= poll_listen) &&
5501 (0 != (p[poll_listen].revents & POLLIN)) )
5502 (void) MHD_accept_connection (daemon);
5503 return MHD_YES;
5504}
5505
5506
5507#endif
5508
5509#ifdef HAVE_POLL
5510
5518static enum MHD_Result
5519MHD_poll (struct MHD_Daemon *daemon,
5520 int may_block)
5521{
5522 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
5523 return MHD_poll_all (daemon,
5524 may_block ? -1 : 0);
5525 return MHD_poll_listen_socket (daemon,
5526 may_block);
5527}
5528
5529
5530#endif /* HAVE_POLL */
5531
5532
5533#ifdef EPOLL_SUPPORT
5534
5543#define MAX_EVENTS 128
5544
5545
5546#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5547
5555static bool
5556is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
5557{
5558 const struct MHD_Connection *const connection = urh->connection;
5559
5560 if ( (0 == urh->in_buffer_size) &&
5561 (0 == urh->out_buffer_size) &&
5562 (0 == urh->in_buffer_used) &&
5563 (0 == urh->out_buffer_used) )
5564 return false;
5565 if (connection->daemon->shutdown)
5566 return true;
5568 & urh->app.celi)) ||
5569 (connection->tls_read_ready) ) &&
5570 (urh->in_buffer_used < urh->in_buffer_size) )
5571 return true;
5573 & urh->mhd.celi)) ||
5574 urh->was_closed) &&
5575 (urh->out_buffer_used < urh->out_buffer_size) )
5576 return true;
5577 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
5578 (urh->out_buffer_used > 0) )
5579 return true;
5580 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
5581 (urh->in_buffer_used > 0) )
5582 return true;
5583 return false;
5584}
5585
5586
5595static enum MHD_Result
5596run_epoll_for_upgrade (struct MHD_Daemon *daemon)
5597{
5598 struct epoll_event events[MAX_EVENTS];
5599 int num_events;
5600 struct MHD_UpgradeResponseHandle *pos;
5601 struct MHD_UpgradeResponseHandle *prev;
5602
5603#ifdef MHD_USE_THREADS
5604 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
5606#endif /* MHD_USE_THREADS */
5607
5608 num_events = MAX_EVENTS;
5609 while (0 != num_events)
5610 {
5611 unsigned int i;
5612 /* update event masks */
5613 num_events = epoll_wait (daemon->epoll_upgrade_fd,
5614 events,
5615 MAX_EVENTS,
5616 0);
5617 if (-1 == num_events)
5618 {
5619 const int err = MHD_socket_get_error_ ();
5620
5621 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5622 return MHD_YES;
5623#ifdef HAVE_MESSAGES
5624 MHD_DLOG (daemon,
5625 _ ("Call to epoll_wait failed: %s\n"),
5626 MHD_socket_strerr_ (err));
5627#endif
5628 return MHD_NO;
5629 }
5630 for (i = 0; i < (unsigned int) num_events; i++)
5631 {
5632 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
5633 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
5634 bool new_err_state = false;
5635
5636 if (urh->clean_ready)
5637 continue;
5638
5639 /* Update ueh state based on what is ready according to epoll() */
5640 if (0 != (events[i].events & EPOLLIN))
5641 {
5642 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
5643 }
5644 if (0 != (events[i].events & EPOLLOUT))
5645 {
5646 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
5647 }
5648 if (0 != (events[i].events & EPOLLHUP))
5649 {
5651 }
5652
5653 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
5654 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
5655 {
5656 /* Process new error state only one time and avoid continuously
5657 * marking this connection as 'ready'. */
5658 ueh->celi |= MHD_EPOLL_STATE_ERROR;
5659 new_err_state = true;
5660 }
5661 if (! urh->in_eready_list)
5662 {
5663 if (new_err_state ||
5664 is_urh_ready (urh))
5665 {
5666 EDLL_insert (daemon->eready_urh_head,
5667 daemon->eready_urh_tail,
5668 urh);
5669 urh->in_eready_list = true;
5670 }
5671 }
5672 }
5673 }
5674 prev = daemon->eready_urh_tail;
5675 while (NULL != (pos = prev))
5676 {
5677 prev = pos->prevE;
5678 process_urh (pos);
5679 if (! is_urh_ready (pos))
5680 {
5681 EDLL_remove (daemon->eready_urh_head,
5682 daemon->eready_urh_tail,
5683 pos);
5684 pos->in_eready_list = false;
5685 }
5686 /* Finished forwarding? */
5687 if ( (0 == pos->in_buffer_size) &&
5688 (0 == pos->out_buffer_size) &&
5689 (0 == pos->in_buffer_used) &&
5690 (0 == pos->out_buffer_used) )
5691 {
5692 MHD_connection_finish_forward_ (pos->connection);
5693 pos->clean_ready = true;
5694 /* If 'pos->was_closed' already was set to true, connection
5695 * will be moved immediately to cleanup list. Otherwise
5696 * connection will stay in suspended list until 'pos' will
5697 * be marked with 'was_closed' by application. */
5698 MHD_resume_connection (pos->connection);
5699 }
5700 }
5701
5702 return MHD_YES;
5703}
5704
5705
5706#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5707
5708
5712static const char *const epoll_itc_marker = "itc_marker";
5713
5714
5724static enum MHD_Result
5725MHD_epoll (struct MHD_Daemon *daemon,
5726 int32_t millisec)
5727{
5728#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5729 static const char *const upgrade_marker = "upgrade_ptr";
5730#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5731 struct MHD_Connection *pos;
5732 struct MHD_Connection *prev;
5733 struct epoll_event events[MAX_EVENTS];
5734 struct epoll_event event;
5735 int timeout_ms;
5736 int num_events;
5737 unsigned int i;
5738 MHD_socket ls;
5739#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5740 bool run_upgraded = false;
5741#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5742 bool need_to_accept;
5743
5744 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5745 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5746 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5747 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5748 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5750
5751 if (-1 == daemon->epoll_fd)
5752 return MHD_NO; /* we're down! */
5753 if (daemon->shutdown)
5754 return MHD_NO;
5755 /* 'listen_socket_in_epoll', 'was_quiesced' and the epoll set itself
5756 are shared with MHD_quiesce_daemon(), which runs on the
5757 application's thread. Testing them and acting on the result has to
5758 be one atomic step. */
5759#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5760 MHD_mutex_lock_chk_ (&daemon->epoll_listen_mutex);
5761#endif
5762 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5763 (! daemon->was_quiesced) &&
5764 (daemon->connections < daemon->connection_limit) &&
5765 (! daemon->listen_socket_in_epoll) &&
5766 (! daemon->at_limit) )
5767 {
5768 event.events = EPOLLIN | EPOLLRDHUP;
5769 event.data.ptr = daemon;
5770 if (0 != epoll_ctl (daemon->epoll_fd,
5771 EPOLL_CTL_ADD,
5772 ls,
5773 &event))
5774 {
5775#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5776 MHD_mutex_unlock_chk_ (&daemon->epoll_listen_mutex);
5777#endif
5778#ifdef HAVE_MESSAGES
5779 MHD_DLOG (daemon,
5780 _ ("Call to epoll_ctl failed: %s\n"),
5782#endif
5783 return MHD_NO;
5784 }
5785 daemon->listen_socket_in_epoll = true;
5786 }
5787 if ( (daemon->was_quiesced) &&
5788 (daemon->listen_socket_in_epoll) )
5789 {
5790 if (0 != epoll_ctl (daemon->epoll_fd,
5791 EPOLL_CTL_DEL,
5792 ls,
5793 NULL))
5794 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
5795 daemon->listen_socket_in_epoll = false;
5796 }
5797#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5798 MHD_mutex_unlock_chk_ (&daemon->epoll_listen_mutex);
5799#endif
5800
5801#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5802 if ( ( (! daemon->upgrade_fd_in_epoll) &&
5803 (-1 != daemon->epoll_upgrade_fd) ) )
5804 {
5805 event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
5806 event.data.ptr = _MHD_DROP_CONST (upgrade_marker);
5807 if (0 != epoll_ctl (daemon->epoll_fd,
5808 EPOLL_CTL_ADD,
5809 daemon->epoll_upgrade_fd,
5810 &event))
5811 {
5812#ifdef HAVE_MESSAGES
5813 MHD_DLOG (daemon,
5814 _ ("Call to epoll_ctl failed: %s\n"),
5816#endif
5817 return MHD_NO;
5818 }
5819 daemon->upgrade_fd_in_epoll = true;
5820 }
5821#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5822#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5823 MHD_mutex_lock_chk_ (&daemon->epoll_listen_mutex);
5824#endif
5825 if ( (daemon->listen_socket_in_epoll) &&
5826 ( (daemon->connections == daemon->connection_limit) ||
5827 (daemon->at_limit) ||
5828 (daemon->was_quiesced) ) )
5829 {
5830 /* we're at the connection limit, disable listen socket
5831 for event loop for now */
5832 if (0 != epoll_ctl (daemon->epoll_fd,
5833 EPOLL_CTL_DEL,
5834 ls,
5835 NULL))
5836 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
5837 daemon->listen_socket_in_epoll = false;
5838 }
5839#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5840 MHD_mutex_unlock_chk_ (&daemon->epoll_listen_mutex);
5841#endif
5842
5843 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
5844 (MHD_NO != resume_suspended_connections (daemon)) )
5845 millisec = 0;
5846
5847 timeout_ms = get_timeout_millisec_int (daemon,
5848 millisec);
5849
5850 /* Reset. New value will be set when connections are processed. */
5851 /* Note: Used mostly for uniformity here as same situation is
5852 * signaled in epoll mode by non-empty eready DLL. */
5853 daemon->data_already_pending = false;
5854
5855 need_to_accept = false;
5856 /* drain 'epoll' event queue; need to iterate as we get at most
5857 MAX_EVENTS in one system call here; in practice this should
5858 pretty much mean only one round, but better an extra loop here
5859 than unfair behavior... */
5860 num_events = MAX_EVENTS;
5861 while (MAX_EVENTS == num_events)
5862 {
5863 /* update event masks */
5864 num_events = epoll_wait (daemon->epoll_fd,
5865 events,
5866 MAX_EVENTS,
5867 timeout_ms);
5868 if (-1 == num_events)
5869 {
5870 const int err = MHD_socket_get_error_ ();
5871 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5872 return MHD_YES;
5873#ifdef HAVE_MESSAGES
5874 MHD_DLOG (daemon,
5875 _ ("Call to epoll_wait failed: %s\n"),
5876 MHD_socket_strerr_ (err));
5877#endif
5878 return MHD_NO;
5879 }
5880 for (i = 0; i < (unsigned int) num_events; i++)
5881 {
5882 /* First, check for the values of `ptr` that would indicate
5883 that this event is not about a normal connection. */
5884 if (NULL == events[i].data.ptr)
5885 continue; /* shutdown signal! */
5886#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5887 if (upgrade_marker == events[i].data.ptr)
5888 {
5889 /* activity on an upgraded connection, we process
5890 those in a separate epoll() */
5891 run_upgraded = true;
5892 continue;
5893 }
5894#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5895 if (epoll_itc_marker == events[i].data.ptr)
5896 {
5897 /* It's OK to clear ITC here as all external
5898 conditions will be processed later. */
5899 MHD_itc_clear_ (daemon->itc);
5900 continue;
5901 }
5902 if (daemon == events[i].data.ptr)
5903 {
5904 /* Check for error conditions on listen socket. */
5905 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
5906 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
5907 need_to_accept = true;
5908 continue;
5909 }
5910 /* this is an event relating to a 'normal' connection,
5911 remember the event and if appropriate mark the
5912 connection as 'eready'. */
5913 pos = events[i].data.ptr;
5914 /* normal processing: update read/write data */
5915 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
5916 {
5917 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
5918 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
5919 {
5920 EDLL_insert (daemon->eready_head,
5921 daemon->eready_tail,
5922 pos);
5923 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5924 }
5925 }
5926 else
5927 {
5928 if (0 != (events[i].events & EPOLLIN))
5929 {
5930 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
5931 if ( ( (0 != (MHD_EVENT_LOOP_INFO_READ & pos->event_loop_info)) ||
5932 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
5933 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5934 {
5935 EDLL_insert (daemon->eready_head,
5936 daemon->eready_tail,
5937 pos);
5938 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5939 }
5940 }
5941 if (0 != (events[i].events & EPOLLOUT))
5942 {
5943 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
5945 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5946 {
5947 EDLL_insert (daemon->eready_head,
5948 daemon->eready_tail,
5949 pos);
5950 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5951 }
5952 }
5953 }
5954 }
5955 }
5956
5957 /* Process externally added connection if any */
5958 if (daemon->have_new)
5960
5961 if (need_to_accept)
5962 {
5963 unsigned int series_length = 0;
5964
5965 /* Run 'accept' until it fails or daemon at limit of connections.
5966 * Do not accept more then 10 connections at once. The rest will
5967 * be accepted on next turn (level trigger is used for listen
5968 * socket). */
5969 while ( (MHD_NO != MHD_accept_connection (daemon)) &&
5970 (series_length < 10) &&
5971 (daemon->connections < daemon->connection_limit) &&
5972 (! daemon->at_limit) )
5973 series_length++;
5974 }
5975
5976 /* Handle timed-out connections; we need to do this here
5977 as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
5978 as the other event loops do. As timeouts do not get an explicit
5979 event, we need to find those connections that might have timed out
5980 here.
5981
5982 Connections with custom timeouts must all be looked at, as we
5983 do not bother to sort that (presumably very short) list. */
5984 prev = daemon->manual_timeout_tail;
5985 while (NULL != (pos = prev))
5986 {
5987 prev = pos->prevX;
5989 }
5990 /* Connections with the default timeout are sorted by prepending
5991 them to the head of the list whenever we touch the connection;
5992 thus it suffices to iterate from the tail until the first
5993 connection is NOT timed out */
5994 prev = daemon->normal_timeout_tail;
5995 while (NULL != (pos = prev))
5996 {
5997 prev = pos->prevX;
5999 if (MHD_CONNECTION_CLOSED != pos->state)
6000 break; /* sorted by timeout, no need to visit the rest! */
6001 }
6002
6003#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6004 if (run_upgraded || (NULL != daemon->eready_urh_head))
6005 run_epoll_for_upgrade (daemon);
6006#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6007
6008 /* process events for connections */
6009 prev = daemon->eready_tail;
6010 while (NULL != (pos = prev))
6011 {
6012 prev = pos->prevE;
6013 call_handlers (pos,
6014 0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
6015 0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
6016 0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
6018 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
6020 {
6021 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
6022 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
6024 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
6026 {
6027 EDLL_remove (daemon->eready_head,
6028 daemon->eready_tail,
6029 pos);
6030 pos->epoll_state &=
6032 }
6033 }
6034 }
6035
6036 return MHD_YES;
6037}
6038
6039
6040#endif
6041
6042
6071MHD_run (struct MHD_Daemon *daemon)
6072{
6073 if ( (daemon->shutdown) ||
6074 MHD_D_IS_USING_THREADS_ (daemon) )
6075 return MHD_NO;
6076
6077 (void) MHD_run_wait (daemon, 0);
6078 return MHD_YES;
6079}
6080
6081
6121MHD_run_wait (struct MHD_Daemon *daemon,
6122 int32_t millisec)
6123{
6124 enum MHD_Result res;
6125 if ( (daemon->shutdown) ||
6126 MHD_D_IS_USING_THREADS_ (daemon) )
6127 return MHD_NO;
6128
6130
6131 if (0 > millisec)
6132 millisec = -1;
6133#ifdef HAVE_POLL
6134 if (MHD_D_IS_USING_POLL_ (daemon))
6135 {
6136 res = MHD_poll_all (daemon, millisec);
6137 MHD_cleanup_connections (daemon);
6138 }
6139 else
6140#endif /* HAVE_POLL */
6141#ifdef EPOLL_SUPPORT
6142 if (MHD_D_IS_USING_EPOLL_ (daemon))
6143 {
6144 res = MHD_epoll (daemon, millisec);
6145 MHD_cleanup_connections (daemon);
6146 }
6147 else
6148#endif
6149 if (1)
6150 {
6152#ifdef HAS_FD_SETSIZE_OVERRIDABLE
6153#ifdef HAVE_MESSAGES
6154 if (daemon->fdset_size_set_by_app
6155 && (((int) FD_SETSIZE) < daemon->fdset_size))
6156 {
6157 MHD_DLOG (daemon,
6158 _ ("MHD_run()/MHD_run_wait() called for daemon started with " \
6159 "MHD_OPTION_APP_FD_SETSIZE option (%d). " \
6160 "The library was compiled with smaller FD_SETSIZE (%d). " \
6161 "Some socket FDs may be not processed. " \
6162 "Use MHD_run_from_select2() instead of MHD_run() or " \
6163 "do not use MHD_OPTION_APP_FD_SETSIZE option.\n"),
6164 daemon->fdset_size, (int) FD_SETSIZE);
6165 }
6166#endif /* HAVE_MESSAGES */
6167#endif /* HAS_FD_SETSIZE_OVERRIDABLE */
6168
6169 res = MHD_select (daemon, millisec);
6170 /* MHD_select does MHD_cleanup_connections already */
6171 }
6172 return res;
6173}
6174
6175
6184static void
6186{
6187 struct MHD_Daemon *daemon = pos->daemon;
6188
6189#ifdef MHD_USE_THREADS
6190 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
6192 mhd_assert (NULL == daemon->worker_pool);
6193#endif /* MHD_USE_THREADS */
6194
6196 {
6198 return; /* must let thread to do the rest */
6199 }
6202#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6203 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
6204#endif
6205 mhd_assert (! pos->suspended);
6206 mhd_assert (! pos->resuming);
6207 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
6209 daemon->normal_timeout_tail,
6210 pos);
6211 else
6213 daemon->manual_timeout_tail,
6214 pos);
6216 daemon->connections_tail,
6217 pos);
6218 DLL_insert (daemon->cleanup_head,
6219 daemon->cleanup_tail,
6220 pos);
6221 daemon->data_already_pending = true;
6222#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6223 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
6224#endif
6225}
6226
6227
6228#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6236static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
6237MHD_polling_thread (void *cls)
6238{
6239 struct MHD_Daemon *daemon = cls;
6240#ifdef HAVE_PTHREAD_SIGMASK
6241 sigset_t s_mask;
6242 int err;
6243#endif /* HAVE_PTHREAD_SIGMASK */
6244
6246#ifdef HAVE_PTHREAD_SIGMASK
6247 if ((0 == sigemptyset (&s_mask)) &&
6248 (0 == sigaddset (&s_mask, SIGPIPE)))
6249 {
6250 err = pthread_sigmask (SIG_BLOCK, &s_mask, NULL);
6251 }
6252 else
6253 err = errno;
6254 if (0 == err)
6255 daemon->sigpipe_blocked = true;
6256#ifdef HAVE_MESSAGES
6257 else
6258 MHD_DLOG (daemon,
6259 _ ("Failed to block SIGPIPE on daemon thread: %s\n"),
6260 MHD_strerror_ (errno));
6261#endif /* HAVE_MESSAGES */
6262#endif /* HAVE_PTHREAD_SIGMASK */
6263 while (! daemon->shutdown)
6264 {
6265#ifdef HAVE_POLL
6266 if (MHD_D_IS_USING_POLL_ (daemon))
6267 MHD_poll (daemon, MHD_YES);
6268 else
6269#endif /* HAVE_POLL */
6270#ifdef EPOLL_SUPPORT
6271 if (MHD_D_IS_USING_EPOLL_ (daemon))
6272 MHD_epoll (daemon, -1);
6273 else
6274#endif
6275 MHD_select (daemon, -1);
6276 MHD_cleanup_connections (daemon);
6277 }
6278
6279 /* Resume any pending for resume connections, join
6280 * all connection's threads (if any) and finally cleanup
6281 * everything. */
6282 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6284 close_all_connections (daemon);
6285
6286 return (MHD_THRD_RTRN_TYPE_) 0;
6287}
6288
6289
6290#endif
6291
6292
6304static size_t
6306 struct MHD_Connection *connection,
6307 char *val)
6308{
6309 bool broken;
6310 size_t res;
6311 (void) cls; /* Mute compiler warning. */
6312
6313 /* TODO: add individual parameter */
6314 if (0 <= connection->daemon->client_discipline)
6316
6317 res = MHD_str_pct_decode_in_place_lenient_ (val, &broken);
6318#ifdef HAVE_MESSAGES
6319 if (broken)
6320 {
6321 MHD_DLOG (connection->daemon,
6322 _ ("The URL encoding is broken.\n"));
6323 }
6324#endif /* HAVE_MESSAGES */
6325 return res;
6326}
6327
6328
6349_MHD_EXTERN struct MHD_Daemon *
6350MHD_start_daemon (unsigned int flags,
6351 uint16_t port,
6353 void *apc_cls,
6355 void *dh_cls,
6356 ...)
6357{
6358 struct MHD_Daemon *daemon;
6359 va_list ap;
6360
6361 va_start (ap,
6362 dh_cls);
6363 daemon = MHD_start_daemon_va (flags,
6364 port,
6365 apc,
6366 apc_cls,
6367 dh,
6368 dh_cls,
6369 ap);
6370 va_end (ap);
6371 return daemon;
6372}
6373
6374
6396{
6397#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6398 unsigned int i;
6399#endif
6400 MHD_socket ret;
6401
6402 ret = daemon->listen_fd;
6403 if ((MHD_INVALID_SOCKET == ret)
6404 || daemon->was_quiesced)
6405 return MHD_INVALID_SOCKET;
6406 if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
6407 MHD_D_IS_USING_THREADS_ (daemon) )
6408 {
6409#ifdef HAVE_MESSAGES
6410 MHD_DLOG (daemon,
6411 _ ("Using MHD_quiesce_daemon in this mode " \
6412 "requires MHD_USE_ITC.\n"));
6413#endif
6414 return MHD_INVALID_SOCKET;
6415 }
6416
6417#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6418 if (NULL != daemon->worker_pool)
6419 for (i = 0; i < daemon->worker_pool_size; i++)
6420 {
6421 /* Each worker is an independent daemon with its own epoll set and
6422 its own lock; they are taken one at a time and never nested, so
6423 there is no ordering to get wrong. Holding the worker's lock
6424 is what stops it removing the same descriptor concurrently from
6425 its own MHD_epoll(). */
6426#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6427 MHD_mutex_lock_chk_ (&daemon->worker_pool[i].epoll_listen_mutex);
6428#endif
6429 daemon->worker_pool[i].was_quiesced = true;
6430#ifdef EPOLL_SUPPORT
6431 if (MHD_D_IS_USING_EPOLL_ (daemon) &&
6432 (-1 != daemon->worker_pool[i].epoll_fd) &&
6433 (daemon->worker_pool[i].listen_socket_in_epoll) )
6434 {
6435 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
6436 EPOLL_CTL_DEL,
6437 ret,
6438 NULL))
6439 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
6440 daemon->worker_pool[i].listen_socket_in_epoll = false;
6441 }
6442 else
6443#endif
6444 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
6445 {
6446 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
6447 MHD_PANIC (_ ("Failed to signal quiesce via inter-thread " \
6448 "communication channel.\n"));
6449 }
6450#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6451 MHD_mutex_unlock_chk_ (&daemon->worker_pool[i].epoll_listen_mutex);
6452#endif
6453 }
6454#endif
6455#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6456 MHD_mutex_lock_chk_ (&daemon->epoll_listen_mutex);
6457#endif
6458 daemon->was_quiesced = true;
6459#ifdef EPOLL_SUPPORT
6460 if (MHD_D_IS_USING_EPOLL_ (daemon) &&
6461 (-1 != daemon->epoll_fd) &&
6462 (daemon->listen_socket_in_epoll) )
6463 {
6464 if (0 != epoll_ctl (daemon->epoll_fd,
6465 EPOLL_CTL_DEL,
6466 ret,
6467 NULL))
6468 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
6469 daemon->listen_socket_in_epoll = false;
6470 }
6471#endif
6472#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6473 MHD_mutex_unlock_chk_ (&daemon->epoll_listen_mutex);
6474#endif
6475 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
6476 (! MHD_itc_activate_ (daemon->itc, "q")) )
6477 MHD_PANIC (_ ("failed to signal quiesce via inter-thread " \
6478 "communication channel.\n"));
6479 return ret;
6480}
6481
6482
6488struct MHD_InterimParams_
6489{
6497 size_t num_opts;
6501 bool fdset_size_set;
6505 int fdset_size;
6509 bool listen_fd_set;
6513 MHD_socket listen_fd;
6517 bool pserver_addr_set;
6521 const struct sockaddr *pserver_addr;
6525 bool server_addr_len_set;
6529 socklen_t server_addr_len;
6530};
6531
6539typedef void
6540(*VfprintfFunctionPointerType)(void *cls,
6541 const char *format,
6542 va_list va);
6543
6544
6554static enum MHD_Result
6555parse_options_va (struct MHD_Daemon *daemon,
6556 struct MHD_InterimParams_ *params,
6557 va_list ap);
6558
6559
6569static enum MHD_Result
6571 struct MHD_InterimParams_ *params,
6572 ...)
6573{
6574 va_list ap;
6575 enum MHD_Result ret;
6576
6577 va_start (ap, params);
6578 ret = parse_options_va (daemon,
6579 params,
6580 ap);
6581 va_end (ap);
6582 return ret;
6583}
6584
6585
6586#ifdef HTTPS_SUPPORT
6590enum MHD_TlsPrioritiesBaseType
6591{
6592 MHD_TLS_PRIO_BASE_LIBMHD = 0,
6593 MHD_TLS_PRIO_BASE_SYSTEM = 1,
6594#if GNUTLS_VERSION_NUMBER >= 0x030300
6595 MHD_TLS_PRIO_BASE_DEFAULT,
6596#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6597 MHD_TLS_PRIO_BASE_NORMAL
6598};
6599
6600static const struct _MHD_cstr_w_len MHD_TlsBasePriotities[] = {
6601 _MHD_S_STR_W_LEN ("@LIBMICROHTTPD"),
6602 _MHD_S_STR_W_LEN ("@SYSTEM"),
6603#if GNUTLS_VERSION_NUMBER >= 0x030300
6604 {NULL, 0},
6605#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6606 _MHD_S_STR_W_LEN ("NORMAL")
6607};
6608
6614static bool
6615daemon_tls_priorities_init_default (struct MHD_Daemon *daemon)
6616{
6617 unsigned int p;
6618 int res;
6619
6620 mhd_assert (0 != (((unsigned int) daemon->options) & MHD_USE_TLS));
6621 mhd_assert (NULL == daemon->priority_cache);
6622 mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \
6623 sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]));
6624
6625 res = GNUTLS_E_SUCCESS; /* Mute compiler warning */
6626
6627 for (p = 0;
6628 p < sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]);
6629 ++p)
6630 {
6631 res = gnutls_priority_init (&daemon->priority_cache,
6632 MHD_TlsBasePriotities[p].str, NULL);
6633 if (GNUTLS_E_SUCCESS == res)
6634 {
6635#ifdef _DEBUG
6636#ifdef HAVE_MESSAGES
6637 switch ((enum MHD_TlsPrioritiesBaseType) p)
6638 {
6639 case MHD_TLS_PRIO_BASE_LIBMHD:
6640 MHD_DLOG (daemon,
6641 _ ("GnuTLS priorities have been initialised with " \
6642 "@LIBMICROHTTPD application-specific system-wide " \
6643 "configuration.\n") );
6644 break;
6645 case MHD_TLS_PRIO_BASE_SYSTEM:
6646 MHD_DLOG (daemon,
6647 _ ("GnuTLS priorities have been initialised with " \
6648 "@SYSTEM system-wide configuration.\n") );
6649 break;
6650#if GNUTLS_VERSION_NUMBER >= 0x030300
6651 case MHD_TLS_PRIO_BASE_DEFAULT:
6652 MHD_DLOG (daemon,
6653 _ ("GnuTLS priorities have been initialised with " \
6654 "GnuTLS default configuration.\n") );
6655 break;
6656#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6657 case MHD_TLS_PRIO_BASE_NORMAL:
6658 MHD_DLOG (daemon,
6659 _ ("GnuTLS priorities have been initialised with " \
6660 "NORMAL configuration.\n") );
6661 break;
6662 default:
6663 mhd_assert (0);
6664 }
6665#endif /* HAVE_MESSAGES */
6666#endif /* _DEBUG */
6667 return true;
6668 }
6669 }
6670#ifdef HAVE_MESSAGES
6671 MHD_DLOG (daemon,
6672 _ ("Failed to set GnuTLS priorities. Last error: %s\n"),
6673 gnutls_strerror (res));
6674#endif /* HAVE_MESSAGES */
6675 return false;
6676}
6677
6678
6688static bool
6689daemon_tls_priorities_init_append_inner_ (struct MHD_Daemon *daemon,
6690 const char *prio,
6691 size_t prio_len,
6692 char *buf,
6693 const size_t buf_size)
6694{
6695 unsigned int p;
6696 int res;
6697 const char *err_pos;
6698
6699 (void) buf_size; /* Mute compiler warning for non-Debug builds */
6700 mhd_assert (0 != (((unsigned int) daemon->options) & MHD_USE_TLS));
6701 mhd_assert (NULL == daemon->priority_cache);
6702 mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \
6703 sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]));
6704
6705 res = GNUTLS_E_SUCCESS; /* Mute compiler warning */
6706
6707 for (p = 0;
6708 p < sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]);
6709 ++p)
6710 {
6711
6712#if GNUTLS_VERSION_NUMBER >= 0x030300
6713#if GNUTLS_VERSION_NUMBER >= 0x030603
6714 if (NULL == MHD_TlsBasePriotities[p].str)
6715 res = gnutls_priority_init2 (&daemon->priority_cache, prio, &err_pos,
6716 GNUTLS_PRIORITY_INIT_DEF_APPEND);
6717 else
6718#else /* 0x030300 <= GNUTLS_VERSION_NUMBER
6719 && GNUTLS_VERSION_NUMBER < 0x030603 */
6720 if (NULL == MHD_TlsBasePriotities[p].str)
6721 continue; /* Skip the value, no way to append priorities to the default string */
6722 else
6723#endif /* GNUTLS_VERSION_NUMBER < 0x030603 */
6724#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6725 if (1)
6726 {
6727 size_t buf_pos;
6728
6729 mhd_assert (NULL != MHD_TlsBasePriotities[p].str);
6730 buf_pos = 0;
6731 memcpy (buf + buf_pos, MHD_TlsBasePriotities[p].str,
6732 MHD_TlsBasePriotities[p].len);
6733 buf_pos += MHD_TlsBasePriotities[p].len;
6734 buf[buf_pos++] = ':';
6735 memcpy (buf + buf_pos, prio, prio_len + 1);
6736#ifdef _DEBUG
6737 buf_pos += prio_len + 1;
6738 mhd_assert (buf_size >= buf_pos);
6739#endif /* _DEBUG */
6740 res = gnutls_priority_init (&daemon->priority_cache, buf, &err_pos);
6741 }
6742 if (GNUTLS_E_SUCCESS == res)
6743 {
6744#ifdef _DEBUG
6745#ifdef HAVE_MESSAGES
6746 switch ((enum MHD_TlsPrioritiesBaseType) p)
6747 {
6748 case MHD_TLS_PRIO_BASE_LIBMHD:
6749 MHD_DLOG (daemon,
6750 _ ("GnuTLS priorities have been initialised with " \
6751 "priorities specified by application appended to " \
6752 "@LIBMICROHTTPD application-specific system-wide " \
6753 "configuration.\n") );
6754 break;
6755 case MHD_TLS_PRIO_BASE_SYSTEM:
6756 MHD_DLOG (daemon,
6757 _ ("GnuTLS priorities have been initialised with " \
6758 "priorities specified by application appended to " \
6759 "@SYSTEM system-wide configuration.\n") );
6760 break;
6761#if GNUTLS_VERSION_NUMBER >= 0x030300
6762 case MHD_TLS_PRIO_BASE_DEFAULT:
6763 MHD_DLOG (daemon,
6764 _ ("GnuTLS priorities have been initialised with " \
6765 "priorities specified by application appended to " \
6766 "GnuTLS default configuration.\n") );
6767 break;
6768#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6769 case MHD_TLS_PRIO_BASE_NORMAL:
6770 MHD_DLOG (daemon,
6771 _ ("GnuTLS priorities have been initialised with " \
6772 "priorities specified by application appended to " \
6773 "NORMAL configuration.\n") );
6774 break;
6775 default:
6776 mhd_assert (0);
6777 }
6778#endif /* HAVE_MESSAGES */
6779#endif /* _DEBUG */
6780 return true;
6781 }
6782 }
6783#ifdef HAVE_MESSAGES
6784 MHD_DLOG (daemon,
6785 _ ("Failed to set GnuTLS priorities. Last error: %s. " \
6786 "The problematic part starts at: %s\n"),
6787 gnutls_strerror (res), err_pos);
6788#endif /* HAVE_MESSAGES */
6789 return false;
6790}
6791
6792
6793#define LOCAL_BUFF_SIZE 128
6794
6803static bool
6804daemon_tls_priorities_init_append (struct MHD_Daemon *daemon, const char *prio)
6805{
6806 static const size_t longest_base_prio = MHD_STATICSTR_LEN_ ("@LIBMICROHTTPD");
6807 bool ret;
6808 size_t prio_len;
6809 size_t buf_size_needed;
6810
6811 if (NULL == prio)
6812 return daemon_tls_priorities_init_default (daemon);
6813
6814 if (':' == prio[0])
6815 ++prio;
6816
6817 prio_len = strlen (prio);
6818
6819 buf_size_needed = longest_base_prio + 1 + prio_len + 1;
6820
6821 if (LOCAL_BUFF_SIZE >= buf_size_needed)
6822 {
6823 char local_buffer[LOCAL_BUFF_SIZE];
6824 ret = daemon_tls_priorities_init_append_inner_ (daemon, prio, prio_len,
6825 local_buffer,
6826 LOCAL_BUFF_SIZE);
6827 }
6828 else
6829 {
6830 char *allocated_buffer;
6831 allocated_buffer = (char *) malloc (buf_size_needed);
6832 if (NULL == allocated_buffer)
6833 {
6834#ifdef HAVE_MESSAGES
6835 MHD_DLOG (daemon,
6836 _ ("Error allocating memory: %s\n"),
6837 MHD_strerror_ (errno));
6838#endif
6839 return false;
6840 }
6841 ret = daemon_tls_priorities_init_append_inner_ (daemon, prio, prio_len,
6842 allocated_buffer,
6843 buf_size_needed);
6844 free (allocated_buffer);
6845 }
6846 return ret;
6847}
6848
6849
6850#endif /* HTTPS_SUPPORT */
6851
6852
6861static enum MHD_Result
6863 struct MHD_InterimParams_ *params,
6864 va_list ap)
6865{
6866 enum MHD_OPTION opt;
6867 struct MHD_OptionItem *oa;
6868 unsigned int i;
6869 unsigned int uv;
6870#ifdef HTTPS_SUPPORT
6871 const char *pstr;
6872#if GNUTLS_VERSION_MAJOR >= 3
6873 gnutls_certificate_retrieve_function2 * pgcrf;
6874#endif
6875#if GNUTLS_VERSION_NUMBER >= 0x030603
6876 gnutls_certificate_retrieve_function3 * pgcrf2;
6877#endif
6878#endif /* HTTPS_SUPPORT */
6879
6880 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
6881 {
6882 /* Increase counter at start, so resulting value is number of
6883 * processed options, including any failed ones. */
6884 params->num_opts++;
6885 switch (opt)
6886 {
6888 if (1)
6889 {
6890 size_t val;
6891
6892 val = va_arg (ap,
6893 size_t);
6894 if (0 != val)
6895 {
6896 daemon->pool_size = val;
6897 if (64 > daemon->pool_size)
6898 {
6899#ifdef HAVE_MESSAGES
6900 MHD_DLOG (daemon,
6901 _ ("Warning: specified " \
6902 "MHD_OPTION_CONNECTION_MEMORY_LIMIT " \
6903 "value is too small and rounded up to 64.\n"));
6904#endif /* HAVE_MESSAGES */
6905 daemon->pool_size = 64;
6906 }
6907 if (daemon->pool_size / 4 < daemon->pool_increment)
6908 daemon->pool_increment = daemon->pool_size / 4;
6909 }
6910 }
6911 break;
6913 if (1)
6914 {
6915 size_t val;
6916
6917 val = va_arg (ap,
6918 size_t);
6919
6920 if (0 != val)
6921 {
6922 daemon->pool_increment = val;
6923 if (daemon->pool_size / 4 < daemon->pool_increment)
6924 {
6925#ifdef HAVE_MESSAGES
6926 MHD_DLOG (daemon,
6927 _ ("Warning: specified " \
6928 "MHD_OPTION_CONNECTION_MEMORY_INCREMENT value is " \
6929 "too large and rounded down to 1/4 of " \
6930 "MHD_OPTION_CONNECTION_MEMORY_LIMIT.\n"));
6931#endif /* HAVE_MESSAGES */
6932 daemon->pool_increment = daemon->pool_size / 4;
6933 }
6934 }
6935 }
6936 break;
6938 daemon->connection_limit = va_arg (ap,
6939 unsigned int);
6940 break;
6942 uv = va_arg (ap,
6943 unsigned int);
6944#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
6945 if ((UINT64_MAX / 4000 - 1) < uv)
6946 {
6947#ifdef HAVE_MESSAGES
6948 MHD_DLOG (daemon,
6949 _ ("The specified connection timeout (%u) is too large. " \
6950 "Maximum allowed value (%" PRIu64 ") will be used " \
6951 "instead.\n"),
6952 uv,
6953 (UINT64_MAX / 4000 - 1));
6954#endif
6955 uv = UINT64_MAX / 4000 - 1;
6956 }
6957#endif /* (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT */
6958 daemon->connection_timeout_ms = ((uint64_t) uv) * 1000;
6959 break;
6961 daemon->notify_completed = va_arg (ap,
6963 daemon->notify_completed_cls = va_arg (ap,
6964 void *);
6965 break;
6967 daemon->notify_connection = va_arg (ap,
6969 daemon->notify_connection_cls = va_arg (ap,
6970 void *);
6971 break;
6973 daemon->per_ip_connection_limit = va_arg (ap,
6974 unsigned int);
6975 break;
6977 params->server_addr_len = va_arg (ap,
6978 socklen_t);
6979 params->server_addr_len_set = true;
6980 params->pserver_addr = va_arg (ap,
6981 const struct sockaddr *);
6982 params->pserver_addr_set = true;
6983 break;
6985 params->server_addr_len_set = false;
6986 params->pserver_addr = va_arg (ap,
6987 const struct sockaddr *);
6988 params->pserver_addr_set = true;
6989 break;
6991 daemon->uri_log_callback = va_arg (ap,
6992 LogCallback);
6993 daemon->uri_log_callback_cls = va_arg (ap,
6994 void *);
6995 break;
6997 daemon->insanity_level = (enum MHD_DisableSanityCheck)
6998 va_arg (ap,
6999 unsigned int);
7000 break;
7001#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7003 daemon->worker_pool_size = va_arg (ap,
7004 unsigned int);
7005 if (0 == daemon->worker_pool_size)
7006 {
7007 (void) 0; /* MHD_OPTION_THREAD_POOL_SIZE ignored, do nothing */
7008 }
7009 else if (1 == daemon->worker_pool_size)
7010 {
7011#ifdef HAVE_MESSAGES
7012 MHD_DLOG (daemon,
7013 _ ("Warning: value \"1\", specified as the thread pool " \
7014 "size, is ignored. Thread pool is not used.\n"));
7015#endif
7016 daemon->worker_pool_size = 0;
7017 }
7018#if SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2)
7019 /* Next comparison could be always false on some platforms and whole branch will
7020 * be optimized out on these platforms. On others it will be compiled into real
7021 * check. */
7022 else if (daemon->worker_pool_size >=
7023 (SIZE_MAX / sizeof (struct MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
7024 {
7025#ifdef HAVE_MESSAGES
7026 MHD_DLOG (daemon,
7027 _ ("Specified thread pool size (%u) too big.\n"),
7028 daemon->worker_pool_size);
7029#endif
7030 return MHD_NO;
7031 }
7032#endif /* SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2) */
7033 else
7034 {
7035 if (! MHD_D_IS_USING_THREADS_ (daemon))
7036 {
7037#ifdef HAVE_MESSAGES
7038 MHD_DLOG (daemon,
7039 _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
7040 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
7041#endif
7042 return MHD_NO;
7043 }
7045 {
7046#ifdef HAVE_MESSAGES
7047 MHD_DLOG (daemon,
7048 _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
7049 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
7050#endif
7051 return MHD_NO;
7052 }
7053 }
7054 break;
7055#endif
7056#ifdef HTTPS_SUPPORT
7058 pstr = va_arg (ap,
7059 const char *);
7060 if (0 != (daemon->options & MHD_USE_TLS))
7061 daemon->https_mem_key = pstr;
7062#ifdef HAVE_MESSAGES
7063 else
7064 MHD_DLOG (daemon,
7065 _ ("MHD HTTPS option %d passed to MHD but " \
7066 "MHD_USE_TLS not set.\n"),
7067 opt);
7068#endif
7069 break;
7071 pstr = va_arg (ap,
7072 const char *);
7073 if (0 != (daemon->options & MHD_USE_TLS))
7074 daemon->https_key_password = pstr;
7075#ifdef HAVE_MESSAGES
7076 else
7077 MHD_DLOG (daemon,
7078 _ ("MHD HTTPS option %d passed to MHD but " \
7079 "MHD_USE_TLS not set.\n"),
7080 opt);
7081#endif
7082 break;
7084 pstr = va_arg (ap,
7085 const char *);
7086 if (0 != (daemon->options & MHD_USE_TLS))
7087 daemon->https_mem_cert = pstr;
7088#ifdef HAVE_MESSAGES
7089 else
7090 MHD_DLOG (daemon,
7091 _ ("MHD HTTPS option %d passed to MHD but " \
7092 "MHD_USE_TLS not set.\n"),
7093 opt);
7094#endif
7095 break;
7097 pstr = va_arg (ap,
7098 const char *);
7099 if (0 != (daemon->options & MHD_USE_TLS))
7100 daemon->https_mem_trust = pstr;
7101#ifdef HAVE_MESSAGES
7102 else
7103 MHD_DLOG (daemon,
7104 _ ("MHD HTTPS option %d passed to MHD but " \
7105 "MHD_USE_TLS not set.\n"),
7106 opt);
7107#endif
7108 break;
7110 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
7111 int);
7112 break;
7114 pstr = va_arg (ap,
7115 const char *);
7116 if (0 != (daemon->options & MHD_USE_TLS))
7117 {
7118 gnutls_datum_t dhpar;
7119 size_t pstr_len;
7120
7121 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
7122 {
7123#ifdef HAVE_MESSAGES
7124 MHD_DLOG (daemon,
7125 _ ("Error initializing DH parameters.\n"));
7126#endif
7127 return MHD_NO;
7128 }
7129 dhpar.data = (unsigned char *) _MHD_DROP_CONST (pstr);
7130 pstr_len = strlen (pstr);
7131 if (UINT_MAX < pstr_len)
7132 {
7133#ifdef HAVE_MESSAGES
7134 MHD_DLOG (daemon,
7135 _ ("Diffie-Hellman parameters string too long.\n"));
7136#endif
7137 return MHD_NO;
7138 }
7139 dhpar.size = (unsigned int) pstr_len;
7140 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
7141 &dhpar,
7142 GNUTLS_X509_FMT_PEM) < 0)
7143 {
7144#ifdef HAVE_MESSAGES
7145 MHD_DLOG (daemon,
7146 _ ("Bad Diffie-Hellman parameters format.\n"));
7147#endif
7148 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
7149 return MHD_NO;
7150 }
7151 daemon->have_dhparams = true;
7152 }
7153#ifdef HAVE_MESSAGES
7154 else
7155 MHD_DLOG (daemon,
7156 _ ("MHD HTTPS option %d passed to MHD but " \
7157 "MHD_USE_TLS not set.\n"),
7158 opt);
7159#endif
7160 break;
7163 pstr = va_arg (ap,
7164 const char *);
7165 if (0 != (daemon->options & MHD_USE_TLS))
7166 {
7167 if (NULL != daemon->priority_cache)
7168 gnutls_priority_deinit (daemon->priority_cache);
7169
7170 if (MHD_OPTION_HTTPS_PRIORITIES == opt)
7171 {
7172 int init_res;
7173 const char *err_pos;
7174 init_res = gnutls_priority_init (&daemon->priority_cache,
7175 pstr,
7176 &err_pos);
7177 if (GNUTLS_E_SUCCESS != init_res)
7178 {
7179#ifdef HAVE_MESSAGES
7180 MHD_DLOG (daemon,
7181 _ ("Setting priorities to '%s' failed: %s " \
7182 "The problematic part starts at: %s\n"),
7183 pstr,
7184 gnutls_strerror (init_res),
7185 err_pos);
7186#endif
7187 daemon->priority_cache = NULL;
7188 return MHD_NO;
7189 }
7190 }
7191 else
7192 {
7193 /* The cache has been deinited */
7194 daemon->priority_cache = NULL;
7195 if (! daemon_tls_priorities_init_append (daemon, pstr))
7196 return MHD_NO;
7197 }
7198 }
7199#ifdef HAVE_MESSAGES
7200 else
7201 MHD_DLOG (daemon,
7202 _ ("MHD HTTPS option %d passed to MHD but " \
7203 "MHD_USE_TLS not set.\n"),
7204 opt);
7205#endif
7206 break;
7208#if GNUTLS_VERSION_MAJOR < 3
7209#ifdef HAVE_MESSAGES
7210 MHD_DLOG (daemon,
7211 _ ("MHD_OPTION_HTTPS_CERT_CALLBACK requires building " \
7212 "MHD with GnuTLS >= 3.0.\n"));
7213#endif
7214 return MHD_NO;
7215#else
7216 pgcrf = va_arg (ap,
7217 gnutls_certificate_retrieve_function2 *);
7218 if (0 != (daemon->options & MHD_USE_TLS))
7219 daemon->cert_callback = pgcrf;
7220#ifdef HAVE_MESSAGES
7221 else
7222 MHD_DLOG (daemon,
7223 _ ("MHD HTTPS option %d passed to MHD but " \
7224 "MHD_USE_TLS not set.\n"),
7225 opt);
7226#endif /* HAVE_MESSAGES */
7227 break;
7228#endif
7230#if GNUTLS_VERSION_NUMBER < 0x030603
7231#ifdef HAVE_MESSAGES
7232 MHD_DLOG (daemon,
7233 _ ("MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building " \
7234 "MHD with GnuTLS >= 3.6.3.\n"));
7235#endif
7236 return MHD_NO;
7237#else
7238 pgcrf2 = va_arg (ap,
7239 gnutls_certificate_retrieve_function3 *);
7240 if (0 != (daemon->options & MHD_USE_TLS))
7241 daemon->cert_callback2 = pgcrf2;
7242#ifdef HAVE_MESSAGES
7243 else
7244 MHD_DLOG (daemon,
7245 _ ("MHD HTTPS option %d passed to MHD but " \
7246 "MHD_USE_TLS not set.\n"),
7247 opt);
7248#endif /* HAVE_MESSAGES */
7249 break;
7250#endif
7251#endif /* HTTPS_SUPPORT */
7252#ifdef DAUTH_SUPPORT
7255 daemon->digest_auth_rand_size = va_arg (ap,
7256 size_t);
7257 daemon->digest_auth_random = va_arg (ap,
7258 const char *);
7260 /* Set to some non-NULL value just to indicate that copy is required. */
7261 daemon->digest_auth_random_copy = daemon;
7262 else
7263 daemon->digest_auth_random_copy = NULL;
7264 break;
7266 daemon->nonce_nc_size = va_arg (ap,
7267 unsigned int);
7268 break;
7270 daemon->dauth_bind_type = va_arg (ap,
7271 unsigned int);
7272 if (0 != (daemon->dauth_bind_type & MHD_DAUTH_BIND_NONCE_URI_PARAMS))
7273 daemon->dauth_bind_type |= MHD_DAUTH_BIND_NONCE_URI;
7274 break;
7276 if (1)
7277 {
7278 unsigned int val;
7279 val = va_arg (ap,
7280 unsigned int);
7281 if (0 != val)
7282 daemon->dauth_def_nonce_timeout = val;
7283 }
7284 break;
7286 if (1)
7287 {
7288 uint32_t val;
7289 val = va_arg (ap,
7290 uint32_t);
7291 if (0 != val)
7292 daemon->dauth_def_max_nc = val;
7293 }
7294 break;
7295#else /* ! DAUTH_SUPPORT */
7302#ifdef HAVE_MESSAGES
7303 MHD_DLOG (daemon,
7304 _ ("Digest Auth is disabled for this build " \
7305 "of GNU libmicrohttpd.\n"));
7306#endif /* HAVE_MESSAGES */
7307 return MHD_NO;
7308#endif /* ! DAUTH_SUPPORT */
7310 params->listen_fd = va_arg (ap,
7311 MHD_socket);
7312 params->listen_fd_set = true;
7313 break;
7315#ifdef HAVE_MESSAGES
7316 daemon->custom_error_log = va_arg (ap,
7318 daemon->custom_error_log_cls = va_arg (ap,
7319 void *);
7320 if (1 != params->num_opts)
7321 MHD_DLOG (daemon,
7322 _ ("MHD_OPTION_EXTERNAL_LOGGER is not the first option "
7323 "specified for the daemon. Some messages may be "
7324 "printed by the standard MHD logger.\n"));
7325
7326#else
7327 (void) va_arg (ap,
7329 (void) va_arg (ap,
7330 void *);
7331#endif
7332 break;
7333#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7335 daemon->thread_stack_size = va_arg (ap,
7336 size_t);
7337 break;
7338#endif
7340#ifdef TCP_FASTOPEN
7341 daemon->fastopen_queue_size = va_arg (ap,
7342 unsigned int);
7343 break;
7344#else /* ! TCP_FASTOPEN */
7345#ifdef HAVE_MESSAGES
7346 MHD_DLOG (daemon,
7347 _ ("TCP fastopen is not supported on this platform.\n"));
7348#endif /* HAVE_MESSAGES */
7349 return MHD_NO;
7350#endif /* ! TCP_FASTOPEN */
7352 daemon->listening_address_reuse = va_arg (ap,
7353 unsigned int) ? 1 : -1;
7354 break;
7356 daemon->listen_backlog_size = va_arg (ap,
7357 unsigned int);
7358 break;
7360 daemon->client_discipline = va_arg (ap, int); /* Temporal assignment */
7361 /* Map to correct value */
7362 if (-1 >= daemon->client_discipline)
7363 daemon->client_discipline = -3;
7364 else if (1 <= daemon->client_discipline)
7365 daemon->client_discipline = 1;
7366#ifdef HAVE_MESSAGES
7367 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
7368 (1 != daemon->client_discipline) )
7369 {
7370 MHD_DLOG (daemon,
7371 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
7372 "another behaviour is specified by "
7373 "MHD_OPTION_STRICT_CLIENT.\n"));
7374 }
7375#endif /* HAVE_MESSAGES */
7376 break;
7378 daemon->client_discipline = va_arg (ap, int);
7379#ifdef HAVE_MESSAGES
7380 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
7381 (1 != daemon->client_discipline) )
7382 {
7383 MHD_DLOG (daemon,
7384 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
7385 "another behaviour is specified by "
7386 "MHD_OPTION_CLIENT_DISCIPLINE_LVL.\n"));
7387 }
7388#endif /* HAVE_MESSAGES */
7389 break;
7391 daemon->allow_bzero_in_url = va_arg (ap, int);
7392 if ((0 > daemon->allow_bzero_in_url) ||
7393 (2 < daemon->allow_bzero_in_url))
7394 daemon->allow_bzero_in_url = 1;
7395 break;
7396 case MHD_OPTION_ARRAY:
7397 params->num_opts--; /* Do not count MHD_OPTION_ARRAY */
7398 oa = va_arg (ap, struct MHD_OptionItem *);
7399 i = 0;
7400 while (MHD_OPTION_END != (opt = oa[i].option))
7401 {
7402 switch (opt)
7403 {
7404 /* all options taking 'size_t' */
7408 if (MHD_NO == parse_options (daemon,
7409 params,
7410 opt,
7411 (size_t) oa[i].value,
7413 return MHD_NO;
7414 break;
7415 /* all options taking 'unsigned int' */
7427 if (MHD_NO == parse_options (daemon,
7428 params,
7429 opt,
7430 (unsigned int) oa[i].value,
7432 return MHD_NO;
7433 break;
7434 /* all options taking 'enum' */
7436#ifdef HTTPS_SUPPORT
7437 if (MHD_NO == parse_options (daemon,
7438 params,
7439 opt,
7440 (gnutls_credentials_type_t) oa[i].value,
7442#endif /* HTTPS_SUPPORT */
7443 return MHD_NO;
7444 break;
7445 /* all options taking 'MHD_socket' */
7447 if (MHD_NO == parse_options (daemon,
7448 params,
7449 opt,
7450 (MHD_socket) oa[i].value,
7452 return MHD_NO;
7453 break;
7454 /* all options taking 'int' */
7461 if (MHD_NO == parse_options (daemon,
7462 params,
7463 opt,
7464 (int) oa[i].value,
7466 return MHD_NO;
7467 break;
7468 /* all options taking 'uint32_t' */
7470 if (MHD_NO == parse_options (daemon,
7471 params,
7472 opt,
7473 (uint32_t) oa[i].value,
7475 return MHD_NO;
7476 break;
7477 /* all options taking one pointer */
7486 case MHD_OPTION_ARRAY:
7489 if (MHD_NO == parse_options (daemon,
7490 params,
7491 opt,
7492 oa[i].ptr_value,
7494 return MHD_NO;
7495 break;
7496 /* all options taking two pointers */
7503 if (MHD_NO == parse_options (daemon,
7504 params,
7505 opt,
7506 (void *) oa[i].value,
7507 oa[i].ptr_value,
7509 return MHD_NO;
7510 break;
7511 /* options taking size_t-number followed by pointer */
7514 if (MHD_NO == parse_options (daemon,
7515 params,
7516 opt,
7517 (size_t) oa[i].value,
7518 oa[i].ptr_value,
7520 return MHD_NO;
7521 break;
7522 /* options taking socklen_t-number followed by pointer */
7524 if (MHD_NO == parse_options (daemon,
7525 params,
7526 opt,
7527 (socklen_t) oa[i].value,
7528 oa[i].ptr_value,
7530 return MHD_NO;
7531 break;
7532 case MHD_OPTION_END: /* Not possible */
7533 default:
7534 return MHD_NO;
7535 }
7536 i++;
7537 }
7538 break;
7540 daemon->unescape_callback = va_arg (ap,
7542 daemon->unescape_callback_cls = va_arg (ap,
7543 void *);
7544 break;
7545#ifdef HTTPS_SUPPORT
7547#if GNUTLS_VERSION_MAJOR >= 3
7548 daemon->cred_callback = va_arg (ap,
7550 daemon->cred_callback_cls = va_arg (ap,
7551 void *);
7552 break;
7553#else
7554 MHD_DLOG (daemon,
7555 _ ("MHD HTTPS option %d passed to MHD compiled " \
7556 "without GNUtls >= 3.\n"),
7557 opt);
7558 return MHD_NO;
7559#endif
7560#endif /* HTTPS_SUPPORT */
7562 if (! MHD_D_IS_USING_THREADS_ (daemon))
7563 daemon->sigpipe_blocked = ( (va_arg (ap,
7564 int)) != 0);
7565 else
7566 {
7567 (void) va_arg (ap,
7568 int);
7569 }
7570 break;
7572#ifdef HTTPS_SUPPORT
7573 daemon->disable_alpn = (va_arg (ap,
7574 int) != 0);
7575#else /* ! HTTPS_SUPPORT */
7576 (void) va_arg (ap, int);
7577#endif /* ! HTTPS_SUPPORT */
7578#ifdef HAVE_MESSAGES
7579 if (0 == (daemon->options & MHD_USE_TLS))
7580 MHD_DLOG (daemon,
7581 _ ("MHD HTTPS option %d passed to MHD " \
7582 "but MHD_USE_TLS not set.\n"),
7583 (int) opt);
7584#endif /* HAVE_MESSAGES */
7585 break;
7587 params->fdset_size_set = true;
7588 params->fdset_size = va_arg (ap,
7589 int);
7590 break;
7591#ifndef HTTPS_SUPPORT
7603#ifdef HAVE_MESSAGES
7604 MHD_DLOG (daemon,
7605 _ ("MHD HTTPS option %d passed to MHD "
7606 "compiled without HTTPS support.\n"),
7607 opt);
7608#endif
7609 return MHD_NO;
7610#endif /* HTTPS_SUPPORT */
7611 case MHD_OPTION_END: /* Not possible */
7612 default:
7613#ifdef HAVE_MESSAGES
7614 MHD_DLOG (daemon,
7615 _ ("Invalid option %d! (Did you terminate "
7616 "the list with MHD_OPTION_END?).\n"),
7617 opt);
7618#endif
7619 return MHD_NO;
7620 }
7621 }
7622 return MHD_YES;
7623}
7624
7625
7626#ifdef EPOLL_SUPPORT
7627static int
7628setup_epoll_fd (struct MHD_Daemon *daemon)
7629{
7630 int fd;
7631
7632#ifndef HAVE_MESSAGES
7633 (void) daemon; /* Mute compiler warning. */
7634#endif /* ! HAVE_MESSAGES */
7635
7636#ifdef USE_EPOLL_CREATE1
7637 fd = epoll_create1 (EPOLL_CLOEXEC);
7638#else /* ! USE_EPOLL_CREATE1 */
7639 fd = epoll_create (MAX_EVENTS);
7640#endif /* ! USE_EPOLL_CREATE1 */
7641 if (MHD_INVALID_SOCKET == fd)
7642 {
7643#ifdef HAVE_MESSAGES
7644 MHD_DLOG (daemon,
7645 _ ("Call to epoll_create1 failed: %s\n"),
7647#endif
7648 return MHD_INVALID_SOCKET;
7649 }
7650#if ! defined(USE_EPOLL_CREATE1)
7652 {
7653#ifdef HAVE_MESSAGES
7654 MHD_DLOG (daemon,
7655 _ ("Failed to set noninheritable mode on epoll FD.\n"));
7656#endif
7657 }
7658#endif /* ! USE_EPOLL_CREATE1 */
7659 return fd;
7660}
7661
7662
7671static enum MHD_Result
7672setup_epoll_to_listen (struct MHD_Daemon *daemon)
7673{
7674 struct epoll_event event;
7675 MHD_socket ls;
7676
7679 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
7680 (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) || \
7681 MHD_ITC_IS_VALID_ (daemon->itc) );
7682 daemon->epoll_fd = setup_epoll_fd (daemon);
7683 if (! MHD_D_IS_USING_THREADS_ (daemon)
7684 && (0 != (daemon->options & MHD_USE_AUTO)))
7685 {
7686 /* Application requested "MHD_USE_AUTO", probably MHD_get_fdset() will be
7687 used.
7688 Make sure that epoll FD is suitable for fd_set.
7689 Actually, MHD_get_fdset() is allowed for MHD_USE_EPOLL direct,
7690 but most probably direct requirement for MHD_USE_EPOLL means that
7691 epoll FD will be used directly. This logic is fuzzy, but better
7692 than nothing with current MHD API. */
7693 if (! MHD_D_DOES_SCKT_FIT_FDSET_ (daemon->epoll_fd, daemon))
7694 {
7695#ifdef HAVE_MESSAGES
7696 MHD_DLOG (daemon,
7697 _ ("The epoll FD is too large to be used with fd_set.\n"));
7698#endif /* HAVE_MESSAGES */
7699 return MHD_NO;
7700 }
7701 }
7702 if (-1 == daemon->epoll_fd)
7703 return MHD_NO;
7704#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7705 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
7706 {
7707 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
7708 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
7709 return MHD_NO;
7710 }
7711#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7712 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
7713 (! daemon->was_quiesced) )
7714 {
7715 event.events = EPOLLIN | EPOLLRDHUP;
7716 event.data.ptr = daemon;
7717 if (0 != epoll_ctl (daemon->epoll_fd,
7718 EPOLL_CTL_ADD,
7719 ls,
7720 &event))
7721 {
7722#ifdef HAVE_MESSAGES
7723 MHD_DLOG (daemon,
7724 _ ("Call to epoll_ctl failed: %s\n"),
7726#endif
7727 return MHD_NO;
7728 }
7729 daemon->listen_socket_in_epoll = true;
7730 }
7731
7732 if (MHD_ITC_IS_VALID_ (daemon->itc))
7733 {
7734 event.events = EPOLLIN | EPOLLRDHUP;
7735 event.data.ptr = _MHD_DROP_CONST (epoll_itc_marker);
7736 if (0 != epoll_ctl (daemon->epoll_fd,
7737 EPOLL_CTL_ADD,
7738 MHD_itc_r_fd_ (daemon->itc),
7739 &event))
7740 {
7741#ifdef HAVE_MESSAGES
7742 MHD_DLOG (daemon,
7743 _ ("Call to epoll_ctl failed: %s\n"),
7745#endif
7746 return MHD_NO;
7747 }
7748 }
7749 return MHD_YES;
7750}
7751
7752
7753#endif
7754
7755
7767static bool
7769 const struct sockaddr **ppsockaddr,
7770 socklen_t *psockaddr_len,
7771 struct MHD_InterimParams_ *params)
7772{
7773 if (params->fdset_size_set)
7774 {
7775 if (0 >= params->fdset_size)
7776 {
7777#ifdef HAVE_MESSAGES
7778 MHD_DLOG (d,
7779 _ ("MHD_OPTION_APP_FD_SETSIZE value (%d) is not positive.\n"),
7780 params->fdset_size);
7781#endif /* HAVE_MESSAGES */
7782 return false;
7783 }
7785 {
7786#ifdef HAVE_MESSAGES
7787 MHD_DLOG (d,
7788 _ ("MHD_OPTION_APP_FD_SETSIZE is ignored for daemon started " \
7789 "with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
7790#endif /* HAVE_MESSAGES */
7791 (void) 0;
7792 }
7793 else if (MHD_D_IS_USING_POLL_ (d))
7794 {
7795#ifdef HAVE_MESSAGES
7796 MHD_DLOG (d,
7797 _ ("MHD_OPTION_APP_FD_SETSIZE is ignored for daemon started " \
7798 "with MHD_USE_POLL.\n"));
7799#endif /* HAVE_MESSAGES */
7800 (void) 0;
7801 }
7802 else
7803 { /* The daemon without internal threads, external sockets polling */
7804#ifndef HAS_FD_SETSIZE_OVERRIDABLE
7805 if (((int) FD_SETSIZE) != params->fdset_size)
7806 {
7807#ifdef HAVE_MESSAGES
7808 MHD_DLOG (d,
7809 _ ("MHD_OPTION_APP_FD_SETSIZE value (%d) does not match " \
7810 "the platform FD_SETSIZE value (%d) and this platform " \
7811 "does not support overriding of FD_SETSIZE.\n"),
7812 params->fdset_size, (int) FD_SETSIZE);
7813#endif /* HAVE_MESSAGES */
7814 return false;
7815 }
7816#else /* HAS_FD_SETSIZE_OVERRIDABLE */
7817 d->fdset_size = params->fdset_size;
7818 d->fdset_size_set_by_app = true;
7819#endif /* HAS_FD_SETSIZE_OVERRIDABLE */
7820 }
7821 }
7822
7823 if (params->listen_fd_set)
7824 {
7825 if (MHD_INVALID_SOCKET == params->listen_fd)
7826 {
7827 (void) 0; /* Use MHD-created socket */
7828 }
7829#ifdef HAS_SIGNED_SOCKET
7830 else if (0 > params->listen_fd)
7831 {
7832#ifdef HAVE_MESSAGES
7833 MHD_DLOG (d,
7834 _ ("The value provided for MHD_OPTION_LISTEN_SOCKET " \
7835 "is invalid.\n"));
7836#endif /* HAVE_MESSAGES */
7837 return false;
7838 }
7839#endif /* HAS_SIGNED_SOCKET */
7840 else if (0 != (d->options & MHD_USE_NO_LISTEN_SOCKET))
7841 {
7842#ifdef HAVE_MESSAGES
7843 MHD_DLOG (d,
7844 _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
7845 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
7846#endif /* HAVE_MESSAGES */
7847 (void) MHD_socket_close_ (params->listen_fd);
7848 return false;
7849 }
7850 else
7851 {
7852 d->listen_fd = params->listen_fd;
7854#ifdef MHD_USE_GETSOCKNAME
7855 d->port = 0; /* Force use of autodetection */
7856#endif /* MHD_USE_GETSOCKNAME */
7857 }
7858 }
7859
7860 mhd_assert (! params->server_addr_len_set || params->pserver_addr_set);
7861 if (params->pserver_addr_set)
7862 {
7863 if (NULL == params->pserver_addr)
7864 {
7865 /* The size must be zero if set */
7866 if (params->server_addr_len_set && (0 != params->server_addr_len))
7867 return false;
7868 /* Ignore parameter if it is NULL */
7869 }
7870 else if (MHD_INVALID_SOCKET != d->listen_fd)
7871 {
7872#ifdef HAVE_MESSAGES
7873 MHD_DLOG (d,
7874 _ ("MHD_OPTION_LISTEN_SOCKET cannot be used together with " \
7875 "MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR.\n"));
7876#endif /* HAVE_MESSAGES */
7877 return false;
7878 }
7879 else if (0 != (d->options & MHD_USE_NO_LISTEN_SOCKET))
7880 {
7881#ifdef HAVE_MESSAGES
7882 MHD_DLOG (d,
7883 _ ("MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR " \
7884 "specified for daemon with MHD_USE_NO_LISTEN_SOCKET " \
7885 "flag set.\n"));
7886#endif /* HAVE_MESSAGES */
7887 if (MHD_INVALID_SOCKET != d->listen_fd)
7888 {
7889 (void) MHD_socket_close_ (params->listen_fd);
7890 params->listen_fd = MHD_INVALID_SOCKET;
7891 }
7892 return false;
7893 }
7894 else
7895 {
7896 *ppsockaddr = params->pserver_addr;
7897 if (params->server_addr_len_set)
7898 {
7899 /* The size must be non-zero if set */
7900 if (0 == params->server_addr_len)
7901 return false;
7902 *psockaddr_len = params->server_addr_len;
7903 }
7904 else
7905 *psockaddr_len = 0;
7906 }
7907 }
7908 return true;
7909}
7910
7911
7933_MHD_EXTERN struct MHD_Daemon *
7934MHD_start_daemon_va (unsigned int flags,
7935 uint16_t port,
7937 void *apc_cls,
7939 void *dh_cls,
7940 va_list ap)
7941{
7942 const MHD_SCKT_OPT_BOOL_ on = 1;
7943 struct MHD_Daemon *daemon;
7944 const struct sockaddr *pservaddr = NULL;
7945 socklen_t addrlen;
7946#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7947 unsigned int i;
7948#endif
7949 enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
7950 enum MHD_FLAG *pflags;
7951 struct MHD_InterimParams_ *interim_params;
7952
7954 eflags = (enum MHD_FLAG) flags;
7955 pflags = &eflags;
7956
7957 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
7958 *pflags |= MHD_USE_INTERNAL_POLLING_THREAD; /* Force enable, log warning later if needed */
7959
7960#ifndef HAVE_INET6
7961 if (0 != (*pflags & MHD_USE_IPv6))
7962 return NULL;
7963#endif
7964#ifndef HAVE_POLL
7965 if (0 != (*pflags & MHD_USE_POLL))
7966 return NULL;
7967#endif
7968#ifndef EPOLL_SUPPORT
7969 if (0 != (*pflags & MHD_USE_EPOLL))
7970 return NULL;
7971#endif /* ! EPOLL_SUPPORT */
7972#ifndef HTTPS_SUPPORT
7973 if (0 != (*pflags & MHD_USE_TLS))
7974 return NULL;
7975#endif /* ! HTTPS_SUPPORT */
7976#ifndef TCP_FASTOPEN
7977 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
7978 return NULL;
7979#endif
7980 if (0 != (*pflags & MHD_ALLOW_UPGRADE))
7981 {
7982#ifdef UPGRADE_SUPPORT
7983 *pflags |= MHD_ALLOW_SUSPEND_RESUME;
7984#else /* ! UPGRADE_SUPPORT */
7985 return NULL;
7986#endif /* ! UPGRADE_SUPPORT */
7987 }
7988#ifdef MHD_USE_THREADS
7991 & *pflags))
7992 return NULL; /* Cannot be thread-unsafe with multiple threads */
7993#else /* ! MHD_USE_THREADS */
7994 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7995 return NULL;
7996#endif /* ! MHD_USE_THREADS */
7997
7998 if (NULL == dh)
7999 return NULL;
8000
8001 /* Check for invalid combinations of flags. */
8002 if ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL)))
8003 return NULL;
8004 if ((0 != (*pflags & MHD_USE_EPOLL)) &&
8005 (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)))
8006 return NULL;
8007 if ((0 != (*pflags & MHD_USE_POLL)) &&
8008 (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
8010 return NULL;
8011 if ((0 != (*pflags & MHD_USE_AUTO)) &&
8012 (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))))
8013 return NULL;
8014
8015 if (0 != (*pflags & MHD_USE_AUTO))
8016 {
8017#if defined(EPOLL_SUPPORT) && defined(HAVE_POLL)
8018 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
8019 *pflags |= MHD_USE_POLL;
8020 else
8021 *pflags |= MHD_USE_EPOLL; /* Including "external select" mode */
8022#elif defined(HAVE_POLL)
8023 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
8024 *pflags |= MHD_USE_POLL; /* Including thread-per-connection */
8025#elif defined(EPOLL_SUPPORT)
8026 if (0 == (*pflags & MHD_USE_THREAD_PER_CONNECTION))
8027 *pflags |= MHD_USE_EPOLL; /* Including "external select" mode */
8028#else
8029 /* No choice: use select() for any mode - do not modify flags */
8030#endif
8031 }
8032
8033 if (0 != (*pflags & MHD_USE_NO_THREAD_SAFETY))
8034 *pflags = (*pflags & ~((enum MHD_FLAG) MHD_USE_ITC)); /* useless in single-threaded environment */
8035 else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
8036 {
8037#ifdef HAVE_LISTEN_SHUTDOWN
8038 if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
8039#endif
8040 *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
8041 }
8042
8043 if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
8044 return NULL;
8045 interim_params = (struct MHD_InterimParams_ *) \
8046 MHD_calloc_ (1, sizeof (struct MHD_InterimParams_));
8047 if (NULL == interim_params)
8048 {
8049 int err_num = errno;
8050 free (daemon);
8051 errno = err_num;
8052 return NULL;
8053 }
8054#ifdef EPOLL_SUPPORT
8055 daemon->epoll_fd = -1;
8056#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
8057 daemon->epoll_upgrade_fd = -1;
8058#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
8059#endif
8060 /* try to open listen socket */
8061#ifdef HTTPS_SUPPORT
8062 daemon->priority_cache = NULL;
8063#endif /* HTTPS_SUPPORT */
8064 daemon->listen_fd = MHD_INVALID_SOCKET;
8065 daemon->listen_is_unix = _MHD_NO;
8066 daemon->listening_address_reuse = 0;
8067 daemon->options = *pflags;
8068 pflags = &daemon->options;
8069 daemon->client_discipline = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ?
8070 1 : 0;
8071 daemon->port = port;
8072 daemon->apc = apc;
8073 daemon->apc_cls = apc_cls;
8074 daemon->default_handler = dh;
8075 daemon->default_handler_cls = dh_cls;
8076 daemon->connections = 0;
8081 daemon->connection_timeout_ms = 0; /* no timeout */
8082 MHD_itc_set_invalid_ (daemon->itc);
8083#ifdef MHD_USE_THREADS
8084 MHD_thread_handle_ID_set_invalid_ (&daemon->tid);
8085#endif /* MHD_USE_THREADS */
8086#ifdef SOMAXCONN
8087 daemon->listen_backlog_size = SOMAXCONN;
8088#else /* !SOMAXCONN */
8089 daemon->listen_backlog_size = 511; /* should be safe value */
8090#endif /* !SOMAXCONN */
8091#ifdef HAVE_MESSAGES
8092 daemon->custom_error_log = &MHD_default_logger_;
8093 daemon->custom_error_log_cls = stderr;
8094#endif
8095#ifndef MHD_WINSOCK_SOCKETS
8096 daemon->sigpipe_blocked = false;
8097#else /* MHD_WINSOCK_SOCKETS */
8098 /* There is no SIGPIPE on W32, nothing to block. */
8099 daemon->sigpipe_blocked = true;
8100#endif /* _WIN32 && ! __CYGWIN__ */
8101#if defined(_DEBUG) && defined(HAVE_ACCEPT4)
8102 daemon->avoid_accept4 = false;
8103#endif /* _DEBUG */
8104#ifdef HAS_FD_SETSIZE_OVERRIDABLE
8105 daemon->fdset_size = (int) FD_SETSIZE;
8106 daemon->fdset_size_set_by_app = false;
8107#endif /* HAS_FD_SETSIZE_OVERRIDABLE */
8108
8109#ifdef DAUTH_SUPPORT
8110 daemon->digest_auth_rand_size = 0;
8111 daemon->digest_auth_random = NULL;
8112 daemon->nonce_nc_size = 4; /* tiny */
8113 daemon->dauth_def_nonce_timeout = MHD_DAUTH_DEF_TIMEOUT_;
8114 daemon->dauth_def_max_nc = MHD_DAUTH_DEF_MAX_NC_;
8115#endif
8116#ifdef HTTPS_SUPPORT
8117 if (0 != (*pflags & MHD_USE_TLS))
8118 {
8119 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
8120 }
8121#endif /* HTTPS_SUPPORT */
8122
8123 interim_params->num_opts = 0;
8124 interim_params->fdset_size_set = false;
8125 interim_params->fdset_size = 0;
8126 interim_params->listen_fd_set = false;
8127 interim_params->listen_fd = MHD_INVALID_SOCKET;
8128 interim_params->pserver_addr_set = false;
8129 interim_params->pserver_addr = NULL;
8130 interim_params->server_addr_len_set = false;
8131 interim_params->server_addr_len = 0;
8132
8133 if (MHD_NO == parse_options_va (daemon,
8134 interim_params,
8135 ap))
8136 {
8137#ifdef HTTPS_SUPPORT
8138 tls_cleanup_failed_start (daemon);
8139#endif /* HTTPS_SUPPORT */
8140 free (interim_params);
8141 free (daemon);
8142 return NULL;
8143 }
8144 if (! process_interim_params (daemon,
8145 &pservaddr,
8146 &addrlen,
8147 interim_params))
8148 {
8149#ifdef HTTPS_SUPPORT
8150 tls_cleanup_failed_start (daemon);
8151#endif /* HTTPS_SUPPORT */
8152 free (interim_params);
8153 free (daemon);
8154 return NULL;
8155 }
8156 free (interim_params);
8157 interim_params = NULL;
8158#ifdef HTTPS_SUPPORT
8159 if ((0 != (*pflags & MHD_USE_TLS))
8160 && (NULL == daemon->priority_cache)
8161 && ! daemon_tls_priorities_init_default (daemon))
8162 {
8163#ifdef HAVE_MESSAGES
8164 MHD_DLOG (daemon,
8165 _ ("Failed to initialise GnuTLS priorities.\n"));
8166#endif /* HAVE_MESSAGES */
8167 tls_cleanup_failed_start (daemon);
8168 free (daemon);
8169 return NULL;
8170 }
8171#endif /* HTTPS_SUPPORT */
8172
8173#ifdef HAVE_MESSAGES
8174 if ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) &&
8175 (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD)) )
8176 {
8177 MHD_DLOG (daemon,
8178 _ ("Warning: MHD_USE_THREAD_PER_CONNECTION must be used " \
8179 "only with MHD_USE_INTERNAL_POLLING_THREAD. " \
8180 "Flag MHD_USE_INTERNAL_POLLING_THREAD was added. " \
8181 "Consider setting MHD_USE_INTERNAL_POLLING_THREAD " \
8182 "explicitly.\n"));
8183 }
8184#endif
8185
8187 && ((NULL != daemon->notify_completed)
8188 || (NULL != daemon->notify_connection)) )
8189 *pflags |= MHD_USE_ITC; /* requires ITC */
8190
8191#ifdef _DEBUG
8192#ifdef HAVE_MESSAGES
8193 MHD_DLOG (daemon,
8194 _ ("Using debug build of libmicrohttpd.\n") );
8195#endif /* HAVE_MESSAGES */
8196#endif /* _DEBUG */
8197
8198 if ( (0 != (*pflags & MHD_USE_ITC))
8199#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8200 && (0 == daemon->worker_pool_size)
8201#endif
8202 )
8203 {
8204 if (! MHD_itc_init_ (daemon->itc))
8205 {
8206#ifdef HAVE_MESSAGES
8207 MHD_DLOG (daemon,
8208 _ ("Failed to create inter-thread communication channel: %s\n"),
8209 MHD_itc_last_strerror_ ());
8210#endif
8211#ifdef HTTPS_SUPPORT
8212 if (NULL != daemon->priority_cache)
8213 gnutls_priority_deinit (daemon->priority_cache);
8214#endif /* HTTPS_SUPPORT */
8215 free (daemon);
8216 return NULL;
8217 }
8218 if (MHD_D_IS_USING_SELECT_ (daemon) &&
8219 (! MHD_D_DOES_SCKT_FIT_FDSET_ (MHD_itc_r_fd_ (daemon->itc), daemon)) )
8220 {
8221#ifdef HAVE_MESSAGES
8222 MHD_DLOG (daemon,
8223 _ ("file descriptor for inter-thread communication " \
8224 "channel exceeds maximum value.\n"));
8225#endif
8226 MHD_itc_destroy_chk_ (daemon->itc);
8227#ifdef HTTPS_SUPPORT
8228 if (NULL != daemon->priority_cache)
8229 gnutls_priority_deinit (daemon->priority_cache);
8230#endif /* HTTPS_SUPPORT */
8231 free (daemon);
8232 return NULL;
8233 }
8234 }
8235
8236#ifdef DAUTH_SUPPORT
8237 if (NULL != daemon->digest_auth_random_copy)
8238 {
8239 mhd_assert (daemon == daemon->digest_auth_random_copy);
8240 daemon->digest_auth_random_copy = malloc (daemon->digest_auth_rand_size);
8241 if (NULL == daemon->digest_auth_random_copy)
8242 {
8243#ifdef HTTPS_SUPPORT
8244 if (0 != (*pflags & MHD_USE_TLS))
8245 gnutls_priority_deinit (daemon->priority_cache);
8246#endif /* HTTPS_SUPPORT */
8247 free (daemon);
8248 return NULL;
8249 }
8250 memcpy (daemon->digest_auth_random_copy,
8251 daemon->digest_auth_random,
8252 daemon->digest_auth_rand_size);
8253 daemon->digest_auth_random = daemon->digest_auth_random_copy;
8254 }
8255 if (daemon->nonce_nc_size > 0)
8256 {
8257 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
8258 / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
8259 {
8260#ifdef HAVE_MESSAGES
8261 MHD_DLOG (daemon,
8262 _ ("Specified value for NC_SIZE too large.\n"));
8263#endif
8264#ifdef HTTPS_SUPPORT
8265 if (0 != (*pflags & MHD_USE_TLS))
8266 gnutls_priority_deinit (daemon->priority_cache);
8267#endif /* HTTPS_SUPPORT */
8268 free (daemon->digest_auth_random_copy);
8269 free (daemon);
8270 return NULL;
8271 }
8272 daemon->nnc = MHD_calloc_ (daemon->nonce_nc_size,
8273 sizeof (struct MHD_NonceNc));
8274 if (NULL == daemon->nnc)
8275 {
8276#ifdef HAVE_MESSAGES
8277 MHD_DLOG (daemon,
8278 _ ("Failed to allocate memory for nonce-nc map: %s\n"),
8279 MHD_strerror_ (errno));
8280#endif
8281#ifdef HTTPS_SUPPORT
8282 if (0 != (*pflags & MHD_USE_TLS))
8283 gnutls_priority_deinit (daemon->priority_cache);
8284#endif /* HTTPS_SUPPORT */
8285 free (daemon->digest_auth_random_copy);
8286 free (daemon);
8287 return NULL;
8288 }
8289 }
8290
8291#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8292 if (! MHD_mutex_init_ (&daemon->nnc_lock))
8293 {
8294#ifdef HAVE_MESSAGES
8295 MHD_DLOG (daemon,
8296 _ ("MHD failed to initialize nonce-nc mutex.\n"));
8297#endif
8298#ifdef HTTPS_SUPPORT
8299 if (0 != (*pflags & MHD_USE_TLS))
8300 gnutls_priority_deinit (daemon->priority_cache);
8301#endif /* HTTPS_SUPPORT */
8302 free (daemon->digest_auth_random_copy);
8303 free (daemon->nnc);
8304 free (daemon);
8305 return NULL;
8306 }
8307#endif
8308#endif
8309
8310 /* Thread polling currently works only with internal select thread mode */
8311#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8312 if ( (! MHD_D_IS_USING_THREADS_ (daemon)) &&
8313 (daemon->worker_pool_size > 0) )
8314 {
8315#ifdef HAVE_MESSAGES
8316 MHD_DLOG (daemon,
8317 _ ("MHD thread polling only works with " \
8318 "MHD_USE_INTERNAL_POLLING_THREAD.\n"));
8319#endif
8320 goto free_and_fail;
8321 }
8322#endif
8323
8324 if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
8325 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
8326 {
8327 /* try to open listen socket */
8328 struct sockaddr_in servaddr4;
8329#ifdef HAVE_INET6
8330 struct sockaddr_in6 servaddr6;
8331 const bool use_ipv6 = (0 != (*pflags & MHD_USE_IPv6));
8332#else /* ! HAVE_INET6 */
8333 const bool use_ipv6 = false;
8334#endif /* ! HAVE_INET6 */
8335 int domain;
8336
8337 if (NULL != pservaddr)
8338 {
8339#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8340 const socklen_t sa_len = pservaddr->sa_len;
8341#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8342#ifdef HAVE_INET6
8343 if (use_ipv6 && (AF_INET6 != pservaddr->sa_family))
8344 {
8345#ifdef HAVE_MESSAGES
8346 MHD_DLOG (daemon,
8347 _ ("MHD_USE_IPv6 is enabled, but 'struct sockaddr *' " \
8348 "specified for MHD_OPTION_SOCK_ADDR_LEN or " \
8349 "MHD_OPTION_SOCK_ADDR is not IPv6 address.\n"));
8350#endif /* HAVE_MESSAGES */
8351 goto free_and_fail;
8352 }
8353#endif /* HAVE_INET6 */
8354 switch (pservaddr->sa_family)
8355 {
8356 case AF_INET:
8357 if (1)
8358 {
8359 struct sockaddr_in sa4;
8360 uint16_t sa4_port;
8361 if ((0 != addrlen)
8362 && (((socklen_t) sizeof(sa4)) > addrlen))
8363 {
8364#ifdef HAVE_MESSAGES
8365 MHD_DLOG (daemon,
8366 _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
8367 "option is wrong.\n"));
8368#endif /* HAVE_MESSAGES */
8369 goto free_and_fail;
8370 }
8371#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8372 if (0 != sa_len)
8373 {
8374 if (((socklen_t) sizeof(sa4)) > sa_len)
8375 {
8376#ifdef HAVE_MESSAGES
8377 MHD_DLOG (daemon,
8378 _ ("The value of 'struct sockaddr.sa_len' provided " \
8379 "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
8380 "and does not match 'sa_family' value of the " \
8381 "same structure.\n"));
8382#endif /* HAVE_MESSAGES */
8383 goto free_and_fail;
8384 }
8385 if ((0 == addrlen) || (sa_len < addrlen))
8386 addrlen = sa_len; /* Use smaller value for safety */
8387 }
8388#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8389 if (0 == addrlen)
8390 addrlen = sizeof(sa4);
8391 memcpy (&sa4, pservaddr, sizeof(sa4)); /* Required due to stronger alignment */
8392 sa4_port = (uint16_t) ntohs (sa4.sin_port);
8393#ifndef MHD_USE_GETSOCKNAME
8394 if (0 != sa4_port)
8395#endif /* ! MHD_USE_GETSOCKNAME */
8396 daemon->port = sa4_port;
8397 domain = PF_INET;
8398 }
8399 break;
8400#ifdef HAVE_INET6
8401 case AF_INET6:
8402 if (1)
8403 {
8404 struct sockaddr_in6 sa6;
8405 uint16_t sa6_port;
8406 if ((0 != addrlen)
8407 && (((socklen_t) sizeof(sa6)) > addrlen))
8408 {
8409#ifdef HAVE_MESSAGES
8410 MHD_DLOG (daemon,
8411 _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
8412 "option is wrong.\n"));
8413#endif /* HAVE_MESSAGES */
8414 goto free_and_fail;
8415 }
8416#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8417 if (0 != sa_len)
8418 {
8419 if (((socklen_t) sizeof(sa6)) > sa_len)
8420 {
8421#ifdef HAVE_MESSAGES
8422 MHD_DLOG (daemon,
8423 _ ("The value of 'struct sockaddr.sa_len' provided " \
8424 "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
8425 "and does not match 'sa_family' value of the " \
8426 "same structure.\n"));
8427#endif /* HAVE_MESSAGES */
8428 goto free_and_fail;
8429 }
8430 if ((0 == addrlen) || (sa_len < addrlen))
8431 addrlen = sa_len; /* Use smaller value for safety */
8432 }
8433#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8434 if (0 == addrlen)
8435 addrlen = sizeof(sa6);
8436 memcpy (&sa6, pservaddr, sizeof(sa6)); /* Required due to stronger alignment */
8437 sa6_port = (uint16_t) ntohs (sa6.sin6_port);
8438#ifndef MHD_USE_GETSOCKNAME
8439 if (0 != sa6_port)
8440#endif /* ! MHD_USE_GETSOCKNAME */
8441 daemon->port = sa6_port;
8442 domain = PF_INET6;
8443 *pflags |= ((enum MHD_FLAG) MHD_USE_IPv6);
8444 }
8445 break;
8446#endif /* HAVE_INET6 */
8447#ifdef AF_UNIX
8448 case AF_UNIX:
8449#endif /* AF_UNIX */
8450 default:
8451#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8452 if (0 == addrlen)
8453 addrlen = sa_len;
8454 else if ((0 != sa_len) && (sa_len < addrlen))
8455 addrlen = sa_len; /* Use smaller value for safety */
8456#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8457 if (0 >= addrlen)
8458 {
8459#ifdef HAVE_MESSAGES
8460 MHD_DLOG (daemon,
8461 _ ("The 'sa_family' of the 'struct sockaddr' provided " \
8462 "via MHD_OPTION_SOCK_ADDR option is not supported.\n"));
8463#endif /* HAVE_MESSAGES */
8464 goto free_and_fail;
8465 }
8466#ifdef AF_UNIX
8467 if (AF_UNIX == pservaddr->sa_family)
8468 {
8469 daemon->port = 0; /* special value for UNIX domain sockets */
8470 daemon->listen_is_unix = _MHD_YES;
8471#ifdef PF_UNIX
8472 domain = PF_UNIX;
8473#else /* ! PF_UNIX */
8474 domain = AF_UNIX;
8475#endif /* ! PF_UNIX */
8476 }
8477 else /* combined with the next 'if' */
8478#endif /* AF_UNIX */
8479 if (1)
8480 {
8481 daemon->port = 0; /* ugh */
8482 daemon->listen_is_unix = _MHD_UNKNOWN;
8483 /* Assumed the same values for AF_* and PF_* */
8484 domain = pservaddr->sa_family;
8485 }
8486 break;
8487 }
8488 }
8489 else
8490 {
8491 if (! use_ipv6)
8492 {
8493 memset (&servaddr4,
8494 0,
8495 sizeof (struct sockaddr_in));
8496 servaddr4.sin_family = AF_INET;
8497 servaddr4.sin_port = htons (port);
8498 if (0 != INADDR_ANY)
8499 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
8500#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
8501 servaddr4.sin_len = sizeof (struct sockaddr_in);
8502#endif
8503 pservaddr = (struct sockaddr *) &servaddr4;
8504 addrlen = (socklen_t) sizeof(servaddr4);
8505 daemon->listen_is_unix = _MHD_NO;
8506 domain = PF_INET;
8507 }
8508#ifdef HAVE_INET6
8509 else
8510 {
8511#ifdef IN6ADDR_ANY_INIT
8512 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
8513#endif
8514 memset (&servaddr6,
8515 0,
8516 sizeof (struct sockaddr_in6));
8517 servaddr6.sin6_family = AF_INET6;
8518 servaddr6.sin6_port = htons (port);
8519#ifdef IN6ADDR_ANY_INIT
8520 servaddr6.sin6_addr = static_in6any;
8521#endif
8522#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
8523 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
8524#endif
8525 pservaddr = (struct sockaddr *) &servaddr6;
8526 addrlen = (socklen_t) sizeof (servaddr6);
8527 daemon->listen_is_unix = _MHD_NO;
8528 domain = PF_INET6;
8529 }
8530#endif /* HAVE_INET6 */
8531 }
8532
8533 daemon->listen_fd = MHD_socket_create_listen_ (domain);
8534 if (MHD_INVALID_SOCKET == daemon->listen_fd)
8535 {
8536#ifdef HAVE_MESSAGES
8537 MHD_DLOG (daemon,
8538 _ ("Failed to create socket for listening: %s\n"),
8540#endif
8541 goto free_and_fail;
8542 }
8543 if (MHD_D_IS_USING_SELECT_ (daemon) &&
8545 daemon)) )
8546 {
8547#ifdef HAVE_MESSAGES
8548 MHD_DLOG (daemon,
8549 _ ("Listen socket descriptor (%d) is not " \
8550 "less than daemon FD_SETSIZE value (%d).\n"),
8551 (int) daemon->listen_fd,
8552 (int) MHD_D_GET_FD_SETSIZE_ (daemon));
8553#endif
8554 goto free_and_fail;
8555 }
8556
8557 /* Apply the socket options according to listening_address_reuse. */
8558 if (0 == daemon->listening_address_reuse)
8559 {
8560#ifndef MHD_WINSOCK_SOCKETS
8561 /* No user requirement, use "traditional" default SO_REUSEADDR
8562 * on non-W32 platforms, and do not fail if it doesn't work.
8563 * Don't use it on W32, because on W32 it will allow multiple
8564 * bind to the same address:port, like SO_REUSEPORT on others. */
8565 if (0 > setsockopt (daemon->listen_fd,
8566 SOL_SOCKET,
8567 SO_REUSEADDR,
8568 (const void *) &on, sizeof (on)))
8569 {
8570#ifdef HAVE_MESSAGES
8571 MHD_DLOG (daemon,
8572 _ ("setsockopt failed: %s\n"),
8574#endif
8575 }
8576#endif /* ! MHD_WINSOCK_SOCKETS */
8577 }
8578 else if (daemon->listening_address_reuse > 0)
8579 {
8580 /* User requested to allow reusing listening address:port. */
8581#ifndef MHD_WINSOCK_SOCKETS
8582 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
8583 * it doesn't work. */
8584 if (0 > setsockopt (daemon->listen_fd,
8585 SOL_SOCKET,
8586 SO_REUSEADDR,
8587 (const void *) &on, sizeof (on)))
8588 {
8589#ifdef HAVE_MESSAGES
8590 MHD_DLOG (daemon,
8591 _ ("setsockopt failed: %s\n"),
8593#endif
8594 }
8595#endif /* ! MHD_WINSOCK_SOCKETS */
8596 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
8597 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
8598 */
8599 /* SO_REUSEADDR on W32 has the same semantics
8600 as SO_REUSEPORT on BSD/Linux */
8601#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
8602 if (0 > setsockopt (daemon->listen_fd,
8603 SOL_SOCKET,
8604#ifndef MHD_WINSOCK_SOCKETS
8605 SO_REUSEPORT,
8606#else /* MHD_WINSOCK_SOCKETS */
8607 SO_REUSEADDR,
8608#endif /* MHD_WINSOCK_SOCKETS */
8609 (const void *) &on,
8610 sizeof (on)))
8611 {
8612#ifdef HAVE_MESSAGES
8613 MHD_DLOG (daemon,
8614 _ ("setsockopt failed: %s\n"),
8616#endif
8617 goto free_and_fail;
8618 }
8619#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
8620 /* we're supposed to allow address:port re-use, but
8621 on this platform we cannot; fail hard */
8622#ifdef HAVE_MESSAGES
8623 MHD_DLOG (daemon,
8624 _ ("Cannot allow listening address reuse: " \
8625 "SO_REUSEPORT not defined.\n"));
8626#endif
8627 goto free_and_fail;
8628#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
8629 }
8630 else /* if (daemon->listening_address_reuse < 0) */
8631 {
8632 /* User requested to disallow reusing listening address:port.
8633 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
8634 * is used and Solaris with SO_EXCLBIND.
8635 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
8636 * or setsockopt fails.
8637 */
8638#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
8639 (defined(__sun) && defined(SO_EXCLBIND))
8640 if (0 > setsockopt (daemon->listen_fd,
8641 SOL_SOCKET,
8642#ifdef SO_EXCLUSIVEADDRUSE
8643 SO_EXCLUSIVEADDRUSE,
8644#else /* SO_EXCLBIND */
8645 SO_EXCLBIND,
8646#endif /* SO_EXCLBIND */
8647 (const void *) &on,
8648 sizeof (on)))
8649 {
8650#ifdef HAVE_MESSAGES
8651 MHD_DLOG (daemon,
8652 _ ("setsockopt failed: %s\n"),
8654#endif
8655 goto free_and_fail;
8656 }
8657#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
8658#ifdef HAVE_MESSAGES
8659 MHD_DLOG (daemon,
8660 _ ("Cannot disallow listening address reuse: " \
8661 "SO_EXCLUSIVEADDRUSE not defined.\n"));
8662#endif
8663 goto free_and_fail;
8664#endif /* MHD_WINSOCK_SOCKETS */
8665 }
8666
8667 /* check for user supplied sockaddr */
8668 if (0 != (*pflags & MHD_USE_IPv6))
8669 {
8670#ifdef IPPROTO_IPV6
8671#ifdef IPV6_V6ONLY
8672 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
8673 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
8674 and may also be missing on older POSIX systems; good luck if you have any of those,
8675 your IPv6 socket may then also bind against IPv4 anyway... */
8676 const MHD_SCKT_OPT_BOOL_ v6_only =
8677 (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
8678 if (0 > setsockopt (daemon->listen_fd,
8679 IPPROTO_IPV6, IPV6_V6ONLY,
8680 (const void *) &v6_only,
8681 sizeof (v6_only)))
8682 {
8683#ifdef HAVE_MESSAGES
8684 MHD_DLOG (daemon,
8685 _ ("setsockopt failed: %s\n"),
8687#endif
8688 }
8689#endif
8690#endif
8691 }
8692 if (0 != bind (daemon->listen_fd,
8693 pservaddr,
8694 addrlen))
8695 {
8696#ifdef HAVE_MESSAGES
8697 MHD_DLOG (daemon,
8698 _ ("Failed to bind to port %u: %s\n"),
8699 (unsigned int) port,
8701#endif
8702 goto free_and_fail;
8703 }
8704#ifdef TCP_FASTOPEN
8705 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
8706 {
8707 if (0 == daemon->fastopen_queue_size)
8708 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
8709 if (0 != setsockopt (daemon->listen_fd,
8710 IPPROTO_TCP,
8711 TCP_FASTOPEN,
8712 (const void *) &daemon->fastopen_queue_size,
8713 sizeof (daemon->fastopen_queue_size)))
8714 {
8715#ifdef HAVE_MESSAGES
8716 MHD_DLOG (daemon,
8717 _ ("setsockopt failed: %s\n"),
8719#endif
8720 }
8721 }
8722#endif
8723 if (0 != listen (daemon->listen_fd,
8724 (int) daemon->listen_backlog_size))
8725 {
8726#ifdef HAVE_MESSAGES
8727 MHD_DLOG (daemon,
8728 _ ("Failed to listen for connections: %s\n"),
8730#endif
8731 goto free_and_fail;
8732 }
8733 }
8734 else
8735 {
8736 if (MHD_D_IS_USING_SELECT_ (daemon) &&
8738 daemon)) )
8739 {
8740#ifdef HAVE_MESSAGES
8741 MHD_DLOG (daemon,
8742 _ ("Listen socket descriptor (%d) is not " \
8743 "less than daemon FD_SETSIZE value (%d).\n"),
8744 (int) daemon->listen_fd,
8745 (int) MHD_D_GET_FD_SETSIZE_ (daemon));
8746#endif
8747 goto free_and_fail;
8748 }
8749 else
8750 {
8751#if defined(SOL_SOCKET) && (defined(SO_DOMAIN) || defined(SO_PROTOCOL_INFOW))
8752 int af;
8753 int opt_name;
8754 void *poptval;
8755 socklen_t optval_size;
8756#ifdef SO_DOMAIN
8757 opt_name = SO_DOMAIN;
8758 poptval = &af;
8759 optval_size = (socklen_t) sizeof (af);
8760#else /* SO_PROTOCOL_INFOW */
8761 WSAPROTOCOL_INFOW prot_info;
8762 opt_name = SO_PROTOCOL_INFOW;
8763 poptval = &prot_info;
8764 optval_size = (socklen_t) sizeof (prot_info);
8765#endif /* SO_PROTOCOL_INFOW */
8766
8767 if (0 == getsockopt (daemon->listen_fd,
8768 SOL_SOCKET,
8769 opt_name,
8770 poptval,
8771 &optval_size))
8772 {
8773#ifndef SO_DOMAIN
8774 af = prot_info.iAddressFamily;
8775#endif /* SO_DOMAIN */
8776 switch (af)
8777 {
8778 case AF_INET:
8779 daemon->listen_is_unix = _MHD_NO;
8780 break;
8781#ifdef HAVE_INET6
8782 case AF_INET6:
8783 *pflags |= MHD_USE_IPv6;
8784 daemon->listen_is_unix = _MHD_NO;
8785 break;
8786#endif /* HAVE_INET6 */
8787#ifdef AF_UNIX
8788 case AF_UNIX:
8789 daemon->port = 0; /* special value for UNIX domain sockets */
8790 daemon->listen_is_unix = _MHD_YES;
8791 break;
8792#endif /* AF_UNIX */
8793 default:
8794 daemon->port = 0; /* ugh */
8795 daemon->listen_is_unix = _MHD_UNKNOWN;
8796 break;
8797 }
8798 }
8799 else
8800#endif /* SOL_SOCKET && (SO_DOMAIN || SO_PROTOCOL_INFOW)) */
8801 daemon->listen_is_unix = _MHD_UNKNOWN;
8802 }
8803
8804#ifdef MHD_USE_GETSOCKNAME
8805 daemon->port = 0; /* Force use of autodetection */
8806#endif /* MHD_USE_GETSOCKNAME */
8807 }
8808
8809#ifdef MHD_USE_GETSOCKNAME
8810 if ( (0 == daemon->port) &&
8811 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
8812 (_MHD_YES != daemon->listen_is_unix) )
8813 { /* Get port number. */
8814 struct sockaddr_storage bindaddr;
8815
8816 memset (&bindaddr,
8817 0,
8818 sizeof (struct sockaddr_storage));
8819 addrlen = sizeof (struct sockaddr_storage);
8820#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
8821 bindaddr.ss_len = (socklen_t) addrlen;
8822#endif
8823 if (0 != getsockname (daemon->listen_fd,
8824 (struct sockaddr *) &bindaddr,
8825 &addrlen))
8826 {
8827#ifdef HAVE_MESSAGES
8828 MHD_DLOG (daemon,
8829 _ ("Failed to get listen port number: %s\n"),
8830 MHD_socket_last_strerr_ ());
8831#endif /* HAVE_MESSAGES */
8832 }
8833#ifdef MHD_POSIX_SOCKETS
8834 else if (sizeof (bindaddr) < addrlen)
8835 {
8836 /* should be impossible with `struct sockaddr_storage` */
8837#ifdef HAVE_MESSAGES
8838 MHD_DLOG (daemon,
8839 _ ("Failed to get listen port number " \
8840 "(`struct sockaddr_storage` too small!?).\n"));
8841#endif /* HAVE_MESSAGES */
8842 }
8843#ifndef __linux__
8844 else if (0 == addrlen)
8845 {
8846 /* Many non-Linux-based platforms return zero addrlen
8847 * for AF_UNIX sockets */
8848 daemon->port = 0; /* special value for UNIX domain sockets */
8849 if (_MHD_UNKNOWN == daemon->listen_is_unix)
8850 daemon->listen_is_unix = _MHD_YES;
8851 }
8852#endif /* __linux__ */
8853#endif /* MHD_POSIX_SOCKETS */
8854 else
8855 {
8856 switch (bindaddr.ss_family)
8857 {
8858 case AF_INET:
8859 {
8860 struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
8861
8862 daemon->port = ntohs (s4->sin_port);
8863 daemon->listen_is_unix = _MHD_NO;
8864 break;
8865 }
8866#ifdef HAVE_INET6
8867 case AF_INET6:
8868 {
8869 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
8870
8871 daemon->port = ntohs (s6->sin6_port);
8872 daemon->listen_is_unix = _MHD_NO;
8873 mhd_assert (0 != (*pflags & MHD_USE_IPv6));
8874 break;
8875 }
8876#endif /* HAVE_INET6 */
8877#ifdef AF_UNIX
8878 case AF_UNIX:
8879 daemon->port = 0; /* special value for UNIX domain sockets */
8880 daemon->listen_is_unix = _MHD_YES;
8881 break;
8882#endif
8883 default:
8884#ifdef HAVE_MESSAGES
8885 MHD_DLOG (daemon,
8886 _ ("Listen socket has unknown address family!\n"));
8887#endif
8888 daemon->port = 0; /* ugh */
8889 daemon->listen_is_unix = _MHD_UNKNOWN;
8890 break;
8891 }
8892 }
8893 }
8894#endif /* MHD_USE_GETSOCKNAME */
8895
8896 if (MHD_INVALID_SOCKET != daemon->listen_fd)
8897 {
8898 mhd_assert (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET));
8899 if (! MHD_socket_nonblocking_ (daemon->listen_fd))
8900 {
8901#ifdef HAVE_MESSAGES
8902 MHD_DLOG (daemon,
8903 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
8905#endif
8906 if (MHD_D_IS_USING_EPOLL_ (daemon)
8907#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8908 || (daemon->worker_pool_size > 0)
8909#endif
8910 )
8911 {
8912 /* Accept must be non-blocking. Multiple children may wake up
8913 * to handle a new connection, but only one will win the race.
8914 * The others must immediately return. */
8915 goto free_and_fail;
8916 }
8917 daemon->listen_nonblk = false;
8918 }
8919 else
8920 daemon->listen_nonblk = true;
8921 }
8922 else
8923 {
8924 mhd_assert (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET));
8925 daemon->listen_nonblk = false; /* Actually listen socket does not exist */
8926 }
8927
8928#ifdef EPOLL_SUPPORT
8929 if (MHD_D_IS_USING_EPOLL_ (daemon)
8930#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8931 && (0 == daemon->worker_pool_size)
8932#endif
8933 )
8934 {
8936 {
8937#ifdef HAVE_MESSAGES
8938 MHD_DLOG (daemon,
8939 _ ("Combining MHD_USE_THREAD_PER_CONNECTION and " \
8940 "MHD_USE_EPOLL is not supported.\n"));
8941#endif
8942 goto free_and_fail;
8943 }
8944 if (MHD_NO == setup_epoll_to_listen (daemon))
8945 goto free_and_fail;
8946 }
8947#endif /* EPOLL_SUPPORT */
8948
8949#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8950 if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
8951 {
8952#ifdef HAVE_MESSAGES
8953 MHD_DLOG (daemon,
8954 _ ("MHD failed to initialize IP connection limit mutex.\n"));
8955#endif
8956 goto free_and_fail;
8957 }
8958#endif
8959
8960#ifdef HTTPS_SUPPORT
8961 /* initialize HTTPS daemon certificate aspects & send / recv functions */
8962 if ( (0 != (*pflags & MHD_USE_TLS)) &&
8963 (0 != MHD_TLS_init (daemon)) )
8964 {
8965#ifdef HAVE_MESSAGES
8966 MHD_DLOG (daemon,
8967 _ ("Failed to initialize TLS support.\n"));
8968#endif
8969#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8970 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8971#endif
8972 goto free_and_fail;
8973 }
8974#endif /* HTTPS_SUPPORT */
8975#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8976 /* Start threads if requested by parameters */
8977 if (MHD_D_IS_USING_THREADS_ (daemon))
8978 {
8979 /* Internal thread (or threads) is used.
8980 * Make sure that MHD will be able to communicate with threads. */
8981 /* If using a thread pool ITC will be initialised later
8982 * for each individual worker thread. */
8983#ifdef HAVE_LISTEN_SHUTDOWN
8984 mhd_assert ((1 < daemon->worker_pool_size) || \
8985 (MHD_ITC_IS_VALID_ (daemon->itc)) || \
8986 (MHD_INVALID_SOCKET != daemon->listen_fd));
8987#else /* ! HAVE_LISTEN_SHUTDOWN */
8988 mhd_assert ((1 < daemon->worker_pool_size) || \
8989 (MHD_ITC_IS_VALID_ (daemon->itc)));
8990#endif /* ! HAVE_LISTEN_SHUTDOWN */
8991 if (0 == daemon->worker_pool_size)
8992 {
8993 if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
8994 {
8995#ifdef HAVE_MESSAGES
8996 MHD_DLOG (daemon,
8997 _ ("Failed to initialise internal lists mutex.\n"));
8998#endif
8999 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9000 goto free_and_fail;
9001 }
9002 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
9003 {
9004#ifdef HAVE_MESSAGES
9005 MHD_DLOG (daemon,
9006 _ ("Failed to initialise mutex.\n"));
9007#endif
9008 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9009 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9010 goto free_and_fail;
9011 }
9012 if (! MHD_mutex_init_ (&daemon->epoll_listen_mutex))
9013 {
9014#ifdef HAVE_MESSAGES
9015 MHD_DLOG (daemon,
9016 _ ("Failed to initialise mutex.\n"));
9017#endif
9018 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
9019 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9020 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9021 goto free_and_fail;
9022 }
9023 if (! MHD_create_named_thread_ (&daemon->tid,
9025 "MHD-listen" : "MHD-single",
9026 daemon->thread_stack_size,
9027 &MHD_polling_thread,
9028 daemon) )
9029 {
9030#ifdef HAVE_MESSAGES
9031#ifdef EAGAIN
9032 if (EAGAIN == errno)
9033 MHD_DLOG (daemon,
9034 _ ("Failed to create a new thread because it would have " \
9035 "exceeded the system limit on the number of threads or " \
9036 "no system resources available.\n"));
9037 else
9038#endif /* EAGAIN */
9039 MHD_DLOG (daemon,
9040 _ ("Failed to create listen thread: %s\n"),
9041 MHD_strerror_ (errno));
9042#endif /* HAVE_MESSAGES */
9043 MHD_mutex_destroy_chk_ (&daemon->epoll_listen_mutex);
9044 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
9045 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9046 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9047 goto free_and_fail;
9048 }
9049 }
9050 else /* 0 < daemon->worker_pool_size */
9051 {
9052 /* Coarse-grained count of connections per thread (note error
9053 * due to integer division). Also keep track of how many
9054 * connections are leftover after an equal split. */
9055 unsigned int conns_per_thread = daemon->connection_limit
9056 / daemon->worker_pool_size;
9057 unsigned int leftover_conns = daemon->connection_limit
9058 % daemon->worker_pool_size;
9059
9060 mhd_assert (2 <= daemon->worker_pool_size);
9061 i = 0; /* we need this in case fcntl or malloc fails */
9062
9063 /* Allocate memory for pooled objects */
9064 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
9065 * daemon->worker_pool_size);
9066 if (NULL == daemon->worker_pool)
9067 goto thread_failed;
9068
9069 /* Start the workers in the pool */
9070 for (i = 0; i < daemon->worker_pool_size; ++i)
9071 {
9072 /* Create copy of the Daemon object for each worker */
9073 struct MHD_Daemon *d = &daemon->worker_pool[i];
9074
9075 memcpy (d, daemon, sizeof (struct MHD_Daemon));
9076 /* Adjust polling params for worker daemons; note that memcpy()
9077 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
9078 the worker threads. */
9079 d->master = daemon;
9080 d->worker_pool_size = 0;
9081 d->worker_pool = NULL;
9082 if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
9083 {
9084#ifdef HAVE_MESSAGES
9085 MHD_DLOG (daemon,
9086 _ ("Failed to initialise internal lists mutex.\n"));
9087#endif
9088 goto thread_failed;
9089 }
9090 if (! MHD_mutex_init_ (&d->new_connections_mutex))
9091 {
9092#ifdef HAVE_MESSAGES
9093 MHD_DLOG (daemon,
9094 _ ("Failed to initialise mutex.\n"));
9095#endif
9096 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
9097 goto thread_failed;
9098 }
9099 if (! MHD_mutex_init_ (&d->epoll_listen_mutex))
9100 {
9101#ifdef HAVE_MESSAGES
9102 MHD_DLOG (daemon,
9103 _ ("Failed to initialise mutex.\n"));
9104#endif
9105 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
9106 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
9107 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9108 goto free_and_fail;
9109 }
9110 if (0 != (*pflags & MHD_USE_ITC))
9111 {
9112 if (! MHD_itc_init_ (d->itc))
9113 {
9114#ifdef HAVE_MESSAGES
9115 MHD_DLOG (daemon,
9116 _ ("Failed to create worker inter-thread " \
9117 "communication channel: %s\n"),
9118 MHD_itc_last_strerror_ () );
9119#endif
9120 MHD_mutex_destroy_chk_ (&d->epoll_listen_mutex);
9121 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
9122 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
9123 goto thread_failed;
9124 }
9125 if (MHD_D_IS_USING_SELECT_ (d) &&
9126 (! MHD_D_DOES_SCKT_FIT_FDSET_ (MHD_itc_r_fd_ (d->itc), daemon)) )
9127 {
9128#ifdef HAVE_MESSAGES
9129 MHD_DLOG (daemon,
9130 _ ("File descriptor for worker inter-thread " \
9131 "communication channel exceeds maximum value.\n"));
9132#endif
9134 MHD_mutex_destroy_chk_ (&d->epoll_listen_mutex);
9135 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
9136 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
9137 goto thread_failed;
9138 }
9139 }
9140 else
9141 MHD_itc_set_invalid_ (d->itc);
9142
9143#ifdef HAVE_LISTEN_SHUTDOWN
9144 mhd_assert ((MHD_ITC_IS_VALID_ (d->itc)) || \
9146#else /* ! HAVE_LISTEN_SHUTDOWN */
9147 mhd_assert (MHD_ITC_IS_VALID_ (d->itc));
9148#endif /* ! HAVE_LISTEN_SHUTDOWN */
9149
9150 /* Divide available connections evenly amongst the threads.
9151 * Thread indexes in [0, leftover_conns) each get one of the
9152 * leftover connections. */
9153 d->connection_limit = conns_per_thread;
9154 if (i < leftover_conns)
9155 ++d->connection_limit;
9156#ifdef EPOLL_SUPPORT
9157 if (MHD_D_IS_USING_EPOLL_ (d) &&
9158 (MHD_NO == setup_epoll_to_listen (d)) )
9159 {
9160 if (MHD_ITC_IS_VALID_ (d->itc))
9162 MHD_mutex_destroy_chk_ (&d->epoll_listen_mutex);
9163 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
9164 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
9165 goto thread_failed;
9166 }
9167#endif
9168 /* Some members must be used only in master daemon */
9169#if defined(MHD_USE_THREADS)
9170 memset (&d->per_ip_connection_mutex, 0x7F,
9171 sizeof(d->per_ip_connection_mutex));
9172#endif /* MHD_USE_THREADS */
9173#ifdef DAUTH_SUPPORT
9174 d->nnc = NULL;
9175 d->nonce_nc_size = 0;
9176 d->digest_auth_random_copy = NULL;
9177#if defined(MHD_USE_THREADS)
9178 memset (&d->nnc_lock, 0x7F, sizeof(d->nnc_lock));
9179#endif /* MHD_USE_THREADS */
9180#endif /* DAUTH_SUPPORT */
9181
9182 /* Spawn the worker thread */
9183 if (! MHD_create_named_thread_ (&d->tid,
9184 "MHD-worker",
9185 daemon->thread_stack_size,
9186 &MHD_polling_thread,
9187 d))
9188 {
9189#ifdef HAVE_MESSAGES
9190#ifdef EAGAIN
9191 if (EAGAIN == errno)
9192 MHD_DLOG (daemon,
9193 _ ("Failed to create a new pool thread because it would " \
9194 "have exceeded the system limit on the number of " \
9195 "threads or no system resources available.\n"));
9196 else
9197#endif /* EAGAIN */
9198 MHD_DLOG (daemon,
9199 _ ("Failed to create pool thread: %s\n"),
9200 MHD_strerror_ (errno));
9201#endif
9202 /* Free memory for this worker; cleanup below handles
9203 * all previously-created workers. */
9204 if (MHD_ITC_IS_VALID_ (d->itc))
9206 MHD_mutex_destroy_chk_ (&d->epoll_listen_mutex);
9207 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
9208 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
9209 goto thread_failed;
9210 }
9211 }
9212 }
9213 }
9214 else
9215 { /* Daemon without internal threads */
9216 if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
9217 {
9218#ifdef HAVE_MESSAGES
9219 MHD_DLOG (daemon,
9220 _ ("Failed to initialise internal lists mutex.\n"));
9221#endif
9222 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9223 goto free_and_fail;
9224 }
9225 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
9226 {
9227#ifdef HAVE_MESSAGES
9228 MHD_DLOG (daemon,
9229 _ ("Failed to initialise mutex.\n"));
9230#endif
9231 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9232 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9233 goto free_and_fail;
9234 }
9235 if (! MHD_mutex_init_ (&daemon->epoll_listen_mutex))
9236 {
9237#ifdef HAVE_MESSAGES
9238 MHD_DLOG (daemon,
9239 _ ("Failed to initialise mutex.\n"));
9240#endif
9241 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
9242 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9243 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9244 goto free_and_fail;
9245 }
9246 }
9247#endif
9248#ifdef HTTPS_SUPPORT
9249 /* API promises to never use the password after initialization,
9250 so we additionally NULL it here to not deref a dangling pointer. */
9251 daemon->https_key_password = NULL;
9252#endif /* HTTPS_SUPPORT */
9253
9254 return daemon;
9255
9256#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9257thread_failed:
9258 /* If no worker threads created, then shut down normally. Calling
9259 MHD_stop_daemon (as we do below) doesn't work here since it
9260 assumes a 0-sized thread pool means we had been in the default
9261 MHD_USE_INTERNAL_POLLING_THREAD mode. */
9262 if (0 == i)
9263 {
9264 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9265 if (NULL != daemon->worker_pool)
9266 free (daemon->worker_pool);
9267 goto free_and_fail;
9268 }
9269
9270 /* Shutdown worker threads we've already created. Pretend
9271 as though we had fully initialized our daemon, but
9272 with a smaller number of threads than had been
9273 requested. */
9274 daemon->worker_pool_size = i;
9275 MHD_stop_daemon (daemon);
9276 return NULL;
9277#endif
9278
9279free_and_fail:
9280 /* clean up basic memory state in 'daemon' and return NULL to
9281 indicate failure */
9282#ifdef EPOLL_SUPPORT
9283#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9284 if (daemon->upgrade_fd_in_epoll)
9285 {
9286 if (0 != epoll_ctl (daemon->epoll_fd,
9287 EPOLL_CTL_DEL,
9288 daemon->epoll_upgrade_fd,
9289 NULL))
9290 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
9291 daemon->upgrade_fd_in_epoll = false;
9292 }
9293#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9294 if (-1 != daemon->epoll_fd)
9295 close (daemon->epoll_fd);
9296#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9297 if (-1 != daemon->epoll_upgrade_fd)
9298 close (daemon->epoll_upgrade_fd);
9299#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9300#endif /* EPOLL_SUPPORT */
9301#ifdef DAUTH_SUPPORT
9302 free (daemon->digest_auth_random_copy);
9303 free (daemon->nnc);
9304#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9305 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
9306#endif
9307#endif
9308#ifdef HTTPS_SUPPORT
9309 tls_cleanup_failed_start (daemon);
9310#endif /* HTTPS_SUPPORT */
9311 if (MHD_ITC_IS_VALID_ (daemon->itc))
9312 MHD_itc_destroy_chk_ (daemon->itc);
9313 if (MHD_INVALID_SOCKET != daemon->listen_fd)
9314 (void) MHD_socket_close_ (daemon->listen_fd);
9315 free (daemon);
9316 return NULL;
9317}
9318
9319
9328static void
9330{
9331 struct MHD_Connection *pos;
9332 const bool used_thr_p_c = MHD_D_IS_USING_THREAD_PER_CONN_ (daemon);
9333#ifdef UPGRADE_SUPPORT
9334 const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
9335#endif /* UPGRADE_SUPPORT */
9336#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9337 struct MHD_UpgradeResponseHandle *urh;
9338 struct MHD_UpgradeResponseHandle *urhn;
9339 const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
9340#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9341
9342#ifdef MHD_USE_THREADS
9343 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
9346 mhd_assert (NULL == daemon->worker_pool);
9347#endif /* MHD_USE_THREADS */
9348 mhd_assert (daemon->shutdown);
9349
9350#ifdef MHD_USE_THREADS
9351/* Remove new connections that MHD_add_connection() queued and that were
9352 * never processed. This is not limited to daemons with an internal
9353 * polling thread: internal_add_connection() queues whenever the daemon
9354 * is thread-safe, which is every daemon that was not started with
9355 * MHD_USE_NO_THREAD_SAFETY, and new_connections_list_process_()
9356 * asserts the same condition. An application driving an external
9357 * event loop can therefore call MHD_add_connection() and then
9358 * MHD_stop_daemon() before the next MHD_run(), and this list is what
9359 * holds the connection at that point. */
9360 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
9361 while (NULL != (pos = daemon->new_connections_tail))
9362 {
9365 daemon->new_connections_tail,
9366 pos);
9367 new_connection_close_ (daemon, pos);
9368 }
9369 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
9370#endif /* MHD_USE_THREADS */
9371
9372#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9373 /* give upgraded HTTPS connections a chance to finish */
9374 /* 'daemon->urh_head' is not used in thread-per-connection mode. */
9375 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
9376 {
9377 mhd_assert (! used_thr_p_c);
9378 urhn = urh->prev;
9379 /* call generic forwarding function for passing data
9380 with chance to detect that application is done. */
9381 process_urh (urh);
9382 MHD_connection_finish_forward_ (urh->connection);
9383 urh->clean_ready = true;
9384 /* Resuming will move connection to cleanup list. */
9385 MHD_resume_connection (urh->connection);
9386 }
9387#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9388
9389 /* Give suspended connections a chance to resume to avoid
9390 running into the check for there not being any suspended
9391 connections left in case of a tight race with a recently
9392 resumed connection. */
9393 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
9394 {
9395 daemon->resuming = true; /* Force check for pending resume. */
9397 }
9398 /* first, make sure all threads are aware of shutdown; need to
9399 traverse DLLs in peace... */
9400#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9401 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
9402#endif
9403#ifdef UPGRADE_SUPPORT
9404 if (upg_allowed)
9405 {
9406 struct MHD_Connection *susp;
9407
9409 while (NULL != susp)
9410 {
9411 if (NULL == susp->urh) /* "Upgraded" connection? */
9412 MHD_PANIC (_ ("MHD_stop_daemon() called while we have " \
9413 "suspended connections.\n"));
9414#ifdef HTTPS_SUPPORT
9415 else if (used_tls &&
9416 used_thr_p_c &&
9417 (! susp->urh->clean_ready) )
9418 shutdown (susp->urh->app.socket,
9419 SHUT_RDWR); /* Wake thread by shutdown of app socket. */
9420#endif /* HTTPS_SUPPORT */
9421 else
9422 {
9423#ifdef HAVE_MESSAGES
9424 if (! susp->urh->was_closed)
9425 MHD_DLOG (daemon,
9426 _ ("Initiated daemon shutdown while \"upgraded\" " \
9427 "connection was not closed.\n"));
9428#endif
9429 susp->urh->was_closed = true;
9430 /* If thread-per-connection is used, connection's thread
9431 * may still processing "upgrade" (exiting). */
9432 if (! used_thr_p_c)
9434 /* Do not use MHD_resume_connection() as mutex is
9435 * already locked. */
9436 susp->resuming = true;
9437 daemon->resuming = true;
9438 }
9439 susp = susp->prev;
9440 }
9441 }
9442 else /* This 'else' is combined with next 'if' */
9443#endif /* UPGRADE_SUPPORT */
9445 MHD_PANIC (_ ("MHD_stop_daemon() called while we have " \
9446 "suspended connections.\n"));
9447#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
9448#ifdef MHD_USE_THREADS
9449 if (upg_allowed && used_tls && used_thr_p_c)
9450 {
9451 /* "Upgraded" threads may be running in parallel. Connection will not be
9452 * moved to the "cleanup list" until connection's thread finishes.
9453 * We must ensure that all "upgraded" connections are finished otherwise
9454 * connection may stay in "suspended" list and will not be cleaned. */
9455 for (pos = daemon->suspended_connections_tail; NULL != pos; pos = pos->prev)
9456 {
9457 /* Any connection found here is "upgraded" connection, normal suspended
9458 * connections are already removed from this list. */
9459 mhd_assert (NULL != pos->urh);
9460 if (! pos->thread_joined)
9461 {
9462 /* While "cleanup" list is not manipulated by "upgraded"
9463 * connection, "cleanup" mutex is required for call of
9464 * MHD_resume_connection() during finishing of "upgraded"
9465 * thread. */
9466 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
9467 if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
9468 MHD_PANIC (_ ("Failed to join a thread.\n"));
9469 pos->thread_joined = true;
9470 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
9471 }
9472 }
9473 }
9474#endif /* MHD_USE_THREADS */
9475#endif
9476 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
9477 {
9478 shutdown (pos->socket_fd,
9479 SHUT_RDWR);
9480#ifdef MHD_WINSOCK_SOCKETS
9482 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
9483 (! MHD_itc_activate_ (daemon->itc, "e")) )
9484 MHD_PANIC (_ ("Failed to signal shutdown via inter-thread " \
9485 "communication channel.\n"));
9486#endif
9487 }
9488
9489#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9490 /* now, collect per-connection threads */
9491 if (used_thr_p_c)
9492 {
9493 pos = daemon->connections_tail;
9494 while (NULL != pos)
9495 {
9496 if (! pos->thread_joined)
9497 {
9498 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
9499 if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
9500 MHD_PANIC (_ ("Failed to join a thread.\n"));
9501 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
9502 pos->thread_joined = true;
9503 /* The thread may have concurrently modified the DLL,
9504 need to restart from the beginning */
9505 pos = daemon->connections_tail;
9506 continue;
9507 }
9508 pos = pos->prev;
9509 }
9510 }
9511 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
9512#endif
9513
9514#ifdef UPGRADE_SUPPORT
9515 /* Finished threads with "upgraded" connections need to be moved
9516 * to cleanup list by resume_suspended_connections(). */
9517 /* "Upgraded" connections that were not closed explicitly by
9518 * application should be moved to cleanup list too. */
9519 if (upg_allowed)
9520 {
9521 daemon->resuming = true; /* Force check for pending resume. */
9523 }
9524#endif /* UPGRADE_SUPPORT */
9525
9527 /* now that we're alone, move everyone to cleanup */
9528 while (NULL != (pos = daemon->connections_tail))
9529 {
9530#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9532 (! pos->thread_joined) )
9533 MHD_PANIC (_ ("Failed to join a thread.\n"));
9534#endif
9535 close_connection (pos);
9536 }
9538}
9539
9540
9547_MHD_EXTERN void
9549{
9550 MHD_socket fd;
9551#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9552 unsigned int i;
9553#endif
9554
9555 if (NULL == daemon)
9556 return;
9557 if ( (daemon->shutdown) && (NULL == daemon->master) )
9558 MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
9559
9561 (NULL != daemon->worker_pool) || \
9564 (NULL == daemon->worker_pool)) || \
9566
9567 /* Slave daemons must be stopped by master daemon. */
9568 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
9569
9570 daemon->shutdown = true;
9571 if (daemon->was_quiesced)
9572 fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
9573 else
9574 fd = daemon->listen_fd;
9575
9576#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9577 if (NULL != daemon->worker_pool)
9578 { /* Master daemon with worker pool. */
9579 mhd_assert (1 < daemon->worker_pool_size);
9581
9582 /* Let workers shutdown in parallel. */
9583 for (i = 0; i < daemon->worker_pool_size; ++i)
9584 {
9585 daemon->worker_pool[i].shutdown = true;
9586 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
9587 {
9588 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
9589 "e"))
9590 MHD_PANIC (_ ("Failed to signal shutdown via inter-thread " \
9591 "communication channel.\n"));
9592 }
9593 else
9595 }
9596#ifdef HAVE_LISTEN_SHUTDOWN
9597 if (MHD_INVALID_SOCKET != fd)
9598 {
9599 (void) shutdown (fd,
9600 SHUT_RDWR);
9601 }
9602#endif /* HAVE_LISTEN_SHUTDOWN */
9603 for (i = 0; i < daemon->worker_pool_size; ++i)
9604 {
9605 MHD_stop_daemon (&daemon->worker_pool[i]);
9606 }
9607 free (daemon->worker_pool);
9609#ifdef EPOLL_SUPPORT
9610 mhd_assert (-1 == daemon->epoll_fd);
9611#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9612 mhd_assert (-1 == daemon->epoll_upgrade_fd);
9613#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9614#endif /* EPOLL_SUPPORT */
9615 }
9616 else
9617#endif
9618 { /* Worker daemon or single daemon. */
9619#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9621 { /* Worker daemon or single daemon with internal thread(s). */
9622 mhd_assert (0 == daemon->worker_pool_size);
9623 /* Separate thread(s) is used for polling sockets. */
9624 if (MHD_ITC_IS_VALID_ (daemon->itc))
9625 {
9626 if (! MHD_itc_activate_ (daemon->itc,
9627 "e"))
9628 MHD_PANIC (_ ("Failed to signal shutdown via inter-thread " \
9629 "communication channel.\n"));
9630 }
9631 else
9632 {
9633#ifdef HAVE_LISTEN_SHUTDOWN
9634 if (MHD_INVALID_SOCKET != fd)
9635 {
9636 if (NULL == daemon->master)
9637 (void) shutdown (fd,
9638 SHUT_RDWR);
9639 }
9640 else
9641#endif /* HAVE_LISTEN_SHUTDOWN */
9642 mhd_assert (false); /* Should never happen */
9643 }
9644
9646 {
9647 MHD_PANIC (_ ("Failed to join a thread.\n"));
9648 }
9649 /* close_all_connections() was called in daemon thread. */
9650 }
9651 else
9652#endif
9653 {
9654 /* No internal threads are used for polling sockets. */
9656 }
9661#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
9662 mhd_assert (NULL == daemon->urh_head);
9663#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
9664
9665 if (MHD_ITC_IS_VALID_ (daemon->itc))
9667
9668#ifdef EPOLL_SUPPORT
9670 (-1 != daemon->epoll_fd) )
9671 MHD_socket_close_chk_ (daemon->epoll_fd);
9672#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9674 (-1 != daemon->epoll_upgrade_fd) )
9675 MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
9676#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9677#endif /* EPOLL_SUPPORT */
9678
9679#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9680 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9681 MHD_mutex_destroy_chk_ (&daemon->epoll_listen_mutex);
9682 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
9683#endif
9684 }
9685
9686 if (NULL == daemon->master)
9687 { /* Cleanup that should be done only one time in master/single daemon.
9688 * Do not perform this cleanup in worker daemons. */
9689
9690 if (MHD_INVALID_SOCKET != fd)
9692
9693 /* TLS clean up */
9694#ifdef HTTPS_SUPPORT
9695 if (daemon->have_dhparams)
9696 {
9697 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
9698 daemon->have_dhparams = false;
9699 }
9700 if (0 != (daemon->options & MHD_USE_TLS))
9701 {
9702 gnutls_priority_deinit (daemon->priority_cache);
9703 if (daemon->x509_cred)
9704 gnutls_certificate_free_credentials (daemon->x509_cred);
9705 if (daemon->psk_cred)
9706 gnutls_psk_free_server_credentials (daemon->psk_cred);
9707 }
9708#endif /* HTTPS_SUPPORT */
9709
9710#ifdef DAUTH_SUPPORT
9711 free (daemon->digest_auth_random_copy);
9712 free (daemon->nnc);
9713#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9714 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
9715#endif
9716#endif
9717#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9718 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9719#endif
9720 free (daemon);
9721 }
9722}
9723
9724
9737_MHD_EXTERN const union MHD_DaemonInfo *
9739 enum MHD_DaemonInfoType info_type,
9740 ...)
9741{
9742 if (NULL == daemon)
9743 return NULL;
9744
9745 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
9746 (NULL != daemon->worker_pool) || \
9748 mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
9749 (NULL == daemon->worker_pool)) || \
9750 (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
9751
9752 switch (info_type)
9753 {
9755 return NULL; /* no longer supported */
9757 return NULL; /* no longer supported */
9760 return &daemon->daemon_info_dummy_listen_fd;
9762#ifdef EPOLL_SUPPORT
9763 daemon->daemon_info_dummy_epoll_fd.epoll_fd = daemon->epoll_fd;
9764 return &daemon->daemon_info_dummy_epoll_fd;
9765#else /* ! EPOLL_SUPPORT */
9766 return NULL;
9767#endif /* ! EPOLL_SUPPORT */
9769 if (! MHD_D_IS_THREAD_SAFE_ (daemon))
9770 MHD_cleanup_connections (daemon);
9771#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9772 else if (daemon->worker_pool)
9773 {
9774 unsigned int i;
9775 /* Collect the connection information stored in the workers. */
9776 daemon->connections = 0;
9777 for (i = 0; i < daemon->worker_pool_size; i++)
9778 {
9779 /* FIXME: next line is thread-safe only if read is atomic. */
9780 daemon->connections += daemon->worker_pool[i].connections;
9781 }
9782 }
9783#endif
9785 = daemon->connections;
9786 return &daemon->daemon_info_dummy_num_connections;
9788 daemon->daemon_info_dummy_flags.flags = daemon->options;
9789 return &daemon->daemon_info_dummy_flags;
9791 daemon->daemon_info_dummy_port.port = daemon->port;
9792 return &daemon->daemon_info_dummy_port;
9793 default:
9794 return NULL;
9795 }
9796}
9797
9798
9805_MHD_EXTERN const char *
9807{
9808#ifdef PACKAGE_VERSION
9809 return PACKAGE_VERSION;
9810#else /* !PACKAGE_VERSION */
9811 static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
9812 if (0 == ver[0])
9813 {
9814 int res = MHD_snprintf_ (ver,
9815 sizeof(ver),
9816 "%x.%x.%x",
9817 (int) (((uint32_t) MHD_VERSION >> 24) & 0xFF),
9818 (int) (((uint32_t) MHD_VERSION >> 16) & 0xFF),
9819 (int) (((uint32_t) MHD_VERSION >> 8) & 0xFF));
9820 if ((0 >= res) || (sizeof(ver) <= res))
9821 return "0.0.0"; /* Can't return real version */
9822 }
9823 return ver;
9824#endif /* !PACKAGE_VERSION */
9825}
9826
9827
9836_MHD_EXTERN uint32_t
9838{
9839 return (uint32_t) MHD_VERSION;
9840}
9841
9842
9856{
9857 switch (feature)
9858 {
9860#ifdef HAVE_MESSAGES
9861 return MHD_YES;
9862#else
9863 return MHD_NO;
9864#endif
9865 case MHD_FEATURE_TLS:
9866#ifdef HTTPS_SUPPORT
9867 return MHD_YES;
9868#else /* ! HTTPS_SUPPORT */
9869 return MHD_NO;
9870#endif /* ! HTTPS_SUPPORT */
9872#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
9873 return MHD_YES;
9874#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
9875 return MHD_NO;
9876#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
9878#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
9879 return MHD_YES;
9880#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
9881 return MHD_NO;
9882#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
9883 case MHD_FEATURE_IPv6:
9884#ifdef HAVE_INET6
9885 return MHD_YES;
9886#else
9887 return MHD_NO;
9888#endif
9890#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
9891 return MHD_YES;
9892#else
9893 return MHD_NO;
9894#endif
9895 case MHD_FEATURE_POLL:
9896#ifdef HAVE_POLL
9897 return MHD_YES;
9898#else
9899 return MHD_NO;
9900#endif
9901 case MHD_FEATURE_EPOLL:
9902#ifdef EPOLL_SUPPORT
9903 return MHD_YES;
9904#else
9905 return MHD_NO;
9906#endif
9908#ifdef HAVE_LISTEN_SHUTDOWN
9909 return MHD_YES;
9910#else
9911 return MHD_NO;
9912#endif
9914#ifdef _MHD_ITC_SOCKETPAIR
9915 return MHD_YES;
9916#else
9917 return MHD_NO;
9918#endif
9920#ifdef TCP_FASTOPEN
9921 return MHD_YES;
9922#else
9923 return MHD_NO;
9924#endif
9926#ifdef BAUTH_SUPPORT
9927 return MHD_YES;
9928#else
9929 return MHD_NO;
9930#endif
9932#ifdef DAUTH_SUPPORT
9933 return MHD_YES;
9934#else
9935 return MHD_NO;
9936#endif
9938#ifdef HAVE_POSTPROCESSOR
9939 return MHD_YES;
9940#else
9941 return MHD_NO;
9942#endif
9944#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
9945 return MHD_YES;
9946#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
9947 return MHD_NO;
9948#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
9950#if defined(HAVE_PREAD64) || defined(_WIN32)
9951 return MHD_YES;
9952#elif defined(HAVE_PREAD)
9953 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
9954#elif defined(HAVE_LSEEK64)
9955 return MHD_YES;
9956#else
9957 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
9958#endif
9960#if defined(MHD_USE_THREAD_NAME_)
9961 return MHD_YES;
9962#else
9963 return MHD_NO;
9964#endif
9966#if defined(UPGRADE_SUPPORT)
9967 return MHD_YES;
9968#else
9969 return MHD_NO;
9970#endif
9972#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
9973 return MHD_YES;
9974#else
9975 return MHD_NO;
9976#endif
9978#ifdef MHD_USE_GETSOCKNAME
9979 return MHD_YES;
9980#else
9981 return MHD_NO;
9982#endif
9984#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) || \
9985 ! defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
9986 return MHD_YES;
9987#else
9988 return MHD_NO;
9989#endif
9991#ifdef _MHD_HAVE_SENDFILE
9992 return MHD_YES;
9993#else
9994 return MHD_NO;
9995#endif
9997#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9998 return MHD_YES;
9999#else
10000 return MHD_NO;
10001#endif
10003#if defined(COOKIE_SUPPORT)
10004 return MHD_YES;
10005#else
10006 return MHD_NO;
10007#endif
10009#ifdef DAUTH_SUPPORT
10010 return MHD_YES;
10011#else
10012 return MHD_NO;
10013#endif
10015#if defined(DAUTH_SUPPORT) && defined(MHD_MD5_SUPPORT)
10016 return MHD_YES;
10017#else
10018 return MHD_NO;
10019#endif
10021#if defined(DAUTH_SUPPORT) && defined(MHD_SHA256_SUPPORT)
10022 return MHD_YES;
10023#else
10024 return MHD_NO;
10025#endif
10027#if defined(DAUTH_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
10028 return MHD_YES;
10029#else
10030 return MHD_NO;
10031#endif
10033#ifdef DAUTH_SUPPORT
10034 return MHD_NO;
10035#else
10036 return MHD_NO;
10037#endif
10039#ifdef DAUTH_SUPPORT
10040 return MHD_NO;
10041#else
10042 return MHD_NO;
10043#endif
10045#ifdef DAUTH_SUPPORT
10046 return MHD_YES;
10047#else
10048 return MHD_NO;
10049#endif
10051#if defined(MHD_MD5_TLSLIB) || defined(MHD_SHA256_TLSLIB)
10052 return MHD_YES;
10053#else
10054 return MHD_NO;
10055#endif
10057#ifdef _DEBUG
10058 return MHD_YES;
10059#else
10060 return MHD_NO;
10061#endif
10063#ifdef HAS_FD_SETSIZE_OVERRIDABLE
10064 return MHD_YES;
10065#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
10066 return MHD_NO;
10067#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
10068
10069 default:
10070 break;
10071 }
10072 return MHD_NO;
10073}
10074
10075
10076#ifdef MHD_HTTPS_REQUIRE_GCRYPT
10077#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
10078#if defined(MHD_USE_POSIX_THREADS)
10079GCRY_THREAD_OPTION_PTHREAD_IMPL;
10080#elif defined(MHD_W32_MUTEX_)
10081
10082static int
10083gcry_w32_mutex_init (void **ppmtx)
10084{
10085 *ppmtx = malloc (sizeof (MHD_mutex_));
10086
10087 if (NULL == *ppmtx)
10088 return ENOMEM;
10089 if (! MHD_mutex_init_ ((MHD_mutex_ *) *ppmtx))
10090 {
10091 free (*ppmtx);
10092 *ppmtx = NULL;
10093 return EPERM;
10094 }
10095
10096 return 0;
10097}
10098
10099
10100static int
10101gcry_w32_mutex_destroy (void **ppmtx)
10102{
10103 int res = (MHD_mutex_destroy_ ((MHD_mutex_ *) *ppmtx)) ? 0 : EINVAL;
10104 free (*ppmtx);
10105 return res;
10106}
10107
10108
10109static int
10110gcry_w32_mutex_lock (void **ppmtx)
10111{
10112 return MHD_mutex_lock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
10113}
10114
10115
10116static int
10117gcry_w32_mutex_unlock (void **ppmtx)
10118{
10119 return MHD_mutex_unlock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
10120}
10121
10122
10123static struct gcry_thread_cbs gcry_threads_w32 = {
10124 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
10125 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
10126 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
10128};
10129
10130#endif /* defined(MHD_W32_MUTEX_) */
10131#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
10132#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
10133
10137void
10139{
10140#if defined(MHD_WINSOCK_SOCKETS)
10141 WSADATA wsd;
10142#endif /* MHD_WINSOCK_SOCKETS */
10143
10145
10146#if defined(MHD_WINSOCK_SOCKETS)
10147 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
10148 MHD_PANIC (_ ("Failed to initialize winsock.\n"));
10149 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
10150 MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
10151#endif /* MHD_WINSOCK_SOCKETS */
10152#ifdef HTTPS_SUPPORT
10153#ifdef MHD_HTTPS_REQUIRE_GCRYPT
10154#if GCRYPT_VERSION_NUMBER < 0x010600
10155#if GNUTLS_VERSION_NUMBER <= 0x020b00
10156#if defined(MHD_USE_POSIX_THREADS)
10157 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
10158 &gcry_threads_pthread))
10159 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
10160#elif defined(MHD_W32_MUTEX_)
10161 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
10162 &gcry_threads_w32))
10163 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
10164#endif /* defined(MHD_W32_MUTEX_) */
10165#endif /* GNUTLS_VERSION_NUMBER <= 0x020b00 */
10166 gcry_check_version (NULL);
10167#else
10168 if (NULL == gcry_check_version ("1.6.0"))
10169 MHD_PANIC (_ ("libgcrypt is too old. MHD was compiled for " \
10170 "libgcrypt 1.6.0 or newer.\n"));
10171#endif
10172#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
10173 gnutls_global_init ();
10174#endif /* HTTPS_SUPPORT */
10178 /* Check whether sizes were correctly detected by configure */
10179#ifdef _DEBUG
10180 if (1)
10181 {
10182 struct timeval tv;
10183 mhd_assert (sizeof(tv.tv_sec) == SIZEOF_STRUCT_TIMEVAL_TV_SEC);
10184 }
10185#endif /* _DEBUG */
10186 mhd_assert (sizeof(uint64_t) == SIZEOF_UINT64_T);
10187}
10188
10189
10190void
10192{
10193#ifdef HTTPS_SUPPORT
10194 gnutls_global_deinit ();
10195#endif /* HTTPS_SUPPORT */
10196#if defined(MHD_WINSOCK_SOCKETS)
10197 WSACleanup ();
10198#endif /* MHD_WINSOCK_SOCKETS */
10200}
10201
10202
10203#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
10205#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
10206
10207/* end of daemon.c */
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_set_initial_state_(struct MHD_Connection *c)
void MHD_connection_handle_write(struct MHD_Connection *connection)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
void MHD_connection_handle_read(struct MHD_Connection *connection, bool socket_error)
void MHD_update_last_activity_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Methods for managing connections.
#define MHD_connection_finish_forward_(conn)
Definition connection.h:174
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr_storage *addr, socklen_t addrlen)
Definition daemon.c:437
static void close_all_connections(struct MHD_Daemon *daemon)
Definition daemon.c:9329
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr_storage *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition daemon.c:316
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition daemon.c:3401
void MHD_fini(void)
Definition daemon.c:10191
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr_storage *addr, socklen_t addrlen)
Definition daemon.c:369
static enum MHD_Result call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition daemon.c:1332
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition daemon.c:276
static struct MHD_Connection * new_connection_prepare_(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr_storage *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
Definition daemon.c:2687
volatile int global_init_count
Definition daemon.c:144
void MHD_check_global_init_(void)
Definition daemon.c:161
static void close_connection(struct MHD_Connection *pos)
Definition daemon.c:6185
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition daemon.c:3542
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
Definition daemon.c:5024
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, struct MHD_InterimParams_ *params,...)
Definition daemon.c:6570
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition daemon.c:297
static void new_connections_list_process_(struct MHD_Daemon *daemon)
Definition daemon.c:3349
void MHD_init(void)
Definition daemon.c:10138
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition daemon.c:4254
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition daemon.c:6540
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition daemon.c:4015
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, struct MHD_InterimParams_ *params, va_list ap)
Definition daemon.c:6862
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition daemon.c:80
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition daemon.c:6305
static enum MHD_Result new_connection_process_(struct MHD_Daemon *daemon, struct MHD_Connection *connection)
Definition daemon.c:3039
static enum MHD_Result internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr_storage *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
Definition daemon.c:3262
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition daemon.c:259
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
Definition daemon.c:3644
#define MHD_POOL_SIZE_DEFAULT
Definition daemon.c:88
static bool process_interim_params(struct MHD_Daemon *d, const struct sockaddr **ppsockaddr, socklen_t *psockaddr_len, struct MHD_InterimParams_ *params)
Definition daemon.c:7768
_MHD_EXTERN void MHD_suspend_connection(struct MHD_Connection *connection)
Definition daemon.c:3499
_MHD_EXTERN int MHD_get_timeout_i(struct MHD_Daemon *daemon)
_MHD_EXTERN int64_t MHD_get_timeout64s(struct MHD_Daemon *daemon)
#define MHD_run_from_select(d, r, w, e)
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition daemon.c:9548
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon_va(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
Definition daemon.c:7934
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition daemon.c:6071
static enum MHD_Result internal_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set, int fd_setsize)
Definition daemon.c:4708
_MHD_EXTERN enum MHD_Result MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition daemon.c:1227
static enum MHD_Result internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, int fd_setsize)
Definition daemon.c:1026
#define MHD_get_fdset(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd)
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition daemon.c:4385
_MHD_EXTERN enum MHD_Result MHD_get_timeout64(struct MHD_Daemon *daemon, uint64_t *timeout)
Definition daemon.c:4439
_MHD_EXTERN enum MHD_Result MHD_run_from_select2(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set, unsigned int fd_setsize)
Definition daemon.c:4879
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls,...)
Definition daemon.c:6350
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
Definition daemon.c:6121
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition mhd_panic.c:94
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **req_cls, enum MHD_RequestTerminationCode toe)
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
@ MHD_CONNECTION_NOTIFY_STARTED
@ MHD_CONNECTION_NOTIFY_CLOSED
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_WITH_ERROR
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition response.c:2294
_MHD_EXTERN enum MHD_Result MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
Definition daemon.c:3813
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition daemon.c:9855
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition daemon.c:6395
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition daemon.c:9738
_MHD_EXTERN uint32_t MHD_get_version_bin(void)
Definition daemon.c:9837
_MHD_EXTERN const char * MHD_get_version(void)
Definition daemon.c:9806
_MHD_EXTERN void MHD_free(void *ptr)
Definition daemon.c:213
MHD internal shared structures.
@ MHD_CONNECTION_HEADERS_SENDING
Definition internal.h:694
@ MHD_CONNECTION_INIT
Definition internal.h:618
@ MHD_CONNECTION_CLOSED
Definition internal.h:741
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition internal.h:710
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition internal.h:720
#define MHD_D_IS_USING_POLL_(d)
Definition internal.h:2606
#define XDLL_insert(head, tail, element)
Definition internal.h:2765
MHD_EpollState
Definition internal.h:169
@ MHD_EPOLL_STATE_SUSPENDED
Definition internal.h:202
@ MHD_EPOLL_STATE_IN_EREADY_EDLL
Definition internal.h:192
@ MHD_EPOLL_STATE_READ_READY
Definition internal.h:181
@ MHD_EPOLL_STATE_IN_EPOLL_SET
Definition internal.h:197
@ MHD_EPOLL_STATE_WRITE_READY
Definition internal.h:187
@ MHD_EPOLL_STATE_ERROR
Definition internal.h:207
@ MHD_TLS_CONN_NO_TLS
Definition internal.h:760
@ MHD_TLS_CONN_INIT
Definition internal.h:761
@ MHD_TLS_CONN_CONNECTED
Definition internal.h:763
#define DLL_insert(head, tail, element)
Definition internal.h:2718
#define MHD_D_DOES_SCKT_FIT_FDSET_(sckt, d)
Definition internal.h:2661
@ MHD_EVENT_LOOP_INFO_PROCESS_READ
Definition internal.h:235
@ MHD_EVENT_LOOP_INFO_PROCESS
Definition internal.h:229
@ MHD_EVENT_LOOP_INFO_READ
Definition internal.h:219
@ MHD_EVENT_LOOP_INFO_WRITE
Definition internal.h:224
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition internal.h:241
#define MHD_D_IS_USING_SELECT_(d)
Definition internal.h:2602
#define EDLL_insert(head, tail, element)
Definition internal.h:2812
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition internal.h:1871
_MHD_static_inline struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *const daemon)
Definition internal.h:2960
#define _MHD_DROP_CONST(ptr)
Definition internal.h:77
#define MHD_D_GET_FD_SETSIZE_(d)
Definition internal.h:2655
#define MHD_BUF_INC_SIZE
Definition internal.h:142
#define EDLL_remove(head, tail, element)
Definition internal.h:2832
#define PRIu64
Definition internal.h:53
#define XDLL_remove(head, tail, element)
Definition internal.h:2787
#define MHD_D_IS_USING_THREAD_PER_CONN_(d)
Definition internal.h:2638
#define DLL_remove(head, tail, element)
Definition internal.h:2740
#define MHD_D_IS_USING_THREADS_(d)
Definition internal.h:2634
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition internal.h:249
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition internal.h:1885
#define MHD_D_IS_USING_EPOLL_(d)
Definition internal.h:2610
#define MHD_D_IS_THREAD_SAFE_(d)
Definition internal.h:2643
MHD_tristate
Definition internal.h:156
@ _MHD_UNKNOWN
Definition internal.h:157
@ _MHD_YES
Definition internal.h:161
@ _MHD_OFF
Definition internal.h:158
@ _MHD_NO
Definition internal.h:159
void MHD_init_mem_pools_(void)
Definition memorypool.c:229
void MHD_pool_destroy(struct MemoryPool *pool)
Definition memorypool.c:361
struct MemoryPool * MHD_pool_create(size_t max)
Definition memorypool.c:290
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
types alignment macros
#define mhd_assert(ignore)
Definition mhd_assert.h:45
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition mhd_compat.c:98
Header for platform missing functions.
#define MHD_strerror_(errnum)
Definition mhd_compat.h:46
Header for platform-independent inter-thread communication.
#define MHD_PANIC(msg)
Definition mhd_itc.h:45
#define MHD_ITC_IS_INVALID_(itc)
Definition mhd_itc.h:385
#define MHD_itc_destroy_chk_(itc)
Definition mhd_itc.h:371
limits values definitions
#define SSIZE_MAX
Definition mhd_limits.h:121
#define UINT64_MAX
Definition mhd_limits.h:93
#define SIZE_MAX
Definition mhd_limits.h:111
#define INT_MAX
Definition mhd_limits.h:45
#define ULLONG_MAX
Definition mhd_limits.h:69
#define TIMEVAL_TV_SEC_MAX
Definition mhd_limits.h:150
#define UINT_MAX
Definition mhd_limits.h:53
#define INT64_MAX
Definition mhd_limits.h:101
Header for platform-independent locks abstraction.
#define MHD_mutex_unlock_chk_(ignore)
Definition mhd_locks.h:198
#define MHD_mutex_destroy_(ignore)
Definition mhd_locks.h:193
#define MHD_mutex_unlock_(ignore)
Definition mhd_locks.h:197
#define MHD_mutex_lock_(ignore)
Definition mhd_locks.h:195
#define MHD_mutex_init_(ignore)
Definition mhd_locks.h:192
#define MHD_mutex_lock_chk_(ignore)
Definition mhd_locks.h:196
#define MHD_mutex_destroy_chk_(ignore)
Definition mhd_locks.h:194
#define NULL
uint64_t MHD_monotonic_msec_counter(void)
void MHD_monotonic_sec_counter_finish(void)
void MHD_monotonic_sec_counter_init(void)
internal monotonic clock functions implementations
#define MHD_DAUTH_DEF_TIMEOUT_
#define _(String)
Definition mhd_options.h:42
#define _MHD_EXTERN
Definition mhd_options.h:53
#define MHD_DAUTH_DEF_MAX_NC_
void MHD_send_init_static_vars_(void)
Definition mhd_send.c:157
Declarations of send() wrappers.
int MHD_socket_noninheritable_(MHD_socket sock)
int MHD_socket_nonblocking_(MHD_socket sock)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, int fd_setsize)
MHD_socket MHD_socket_create_listen_(int pf)
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
#define MHD_SCKT_FD_FITS_FDSET_SETSIZE_(fd, pset, setsize)
#define MHD_SCKT_ERR_IS_(err, code)
int MHD_SCKT_OPT_BOOL_
#define SOCK_NONBLOCK_OR_ZERO
#define MHD_socket_close_(fd)
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define MHD_SCKT_EINTR_
#define _MHD_SYS_DEFAULT_FD_SETSIZE
#define MHD_socket_strerr_(err)
#define MHD_socket_last_strerr_()
#define MHD_socket_get_error_()
#define SOCK_NOSIGPIPE_OR_ZERO
#define MHD_SCKT_EINVAL_
#define MHD_socket_close_chk_(fd)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_socket_fset_error_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MHD_recv_(s, b, l)
#define MHD_send_(s, b, l)
#define MHD_SCKT_LAST_ERR_IS_(code)
#define MHD_SYS_select_(n, r, w, e, t)
#define SOCK_CLOEXEC_OR_ZERO
size_t MHD_str_pct_decode_in_place_lenient_(char *str, bool *broken_encoding)
Definition mhd_str.c:1994
size_t MHD_str_pct_decode_in_place_strict_(char *str)
Definition mhd_str.c:1938
Header for string manipulating helpers.
#define _MHD_S_STR_W_LEN(str)
#define MHD_STATICSTR_LEN_(macro)
Header for platform-independent threads abstraction.
#define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr)
#define MHD_thread_handle_ID_is_current_thread_(hndl_id)
#define MHD_thread_handle_ID_is_valid_handle_(hndl_id)
#define MHD_thread_handle_ID_join_thread_(hndl_id)
#define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr)
#define MHD_thread_handle_ID_is_valid_ID_(hndl_id)
#define MHD_create_named_thread_(t, n, s, r, a)
int MHD_socket
Definition microhttpd.h:206
MHD_FEATURE
@ MHD_FEATURE_POSTPROCESSOR
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
@ MHD_FEATURE_DIGEST_AUTH_USERHASH
@ MHD_FEATURE_THREADS
@ MHD_FEATURE_DIGEST_AUTH_AUTH_INT
@ MHD_FEATURE_DIGEST_AUTH_SHA256
@ MHD_FEATURE_SENDFILE
@ MHD_FEATURE_AUTODETECT_BIND_PORT
@ MHD_FEATURE_LARGE_FILE
@ MHD_FEATURE_DIGEST_AUTH_SHA512_256
@ MHD_FEATURE_EXTERN_HASH
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
@ MHD_FEATURE_BASIC_AUTH
@ MHD_FEATURE_DIGEST_AUTH
@ MHD_FEATURE_IPv6
@ MHD_FEATURE_POLL
@ MHD_FEATURE_THREAD_NAMES
@ MHD_FEATURE_DEBUG_BUILD
@ MHD_FEATURE_FLEXIBLE_FD_SETSIZE
@ MHD_FEATURE_EPOLL
@ MHD_FEATURE_TLS
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
@ MHD_FEATURE_RESPONSES_SHARED_FD
@ MHD_FEATURE_MESSAGES
@ MHD_FEATURE_IPv6_ONLY
@ MHD_FEATURE_DIGEST_AUTH_ALGO_SESSION
@ MHD_FEATURE_COOKIE_PARSING
@ MHD_FEATURE_DIGEST_AUTH_MD5
@ MHD_FEATURE_UPGRADE
@ MHD_FEATURE_SOCKETPAIR
@ MHD_FEATURE_TCP_FASTOPEN
@ MHD_FEATURE_DIGEST_AUTH_RFC2069
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
MHD_OPTION
MHD options.
@ MHD_OPTION_HTTPS_PRIORITIES_APPEND
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
@ MHD_OPTION_HTTPS_CRED_TYPE
@ MHD_OPTION_URI_LOG_CALLBACK
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_DIGEST_AUTH_DEFAULT_NONCE_TIMEOUT
@ MHD_OPTION_CLIENT_DISCIPLINE_LVL
@ MHD_OPTION_SOCK_ADDR_LEN
@ MHD_OPTION_APP_FD_SETSIZE
@ MHD_OPTION_SIGPIPE_HANDLED_BY_APP
@ MHD_OPTION_UNESCAPE_CALLBACK
@ MHD_OPTION_EXTERNAL_LOGGER
@ MHD_OPTION_TLS_NO_ALPN
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
@ MHD_OPTION_HTTPS_PRIORITIES
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
@ MHD_OPTION_NOTIFY_CONNECTION
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
@ MHD_OPTION_THREAD_POOL_SIZE
@ MHD_OPTION_CONNECTION_LIMIT
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
@ MHD_OPTION_DIGEST_AUTH_DEFAULT_MAX_NC
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
@ MHD_OPTION_HTTPS_MEM_CERT
@ MHD_OPTION_SERVER_INSANITY
@ MHD_OPTION_LISTEN_SOCKET
@ MHD_OPTION_HTTPS_MEM_KEY
@ MHD_OPTION_DIGEST_AUTH_RANDOM
@ MHD_OPTION_HTTPS_KEY_PASSWORD
@ MHD_OPTION_NONCE_NC_SIZE
@ MHD_OPTION_ALLOW_BIN_ZERO_IN_URI_PATH
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
@ MHD_OPTION_THREAD_STACK_SIZE
@ MHD_OPTION_DIGEST_AUTH_RANDOM_COPY
@ MHD_OPTION_ARRAY
@ MHD_OPTION_STRICT_FOR_CLIENT
@ MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE
@ MHD_OPTION_SOCK_ADDR
@ MHD_OPTION_CONNECTION_TIMEOUT
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
@ MHD_OPTION_END
@ MHD_OPTION_HTTPS_MEM_TRUST
@ MHD_OPTION_HTTPS_CERT_CALLBACK
@ MHD_OPTION_NOTIFY_COMPLETED
MHD_DisableSanityCheck
MHD_Result
Definition microhttpd.h:163
@ MHD_YES
Definition microhttpd.h:172
@ MHD_NO
Definition microhttpd.h:167
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_UNSIGNED_LONG_LONG
Definition microhttpd.h:311
enum MHD_Result(* MHD_AccessHandlerCallback)(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **req_cls)
int fd
#define MHD_POSIX_SOCKETS
Definition microhttpd.h:205
void * data
#define MHD_INVALID_SOCKET
Definition microhttpd.h:207
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
#define MHD_VERSION
Definition microhttpd.h:104
MHD_DaemonInfoType
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
@ MHD_DAEMON_INFO_BIND_PORT
@ MHD_DAEMON_INFO_EPOLL_FD
@ MHD_DAEMON_INFO_FLAGS
@ MHD_DAEMON_INFO_KEY_SIZE
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
@ MHD_DAEMON_INFO_LISTEN_FD
MHD_FLAG
Flags for the struct MHD_Daemon.
@ MHD_USE_EPOLL
@ MHD_ALLOW_SUSPEND_RESUME
@ MHD_USE_TCP_FASTOPEN
@ MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_AUTO
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
@ MHD_USE_TURBO
@ MHD_USE_IPv6
@ MHD_USE_DUAL_STACK
@ MHD_USE_POLL
@ MHD_USE_SELECT_INTERNALLY
@ MHD_USE_TLS
@ MHD_USE_INSECURE_TLS_EARLY_DATA
@ MHD_ALLOW_UPGRADE
@ MHD_USE_NO_LISTEN_SOCKET
@ MHD_USE_PEDANTIC_CHECKS
@ MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_USE_ITC
@ MHD_USE_NO_THREAD_SAFETY
@ MHD_DAUTH_BIND_NONCE_URI
@ MHD_DAUTH_BIND_NONCE_URI_PARAMS
platform-specific includes for libmicrohttpd
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition platform.h:126
Methods for managing response objects.
MHD_socket socket_fd
Definition internal.h:1489
enum MHD_tristate sk_nodelay
Definition internal.h:1515
struct MHD_Connection * prev
Definition internal.h:1347
socklen_t addr_len
Definition internal.h:1469
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition internal.h:1576
enum MHD_tristate is_nonip
Definition internal.h:1495
struct MHD_itc_ resume_itc
Definition internal.h:1657
volatile bool resuming
Definition internal.h:1627
void * socket_context
Definition internal.h:1395
uint64_t last_activity
Definition internal.h:1475
struct MHD_Request rq
Definition internal.h:1371
struct MHD_Connection * nextX
Definition internal.h:1356
struct MHD_Connection * next
Definition internal.h:1342
size_t read_buffer_offset
Definition internal.h:1442
struct MHD_Reply rp
Definition internal.h:1376
struct MemoryPool * pool
Definition internal.h:1386
enum MHD_CONNECTION_STATE state
Definition internal.h:1571
struct MHD_Connection * prevX
Definition internal.h:1361
struct MHD_Daemon * daemon
Definition internal.h:1366
bool sk_spipe_suppress
Definition internal.h:1505
uint64_t connection_timeout_ms
Definition internal.h:1482
struct sockaddr_storage * addr
Definition internal.h:1421
size_t read_buffer_size
Definition internal.h:1436
enum MHD_tristate sk_corked
Definition internal.h:1510
size_t pool_size
Definition internal.h:2172
MHD_NotifyConnectionCallback notify_connection
Definition internal.h:2079
MHD_AccessHandlerCallback default_handler
Definition internal.h:1903
LogCallback uri_log_callback
Definition internal.h:2093
bool data_already_pending
Definition internal.h:2294
union MHD_DaemonInfo daemon_info_dummy_port
Definition internal.h:2542
struct MHD_Connection * normal_timeout_tail
Definition internal.h:2036
bool at_limit
Definition internal.h:2272
struct MHD_Connection * new_connections_tail
Definition internal.h:1926
int client_discipline
Definition internal.h:2318
uint16_t port
Definition internal.h:2116
bool listen_nonblk
Definition internal.h:2147
unsigned int connection_limit
Definition internal.h:2299
void * unescape_callback_cls
Definition internal.h:2108
enum MHD_DisableSanityCheck insanity_level
Definition internal.h:2233
struct MHD_Connection * connections_tail
Definition internal.h:1936
struct MHD_Connection * suspended_connections_tail
Definition internal.h:1946
union MHD_DaemonInfo daemon_info_dummy_listen_fd
Definition internal.h:2520
struct MHD_Connection * manual_timeout_head
Definition internal.h:2044
unsigned int listen_backlog_size
Definition internal.h:2514
struct MHD_Connection * normal_timeout_head
Definition internal.h:2029
union MHD_DaemonInfo daemon_info_dummy_flags
Definition internal.h:2537
MHD_RequestCompletedCallback notify_completed
Definition internal.h:2068
struct MHD_Connection * cleanup_head
Definition internal.h:1951
unsigned int connections
Definition internal.h:2167
struct MHD_itc_ itc
Definition internal.h:2251
int listening_address_reuse
Definition internal.h:2244
uint64_t connection_timeout_ms
Definition internal.h:2306
void * apc_cls
Definition internal.h:2062
unsigned int per_ip_connection_limit
Definition internal.h:2312
struct MHD_Connection * manual_timeout_tail
Definition internal.h:2051
volatile bool shutdown
Definition internal.h:2256
union MHD_DaemonInfo daemon_info_dummy_num_connections
Definition internal.h:2532
enum MHD_FLAG options
Definition internal.h:1916
void * notify_connection_cls
Definition internal.h:2084
struct MHD_Connection * cleanup_tail
Definition internal.h:1956
bool sigpipe_blocked
Definition internal.h:2346
UnescapeCallback unescape_callback
Definition internal.h:2103
void * notify_completed_cls
Definition internal.h:2073
volatile bool was_quiesced
Definition internal.h:2263
struct MHD_Connection * suspended_connections_head
Definition internal.h:1941
struct MHD_Connection * new_connections_head
Definition internal.h:1921
int allow_bzero_in_url
Definition internal.h:2325
enum MHD_tristate listen_is_unix
Definition internal.h:1961
volatile bool resuming
Definition internal.h:2277
void * default_handler_cls
Definition internal.h:1908
struct MHD_Connection * connections_head
Definition internal.h:1931
MHD_AcceptPolicyCallback apc
Definition internal.h:2057
volatile bool have_new
Definition internal.h:2283
size_t pool_increment
Definition internal.h:2177
MHD_socket listen_fd
Definition internal.h:2142
void * per_ip_connection_count
Definition internal.h:2159
void * uri_log_callback_cls
Definition internal.h:2098
struct MHD_Daemon * master
Definition internal.h:2134
enum MHD_OPTION option
struct MHD_Response * response
Definition internal.h:1282
void * client_context
Definition internal.h:1198
bool client_aware
Definition internal.h:1205
const char *const str
const size_t len
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:67
void * tdelete(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:92
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:32
enum MHD_FLAG flags
unsigned int num_connections
MHD_socket listen_fd