GNU libmicrohttpd 1.0.5
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
651#endif /* HTTPS_SUPPORT */
652
653
654#undef MHD_get_fdset
655
688MHD_get_fdset (struct MHD_Daemon *daemon,
689 fd_set *read_fd_set,
690 fd_set *write_fd_set,
691 fd_set *except_fd_set,
692 MHD_socket *max_fd)
693{
694 return MHD_get_fdset2 (daemon,
695 read_fd_set,
696 write_fd_set,
697 except_fd_set,
698 max_fd,
699#ifdef HAS_FD_SETSIZE_OVERRIDABLE
700 daemon->fdset_size_set_by_app ?
701 ((unsigned int) daemon->fdset_size) :
702 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
703#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
704 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
705#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
706 );
707}
708
709
710#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
723static bool
724urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
725 fd_set *rs,
726 fd_set *ws,
727 fd_set *es,
728 MHD_socket *max_fd,
729 int fd_setsize)
730{
731 const MHD_socket conn_sckt = urh->connection->socket_fd;
732 const MHD_socket mhd_sckt = urh->mhd.socket;
733 bool res = true;
734
735#ifndef HAS_FD_SETSIZE_OVERRIDABLE
736 (void) fd_setsize; /* Mute compiler warning */
737 fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
738#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
739
740 /* Do not add to 'es' only if socket is closed
741 * or not used anymore. */
742 if (MHD_INVALID_SOCKET != conn_sckt)
743 {
744 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
745 (! MHD_add_to_fd_set_ (conn_sckt,
746 rs,
747 max_fd,
748 fd_setsize)) )
749 res = false;
750 if ( (0 != urh->out_buffer_used) &&
751 (! MHD_add_to_fd_set_ (conn_sckt,
752 ws,
753 max_fd,
754 fd_setsize)) )
755 res = false;
756 /* Do not monitor again for errors if error was detected before as
757 * error state is remembered. */
758 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
759 ((0 != urh->in_buffer_size) ||
760 (0 != urh->out_buffer_size) ||
761 (0 != urh->out_buffer_used))
762 && (NULL != es))
763 (void) MHD_add_to_fd_set_ (conn_sckt,
764 es,
765 max_fd,
766 fd_setsize);
767 }
768 if (MHD_INVALID_SOCKET != mhd_sckt)
769 {
770 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
771 (! MHD_add_to_fd_set_ (mhd_sckt,
772 rs,
773 max_fd,
774 fd_setsize)) )
775 res = false;
776 if ( (0 != urh->in_buffer_used) &&
777 (! MHD_add_to_fd_set_ (mhd_sckt,
778 ws,
779 max_fd,
780 fd_setsize)) )
781 res = false;
782 /* Do not monitor again for errors if error was detected before as
783 * error state is remembered. */
784 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
785 ((0 != urh->out_buffer_size) ||
786 (0 != urh->in_buffer_size) ||
787 (0 != urh->in_buffer_used))
788 && (NULL != es))
789 MHD_add_to_fd_set_ (mhd_sckt,
790 es,
791 max_fd,
792 fd_setsize);
793 }
794
795 return res;
796}
797
798
809static void
810urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
811 const fd_set *rs,
812 const fd_set *ws,
813 const fd_set *es,
814 int fd_setsize)
815{
816 const MHD_socket conn_sckt = urh->connection->socket_fd;
817 const MHD_socket mhd_sckt = urh->mhd.socket;
818
819 /* Reset read/write ready, preserve error state. */
820 urh->app.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
822 urh->mhd.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
824
825 mhd_assert (urh->connection->sk_nonblck);
826
827#ifndef HAS_FD_SETSIZE_OVERRIDABLE
828 (void) fd_setsize; /* Mute compiler warning */
829 mhd_assert (((int) FD_SETSIZE) <= fd_setsize);
830 fd_setsize = FD_SETSIZE; /* Help compiler to optimise */
831#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
832
833 if (MHD_INVALID_SOCKET != conn_sckt)
834 {
835 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (conn_sckt, NULL, fd_setsize))
836 {
837 if (FD_ISSET (conn_sckt, (fd_set *) _MHD_DROP_CONST (rs)))
838 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
839 if (FD_ISSET (conn_sckt, (fd_set *) _MHD_DROP_CONST (ws)))
840 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
841 if ((NULL != es) &&
842 FD_ISSET (conn_sckt, (fd_set *) _MHD_DROP_CONST (es)))
843 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
844 }
845 else
846 { /* Cannot check readiness. Force ready state is safe as socket is non-blocking */
847 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
848 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
849 }
850 }
851 if ((MHD_INVALID_SOCKET != mhd_sckt))
852 {
853 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (mhd_sckt, NULL, fd_setsize))
854 {
855 if (FD_ISSET (mhd_sckt, (fd_set *) _MHD_DROP_CONST (rs)))
856 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
857 if (FD_ISSET (mhd_sckt, (fd_set *) _MHD_DROP_CONST (ws)))
858 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
859 if ((NULL != es) &&
860 FD_ISSET (mhd_sckt, (fd_set *) _MHD_DROP_CONST (es)))
861 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
862 }
863 else
864 { /* Cannot check readiness. Force ready state is safe as socket is non-blocking */
865 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
866 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
867 }
868 }
869}
870
871
872#ifdef HAVE_POLL
873
882static void
883urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
884 struct pollfd p[2])
885{
886 p[0].events = 0;
887 p[1].events = 0;
888
889 if (urh->in_buffer_used < urh->in_buffer_size)
890 p[0].events |= POLLIN;
891 if (0 != urh->out_buffer_used)
892 p[0].events |= POLLOUT;
893
894 /* Do not monitor again for errors if error was detected before as
895 * error state is remembered. */
896 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
897 ((0 != urh->in_buffer_size) ||
898 (0 != urh->out_buffer_size) ||
899 (0 != urh->out_buffer_used)))
900 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
901
902 if (urh->out_buffer_used < urh->out_buffer_size)
903 p[1].events |= POLLIN;
904 if (0 != urh->in_buffer_used)
905 p[1].events |= POLLOUT;
906
907 /* Do not monitor again for errors if error was detected before as
908 * error state is remembered. */
909 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
910 ((0 != urh->out_buffer_size) ||
911 (0 != urh->in_buffer_size) ||
912 (0 != urh->in_buffer_used)))
913 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
914}
915
916
923static void
924urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
925 struct pollfd p[2])
926{
927 p[0].fd = urh->connection->socket_fd;
928 p[1].fd = urh->mhd.socket;
929 urh_update_pollfd (urh,
930 p);
931}
932
933
939static void
940urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
941 struct pollfd p[2])
942{
943 /* Reset read/write ready, preserve error state. */
944 urh->app.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
946 urh->mhd.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
948
949 if (0 != (p[0].revents & POLLIN))
950 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
951 if (0 != (p[0].revents & POLLOUT))
952 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
953 if (0 != (p[0].revents & POLLHUP))
955 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
956 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
957 if (0 != (p[1].revents & POLLIN))
958 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
959 if (0 != (p[1].revents & POLLOUT))
960 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
961 if (0 != (p[1].revents & POLLHUP))
962 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
963 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
965}
966
967
968#endif /* HAVE_POLL */
969#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
970
971
986static enum MHD_Result
988 fd_set *read_fd_set,
989 fd_set *write_fd_set,
990 fd_set *except_fd_set,
991 MHD_socket *max_fd,
992 int fd_setsize)
993{
994 struct MHD_Connection *pos;
995 struct MHD_Connection *posn;
996 enum MHD_Result result = MHD_YES;
997 MHD_socket ls;
998 bool itc_added;
999
1000#ifndef HAS_FD_SETSIZE_OVERRIDABLE
1001 (void) fd_setsize; /* Mute compiler warning */
1002 fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
1003#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
1004
1005 if (daemon->shutdown)
1006 return MHD_YES;
1007
1008 /* The order of FDs added is important for W32 sockets as W32 fd_set has
1009 limits for number of added FDs instead of the limit for the higher
1010 FD value. */
1011
1012 /* Add ITC FD first. The daemon must be able to respond on application
1013 commands issued in other threads. */
1014 itc_added = false;
1015 if (MHD_ITC_IS_VALID_ (daemon->itc))
1016 {
1017 itc_added = MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1018 read_fd_set,
1019 max_fd,
1020 fd_setsize);
1021 if (! itc_added)
1022 result = MHD_NO;
1023 }
1024
1026 if (! itc_added &&
1027 (MHD_INVALID_SOCKET != ls))
1028 {
1029 /* Add listen FD if ITC was not added. Listen FD could be used to signal
1030 the daemon shutdown. */
1031 if (MHD_add_to_fd_set_ (ls,
1032 read_fd_set,
1033 max_fd,
1034 fd_setsize))
1035 ls = MHD_INVALID_SOCKET; /* Already added */
1036 else
1037 result = MHD_NO;
1038 }
1039
1040 /* Add all sockets to 'except_fd_set' as well to watch for
1041 * out-of-band data. However, ignore errors if INFO_READ
1042 * or INFO_WRITE sockets will not fit 'except_fd_set'. */
1043 /* Start from oldest connections. Make sense for W32 FDSETs. */
1044 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1045 {
1046 posn = pos->prev;
1047
1048 switch (pos->event_loop_info)
1049 {
1052 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1053 read_fd_set,
1054 max_fd,
1055 fd_setsize))
1056 result = MHD_NO;
1057#ifdef MHD_POSIX_SOCKETS
1058 if (NULL != except_fd_set)
1059 (void) MHD_add_to_fd_set_ (pos->socket_fd,
1060 except_fd_set,
1061 max_fd,
1062 fd_setsize);
1063#endif /* MHD_POSIX_SOCKETS */
1064 break;
1066 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1067 write_fd_set,
1068 max_fd,
1069 fd_setsize))
1070 result = MHD_NO;
1071#ifdef MHD_POSIX_SOCKETS
1072 if (NULL != except_fd_set)
1073 (void) MHD_add_to_fd_set_ (pos->socket_fd,
1074 except_fd_set,
1075 max_fd,
1076 fd_setsize);
1077#endif /* MHD_POSIX_SOCKETS */
1078 break;
1080 if ( (NULL == except_fd_set) ||
1082 except_fd_set,
1083 max_fd,
1084 fd_setsize))
1085 result = MHD_NO;
1086 break;
1088 /* this should never happen */
1089 break;
1090 }
1091 }
1092#ifdef MHD_WINSOCK_SOCKETS
1093 /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
1094 * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
1095 * not be pushed out. */
1096 if (NULL != except_fd_set)
1097 {
1098 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1099 {
1100 posn = pos->prev;
1102 except_fd_set,
1103 max_fd,
1104 fd_setsize);
1105 }
1106 }
1107#endif /* MHD_WINSOCK_SOCKETS */
1108#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1109 if (1)
1110 {
1111 struct MHD_UpgradeResponseHandle *urh;
1112
1113 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
1114 {
1115 if (MHD_NO ==
1116 urh_to_fdset (urh,
1117 read_fd_set,
1118 write_fd_set,
1119 except_fd_set,
1120 max_fd,
1121 fd_setsize))
1122 result = MHD_NO;
1123 }
1124 }
1125#endif
1126
1127 if (MHD_INVALID_SOCKET != ls)
1128 {
1129 /* The listen socket is present and hasn't been added */
1130 if ((daemon->connections < daemon->connection_limit) &&
1131 ! daemon->at_limit)
1132 {
1133 if (! MHD_add_to_fd_set_ (ls,
1134 read_fd_set,
1135 max_fd,
1136 fd_setsize))
1137 result = MHD_NO;
1138 }
1139 }
1140
1141#if _MHD_DEBUG_CONNECT
1142#ifdef HAVE_MESSAGES
1143 if (NULL != max_fd)
1144 MHD_DLOG (daemon,
1145 _ ("Maximum socket in select set: %d\n"),
1146 *max_fd);
1147#endif
1148#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1149 return result;
1150}
1151
1152
1189 fd_set *read_fd_set,
1190 fd_set *write_fd_set,
1191 fd_set *except_fd_set,
1192 MHD_socket *max_fd,
1193 unsigned int fd_setsize)
1194{
1195 if ( (NULL == daemon) ||
1196 (NULL == read_fd_set) ||
1197 (NULL == write_fd_set) ||
1198 MHD_D_IS_USING_THREADS_ (daemon) ||
1199 MHD_D_IS_USING_POLL_ (daemon))
1200 return MHD_NO;
1201
1202#ifdef HAVE_MESSAGES
1203 if (NULL == except_fd_set)
1204 {
1205 MHD_DLOG (daemon,
1206 _ ("MHD_get_fdset2() called with except_fd_set "
1207 "set to NULL. Such behavior is unsupported.\n"));
1208 }
1209#endif
1210
1211#ifdef HAS_FD_SETSIZE_OVERRIDABLE
1212 if (0 == fd_setsize)
1213 return MHD_NO;
1214 else if (((unsigned int) INT_MAX) < fd_setsize)
1215 fd_setsize = (unsigned int) INT_MAX;
1216#ifdef HAVE_MESSAGES
1217 else if (daemon->fdset_size > ((int) fd_setsize))
1218 {
1219 if (daemon->fdset_size_set_by_app)
1220 {
1221 MHD_DLOG (daemon,
1222 _ ("%s() called with fd_setsize (%u) " \
1223 "less than value set by MHD_OPTION_APP_FD_SETSIZE (%d). " \
1224 "Some socket FDs may be not processed. " \
1225 "Use MHD_OPTION_APP_FD_SETSIZE with the correct value.\n"),
1226 "MHD_get_fdset2", fd_setsize, daemon->fdset_size);
1227 }
1228 else
1229 {
1230 MHD_DLOG (daemon,
1231 _ ("%s() called with fd_setsize (%u) " \
1232 "less than FD_SETSIZE used by MHD (%d). " \
1233 "Some socket FDs may be not processed. " \
1234 "Consider using MHD_OPTION_APP_FD_SETSIZE option.\n"),
1235 "MHD_get_fdset2", fd_setsize, daemon->fdset_size);
1236 }
1237 }
1238#endif /* HAVE_MESSAGES */
1239#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
1240 if (((unsigned int) FD_SETSIZE) > fd_setsize)
1241 {
1242#ifdef HAVE_MESSAGES
1243 MHD_DLOG (daemon,
1244 _ ("%s() called with fd_setsize (%u) " \
1245 "less than fixed FD_SETSIZE value (%d) used on the " \
1246 "platform.\n"),
1247 "MHD_get_fdset2", fd_setsize, (int) FD_SETSIZE);
1248#endif /* HAVE_MESSAGES */
1249 return MHD_NO;
1250 }
1251 fd_setsize = (int) FD_SETSIZE; /* Help compiler to optimise */
1252#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
1253
1254#ifdef EPOLL_SUPPORT
1255 if (MHD_D_IS_USING_EPOLL_ (daemon))
1256 {
1257 if (daemon->shutdown)
1258 return MHD_YES;
1259
1260 /* we're in epoll mode, use the epoll FD as a stand-in for
1261 the entire event set */
1262
1263 return MHD_add_to_fd_set_ (daemon->epoll_fd,
1264 read_fd_set,
1265 max_fd,
1266 (int) fd_setsize) ? MHD_YES : MHD_NO;
1267 }
1268#endif
1269
1270 return internal_get_fdset2 (daemon,
1271 read_fd_set,
1272 write_fd_set,
1273 except_fd_set,
1274 max_fd,
1275 (int) fd_setsize);
1276}
1277
1278
1292static enum MHD_Result
1294 bool read_ready,
1295 bool write_ready,
1296 bool force_close)
1297{
1298 enum MHD_Result ret;
1299 bool states_info_processed = false;
1300 /* Fast track flag */
1301 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1302 ret = MHD_YES;
1303
1304 mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1306 mhd_assert ((0 != (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1307 (! MHD_thread_handle_ID_is_valid_ID_ (con->tid)));
1308 mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
1310
1311#ifdef HTTPS_SUPPORT
1312 if (con->tls_read_ready)
1313 read_ready = true;
1314#endif /* HTTPS_SUPPORT */
1315 if ( (0 != (MHD_EVENT_LOOP_INFO_READ & con->event_loop_info)) &&
1316 (read_ready || (force_close && con->sk_nonblck)) )
1317 {
1318 MHD_connection_handle_read (con, force_close);
1319 mhd_assert (! force_close || MHD_CONNECTION_CLOSED == con->state);
1320 ret = MHD_connection_handle_idle (con);
1321 if (force_close)
1322 return ret;
1323 states_info_processed = true;
1324 }
1325 if (! force_close)
1326 {
1327 /* No need to check value of 'ret' here as closed connection
1328 * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1330 write_ready)
1331 {
1333 ret = MHD_connection_handle_idle (con);
1334 states_info_processed = true;
1335 }
1336 }
1337 else
1338 {
1341 return MHD_connection_handle_idle (con);
1342 }
1343
1344 if (! states_info_processed)
1345 { /* Connection is not read or write ready, but external conditions
1346 * may be changed and need to be processed. */
1347 ret = MHD_connection_handle_idle (con);
1348 }
1349 /* Fast track for fast connections. */
1350 /* If full request was read by single read_handler() invocation
1351 and headers were completely prepared by single MHD_connection_handle_idle()
1352 then try not to wait for next sockets polling and send response
1353 immediately.
1354 As writeability of socket was not checked and it may have
1355 some data pending in system buffers, use this optimization
1356 only for non-blocking sockets. */
1357 /* No need to check 'ret' as connection is always in
1358 * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1359 else if (on_fasttrack && con->sk_nonblck)
1360 {
1362 {
1364 /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1365 ret = MHD_connection_handle_idle (con);
1366 }
1367 /* If all headers were sent by single write_handler() and
1368 * response body is prepared by single MHD_connection_handle_idle()
1369 * call - continue. */
1372 {
1374 ret = MHD_connection_handle_idle (con);
1375 }
1376 }
1377
1378 /* All connection's data and states are processed for this turn.
1379 * If connection already has more data to be processed - use
1380 * zero timeout for next select()/poll(). */
1381 /* Thread-per-connection do not need global zero timeout as
1382 * connections are processed individually. */
1383 /* Note: no need to check for read buffer availability for
1384 * TLS read-ready connection in 'read info' state as connection
1385 * without space in read buffer will be marked as 'info block'. */
1386 if ( (! con->daemon->data_already_pending) &&
1388 {
1390 con->daemon->data_already_pending = true;
1391#ifdef HTTPS_SUPPORT
1392 else if ( (con->tls_read_ready) &&
1394 con->daemon->data_already_pending = true;
1395#endif /* HTTPS_SUPPORT */
1396 }
1397 return ret;
1398}
1399
1400
1401#ifdef UPGRADE_SUPPORT
1409static void
1410cleanup_upgraded_connection (struct MHD_Connection *connection)
1411{
1412 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1413
1414 if (NULL == urh)
1415 return;
1416#ifdef HTTPS_SUPPORT
1417 /* Signal remote client the end of TLS connection by
1418 * gracefully closing TLS session. */
1419 if (0 != (connection->daemon->options & MHD_USE_TLS))
1420 gnutls_bye (connection->tls_session,
1421 GNUTLS_SHUT_WR);
1422
1423 if (MHD_INVALID_SOCKET != urh->mhd.socket)
1424 MHD_socket_close_chk_ (urh->mhd.socket);
1425
1426 if (MHD_INVALID_SOCKET != urh->app.socket)
1427 MHD_socket_close_chk_ (urh->app.socket);
1428#endif /* HTTPS_SUPPORT */
1429 connection->urh = NULL;
1430 free (urh);
1431}
1432
1433
1434#endif /* UPGRADE_SUPPORT */
1435
1436
1437#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1446static void
1447process_urh (struct MHD_UpgradeResponseHandle *urh)
1448{
1449 /* Help compiler to optimize:
1450 * pointers to 'connection' and 'daemon' are not changed
1451 * during this processing, so no need to chain dereference
1452 * each time. */
1453 struct MHD_Connection *const connection = urh->connection;
1454 struct MHD_Daemon *const daemon = connection->daemon;
1455 /* Prevent data races: use same value of 'was_closed' throughout
1456 * this function. If 'was_closed' changed externally in the middle
1457 * of processing - it will be processed on next iteration. */
1458 bool was_closed;
1459
1460#ifdef MHD_USE_THREADS
1461 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
1462 MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
1463#endif /* MHD_USE_THREADS */
1464
1465 mhd_assert (0 != (daemon->options & MHD_USE_TLS));
1466
1467 if (daemon->shutdown)
1468 {
1469 /* Daemon shutting down, application will not receive any more data. */
1470#ifdef HAVE_MESSAGES
1471 if (! urh->was_closed)
1472 {
1473 MHD_DLOG (daemon,
1474 _ ("Initiated daemon shutdown while \"upgraded\" " \
1475 "connection was not closed.\n"));
1476 }
1477#endif
1478 urh->was_closed = true;
1479 }
1480 was_closed = urh->was_closed;
1481 if (was_closed)
1482 {
1483 /* Application was closed connections: no more data
1484 * can be forwarded to application socket. */
1485 if (0 < urh->in_buffer_used)
1486 {
1487#ifdef HAVE_MESSAGES
1488 MHD_DLOG (daemon,
1489 _ ("Failed to forward to application %" PRIu64 \
1490 " bytes of data received from remote side: " \
1491 "application closed data forwarding.\n"),
1492 (uint64_t) urh->in_buffer_used);
1493#endif
1494
1495 }
1496 /* Discard any data received form remote. */
1497 urh->in_buffer_used = 0;
1498 /* Do not try to push data to application. */
1499 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1500 /* Reading from remote client is not required anymore. */
1501 urh->in_buffer_size = 0;
1502 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1503 connection->tls_read_ready = false;
1504 }
1505
1506 /* On some platforms (W32, possibly Darwin) failed send() (send() will
1507 * always fail after remote disconnect was detected) may discard data in
1508 * system buffers received by system but not yet read by recv(). So, before
1509 * trying send() on any socket, recv() must be performed at first otherwise
1510 * last part of incoming data may be lost. If disconnect or error was
1511 * detected - try to read from socket to dry data possibly pending is system
1512 * buffers. */
1513
1514 /*
1515 * handle reading from remote TLS client
1516 */
1518 & urh->app.celi)) ||
1519 (connection->tls_read_ready)) &&
1520 (urh->in_buffer_used < urh->in_buffer_size))
1521 {
1522 ssize_t res;
1523 size_t buf_size;
1524
1525 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1526 if (buf_size > SSIZE_MAX)
1527 buf_size = SSIZE_MAX;
1528
1529 res = gnutls_record_recv (connection->tls_session,
1530 &urh->in_buffer[urh->in_buffer_used],
1531 buf_size);
1532 if (0 >= res)
1533 {
1534 connection->tls_read_ready = false;
1535 if (GNUTLS_E_INTERRUPTED != res)
1536 {
1537 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1538 if ((GNUTLS_E_AGAIN != res) ||
1539 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)))
1540 {
1541 /* TLS unrecoverable error has been detected,
1542 socket error was detected and all data has been read,
1543 or socket was disconnected/shut down. */
1544 /* Stop trying to read from this TLS socket. */
1545 urh->in_buffer_size = 0;
1546 }
1547 }
1548 }
1549 else /* 0 < res */
1550 {
1551 urh->in_buffer_used += (size_t) res;
1552 connection->tls_read_ready =
1553 (0 < gnutls_record_check_pending (connection->tls_session));
1554 }
1555 }
1556
1557 /*
1558 * handle reading from application
1559 */
1560 /* If application signalled MHD about socket closure then
1561 * check for any pending data even if socket is not marked
1562 * as 'ready' (signal may arrive after poll()/select()).
1563 * Socketpair for forwarding is always in non-blocking mode
1564 * so no risk that recv() will block the thread. */
1566 & urh->mhd.celi))
1567 || was_closed) /* Force last reading from app if app has closed the connection */
1568 && (urh->out_buffer_used < urh->out_buffer_size))
1569 {
1570 ssize_t res;
1571 size_t buf_size;
1572
1573 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1574 if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1575 buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1576
1577 res = MHD_recv_ (urh->mhd.socket,
1578 &urh->out_buffer[urh->out_buffer_used],
1579 buf_size);
1580 if (0 >= res)
1581 {
1582 const int err = MHD_socket_get_error_ ();
1583 if ((0 == res) ||
1584 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1586 {
1587 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1588 if ((0 == res) ||
1589 (was_closed) ||
1590 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1591 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1592 {
1593 /* Socket disconnect/shutdown was detected;
1594 * Application signalled about closure of 'upgraded' socket and
1595 * all data has been read from application;
1596 * or persistent / unrecoverable error. */
1597 /* Do not try to pull more data from application. */
1598 urh->out_buffer_size = 0;
1599 }
1600 }
1601 }
1602 else /* 0 < res */
1603 {
1604 urh->out_buffer_used += (size_t) res;
1605 if (buf_size > (size_t) res)
1606 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1607 }
1608 }
1609
1610 /*
1611 * handle writing to remote HTTPS client
1612 */
1613 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1614 (urh->out_buffer_used > 0) )
1615 {
1616 ssize_t res;
1617 size_t data_size;
1618
1619 data_size = urh->out_buffer_used;
1620 if (data_size > SSIZE_MAX)
1621 data_size = SSIZE_MAX;
1622
1623 res = gnutls_record_send (connection->tls_session,
1624 urh->out_buffer,
1625 data_size);
1626 if (0 >= res)
1627 {
1628 if (GNUTLS_E_INTERRUPTED != res)
1629 {
1630 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1631 if (GNUTLS_E_AGAIN != res)
1632 {
1633 /* TLS connection shut down or
1634 * persistent / unrecoverable error. */
1635#ifdef HAVE_MESSAGES
1636 MHD_DLOG (daemon,
1637 _ ("Failed to forward to remote client %" PRIu64 \
1638 " bytes of data received from application: %s\n"),
1639 (uint64_t) urh->out_buffer_used,
1640 gnutls_strerror ((int) res));
1641#endif
1642 /* Discard any data unsent to remote. */
1643 urh->out_buffer_used = 0;
1644 /* Do not try to pull more data from application. */
1645 urh->out_buffer_size = 0;
1646 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1647 }
1648 }
1649 }
1650 else /* 0 < res */
1651 {
1652 const size_t next_out_buffer_used = urh->out_buffer_used - (size_t) res;
1653 if (0 != next_out_buffer_used)
1654 {
1655 memmove (urh->out_buffer,
1656 &urh->out_buffer[res],
1657 next_out_buffer_used);
1658 }
1659 urh->out_buffer_used = next_out_buffer_used;
1660 }
1661 if ( (0 == urh->out_buffer_used) &&
1662 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1663 {
1664 /* Unrecoverable error on socket was detected and all
1665 * pending data was sent to remote. */
1666 /* Do not try to send to remote anymore. */
1667 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1668 /* Do not try to pull more data from application. */
1669 urh->out_buffer_size = 0;
1670 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1671 }
1672 }
1673
1674 /*
1675 * handle writing to application
1676 */
1677 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1678 (urh->in_buffer_used > 0) )
1679 {
1680 ssize_t res;
1681 size_t data_size;
1682
1683 data_size = urh->in_buffer_used;
1684 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1685 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1686
1687 res = MHD_send_ (urh->mhd.socket,
1688 urh->in_buffer,
1689 data_size);
1690 if (0 >= res)
1691 {
1692 const int err = MHD_socket_get_error_ ();
1693 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1695 {
1696 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1697 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1698 {
1699 /* Socketpair connection shut down or
1700 * persistent / unrecoverable error. */
1701#ifdef HAVE_MESSAGES
1702 MHD_DLOG (daemon,
1703 _ ("Failed to forward to application %" PRIu64 \
1704 " bytes of data received from remote side: %s\n"),
1705 (uint64_t) urh->in_buffer_used,
1706 MHD_socket_strerr_ (err));
1707#endif
1708 /* Discard any data received from remote. */
1709 urh->in_buffer_used = 0;
1710 /* Reading from remote client is not required anymore. */
1711 urh->in_buffer_size = 0;
1712 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1713 connection->tls_read_ready = false;
1714 }
1715 }
1716 }
1717 else /* 0 < res */
1718 {
1719 const size_t next_in_buffer_used = urh->in_buffer_used - (size_t) res;
1720 if (0 != next_in_buffer_used)
1721 {
1722 memmove (urh->in_buffer,
1723 &urh->in_buffer[res],
1724 next_in_buffer_used);
1725 if (data_size > (size_t) res)
1726 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1727 }
1728 urh->in_buffer_used = next_in_buffer_used;
1729 }
1730 if ( (0 == urh->in_buffer_used) &&
1731 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1732 {
1733 /* Do not try to push data to application. */
1734 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1735 /* Reading from remote client is not required anymore. */
1736 urh->in_buffer_size = 0;
1737 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1738 connection->tls_read_ready = false;
1739 }
1740 }
1741
1742 /* Check whether data is present in TLS buffers
1743 * and incoming forward buffer have some space. */
1744 if ( (connection->tls_read_ready) &&
1745 (urh->in_buffer_used < urh->in_buffer_size) &&
1746 (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) )
1747 daemon->data_already_pending = true;
1748
1749 if ( (daemon->shutdown) &&
1750 ( (0 != urh->out_buffer_size) ||
1751 (0 != urh->out_buffer_used) ) )
1752 {
1753 /* Daemon shutting down, discard any remaining forward data. */
1754#ifdef HAVE_MESSAGES
1755 if (0 < urh->out_buffer_used)
1756 MHD_DLOG (daemon,
1757 _ ("Failed to forward to remote client %" PRIu64 \
1758 " bytes of data received from application: daemon shut down.\n"),
1759 (uint64_t) urh->out_buffer_used);
1760#endif
1761 /* Discard any data unsent to remote. */
1762 urh->out_buffer_used = 0;
1763 /* Do not try to sent to remote anymore. */
1764 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1765 /* Do not try to pull more data from application. */
1766 urh->out_buffer_size = 0;
1767 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1768 }
1769
1770 if (! was_closed && urh->was_closed)
1771 daemon->data_already_pending = true; /* Force processing again */
1772}
1773
1774
1775#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1776
1777#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1778#ifdef UPGRADE_SUPPORT
1787static void
1788thread_main_connection_upgrade (struct MHD_Connection *con)
1789{
1790#ifdef HTTPS_SUPPORT
1791 struct MHD_UpgradeResponseHandle *urh = con->urh;
1792 struct MHD_Daemon *daemon = con->daemon;
1793
1794 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
1796 /* Here, we need to bi-directionally forward
1797 until the application tells us that it is done
1798 with the socket; */
1799 if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1800 MHD_D_IS_USING_SELECT_ (daemon))
1801 {
1802 while ( (0 != urh->in_buffer_size) ||
1803 (0 != urh->out_buffer_size) ||
1804 (0 != urh->in_buffer_used) ||
1805 (0 != urh->out_buffer_used) )
1806 {
1807 /* use select */
1808 fd_set rs;
1809 fd_set ws;
1810 fd_set es;
1811 MHD_socket max_fd;
1812 int num_ready;
1813 bool result;
1814
1815 FD_ZERO (&rs);
1816 FD_ZERO (&ws);
1817 FD_ZERO (&es);
1818 max_fd = MHD_INVALID_SOCKET;
1819 result = urh_to_fdset (urh,
1820 &rs,
1821 &ws,
1822 &es,
1823 &max_fd,
1824 FD_SETSIZE);
1825 if (! result)
1826 {
1827#ifdef HAVE_MESSAGES
1828 MHD_DLOG (con->daemon,
1829 _ ("Error preparing select.\n"));
1830#endif
1831 break;
1832 }
1833 /* FIXME: does this check really needed? */
1834 if (MHD_INVALID_SOCKET != max_fd)
1835 {
1836 struct timeval *tvp;
1837 struct timeval tv;
1838 if (((con->tls_read_ready) &&
1839 (urh->in_buffer_used < urh->in_buffer_size)) ||
1840 (daemon->shutdown))
1841 { /* No need to wait if incoming data is already pending in TLS buffers. */
1842 tv.tv_sec = 0;
1843 tv.tv_usec = 0;
1844 tvp = &tv;
1845 }
1846 else
1847 tvp = NULL;
1848 num_ready = MHD_SYS_select_ (max_fd + 1,
1849 &rs,
1850 &ws,
1851 &es,
1852 tvp);
1853 }
1854 else
1855 num_ready = 0;
1856 if (num_ready < 0)
1857 {
1858 const int err = MHD_socket_get_error_ ();
1859
1860 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1861 continue;
1862#ifdef HAVE_MESSAGES
1863 MHD_DLOG (con->daemon,
1864 _ ("Error during select (%d): `%s'\n"),
1865 err,
1866 MHD_socket_strerr_ (err));
1867#endif
1868 break;
1869 }
1870 urh_from_fdset (urh,
1871 &rs,
1872 &ws,
1873 &es,
1874 (int) FD_SETSIZE);
1875 process_urh (urh);
1876 }
1877 }
1878#ifdef HAVE_POLL
1879 else if (0 != (daemon->options & MHD_USE_TLS))
1880 {
1881 /* use poll() */
1882 struct pollfd p[2];
1883 memset (p,
1884 0,
1885 sizeof (p));
1886 p[0].fd = urh->connection->socket_fd;
1887 p[1].fd = urh->mhd.socket;
1888
1889 while ( (0 != urh->in_buffer_size) ||
1890 (0 != urh->out_buffer_size) ||
1891 (0 != urh->in_buffer_used) ||
1892 (0 != urh->out_buffer_used) )
1893 {
1894 int timeout;
1895
1896 urh_update_pollfd (urh, p);
1897
1898 if (((con->tls_read_ready) &&
1899 (urh->in_buffer_used < urh->in_buffer_size)) ||
1900 (daemon->shutdown))
1901 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1902 else
1903 timeout = -1;
1904
1905 if (MHD_sys_poll_ (p,
1906 2,
1907 timeout) < 0)
1908 {
1909 const int err = MHD_socket_get_error_ ();
1910
1911 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1912 continue;
1913#ifdef HAVE_MESSAGES
1914 MHD_DLOG (con->daemon,
1915 _ ("Error during poll: `%s'\n"),
1916 MHD_socket_strerr_ (err));
1917#endif
1918 break;
1919 }
1920 urh_from_pollfd (urh,
1921 p);
1922 process_urh (urh);
1923 }
1924 }
1925 /* end POLL */
1926#endif
1927 /* end HTTPS */
1928#endif /* HTTPS_SUPPORT */
1929 /* TLS forwarding was finished. Cleanup socketpair. */
1931 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1932 * in connection thread for a little while. */
1933}
1934
1935
1936#endif /* UPGRADE_SUPPORT */
1937
1938
1946static uint64_t
1947connection_get_wait (struct MHD_Connection *c)
1948{
1949 const uint64_t now = MHD_monotonic_msec_counter ();
1950 const uint64_t since_actv = now - c->last_activity;
1951 const uint64_t timeout = c->connection_timeout_ms;
1952 uint64_t mseconds_left;
1953
1954 mhd_assert (0 != timeout);
1955 /* Keep the next lines in sync with #connection_check_timedout() to avoid
1956 * undesired side-effects like busy-waiting. */
1957 if (timeout < since_actv)
1958 {
1959 if (UINT64_MAX / 2 < since_actv)
1960 {
1961 const uint64_t jump_back = c->last_activity - now;
1962 /* Very unlikely that it is more than quarter-million years pause.
1963 * More likely that system clock jumps back. */
1964 if (5000 >= jump_back)
1965 { /* Jump back is less than 5 seconds, try to recover. */
1966 return 100; /* Set wait time to 0.1 seconds */
1967 }
1968 /* Too large jump back */
1969 }
1970 return 0; /* Connection has timed out */
1971 }
1972 else if (since_actv == timeout)
1973 {
1974 /* Exact match for timeout and time from last activity.
1975 * Maybe this is just a precise match or this happens because the timer
1976 * resolution is too low.
1977 * Set wait time to 0.1 seconds to avoid busy-waiting with low
1978 * timer resolution as connection is not timed-out yet. */
1979 return 100;
1980 }
1981 mseconds_left = timeout - since_actv;
1982
1983 return mseconds_left;
1984}
1985
1986
1994static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1995thread_main_handle_connection (void *data)
1996{
1997 struct MHD_Connection *con = data;
1998 struct MHD_Daemon *daemon = con->daemon;
1999 int num_ready;
2000 fd_set rs;
2001 fd_set ws;
2002 fd_set es;
2003 MHD_socket maxsock;
2004#ifdef WINDOWS
2005#ifdef HAVE_POLL
2006 unsigned int extra_slot;
2007#endif /* HAVE_POLL */
2008#define EXTRA_SLOTS 1
2009#else /* !WINDOWS */
2010#define EXTRA_SLOTS 0
2011#endif /* !WINDOWS */
2012#ifdef HAVE_POLL
2013 struct pollfd p[1 + EXTRA_SLOTS];
2014#endif
2015#undef EXTRA_SLOTS
2016#ifdef HAVE_POLL
2017 const bool use_poll = MHD_D_IS_USING_POLL_ (daemon);
2018#else /* ! HAVE_POLL */
2019 const bool use_poll = 0;
2020#endif /* ! HAVE_POLL */
2021 bool was_suspended = false;
2023
2024 while ( (! daemon->shutdown) &&
2025 (MHD_CONNECTION_CLOSED != con->state) )
2026 {
2027 bool use_zero_timeout;
2028#ifdef UPGRADE_SUPPORT
2029 struct MHD_UpgradeResponseHandle *const urh = con->urh;
2030#else /* ! UPGRADE_SUPPORT */
2031 static const void *const urh = NULL;
2032#endif /* ! UPGRADE_SUPPORT */
2033
2034 if ( (con->suspended) &&
2035 (NULL == urh) )
2036 {
2037 /* Connection was suspended, wait for resume. */
2038 was_suspended = true;
2039 if (! use_poll)
2040 {
2041 FD_ZERO (&rs);
2042 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2043 &rs,
2044 NULL,
2045 FD_SETSIZE))
2046 {
2047 #ifdef HAVE_MESSAGES
2048 MHD_DLOG (con->daemon,
2049 _ ("Failed to add FD to fd_set.\n"));
2050 #endif
2051 goto exit;
2052 }
2053 if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
2054 &rs,
2055 NULL,
2056 NULL,
2057 NULL))
2058 {
2059 const int err = MHD_socket_get_error_ ();
2060
2061 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2062 continue;
2063#ifdef HAVE_MESSAGES
2064 MHD_DLOG (con->daemon,
2065 _ ("Error during select (%d): `%s'\n"),
2066 err,
2067 MHD_socket_strerr_ (err));
2068#endif
2069 break;
2070 }
2071 }
2072#ifdef HAVE_POLL
2073 else /* use_poll */
2074 {
2075 p[0].events = POLLIN;
2076 p[0].fd = MHD_itc_r_fd_ (daemon->itc);
2077 p[0].revents = 0;
2078 if (0 > MHD_sys_poll_ (p,
2079 1,
2080 -1))
2081 {
2083 continue;
2084#ifdef HAVE_MESSAGES
2085 MHD_DLOG (con->daemon,
2086 _ ("Error during poll: `%s'\n"),
2088#endif
2089 break;
2090 }
2091 }
2092#endif /* HAVE_POLL */
2093 MHD_itc_clear_ (daemon->itc);
2094 continue; /* Check again for resume. */
2095 } /* End of "suspended" branch. */
2096
2097 if (was_suspended)
2098 {
2099 MHD_update_last_activity_ (con); /* Reset timeout timer. */
2100 /* Process response queued during suspend and update states. */
2102 was_suspended = false;
2103 }
2104
2105 use_zero_timeout =
2107#ifdef HTTPS_SUPPORT
2108 || ( (con->tls_read_ready) &&
2110#endif /* HTTPS_SUPPORT */
2111 );
2112 if (! use_poll)
2113 {
2114 /* use select */
2115 bool err_state = false;
2116 struct timeval tv;
2117 struct timeval *tvp;
2118 if (use_zero_timeout)
2119 {
2120 tv.tv_sec = 0;
2121 tv.tv_usec = 0;
2122 tvp = &tv;
2123 }
2124 else if (con->connection_timeout_ms > 0)
2125 {
2126 const uint64_t mseconds_left = connection_get_wait (con);
2127#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
2128 if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
2129 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
2130 else
2131#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
2132 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
2133
2134 tv.tv_usec = ((uint16_t) (mseconds_left % 1000)) * ((int32_t) 1000);
2135 tvp = &tv;
2136 }
2137 else
2138 tvp = NULL;
2139
2140 FD_ZERO (&rs);
2141 FD_ZERO (&ws);
2142 FD_ZERO (&es);
2143 maxsock = MHD_INVALID_SOCKET;
2144 switch (con->event_loop_info)
2145 {
2148 if (! MHD_add_to_fd_set_ (con->socket_fd,
2149 &rs,
2150 &maxsock,
2151 FD_SETSIZE))
2152 err_state = true;
2153 break;
2155 if (! MHD_add_to_fd_set_ (con->socket_fd,
2156 &ws,
2157 &maxsock,
2158 FD_SETSIZE))
2159 err_state = true;
2160 break;
2162 if (! MHD_add_to_fd_set_ (con->socket_fd,
2163 &es,
2164 &maxsock,
2165 FD_SETSIZE))
2166 err_state = true;
2167 break;
2169 /* how did we get here!? */
2170 goto exit;
2171 }
2172#ifdef WINDOWS
2173 if (MHD_ITC_IS_VALID_ (daemon->itc) )
2174 {
2175 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2176 &rs,
2177 &maxsock,
2178 FD_SETSIZE))
2179 err_state = 1;
2180 }
2181#endif
2182 if (err_state)
2183 {
2184#ifdef HAVE_MESSAGES
2185 MHD_DLOG (con->daemon,
2186 _ ("Failed to add FD to fd_set.\n"));
2187#endif
2188 goto exit;
2189 }
2190
2191 num_ready = MHD_SYS_select_ (maxsock + 1,
2192 &rs,
2193 &ws,
2194 &es,
2195 tvp);
2196 if (num_ready < 0)
2197 {
2198 const int err = MHD_socket_get_error_ ();
2199
2200 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2201 continue;
2202#ifdef HAVE_MESSAGES
2203 MHD_DLOG (con->daemon,
2204 _ ("Error during select (%d): `%s'\n"),
2205 err,
2206 MHD_socket_strerr_ (err));
2207#endif
2208 break;
2209 }
2210#ifdef WINDOWS
2211 /* Clear ITC before other processing so additional
2212 * signals will trigger select() again */
2213 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2214 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2215 &rs)) )
2216 MHD_itc_clear_ (daemon->itc);
2217#endif
2218 if (MHD_NO ==
2219 call_handlers (con,
2220 FD_ISSET (con->socket_fd,
2221 &rs),
2222 FD_ISSET (con->socket_fd,
2223 &ws),
2224 FD_ISSET (con->socket_fd,
2225 &es)) )
2226 goto exit;
2227 }
2228#ifdef HAVE_POLL
2229 else
2230 {
2231 int timeout_val;
2232 /* use poll */
2233 if (use_zero_timeout)
2234 timeout_val = 0;
2235 else if (con->connection_timeout_ms > 0)
2236 {
2237 const uint64_t mseconds_left = connection_get_wait (con);
2238#if SIZEOF_UINT64_T >= SIZEOF_INT
2239 if (mseconds_left >= INT_MAX)
2240 timeout_val = INT_MAX;
2241 else
2242#endif /* SIZEOF_UINT64_T >= SIZEOF_INT */
2243 timeout_val = (int) mseconds_left;
2244 }
2245 else
2246 timeout_val = -1;
2247 memset (&p,
2248 0,
2249 sizeof (p));
2250 p[0].fd = con->socket_fd;
2251 switch (con->event_loop_info)
2252 {
2255 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2256 break;
2258 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2259 break;
2261 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2262 break;
2264 /* how did we get here!? */
2265 goto exit;
2266 }
2267#ifdef WINDOWS
2268 extra_slot = 0;
2269 if (MHD_ITC_IS_VALID_ (daemon->itc))
2270 {
2271 p[1].events |= POLLIN;
2272 p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2273 p[1].revents = 0;
2274 extra_slot = 1;
2275 }
2276#endif
2277 if (MHD_sys_poll_ (p,
2278#ifdef WINDOWS
2279 1 + extra_slot,
2280#else
2281 1,
2282#endif
2283 timeout_val) < 0)
2284 {
2286 continue;
2287#ifdef HAVE_MESSAGES
2288 MHD_DLOG (con->daemon,
2289 _ ("Error during poll: `%s'\n"),
2291#endif
2292 break;
2293 }
2294#ifdef WINDOWS
2295 /* Clear ITC before other processing so additional
2296 * signals will trigger poll() again */
2297 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2298 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2299 MHD_itc_clear_ (daemon->itc);
2300#endif
2301 if (MHD_NO ==
2302 call_handlers (con,
2303 (0 != (p[0].revents & POLLIN)),
2304 (0 != (p[0].revents & POLLOUT)),
2305 (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC)) ))
2306 goto exit;
2307 }
2308#endif
2309#ifdef UPGRADE_SUPPORT
2310 if (MHD_CONNECTION_UPGRADE == con->state)
2311 {
2312 /* Normal HTTP processing is finished,
2313 * notify application. */
2314 if ( (NULL != daemon->notify_completed) &&
2315 (con->rq.client_aware) )
2316 daemon->notify_completed (daemon->notify_completed_cls,
2317 con,
2318 &con->rq.client_context,
2320 con->rq.client_aware = false;
2321
2322 thread_main_connection_upgrade (con);
2323 /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2324
2325 /* "Upgraded" data will not be used in this thread from this point. */
2326 con->urh->clean_ready = true;
2327 /* If 'urh->was_closed' set to true, connection will be
2328 * moved immediately to cleanup list. Otherwise connection
2329 * will stay in suspended list until 'urh' will be marked
2330 * with 'was_closed' by application. */
2332
2333 /* skip usual clean up */
2334 return (MHD_THRD_RTRN_TYPE_) 0;
2335 }
2336#endif /* UPGRADE_SUPPORT */
2337 }
2338#if _MHD_DEBUG_CLOSE
2339#ifdef HAVE_MESSAGES
2340 MHD_DLOG (con->daemon,
2341 _ ("Processing thread terminating. Closing connection.\n"));
2342#endif
2343#endif
2344 if (MHD_CONNECTION_CLOSED != con->state)
2346 (daemon->shutdown) ?
2350exit:
2351 if (NULL != con->rp.response)
2352 {
2354 con->rp.response = NULL;
2355 }
2356
2357 if (MHD_INVALID_SOCKET != con->socket_fd)
2358 {
2359 shutdown (con->socket_fd,
2360 SHUT_WR);
2361 /* 'socket_fd' can be used in other thread to signal shutdown.
2362 * To avoid data races, do not close socket here. Daemon will
2363 * use more connections only after cleanup anyway. */
2364 }
2365 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2366 (! MHD_itc_activate_ (daemon->itc, "t")) )
2367 {
2368#ifdef HAVE_MESSAGES
2369 MHD_DLOG (daemon,
2370 _ ("Failed to signal thread termination via inter-thread " \
2371 "communication channel.\n"));
2372#endif
2373 }
2374 return (MHD_THRD_RTRN_TYPE_) 0;
2375}
2376
2377
2378#endif
2379
2380
2388static void
2389MHD_cleanup_connections (struct MHD_Daemon *daemon);
2390
2391#if defined(HTTPS_SUPPORT)
2392#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2393 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2394 ! defined(MHD_socket_nosignal_) && \
2395 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2401#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2402#endif /* MHD_SEND_SPIPE_SUPPRESS_NEEDED &&
2403 MHD_SEND_SPIPE_SUPPRESS_POSSIBLE &&
2404 ! MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) &&
2405 MSG_NOSIGNAL */
2406
2407#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2412static ssize_t
2413MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2414 const void *data,
2415 size_t data_size)
2416{
2417#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2418 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2419 data_size = MHD_SCKT_SEND_MAX_SIZE_;
2420#endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2421 return MHD_send_ ((MHD_socket) (intptr_t) (trnsp), data, data_size);
2422}
2423
2424
2425#endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2426
2427
2436static int
2437psk_gnutls_adapter (gnutls_session_t session,
2438 const char *username,
2439 gnutls_datum_t *key)
2440{
2441 struct MHD_Connection *connection;
2442 struct MHD_Daemon *daemon;
2443#if GNUTLS_VERSION_MAJOR >= 3
2444 void *app_psk;
2445 size_t app_psk_size;
2446#endif /* GNUTLS_VERSION_MAJOR >= 3 */
2447
2448 connection = gnutls_session_get_ptr (session);
2449 if (NULL == connection)
2450 {
2451#ifdef HAVE_MESSAGES
2452 /* Cannot use our logger, we don't even have "daemon" */
2453 MHD_PANIC (_ ("Internal server error. This should be impossible.\n"));
2454#endif
2455 return -1;
2456 }
2457 daemon = connection->daemon;
2458#if GNUTLS_VERSION_MAJOR >= 3
2459 if (NULL == daemon->cred_callback)
2460 {
2461#ifdef HAVE_MESSAGES
2462 MHD_DLOG (daemon,
2463 _ ("PSK not supported by this server.\n"));
2464#endif
2465 return -1;
2466 }
2467 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2468 connection,
2469 username,
2470 &app_psk,
2471 &app_psk_size))
2472 return -1;
2473 if (NULL == (key->data = gnutls_malloc (app_psk_size)))
2474 {
2475#ifdef HAVE_MESSAGES
2476 MHD_DLOG (daemon,
2477 _ ("PSK authentication failed: gnutls_malloc failed to " \
2478 "allocate memory.\n"));
2479#endif
2480 free (app_psk);
2481 return -1;
2482 }
2483 if (UINT_MAX < app_psk_size)
2484 {
2485#ifdef HAVE_MESSAGES
2486 MHD_DLOG (daemon,
2487 _ ("PSK authentication failed: PSK too long.\n"));
2488#endif
2489 free (app_psk);
2490 return -1;
2491 }
2492 key->size = (unsigned int) app_psk_size;
2493 memcpy (key->data,
2494 app_psk,
2495 app_psk_size);
2496 free (app_psk);
2497 return 0;
2498#else
2499 (void) username; (void) key; /* Mute compiler warning */
2500#ifdef HAVE_MESSAGES
2501 MHD_DLOG (daemon,
2502 _ ("PSK not supported by this server.\n"));
2503#endif
2504 return -1;
2505#endif
2506}
2507
2508
2509#endif /* HTTPS_SUPPORT */
2510
2511
2534static struct MHD_Connection *
2536 MHD_socket client_socket,
2537 const struct sockaddr_storage *addr,
2538 socklen_t addrlen,
2539 bool external_add,
2540 bool non_blck,
2541 bool sk_spipe_supprs,
2542 enum MHD_tristate sk_is_nonip)
2543{
2544 struct MHD_Connection *connection;
2545 int eno = 0;
2546
2547#ifdef HAVE_MESSAGES
2548#if _MHD_DEBUG_CONNECT
2549 MHD_DLOG (daemon,
2550 _ ("Accepted connection on socket %d.\n"),
2551 client_socket);
2552#endif
2553#endif
2556 addr,
2557 addrlen)) )
2558 {
2559 /* above connection limit - reject */
2560#ifdef HAVE_MESSAGES
2561 MHD_DLOG (daemon,
2562 _ ("Server reached connection limit. " \
2563 "Closing inbound connection.\n"));
2564#endif
2565 MHD_socket_close_chk_ (client_socket);
2566#if defined(ENFILE) && (ENFILE + 0 != 0)
2567 errno = ENFILE;
2568#endif
2569 return NULL;
2570 }
2571
2572 /* apply connection acceptance policy if present */
2573 if ( (NULL != daemon->apc) &&
2575 (const struct sockaddr *) addr,
2576 addrlen)) )
2577 {
2578#if _MHD_DEBUG_CLOSE
2579#ifdef HAVE_MESSAGES
2580 MHD_DLOG (daemon,
2581 _ ("Connection rejected by application. Closing connection.\n"));
2582#endif
2583#endif
2584 MHD_socket_close_chk_ (client_socket);
2586 addr,
2587 addrlen);
2588#if defined(EACCESS) && (EACCESS + 0 != 0)
2589 errno = EACCESS;
2590#endif
2591 return NULL;
2592 }
2593
2594 if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2595 {
2596 eno = errno;
2597#ifdef HAVE_MESSAGES
2598 MHD_DLOG (daemon,
2599 _ ("Error allocating memory: %s\n"),
2600 MHD_strerror_ (errno));
2601#endif
2602 MHD_socket_close_chk_ (client_socket);
2604 addr,
2605 addrlen);
2606 errno = eno;
2607 return NULL;
2608 }
2609
2610 if (! external_add)
2611 {
2612 connection->sk_corked = _MHD_OFF;
2613 connection->sk_nodelay = _MHD_OFF;
2614 }
2615 else
2616 {
2617 connection->sk_corked = _MHD_UNKNOWN;
2618 connection->sk_nodelay = _MHD_UNKNOWN;
2619 }
2620
2621 if (0 < addrlen)
2622 {
2623 if (NULL == (connection->addr = malloc ((size_t) addrlen)))
2624 {
2625 eno = errno;
2626#ifdef HAVE_MESSAGES
2627 MHD_DLOG (daemon,
2628 _ ("Error allocating memory: %s\n"),
2629 MHD_strerror_ (errno));
2630#endif
2631 MHD_socket_close_chk_ (client_socket);
2633 addr,
2634 addrlen);
2635 free (connection);
2636 errno = eno;
2637 return NULL;
2638 }
2639 memcpy (connection->addr,
2640 addr,
2641 (size_t) addrlen);
2642 }
2643 else
2644 connection->addr = NULL;
2645 connection->addr_len = addrlen;
2646 connection->socket_fd = client_socket;
2647 connection->sk_nonblck = non_blck;
2648 connection->is_nonip = sk_is_nonip;
2649 connection->sk_spipe_suppress = sk_spipe_supprs;
2650#ifdef MHD_USE_THREADS
2651 MHD_thread_handle_ID_set_invalid_ (&connection->tid);
2652#endif /* MHD_USE_THREADS */
2653 connection->daemon = daemon;
2656 if (0 != connection->connection_timeout_ms)
2658
2659 if (0 == (daemon->options & MHD_USE_TLS))
2660 {
2661 /* set default connection handlers */
2662 MHD_set_http_callbacks_ (connection);
2663 }
2664 else
2665 {
2666#ifdef HTTPS_SUPPORT
2667#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2668 gnutls_init_flags_t
2669#else
2670 unsigned int
2671#endif
2672 flags;
2673
2674 flags = GNUTLS_SERVER;
2675#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2676 flags |= GNUTLS_NO_SIGNAL;
2677#endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2678#if GNUTLS_VERSION_MAJOR >= 3
2679 flags |= GNUTLS_NONBLOCK;
2680#endif /* GNUTLS_VERSION_MAJOR >= 3*/
2681#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2683 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2684#endif
2685#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2687 flags |= GNUTLS_ENABLE_EARLY_DATA;
2688#endif
2689 connection->tls_state = MHD_TLS_CONN_INIT;
2690 MHD_set_https_callbacks (connection);
2691 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2692 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2693 daemon->priority_cache)))
2694 {
2695 if (NULL != connection->tls_session)
2696 gnutls_deinit (connection->tls_session);
2697 MHD_socket_close_chk_ (client_socket);
2699 addr,
2700 addrlen);
2701 if (NULL != connection->addr)
2702 free (connection->addr);
2703 free (connection);
2704#ifdef HAVE_MESSAGES
2705 MHD_DLOG (daemon,
2706 _ ("Failed to initialise TLS session.\n"));
2707#endif
2708#if defined(EPROTO) && (EPROTO + 0 != 0)
2709 errno = EPROTO;
2710#endif
2711 return NULL;
2712 }
2713#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2714 if (! daemon->disable_alpn)
2715 {
2716 static const char prt1[] = "http/1.1"; /* Registered code for HTTP/1.1 */
2717 static const char prt2[] = "http/1.0"; /* Registered code for HTTP/1.0 */
2718 static const gnutls_datum_t prts[2] =
2719 { {_MHD_DROP_CONST (prt1), MHD_STATICSTR_LEN_ (prt1)},
2720 {_MHD_DROP_CONST (prt2), MHD_STATICSTR_LEN_ (prt2)} };
2721
2722 if (GNUTLS_E_SUCCESS !=
2723 gnutls_alpn_set_protocols (connection->tls_session,
2724 prts,
2725 sizeof(prts) / sizeof(prts[0]),
2726 0 /* | GNUTLS_ALPN_SERVER_PRECEDENCE */))
2727 {
2728#ifdef HAVE_MESSAGES
2729 MHD_DLOG (daemon,
2730 _ ("Failed to set ALPN protocols.\n"));
2731#else /* ! HAVE_MESSAGES */
2732 (void) 0; /* Mute compiler warning */
2733#endif /* ! HAVE_MESSAGES */
2734 }
2735 }
2736#endif /* GNUTLS_VERSION_NUMBER >= 0x030200 */
2737 gnutls_session_set_ptr (connection->tls_session,
2738 connection);
2739 switch (daemon->cred_type)
2740 {
2741 /* set needed credentials for certificate authentication. */
2742 case GNUTLS_CRD_CERTIFICATE:
2743 gnutls_credentials_set (connection->tls_session,
2744 GNUTLS_CRD_CERTIFICATE,
2745 daemon->x509_cred);
2746 break;
2747 case GNUTLS_CRD_PSK:
2748 gnutls_credentials_set (connection->tls_session,
2749 GNUTLS_CRD_PSK,
2750 daemon->psk_cred);
2751 gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2752 &psk_gnutls_adapter);
2753 break;
2754 case GNUTLS_CRD_ANON:
2755 case GNUTLS_CRD_SRP:
2756 case GNUTLS_CRD_IA:
2757 default:
2758#ifdef HAVE_MESSAGES
2759 MHD_DLOG (daemon,
2760 _ ("Failed to setup TLS credentials: " \
2761 "unknown credential type %d.\n"),
2762 daemon->cred_type);
2763#endif
2764 gnutls_deinit (connection->tls_session);
2765 MHD_socket_close_chk_ (client_socket);
2767 addr,
2768 addrlen);
2769 if (NULL != connection->addr)
2770 free (connection->addr);
2771 free (connection);
2772 MHD_PANIC (_ ("Unknown credential type.\n"));
2773#if defined(EINVAL) && (EINVAL + 0 != 0)
2774 errno = EINVAL;
2775#endif
2776 return NULL;
2777 }
2778#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2779 gnutls_transport_set_int (connection->tls_session,
2780 (int) (client_socket));
2781#else /* GnuTLS before 3.1.9 or Win x64 */
2782 gnutls_transport_set_ptr (connection->tls_session,
2783 (gnutls_transport_ptr_t) \
2784 (intptr_t) client_socket);
2785#endif /* GnuTLS before 3.1.9 or Win x64 */
2786#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2787 gnutls_transport_set_push_function (connection->tls_session,
2788 MHD_tls_push_func_);
2789#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2790 if (daemon->https_mem_trust)
2791 gnutls_certificate_server_set_request (connection->tls_session,
2792 GNUTLS_CERT_REQUEST);
2793#else /* ! HTTPS_SUPPORT */
2794 MHD_socket_close_chk_ (client_socket);
2796 addr,
2797 addrlen);
2798 free (connection->addr);
2799 free (connection);
2800 MHD_PANIC (_ ("TLS connection on non-TLS daemon.\n"));
2801#if 0
2802 /* Unreachable code */
2803 eno = EINVAL;
2804 return NULL;
2805#endif
2806#endif /* ! HTTPS_SUPPORT */
2807 }
2808
2809 return connection;
2810}
2811
2812
2813#ifdef MHD_USE_THREADS
2819static void
2820new_connection_close_ (struct MHD_Daemon *daemon,
2821 struct MHD_Connection *connection)
2822{
2823 mhd_assert (connection->daemon == daemon);
2824 mhd_assert (! connection->in_cleanup);
2825 mhd_assert (NULL == connection->next);
2826 mhd_assert (NULL == connection->nextX);
2827#ifdef EPOLL_SUPPORT
2828 mhd_assert (NULL == connection->nextE);
2829#endif /* EPOLL_SUPPORT */
2830
2831#ifdef HTTPS_SUPPORT
2832 if (NULL != connection->tls_session)
2833 {
2835 gnutls_deinit (connection->tls_session);
2836 }
2837#endif /* HTTPS_SUPPORT */
2838 MHD_socket_close_chk_ (connection->socket_fd);
2840 connection->addr,
2841 connection->addr_len);
2842 if (NULL != connection->addr)
2843 free (connection->addr);
2844 free (connection);
2845}
2846
2847
2848#endif /* MHD_USE_THREADS */
2849
2850
2861static enum MHD_Result
2863 struct MHD_Connection *connection)
2864{
2865 int eno = 0;
2866
2867 mhd_assert (connection->daemon == daemon);
2868
2869#ifdef MHD_USE_THREADS
2870 /* Function manipulate connection and timeout DL-lists,
2871 * must be called only within daemon thread. */
2874 mhd_assert (NULL == daemon->worker_pool);
2875#endif /* MHD_USE_THREADS */
2876
2877 /* Allocate memory pool in the processing thread so
2878 * intensively used memory area is allocated in "good"
2879 * (for the thread) memory region. It is important with
2880 * NUMA and/or complex cache hierarchy. */
2881 connection->pool = MHD_pool_create (daemon->pool_size);
2882 if (NULL == connection->pool)
2883 { /* 'pool' creation failed */
2884#ifdef HAVE_MESSAGES
2885 MHD_DLOG (daemon,
2886 _ ("Error allocating memory: %s\n"),
2887 MHD_strerror_ (errno));
2888#endif
2889#if defined(ENOMEM) && (ENOMEM + 0 != 0)
2890 eno = ENOMEM;
2891#endif
2892 (void) 0; /* Mute possible compiler warning */
2893 }
2894 else
2895 { /* 'pool' creation succeed */
2896 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2897 /* Firm check under lock. */
2899 { /* Connections limit */
2900 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2901#ifdef HAVE_MESSAGES
2902 MHD_DLOG (daemon,
2903 _ ("Server reached connection limit. "
2904 "Closing inbound connection.\n"));
2905#endif
2906#if defined(ENFILE) && (ENFILE + 0 != 0)
2907 eno = ENFILE;
2908#endif
2909 (void) 0; /* Mute possible compiler warning */
2910 }
2911 else
2912 { /* Have space for new connection */
2916 connection);
2918 {
2921 connection);
2922 }
2923 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2924
2926
2929 connection,
2930 &connection->socket_context,
2932#ifdef MHD_USE_THREADS
2934 {
2936 if (! MHD_create_named_thread_ (&connection->tid,
2937 "MHD-connection",
2938 daemon->thread_stack_size,
2939 &thread_main_handle_connection,
2940 connection))
2941 {
2942 eno = errno;
2943#ifdef HAVE_MESSAGES
2944#ifdef EAGAIN
2945 if (EAGAIN == eno)
2946 MHD_DLOG (daemon,
2947 _ ("Failed to create a new thread because it would "
2948 "have exceeded the system limit on the number of "
2949 "threads or no system resources available.\n"));
2950 else
2951#endif /* EAGAIN */
2952 MHD_DLOG (daemon,
2953 _ ("Failed to create a thread: %s\n"),
2954 MHD_strerror_ (eno));
2955#endif /* HAVE_MESSAGES */
2956 }
2957 else /* New thread has been created successfully */
2958 return MHD_YES; /* *** Function success exit point *** */
2959 }
2960 else
2961#else /* ! MHD_USE_THREADS */
2962 if (1)
2963#endif /* ! MHD_USE_THREADS */
2964 { /* No 'thread-per-connection' */
2965#ifdef MHD_USE_THREADS
2966 connection->tid = daemon->tid;
2967#endif /* MHD_USE_THREADS */
2968#ifdef EPOLL_SUPPORT
2970 {
2971 if (0 == (daemon->options & MHD_USE_TURBO))
2972 {
2973 struct epoll_event event;
2974
2975 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET | EPOLLRDHUP;
2976 event.data.ptr = connection;
2977 if (0 != epoll_ctl (daemon->epoll_fd,
2978 EPOLL_CTL_ADD,
2979 connection->socket_fd,
2980 &event))
2981 {
2982 eno = errno;
2983#ifdef HAVE_MESSAGES
2984 MHD_DLOG (daemon,
2985 _ ("Call to epoll_ctl failed: %s\n"),
2987#endif
2988 }
2989 else
2990 { /* 'socket_fd' has been added to 'epool' */
2991 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2992
2993 return MHD_YES; /* *** Function success exit point *** */
2994 }
2995 }
2996 else
2997 {
2998 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
3001 EDLL_insert (daemon->eready_head,
3002 daemon->eready_tail,
3003 connection);
3004
3005 return MHD_YES; /* *** Function success exit point *** */
3006 }
3007 }
3008 else /* No 'epoll' */
3009#endif /* EPOLL_SUPPORT */
3010 return MHD_YES; /* *** Function success exit point *** */
3011 }
3012
3013 /* ** Below is a cleanup path ** */
3014 if (NULL != daemon->notify_connection)
3016 connection,
3017 &connection->socket_context,
3019 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3020 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
3021 {
3023 daemon->normal_timeout_tail,
3024 connection);
3025 }
3027 daemon->connections_tail,
3028 connection);
3029 daemon->connections--;
3030 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3031 }
3032 MHD_pool_destroy (connection->pool);
3033 }
3034 /* Free resources allocated before the call of this functions */
3035#ifdef HTTPS_SUPPORT
3036 if (NULL != connection->tls_session)
3037 gnutls_deinit (connection->tls_session);
3038#endif /* HTTPS_SUPPORT */
3039 MHD_ip_limit_del (daemon,
3040 connection->addr,
3041 connection->addr_len);
3042 if (NULL != connection->addr)
3043 free (connection->addr);
3044 MHD_socket_close_chk_ (connection->socket_fd);
3045 free (connection);
3046 if (0 != eno)
3047 errno = eno;
3048#ifdef EINVAL
3049 else
3050 errno = EINVAL;
3051#endif /* EINVAL */
3052 return MHD_NO; /* *** Function failure exit point *** */
3053}
3054
3055
3084static enum MHD_Result
3086 MHD_socket client_socket,
3087 const struct sockaddr_storage *addr,
3088 socklen_t addrlen,
3089 bool external_add,
3090 bool non_blck,
3091 bool sk_spipe_supprs,
3092 enum MHD_tristate sk_is_nonip)
3093{
3094 struct MHD_Connection *connection;
3095
3096#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3097 /* Direct add to master daemon could never happen. */
3098 mhd_assert (NULL == daemon->worker_pool);
3099#endif
3100
3102 (! MHD_D_DOES_SCKT_FIT_FDSET_ (client_socket, daemon)) )
3103 {
3104#ifdef HAVE_MESSAGES
3105 MHD_DLOG (daemon,
3106 _ ("New connection socket descriptor (%d) is not less " \
3107 "than FD_SETSIZE (%d).\n"),
3108 (int) client_socket,
3110#endif
3111 MHD_socket_close_chk_ (client_socket);
3112#if defined(ENFILE) && (ENFILE + 0 != 0)
3113 errno = ENFILE;
3114#endif
3115 return MHD_NO;
3116 }
3117
3119 (! non_blck) )
3120 {
3121#ifdef HAVE_MESSAGES
3122 MHD_DLOG (daemon,
3123 _ ("Epoll mode supports only non-blocking sockets\n"));
3124#endif
3125 MHD_socket_close_chk_ (client_socket);
3126#if defined(EINVAL) && (EINVAL + 0 != 0)
3127 errno = EINVAL;
3128#endif
3129 return MHD_NO;
3130 }
3131
3132 connection = new_connection_prepare_ (daemon,
3133 client_socket,
3134 addr, addrlen,
3135 external_add,
3136 non_blck,
3137 sk_spipe_supprs,
3138 sk_is_nonip);
3139 if (NULL == connection)
3140 return MHD_NO;
3141
3142 if ((external_add) &&
3144 {
3145 /* Connection is added externally and MHD is thread safe mode. */
3146 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3149 connection);
3150 daemon->have_new = true;
3151 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3152
3153 /* The rest of connection processing must be handled in
3154 * the daemon thread. */
3155 if ((MHD_ITC_IS_VALID_ (daemon->itc)) &&
3156 (! MHD_itc_activate_ (daemon->itc, "n")))
3157 {
3158#ifdef HAVE_MESSAGES
3159 MHD_DLOG (daemon,
3160 _ ("Failed to signal new connection via inter-thread " \
3161 "communication channel.\n"));
3162#endif
3163 }
3164 return MHD_YES;
3165 }
3166
3167 return new_connection_process_ (daemon, connection);
3168}
3169
3170
3171static void
3173{
3174 struct MHD_Connection *local_head;
3175 struct MHD_Connection *local_tail;
3178
3179 /* Detach DL-list of new connections from the daemon for
3180 * following local processing. */
3181 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3183 local_head = daemon->new_connections_head;
3184 local_tail = daemon->new_connections_tail;
3187 daemon->have_new = false;
3188 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3189 (void) local_head; /* Mute compiler warning */
3190
3191 /* Process new connections in FIFO order. */
3192 do
3193 {
3194 struct MHD_Connection *c;
3195
3196 c = local_tail;
3197 DLL_remove (local_head,
3198 local_tail,
3199 c);
3200 mhd_assert (daemon == c->daemon);
3202 {
3203#ifdef HAVE_MESSAGES
3204 MHD_DLOG (daemon,
3205 _ ("Failed to start serving new connection.\n"));
3206#endif
3207 (void) 0;
3208 }
3209 } while (NULL != local_tail);
3210
3211}
3212
3213
3223void
3225{
3226 struct MHD_Daemon *daemon = connection->daemon;
3227 mhd_assert (NULL == daemon->worker_pool);
3228
3229#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3230 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
3233 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3234#endif
3235 if (connection->resuming)
3236 {
3237 /* suspending again while we didn't even complete resuming yet */
3238 connection->resuming = false;
3239#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3240 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3241#endif
3242 return;
3243 }
3244 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
3245 {
3246 if (connection->connection_timeout_ms == daemon->connection_timeout_ms)
3248 daemon->normal_timeout_tail,
3249 connection);
3250 else
3252 daemon->manual_timeout_tail,
3253 connection);
3254 }
3256 daemon->connections_tail,
3257 connection);
3258 mhd_assert (! connection->suspended);
3261 connection);
3262 connection->suspended = true;
3263#ifdef EPOLL_SUPPORT
3264 if (MHD_D_IS_USING_EPOLL_ (daemon))
3265 {
3266 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3267 {
3268 EDLL_remove (daemon->eready_head,
3269 daemon->eready_tail,
3270 connection);
3271 connection->epoll_state &=
3273 }
3274 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
3275 {
3276 if (0 != epoll_ctl (daemon->epoll_fd,
3277 EPOLL_CTL_DEL,
3278 connection->socket_fd,
3279 NULL))
3280 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3281 connection->epoll_state &=
3283 }
3284 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
3285 }
3286#endif
3287#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3288 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3289#endif
3290}
3291
3292
3321_MHD_EXTERN void
3323{
3324 struct MHD_Daemon *const daemon = connection->daemon;
3325
3326#ifdef MHD_USE_THREADS
3327 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
3330#endif /* MHD_USE_THREADS */
3331
3332 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3333 MHD_PANIC (_ ("Cannot suspend connections without " \
3334 "enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3335#ifdef UPGRADE_SUPPORT
3336 if (NULL != connection->urh)
3337 {
3338#ifdef HAVE_MESSAGES
3339 MHD_DLOG (daemon,
3340 _ ("Error: connection scheduled for \"upgrade\" cannot " \
3341 "be suspended.\n"));
3342#endif /* HAVE_MESSAGES */
3343 return;
3344 }
3345#endif /* UPGRADE_SUPPORT */
3346 internal_suspend_connection_ (connection);
3347}
3348
3349
3364_MHD_EXTERN void
3366{
3367 struct MHD_Daemon *daemon = connection->daemon;
3368#if defined(MHD_USE_THREADS)
3369 mhd_assert (NULL == daemon->worker_pool);
3370#endif /* MHD_USE_THREADS */
3371
3372 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3373 MHD_PANIC (_ ("Cannot resume connections without enabling " \
3374 "MHD_ALLOW_SUSPEND_RESUME!\n"));
3375#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3376 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3377#endif
3378 connection->resuming = true;
3379 daemon->resuming = true;
3380#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3381 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3382#endif
3383 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3384 (! MHD_itc_activate_ (daemon->itc, "r")) )
3385 {
3386#ifdef HAVE_MESSAGES
3387 MHD_DLOG (daemon,
3388 _ ("Failed to signal resume via inter-thread " \
3389 "communication channel.\n"));
3390#endif
3391 }
3392}
3393
3394
3395#ifdef UPGRADE_SUPPORT
3403void
3404MHD_upgraded_connection_mark_app_closed_ (struct MHD_Connection *connection)
3405{
3406 /* Cache 'daemon' here to avoid data races */
3407 struct MHD_Daemon *const daemon = connection->daemon;
3408#if defined(MHD_USE_THREADS)
3409 mhd_assert (NULL == daemon->worker_pool);
3410#endif /* MHD_USE_THREADS */
3411 mhd_assert (NULL != connection->urh);
3413
3414 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3415 connection->urh->was_closed = true;
3416 connection->resuming = true;
3417 daemon->resuming = true;
3418 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3419 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3420 (! MHD_itc_activate_ (daemon->itc, "r")) )
3421 {
3422#ifdef HAVE_MESSAGES
3423 MHD_DLOG (daemon,
3424 _ ("Failed to signal resume via " \
3425 "inter-thread communication channel.\n"));
3426#endif
3427 }
3428}
3429
3430
3431#endif /* UPGRADE_SUPPORT */
3432
3442static enum MHD_Result
3444{
3445 struct MHD_Connection *pos;
3446 struct MHD_Connection *prev = NULL;
3447 enum MHD_Result ret;
3448 const bool used_thr_p_c = (0 != (daemon->options
3450#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3451 mhd_assert (NULL == daemon->worker_pool);
3454#endif
3455
3456 ret = MHD_NO;
3457#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3458 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3459#endif
3460
3461 if (daemon->resuming)
3462 {
3464 /* During shutdown check for resuming is forced. */
3465 mhd_assert ((NULL != prev) || (daemon->shutdown) || \
3466 (0 != (daemon->options & MHD_ALLOW_UPGRADE)));
3467 }
3468
3469 daemon->resuming = false;
3470
3471 while (NULL != (pos = prev))
3472 {
3473#ifdef UPGRADE_SUPPORT
3474 struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3475#else /* ! UPGRADE_SUPPORT */
3476 static const void *const urh = NULL;
3477#endif /* ! UPGRADE_SUPPORT */
3478 prev = pos->prev;
3479 if ( (! pos->resuming)
3480#ifdef UPGRADE_SUPPORT
3481 || ( (NULL != urh) &&
3482 ( (! urh->was_closed) ||
3483 (! urh->clean_ready) ) )
3484#endif /* UPGRADE_SUPPORT */
3485 )
3486 continue;
3487 ret = MHD_YES;
3488 mhd_assert (pos->suspended);
3491 pos);
3492 pos->suspended = false;
3493 if (NULL == urh)
3494 {
3496 daemon->connections_tail,
3497 pos);
3498 if (! used_thr_p_c)
3499 {
3500 /* Reset timeout timer on resume. */
3501 if (0 != pos->connection_timeout_ms)
3503
3504 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
3506 daemon->normal_timeout_tail,
3507 pos);
3508 else
3510 daemon->manual_timeout_tail,
3511 pos);
3512 }
3513#ifdef EPOLL_SUPPORT
3514 if (MHD_D_IS_USING_EPOLL_ (daemon))
3515 {
3516 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3517 MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3518 /* we always mark resumed connections as ready, as we
3519 might have missed the edge poll event during suspension */
3520 EDLL_insert (daemon->eready_head,
3521 daemon->eready_tail,
3522 pos);
3523 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3526 pos->epoll_state &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_SUSPENDED);
3527 }
3528#endif
3529 }
3530#ifdef UPGRADE_SUPPORT
3531 else
3532 {
3533 /* Data forwarding was finished (for TLS connections) AND
3534 * application was closed upgraded connection.
3535 * Insert connection into cleanup list. */
3536 if ( (NULL != daemon->notify_completed) &&
3537 (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) &&
3538 (pos->rq.client_aware) )
3539 {
3540 daemon->notify_completed (daemon->notify_completed_cls,
3541 pos,
3542 &pos->rq.client_context,
3544 pos->rq.client_aware = false;
3545 }
3546 DLL_insert (daemon->cleanup_head,
3547 daemon->cleanup_tail,
3548 pos);
3549 daemon->data_already_pending = true;
3550 }
3551#endif /* UPGRADE_SUPPORT */
3552 pos->resuming = false;
3553 }
3554#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3555 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3556#endif
3557 if ( (used_thr_p_c) &&
3558 (MHD_NO != ret) )
3559 { /* Wake up suspended connections. */
3560 if (! MHD_itc_activate_ (daemon->itc,
3561 "w"))
3562 {
3563#ifdef HAVE_MESSAGES
3564 MHD_DLOG (daemon,
3565 _ ("Failed to signal resume of connection via " \
3566 "inter-thread communication channel.\n"));
3567#endif
3568 }
3569 }
3570 return ret;
3571}
3572
3573
3603 MHD_socket client_socket,
3604 const struct sockaddr *addr,
3605 socklen_t addrlen)
3606{
3607 bool sk_nonbl;
3608 bool sk_spipe_supprs;
3609 struct sockaddr_storage addrstorage;
3610
3611 /* TODO: fix atomic value reading */
3612 if ((! MHD_D_IS_THREAD_SAFE_ (daemon)) &&
3613 (daemon->connection_limit <= daemon->connections))
3614 MHD_cleanup_connections (daemon);
3615
3616#ifdef HAVE_MESSAGES
3617 if (MHD_D_IS_USING_THREADS_ (daemon) &&
3618 (0 == (daemon->options & MHD_USE_ITC)))
3619 {
3620 MHD_DLOG (daemon,
3621 _ ("MHD_add_connection() has been called for daemon started"
3622 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3623 " added connection until any activity occurs in already"
3624 " added sockets.\n"));
3625 }
3626#endif /* HAVE_MESSAGES */
3627 if (0 != addrlen)
3628 {
3629 if (AF_INET == addr->sa_family)
3630 {
3631 if (sizeof(struct sockaddr_in) > (size_t) addrlen)
3632 {
3633#ifdef HAVE_MESSAGES
3634 MHD_DLOG (daemon,
3635 _ ("MHD_add_connection() has been called with "
3636 "incorrect 'addrlen' value.\n"));
3637#endif /* HAVE_MESSAGES */
3638 return MHD_NO;
3639 }
3640#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3641 if ((0 != addr->sa_len) &&
3642 (sizeof(struct sockaddr_in) > (size_t) addr->sa_len) )
3643 {
3644#ifdef HAVE_MESSAGES
3645 MHD_DLOG (daemon,
3646 _ ("MHD_add_connection() has been called with " \
3647 "non-zero value of 'sa_len' member of " \
3648 "'struct sockaddr' which does not match 'sa_family'.\n"));
3649#endif /* HAVE_MESSAGES */
3650 return MHD_NO;
3651 }
3652#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
3653 }
3654#ifdef HAVE_INET6
3655 if (AF_INET6 == addr->sa_family)
3656 {
3657 if (sizeof(struct sockaddr_in6) > (size_t) addrlen)
3658 {
3659#ifdef HAVE_MESSAGES
3660 MHD_DLOG (daemon,
3661 _ ("MHD_add_connection() has been called with "
3662 "incorrect 'addrlen' value.\n"));
3663#endif /* HAVE_MESSAGES */
3664 return MHD_NO;
3665 }
3666#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3667 if ((0 != addr->sa_len) &&
3668 (sizeof(struct sockaddr_in6) > (size_t) addr->sa_len) )
3669 {
3670#ifdef HAVE_MESSAGES
3671 MHD_DLOG (daemon,
3672 _ ("MHD_add_connection() has been called with " \
3673 "non-zero value of 'sa_len' member of " \
3674 "'struct sockaddr' which does not match 'sa_family'.\n"));
3675#endif /* HAVE_MESSAGES */
3676 return MHD_NO;
3677 }
3678#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
3679 }
3680#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3681 if ((0 != addr->sa_len) &&
3682 (addrlen > addr->sa_len))
3683 addrlen = (socklen_t) addr->sa_len; /* Use safest value */
3684#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
3685#endif /* HAVE_INET6 */
3686 }
3687
3688 if (! MHD_socket_nonblocking_ (client_socket))
3689 {
3690#ifdef HAVE_MESSAGES
3691 MHD_DLOG (daemon,
3692 _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3694#endif
3695 sk_nonbl = false;
3696 }
3697 else
3698 sk_nonbl = true;
3699
3700#ifndef MHD_WINSOCK_SOCKETS
3701 sk_spipe_supprs = false;
3702#else /* MHD_WINSOCK_SOCKETS */
3703 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3704#endif /* MHD_WINSOCK_SOCKETS */
3705#if defined(MHD_socket_nosignal_)
3706 if (! sk_spipe_supprs)
3707 sk_spipe_supprs = MHD_socket_nosignal_ (client_socket);
3708 if (! sk_spipe_supprs)
3709 {
3710#ifdef HAVE_MESSAGES
3711 MHD_DLOG (daemon,
3712 _ ("Failed to suppress SIGPIPE on new client socket: %s\n"),
3714#else /* ! HAVE_MESSAGES */
3715 (void) 0; /* Mute compiler warning */
3716#endif /* ! HAVE_MESSAGES */
3717#ifndef MSG_NOSIGNAL
3718 /* Application expects that SIGPIPE will be suppressed,
3719 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3720 if (! daemon->sigpipe_blocked)
3721 {
3722 int err = MHD_socket_get_error_ ();
3723 MHD_socket_close_ (client_socket);
3725 return MHD_NO;
3726 }
3727#endif /* MSG_NOSIGNAL */
3728 }
3729#endif /* MHD_socket_nosignal_ */
3730
3731 if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3732 (! MHD_socket_noninheritable_ (client_socket)) )
3733 {
3734#ifdef HAVE_MESSAGES
3735 MHD_DLOG (daemon,
3736 _ ("Failed to set noninheritable mode on new client socket.\n"));
3737#endif
3738 }
3739
3740 /* Copy to sockaddr_storage structure to avoid alignment problems */
3741 if (0 < addrlen)
3742 memcpy (&addrstorage, addr, (size_t) addrlen);
3743#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
3744 addrstorage.ss_len = addrlen; /* Force set the right length */
3745#endif /* HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */
3746
3747#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3748 if (NULL != daemon->worker_pool)
3749 {
3750 unsigned int i;
3751 /* have a pool, try to find a pool with capacity; we use the
3752 socket as the initial offset into the pool for load
3753 balancing */
3754 for (i = 0; i < daemon->worker_pool_size; ++i)
3755 {
3756 struct MHD_Daemon *const worker =
3757 &daemon->worker_pool[(i + (unsigned int) client_socket)
3758 % daemon->worker_pool_size];
3759 if (worker->connections < worker->connection_limit)
3760 return internal_add_connection (worker,
3761 client_socket,
3762 &addrstorage,
3763 addrlen,
3764 true,
3765 sk_nonbl,
3766 sk_spipe_supprs,
3767 _MHD_UNKNOWN);
3768 }
3769 /* all pools are at their connection limit, must refuse */
3770 MHD_socket_close_chk_ (client_socket);
3771#if defined(ENFILE) && (ENFILE + 0 != 0)
3772 errno = ENFILE;
3773#endif
3774 return MHD_NO;
3775 }
3776#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
3777
3778 return internal_add_connection (daemon,
3779 client_socket,
3780 &addrstorage,
3781 addrlen,
3782 true,
3783 sk_nonbl,
3784 sk_spipe_supprs,
3785 _MHD_UNKNOWN);
3786}
3787
3788
3803static enum MHD_Result
3805{
3806 struct sockaddr_storage addrstorage;
3807 socklen_t addrlen;
3808 MHD_socket s;
3809 MHD_socket fd;
3810 bool sk_nonbl;
3811 bool sk_spipe_supprs;
3812 bool sk_cloexec;
3813 enum MHD_tristate sk_non_ip;
3814#if defined(_DEBUG) && defined (USE_ACCEPT4)
3815 const bool use_accept4 = ! daemon->avoid_accept4;
3816#elif defined (USE_ACCEPT4)
3817 static const bool use_accept4 = true;
3818#else /* ! USE_ACCEPT4 && ! _DEBUG */
3819 static const bool use_accept4 = false;
3820#endif /* ! USE_ACCEPT4 && ! _DEBUG */
3821
3822#ifdef MHD_USE_THREADS
3823 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
3825 mhd_assert (NULL == daemon->worker_pool);
3826#endif /* MHD_USE_THREADS */
3827
3828 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3829 (daemon->was_quiesced) )
3830 return MHD_NO;
3831
3832 addrlen = (socklen_t) sizeof (addrstorage);
3833 memset (&addrstorage,
3834 0,
3835 (size_t) addrlen);
3836#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
3837 addrstorage.ss_len = addrlen;
3838#endif /* HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */
3839
3840 /* Initialise with default values to avoid compiler warnings */
3841 sk_nonbl = false;
3842 sk_spipe_supprs = false;
3843 sk_cloexec = false;
3845
3846#ifdef USE_ACCEPT4
3847 if (use_accept4 &&
3849 (s = accept4 (fd,
3850 (struct sockaddr *) &addrstorage,
3851 &addrlen,
3854 {
3855 sk_nonbl = (SOCK_NONBLOCK_OR_ZERO != 0);
3856#ifndef MHD_WINSOCK_SOCKETS
3857 sk_spipe_supprs = (SOCK_NOSIGPIPE_OR_ZERO != 0);
3858#else /* MHD_WINSOCK_SOCKETS */
3859 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3860#endif /* MHD_WINSOCK_SOCKETS */
3861 sk_cloexec = (SOCK_CLOEXEC_OR_ZERO != 0);
3862 }
3863#endif /* USE_ACCEPT4 */
3864#if defined(_DEBUG) || ! defined(USE_ACCEPT4)
3865 if (! use_accept4 &&
3867 (s = accept (fd,
3868 (struct sockaddr *) &addrstorage,
3869 &addrlen))))
3870 {
3871#ifdef MHD_ACCEPT_INHERIT_NONBLOCK
3872 sk_nonbl = daemon->listen_nonblk;
3873#else /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
3874 sk_nonbl = false;
3875#endif /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
3876#ifndef MHD_WINSOCK_SOCKETS
3877 sk_spipe_supprs = false;
3878#else /* MHD_WINSOCK_SOCKETS */
3879 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3880#endif /* MHD_WINSOCK_SOCKETS */
3881 sk_cloexec = false;
3882 }
3883#endif /* _DEBUG || !USE_ACCEPT4 */
3884
3885 if (MHD_INVALID_SOCKET == s)
3886 {
3887 const int err = MHD_socket_get_error_ ();
3888
3889 /* This could be a common occurrence with multiple worker threads */
3890 if (MHD_SCKT_ERR_IS_ (err,
3892 return MHD_NO; /* can happen during shutdown */
3894 return MHD_NO; /* do not print error if client just disconnected early */
3895#ifdef HAVE_MESSAGES
3896 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3897 MHD_DLOG (daemon,
3898 _ ("Error accepting connection: %s\n"),
3899 MHD_socket_strerr_ (err));
3900#endif
3902 {
3903 /* system/process out of resources */
3904 if (0 == daemon->connections)
3905 {
3906#ifdef HAVE_MESSAGES
3907 /* Not setting 'at_limit' flag, as there is no way it
3908 would ever be cleared. Instead trying to produce
3909 bit fat ugly warning. */
3910 MHD_DLOG (daemon,
3911 _ ("Hit process or system resource limit at FIRST " \
3912 "connection. This is really bad as there is no sane " \
3913 "way to proceed. Will try busy waiting for system " \
3914 "resources to become magically available.\n"));
3915#endif
3916 }
3917 else
3918 {
3919#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3920 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3921#endif
3922 daemon->at_limit = true;
3923#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3924 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3925#endif
3926#ifdef HAVE_MESSAGES
3927 MHD_DLOG (daemon,
3928 _ ("Hit process or system resource limit at %u " \
3929 "connections, temporarily suspending accept(). " \
3930 "Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3931 (unsigned int) daemon->connections);
3932#endif
3933 }
3934 }
3935 return MHD_NO;
3936 }
3937
3938 sk_non_ip = daemon->listen_is_unix;
3939 if (0 >= addrlen)
3940 {
3941#ifdef HAVE_MESSAGES
3942 if (_MHD_NO != daemon->listen_is_unix)
3943 MHD_DLOG (daemon,
3944 _ ("Accepted socket has zero-length address. "
3945 "Processing the new socket as a socket with " \
3946 "unknown type.\n"));
3947#endif
3948 addrlen = 0;
3949 sk_non_ip = _MHD_YES; /* IP-type addresses have non-zero length */
3950 }
3951 if (((socklen_t) sizeof (addrstorage)) < addrlen)
3952 {
3953 /* Should not happen as 'sockaddr_storage' must be large enough to
3954 * store any address supported by the system. */
3955#ifdef HAVE_MESSAGES
3956 MHD_DLOG (daemon,
3957 _ ("Accepted socket address is larger than expected by " \
3958 "system headers. Processing the new socket as a socket with " \
3959 "unknown type.\n"));
3960#endif
3961 addrlen = 0;
3962 sk_non_ip = _MHD_YES; /* IP-type addresses must fit */
3963 }
3964
3965 if (! sk_nonbl && ! MHD_socket_nonblocking_ (s))
3966 {
3967#ifdef HAVE_MESSAGES
3968 MHD_DLOG (daemon,
3969 _ ("Failed to set nonblocking mode on incoming connection " \
3970 "socket: %s\n"),
3972#else /* ! HAVE_MESSAGES */
3973 (void) 0; /* Mute compiler warning */
3974#endif /* ! HAVE_MESSAGES */
3975 }
3976 else
3977 sk_nonbl = true;
3978
3979 if (! sk_cloexec && ! MHD_socket_noninheritable_ (s))
3980 {
3981#ifdef HAVE_MESSAGES
3982 MHD_DLOG (daemon,
3983 _ ("Failed to set noninheritable mode on incoming connection " \
3984 "socket.\n"));
3985#else /* ! HAVE_MESSAGES */
3986 (void) 0; /* Mute compiler warning */
3987#endif /* ! HAVE_MESSAGES */
3988 }
3989
3990#if defined(MHD_socket_nosignal_)
3991 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
3992 {
3993#ifdef HAVE_MESSAGES
3994 MHD_DLOG (daemon,
3995 _ ("Failed to suppress SIGPIPE on incoming connection " \
3996 "socket: %s\n"),
3998#else /* ! HAVE_MESSAGES */
3999 (void) 0; /* Mute compiler warning */
4000#endif /* ! HAVE_MESSAGES */
4001#ifndef MSG_NOSIGNAL
4002 /* Application expects that SIGPIPE will be suppressed,
4003 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
4004 if (! daemon->sigpipe_blocked)
4005 {
4006 (void) MHD_socket_close_ (s);
4007 return MHD_NO;
4008 }
4009#endif /* MSG_NOSIGNAL */
4010 }
4011 else
4012 sk_spipe_supprs = true;
4013#endif /* MHD_socket_nosignal_ */
4014#ifdef HAVE_MESSAGES
4015#if _MHD_DEBUG_CONNECT
4016 MHD_DLOG (daemon,
4017 _ ("Accepted connection on socket %d\n"),
4018 s);
4019#endif
4020#endif
4021 (void) internal_add_connection (daemon,
4022 s,
4023 &addrstorage,
4024 addrlen,
4025 false,
4026 sk_nonbl,
4027 sk_spipe_supprs,
4028 sk_non_ip);
4029 return MHD_YES;
4030}
4031
4032
4042static void
4044{
4045 struct MHD_Connection *pos;
4046#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4049 mhd_assert (NULL == daemon->worker_pool);
4050
4051 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
4052#endif
4053 while (NULL != (pos = daemon->cleanup_tail))
4054 {
4057 pos);
4058#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4059 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
4061 (! pos->thread_joined) &&
4062 (! MHD_thread_handle_ID_join_thread_ (pos->tid)) )
4063 MHD_PANIC (_ ("Failed to join a thread.\n"));
4064#endif
4065#ifdef UPGRADE_SUPPORT
4066 cleanup_upgraded_connection (pos);
4067#endif /* UPGRADE_SUPPORT */
4068 MHD_pool_destroy (pos->pool);
4069#ifdef HTTPS_SUPPORT
4070 if (NULL != pos->tls_session)
4071 gnutls_deinit (pos->tls_session);
4072#endif /* HTTPS_SUPPORT */
4073
4074 /* clean up the connection */
4077 pos,
4078 &pos->socket_context,
4081 pos->addr,
4082 pos->addr_len);
4083#ifdef EPOLL_SUPPORT
4085 {
4086 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4087 {
4088 EDLL_remove (daemon->eready_head,
4089 daemon->eready_tail,
4090 pos);
4091 pos->epoll_state &=
4093 }
4094 if ( (-1 != daemon->epoll_fd) &&
4095 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
4096 {
4097 /* epoll documentation suggests that closing a FD
4098 automatically removes it from the epoll set; however,
4099 this is not true as if we fail to do manually remove it,
4100 we are still seeing an event for this fd in epoll,
4101 causing grief (use-after-free...) --- at least on my
4102 system. */
4103 if (0 != epoll_ctl (daemon->epoll_fd,
4104 EPOLL_CTL_DEL,
4105 pos->socket_fd,
4106 NULL))
4107 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
4108 pos->epoll_state &=
4109 ~((enum MHD_EpollState)
4111 }
4112 }
4113#endif
4114 if (NULL != pos->rp.response)
4115 {
4117 pos->rp.response = NULL;
4118 }
4119 if (MHD_INVALID_SOCKET != pos->socket_fd)
4121 if (NULL != pos->addr)
4122 free (pos->addr);
4123 free (pos);
4124
4125#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4126 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
4127#endif
4129 daemon->at_limit = false;
4130 }
4131#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4132 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
4133#endif
4134}
4135
4136
4173 MHD_UNSIGNED_LONG_LONG *timeout)
4174{
4175 uint64_t t64;
4176 if (MHD_NO == MHD_get_timeout64 (daemon, &t64))
4177 return MHD_NO;
4178
4179#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
4180 if (ULLONG_MAX <= t64)
4181 *timeout = ULLONG_MAX;
4182 else
4183#endif /* SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG */
4184 *timeout = (MHD_UNSIGNED_LONG_LONG) t64;
4185 return MHD_YES;
4186}
4187
4188
4227 uint64_t *timeout64)
4228{
4229 uint64_t earliest_deadline;
4230 struct MHD_Connection *pos;
4231 struct MHD_Connection *earliest_tmot_conn;
4232
4233#ifdef MHD_USE_THREADS
4236#endif /* MHD_USE_THREADS */
4237
4239 {
4240#ifdef HAVE_MESSAGES
4241 MHD_DLOG (daemon,
4242 _ ("Illegal call to MHD_get_timeout.\n"));
4243#endif
4244 return MHD_NO;
4245 }
4247 || (NULL != daemon->cleanup_head)
4248 || daemon->resuming
4249 || daemon->have_new
4250 || daemon->shutdown)
4251 {
4252 /* Some data or connection statuses already waiting to be processed. */
4253 *timeout64 = 0;
4254 return MHD_YES;
4255 }
4256#ifdef EPOLL_SUPPORT
4258 ((NULL != daemon->eready_head)
4259#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
4260 || (NULL != daemon->eready_urh_head)
4261#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
4262 ) )
4263 {
4264 /* Some connection(s) already have some data pending. */
4265 *timeout64 = 0;
4266 return MHD_YES;
4267 }
4268#endif /* EPOLL_SUPPORT */
4269
4270 earliest_tmot_conn = NULL;
4271 earliest_deadline = 0; /* mute compiler warning */
4272 /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
4274 if ( (NULL != pos) &&
4275 (0 != pos->connection_timeout_ms) )
4276 {
4277 earliest_tmot_conn = pos;
4278 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
4279 }
4280
4281 for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
4282 {
4283 if (0 != pos->connection_timeout_ms)
4284 {
4285 if ( (NULL == earliest_tmot_conn) ||
4286 (earliest_deadline - pos->last_activity >
4287 pos->connection_timeout_ms) )
4288 {
4289 earliest_tmot_conn = pos;
4290 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
4291 }
4292 }
4293 }
4294
4295 if (NULL != earliest_tmot_conn)
4296 {
4297 *timeout64 = connection_get_wait (earliest_tmot_conn);
4298 return MHD_YES;
4299 }
4300 return MHD_NO;
4301}
4302
4303
4304#if defined(HAVE_POLL) || defined(EPOLL_SUPPORT)
4343_MHD_EXTERN int64_t
4345{
4346 uint64_t utimeout;
4347 if (MHD_NO == MHD_get_timeout64 (daemon, &utimeout))
4348 return -1;
4349 if (INT64_MAX < utimeout)
4350 return INT64_MAX;
4351
4352 return (int64_t) utimeout;
4353}
4354
4355
4395_MHD_EXTERN int
4397{
4398#if SIZEOF_INT >= SIZEOF_INT64_T
4399 return MHD_get_timeout64s (daemon);
4400#else /* SIZEOF_INT < SIZEOF_INT64_T */
4401 const int64_t to64 = MHD_get_timeout64s (daemon);
4402 if (INT_MAX >= to64)
4403 return (int) to64;
4404 return INT_MAX;
4405#endif /* SIZEOF_INT < SIZEOF_INT64_T */
4406}
4407
4408
4419static int64_t
4420get_timeout_millisec_ (struct MHD_Daemon *daemon,
4421 int32_t max_timeout)
4422{
4423 uint64_t d_timeout;
4424 mhd_assert (0 <= max_timeout || -1 == max_timeout);
4425 if (0 == max_timeout)
4426 return 0;
4427
4428 if (MHD_NO == MHD_get_timeout64 (daemon, &d_timeout))
4429 return max_timeout;
4430
4431 if ((0 < max_timeout) && ((uint64_t) max_timeout < d_timeout))
4432 return max_timeout;
4433
4434 if (INT64_MAX <= d_timeout)
4435 return INT64_MAX;
4436
4437 return (int64_t) d_timeout;
4438}
4439
4440
4452static int
4453get_timeout_millisec_int (struct MHD_Daemon *daemon,
4454 int32_t max_timeout)
4455{
4456 int64_t res;
4457
4458 res = get_timeout_millisec_ (daemon, max_timeout);
4459#if SIZEOF_INT < SIZEOF_INT64_T
4460 if (INT_MAX <= res)
4461 return INT_MAX;
4462#endif /* SIZEOF_INT < SIZEOF_INT64_T */
4463 return (int) res;
4464}
4465
4466
4467#endif /* HAVE_POLL || EPOLL_SUPPORT */
4468
4480static enum MHD_Result
4482 const fd_set *read_fd_set,
4483 const fd_set *write_fd_set,
4484 const fd_set *except_fd_set,
4485 int fd_setsize)
4486{
4487 MHD_socket ds;
4488#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4489 struct MHD_UpgradeResponseHandle *urh;
4490 struct MHD_UpgradeResponseHandle *urhn;
4491#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4492
4493 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4494 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4495 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4496 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4497 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4499
4500 mhd_assert (0 < fd_setsize);
4501 (void) fd_setsize; /* Mute compiler warning */
4502#ifndef HAS_FD_SETSIZE_OVERRIDABLE
4503 (void) fd_setsize; /* Mute compiler warning */
4504 mhd_assert (((int) FD_SETSIZE) <= fd_setsize);
4505 fd_setsize = FD_SETSIZE; /* Help compiler to optimise */
4506#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4507
4508 /* Clear ITC to avoid spinning select */
4509 /* Do it before any other processing so new signals
4510 will trigger select again and will be processed */
4511 if (MHD_ITC_IS_VALID_ (daemon->itc))
4512 { /* Have ITC */
4513 bool need_to_clear_itc = true; /* ITC is always non-blocking, it is safe to clear even if ITC not activated */
4514 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (MHD_itc_r_fd_ (daemon->itc),
4515 NULL, fd_setsize))
4516 need_to_clear_itc = FD_ISSET (MHD_itc_r_fd_ (daemon->itc), \
4517 (fd_set *) _MHD_DROP_CONST (read_fd_set)); /* Skip clearing, if not needed */
4518 if (need_to_clear_itc)
4519 MHD_itc_clear_ (daemon->itc);
4520 }
4521
4522 /* Reset. New value will be set when connections are processed. */
4523 /* Note: no-op for thread-per-connection as it is always false in that mode. */
4524 daemon->data_already_pending = false;
4525
4526 /* Process externally added connection if any */
4527 if (daemon->have_new)
4529
4530 /* select connection thread handling type */
4531 ds = daemon->listen_fd;
4532 if ( (MHD_INVALID_SOCKET != ds) &&
4533 (! daemon->was_quiesced) )
4534 {
4535 bool need_to_accept;
4536 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (ds, NULL, fd_setsize))
4537 need_to_accept = FD_ISSET (ds,
4538 (fd_set *) _MHD_DROP_CONST (read_fd_set));
4539 else /* Cannot check whether new connection are pending */
4540 need_to_accept = daemon->listen_nonblk; /* Try to accept if non-blocking */
4541
4542 if (need_to_accept)
4543 (void) MHD_accept_connection (daemon);
4544 }
4545
4546 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
4547 {
4548 /* do not have a thread per connection, process all connections now */
4549 struct MHD_Connection *pos;
4550 struct MHD_Connection *prev;
4551
4552 for (pos = daemon->connections_tail; NULL != pos; pos = prev)
4553 {
4554 MHD_socket cs;
4555 bool r_ready;
4556 bool w_ready;
4557 bool has_err;
4558
4559 prev = pos->prev;
4560 cs = pos->socket_fd;
4561 if (MHD_INVALID_SOCKET == cs)
4562 continue;
4563
4564 if (MHD_SCKT_FD_FITS_FDSET_SETSIZE_ (cs, NULL, fd_setsize))
4565 {
4566 r_ready = FD_ISSET (cs,
4567 (fd_set *) _MHD_DROP_CONST (read_fd_set));
4568 w_ready = FD_ISSET (cs,
4569 (fd_set *) _MHD_DROP_CONST (write_fd_set));
4570 has_err = (NULL != except_fd_set) &&
4571 FD_ISSET (cs,
4572 (fd_set *) _MHD_DROP_CONST (except_fd_set));
4573 }
4574 else
4575 { /* Cannot check the real readiness */
4576 r_ready = pos->sk_nonblck;
4577 w_ready = r_ready;
4578 has_err = false;
4579 }
4580 call_handlers (pos,
4581 r_ready,
4582 w_ready,
4583 has_err);
4584 }
4585 }
4586
4587#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4588 /* handle upgraded HTTPS connections */
4589 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4590 {
4591 urhn = urh->prev;
4592 /* update urh state based on select() output */
4593 urh_from_fdset (urh,
4594 read_fd_set,
4595 write_fd_set,
4596 except_fd_set,
4597 fd_setsize);
4598 /* call generic forwarding function for passing data */
4599 process_urh (urh);
4600 /* Finished forwarding? */
4601 if ( (0 == urh->in_buffer_size) &&
4602 (0 == urh->out_buffer_size) &&
4603 (0 == urh->in_buffer_used) &&
4604 (0 == urh->out_buffer_used) )
4605 {
4606 MHD_connection_finish_forward_ (urh->connection);
4607 urh->clean_ready = true;
4608 /* Resuming will move connection to cleanup list. */
4609 MHD_resume_connection (urh->connection);
4610 }
4611 }
4612#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4614 return MHD_YES;
4615}
4616
4617
4618#undef MHD_run_from_select
4619
4653 const fd_set *read_fd_set,
4654 const fd_set *write_fd_set,
4655 const fd_set *except_fd_set,
4656 unsigned int fd_setsize)
4657{
4660 return MHD_NO;
4661 if ((NULL == read_fd_set) || (NULL == write_fd_set))
4662 return MHD_NO;
4663#ifdef HAVE_MESSAGES
4664 if (NULL == except_fd_set)
4665 {
4666 MHD_DLOG (daemon,
4667 _ ("MHD_run_from_select() called with except_fd_set "
4668 "set to NULL. Such behavior is deprecated.\n"));
4669 }
4670#endif /* HAVE_MESSAGES */
4671
4672#ifdef HAS_FD_SETSIZE_OVERRIDABLE
4673 if (0 == fd_setsize)
4674 return MHD_NO;
4675 else if (((unsigned int) INT_MAX) < fd_setsize)
4676 fd_setsize = (unsigned int) INT_MAX;
4677#ifdef HAVE_MESSAGES
4678 else if (daemon->fdset_size > ((int) fd_setsize))
4679 {
4680 if (daemon->fdset_size_set_by_app)
4681 {
4682 MHD_DLOG (daemon,
4683 _ ("%s() called with fd_setsize (%u) " \
4684 "less than value set by MHD_OPTION_APP_FD_SETSIZE (%d). " \
4685 "Some socket FDs may be not processed. " \
4686 "Use MHD_OPTION_APP_FD_SETSIZE with the correct value.\n"),
4687 "MHD_run_from_select2", fd_setsize, daemon->fdset_size);
4688 }
4689 else
4690 {
4691 MHD_DLOG (daemon,
4692 _ ("%s() called with fd_setsize (%u) " \
4693 "less than FD_SETSIZE used by MHD (%d). " \
4694 "Some socket FDs may be not processed. " \
4695 "Consider using MHD_OPTION_APP_FD_SETSIZE option.\n"),
4696 "MHD_run_from_select2", fd_setsize, daemon->fdset_size);
4697 }
4698 }
4699#endif /* HAVE_MESSAGES */
4700#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4701 if (((unsigned int) FD_SETSIZE) > fd_setsize)
4702 {
4703#ifdef HAVE_MESSAGES
4704 MHD_DLOG (daemon,
4705 _ ("%s() called with fd_setsize (%u) " \
4706 "less than fixed FD_SETSIZE value (%d) used on the " \
4707 "platform.\n"),
4708 "MHD_run_from_select2", fd_setsize, (int) FD_SETSIZE);
4709#endif /* HAVE_MESSAGES */
4710 return MHD_NO;
4711 }
4712#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4713
4715 {
4716#ifdef EPOLL_SUPPORT
4717 enum MHD_Result ret = MHD_epoll (daemon,
4718 0);
4719
4721 return ret;
4722#else /* ! EPOLL_SUPPORT */
4723 return MHD_NO;
4724#endif /* ! EPOLL_SUPPORT */
4725 }
4726
4727 /* Resuming external connections when using an extern mainloop */
4730
4732 read_fd_set,
4733 write_fd_set,
4734 except_fd_set,
4735 (int) fd_setsize);
4736}
4737
4738
4767 const fd_set *read_fd_set,
4768 const fd_set *write_fd_set,
4769 const fd_set *except_fd_set)
4770{
4772 read_fd_set,
4773 write_fd_set,
4774 except_fd_set,
4775#ifdef HAS_FD_SETSIZE_OVERRIDABLE
4776 daemon->fdset_size_set_by_app ?
4777 ((unsigned int) daemon->fdset_size) :
4778 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
4779#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4780 ((unsigned int) _MHD_SYS_DEFAULT_FD_SETSIZE)
4781#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
4782 );
4783}
4784
4785
4796static enum MHD_Result
4798 int32_t millisec)
4799{
4800 int num_ready;
4801 fd_set rs;
4802 fd_set ws;
4803 fd_set es;
4804 MHD_socket maxsock;
4805 struct timeval timeout;
4806 struct timeval *tv;
4807 int err_state;
4808 MHD_socket ls;
4809
4810 timeout.tv_sec = 0;
4811 timeout.tv_usec = 0;
4812 if (daemon->shutdown)
4813 return MHD_NO;
4814 FD_ZERO (&rs);
4815 FD_ZERO (&ws);
4816 FD_ZERO (&es);
4817 maxsock = MHD_INVALID_SOCKET;
4818 err_state = MHD_NO;
4819 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4820 (MHD_NO != resume_suspended_connections (daemon)) &&
4821 (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) )
4822 millisec = 0;
4823
4824 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
4825 {
4826 /* single-threaded, go over everything */
4827 if (MHD_NO ==
4828 internal_get_fdset2 (daemon,
4829 &rs,
4830 &ws,
4831 &es,
4832 &maxsock,
4833 (int) FD_SETSIZE))
4834 {
4835#ifdef HAVE_MESSAGES
4836 MHD_DLOG (daemon,
4837 _ ("Could not obtain daemon fdsets.\n"));
4838#endif
4839 err_state = MHD_YES;
4840 }
4841 }
4842 else
4843 {
4844 bool itc_added;
4845 /* accept only, have one thread per connection */
4846 itc_added = false;
4847 if (MHD_ITC_IS_VALID_ (daemon->itc))
4848 {
4849 itc_added = MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4850 &rs,
4851 &maxsock,
4852 (int) FD_SETSIZE);
4853 if (! itc_added)
4854 {
4855#ifdef HAVE_MESSAGES
4856 MHD_DLOG (daemon, _ ("Could not add control inter-thread " \
4857 "communication channel FD to fdset.\n"));
4858#endif
4859 err_state = MHD_YES;
4860 }
4861 }
4862 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4863 (! daemon->was_quiesced) )
4864 {
4865 /* Stop listening if we are at the configured connection limit */
4866 /* If we're at the connection limit, no point in really
4867 accepting new connections; however, make sure we do not miss
4868 the shutdown OR the termination of an existing connection; so
4869 only do this optimisation if we have a signaling ITC in
4870 place. */
4871 if (! itc_added ||
4872 ((daemon->connections < daemon->connection_limit) &&
4873 ! daemon->at_limit))
4874 {
4875 if (! MHD_add_to_fd_set_ (ls,
4876 &rs,
4877 &maxsock,
4878 (int) FD_SETSIZE))
4879 {
4880#ifdef HAVE_MESSAGES
4881 MHD_DLOG (daemon,
4882 _ ("Could not add listen socket to fdset.\n"));
4883#endif
4884 err_state = MHD_YES;
4885 }
4886 }
4887 }
4888 }
4889
4890 if (MHD_NO != err_state)
4891 millisec = 0;
4892 if (0 == millisec)
4893 {
4894 timeout.tv_usec = 0;
4895 timeout.tv_sec = 0;
4896 tv = &timeout;
4897 }
4898 else
4899 {
4900 uint64_t mhd_tmo;
4901 uint64_t select_tmo;
4902
4903 if ( (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon)) &&
4904 (MHD_NO != MHD_get_timeout64 (daemon, &mhd_tmo)) )
4905 {
4906 if ( (0 < millisec) &&
4907 (mhd_tmo > (uint64_t) millisec) )
4908 select_tmo = (uint64_t) millisec;
4909 else
4910 select_tmo = mhd_tmo;
4911 tv = &timeout; /* have timeout value */
4912 }
4913 else if (0 < millisec)
4914 {
4915 select_tmo = (uint64_t) millisec;
4916 tv = &timeout; /* have timeout value */
4917 }
4918 else
4919 {
4920 select_tmo = 0; /* Not actually used, silent compiler warning */
4921 tv = NULL;
4922 }
4923
4924 if (NULL != tv)
4925 { /* have timeout value */
4926#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
4927 if (select_tmo / 1000 > TIMEVAL_TV_SEC_MAX)
4928 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
4929 else
4930#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
4931 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (select_tmo / 1000);
4932
4933 timeout.tv_usec = ((uint16_t) (select_tmo % 1000)) * ((int32_t) 1000);
4934 }
4935 }
4936 num_ready = MHD_SYS_select_ (maxsock + 1,
4937 &rs,
4938 &ws,
4939 &es,
4940 tv);
4941 if (daemon->shutdown)
4942 return MHD_NO;
4943 if (num_ready < 0)
4944 {
4945 const int err = MHD_socket_get_error_ ();
4946 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4947 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4948#ifdef HAVE_MESSAGES
4949 MHD_DLOG (daemon,
4950 _ ("select failed: %s\n"),
4951 MHD_socket_strerr_ (err));
4952#endif
4953 return MHD_NO;
4954 }
4955 if (MHD_NO != internal_run_from_select (daemon,
4956 &rs,
4957 &ws,
4958 &es,
4959 (int) FD_SETSIZE))
4960 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4961 return MHD_NO;
4962}
4963
4964
4965#ifdef HAVE_POLL
4976static enum MHD_Result
4977MHD_poll_all (struct MHD_Daemon *daemon,
4978 int32_t millisec)
4979{
4980 unsigned int num_connections;
4981 struct MHD_Connection *pos;
4982 struct MHD_Connection *prev;
4983#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4984 struct MHD_UpgradeResponseHandle *urh;
4985 struct MHD_UpgradeResponseHandle *urhn;
4986#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4987
4988 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4989 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4990 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4991 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
4992 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
4994
4995 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4996 (MHD_NO != resume_suspended_connections (daemon)) )
4997 millisec = 0;
4998
4999 /* count number of connections and thus determine poll set size */
5000 num_connections = 0;
5001 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
5002 num_connections++;
5003#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5004 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
5005 num_connections += 2;
5006#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5007 {
5008 unsigned int i;
5009 int timeout;
5010 unsigned int poll_server;
5011 int poll_listen;
5012 int poll_itc_idx;
5013 struct pollfd *p;
5014 MHD_socket ls;
5015
5016 p = MHD_calloc_ ((2 + (size_t) num_connections),
5017 sizeof (struct pollfd));
5018 if (NULL == p)
5019 {
5020#ifdef HAVE_MESSAGES
5021 MHD_DLOG (daemon,
5022 _ ("Error allocating memory: %s\n"),
5023 MHD_strerror_ (errno));
5024#endif
5025 return MHD_NO;
5026 }
5027 poll_server = 0;
5028 poll_listen = -1;
5029 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5030 (! daemon->was_quiesced) &&
5031 (daemon->connections < daemon->connection_limit) &&
5032 (! daemon->at_limit) )
5033 {
5034 /* only listen if we are not at the connection limit */
5035 p[poll_server].fd = ls;
5036 p[poll_server].events = POLLIN;
5037 p[poll_server].revents = 0;
5038 poll_listen = (int) poll_server;
5039 poll_server++;
5040 }
5041 poll_itc_idx = -1;
5042 if (MHD_ITC_IS_VALID_ (daemon->itc))
5043 {
5044 p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
5045 p[poll_server].events = POLLIN;
5046 p[poll_server].revents = 0;
5047 poll_itc_idx = (int) poll_server;
5048 poll_server++;
5049 }
5050
5051 timeout = get_timeout_millisec_int (daemon, millisec);
5052
5053 i = 0;
5054 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
5055 {
5056 p[poll_server + i].fd = pos->socket_fd;
5057 switch (pos->event_loop_info)
5058 {
5061 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
5062 break;
5064 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
5065 break;
5067 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
5068 break;
5070 timeout = 0; /* clean up "pos" immediately */
5071 break;
5072 }
5073 i++;
5074 }
5075#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5076 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
5077 {
5078 urh_to_pollfd (urh, &(p[poll_server + i]));
5079 i += 2;
5080 }
5081#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5082 if (0 == poll_server + num_connections)
5083 {
5084 free (p);
5085 return MHD_YES;
5086 }
5087 if (MHD_sys_poll_ (p,
5088 poll_server + num_connections,
5089 timeout) < 0)
5090 {
5091 const int err = MHD_socket_get_error_ ();
5092 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5093 {
5094 free (p);
5095 return MHD_YES;
5096 }
5097#ifdef HAVE_MESSAGES
5098 MHD_DLOG (daemon,
5099 _ ("poll failed: %s\n"),
5100 MHD_socket_strerr_ (err));
5101#endif
5102 free (p);
5103 return MHD_NO;
5104 }
5105
5106 /* handle ITC FD */
5107 /* do it before any other processing so
5108 new signals will be processed in next loop */
5109 if ( (-1 != poll_itc_idx) &&
5110 (0 != (p[poll_itc_idx].revents & POLLIN)) )
5111 MHD_itc_clear_ (daemon->itc);
5112
5113 /* handle shutdown */
5114 if (daemon->shutdown)
5115 {
5116 free (p);
5117 return MHD_NO;
5118 }
5119
5120 /* Process externally added connection if any */
5121 if (daemon->have_new)
5123
5124 /* handle 'listen' FD */
5125 if ( (-1 != poll_listen) &&
5126 (0 != (p[poll_listen].revents & POLLIN)) )
5127 (void) MHD_accept_connection (daemon);
5128
5129 /* Reset. New value will be set when connections are processed. */
5130 daemon->data_already_pending = false;
5131
5132 i = 0;
5133 prev = daemon->connections_tail;
5134 while (NULL != (pos = prev))
5135 {
5136 prev = pos->prev;
5137 /* first, sanity checks */
5138 if (i >= num_connections)
5139 break; /* connection list changed somehow, retry later ... */
5140 if (p[poll_server + i].fd != pos->socket_fd)
5141 continue; /* fd mismatch, something else happened, retry later ... */
5142 call_handlers (pos,
5143 0 != (p[poll_server + i].revents & POLLIN),
5144 0 != (p[poll_server + i].revents & POLLOUT),
5145 0 != (p[poll_server + i].revents
5146 & MHD_POLL_REVENTS_ERR_DISC));
5147 i++;
5148 }
5149#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5150 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
5151 {
5152 if (i >= num_connections)
5153 break; /* connection list changed somehow, retry later ... */
5154
5155 /* Get next connection here as connection can be removed
5156 * from 'daemon->urh_head' list. */
5157 urhn = urh->prev;
5158 /* Check for fd mismatch. FIXME: required for safety? */
5159 if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
5160 (p[poll_server + i + 1].fd != urh->mhd.socket))
5161 break;
5162 urh_from_pollfd (urh,
5163 &p[poll_server + i]);
5164 i += 2;
5165 process_urh (urh);
5166 /* Finished forwarding? */
5167 if ( (0 == urh->in_buffer_size) &&
5168 (0 == urh->out_buffer_size) &&
5169 (0 == urh->in_buffer_used) &&
5170 (0 == urh->out_buffer_used) )
5171 {
5172 /* MHD_connection_finish_forward_() will remove connection from
5173 * 'daemon->urh_head' list. */
5174 MHD_connection_finish_forward_ (urh->connection);
5175 urh->clean_ready = true;
5176 /* If 'urh->was_closed' already was set to true, connection will be
5177 * moved immediately to cleanup list. Otherwise connection
5178 * will stay in suspended list until 'urh' will be marked
5179 * with 'was_closed' by application. */
5180 MHD_resume_connection (urh->connection);
5181 }
5182 }
5183#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5184
5185 free (p);
5186 }
5187 return MHD_YES;
5188}
5189
5190
5198static enum MHD_Result
5199MHD_poll_listen_socket (struct MHD_Daemon *daemon,
5200 int may_block)
5201{
5202 struct pollfd p[2];
5203 int timeout;
5204 unsigned int poll_count;
5205 int poll_listen;
5206 int poll_itc_idx;
5207 MHD_socket ls;
5208
5211
5212 memset (&p,
5213 0,
5214 sizeof (p));
5215 poll_count = 0;
5216 poll_listen = -1;
5217 poll_itc_idx = -1;
5218 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5219 (! daemon->was_quiesced) )
5220
5221 {
5222 p[poll_count].fd = ls;
5223 p[poll_count].events = POLLIN;
5224 p[poll_count].revents = 0;
5225 poll_listen = (int) poll_count;
5226 poll_count++;
5227 }
5228 if (MHD_ITC_IS_VALID_ (daemon->itc))
5229 {
5230 p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
5231 p[poll_count].events = POLLIN;
5232 p[poll_count].revents = 0;
5233 poll_itc_idx = (int) poll_count;
5234 poll_count++;
5235 }
5236
5237 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
5238 (void) resume_suspended_connections (daemon);
5239
5240 if (MHD_NO == may_block)
5241 timeout = 0;
5242 else
5243 timeout = -1;
5244 if (0 == poll_count)
5245 return MHD_YES;
5246 if (MHD_sys_poll_ (p,
5247 poll_count,
5248 timeout) < 0)
5249 {
5250 const int err = MHD_socket_get_error_ ();
5251
5252 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5253 return MHD_YES;
5254#ifdef HAVE_MESSAGES
5255 MHD_DLOG (daemon,
5256 _ ("poll failed: %s\n"),
5257 MHD_socket_strerr_ (err));
5258#endif
5259 return MHD_NO;
5260 }
5261 if ( (0 <= poll_itc_idx) &&
5262 (0 != (p[poll_itc_idx].revents & POLLIN)) )
5263 MHD_itc_clear_ (daemon->itc);
5264
5265 /* handle shutdown */
5266 if (daemon->shutdown)
5267 return MHD_NO;
5268
5269 /* Process externally added connection if any */
5270 if (daemon->have_new)
5272
5273 if ( (0 <= poll_listen) &&
5274 (0 != (p[poll_listen].revents & POLLIN)) )
5275 (void) MHD_accept_connection (daemon);
5276 return MHD_YES;
5277}
5278
5279
5280#endif
5281
5282#ifdef HAVE_POLL
5283
5291static enum MHD_Result
5292MHD_poll (struct MHD_Daemon *daemon,
5293 int may_block)
5294{
5295 if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
5296 return MHD_poll_all (daemon,
5297 may_block ? -1 : 0);
5298 return MHD_poll_listen_socket (daemon,
5299 may_block);
5300}
5301
5302
5303#endif /* HAVE_POLL */
5304
5305
5306#ifdef EPOLL_SUPPORT
5307
5316#define MAX_EVENTS 128
5317
5318
5319#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5320
5328static bool
5329is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
5330{
5331 const struct MHD_Connection *const connection = urh->connection;
5332
5333 if ( (0 == urh->in_buffer_size) &&
5334 (0 == urh->out_buffer_size) &&
5335 (0 == urh->in_buffer_used) &&
5336 (0 == urh->out_buffer_used) )
5337 return false;
5338 if (connection->daemon->shutdown)
5339 return true;
5341 & urh->app.celi)) ||
5342 (connection->tls_read_ready) ) &&
5343 (urh->in_buffer_used < urh->in_buffer_size) )
5344 return true;
5346 & urh->mhd.celi)) ||
5347 urh->was_closed) &&
5348 (urh->out_buffer_used < urh->out_buffer_size) )
5349 return true;
5350 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
5351 (urh->out_buffer_used > 0) )
5352 return true;
5353 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
5354 (urh->in_buffer_used > 0) )
5355 return true;
5356 return false;
5357}
5358
5359
5368static enum MHD_Result
5369run_epoll_for_upgrade (struct MHD_Daemon *daemon)
5370{
5371 struct epoll_event events[MAX_EVENTS];
5372 int num_events;
5373 struct MHD_UpgradeResponseHandle *pos;
5374 struct MHD_UpgradeResponseHandle *prev;
5375
5376#ifdef MHD_USE_THREADS
5377 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
5379#endif /* MHD_USE_THREADS */
5380
5381 num_events = MAX_EVENTS;
5382 while (0 != num_events)
5383 {
5384 unsigned int i;
5385 /* update event masks */
5386 num_events = epoll_wait (daemon->epoll_upgrade_fd,
5387 events,
5388 MAX_EVENTS,
5389 0);
5390 if (-1 == num_events)
5391 {
5392 const int err = MHD_socket_get_error_ ();
5393
5394 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5395 return MHD_YES;
5396#ifdef HAVE_MESSAGES
5397 MHD_DLOG (daemon,
5398 _ ("Call to epoll_wait failed: %s\n"),
5399 MHD_socket_strerr_ (err));
5400#endif
5401 return MHD_NO;
5402 }
5403 for (i = 0; i < (unsigned int) num_events; i++)
5404 {
5405 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
5406 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
5407 bool new_err_state = false;
5408
5409 if (urh->clean_ready)
5410 continue;
5411
5412 /* Update ueh state based on what is ready according to epoll() */
5413 if (0 != (events[i].events & EPOLLIN))
5414 {
5415 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
5416 }
5417 if (0 != (events[i].events & EPOLLOUT))
5418 {
5419 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
5420 }
5421 if (0 != (events[i].events & EPOLLHUP))
5422 {
5424 }
5425
5426 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
5427 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
5428 {
5429 /* Process new error state only one time and avoid continuously
5430 * marking this connection as 'ready'. */
5431 ueh->celi |= MHD_EPOLL_STATE_ERROR;
5432 new_err_state = true;
5433 }
5434 if (! urh->in_eready_list)
5435 {
5436 if (new_err_state ||
5437 is_urh_ready (urh))
5438 {
5439 EDLL_insert (daemon->eready_urh_head,
5440 daemon->eready_urh_tail,
5441 urh);
5442 urh->in_eready_list = true;
5443 }
5444 }
5445 }
5446 }
5447 prev = daemon->eready_urh_tail;
5448 while (NULL != (pos = prev))
5449 {
5450 prev = pos->prevE;
5451 process_urh (pos);
5452 if (! is_urh_ready (pos))
5453 {
5454 EDLL_remove (daemon->eready_urh_head,
5455 daemon->eready_urh_tail,
5456 pos);
5457 pos->in_eready_list = false;
5458 }
5459 /* Finished forwarding? */
5460 if ( (0 == pos->in_buffer_size) &&
5461 (0 == pos->out_buffer_size) &&
5462 (0 == pos->in_buffer_used) &&
5463 (0 == pos->out_buffer_used) )
5464 {
5465 MHD_connection_finish_forward_ (pos->connection);
5466 pos->clean_ready = true;
5467 /* If 'pos->was_closed' already was set to true, connection
5468 * will be moved immediately to cleanup list. Otherwise
5469 * connection will stay in suspended list until 'pos' will
5470 * be marked with 'was_closed' by application. */
5471 MHD_resume_connection (pos->connection);
5472 }
5473 }
5474
5475 return MHD_YES;
5476}
5477
5478
5479#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5480
5481
5485static const char *const epoll_itc_marker = "itc_marker";
5486
5487
5497static enum MHD_Result
5498MHD_epoll (struct MHD_Daemon *daemon,
5499 int32_t millisec)
5500{
5501#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5502 static const char *const upgrade_marker = "upgrade_ptr";
5503#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5504 struct MHD_Connection *pos;
5505 struct MHD_Connection *prev;
5506 struct epoll_event events[MAX_EVENTS];
5507 struct epoll_event event;
5508 int timeout_ms;
5509 int num_events;
5510 unsigned int i;
5511 MHD_socket ls;
5512#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5513 bool run_upgraded = false;
5514#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5515 bool need_to_accept;
5516
5517 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5518 (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5519 mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5520 (! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
5521 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
5523
5524 if (-1 == daemon->epoll_fd)
5525 return MHD_NO; /* we're down! */
5526 if (daemon->shutdown)
5527 return MHD_NO;
5528 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
5529 (! daemon->was_quiesced) &&
5530 (daemon->connections < daemon->connection_limit) &&
5531 (! daemon->listen_socket_in_epoll) &&
5532 (! daemon->at_limit) )
5533 {
5534 event.events = EPOLLIN | EPOLLRDHUP;
5535 event.data.ptr = daemon;
5536 if (0 != epoll_ctl (daemon->epoll_fd,
5537 EPOLL_CTL_ADD,
5538 ls,
5539 &event))
5540 {
5541#ifdef HAVE_MESSAGES
5542 MHD_DLOG (daemon,
5543 _ ("Call to epoll_ctl failed: %s\n"),
5545#endif
5546 return MHD_NO;
5547 }
5548 daemon->listen_socket_in_epoll = true;
5549 }
5550 if ( (daemon->was_quiesced) &&
5551 (daemon->listen_socket_in_epoll) )
5552 {
5553 if ( (0 != epoll_ctl (daemon->epoll_fd,
5554 EPOLL_CTL_DEL,
5555 ls,
5556 NULL)) &&
5557 (ENOENT != errno) ) /* ENOENT can happen due to race with
5558 #MHD_quiesce_daemon() */
5559 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
5560 daemon->listen_socket_in_epoll = false;
5561 }
5562
5563#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5564 if ( ( (! daemon->upgrade_fd_in_epoll) &&
5565 (-1 != daemon->epoll_upgrade_fd) ) )
5566 {
5567 event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
5568 event.data.ptr = _MHD_DROP_CONST (upgrade_marker);
5569 if (0 != epoll_ctl (daemon->epoll_fd,
5570 EPOLL_CTL_ADD,
5571 daemon->epoll_upgrade_fd,
5572 &event))
5573 {
5574#ifdef HAVE_MESSAGES
5575 MHD_DLOG (daemon,
5576 _ ("Call to epoll_ctl failed: %s\n"),
5578#endif
5579 return MHD_NO;
5580 }
5581 daemon->upgrade_fd_in_epoll = true;
5582 }
5583#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5584 if ( (daemon->listen_socket_in_epoll) &&
5585 ( (daemon->connections == daemon->connection_limit) ||
5586 (daemon->at_limit) ||
5587 (daemon->was_quiesced) ) )
5588 {
5589 /* we're at the connection limit, disable listen socket
5590 for event loop for now */
5591 if (0 != epoll_ctl (daemon->epoll_fd,
5592 EPOLL_CTL_DEL,
5593 ls,
5594 NULL))
5595 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
5596 daemon->listen_socket_in_epoll = false;
5597 }
5598
5599 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
5600 (MHD_NO != resume_suspended_connections (daemon)) )
5601 millisec = 0;
5602
5603 timeout_ms = get_timeout_millisec_int (daemon,
5604 millisec);
5605
5606 /* Reset. New value will be set when connections are processed. */
5607 /* Note: Used mostly for uniformity here as same situation is
5608 * signaled in epoll mode by non-empty eready DLL. */
5609 daemon->data_already_pending = false;
5610
5611 need_to_accept = false;
5612 /* drain 'epoll' event queue; need to iterate as we get at most
5613 MAX_EVENTS in one system call here; in practice this should
5614 pretty much mean only one round, but better an extra loop here
5615 than unfair behavior... */
5616 num_events = MAX_EVENTS;
5617 while (MAX_EVENTS == num_events)
5618 {
5619 /* update event masks */
5620 num_events = epoll_wait (daemon->epoll_fd,
5621 events,
5622 MAX_EVENTS,
5623 timeout_ms);
5624 if (-1 == num_events)
5625 {
5626 const int err = MHD_socket_get_error_ ();
5627 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5628 return MHD_YES;
5629#ifdef HAVE_MESSAGES
5630 MHD_DLOG (daemon,
5631 _ ("Call to epoll_wait failed: %s\n"),
5632 MHD_socket_strerr_ (err));
5633#endif
5634 return MHD_NO;
5635 }
5636 for (i = 0; i < (unsigned int) num_events; i++)
5637 {
5638 /* First, check for the values of `ptr` that would indicate
5639 that this event is not about a normal connection. */
5640 if (NULL == events[i].data.ptr)
5641 continue; /* shutdown signal! */
5642#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5643 if (upgrade_marker == events[i].data.ptr)
5644 {
5645 /* activity on an upgraded connection, we process
5646 those in a separate epoll() */
5647 run_upgraded = true;
5648 continue;
5649 }
5650#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5651 if (epoll_itc_marker == events[i].data.ptr)
5652 {
5653 /* It's OK to clear ITC here as all external
5654 conditions will be processed later. */
5655 MHD_itc_clear_ (daemon->itc);
5656 continue;
5657 }
5658 if (daemon == events[i].data.ptr)
5659 {
5660 /* Check for error conditions on listen socket. */
5661 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
5662 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
5663 need_to_accept = true;
5664 continue;
5665 }
5666 /* this is an event relating to a 'normal' connection,
5667 remember the event and if appropriate mark the
5668 connection as 'eready'. */
5669 pos = events[i].data.ptr;
5670 /* normal processing: update read/write data */
5671 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
5672 {
5673 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
5674 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
5675 {
5676 EDLL_insert (daemon->eready_head,
5677 daemon->eready_tail,
5678 pos);
5679 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5680 }
5681 }
5682 else
5683 {
5684 if (0 != (events[i].events & EPOLLIN))
5685 {
5686 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
5687 if ( ( (0 != (MHD_EVENT_LOOP_INFO_READ & pos->event_loop_info)) ||
5688 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
5689 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5690 {
5691 EDLL_insert (daemon->eready_head,
5692 daemon->eready_tail,
5693 pos);
5694 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5695 }
5696 }
5697 if (0 != (events[i].events & EPOLLOUT))
5698 {
5699 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
5701 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5702 {
5703 EDLL_insert (daemon->eready_head,
5704 daemon->eready_tail,
5705 pos);
5706 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5707 }
5708 }
5709 }
5710 }
5711 }
5712
5713 /* Process externally added connection if any */
5714 if (daemon->have_new)
5716
5717 if (need_to_accept)
5718 {
5719 unsigned int series_length = 0;
5720
5721 /* Run 'accept' until it fails or daemon at limit of connections.
5722 * Do not accept more then 10 connections at once. The rest will
5723 * be accepted on next turn (level trigger is used for listen
5724 * socket). */
5725 while ( (MHD_NO != MHD_accept_connection (daemon)) &&
5726 (series_length < 10) &&
5727 (daemon->connections < daemon->connection_limit) &&
5728 (! daemon->at_limit) )
5729 series_length++;
5730 }
5731
5732 /* Handle timed-out connections; we need to do this here
5733 as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
5734 as the other event loops do. As timeouts do not get an explicit
5735 event, we need to find those connections that might have timed out
5736 here.
5737
5738 Connections with custom timeouts must all be looked at, as we
5739 do not bother to sort that (presumably very short) list. */
5740 prev = daemon->manual_timeout_tail;
5741 while (NULL != (pos = prev))
5742 {
5743 prev = pos->prevX;
5745 }
5746 /* Connections with the default timeout are sorted by prepending
5747 them to the head of the list whenever we touch the connection;
5748 thus it suffices to iterate from the tail until the first
5749 connection is NOT timed out */
5750 prev = daemon->normal_timeout_tail;
5751 while (NULL != (pos = prev))
5752 {
5753 prev = pos->prevX;
5755 if (MHD_CONNECTION_CLOSED != pos->state)
5756 break; /* sorted by timeout, no need to visit the rest! */
5757 }
5758
5759#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5760 if (run_upgraded || (NULL != daemon->eready_urh_head))
5761 run_epoll_for_upgrade (daemon);
5762#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5763
5764 /* process events for connections */
5765 prev = daemon->eready_tail;
5766 while (NULL != (pos = prev))
5767 {
5768 prev = pos->prevE;
5769 call_handlers (pos,
5770 0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
5771 0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
5772 0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
5774 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
5776 {
5777 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
5778 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
5780 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
5782 {
5783 EDLL_remove (daemon->eready_head,
5784 daemon->eready_tail,
5785 pos);
5786 pos->epoll_state &=
5788 }
5789 }
5790 }
5791
5792 return MHD_YES;
5793}
5794
5795
5796#endif
5797
5798
5827MHD_run (struct MHD_Daemon *daemon)
5828{
5829 if ( (daemon->shutdown) ||
5830 MHD_D_IS_USING_THREADS_ (daemon) )
5831 return MHD_NO;
5832
5833 (void) MHD_run_wait (daemon, 0);
5834 return MHD_YES;
5835}
5836
5837
5877MHD_run_wait (struct MHD_Daemon *daemon,
5878 int32_t millisec)
5879{
5880 enum MHD_Result res;
5881 if ( (daemon->shutdown) ||
5882 MHD_D_IS_USING_THREADS_ (daemon) )
5883 return MHD_NO;
5884
5886
5887 if (0 > millisec)
5888 millisec = -1;
5889#ifdef HAVE_POLL
5890 if (MHD_D_IS_USING_POLL_ (daemon))
5891 {
5892 res = MHD_poll_all (daemon, millisec);
5893 MHD_cleanup_connections (daemon);
5894 }
5895 else
5896#endif /* HAVE_POLL */
5897#ifdef EPOLL_SUPPORT
5898 if (MHD_D_IS_USING_EPOLL_ (daemon))
5899 {
5900 res = MHD_epoll (daemon, millisec);
5901 MHD_cleanup_connections (daemon);
5902 }
5903 else
5904#endif
5905 if (1)
5906 {
5908#ifdef HAS_FD_SETSIZE_OVERRIDABLE
5909#ifdef HAVE_MESSAGES
5910 if (daemon->fdset_size_set_by_app
5911 && (((int) FD_SETSIZE) < daemon->fdset_size))
5912 {
5913 MHD_DLOG (daemon,
5914 _ ("MHD_run()/MHD_run_wait() called for daemon started with " \
5915 "MHD_OPTION_APP_FD_SETSIZE option (%d). " \
5916 "The library was compiled with smaller FD_SETSIZE (%d). " \
5917 "Some socket FDs may be not processed. " \
5918 "Use MHD_run_from_select2() instead of MHD_run() or " \
5919 "do not use MHD_OPTION_APP_FD_SETSIZE option.\n"),
5920 daemon->fdset_size, (int) FD_SETSIZE);
5921 }
5922#endif /* HAVE_MESSAGES */
5923#endif /* HAS_FD_SETSIZE_OVERRIDABLE */
5924
5925 res = MHD_select (daemon, millisec);
5926 /* MHD_select does MHD_cleanup_connections already */
5927 }
5928 return res;
5929}
5930
5931
5940static void
5942{
5943 struct MHD_Daemon *daemon = pos->daemon;
5944
5945#ifdef MHD_USE_THREADS
5946 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
5948 mhd_assert (NULL == daemon->worker_pool);
5949#endif /* MHD_USE_THREADS */
5950
5952 {
5954 return; /* must let thread to do the rest */
5955 }
5958#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5959 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
5960#endif
5961 mhd_assert (! pos->suspended);
5962 mhd_assert (! pos->resuming);
5963 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
5965 daemon->normal_timeout_tail,
5966 pos);
5967 else
5969 daemon->manual_timeout_tail,
5970 pos);
5972 daemon->connections_tail,
5973 pos);
5974 DLL_insert (daemon->cleanup_head,
5975 daemon->cleanup_tail,
5976 pos);
5977 daemon->data_already_pending = true;
5978#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5979 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
5980#endif
5981}
5982
5983
5984#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5992static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
5993MHD_polling_thread (void *cls)
5994{
5995 struct MHD_Daemon *daemon = cls;
5996#ifdef HAVE_PTHREAD_SIGMASK
5997 sigset_t s_mask;
5998 int err;
5999#endif /* HAVE_PTHREAD_SIGMASK */
6000
6002#ifdef HAVE_PTHREAD_SIGMASK
6003 if ((0 == sigemptyset (&s_mask)) &&
6004 (0 == sigaddset (&s_mask, SIGPIPE)))
6005 {
6006 err = pthread_sigmask (SIG_BLOCK, &s_mask, NULL);
6007 }
6008 else
6009 err = errno;
6010 if (0 == err)
6011 daemon->sigpipe_blocked = true;
6012#ifdef HAVE_MESSAGES
6013 else
6014 MHD_DLOG (daemon,
6015 _ ("Failed to block SIGPIPE on daemon thread: %s\n"),
6016 MHD_strerror_ (errno));
6017#endif /* HAVE_MESSAGES */
6018#endif /* HAVE_PTHREAD_SIGMASK */
6019 while (! daemon->shutdown)
6020 {
6021#ifdef HAVE_POLL
6022 if (MHD_D_IS_USING_POLL_ (daemon))
6023 MHD_poll (daemon, MHD_YES);
6024 else
6025#endif /* HAVE_POLL */
6026#ifdef EPOLL_SUPPORT
6027 if (MHD_D_IS_USING_EPOLL_ (daemon))
6028 MHD_epoll (daemon, -1);
6029 else
6030#endif
6031 MHD_select (daemon, -1);
6032 MHD_cleanup_connections (daemon);
6033 }
6034
6035 /* Resume any pending for resume connections, join
6036 * all connection's threads (if any) and finally cleanup
6037 * everything. */
6038 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6040 close_all_connections (daemon);
6041
6042 return (MHD_THRD_RTRN_TYPE_) 0;
6043}
6044
6045
6046#endif
6047
6048
6060static size_t
6062 struct MHD_Connection *connection,
6063 char *val)
6064{
6065 bool broken;
6066 size_t res;
6067 (void) cls; /* Mute compiler warning. */
6068
6069 /* TODO: add individual parameter */
6070 if (0 <= connection->daemon->client_discipline)
6072
6073 res = MHD_str_pct_decode_in_place_lenient_ (val, &broken);
6074#ifdef HAVE_MESSAGES
6075 if (broken)
6076 {
6077 MHD_DLOG (connection->daemon,
6078 _ ("The URL encoding is broken.\n"));
6079 }
6080#endif /* HAVE_MESSAGES */
6081 return res;
6082}
6083
6084
6105_MHD_EXTERN struct MHD_Daemon *
6106MHD_start_daemon (unsigned int flags,
6107 uint16_t port,
6109 void *apc_cls,
6111 void *dh_cls,
6112 ...)
6113{
6114 struct MHD_Daemon *daemon;
6115 va_list ap;
6116
6117 va_start (ap,
6118 dh_cls);
6119 daemon = MHD_start_daemon_va (flags,
6120 port,
6121 apc,
6122 apc_cls,
6123 dh,
6124 dh_cls,
6125 ap);
6126 va_end (ap);
6127 return daemon;
6128}
6129
6130
6152{
6153#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6154 unsigned int i;
6155#endif
6156 MHD_socket ret;
6157
6158 ret = daemon->listen_fd;
6159 if ((MHD_INVALID_SOCKET == ret)
6160 || daemon->was_quiesced)
6161 return MHD_INVALID_SOCKET;
6162 if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
6163 MHD_D_IS_USING_THREADS_ (daemon) )
6164 {
6165#ifdef HAVE_MESSAGES
6166 MHD_DLOG (daemon,
6167 _ ("Using MHD_quiesce_daemon in this mode " \
6168 "requires MHD_USE_ITC.\n"));
6169#endif
6170 return MHD_INVALID_SOCKET;
6171 }
6172
6173#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6174 if (NULL != daemon->worker_pool)
6175 for (i = 0; i < daemon->worker_pool_size; i++)
6176 {
6177 daemon->worker_pool[i].was_quiesced = true;
6178#ifdef EPOLL_SUPPORT
6179 if (MHD_D_IS_USING_EPOLL_ (daemon) &&
6180 (-1 != daemon->worker_pool[i].epoll_fd) &&
6181 (daemon->worker_pool[i].listen_socket_in_epoll) )
6182 {
6183 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
6184 EPOLL_CTL_DEL,
6185 ret,
6186 NULL))
6187 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
6188 daemon->worker_pool[i].listen_socket_in_epoll = false;
6189 }
6190 else
6191#endif
6192 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
6193 {
6194 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
6195 MHD_PANIC (_ ("Failed to signal quiesce via inter-thread " \
6196 "communication channel.\n"));
6197 }
6198 }
6199#endif
6200 daemon->was_quiesced = true;
6201#ifdef EPOLL_SUPPORT
6202 if (MHD_D_IS_USING_EPOLL_ (daemon) &&
6203 (-1 != daemon->epoll_fd) &&
6204 (daemon->listen_socket_in_epoll) )
6205 {
6206 if ( (0 != epoll_ctl (daemon->epoll_fd,
6207 EPOLL_CTL_DEL,
6208 ret,
6209 NULL)) &&
6210 (ENOENT != errno) ) /* ENOENT can happen due to race with
6211 #MHD_epoll() */
6212 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
6213 daemon->listen_socket_in_epoll = false;
6214 }
6215#endif
6216 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
6217 (! MHD_itc_activate_ (daemon->itc, "q")) )
6218 MHD_PANIC (_ ("failed to signal quiesce via inter-thread " \
6219 "communication channel.\n"));
6220 return ret;
6221}
6222
6223
6229struct MHD_InterimParams_
6230{
6238 size_t num_opts;
6242 bool fdset_size_set;
6246 int fdset_size;
6250 bool listen_fd_set;
6254 MHD_socket listen_fd;
6258 bool pserver_addr_set;
6262 const struct sockaddr *pserver_addr;
6266 bool server_addr_len_set;
6270 socklen_t server_addr_len;
6271};
6272
6280typedef void
6281(*VfprintfFunctionPointerType)(void *cls,
6282 const char *format,
6283 va_list va);
6284
6285
6295static enum MHD_Result
6296parse_options_va (struct MHD_Daemon *daemon,
6297 struct MHD_InterimParams_ *params,
6298 va_list ap);
6299
6300
6310static enum MHD_Result
6312 struct MHD_InterimParams_ *params,
6313 ...)
6314{
6315 va_list ap;
6316 enum MHD_Result ret;
6317
6318 va_start (ap, params);
6319 ret = parse_options_va (daemon,
6320 params,
6321 ap);
6322 va_end (ap);
6323 return ret;
6324}
6325
6326
6327#ifdef HTTPS_SUPPORT
6331enum MHD_TlsPrioritiesBaseType
6332{
6333 MHD_TLS_PRIO_BASE_LIBMHD = 0,
6334 MHD_TLS_PRIO_BASE_SYSTEM = 1,
6335#if GNUTLS_VERSION_NUMBER >= 0x030300
6336 MHD_TLS_PRIO_BASE_DEFAULT,
6337#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6338 MHD_TLS_PRIO_BASE_NORMAL
6339};
6340
6341static const struct _MHD_cstr_w_len MHD_TlsBasePriotities[] = {
6342 _MHD_S_STR_W_LEN ("@LIBMICROHTTPD"),
6343 _MHD_S_STR_W_LEN ("@SYSTEM"),
6344#if GNUTLS_VERSION_NUMBER >= 0x030300
6345 {NULL, 0},
6346#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6347 _MHD_S_STR_W_LEN ("NORMAL")
6348};
6349
6355static bool
6356daemon_tls_priorities_init_default (struct MHD_Daemon *daemon)
6357{
6358 unsigned int p;
6359 int res;
6360
6361 mhd_assert (0 != (((unsigned int) daemon->options) & MHD_USE_TLS));
6362 mhd_assert (NULL == daemon->priority_cache);
6363 mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \
6364 sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]));
6365
6366 res = GNUTLS_E_SUCCESS; /* Mute compiler warning */
6367
6368 for (p = 0;
6369 p < sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]);
6370 ++p)
6371 {
6372 res = gnutls_priority_init (&daemon->priority_cache,
6373 MHD_TlsBasePriotities[p].str, NULL);
6374 if (GNUTLS_E_SUCCESS == res)
6375 {
6376#ifdef _DEBUG
6377#ifdef HAVE_MESSAGES
6378 switch ((enum MHD_TlsPrioritiesBaseType) p)
6379 {
6380 case MHD_TLS_PRIO_BASE_LIBMHD:
6381 MHD_DLOG (daemon,
6382 _ ("GnuTLS priorities have been initialised with " \
6383 "@LIBMICROHTTPD application-specific system-wide " \
6384 "configuration.\n") );
6385 break;
6386 case MHD_TLS_PRIO_BASE_SYSTEM:
6387 MHD_DLOG (daemon,
6388 _ ("GnuTLS priorities have been initialised with " \
6389 "@SYSTEM system-wide configuration.\n") );
6390 break;
6391#if GNUTLS_VERSION_NUMBER >= 0x030300
6392 case MHD_TLS_PRIO_BASE_DEFAULT:
6393 MHD_DLOG (daemon,
6394 _ ("GnuTLS priorities have been initialised with " \
6395 "GnuTLS default configuration.\n") );
6396 break;
6397#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6398 case MHD_TLS_PRIO_BASE_NORMAL:
6399 MHD_DLOG (daemon,
6400 _ ("GnuTLS priorities have been initialised with " \
6401 "NORMAL configuration.\n") );
6402 break;
6403 default:
6404 mhd_assert (0);
6405 }
6406#endif /* HAVE_MESSAGES */
6407#endif /* _DEBUG */
6408 return true;
6409 }
6410 }
6411#ifdef HAVE_MESSAGES
6412 MHD_DLOG (daemon,
6413 _ ("Failed to set GnuTLS priorities. Last error: %s\n"),
6414 gnutls_strerror (res));
6415#endif /* HAVE_MESSAGES */
6416 return false;
6417}
6418
6419
6429static bool
6430daemon_tls_priorities_init_append_inner_ (struct MHD_Daemon *daemon,
6431 const char *prio,
6432 size_t prio_len,
6433 char *buf,
6434 const size_t buf_size)
6435{
6436 unsigned int p;
6437 int res;
6438 const char *err_pos;
6439
6440 (void) buf_size; /* Mute compiler warning for non-Debug builds */
6441 mhd_assert (0 != (((unsigned int) daemon->options) & MHD_USE_TLS));
6442 mhd_assert (NULL == daemon->priority_cache);
6443 mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \
6444 sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]));
6445
6446 res = GNUTLS_E_SUCCESS; /* Mute compiler warning */
6447
6448 for (p = 0;
6449 p < sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]);
6450 ++p)
6451 {
6452
6453#if GNUTLS_VERSION_NUMBER >= 0x030300
6454#if GNUTLS_VERSION_NUMBER >= 0x030603
6455 if (NULL == MHD_TlsBasePriotities[p].str)
6456 res = gnutls_priority_init2 (&daemon->priority_cache, prio, &err_pos,
6457 GNUTLS_PRIORITY_INIT_DEF_APPEND);
6458 else
6459#else /* 0x030300 <= GNUTLS_VERSION_NUMBER
6460 && GNUTLS_VERSION_NUMBER < 0x030603 */
6461 if (NULL == MHD_TlsBasePriotities[p].str)
6462 continue; /* Skip the value, no way to append priorities to the default string */
6463 else
6464#endif /* GNUTLS_VERSION_NUMBER < 0x030603 */
6465#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6466 if (1)
6467 {
6468 size_t buf_pos;
6469
6470 mhd_assert (NULL != MHD_TlsBasePriotities[p].str);
6471 buf_pos = 0;
6472 memcpy (buf + buf_pos, MHD_TlsBasePriotities[p].str,
6473 MHD_TlsBasePriotities[p].len);
6474 buf_pos += MHD_TlsBasePriotities[p].len;
6475 buf[buf_pos++] = ':';
6476 memcpy (buf + buf_pos, prio, prio_len + 1);
6477#ifdef _DEBUG
6478 buf_pos += prio_len + 1;
6479 mhd_assert (buf_size >= buf_pos);
6480#endif /* _DEBUG */
6481 res = gnutls_priority_init (&daemon->priority_cache, buf, &err_pos);
6482 }
6483 if (GNUTLS_E_SUCCESS == res)
6484 {
6485#ifdef _DEBUG
6486#ifdef HAVE_MESSAGES
6487 switch ((enum MHD_TlsPrioritiesBaseType) p)
6488 {
6489 case MHD_TLS_PRIO_BASE_LIBMHD:
6490 MHD_DLOG (daemon,
6491 _ ("GnuTLS priorities have been initialised with " \
6492 "priorities specified by application appended to " \
6493 "@LIBMICROHTTPD application-specific system-wide " \
6494 "configuration.\n") );
6495 break;
6496 case MHD_TLS_PRIO_BASE_SYSTEM:
6497 MHD_DLOG (daemon,
6498 _ ("GnuTLS priorities have been initialised with " \
6499 "priorities specified by application appended to " \
6500 "@SYSTEM system-wide configuration.\n") );
6501 break;
6502#if GNUTLS_VERSION_NUMBER >= 0x030300
6503 case MHD_TLS_PRIO_BASE_DEFAULT:
6504 MHD_DLOG (daemon,
6505 _ ("GnuTLS priorities have been initialised with " \
6506 "priorities specified by application appended to " \
6507 "GnuTLS default configuration.\n") );
6508 break;
6509#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */
6510 case MHD_TLS_PRIO_BASE_NORMAL:
6511 MHD_DLOG (daemon,
6512 _ ("GnuTLS priorities have been initialised with " \
6513 "priorities specified by application appended to " \
6514 "NORMAL configuration.\n") );
6515 break;
6516 default:
6517 mhd_assert (0);
6518 }
6519#endif /* HAVE_MESSAGES */
6520#endif /* _DEBUG */
6521 return true;
6522 }
6523 }
6524#ifdef HAVE_MESSAGES
6525 MHD_DLOG (daemon,
6526 _ ("Failed to set GnuTLS priorities. Last error: %s. " \
6527 "The problematic part starts at: %s\n"),
6528 gnutls_strerror (res), err_pos);
6529#endif /* HAVE_MESSAGES */
6530 return false;
6531}
6532
6533
6534#define LOCAL_BUFF_SIZE 128
6535
6544static bool
6545daemon_tls_priorities_init_append (struct MHD_Daemon *daemon, const char *prio)
6546{
6547 static const size_t longest_base_prio = MHD_STATICSTR_LEN_ ("@LIBMICROHTTPD");
6548 bool ret;
6549 size_t prio_len;
6550 size_t buf_size_needed;
6551
6552 if (NULL == prio)
6553 return daemon_tls_priorities_init_default (daemon);
6554
6555 if (':' == prio[0])
6556 ++prio;
6557
6558 prio_len = strlen (prio);
6559
6560 buf_size_needed = longest_base_prio + 1 + prio_len + 1;
6561
6562 if (LOCAL_BUFF_SIZE >= buf_size_needed)
6563 {
6564 char local_buffer[LOCAL_BUFF_SIZE];
6565 ret = daemon_tls_priorities_init_append_inner_ (daemon, prio, prio_len,
6566 local_buffer,
6567 LOCAL_BUFF_SIZE);
6568 }
6569 else
6570 {
6571 char *allocated_buffer;
6572 allocated_buffer = (char *) malloc (buf_size_needed);
6573 if (NULL == allocated_buffer)
6574 {
6575#ifdef HAVE_MESSAGES
6576 MHD_DLOG (daemon,
6577 _ ("Error allocating memory: %s\n"),
6578 MHD_strerror_ (errno));
6579#endif
6580 return false;
6581 }
6582 ret = daemon_tls_priorities_init_append_inner_ (daemon, prio, prio_len,
6583 allocated_buffer,
6584 buf_size_needed);
6585 free (allocated_buffer);
6586 }
6587 return ret;
6588}
6589
6590
6591#endif /* HTTPS_SUPPORT */
6592
6593
6602static enum MHD_Result
6604 struct MHD_InterimParams_ *params,
6605 va_list ap)
6606{
6607 enum MHD_OPTION opt;
6608 struct MHD_OptionItem *oa;
6609 unsigned int i;
6610 unsigned int uv;
6611#ifdef HTTPS_SUPPORT
6612 const char *pstr;
6613#if GNUTLS_VERSION_MAJOR >= 3
6614 gnutls_certificate_retrieve_function2 * pgcrf;
6615#endif
6616#if GNUTLS_VERSION_NUMBER >= 0x030603
6617 gnutls_certificate_retrieve_function3 * pgcrf2;
6618#endif
6619#endif /* HTTPS_SUPPORT */
6620
6621 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
6622 {
6623 /* Increase counter at start, so resulting value is number of
6624 * processed options, including any failed ones. */
6625 params->num_opts++;
6626 switch (opt)
6627 {
6629 if (1)
6630 {
6631 size_t val;
6632
6633 val = va_arg (ap,
6634 size_t);
6635 if (0 != val)
6636 {
6637 daemon->pool_size = val;
6638 if (64 > daemon->pool_size)
6639 {
6640#ifdef HAVE_MESSAGES
6641 MHD_DLOG (daemon,
6642 _ ("Warning: specified " \
6643 "MHD_OPTION_CONNECTION_MEMORY_LIMIT " \
6644 "value is too small and rounded up to 64.\n"));
6645#endif /* HAVE_MESSAGES */
6646 daemon->pool_size = 64;
6647 }
6648 if (daemon->pool_size / 4 < daemon->pool_increment)
6649 daemon->pool_increment = daemon->pool_size / 4;
6650 }
6651 }
6652 break;
6654 if (1)
6655 {
6656 size_t val;
6657
6658 val = va_arg (ap,
6659 size_t);
6660
6661 if (0 != val)
6662 {
6663 daemon->pool_increment = val;
6664 if (daemon->pool_size / 4 < daemon->pool_increment)
6665 {
6666#ifdef HAVE_MESSAGES
6667 MHD_DLOG (daemon,
6668 _ ("Warning: specified " \
6669 "MHD_OPTION_CONNECTION_MEMORY_INCREMENT value is " \
6670 "too large and rounded down to 1/4 of " \
6671 "MHD_OPTION_CONNECTION_MEMORY_LIMIT.\n"));
6672#endif /* HAVE_MESSAGES */
6673 daemon->pool_increment = daemon->pool_size / 4;
6674 }
6675 }
6676 }
6677 break;
6679 daemon->connection_limit = va_arg (ap,
6680 unsigned int);
6681 break;
6683 uv = va_arg (ap,
6684 unsigned int);
6685#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
6686 if ((UINT64_MAX / 4000 - 1) < uv)
6687 {
6688#ifdef HAVE_MESSAGES
6689 MHD_DLOG (daemon,
6690 _ ("The specified connection timeout (%u) is too large. " \
6691 "Maximum allowed value (%" PRIu64 ") will be used " \
6692 "instead.\n"),
6693 uv,
6694 (UINT64_MAX / 4000 - 1));
6695#endif
6696 uv = UINT64_MAX / 4000 - 1;
6697 }
6698#endif /* (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT */
6699 daemon->connection_timeout_ms = ((uint64_t) uv) * 1000;
6700 break;
6702 daemon->notify_completed = va_arg (ap,
6704 daemon->notify_completed_cls = va_arg (ap,
6705 void *);
6706 break;
6708 daemon->notify_connection = va_arg (ap,
6710 daemon->notify_connection_cls = va_arg (ap,
6711 void *);
6712 break;
6714 daemon->per_ip_connection_limit = va_arg (ap,
6715 unsigned int);
6716 break;
6718 params->server_addr_len = va_arg (ap,
6719 socklen_t);
6720 params->server_addr_len_set = true;
6721 params->pserver_addr = va_arg (ap,
6722 const struct sockaddr *);
6723 params->pserver_addr_set = true;
6724 break;
6726 params->server_addr_len_set = false;
6727 params->pserver_addr = va_arg (ap,
6728 const struct sockaddr *);
6729 params->pserver_addr_set = true;
6730 break;
6732 daemon->uri_log_callback = va_arg (ap,
6733 LogCallback);
6734 daemon->uri_log_callback_cls = va_arg (ap,
6735 void *);
6736 break;
6738 daemon->insanity_level = (enum MHD_DisableSanityCheck)
6739 va_arg (ap,
6740 unsigned int);
6741 break;
6742#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6744 daemon->worker_pool_size = va_arg (ap,
6745 unsigned int);
6746 if (0 == daemon->worker_pool_size)
6747 {
6748 (void) 0; /* MHD_OPTION_THREAD_POOL_SIZE ignored, do nothing */
6749 }
6750 else if (1 == daemon->worker_pool_size)
6751 {
6752#ifdef HAVE_MESSAGES
6753 MHD_DLOG (daemon,
6754 _ ("Warning: value \"1\", specified as the thread pool " \
6755 "size, is ignored. Thread pool is not used.\n"));
6756#endif
6757 daemon->worker_pool_size = 0;
6758 }
6759#if SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2)
6760 /* Next comparison could be always false on some platforms and whole branch will
6761 * be optimized out on these platforms. On others it will be compiled into real
6762 * check. */
6763 else if (daemon->worker_pool_size >=
6764 (SIZE_MAX / sizeof (struct MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
6765 {
6766#ifdef HAVE_MESSAGES
6767 MHD_DLOG (daemon,
6768 _ ("Specified thread pool size (%u) too big.\n"),
6769 daemon->worker_pool_size);
6770#endif
6771 return MHD_NO;
6772 }
6773#endif /* SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2) */
6774 else
6775 {
6776 if (! MHD_D_IS_USING_THREADS_ (daemon))
6777 {
6778#ifdef HAVE_MESSAGES
6779 MHD_DLOG (daemon,
6780 _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
6781 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
6782#endif
6783 return MHD_NO;
6784 }
6786 {
6787#ifdef HAVE_MESSAGES
6788 MHD_DLOG (daemon,
6789 _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
6790 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
6791#endif
6792 return MHD_NO;
6793 }
6794 }
6795 break;
6796#endif
6797#ifdef HTTPS_SUPPORT
6799 pstr = va_arg (ap,
6800 const char *);
6801 if (0 != (daemon->options & MHD_USE_TLS))
6802 daemon->https_mem_key = pstr;
6803#ifdef HAVE_MESSAGES
6804 else
6805 MHD_DLOG (daemon,
6806 _ ("MHD HTTPS option %d passed to MHD but " \
6807 "MHD_USE_TLS not set.\n"),
6808 opt);
6809#endif
6810 break;
6812 pstr = va_arg (ap,
6813 const char *);
6814 if (0 != (daemon->options & MHD_USE_TLS))
6815 daemon->https_key_password = pstr;
6816#ifdef HAVE_MESSAGES
6817 else
6818 MHD_DLOG (daemon,
6819 _ ("MHD HTTPS option %d passed to MHD but " \
6820 "MHD_USE_TLS not set.\n"),
6821 opt);
6822#endif
6823 break;
6825 pstr = va_arg (ap,
6826 const char *);
6827 if (0 != (daemon->options & MHD_USE_TLS))
6828 daemon->https_mem_cert = pstr;
6829#ifdef HAVE_MESSAGES
6830 else
6831 MHD_DLOG (daemon,
6832 _ ("MHD HTTPS option %d passed to MHD but " \
6833 "MHD_USE_TLS not set.\n"),
6834 opt);
6835#endif
6836 break;
6838 pstr = va_arg (ap,
6839 const char *);
6840 if (0 != (daemon->options & MHD_USE_TLS))
6841 daemon->https_mem_trust = pstr;
6842#ifdef HAVE_MESSAGES
6843 else
6844 MHD_DLOG (daemon,
6845 _ ("MHD HTTPS option %d passed to MHD but " \
6846 "MHD_USE_TLS not set.\n"),
6847 opt);
6848#endif
6849 break;
6851 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
6852 int);
6853 break;
6855 pstr = va_arg (ap,
6856 const char *);
6857 if (0 != (daemon->options & MHD_USE_TLS))
6858 {
6859 gnutls_datum_t dhpar;
6860 size_t pstr_len;
6861
6862 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
6863 {
6864#ifdef HAVE_MESSAGES
6865 MHD_DLOG (daemon,
6866 _ ("Error initializing DH parameters.\n"));
6867#endif
6868 return MHD_NO;
6869 }
6870 dhpar.data = (unsigned char *) _MHD_DROP_CONST (pstr);
6871 pstr_len = strlen (pstr);
6872 if (UINT_MAX < pstr_len)
6873 {
6874#ifdef HAVE_MESSAGES
6875 MHD_DLOG (daemon,
6876 _ ("Diffie-Hellman parameters string too long.\n"));
6877#endif
6878 return MHD_NO;
6879 }
6880 dhpar.size = (unsigned int) pstr_len;
6881 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
6882 &dhpar,
6883 GNUTLS_X509_FMT_PEM) < 0)
6884 {
6885#ifdef HAVE_MESSAGES
6886 MHD_DLOG (daemon,
6887 _ ("Bad Diffie-Hellman parameters format.\n"));
6888#endif
6889 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6890 return MHD_NO;
6891 }
6892 daemon->have_dhparams = true;
6893 }
6894#ifdef HAVE_MESSAGES
6895 else
6896 MHD_DLOG (daemon,
6897 _ ("MHD HTTPS option %d passed to MHD but " \
6898 "MHD_USE_TLS not set.\n"),
6899 opt);
6900#endif
6901 break;
6904 pstr = va_arg (ap,
6905 const char *);
6906 if (0 != (daemon->options & MHD_USE_TLS))
6907 {
6908 if (NULL != daemon->priority_cache)
6909 gnutls_priority_deinit (daemon->priority_cache);
6910
6911 if (MHD_OPTION_HTTPS_PRIORITIES == opt)
6912 {
6913 int init_res;
6914 const char *err_pos;
6915 init_res = gnutls_priority_init (&daemon->priority_cache,
6916 pstr,
6917 &err_pos);
6918 if (GNUTLS_E_SUCCESS != init_res)
6919 {
6920#ifdef HAVE_MESSAGES
6921 MHD_DLOG (daemon,
6922 _ ("Setting priorities to '%s' failed: %s " \
6923 "The problematic part starts at: %s\n"),
6924 pstr,
6925 gnutls_strerror (init_res),
6926 err_pos);
6927#endif
6928 daemon->priority_cache = NULL;
6929 return MHD_NO;
6930 }
6931 }
6932 else
6933 {
6934 /* The cache has been deinited */
6935 daemon->priority_cache = NULL;
6936 if (! daemon_tls_priorities_init_append (daemon, pstr))
6937 return MHD_NO;
6938 }
6939 }
6940#ifdef HAVE_MESSAGES
6941 else
6942 MHD_DLOG (daemon,
6943 _ ("MHD HTTPS option %d passed to MHD but " \
6944 "MHD_USE_TLS not set.\n"),
6945 opt);
6946#endif
6947 break;
6949#if GNUTLS_VERSION_MAJOR < 3
6950#ifdef HAVE_MESSAGES
6951 MHD_DLOG (daemon,
6952 _ ("MHD_OPTION_HTTPS_CERT_CALLBACK requires building " \
6953 "MHD with GnuTLS >= 3.0.\n"));
6954#endif
6955 return MHD_NO;
6956#else
6957 pgcrf = va_arg (ap,
6958 gnutls_certificate_retrieve_function2 *);
6959 if (0 != (daemon->options & MHD_USE_TLS))
6960 daemon->cert_callback = pgcrf;
6961#ifdef HAVE_MESSAGES
6962 else
6963 MHD_DLOG (daemon,
6964 _ ("MHD HTTPS option %d passed to MHD but " \
6965 "MHD_USE_TLS not set.\n"),
6966 opt);
6967#endif /* HAVE_MESSAGES */
6968 break;
6969#endif
6971#if GNUTLS_VERSION_NUMBER < 0x030603
6972#ifdef HAVE_MESSAGES
6973 MHD_DLOG (daemon,
6974 _ ("MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building " \
6975 "MHD with GnuTLS >= 3.6.3.\n"));
6976#endif
6977 return MHD_NO;
6978#else
6979 pgcrf2 = va_arg (ap,
6980 gnutls_certificate_retrieve_function3 *);
6981 if (0 != (daemon->options & MHD_USE_TLS))
6982 daemon->cert_callback2 = pgcrf2;
6983#ifdef HAVE_MESSAGES
6984 else
6985 MHD_DLOG (daemon,
6986 _ ("MHD HTTPS option %d passed to MHD but " \
6987 "MHD_USE_TLS not set.\n"),
6988 opt);
6989#endif /* HAVE_MESSAGES */
6990 break;
6991#endif
6992#endif /* HTTPS_SUPPORT */
6993#ifdef DAUTH_SUPPORT
6996 daemon->digest_auth_rand_size = va_arg (ap,
6997 size_t);
6998 daemon->digest_auth_random = va_arg (ap,
6999 const char *);
7001 /* Set to some non-NULL value just to indicate that copy is required. */
7002 daemon->digest_auth_random_copy = daemon;
7003 else
7004 daemon->digest_auth_random_copy = NULL;
7005 break;
7007 daemon->nonce_nc_size = va_arg (ap,
7008 unsigned int);
7009 break;
7010 case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
7011 daemon->dauth_bind_type = va_arg (ap,
7012 unsigned int);
7013 if (0 != (daemon->dauth_bind_type & MHD_DAUTH_BIND_NONCE_URI_PARAMS))
7014 daemon->dauth_bind_type |= MHD_DAUTH_BIND_NONCE_URI;
7015 break;
7017 if (1)
7018 {
7019 unsigned int val;
7020 val = va_arg (ap,
7021 unsigned int);
7022 if (0 != val)
7023 daemon->dauth_def_nonce_timeout = val;
7024 }
7025 break;
7027 if (1)
7028 {
7029 uint32_t val;
7030 val = va_arg (ap,
7031 uint32_t);
7032 if (0 != val)
7033 daemon->dauth_def_max_nc = val;
7034 }
7035 break;
7036#else /* ! DAUTH_SUPPORT */
7040 case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
7043#ifdef HAVE_MESSAGES
7044 MHD_DLOG (daemon,
7045 _ ("Digest Auth is disabled for this build " \
7046 "of GNU libmicrohttpd.\n"));
7047#endif /* HAVE_MESSAGES */
7048 return MHD_NO;
7049#endif /* ! DAUTH_SUPPORT */
7051 params->listen_fd = va_arg (ap,
7052 MHD_socket);
7053 params->listen_fd_set = true;
7054 break;
7056#ifdef HAVE_MESSAGES
7057 daemon->custom_error_log = va_arg (ap,
7059 daemon->custom_error_log_cls = va_arg (ap,
7060 void *);
7061 if (1 != params->num_opts)
7062 MHD_DLOG (daemon,
7063 _ ("MHD_OPTION_EXTERNAL_LOGGER is not the first option "
7064 "specified for the daemon. Some messages may be "
7065 "printed by the standard MHD logger.\n"));
7066
7067#else
7068 (void) va_arg (ap,
7070 (void) va_arg (ap,
7071 void *);
7072#endif
7073 break;
7074#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7076 daemon->thread_stack_size = va_arg (ap,
7077 size_t);
7078 break;
7079#endif
7081#ifdef TCP_FASTOPEN
7082 daemon->fastopen_queue_size = va_arg (ap,
7083 unsigned int);
7084 break;
7085#else /* ! TCP_FASTOPEN */
7086#ifdef HAVE_MESSAGES
7087 MHD_DLOG (daemon,
7088 _ ("TCP fastopen is not supported on this platform.\n"));
7089#endif /* HAVE_MESSAGES */
7090 return MHD_NO;
7091#endif /* ! TCP_FASTOPEN */
7093 daemon->listening_address_reuse = va_arg (ap,
7094 unsigned int) ? 1 : -1;
7095 break;
7097 daemon->listen_backlog_size = va_arg (ap,
7098 unsigned int);
7099 break;
7101 daemon->client_discipline = va_arg (ap, int); /* Temporal assignment */
7102 /* Map to correct value */
7103 if (-1 >= daemon->client_discipline)
7104 daemon->client_discipline = -3;
7105 else if (1 <= daemon->client_discipline)
7106 daemon->client_discipline = 1;
7107#ifdef HAVE_MESSAGES
7108 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
7109 (1 != daemon->client_discipline) )
7110 {
7111 MHD_DLOG (daemon,
7112 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
7113 "another behaviour is specified by "
7114 "MHD_OPTION_STRICT_CLIENT.\n"));
7115 }
7116#endif /* HAVE_MESSAGES */
7117 break;
7119 daemon->client_discipline = va_arg (ap, int);
7120#ifdef HAVE_MESSAGES
7121 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
7122 (1 != daemon->client_discipline) )
7123 {
7124 MHD_DLOG (daemon,
7125 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
7126 "another behaviour is specified by "
7127 "MHD_OPTION_CLIENT_DISCIPLINE_LVL.\n"));
7128 }
7129#endif /* HAVE_MESSAGES */
7130 break;
7132 daemon->allow_bzero_in_url = va_arg (ap, int);
7133 if ((0 > daemon->allow_bzero_in_url) ||
7134 (2 < daemon->allow_bzero_in_url))
7135 daemon->allow_bzero_in_url = 1;
7136 break;
7137 case MHD_OPTION_ARRAY:
7138 params->num_opts--; /* Do not count MHD_OPTION_ARRAY */
7139 oa = va_arg (ap, struct MHD_OptionItem *);
7140 i = 0;
7141 while (MHD_OPTION_END != (opt = oa[i].option))
7142 {
7143 switch (opt)
7144 {
7145 /* all options taking 'size_t' */
7149 if (MHD_NO == parse_options (daemon,
7150 params,
7151 opt,
7152 (size_t) oa[i].value,
7154 return MHD_NO;
7155 break;
7156 /* all options taking 'unsigned int' */
7166 case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
7168 if (MHD_NO == parse_options (daemon,
7169 params,
7170 opt,
7171 (unsigned int) oa[i].value,
7173 return MHD_NO;
7174 break;
7175 /* all options taking 'enum' */
7177#ifdef HTTPS_SUPPORT
7178 if (MHD_NO == parse_options (daemon,
7179 params,
7180 opt,
7181 (gnutls_credentials_type_t) oa[i].value,
7183#endif /* HTTPS_SUPPORT */
7184 return MHD_NO;
7185 break;
7186 /* all options taking 'MHD_socket' */
7188 if (MHD_NO == parse_options (daemon,
7189 params,
7190 opt,
7191 (MHD_socket) oa[i].value,
7193 return MHD_NO;
7194 break;
7195 /* all options taking 'int' */
7202 if (MHD_NO == parse_options (daemon,
7203 params,
7204 opt,
7205 (int) oa[i].value,
7207 return MHD_NO;
7208 break;
7209 /* all options taking 'uint32_t' */
7211 if (MHD_NO == parse_options (daemon,
7212 params,
7213 opt,
7214 (uint32_t) oa[i].value,
7216 return MHD_NO;
7217 break;
7218 /* all options taking one pointer */
7227 case MHD_OPTION_ARRAY:
7230 if (MHD_NO == parse_options (daemon,
7231 params,
7232 opt,
7233 oa[i].ptr_value,
7235 return MHD_NO;
7236 break;
7237 /* all options taking two pointers */
7244 if (MHD_NO == parse_options (daemon,
7245 params,
7246 opt,
7247 (void *) oa[i].value,
7248 oa[i].ptr_value,
7250 return MHD_NO;
7251 break;
7252 /* options taking size_t-number followed by pointer */
7255 if (MHD_NO == parse_options (daemon,
7256 params,
7257 opt,
7258 (size_t) oa[i].value,
7259 oa[i].ptr_value,
7261 return MHD_NO;
7262 break;
7263 /* options taking socklen_t-number followed by pointer */
7265 if (MHD_NO == parse_options (daemon,
7266 params,
7267 opt,
7268 (socklen_t) oa[i].value,
7269 oa[i].ptr_value,
7271 return MHD_NO;
7272 break;
7273 case MHD_OPTION_END: /* Not possible */
7274 default:
7275 return MHD_NO;
7276 }
7277 i++;
7278 }
7279 break;
7281 daemon->unescape_callback = va_arg (ap,
7283 daemon->unescape_callback_cls = va_arg (ap,
7284 void *);
7285 break;
7286#ifdef HTTPS_SUPPORT
7288#if GNUTLS_VERSION_MAJOR >= 3
7289 daemon->cred_callback = va_arg (ap,
7291 daemon->cred_callback_cls = va_arg (ap,
7292 void *);
7293 break;
7294#else
7295 MHD_DLOG (daemon,
7296 _ ("MHD HTTPS option %d passed to MHD compiled " \
7297 "without GNUtls >= 3.\n"),
7298 opt);
7299 return MHD_NO;
7300#endif
7301#endif /* HTTPS_SUPPORT */
7303 if (! MHD_D_IS_USING_THREADS_ (daemon))
7304 daemon->sigpipe_blocked = ( (va_arg (ap,
7305 int)) != 0);
7306 else
7307 {
7308 (void) va_arg (ap,
7309 int);
7310 }
7311 break;
7313#ifdef HTTPS_SUPPORT
7314 daemon->disable_alpn = (va_arg (ap,
7315 int) != 0);
7316#else /* ! HTTPS_SUPPORT */
7317 (void) va_arg (ap, int);
7318#endif /* ! HTTPS_SUPPORT */
7319#ifdef HAVE_MESSAGES
7320 if (0 == (daemon->options & MHD_USE_TLS))
7321 MHD_DLOG (daemon,
7322 _ ("MHD HTTPS option %d passed to MHD " \
7323 "but MHD_USE_TLS not set.\n"),
7324 (int) opt);
7325#endif /* HAVE_MESSAGES */
7326 break;
7328 params->fdset_size_set = true;
7329 params->fdset_size = va_arg (ap,
7330 int);
7331 break;
7332#ifndef HTTPS_SUPPORT
7344#ifdef HAVE_MESSAGES
7345 MHD_DLOG (daemon,
7346 _ ("MHD HTTPS option %d passed to MHD "
7347 "compiled without HTTPS support.\n"),
7348 opt);
7349#endif
7350 return MHD_NO;
7351#endif /* HTTPS_SUPPORT */
7352 case MHD_OPTION_END: /* Not possible */
7353 default:
7354#ifdef HAVE_MESSAGES
7355 MHD_DLOG (daemon,
7356 _ ("Invalid option %d! (Did you terminate "
7357 "the list with MHD_OPTION_END?).\n"),
7358 opt);
7359#endif
7360 return MHD_NO;
7361 }
7362 }
7363 return MHD_YES;
7364}
7365
7366
7367#ifdef EPOLL_SUPPORT
7368static int
7369setup_epoll_fd (struct MHD_Daemon *daemon)
7370{
7371 int fd;
7372
7373#ifndef HAVE_MESSAGES
7374 (void) daemon; /* Mute compiler warning. */
7375#endif /* ! HAVE_MESSAGES */
7376
7377#ifdef USE_EPOLL_CREATE1
7378 fd = epoll_create1 (EPOLL_CLOEXEC);
7379#else /* ! USE_EPOLL_CREATE1 */
7380 fd = epoll_create (MAX_EVENTS);
7381#endif /* ! USE_EPOLL_CREATE1 */
7382 if (MHD_INVALID_SOCKET == fd)
7383 {
7384#ifdef HAVE_MESSAGES
7385 MHD_DLOG (daemon,
7386 _ ("Call to epoll_create1 failed: %s\n"),
7388#endif
7389 return MHD_INVALID_SOCKET;
7390 }
7391#if ! defined(USE_EPOLL_CREATE1)
7393 {
7394#ifdef HAVE_MESSAGES
7395 MHD_DLOG (daemon,
7396 _ ("Failed to set noninheritable mode on epoll FD.\n"));
7397#endif
7398 }
7399#endif /* ! USE_EPOLL_CREATE1 */
7400 return fd;
7401}
7402
7403
7412static enum MHD_Result
7413setup_epoll_to_listen (struct MHD_Daemon *daemon)
7414{
7415 struct epoll_event event;
7416 MHD_socket ls;
7417
7420 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
7421 (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) || \
7422 MHD_ITC_IS_VALID_ (daemon->itc) );
7423 daemon->epoll_fd = setup_epoll_fd (daemon);
7424 if (! MHD_D_IS_USING_THREADS_ (daemon)
7425 && (0 != (daemon->options & MHD_USE_AUTO)))
7426 {
7427 /* Application requested "MHD_USE_AUTO", probably MHD_get_fdset() will be
7428 used.
7429 Make sure that epoll FD is suitable for fd_set.
7430 Actually, MHD_get_fdset() is allowed for MHD_USE_EPOLL direct,
7431 but most probably direct requirement for MHD_USE_EPOLL means that
7432 epoll FD will be used directly. This logic is fuzzy, but better
7433 than nothing with current MHD API. */
7434 if (! MHD_D_DOES_SCKT_FIT_FDSET_ (daemon->epoll_fd, daemon))
7435 {
7436#ifdef HAVE_MESSAGES
7437 MHD_DLOG (daemon,
7438 _ ("The epoll FD is too large to be used with fd_set.\n"));
7439#endif /* HAVE_MESSAGES */
7440 return MHD_NO;
7441 }
7442 }
7443 if (-1 == daemon->epoll_fd)
7444 return MHD_NO;
7445#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7446 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
7447 {
7448 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
7449 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
7450 return MHD_NO;
7451 }
7452#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7453 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
7454 (! daemon->was_quiesced) )
7455 {
7456 event.events = EPOLLIN | EPOLLRDHUP;
7457 event.data.ptr = daemon;
7458 if (0 != epoll_ctl (daemon->epoll_fd,
7459 EPOLL_CTL_ADD,
7460 ls,
7461 &event))
7462 {
7463#ifdef HAVE_MESSAGES
7464 MHD_DLOG (daemon,
7465 _ ("Call to epoll_ctl failed: %s\n"),
7467#endif
7468 return MHD_NO;
7469 }
7470 daemon->listen_socket_in_epoll = true;
7471 }
7472
7473 if (MHD_ITC_IS_VALID_ (daemon->itc))
7474 {
7475 event.events = EPOLLIN | EPOLLRDHUP;
7476 event.data.ptr = _MHD_DROP_CONST (epoll_itc_marker);
7477 if (0 != epoll_ctl (daemon->epoll_fd,
7478 EPOLL_CTL_ADD,
7479 MHD_itc_r_fd_ (daemon->itc),
7480 &event))
7481 {
7482#ifdef HAVE_MESSAGES
7483 MHD_DLOG (daemon,
7484 _ ("Call to epoll_ctl failed: %s\n"),
7486#endif
7487 return MHD_NO;
7488 }
7489 }
7490 return MHD_YES;
7491}
7492
7493
7494#endif
7495
7496
7508static bool
7510 const struct sockaddr **ppsockaddr,
7511 socklen_t *psockaddr_len,
7512 struct MHD_InterimParams_ *params)
7513{
7514 if (params->fdset_size_set)
7515 {
7516 if (0 >= params->fdset_size)
7517 {
7518#ifdef HAVE_MESSAGES
7519 MHD_DLOG (d,
7520 _ ("MHD_OPTION_APP_FD_SETSIZE value (%d) is not positive.\n"),
7521 params->fdset_size);
7522#endif /* HAVE_MESSAGES */
7523 return false;
7524 }
7526 {
7527#ifdef HAVE_MESSAGES
7528 MHD_DLOG (d,
7529 _ ("MHD_OPTION_APP_FD_SETSIZE is ignored for daemon started " \
7530 "with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
7531#endif /* HAVE_MESSAGES */
7532 (void) 0;
7533 }
7534 else if (MHD_D_IS_USING_POLL_ (d))
7535 {
7536#ifdef HAVE_MESSAGES
7537 MHD_DLOG (d,
7538 _ ("MHD_OPTION_APP_FD_SETSIZE is ignored for daemon started " \
7539 "with MHD_USE_POLL.\n"));
7540#endif /* HAVE_MESSAGES */
7541 (void) 0;
7542 }
7543 else
7544 { /* The daemon without internal threads, external sockets polling */
7545#ifndef HAS_FD_SETSIZE_OVERRIDABLE
7546 if (((int) FD_SETSIZE) != params->fdset_size)
7547 {
7548#ifdef HAVE_MESSAGES
7549 MHD_DLOG (d,
7550 _ ("MHD_OPTION_APP_FD_SETSIZE value (%d) does not match " \
7551 "the platform FD_SETSIZE value (%d) and this platform " \
7552 "does not support overriding of FD_SETSIZE.\n"),
7553 params->fdset_size, (int) FD_SETSIZE);
7554#endif /* HAVE_MESSAGES */
7555 return false;
7556 }
7557#else /* HAS_FD_SETSIZE_OVERRIDABLE */
7558 d->fdset_size = params->fdset_size;
7559 d->fdset_size_set_by_app = true;
7560#endif /* HAS_FD_SETSIZE_OVERRIDABLE */
7561 }
7562 }
7563
7564 if (params->listen_fd_set)
7565 {
7566 if (MHD_INVALID_SOCKET == params->listen_fd)
7567 {
7568 (void) 0; /* Use MHD-created socket */
7569 }
7570#ifdef HAS_SIGNED_SOCKET
7571 else if (0 > params->listen_fd)
7572 {
7573#ifdef HAVE_MESSAGES
7574 MHD_DLOG (d,
7575 _ ("The value provided for MHD_OPTION_LISTEN_SOCKET " \
7576 "is invalid.\n"));
7577#endif /* HAVE_MESSAGES */
7578 return false;
7579 }
7580#endif /* HAS_SIGNED_SOCKET */
7581 else if (0 != (d->options & MHD_USE_NO_LISTEN_SOCKET))
7582 {
7583#ifdef HAVE_MESSAGES
7584 MHD_DLOG (d,
7585 _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
7586 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
7587#endif /* HAVE_MESSAGES */
7588 (void) MHD_socket_close_ (params->listen_fd);
7589 return false;
7590 }
7591 else
7592 {
7593 d->listen_fd = params->listen_fd;
7595#ifdef MHD_USE_GETSOCKNAME
7596 d->port = 0; /* Force use of autodetection */
7597#endif /* MHD_USE_GETSOCKNAME */
7598 }
7599 }
7600
7601 mhd_assert (! params->server_addr_len_set || params->pserver_addr_set);
7602 if (params->pserver_addr_set)
7603 {
7604 if (NULL == params->pserver_addr)
7605 {
7606 /* The size must be zero if set */
7607 if (params->server_addr_len_set && (0 != params->server_addr_len))
7608 return false;
7609 /* Ignore parameter if it is NULL */
7610 }
7611 else if (MHD_INVALID_SOCKET != d->listen_fd)
7612 {
7613#ifdef HAVE_MESSAGES
7614 MHD_DLOG (d,
7615 _ ("MHD_OPTION_LISTEN_SOCKET cannot be used together with " \
7616 "MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR.\n"));
7617#endif /* HAVE_MESSAGES */
7618 return false;
7619 }
7620 else if (0 != (d->options & MHD_USE_NO_LISTEN_SOCKET))
7621 {
7622#ifdef HAVE_MESSAGES
7623 MHD_DLOG (d,
7624 _ ("MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR " \
7625 "specified for daemon with MHD_USE_NO_LISTEN_SOCKET " \
7626 "flag set.\n"));
7627#endif /* HAVE_MESSAGES */
7628 if (MHD_INVALID_SOCKET != d->listen_fd)
7629 {
7630 (void) MHD_socket_close_ (params->listen_fd);
7631 params->listen_fd = MHD_INVALID_SOCKET;
7632 }
7633 return false;
7634 }
7635 else
7636 {
7637 *ppsockaddr = params->pserver_addr;
7638 if (params->server_addr_len_set)
7639 {
7640 /* The size must be non-zero if set */
7641 if (0 == params->server_addr_len)
7642 return false;
7643 *psockaddr_len = params->server_addr_len;
7644 }
7645 else
7646 *psockaddr_len = 0;
7647 }
7648 }
7649 return true;
7650}
7651
7652
7674_MHD_EXTERN struct MHD_Daemon *
7675MHD_start_daemon_va (unsigned int flags,
7676 uint16_t port,
7678 void *apc_cls,
7680 void *dh_cls,
7681 va_list ap)
7682{
7683 const MHD_SCKT_OPT_BOOL_ on = 1;
7684 struct MHD_Daemon *daemon;
7685 const struct sockaddr *pservaddr = NULL;
7686 socklen_t addrlen;
7687#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7688 unsigned int i;
7689#endif
7690 enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
7691 enum MHD_FLAG *pflags;
7692 struct MHD_InterimParams_ *interim_params;
7693
7695 eflags = (enum MHD_FLAG) flags;
7696 pflags = &eflags;
7697
7698 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
7699 *pflags |= MHD_USE_INTERNAL_POLLING_THREAD; /* Force enable, log warning later if needed */
7700
7701#ifndef HAVE_INET6
7702 if (0 != (*pflags & MHD_USE_IPv6))
7703 return NULL;
7704#endif
7705#ifndef HAVE_POLL
7706 if (0 != (*pflags & MHD_USE_POLL))
7707 return NULL;
7708#endif
7709#ifndef EPOLL_SUPPORT
7710 if (0 != (*pflags & MHD_USE_EPOLL))
7711 return NULL;
7712#endif /* ! EPOLL_SUPPORT */
7713#ifndef HTTPS_SUPPORT
7714 if (0 != (*pflags & MHD_USE_TLS))
7715 return NULL;
7716#endif /* ! HTTPS_SUPPORT */
7717#ifndef TCP_FASTOPEN
7718 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
7719 return NULL;
7720#endif
7721 if (0 != (*pflags & MHD_ALLOW_UPGRADE))
7722 {
7723#ifdef UPGRADE_SUPPORT
7724 *pflags |= MHD_ALLOW_SUSPEND_RESUME;
7725#else /* ! UPGRADE_SUPPORT */
7726 return NULL;
7727#endif /* ! UPGRADE_SUPPORT */
7728 }
7729#ifdef MHD_USE_THREADS
7732 & *pflags))
7733 return NULL; /* Cannot be thread-unsafe with multiple threads */
7734#else /* ! MHD_USE_THREADS */
7735 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7736 return NULL;
7737#endif /* ! MHD_USE_THREADS */
7738
7739 if (NULL == dh)
7740 return NULL;
7741
7742 /* Check for invalid combinations of flags. */
7743 if ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL)))
7744 return NULL;
7745 if ((0 != (*pflags & MHD_USE_EPOLL)) &&
7746 (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)))
7747 return NULL;
7748 if ((0 != (*pflags & MHD_USE_POLL)) &&
7749 (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
7751 return NULL;
7752 if ((0 != (*pflags & MHD_USE_AUTO)) &&
7753 (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))))
7754 return NULL;
7755
7756 if (0 != (*pflags & MHD_USE_AUTO))
7757 {
7758#if defined(EPOLL_SUPPORT) && defined(HAVE_POLL)
7759 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
7760 *pflags |= MHD_USE_POLL;
7761 else
7762 *pflags |= MHD_USE_EPOLL; /* Including "external select" mode */
7763#elif defined(HAVE_POLL)
7764 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7765 *pflags |= MHD_USE_POLL; /* Including thread-per-connection */
7766#elif defined(EPOLL_SUPPORT)
7767 if (0 == (*pflags & MHD_USE_THREAD_PER_CONNECTION))
7768 *pflags |= MHD_USE_EPOLL; /* Including "external select" mode */
7769#else
7770 /* No choice: use select() for any mode - do not modify flags */
7771#endif
7772 }
7773
7774 if (0 != (*pflags & MHD_USE_NO_THREAD_SAFETY))
7775 *pflags = (*pflags & ~((enum MHD_FLAG) MHD_USE_ITC)); /* useless in single-threaded environment */
7776 else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7777 {
7778#ifdef HAVE_LISTEN_SHUTDOWN
7779 if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
7780#endif
7781 *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
7782 }
7783
7784 if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
7785 return NULL;
7786 interim_params = (struct MHD_InterimParams_ *) \
7787 MHD_calloc_ (1, sizeof (struct MHD_InterimParams_));
7788 if (NULL == interim_params)
7789 {
7790 int err_num = errno;
7791 free (daemon);
7792 errno = err_num;
7793 return NULL;
7794 }
7795#ifdef EPOLL_SUPPORT
7796 daemon->epoll_fd = -1;
7797#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7798 daemon->epoll_upgrade_fd = -1;
7799#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7800#endif
7801 /* try to open listen socket */
7802#ifdef HTTPS_SUPPORT
7803 daemon->priority_cache = NULL;
7804#endif /* HTTPS_SUPPORT */
7805 daemon->listen_fd = MHD_INVALID_SOCKET;
7806 daemon->listen_is_unix = _MHD_NO;
7807 daemon->listening_address_reuse = 0;
7808 daemon->options = *pflags;
7809 pflags = &daemon->options;
7810 daemon->client_discipline = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ?
7811 1 : 0;
7812 daemon->port = port;
7813 daemon->apc = apc;
7814 daemon->apc_cls = apc_cls;
7815 daemon->default_handler = dh;
7816 daemon->default_handler_cls = dh_cls;
7817 daemon->connections = 0;
7822 daemon->connection_timeout_ms = 0; /* no timeout */
7823 MHD_itc_set_invalid_ (daemon->itc);
7824#ifdef MHD_USE_THREADS
7825 MHD_thread_handle_ID_set_invalid_ (&daemon->tid);
7826#endif /* MHD_USE_THREADS */
7827#ifdef SOMAXCONN
7828 daemon->listen_backlog_size = SOMAXCONN;
7829#else /* !SOMAXCONN */
7830 daemon->listen_backlog_size = 511; /* should be safe value */
7831#endif /* !SOMAXCONN */
7832#ifdef HAVE_MESSAGES
7833 daemon->custom_error_log = &MHD_default_logger_;
7834 daemon->custom_error_log_cls = stderr;
7835#endif
7836#ifndef MHD_WINSOCK_SOCKETS
7837 daemon->sigpipe_blocked = false;
7838#else /* MHD_WINSOCK_SOCKETS */
7839 /* There is no SIGPIPE on W32, nothing to block. */
7840 daemon->sigpipe_blocked = true;
7841#endif /* _WIN32 && ! __CYGWIN__ */
7842#if defined(_DEBUG) && defined(HAVE_ACCEPT4)
7843 daemon->avoid_accept4 = false;
7844#endif /* _DEBUG */
7845#ifdef HAS_FD_SETSIZE_OVERRIDABLE
7846 daemon->fdset_size = (int) FD_SETSIZE;
7847 daemon->fdset_size_set_by_app = false;
7848#endif /* HAS_FD_SETSIZE_OVERRIDABLE */
7849
7850#ifdef DAUTH_SUPPORT
7851 daemon->digest_auth_rand_size = 0;
7852 daemon->digest_auth_random = NULL;
7853 daemon->nonce_nc_size = 4; /* tiny */
7854 daemon->dauth_def_nonce_timeout = MHD_DAUTH_DEF_TIMEOUT_;
7855 daemon->dauth_def_max_nc = MHD_DAUTH_DEF_MAX_NC_;
7856#endif
7857#ifdef HTTPS_SUPPORT
7858 if (0 != (*pflags & MHD_USE_TLS))
7859 {
7860 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
7861 }
7862#endif /* HTTPS_SUPPORT */
7863
7864 interim_params->num_opts = 0;
7865 interim_params->fdset_size_set = false;
7866 interim_params->fdset_size = 0;
7867 interim_params->listen_fd_set = false;
7868 interim_params->listen_fd = MHD_INVALID_SOCKET;
7869 interim_params->pserver_addr_set = false;
7870 interim_params->pserver_addr = NULL;
7871 interim_params->server_addr_len_set = false;
7872 interim_params->server_addr_len = 0;
7873
7874 if (MHD_NO == parse_options_va (daemon,
7875 interim_params,
7876 ap))
7877 {
7878#ifdef HTTPS_SUPPORT
7879 if ( (0 != (*pflags & MHD_USE_TLS)) &&
7880 (NULL != daemon->priority_cache) )
7881 gnutls_priority_deinit (daemon->priority_cache);
7882#endif /* HTTPS_SUPPORT */
7883 free (interim_params);
7884 free (daemon);
7885 return NULL;
7886 }
7887 if (! process_interim_params (daemon,
7888 &pservaddr,
7889 &addrlen,
7890 interim_params))
7891 {
7892 free (interim_params);
7893 free (daemon);
7894 return NULL;
7895 }
7896 free (interim_params);
7897 interim_params = NULL;
7898#ifdef HTTPS_SUPPORT
7899 if ((0 != (*pflags & MHD_USE_TLS))
7900 && (NULL == daemon->priority_cache)
7901 && ! daemon_tls_priorities_init_default (daemon))
7902 {
7903#ifdef HAVE_MESSAGES
7904 MHD_DLOG (daemon,
7905 _ ("Failed to initialise GnuTLS priorities.\n"));
7906#endif /* HAVE_MESSAGES */
7907 free (daemon);
7908 return NULL;
7909 }
7910#endif /* HTTPS_SUPPORT */
7911
7912#ifdef HAVE_MESSAGES
7913 if ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) &&
7914 (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD)) )
7915 {
7916 MHD_DLOG (daemon,
7917 _ ("Warning: MHD_USE_THREAD_PER_CONNECTION must be used " \
7918 "only with MHD_USE_INTERNAL_POLLING_THREAD. " \
7919 "Flag MHD_USE_INTERNAL_POLLING_THREAD was added. " \
7920 "Consider setting MHD_USE_INTERNAL_POLLING_THREAD " \
7921 "explicitly.\n"));
7922 }
7923#endif
7924
7926 && ((NULL != daemon->notify_completed)
7927 || (NULL != daemon->notify_connection)) )
7928 *pflags |= MHD_USE_ITC; /* requires ITC */
7929
7930#ifdef _DEBUG
7931#ifdef HAVE_MESSAGES
7932 MHD_DLOG (daemon,
7933 _ ("Using debug build of libmicrohttpd.\n") );
7934#endif /* HAVE_MESSAGES */
7935#endif /* _DEBUG */
7936
7937 if ( (0 != (*pflags & MHD_USE_ITC))
7938#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7939 && (0 == daemon->worker_pool_size)
7940#endif
7941 )
7942 {
7943 if (! MHD_itc_init_ (daemon->itc))
7944 {
7945#ifdef HAVE_MESSAGES
7946 MHD_DLOG (daemon,
7947 _ ("Failed to create inter-thread communication channel: %s\n"),
7948 MHD_itc_last_strerror_ ());
7949#endif
7950#ifdef HTTPS_SUPPORT
7951 if (NULL != daemon->priority_cache)
7952 gnutls_priority_deinit (daemon->priority_cache);
7953#endif /* HTTPS_SUPPORT */
7954 free (daemon);
7955 return NULL;
7956 }
7957 if (MHD_D_IS_USING_SELECT_ (daemon) &&
7958 (! MHD_D_DOES_SCKT_FIT_FDSET_ (MHD_itc_r_fd_ (daemon->itc), daemon)) )
7959 {
7960#ifdef HAVE_MESSAGES
7961 MHD_DLOG (daemon,
7962 _ ("file descriptor for inter-thread communication " \
7963 "channel exceeds maximum value.\n"));
7964#endif
7965 MHD_itc_destroy_chk_ (daemon->itc);
7966#ifdef HTTPS_SUPPORT
7967 if (NULL != daemon->priority_cache)
7968 gnutls_priority_deinit (daemon->priority_cache);
7969#endif /* HTTPS_SUPPORT */
7970 free (daemon);
7971 return NULL;
7972 }
7973 }
7974
7975#ifdef DAUTH_SUPPORT
7976 if (NULL != daemon->digest_auth_random_copy)
7977 {
7978 mhd_assert (daemon == daemon->digest_auth_random_copy);
7979 daemon->digest_auth_random_copy = malloc (daemon->digest_auth_rand_size);
7980 if (NULL == daemon->digest_auth_random_copy)
7981 {
7982#ifdef HTTPS_SUPPORT
7983 if (0 != (*pflags & MHD_USE_TLS))
7984 gnutls_priority_deinit (daemon->priority_cache);
7985#endif /* HTTPS_SUPPORT */
7986 free (daemon);
7987 return NULL;
7988 }
7989 memcpy (daemon->digest_auth_random_copy,
7990 daemon->digest_auth_random,
7991 daemon->digest_auth_rand_size);
7992 daemon->digest_auth_random = daemon->digest_auth_random_copy;
7993 }
7994 if (daemon->nonce_nc_size > 0)
7995 {
7996 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
7997 / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
7998 {
7999#ifdef HAVE_MESSAGES
8000 MHD_DLOG (daemon,
8001 _ ("Specified value for NC_SIZE too large.\n"));
8002#endif
8003#ifdef HTTPS_SUPPORT
8004 if (0 != (*pflags & MHD_USE_TLS))
8005 gnutls_priority_deinit (daemon->priority_cache);
8006#endif /* HTTPS_SUPPORT */
8007 free (daemon->digest_auth_random_copy);
8008 free (daemon);
8009 return NULL;
8010 }
8011 daemon->nnc = MHD_calloc_ (daemon->nonce_nc_size,
8012 sizeof (struct MHD_NonceNc));
8013 if (NULL == daemon->nnc)
8014 {
8015#ifdef HAVE_MESSAGES
8016 MHD_DLOG (daemon,
8017 _ ("Failed to allocate memory for nonce-nc map: %s\n"),
8018 MHD_strerror_ (errno));
8019#endif
8020#ifdef HTTPS_SUPPORT
8021 if (0 != (*pflags & MHD_USE_TLS))
8022 gnutls_priority_deinit (daemon->priority_cache);
8023#endif /* HTTPS_SUPPORT */
8024 free (daemon->digest_auth_random_copy);
8025 free (daemon);
8026 return NULL;
8027 }
8028 }
8029
8030#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8031 if (! MHD_mutex_init_ (&daemon->nnc_lock))
8032 {
8033#ifdef HAVE_MESSAGES
8034 MHD_DLOG (daemon,
8035 _ ("MHD failed to initialize nonce-nc mutex.\n"));
8036#endif
8037#ifdef HTTPS_SUPPORT
8038 if (0 != (*pflags & MHD_USE_TLS))
8039 gnutls_priority_deinit (daemon->priority_cache);
8040#endif /* HTTPS_SUPPORT */
8041 free (daemon->digest_auth_random_copy);
8042 free (daemon->nnc);
8043 free (daemon);
8044 return NULL;
8045 }
8046#endif
8047#endif
8048
8049 /* Thread polling currently works only with internal select thread mode */
8050#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8051 if ( (! MHD_D_IS_USING_THREADS_ (daemon)) &&
8052 (daemon->worker_pool_size > 0) )
8053 {
8054#ifdef HAVE_MESSAGES
8055 MHD_DLOG (daemon,
8056 _ ("MHD thread polling only works with " \
8057 "MHD_USE_INTERNAL_POLLING_THREAD.\n"));
8058#endif
8059 goto free_and_fail;
8060 }
8061#endif
8062
8063 if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
8064 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
8065 {
8066 /* try to open listen socket */
8067 struct sockaddr_in servaddr4;
8068#ifdef HAVE_INET6
8069 struct sockaddr_in6 servaddr6;
8070 const bool use_ipv6 = (0 != (*pflags & MHD_USE_IPv6));
8071#else /* ! HAVE_INET6 */
8072 const bool use_ipv6 = false;
8073#endif /* ! HAVE_INET6 */
8074 int domain;
8075
8076 if (NULL != pservaddr)
8077 {
8078#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8079 const socklen_t sa_len = pservaddr->sa_len;
8080#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8081#ifdef HAVE_INET6
8082 if (use_ipv6 && (AF_INET6 != pservaddr->sa_family))
8083 {
8084#ifdef HAVE_MESSAGES
8085 MHD_DLOG (daemon,
8086 _ ("MHD_USE_IPv6 is enabled, but 'struct sockaddr *' " \
8087 "specified for MHD_OPTION_SOCK_ADDR_LEN or " \
8088 "MHD_OPTION_SOCK_ADDR is not IPv6 address.\n"));
8089#endif /* HAVE_MESSAGES */
8090 goto free_and_fail;
8091 }
8092#endif /* HAVE_INET6 */
8093 switch (pservaddr->sa_family)
8094 {
8095 case AF_INET:
8096 if (1)
8097 {
8098 struct sockaddr_in sa4;
8099 uint16_t sa4_port;
8100 if ((0 != addrlen)
8101 && (((socklen_t) sizeof(sa4)) > addrlen))
8102 {
8103#ifdef HAVE_MESSAGES
8104 MHD_DLOG (daemon,
8105 _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
8106 "option is wrong.\n"));
8107#endif /* HAVE_MESSAGES */
8108 goto free_and_fail;
8109 }
8110#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8111 if (0 != sa_len)
8112 {
8113 if (((socklen_t) sizeof(sa4)) > sa_len)
8114 {
8115#ifdef HAVE_MESSAGES
8116 MHD_DLOG (daemon,
8117 _ ("The value of 'struct sockaddr.sa_len' provided " \
8118 "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
8119 "and does not match 'sa_family' value of the " \
8120 "same structure.\n"));
8121#endif /* HAVE_MESSAGES */
8122 goto free_and_fail;
8123 }
8124 if ((0 == addrlen) || (sa_len < addrlen))
8125 addrlen = sa_len; /* Use smaller value for safety */
8126 }
8127#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8128 if (0 == addrlen)
8129 addrlen = sizeof(sa4);
8130 memcpy (&sa4, pservaddr, sizeof(sa4)); /* Required due to stronger alignment */
8131 sa4_port = (uint16_t) ntohs (sa4.sin_port);
8132#ifndef MHD_USE_GETSOCKNAME
8133 if (0 != sa4_port)
8134#endif /* ! MHD_USE_GETSOCKNAME */
8135 daemon->port = sa4_port;
8136 domain = PF_INET;
8137 }
8138 break;
8139#ifdef HAVE_INET6
8140 case AF_INET6:
8141 if (1)
8142 {
8143 struct sockaddr_in6 sa6;
8144 uint16_t sa6_port;
8145 if ((0 != addrlen)
8146 && (((socklen_t) sizeof(sa6)) > addrlen))
8147 {
8148#ifdef HAVE_MESSAGES
8149 MHD_DLOG (daemon,
8150 _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
8151 "option is wrong.\n"));
8152#endif /* HAVE_MESSAGES */
8153 goto free_and_fail;
8154 }
8155#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8156 if (0 != sa_len)
8157 {
8158 if (((socklen_t) sizeof(sa6)) > sa_len)
8159 {
8160#ifdef HAVE_MESSAGES
8161 MHD_DLOG (daemon,
8162 _ ("The value of 'struct sockaddr.sa_len' provided " \
8163 "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
8164 "and does not match 'sa_family' value of the " \
8165 "same structure.\n"));
8166#endif /* HAVE_MESSAGES */
8167 goto free_and_fail;
8168 }
8169 if ((0 == addrlen) || (sa_len < addrlen))
8170 addrlen = sa_len; /* Use smaller value for safety */
8171 }
8172#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8173 if (0 == addrlen)
8174 addrlen = sizeof(sa6);
8175 memcpy (&sa6, pservaddr, sizeof(sa6)); /* Required due to stronger alignment */
8176 sa6_port = (uint16_t) ntohs (sa6.sin6_port);
8177#ifndef MHD_USE_GETSOCKNAME
8178 if (0 != sa6_port)
8179#endif /* ! MHD_USE_GETSOCKNAME */
8180 daemon->port = sa6_port;
8181 domain = PF_INET6;
8182 *pflags |= ((enum MHD_FLAG) MHD_USE_IPv6);
8183 }
8184 break;
8185#endif /* HAVE_INET6 */
8186#ifdef AF_UNIX
8187 case AF_UNIX:
8188#endif /* AF_UNIX */
8189 default:
8190#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8191 if (0 == addrlen)
8192 addrlen = sa_len;
8193 else if ((0 != sa_len) && (sa_len < addrlen))
8194 addrlen = sa_len; /* Use smaller value for safety */
8195#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
8196 if (0 >= addrlen)
8197 {
8198#ifdef HAVE_MESSAGES
8199 MHD_DLOG (daemon,
8200 _ ("The 'sa_family' of the 'struct sockaddr' provided " \
8201 "via MHD_OPTION_SOCK_ADDR option is not supported.\n"));
8202#endif /* HAVE_MESSAGES */
8203 goto free_and_fail;
8204 }
8205#ifdef AF_UNIX
8206 if (AF_UNIX == pservaddr->sa_family)
8207 {
8208 daemon->port = 0; /* special value for UNIX domain sockets */
8209 daemon->listen_is_unix = _MHD_YES;
8210#ifdef PF_UNIX
8211 domain = PF_UNIX;
8212#else /* ! PF_UNIX */
8213 domain = AF_UNIX;
8214#endif /* ! PF_UNIX */
8215 }
8216 else /* combined with the next 'if' */
8217#endif /* AF_UNIX */
8218 if (1)
8219 {
8220 daemon->port = 0; /* ugh */
8221 daemon->listen_is_unix = _MHD_UNKNOWN;
8222 /* Assumed the same values for AF_* and PF_* */
8223 domain = pservaddr->sa_family;
8224 }
8225 break;
8226 }
8227 }
8228 else
8229 {
8230 if (! use_ipv6)
8231 {
8232 memset (&servaddr4,
8233 0,
8234 sizeof (struct sockaddr_in));
8235 servaddr4.sin_family = AF_INET;
8236 servaddr4.sin_port = htons (port);
8237 if (0 != INADDR_ANY)
8238 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
8239#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
8240 servaddr4.sin_len = sizeof (struct sockaddr_in);
8241#endif
8242 pservaddr = (struct sockaddr *) &servaddr4;
8243 addrlen = (socklen_t) sizeof(servaddr4);
8244 daemon->listen_is_unix = _MHD_NO;
8245 domain = PF_INET;
8246 }
8247#ifdef HAVE_INET6
8248 else
8249 {
8250#ifdef IN6ADDR_ANY_INIT
8251 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
8252#endif
8253 memset (&servaddr6,
8254 0,
8255 sizeof (struct sockaddr_in6));
8256 servaddr6.sin6_family = AF_INET6;
8257 servaddr6.sin6_port = htons (port);
8258#ifdef IN6ADDR_ANY_INIT
8259 servaddr6.sin6_addr = static_in6any;
8260#endif
8261#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
8262 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
8263#endif
8264 pservaddr = (struct sockaddr *) &servaddr6;
8265 addrlen = (socklen_t) sizeof (servaddr6);
8266 daemon->listen_is_unix = _MHD_NO;
8267 domain = PF_INET6;
8268 }
8269#endif /* HAVE_INET6 */
8270 }
8271
8272 daemon->listen_fd = MHD_socket_create_listen_ (domain);
8273 if (MHD_INVALID_SOCKET == daemon->listen_fd)
8274 {
8275#ifdef HAVE_MESSAGES
8276 MHD_DLOG (daemon,
8277 _ ("Failed to create socket for listening: %s\n"),
8279#endif
8280 goto free_and_fail;
8281 }
8282 if (MHD_D_IS_USING_SELECT_ (daemon) &&
8284 daemon)) )
8285 {
8286#ifdef HAVE_MESSAGES
8287 MHD_DLOG (daemon,
8288 _ ("Listen socket descriptor (%d) is not " \
8289 "less than daemon FD_SETSIZE value (%d).\n"),
8290 (int) daemon->listen_fd,
8291 (int) MHD_D_GET_FD_SETSIZE_ (daemon));
8292#endif
8293 goto free_and_fail;
8294 }
8295
8296 /* Apply the socket options according to listening_address_reuse. */
8297 if (0 == daemon->listening_address_reuse)
8298 {
8299#ifndef MHD_WINSOCK_SOCKETS
8300 /* No user requirement, use "traditional" default SO_REUSEADDR
8301 * on non-W32 platforms, and do not fail if it doesn't work.
8302 * Don't use it on W32, because on W32 it will allow multiple
8303 * bind to the same address:port, like SO_REUSEPORT on others. */
8304 if (0 > setsockopt (daemon->listen_fd,
8305 SOL_SOCKET,
8306 SO_REUSEADDR,
8307 (const void *) &on, sizeof (on)))
8308 {
8309#ifdef HAVE_MESSAGES
8310 MHD_DLOG (daemon,
8311 _ ("setsockopt failed: %s\n"),
8313#endif
8314 }
8315#endif /* ! MHD_WINSOCK_SOCKETS */
8316 }
8317 else if (daemon->listening_address_reuse > 0)
8318 {
8319 /* User requested to allow reusing listening address:port. */
8320#ifndef MHD_WINSOCK_SOCKETS
8321 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
8322 * it doesn't work. */
8323 if (0 > setsockopt (daemon->listen_fd,
8324 SOL_SOCKET,
8325 SO_REUSEADDR,
8326 (const void *) &on, sizeof (on)))
8327 {
8328#ifdef HAVE_MESSAGES
8329 MHD_DLOG (daemon,
8330 _ ("setsockopt failed: %s\n"),
8332#endif
8333 }
8334#endif /* ! MHD_WINSOCK_SOCKETS */
8335 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
8336 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
8337 */
8338 /* SO_REUSEADDR on W32 has the same semantics
8339 as SO_REUSEPORT on BSD/Linux */
8340#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
8341 if (0 > setsockopt (daemon->listen_fd,
8342 SOL_SOCKET,
8343#ifndef MHD_WINSOCK_SOCKETS
8344 SO_REUSEPORT,
8345#else /* MHD_WINSOCK_SOCKETS */
8346 SO_REUSEADDR,
8347#endif /* MHD_WINSOCK_SOCKETS */
8348 (const void *) &on,
8349 sizeof (on)))
8350 {
8351#ifdef HAVE_MESSAGES
8352 MHD_DLOG (daemon,
8353 _ ("setsockopt failed: %s\n"),
8355#endif
8356 goto free_and_fail;
8357 }
8358#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
8359 /* we're supposed to allow address:port re-use, but
8360 on this platform we cannot; fail hard */
8361#ifdef HAVE_MESSAGES
8362 MHD_DLOG (daemon,
8363 _ ("Cannot allow listening address reuse: " \
8364 "SO_REUSEPORT not defined.\n"));
8365#endif
8366 goto free_and_fail;
8367#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
8368 }
8369 else /* if (daemon->listening_address_reuse < 0) */
8370 {
8371 /* User requested to disallow reusing listening address:port.
8372 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
8373 * is used and Solaris with SO_EXCLBIND.
8374 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
8375 * or setsockopt fails.
8376 */
8377#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
8378 (defined(__sun) && defined(SO_EXCLBIND))
8379 if (0 > setsockopt (daemon->listen_fd,
8380 SOL_SOCKET,
8381#ifdef SO_EXCLUSIVEADDRUSE
8382 SO_EXCLUSIVEADDRUSE,
8383#else /* SO_EXCLBIND */
8384 SO_EXCLBIND,
8385#endif /* SO_EXCLBIND */
8386 (const void *) &on,
8387 sizeof (on)))
8388 {
8389#ifdef HAVE_MESSAGES
8390 MHD_DLOG (daemon,
8391 _ ("setsockopt failed: %s\n"),
8393#endif
8394 goto free_and_fail;
8395 }
8396#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
8397#ifdef HAVE_MESSAGES
8398 MHD_DLOG (daemon,
8399 _ ("Cannot disallow listening address reuse: " \
8400 "SO_EXCLUSIVEADDRUSE not defined.\n"));
8401#endif
8402 goto free_and_fail;
8403#endif /* MHD_WINSOCK_SOCKETS */
8404 }
8405
8406 /* check for user supplied sockaddr */
8407 if (0 != (*pflags & MHD_USE_IPv6))
8408 {
8409#ifdef IPPROTO_IPV6
8410#ifdef IPV6_V6ONLY
8411 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
8412 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
8413 and may also be missing on older POSIX systems; good luck if you have any of those,
8414 your IPv6 socket may then also bind against IPv4 anyway... */
8415 const MHD_SCKT_OPT_BOOL_ v6_only =
8416 (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
8417 if (0 > setsockopt (daemon->listen_fd,
8418 IPPROTO_IPV6, IPV6_V6ONLY,
8419 (const void *) &v6_only,
8420 sizeof (v6_only)))
8421 {
8422#ifdef HAVE_MESSAGES
8423 MHD_DLOG (daemon,
8424 _ ("setsockopt failed: %s\n"),
8426#endif
8427 }
8428#endif
8429#endif
8430 }
8431 if (0 != bind (daemon->listen_fd,
8432 pservaddr,
8433 addrlen))
8434 {
8435#ifdef HAVE_MESSAGES
8436 MHD_DLOG (daemon,
8437 _ ("Failed to bind to port %u: %s\n"),
8438 (unsigned int) port,
8440#endif
8441 goto free_and_fail;
8442 }
8443#ifdef TCP_FASTOPEN
8444 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
8445 {
8446 if (0 == daemon->fastopen_queue_size)
8447 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
8448 if (0 != setsockopt (daemon->listen_fd,
8449 IPPROTO_TCP,
8450 TCP_FASTOPEN,
8451 (const void *) &daemon->fastopen_queue_size,
8452 sizeof (daemon->fastopen_queue_size)))
8453 {
8454#ifdef HAVE_MESSAGES
8455 MHD_DLOG (daemon,
8456 _ ("setsockopt failed: %s\n"),
8458#endif
8459 }
8460 }
8461#endif
8462 if (0 != listen (daemon->listen_fd,
8463 (int) daemon->listen_backlog_size))
8464 {
8465#ifdef HAVE_MESSAGES
8466 MHD_DLOG (daemon,
8467 _ ("Failed to listen for connections: %s\n"),
8469#endif
8470 goto free_and_fail;
8471 }
8472 }
8473 else
8474 {
8475 if (MHD_D_IS_USING_SELECT_ (daemon) &&
8477 daemon)) )
8478 {
8479#ifdef HAVE_MESSAGES
8480 MHD_DLOG (daemon,
8481 _ ("Listen socket descriptor (%d) is not " \
8482 "less than daemon FD_SETSIZE value (%d).\n"),
8483 (int) daemon->listen_fd,
8484 (int) MHD_D_GET_FD_SETSIZE_ (daemon));
8485#endif
8486 goto free_and_fail;
8487 }
8488 else
8489 {
8490#if defined(SOL_SOCKET) && (defined(SO_DOMAIN) || defined(SO_PROTOCOL_INFOW))
8491 int af;
8492 int opt_name;
8493 void *poptval;
8494 socklen_t optval_size;
8495#ifdef SO_DOMAIN
8496 opt_name = SO_DOMAIN;
8497 poptval = &af;
8498 optval_size = (socklen_t) sizeof (af);
8499#else /* SO_PROTOCOL_INFOW */
8500 WSAPROTOCOL_INFOW prot_info;
8501 opt_name = SO_PROTOCOL_INFOW;
8502 poptval = &prot_info;
8503 optval_size = (socklen_t) sizeof (prot_info);
8504#endif /* SO_PROTOCOL_INFOW */
8505
8506 if (0 == getsockopt (daemon->listen_fd,
8507 SOL_SOCKET,
8508 opt_name,
8509 poptval,
8510 &optval_size))
8511 {
8512#ifndef SO_DOMAIN
8513 af = prot_info.iAddressFamily;
8514#endif /* SO_DOMAIN */
8515 switch (af)
8516 {
8517 case AF_INET:
8518 daemon->listen_is_unix = _MHD_NO;
8519 break;
8520#ifdef HAVE_INET6
8521 case AF_INET6:
8522 *pflags |= MHD_USE_IPv6;
8523 daemon->listen_is_unix = _MHD_NO;
8524 break;
8525#endif /* HAVE_INET6 */
8526#ifdef AF_UNIX
8527 case AF_UNIX:
8528 daemon->port = 0; /* special value for UNIX domain sockets */
8529 daemon->listen_is_unix = _MHD_YES;
8530 break;
8531#endif /* AF_UNIX */
8532 default:
8533 daemon->port = 0; /* ugh */
8534 daemon->listen_is_unix = _MHD_UNKNOWN;
8535 break;
8536 }
8537 }
8538 else
8539#endif /* SOL_SOCKET && (SO_DOMAIN || SO_PROTOCOL_INFOW)) */
8540 daemon->listen_is_unix = _MHD_UNKNOWN;
8541 }
8542
8543#ifdef MHD_USE_GETSOCKNAME
8544 daemon->port = 0; /* Force use of autodetection */
8545#endif /* MHD_USE_GETSOCKNAME */
8546 }
8547
8548#ifdef MHD_USE_GETSOCKNAME
8549 if ( (0 == daemon->port) &&
8550 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
8551 (_MHD_YES != daemon->listen_is_unix) )
8552 { /* Get port number. */
8553 struct sockaddr_storage bindaddr;
8554
8555 memset (&bindaddr,
8556 0,
8557 sizeof (struct sockaddr_storage));
8558 addrlen = sizeof (struct sockaddr_storage);
8559#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
8560 bindaddr.ss_len = (socklen_t) addrlen;
8561#endif
8562 if (0 != getsockname (daemon->listen_fd,
8563 (struct sockaddr *) &bindaddr,
8564 &addrlen))
8565 {
8566#ifdef HAVE_MESSAGES
8567 MHD_DLOG (daemon,
8568 _ ("Failed to get listen port number: %s\n"),
8569 MHD_socket_last_strerr_ ());
8570#endif /* HAVE_MESSAGES */
8571 }
8572#ifdef MHD_POSIX_SOCKETS
8573 else if (sizeof (bindaddr) < addrlen)
8574 {
8575 /* should be impossible with `struct sockaddr_storage` */
8576#ifdef HAVE_MESSAGES
8577 MHD_DLOG (daemon,
8578 _ ("Failed to get listen port number " \
8579 "(`struct sockaddr_storage` too small!?).\n"));
8580#endif /* HAVE_MESSAGES */
8581 }
8582#ifndef __linux__
8583 else if (0 == addrlen)
8584 {
8585 /* Many non-Linux-based platforms return zero addrlen
8586 * for AF_UNIX sockets */
8587 daemon->port = 0; /* special value for UNIX domain sockets */
8588 if (_MHD_UNKNOWN == daemon->listen_is_unix)
8589 daemon->listen_is_unix = _MHD_YES;
8590 }
8591#endif /* __linux__ */
8592#endif /* MHD_POSIX_SOCKETS */
8593 else
8594 {
8595 switch (bindaddr.ss_family)
8596 {
8597 case AF_INET:
8598 {
8599 struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
8600
8601 daemon->port = ntohs (s4->sin_port);
8602 daemon->listen_is_unix = _MHD_NO;
8603 break;
8604 }
8605#ifdef HAVE_INET6
8606 case AF_INET6:
8607 {
8608 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
8609
8610 daemon->port = ntohs (s6->sin6_port);
8611 daemon->listen_is_unix = _MHD_NO;
8612 mhd_assert (0 != (*pflags & MHD_USE_IPv6));
8613 break;
8614 }
8615#endif /* HAVE_INET6 */
8616#ifdef AF_UNIX
8617 case AF_UNIX:
8618 daemon->port = 0; /* special value for UNIX domain sockets */
8619 daemon->listen_is_unix = _MHD_YES;
8620 break;
8621#endif
8622 default:
8623#ifdef HAVE_MESSAGES
8624 MHD_DLOG (daemon,
8625 _ ("Listen socket has unknown address family!\n"));
8626#endif
8627 daemon->port = 0; /* ugh */
8628 daemon->listen_is_unix = _MHD_UNKNOWN;
8629 break;
8630 }
8631 }
8632 }
8633#endif /* MHD_USE_GETSOCKNAME */
8634
8635 if (MHD_INVALID_SOCKET != daemon->listen_fd)
8636 {
8637 mhd_assert (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET));
8638 if (! MHD_socket_nonblocking_ (daemon->listen_fd))
8639 {
8640#ifdef HAVE_MESSAGES
8641 MHD_DLOG (daemon,
8642 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
8644#endif
8645 if (MHD_D_IS_USING_EPOLL_ (daemon)
8646#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8647 || (daemon->worker_pool_size > 0)
8648#endif
8649 )
8650 {
8651 /* Accept must be non-blocking. Multiple children may wake up
8652 * to handle a new connection, but only one will win the race.
8653 * The others must immediately return. */
8654 goto free_and_fail;
8655 }
8656 daemon->listen_nonblk = false;
8657 }
8658 else
8659 daemon->listen_nonblk = true;
8660 }
8661 else
8662 {
8663 mhd_assert (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET));
8664 daemon->listen_nonblk = false; /* Actually listen socket does not exist */
8665 }
8666
8667#ifdef EPOLL_SUPPORT
8668 if (MHD_D_IS_USING_EPOLL_ (daemon)
8669#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8670 && (0 == daemon->worker_pool_size)
8671#endif
8672 )
8673 {
8675 {
8676#ifdef HAVE_MESSAGES
8677 MHD_DLOG (daemon,
8678 _ ("Combining MHD_USE_THREAD_PER_CONNECTION and " \
8679 "MHD_USE_EPOLL is not supported.\n"));
8680#endif
8681 goto free_and_fail;
8682 }
8683 if (MHD_NO == setup_epoll_to_listen (daemon))
8684 goto free_and_fail;
8685 }
8686#endif /* EPOLL_SUPPORT */
8687
8688#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8689 if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
8690 {
8691#ifdef HAVE_MESSAGES
8692 MHD_DLOG (daemon,
8693 _ ("MHD failed to initialize IP connection limit mutex.\n"));
8694#endif
8695 goto free_and_fail;
8696 }
8697#endif
8698
8699#ifdef HTTPS_SUPPORT
8700 /* initialize HTTPS daemon certificate aspects & send / recv functions */
8701 if ( (0 != (*pflags & MHD_USE_TLS)) &&
8702 (0 != MHD_TLS_init (daemon)) )
8703 {
8704#ifdef HAVE_MESSAGES
8705 MHD_DLOG (daemon,
8706 _ ("Failed to initialize TLS support.\n"));
8707#endif
8708#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8709 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8710#endif
8711 goto free_and_fail;
8712 }
8713#endif /* HTTPS_SUPPORT */
8714#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8715 /* Start threads if requested by parameters */
8716 if (MHD_D_IS_USING_THREADS_ (daemon))
8717 {
8718 /* Internal thread (or threads) is used.
8719 * Make sure that MHD will be able to communicate with threads. */
8720 /* If using a thread pool ITC will be initialised later
8721 * for each individual worker thread. */
8722#ifdef HAVE_LISTEN_SHUTDOWN
8723 mhd_assert ((1 < daemon->worker_pool_size) || \
8724 (MHD_ITC_IS_VALID_ (daemon->itc)) || \
8725 (MHD_INVALID_SOCKET != daemon->listen_fd));
8726#else /* ! HAVE_LISTEN_SHUTDOWN */
8727 mhd_assert ((1 < daemon->worker_pool_size) || \
8728 (MHD_ITC_IS_VALID_ (daemon->itc)));
8729#endif /* ! HAVE_LISTEN_SHUTDOWN */
8730 if (0 == daemon->worker_pool_size)
8731 {
8732 if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
8733 {
8734#ifdef HAVE_MESSAGES
8735 MHD_DLOG (daemon,
8736 _ ("Failed to initialise internal lists mutex.\n"));
8737#endif
8738 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8739 goto free_and_fail;
8740 }
8741 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
8742 {
8743#ifdef HAVE_MESSAGES
8744 MHD_DLOG (daemon,
8745 _ ("Failed to initialise mutex.\n"));
8746#endif
8747 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8748 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
8749 goto free_and_fail;
8750 }
8751 if (! MHD_create_named_thread_ (&daemon->tid,
8753 "MHD-listen" : "MHD-single",
8754 daemon->thread_stack_size,
8755 &MHD_polling_thread,
8756 daemon) )
8757 {
8758#ifdef HAVE_MESSAGES
8759#ifdef EAGAIN
8760 if (EAGAIN == errno)
8761 MHD_DLOG (daemon,
8762 _ ("Failed to create a new thread because it would have " \
8763 "exceeded the system limit on the number of threads or " \
8764 "no system resources available.\n"));
8765 else
8766#endif /* EAGAIN */
8767 MHD_DLOG (daemon,
8768 _ ("Failed to create listen thread: %s\n"),
8769 MHD_strerror_ (errno));
8770#endif /* HAVE_MESSAGES */
8771 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
8772 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8773 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
8774 goto free_and_fail;
8775 }
8776 }
8777 else /* 0 < daemon->worker_pool_size */
8778 {
8779 /* Coarse-grained count of connections per thread (note error
8780 * due to integer division). Also keep track of how many
8781 * connections are leftover after an equal split. */
8782 unsigned int conns_per_thread = daemon->connection_limit
8783 / daemon->worker_pool_size;
8784 unsigned int leftover_conns = daemon->connection_limit
8785 % daemon->worker_pool_size;
8786
8787 mhd_assert (2 <= daemon->worker_pool_size);
8788 i = 0; /* we need this in case fcntl or malloc fails */
8789
8790 /* Allocate memory for pooled objects */
8791 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
8792 * daemon->worker_pool_size);
8793 if (NULL == daemon->worker_pool)
8794 goto thread_failed;
8795
8796 /* Start the workers in the pool */
8797 for (i = 0; i < daemon->worker_pool_size; ++i)
8798 {
8799 /* Create copy of the Daemon object for each worker */
8800 struct MHD_Daemon *d = &daemon->worker_pool[i];
8801
8802 memcpy (d, daemon, sizeof (struct MHD_Daemon));
8803 /* Adjust polling params for worker daemons; note that memcpy()
8804 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
8805 the worker threads. */
8806 d->master = daemon;
8807 d->worker_pool_size = 0;
8808 d->worker_pool = NULL;
8809 if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
8810 {
8811#ifdef HAVE_MESSAGES
8812 MHD_DLOG (daemon,
8813 _ ("Failed to initialise internal lists mutex.\n"));
8814#endif
8815 goto thread_failed;
8816 }
8817 if (! MHD_mutex_init_ (&d->new_connections_mutex))
8818 {
8819#ifdef HAVE_MESSAGES
8820 MHD_DLOG (daemon,
8821 _ ("Failed to initialise mutex.\n"));
8822#endif
8823 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
8824 goto thread_failed;
8825 }
8826 if (0 != (*pflags & MHD_USE_ITC))
8827 {
8828 if (! MHD_itc_init_ (d->itc))
8829 {
8830#ifdef HAVE_MESSAGES
8831 MHD_DLOG (daemon,
8832 _ ("Failed to create worker inter-thread " \
8833 "communication channel: %s\n"),
8834 MHD_itc_last_strerror_ () );
8835#endif
8836 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
8837 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
8838 goto thread_failed;
8839 }
8840 if (MHD_D_IS_USING_SELECT_ (d) &&
8841 (! MHD_D_DOES_SCKT_FIT_FDSET_ (MHD_itc_r_fd_ (d->itc), daemon)) )
8842 {
8843#ifdef HAVE_MESSAGES
8844 MHD_DLOG (daemon,
8845 _ ("File descriptor for worker inter-thread " \
8846 "communication channel exceeds maximum value.\n"));
8847#endif
8849 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
8850 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
8851 goto thread_failed;
8852 }
8853 }
8854 else
8855 MHD_itc_set_invalid_ (d->itc);
8856
8857#ifdef HAVE_LISTEN_SHUTDOWN
8858 mhd_assert ((MHD_ITC_IS_VALID_ (d->itc)) || \
8860#else /* ! HAVE_LISTEN_SHUTDOWN */
8861 mhd_assert (MHD_ITC_IS_VALID_ (d->itc));
8862#endif /* ! HAVE_LISTEN_SHUTDOWN */
8863
8864 /* Divide available connections evenly amongst the threads.
8865 * Thread indexes in [0, leftover_conns) each get one of the
8866 * leftover connections. */
8867 d->connection_limit = conns_per_thread;
8868 if (i < leftover_conns)
8869 ++d->connection_limit;
8870#ifdef EPOLL_SUPPORT
8871 if (MHD_D_IS_USING_EPOLL_ (d) &&
8872 (MHD_NO == setup_epoll_to_listen (d)) )
8873 {
8874 if (MHD_ITC_IS_VALID_ (d->itc))
8876 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
8877 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
8878 goto thread_failed;
8879 }
8880#endif
8881 /* Some members must be used only in master daemon */
8882#if defined(MHD_USE_THREADS)
8883 memset (&d->per_ip_connection_mutex, 0x7F,
8884 sizeof(d->per_ip_connection_mutex));
8885#endif /* MHD_USE_THREADS */
8886#ifdef DAUTH_SUPPORT
8887 d->nnc = NULL;
8888 d->nonce_nc_size = 0;
8889 d->digest_auth_random_copy = NULL;
8890#if defined(MHD_USE_THREADS)
8891 memset (&d->nnc_lock, 0x7F, sizeof(d->nnc_lock));
8892#endif /* MHD_USE_THREADS */
8893#endif /* DAUTH_SUPPORT */
8894
8895 /* Spawn the worker thread */
8896 if (! MHD_create_named_thread_ (&d->tid,
8897 "MHD-worker",
8898 daemon->thread_stack_size,
8899 &MHD_polling_thread,
8900 d))
8901 {
8902#ifdef HAVE_MESSAGES
8903#ifdef EAGAIN
8904 if (EAGAIN == errno)
8905 MHD_DLOG (daemon,
8906 _ ("Failed to create a new pool thread because it would " \
8907 "have exceeded the system limit on the number of " \
8908 "threads or no system resources available.\n"));
8909 else
8910#endif /* EAGAIN */
8911 MHD_DLOG (daemon,
8912 _ ("Failed to create pool thread: %s\n"),
8913 MHD_strerror_ (errno));
8914#endif
8915 /* Free memory for this worker; cleanup below handles
8916 * all previously-created workers. */
8917 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
8918 if (MHD_ITC_IS_VALID_ (d->itc))
8920 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
8921 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
8922 goto thread_failed;
8923 }
8924 }
8925 }
8926 }
8927 else
8928 { /* Daemon without internal threads */
8929 if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
8930 {
8931#ifdef HAVE_MESSAGES
8932 MHD_DLOG (daemon,
8933 _ ("Failed to initialise internal lists mutex.\n"));
8934#endif
8935 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8936 goto free_and_fail;
8937 }
8938 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
8939 {
8940#ifdef HAVE_MESSAGES
8941 MHD_DLOG (daemon,
8942 _ ("Failed to initialise mutex.\n"));
8943#endif
8944 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
8945 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8946 goto free_and_fail;
8947 }
8948 }
8949#endif
8950#ifdef HTTPS_SUPPORT
8951 /* API promises to never use the password after initialization,
8952 so we additionally NULL it here to not deref a dangling pointer. */
8953 daemon->https_key_password = NULL;
8954#endif /* HTTPS_SUPPORT */
8955
8956 return daemon;
8957
8958#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8959thread_failed:
8960 /* If no worker threads created, then shut down normally. Calling
8961 MHD_stop_daemon (as we do below) doesn't work here since it
8962 assumes a 0-sized thread pool means we had been in the default
8963 MHD_USE_INTERNAL_POLLING_THREAD mode. */
8964 if (0 == i)
8965 {
8966 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
8967 if (NULL != daemon->worker_pool)
8968 free (daemon->worker_pool);
8969 goto free_and_fail;
8970 }
8971
8972 /* Shutdown worker threads we've already created. Pretend
8973 as though we had fully initialized our daemon, but
8974 with a smaller number of threads than had been
8975 requested. */
8976 daemon->worker_pool_size = i;
8977 MHD_stop_daemon (daemon);
8978 return NULL;
8979#endif
8980
8981free_and_fail:
8982 /* clean up basic memory state in 'daemon' and return NULL to
8983 indicate failure */
8984#ifdef EPOLL_SUPPORT
8985#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
8986 if (daemon->upgrade_fd_in_epoll)
8987 {
8988 if (0 != epoll_ctl (daemon->epoll_fd,
8989 EPOLL_CTL_DEL,
8990 daemon->epoll_upgrade_fd,
8991 NULL))
8992 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
8993 daemon->upgrade_fd_in_epoll = false;
8994 }
8995#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
8996 if (-1 != daemon->epoll_fd)
8997 close (daemon->epoll_fd);
8998#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
8999 if (-1 != daemon->epoll_upgrade_fd)
9000 close (daemon->epoll_upgrade_fd);
9001#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9002#endif /* EPOLL_SUPPORT */
9003#ifdef DAUTH_SUPPORT
9004 free (daemon->digest_auth_random_copy);
9005 free (daemon->nnc);
9006#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9007 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
9008#endif
9009#endif
9010#ifdef HTTPS_SUPPORT
9011 if (0 != (*pflags & MHD_USE_TLS))
9012 {
9013 gnutls_priority_deinit (daemon->priority_cache);
9014 if (daemon->x509_cred)
9015 gnutls_certificate_free_credentials (daemon->x509_cred);
9016 if (daemon->psk_cred)
9017 gnutls_psk_free_server_credentials (daemon->psk_cred);
9018 }
9019#endif /* HTTPS_SUPPORT */
9020 if (MHD_ITC_IS_VALID_ (daemon->itc))
9021 MHD_itc_destroy_chk_ (daemon->itc);
9022 if (MHD_INVALID_SOCKET != daemon->listen_fd)
9023 (void) MHD_socket_close_ (daemon->listen_fd);
9024 free (daemon);
9025 return NULL;
9026}
9027
9028
9037static void
9039{
9040 struct MHD_Connection *pos;
9041 const bool used_thr_p_c = MHD_D_IS_USING_THREAD_PER_CONN_ (daemon);
9042#ifdef UPGRADE_SUPPORT
9043 const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
9044#endif /* UPGRADE_SUPPORT */
9045#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9046 struct MHD_UpgradeResponseHandle *urh;
9047 struct MHD_UpgradeResponseHandle *urhn;
9048 const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
9049#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9050
9051#ifdef MHD_USE_THREADS
9052 mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
9055 mhd_assert (NULL == daemon->worker_pool);
9056#endif /* MHD_USE_THREADS */
9057 mhd_assert (daemon->shutdown);
9058
9059#ifdef MHD_USE_THREADS
9060/* Remove externally added new connections that are
9061 * not processed by the daemon thread. */
9062 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
9063 while (NULL != (pos = daemon->new_connections_tail))
9064 {
9067 daemon->new_connections_tail,
9068 pos);
9069 new_connection_close_ (daemon, pos);
9070 }
9071 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
9072#endif /* MHD_USE_THREADS */
9073
9074#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9075 /* give upgraded HTTPS connections a chance to finish */
9076 /* 'daemon->urh_head' is not used in thread-per-connection mode. */
9077 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
9078 {
9079 mhd_assert (! used_thr_p_c);
9080 urhn = urh->prev;
9081 /* call generic forwarding function for passing data
9082 with chance to detect that application is done. */
9083 process_urh (urh);
9084 MHD_connection_finish_forward_ (urh->connection);
9085 urh->clean_ready = true;
9086 /* Resuming will move connection to cleanup list. */
9087 MHD_resume_connection (urh->connection);
9088 }
9089#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9090
9091 /* Give suspended connections a chance to resume to avoid
9092 running into the check for there not being any suspended
9093 connections left in case of a tight race with a recently
9094 resumed connection. */
9095 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
9096 {
9097 daemon->resuming = true; /* Force check for pending resume. */
9099 }
9100 /* first, make sure all threads are aware of shutdown; need to
9101 traverse DLLs in peace... */
9102#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9103 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
9104#endif
9105#ifdef UPGRADE_SUPPORT
9106 if (upg_allowed)
9107 {
9108 struct MHD_Connection *susp;
9109
9111 while (NULL != susp)
9112 {
9113 if (NULL == susp->urh) /* "Upgraded" connection? */
9114 MHD_PANIC (_ ("MHD_stop_daemon() called while we have " \
9115 "suspended connections.\n"));
9116#ifdef HTTPS_SUPPORT
9117 else if (used_tls &&
9118 used_thr_p_c &&
9119 (! susp->urh->clean_ready) )
9120 shutdown (susp->urh->app.socket,
9121 SHUT_RDWR); /* Wake thread by shutdown of app socket. */
9122#endif /* HTTPS_SUPPORT */
9123 else
9124 {
9125#ifdef HAVE_MESSAGES
9126 if (! susp->urh->was_closed)
9127 MHD_DLOG (daemon,
9128 _ ("Initiated daemon shutdown while \"upgraded\" " \
9129 "connection was not closed.\n"));
9130#endif
9131 susp->urh->was_closed = true;
9132 /* If thread-per-connection is used, connection's thread
9133 * may still processing "upgrade" (exiting). */
9134 if (! used_thr_p_c)
9136 /* Do not use MHD_resume_connection() as mutex is
9137 * already locked. */
9138 susp->resuming = true;
9139 daemon->resuming = true;
9140 }
9141 susp = susp->prev;
9142 }
9143 }
9144 else /* This 'else' is combined with next 'if' */
9145#endif /* UPGRADE_SUPPORT */
9147 MHD_PANIC (_ ("MHD_stop_daemon() called while we have " \
9148 "suspended connections.\n"));
9149#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
9150#ifdef MHD_USE_THREADS
9151 if (upg_allowed && used_tls && used_thr_p_c)
9152 {
9153 /* "Upgraded" threads may be running in parallel. Connection will not be
9154 * moved to the "cleanup list" until connection's thread finishes.
9155 * We must ensure that all "upgraded" connections are finished otherwise
9156 * connection may stay in "suspended" list and will not be cleaned. */
9157 for (pos = daemon->suspended_connections_tail; NULL != pos; pos = pos->prev)
9158 {
9159 /* Any connection found here is "upgraded" connection, normal suspended
9160 * connections are already removed from this list. */
9161 mhd_assert (NULL != pos->urh);
9162 if (! pos->thread_joined)
9163 {
9164 /* While "cleanup" list is not manipulated by "upgraded"
9165 * connection, "cleanup" mutex is required for call of
9166 * MHD_resume_connection() during finishing of "upgraded"
9167 * thread. */
9168 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
9169 if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
9170 MHD_PANIC (_ ("Failed to join a thread.\n"));
9171 pos->thread_joined = true;
9172 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
9173 }
9174 }
9175 }
9176#endif /* MHD_USE_THREADS */
9177#endif
9178 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
9179 {
9180 shutdown (pos->socket_fd,
9181 SHUT_RDWR);
9182#ifdef MHD_WINSOCK_SOCKETS
9184 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
9185 (! MHD_itc_activate_ (daemon->itc, "e")) )
9186 MHD_PANIC (_ ("Failed to signal shutdown via inter-thread " \
9187 "communication channel.\n"));
9188#endif
9189 }
9190
9191#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9192 /* now, collect per-connection threads */
9193 if (used_thr_p_c)
9194 {
9195 pos = daemon->connections_tail;
9196 while (NULL != pos)
9197 {
9198 if (! pos->thread_joined)
9199 {
9200 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
9201 if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
9202 MHD_PANIC (_ ("Failed to join a thread.\n"));
9203 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
9204 pos->thread_joined = true;
9205 /* The thread may have concurrently modified the DLL,
9206 need to restart from the beginning */
9207 pos = daemon->connections_tail;
9208 continue;
9209 }
9210 pos = pos->prev;
9211 }
9212 }
9213 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
9214#endif
9215
9216#ifdef UPGRADE_SUPPORT
9217 /* Finished threads with "upgraded" connections need to be moved
9218 * to cleanup list by resume_suspended_connections(). */
9219 /* "Upgraded" connections that were not closed explicitly by
9220 * application should be moved to cleanup list too. */
9221 if (upg_allowed)
9222 {
9223 daemon->resuming = true; /* Force check for pending resume. */
9225 }
9226#endif /* UPGRADE_SUPPORT */
9227
9229 /* now that we're alone, move everyone to cleanup */
9230 while (NULL != (pos = daemon->connections_tail))
9231 {
9232#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9234 (! pos->thread_joined) )
9235 MHD_PANIC (_ ("Failed to join a thread.\n"));
9236#endif
9237 close_connection (pos);
9238 }
9240}
9241
9242
9249_MHD_EXTERN void
9251{
9252 MHD_socket fd;
9253#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9254 unsigned int i;
9255#endif
9256
9257 if (NULL == daemon)
9258 return;
9259 if ( (daemon->shutdown) && (NULL == daemon->master) )
9260 MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
9261
9263 (NULL != daemon->worker_pool) || \
9266 (NULL == daemon->worker_pool)) || \
9268
9269 /* Slave daemons must be stopped by master daemon. */
9270 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
9271
9272 daemon->shutdown = true;
9273 if (daemon->was_quiesced)
9274 fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
9275 else
9276 fd = daemon->listen_fd;
9277
9278#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9279 if (NULL != daemon->worker_pool)
9280 { /* Master daemon with worker pool. */
9281 mhd_assert (1 < daemon->worker_pool_size);
9283
9284 /* Let workers shutdown in parallel. */
9285 for (i = 0; i < daemon->worker_pool_size; ++i)
9286 {
9287 daemon->worker_pool[i].shutdown = true;
9288 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
9289 {
9290 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
9291 "e"))
9292 MHD_PANIC (_ ("Failed to signal shutdown via inter-thread " \
9293 "communication channel.\n"));
9294 }
9295 else
9297 }
9298#ifdef HAVE_LISTEN_SHUTDOWN
9299 if (MHD_INVALID_SOCKET != fd)
9300 {
9301 (void) shutdown (fd,
9302 SHUT_RDWR);
9303 }
9304#endif /* HAVE_LISTEN_SHUTDOWN */
9305 for (i = 0; i < daemon->worker_pool_size; ++i)
9306 {
9307 MHD_stop_daemon (&daemon->worker_pool[i]);
9308 }
9309 free (daemon->worker_pool);
9311#ifdef EPOLL_SUPPORT
9312 mhd_assert (-1 == daemon->epoll_fd);
9313#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9314 mhd_assert (-1 == daemon->epoll_upgrade_fd);
9315#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9316#endif /* EPOLL_SUPPORT */
9317 }
9318 else
9319#endif
9320 { /* Worker daemon or single daemon. */
9321#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9323 { /* Worker daemon or single daemon with internal thread(s). */
9324 mhd_assert (0 == daemon->worker_pool_size);
9325 /* Separate thread(s) is used for polling sockets. */
9326 if (MHD_ITC_IS_VALID_ (daemon->itc))
9327 {
9328 if (! MHD_itc_activate_ (daemon->itc,
9329 "e"))
9330 MHD_PANIC (_ ("Failed to signal shutdown via inter-thread " \
9331 "communication channel.\n"));
9332 }
9333 else
9334 {
9335#ifdef HAVE_LISTEN_SHUTDOWN
9336 if (MHD_INVALID_SOCKET != fd)
9337 {
9338 if (NULL == daemon->master)
9339 (void) shutdown (fd,
9340 SHUT_RDWR);
9341 }
9342 else
9343#endif /* HAVE_LISTEN_SHUTDOWN */
9344 mhd_assert (false); /* Should never happen */
9345 }
9346
9348 {
9349 MHD_PANIC (_ ("Failed to join a thread.\n"));
9350 }
9351 /* close_all_connections() was called in daemon thread. */
9352 }
9353 else
9354#endif
9355 {
9356 /* No internal threads are used for polling sockets. */
9358 }
9363#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
9364 mhd_assert (NULL == daemon->urh_head);
9365#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
9366
9367 if (MHD_ITC_IS_VALID_ (daemon->itc))
9369
9370#ifdef EPOLL_SUPPORT
9372 (-1 != daemon->epoll_fd) )
9373 MHD_socket_close_chk_ (daemon->epoll_fd);
9374#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9376 (-1 != daemon->epoll_upgrade_fd) )
9377 MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
9378#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
9379#endif /* EPOLL_SUPPORT */
9380
9381#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9382 MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex);
9383 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
9384#endif
9385 }
9386
9387 if (NULL == daemon->master)
9388 { /* Cleanup that should be done only one time in master/single daemon.
9389 * Do not perform this cleanup in worker daemons. */
9390
9391 if (MHD_INVALID_SOCKET != fd)
9393
9394 /* TLS clean up */
9395#ifdef HTTPS_SUPPORT
9396 if (daemon->have_dhparams)
9397 {
9398 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
9399 daemon->have_dhparams = false;
9400 }
9401 if (0 != (daemon->options & MHD_USE_TLS))
9402 {
9403 gnutls_priority_deinit (daemon->priority_cache);
9404 if (daemon->x509_cred)
9405 gnutls_certificate_free_credentials (daemon->x509_cred);
9406 if (daemon->psk_cred)
9407 gnutls_psk_free_server_credentials (daemon->psk_cred);
9408 }
9409#endif /* HTTPS_SUPPORT */
9410
9411#ifdef DAUTH_SUPPORT
9412 free (daemon->digest_auth_random_copy);
9413 free (daemon->nnc);
9414#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9415 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
9416#endif
9417#endif
9418#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9419 MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex);
9420#endif
9421 free (daemon);
9422 }
9423}
9424
9425
9438_MHD_EXTERN const union MHD_DaemonInfo *
9440 enum MHD_DaemonInfoType info_type,
9441 ...)
9442{
9443 if (NULL == daemon)
9444 return NULL;
9445
9446 mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
9447 (NULL != daemon->worker_pool) || \
9449 mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
9450 (NULL == daemon->worker_pool)) || \
9451 (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
9452
9453 switch (info_type)
9454 {
9456 return NULL; /* no longer supported */
9458 return NULL; /* no longer supported */
9461 return &daemon->daemon_info_dummy_listen_fd;
9463#ifdef EPOLL_SUPPORT
9464 daemon->daemon_info_dummy_epoll_fd.epoll_fd = daemon->epoll_fd;
9465 return &daemon->daemon_info_dummy_epoll_fd;
9466#else /* ! EPOLL_SUPPORT */
9467 return NULL;
9468#endif /* ! EPOLL_SUPPORT */
9470 if (! MHD_D_IS_THREAD_SAFE_ (daemon))
9471 MHD_cleanup_connections (daemon);
9472#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9473 else if (daemon->worker_pool)
9474 {
9475 unsigned int i;
9476 /* Collect the connection information stored in the workers. */
9477 daemon->connections = 0;
9478 for (i = 0; i < daemon->worker_pool_size; i++)
9479 {
9480 /* FIXME: next line is thread-safe only if read is atomic. */
9481 daemon->connections += daemon->worker_pool[i].connections;
9482 }
9483 }
9484#endif
9486 = daemon->connections;
9487 return &daemon->daemon_info_dummy_num_connections;
9489 daemon->daemon_info_dummy_flags.flags = daemon->options;
9490 return &daemon->daemon_info_dummy_flags;
9492 daemon->daemon_info_dummy_port.port = daemon->port;
9493 return &daemon->daemon_info_dummy_port;
9494 default:
9495 return NULL;
9496 }
9497}
9498
9499
9506_MHD_EXTERN const char *
9508{
9509#ifdef PACKAGE_VERSION
9510 return PACKAGE_VERSION;
9511#else /* !PACKAGE_VERSION */
9512 static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
9513 if (0 == ver[0])
9514 {
9515 int res = MHD_snprintf_ (ver,
9516 sizeof(ver),
9517 "%x.%x.%x",
9518 (int) (((uint32_t) MHD_VERSION >> 24) & 0xFF),
9519 (int) (((uint32_t) MHD_VERSION >> 16) & 0xFF),
9520 (int) (((uint32_t) MHD_VERSION >> 8) & 0xFF));
9521 if ((0 >= res) || (sizeof(ver) <= res))
9522 return "0.0.0"; /* Can't return real version */
9523 }
9524 return ver;
9525#endif /* !PACKAGE_VERSION */
9526}
9527
9528
9537_MHD_EXTERN uint32_t
9539{
9540 return (uint32_t) MHD_VERSION;
9541}
9542
9543
9557{
9558 switch (feature)
9559 {
9561#ifdef HAVE_MESSAGES
9562 return MHD_YES;
9563#else
9564 return MHD_NO;
9565#endif
9566 case MHD_FEATURE_TLS:
9567#ifdef HTTPS_SUPPORT
9568 return MHD_YES;
9569#else /* ! HTTPS_SUPPORT */
9570 return MHD_NO;
9571#endif /* ! HTTPS_SUPPORT */
9573#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
9574 return MHD_YES;
9575#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
9576 return MHD_NO;
9577#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
9579#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
9580 return MHD_YES;
9581#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
9582 return MHD_NO;
9583#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
9584 case MHD_FEATURE_IPv6:
9585#ifdef HAVE_INET6
9586 return MHD_YES;
9587#else
9588 return MHD_NO;
9589#endif
9591#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
9592 return MHD_YES;
9593#else
9594 return MHD_NO;
9595#endif
9596 case MHD_FEATURE_POLL:
9597#ifdef HAVE_POLL
9598 return MHD_YES;
9599#else
9600 return MHD_NO;
9601#endif
9602 case MHD_FEATURE_EPOLL:
9603#ifdef EPOLL_SUPPORT
9604 return MHD_YES;
9605#else
9606 return MHD_NO;
9607#endif
9609#ifdef HAVE_LISTEN_SHUTDOWN
9610 return MHD_YES;
9611#else
9612 return MHD_NO;
9613#endif
9615#ifdef _MHD_ITC_SOCKETPAIR
9616 return MHD_YES;
9617#else
9618 return MHD_NO;
9619#endif
9621#ifdef TCP_FASTOPEN
9622 return MHD_YES;
9623#else
9624 return MHD_NO;
9625#endif
9627#ifdef BAUTH_SUPPORT
9628 return MHD_YES;
9629#else
9630 return MHD_NO;
9631#endif
9633#ifdef DAUTH_SUPPORT
9634 return MHD_YES;
9635#else
9636 return MHD_NO;
9637#endif
9639#ifdef HAVE_POSTPROCESSOR
9640 return MHD_YES;
9641#else
9642 return MHD_NO;
9643#endif
9645#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
9646 return MHD_YES;
9647#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
9648 return MHD_NO;
9649#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
9651#if defined(HAVE_PREAD64) || defined(_WIN32)
9652 return MHD_YES;
9653#elif defined(HAVE_PREAD)
9654 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
9655#elif defined(HAVE_LSEEK64)
9656 return MHD_YES;
9657#else
9658 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
9659#endif
9661#if defined(MHD_USE_THREAD_NAME_)
9662 return MHD_YES;
9663#else
9664 return MHD_NO;
9665#endif
9667#if defined(UPGRADE_SUPPORT)
9668 return MHD_YES;
9669#else
9670 return MHD_NO;
9671#endif
9673#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
9674 return MHD_YES;
9675#else
9676 return MHD_NO;
9677#endif
9679#ifdef MHD_USE_GETSOCKNAME
9680 return MHD_YES;
9681#else
9682 return MHD_NO;
9683#endif
9685#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) || \
9686 ! defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
9687 return MHD_YES;
9688#else
9689 return MHD_NO;
9690#endif
9692#ifdef _MHD_HAVE_SENDFILE
9693 return MHD_YES;
9694#else
9695 return MHD_NO;
9696#endif
9698#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9699 return MHD_YES;
9700#else
9701 return MHD_NO;
9702#endif
9704#if defined(COOKIE_SUPPORT)
9705 return MHD_YES;
9706#else
9707 return MHD_NO;
9708#endif
9710#ifdef DAUTH_SUPPORT
9711 return MHD_YES;
9712#else
9713 return MHD_NO;
9714#endif
9716#if defined(DAUTH_SUPPORT) && defined(MHD_MD5_SUPPORT)
9717 return MHD_YES;
9718#else
9719 return MHD_NO;
9720#endif
9722#if defined(DAUTH_SUPPORT) && defined(MHD_SHA256_SUPPORT)
9723 return MHD_YES;
9724#else
9725 return MHD_NO;
9726#endif
9728#if defined(DAUTH_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
9729 return MHD_YES;
9730#else
9731 return MHD_NO;
9732#endif
9734#ifdef DAUTH_SUPPORT
9735 return MHD_NO;
9736#else
9737 return MHD_NO;
9738#endif
9740#ifdef DAUTH_SUPPORT
9741 return MHD_NO;
9742#else
9743 return MHD_NO;
9744#endif
9746#ifdef DAUTH_SUPPORT
9747 return MHD_YES;
9748#else
9749 return MHD_NO;
9750#endif
9752#if defined(MHD_MD5_TLSLIB) || defined(MHD_SHA256_TLSLIB)
9753 return MHD_YES;
9754#else
9755 return MHD_NO;
9756#endif
9758#ifdef _DEBUG
9759 return MHD_YES;
9760#else
9761 return MHD_NO;
9762#endif
9764#ifdef HAS_FD_SETSIZE_OVERRIDABLE
9765 return MHD_YES;
9766#else /* ! HAS_FD_SETSIZE_OVERRIDABLE */
9767 return MHD_NO;
9768#endif /* ! HAS_FD_SETSIZE_OVERRIDABLE */
9769
9770 default:
9771 break;
9772 }
9773 return MHD_NO;
9774}
9775
9776
9777#ifdef MHD_HTTPS_REQUIRE_GCRYPT
9778#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
9779#if defined(MHD_USE_POSIX_THREADS)
9780GCRY_THREAD_OPTION_PTHREAD_IMPL;
9781#elif defined(MHD_W32_MUTEX_)
9782
9783static int
9784gcry_w32_mutex_init (void **ppmtx)
9785{
9786 *ppmtx = malloc (sizeof (MHD_mutex_));
9787
9788 if (NULL == *ppmtx)
9789 return ENOMEM;
9790 if (! MHD_mutex_init_ ((MHD_mutex_ *) *ppmtx))
9791 {
9792 free (*ppmtx);
9793 *ppmtx = NULL;
9794 return EPERM;
9795 }
9796
9797 return 0;
9798}
9799
9800
9801static int
9802gcry_w32_mutex_destroy (void **ppmtx)
9803{
9804 int res = (MHD_mutex_destroy_ ((MHD_mutex_ *) *ppmtx)) ? 0 : EINVAL;
9805 free (*ppmtx);
9806 return res;
9807}
9808
9809
9810static int
9811gcry_w32_mutex_lock (void **ppmtx)
9812{
9813 return MHD_mutex_lock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
9814}
9815
9816
9817static int
9818gcry_w32_mutex_unlock (void **ppmtx)
9819{
9820 return MHD_mutex_unlock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
9821}
9822
9823
9824static struct gcry_thread_cbs gcry_threads_w32 = {
9825 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
9826 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
9827 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
9829};
9830
9831#endif /* defined(MHD_W32_MUTEX_) */
9832#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
9833#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
9834
9838void
9840{
9841#if defined(MHD_WINSOCK_SOCKETS)
9842 WSADATA wsd;
9843#endif /* MHD_WINSOCK_SOCKETS */
9844
9846
9847#if defined(MHD_WINSOCK_SOCKETS)
9848 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
9849 MHD_PANIC (_ ("Failed to initialize winsock.\n"));
9850 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
9851 MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
9852#endif /* MHD_WINSOCK_SOCKETS */
9853#ifdef HTTPS_SUPPORT
9854#ifdef MHD_HTTPS_REQUIRE_GCRYPT
9855#if GCRYPT_VERSION_NUMBER < 0x010600
9856#if GNUTLS_VERSION_NUMBER <= 0x020b00
9857#if defined(MHD_USE_POSIX_THREADS)
9858 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
9859 &gcry_threads_pthread))
9860 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
9861#elif defined(MHD_W32_MUTEX_)
9862 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
9863 &gcry_threads_w32))
9864 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
9865#endif /* defined(MHD_W32_MUTEX_) */
9866#endif /* GNUTLS_VERSION_NUMBER <= 0x020b00 */
9867 gcry_check_version (NULL);
9868#else
9869 if (NULL == gcry_check_version ("1.6.0"))
9870 MHD_PANIC (_ ("libgcrypt is too old. MHD was compiled for " \
9871 "libgcrypt 1.6.0 or newer.\n"));
9872#endif
9873#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
9874 gnutls_global_init ();
9875#endif /* HTTPS_SUPPORT */
9879 /* Check whether sizes were correctly detected by configure */
9880#ifdef _DEBUG
9881 if (1)
9882 {
9883 struct timeval tv;
9884 mhd_assert (sizeof(tv.tv_sec) == SIZEOF_STRUCT_TIMEVAL_TV_SEC);
9885 }
9886#endif /* _DEBUG */
9887 mhd_assert (sizeof(uint64_t) == SIZEOF_UINT64_T);
9888}
9889
9890
9891void
9893{
9894#ifdef HTTPS_SUPPORT
9895 gnutls_global_deinit ();
9896#endif /* HTTPS_SUPPORT */
9897#if defined(MHD_WINSOCK_SOCKETS)
9898 WSACleanup ();
9899#endif /* MHD_WINSOCK_SOCKETS */
9901}
9902
9903
9904#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
9906#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
9907
9908/* 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:9038
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:3224
void MHD_fini(void)
Definition daemon.c:9892
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:1293
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:2535
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:5941
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition daemon.c:3365
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
Definition daemon.c:4797
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, struct MHD_InterimParams_ *params,...)
Definition daemon.c:6311
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:3172
void MHD_init(void)
Definition daemon.c:9839
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition daemon.c:4043
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition daemon.c:6281
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition daemon.c:3804
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, struct MHD_InterimParams_ *params, va_list ap)
Definition daemon.c:6603
#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:6061
static enum MHD_Result new_connection_process_(struct MHD_Daemon *daemon, struct MHD_Connection *connection)
Definition daemon.c:2862
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:3085
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:3443
#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:7509
_MHD_EXTERN void MHD_suspend_connection(struct MHD_Connection *connection)
Definition daemon.c:3322
_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:9250
_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:7675
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition daemon.c:5827
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:4481
_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:1188
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:987
#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:4172
_MHD_EXTERN enum MHD_Result MHD_get_timeout64(struct MHD_Daemon *daemon, uint64_t *timeout)
Definition daemon.c:4226
_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:4652
_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:6106
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
Definition daemon.c:5877
_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:2289
_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:3602
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition daemon.c:9556
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition daemon.c:6151
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition daemon.c:9439
_MHD_EXTERN uint32_t MHD_get_version_bin(void)
Definition daemon.c:9538
_MHD_EXTERN const char * MHD_get_version(void)
Definition daemon.c:9507
_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:2559
#define XDLL_insert(head, tail, element)
Definition internal.h:2718
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_INIT
Definition internal.h:761
#define DLL_insert(head, tail, element)
Definition internal.h:2671
#define MHD_D_DOES_SCKT_FIT_FDSET_(sckt, d)
Definition internal.h:2614
@ 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:2555
#define EDLL_insert(head, tail, element)
Definition internal.h:2765
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition internal.h:1841
_MHD_static_inline struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *const daemon)
Definition internal.h:2913
#define _MHD_DROP_CONST(ptr)
Definition internal.h:77
#define MHD_D_GET_FD_SETSIZE_(d)
Definition internal.h:2608
#define MHD_BUF_INC_SIZE
Definition internal.h:142
#define EDLL_remove(head, tail, element)
Definition internal.h:2785
#define PRIu64
Definition internal.h:53
#define XDLL_remove(head, tail, element)
Definition internal.h:2740
#define MHD_D_IS_USING_THREAD_PER_CONN_(d)
Definition internal.h:2591
#define DLL_remove(head, tail, element)
Definition internal.h:2693
#define MHD_D_IS_USING_THREADS_(d)
Definition internal.h:2587
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition internal.h:249
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition internal.h:1855
#define MHD_D_IS_USING_EPOLL_(d)
Definition internal.h:2563
#define MHD_D_IS_THREAD_SAFE_(d)
Definition internal.h:2596
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:209
void MHD_pool_destroy(struct MemoryPool *pool)
Definition memorypool.c:341
struct MemoryPool * MHD_pool_create(size_t max)
Definition memorypool.c:270
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:1995
size_t MHD_str_pct_decode_in_place_strict_(char *str)
Definition mhd_str.c:1939
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_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
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:2142
MHD_NotifyConnectionCallback notify_connection
Definition internal.h:2049
MHD_AccessHandlerCallback default_handler
Definition internal.h:1873
LogCallback uri_log_callback
Definition internal.h:2063
bool data_already_pending
Definition internal.h:2247
union MHD_DaemonInfo daemon_info_dummy_port
Definition internal.h:2495
struct MHD_Connection * normal_timeout_tail
Definition internal.h:2006
bool at_limit
Definition internal.h:2225
struct MHD_Connection * new_connections_tail
Definition internal.h:1896
int client_discipline
Definition internal.h:2271
uint16_t port
Definition internal.h:2086
bool listen_nonblk
Definition internal.h:2117
unsigned int connection_limit
Definition internal.h:2252
void * unescape_callback_cls
Definition internal.h:2078
enum MHD_DisableSanityCheck insanity_level
Definition internal.h:2186
struct MHD_Connection * connections_tail
Definition internal.h:1906
struct MHD_Connection * suspended_connections_tail
Definition internal.h:1916
union MHD_DaemonInfo daemon_info_dummy_listen_fd
Definition internal.h:2473
struct MHD_Connection * manual_timeout_head
Definition internal.h:2014
unsigned int listen_backlog_size
Definition internal.h:2467
struct MHD_Connection * normal_timeout_head
Definition internal.h:1999
union MHD_DaemonInfo daemon_info_dummy_flags
Definition internal.h:2490
MHD_RequestCompletedCallback notify_completed
Definition internal.h:2038
struct MHD_Connection * cleanup_head
Definition internal.h:1921
unsigned int connections
Definition internal.h:2137
struct MHD_itc_ itc
Definition internal.h:2204
int listening_address_reuse
Definition internal.h:2197
uint64_t connection_timeout_ms
Definition internal.h:2259
void * apc_cls
Definition internal.h:2032
unsigned int per_ip_connection_limit
Definition internal.h:2265
struct MHD_Connection * manual_timeout_tail
Definition internal.h:2021
volatile bool shutdown
Definition internal.h:2209
union MHD_DaemonInfo daemon_info_dummy_num_connections
Definition internal.h:2485
enum MHD_FLAG options
Definition internal.h:1886
void * notify_connection_cls
Definition internal.h:2054
struct MHD_Connection * cleanup_tail
Definition internal.h:1926
bool sigpipe_blocked
Definition internal.h:2299
UnescapeCallback unescape_callback
Definition internal.h:2073
void * notify_completed_cls
Definition internal.h:2043
volatile bool was_quiesced
Definition internal.h:2216
struct MHD_Connection * suspended_connections_head
Definition internal.h:1911
struct MHD_Connection * new_connections_head
Definition internal.h:1891
int allow_bzero_in_url
Definition internal.h:2278
enum MHD_tristate listen_is_unix
Definition internal.h:1931
volatile bool resuming
Definition internal.h:2230
void * default_handler_cls
Definition internal.h:1878
struct MHD_Connection * connections_head
Definition internal.h:1901
MHD_AcceptPolicyCallback apc
Definition internal.h:2027
volatile bool have_new
Definition internal.h:2236
size_t pool_increment
Definition internal.h:2147
MHD_socket listen_fd
Definition internal.h:2112
void * per_ip_connection_count
Definition internal.h:2129
void * uri_log_callback_cls
Definition internal.h:2068
struct MHD_Daemon * master
Definition internal.h:2104
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