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