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