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