GNU libmicrohttpd 0.9.75
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-2021 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
48#if HAVE_SEARCH_H
49#include <search.h>
50#else
51#include "tsearch.h"
52#endif
53
54#ifdef HTTPS_SUPPORT
55#include "connection_https.h"
56#ifdef MHD_HTTPS_REQUIRE_GRYPT
57#include <gcrypt.h>
58#endif /* MHD_HTTPS_REQUIRE_GRYPT */
59#endif /* HTTPS_SUPPORT */
60
61#if defined(_WIN32) && ! defined(__CYGWIN__)
62#ifndef WIN32_LEAN_AND_MEAN
63#define WIN32_LEAN_AND_MEAN 1
64#endif /* !WIN32_LEAN_AND_MEAN */
65#include <windows.h>
66#endif
67
68#ifdef MHD_USE_POSIX_THREADS
69#ifdef HAVE_SIGNAL_H
70#include <signal.h>
71#endif /* HAVE_SIGNAL_H */
72#endif /* MHD_USE_POSIX_THREADS */
73
77#ifdef MHD_POSIX_SOCKETS
78#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
79#else
80#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
81#endif
82
86#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
87
88
89/* Forward declarations. */
90
99static void
100close_all_connections (struct MHD_Daemon *daemon);
101
102#ifdef EPOLL_SUPPORT
103
113static enum MHD_Result
114MHD_epoll (struct MHD_Daemon *daemon,
115 int32_t millisec);
116
117#endif /* EPOLL_SUPPORT */
118
128_MHD_NORETURN static void
129mhd_panic_std (void *cls,
130 const char *file,
131 unsigned int line,
132 const char *reason)
133{
134 (void) cls; /* Mute compiler warning. */
135#ifdef HAVE_MESSAGES
136 fprintf (stderr,
137 _ ("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
138 file,
139 line,
140 reason);
141#else /* ! HAVE_MESSAGES */
142 (void) file; /* Mute compiler warning. */
143 (void) line; /* Mute compiler warning. */
144 (void) reason; /* Mute compiler warning. */
145#endif
146 abort ();
147}
148
149
154
159
163void
164MHD_init (void);
165
166
167#if defined(MHD_WINSOCK_SOCKETS)
171static int mhd_winsock_inited_ = 0;
172#endif /* MHD_WINSOCK_SOCKETS */
173
174#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
179#define MHD_check_global_init_() (void) 0
180#else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
184volatile int global_init_count = 0;
185
186#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
187#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
191MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
192#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
193#endif
194
195
200void
202{
203#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
204#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
205 MHD_mutex_lock_chk_ (&global_init_mutex_);
206#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
207#endif
208 if (0 == global_init_count++)
209 MHD_init ();
210#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
211#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
212 MHD_mutex_unlock_chk_ (&global_init_mutex_);
213#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
214#endif
215}
216
217
218#endif /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
219
220#ifdef HAVE_MESSAGES
224static void
225MHD_default_logger_ (void *cls,
226 const char *fm,
227 va_list ap)
228{
229 vfprintf ((FILE *) cls, fm, ap);
230#ifdef _DEBUG
231 fflush ((FILE *) cls);
232#endif /* _DEBUG */
233}
234
235
236#endif /* HAVE_MESSAGES */
237
238
246_MHD_EXTERN void
247MHD_free (void *ptr)
248{
249 free (ptr);
250}
251
252
260static struct MHD_Daemon *
262{
263 while (NULL != daemon->master)
264 daemon = daemon->master;
265 return daemon;
266}
267
268
272struct MHD_IPCount
273{
277 int family;
278
282 union
283 {
287 struct in_addr ipv4;
288#if HAVE_INET6
292 struct in6_addr ipv6;
293#endif
294 } addr;
295
299 unsigned int count;
300};
301
302
308static void
310{
311#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
313#else
314 (void) daemon;
315#endif
316}
317
318
324static void
326{
327#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
329#else
330 (void) daemon;
331#endif
332}
333
334
344static int
345MHD_ip_addr_compare (const void *a1,
346 const void *a2)
347{
348 return memcmp (a1,
349 a2,
350 offsetof (struct MHD_IPCount,
351 count));
352}
353
354
363static enum MHD_Result
364MHD_ip_addr_to_key (const struct sockaddr *addr,
365 socklen_t addrlen,
366 struct MHD_IPCount *key)
367{
368 memset (key,
369 0,
370 sizeof(*key));
371
372 /* IPv4 addresses */
373 if (sizeof (struct sockaddr_in) == addrlen)
374 {
375 const struct sockaddr_in *addr4 = (const struct sockaddr_in *) addr;
376
377 key->family = AF_INET;
378 memcpy (&key->addr.ipv4,
379 &addr4->sin_addr,
380 sizeof(addr4->sin_addr));
381 return MHD_YES;
382 }
383
384#if HAVE_INET6
385 /* IPv6 addresses */
386 if (sizeof (struct sockaddr_in6) == addrlen)
387 {
388 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
389
390 key->family = AF_INET6;
391 memcpy (&key->addr.ipv6,
392 &addr6->sin6_addr,
393 sizeof(addr6->sin6_addr));
394 return MHD_YES;
395 }
396#endif
397
398 /* Some other address */
399 return MHD_NO;
400}
401
402
414static enum MHD_Result
416 const struct sockaddr *addr,
417 socklen_t addrlen)
418{
419 struct MHD_IPCount *key;
420 void **nodep;
421 void *node;
422 enum MHD_Result result;
423
424 daemon = MHD_get_master (daemon);
425 /* Ignore if no connection limit assigned */
426 if (0 == daemon->per_ip_connection_limit)
427 return MHD_YES;
428
429 if (NULL == (key = malloc (sizeof(*key))))
430 return MHD_NO;
431
432 /* Initialize key */
433 if (MHD_NO == MHD_ip_addr_to_key (addr,
434 addrlen,
435 key))
436 {
437 /* Allow unhandled address types through */
438 free (key);
439 return MHD_YES;
440 }
441 MHD_ip_count_lock (daemon);
442
443 /* Search for the IP address */
444 if (NULL == (nodep = tsearch (key,
447 {
448#ifdef HAVE_MESSAGES
449 MHD_DLOG (daemon,
450 _ ("Failed to add IP connection count node.\n"));
451#endif
452 MHD_ip_count_unlock (daemon);
453 free (key);
454 return MHD_NO;
455 }
456 node = *nodep;
457 /* If we got an existing node back, free the one we created */
458 if (node != key)
459 free (key);
460 key = (struct MHD_IPCount *) node;
461 /* Test if there is room for another connection; if so,
462 * increment count */
463 result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
464 if (MHD_NO != result)
465 ++key->count;
466
467 MHD_ip_count_unlock (daemon);
468 return result;
469}
470
471
480static void
482 const struct sockaddr *addr,
483 socklen_t addrlen)
484{
485 struct MHD_IPCount search_key;
486 struct MHD_IPCount *found_key;
487 void **nodep;
488
489 daemon = MHD_get_master (daemon);
490 /* Ignore if no connection limit assigned */
491 if (0 == daemon->per_ip_connection_limit)
492 return;
493 /* Initialize search key */
494 if (MHD_NO == MHD_ip_addr_to_key (addr,
495 addrlen,
496 &search_key))
497 return;
498
499 MHD_ip_count_lock (daemon);
500
501 /* Search for the IP address */
502 if (NULL == (nodep = tfind (&search_key,
505 {
506 /* Something's wrong if we couldn't find an IP address
507 * that was previously added */
508 MHD_PANIC (_ ("Failed to find previously-added IP address.\n"));
509 }
510 found_key = (struct MHD_IPCount *) *nodep;
511 /* Validate existing count for IP address */
512 if (0 == found_key->count)
513 {
514 MHD_PANIC (_ ("Previously-added IP address had counter of zero.\n"));
515 }
516 /* Remove the node entirely if count reduces to 0 */
517 if (0 == --found_key->count)
518 {
519 tdelete (found_key,
522 free (found_key);
523 }
524
525 MHD_ip_count_unlock (daemon);
526}
527
528
529#ifdef HTTPS_SUPPORT
536static int
537MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
538{
539 gnutls_datum_t key;
540 gnutls_datum_t cert;
541 int ret;
542
543#if GNUTLS_VERSION_MAJOR >= 3
544 if (NULL != daemon->cert_callback)
545 {
546 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
547 daemon->cert_callback);
548 }
549#endif
550#if GNUTLS_VERSION_NUMBER >= 0x030603
551 else if (NULL != daemon->cert_callback2)
552 {
553 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
554 daemon->cert_callback2);
555 }
556#endif
557
558 if (NULL != daemon->https_mem_trust)
559 {
560 size_t paramlen;
561 paramlen = strlen (daemon->https_mem_trust);
562 if (UINT_MAX < paramlen)
563 {
564#ifdef HAVE_MESSAGES
565 MHD_DLOG (daemon,
566 _ ("Too long trust certificate.\n"));
567#endif
568 return -1;
569 }
570 cert.data = (unsigned char *) daemon->https_mem_trust;
571 cert.size = (unsigned int) paramlen;
572 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
573 &cert,
574 GNUTLS_X509_FMT_PEM) < 0)
575 {
576#ifdef HAVE_MESSAGES
577 MHD_DLOG (daemon,
578 _ ("Bad trust certificate format.\n"));
579#endif
580 return -1;
581 }
582 }
583
584 if (daemon->have_dhparams)
585 {
586 gnutls_certificate_set_dh_params (daemon->x509_cred,
587 daemon->https_mem_dhparams);
588 }
589 /* certificate & key loaded from memory */
590 if ( (NULL != daemon->https_mem_cert) &&
591 (NULL != daemon->https_mem_key) )
592 {
593 size_t param1len;
594 size_t param2len;
595
596 param1len = strlen (daemon->https_mem_key);
597 param2len = strlen (daemon->https_mem_cert);
598 if ( (UINT_MAX < param1len) ||
599 (UINT_MAX < param2len) )
600 {
601#ifdef HAVE_MESSAGES
602 MHD_DLOG (daemon,
603 _ ("Too long key or certificate.\n"));
604#endif
605 return -1;
606 }
607 key.data = (unsigned char *) daemon->https_mem_key;
608 key.size = (unsigned int) param1len;
609 cert.data = (unsigned char *) daemon->https_mem_cert;
610 cert.size = (unsigned int) param2len;
611
612 if (NULL != daemon->https_key_password)
613 {
614#if GNUTLS_VERSION_NUMBER >= 0x030111
615 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
616 &cert,
617 &key,
618 GNUTLS_X509_FMT_PEM,
619 daemon->https_key_password,
620 0);
621#else
622#ifdef HAVE_MESSAGES
623 MHD_DLOG (daemon,
624 _ ("Failed to setup x509 certificate/key: pre 3.X.X version " \
625 "of GnuTLS does not support setting key password.\n"));
626#endif
627 return -1;
628#endif
629 }
630 else
631 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
632 &cert,
633 &key,
634 GNUTLS_X509_FMT_PEM);
635#ifdef HAVE_MESSAGES
636 if (0 != ret)
637 MHD_DLOG (daemon,
638 _ ("GnuTLS failed to setup x509 certificate/key: %s\n"),
639 gnutls_strerror (ret));
640#endif
641 return ret;
642 }
643#if GNUTLS_VERSION_MAJOR >= 3
644 if (NULL != daemon->cert_callback)
645 return 0;
646#endif
647#if GNUTLS_VERSION_NUMBER >= 0x030603
648 else if (NULL != daemon->cert_callback2)
649 return 0;
650#endif
651#ifdef HAVE_MESSAGES
652 MHD_DLOG (daemon,
653 _ ("You need to specify a certificate and key location.\n"));
654#endif
655 return -1;
656}
657
658
665static int
666MHD_TLS_init (struct MHD_Daemon *daemon)
667{
668 switch (daemon->cred_type)
669 {
670 case GNUTLS_CRD_CERTIFICATE:
671 if (0 !=
672 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
673 return GNUTLS_E_MEMORY_ERROR;
674 return MHD_init_daemon_certificate (daemon);
675 case GNUTLS_CRD_PSK:
676 if (0 !=
677 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
678 return GNUTLS_E_MEMORY_ERROR;
679 return 0;
680 default:
681#ifdef HAVE_MESSAGES
682 MHD_DLOG (daemon,
683 _ ("Error: invalid credentials type %d specified.\n"),
684 daemon->cred_type);
685#endif
686 return -1;
687 }
688}
689
690
691#endif /* HTTPS_SUPPORT */
692
693
694#undef MHD_get_fdset
695
727enum MHD_Result
728MHD_get_fdset (struct MHD_Daemon *daemon,
729 fd_set *read_fd_set,
730 fd_set *write_fd_set,
731 fd_set *except_fd_set,
732 MHD_socket *max_fd)
733{
734 return MHD_get_fdset2 (daemon,
735 read_fd_set,
736 write_fd_set,
737 except_fd_set,
738 max_fd,
740}
741
742
743#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
756static bool
757urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
758 fd_set *rs,
759 fd_set *ws,
760 fd_set *es,
761 MHD_socket *max_fd,
762 unsigned int fd_setsize)
763{
764 const MHD_socket conn_sckt = urh->connection->socket_fd;
765 const MHD_socket mhd_sckt = urh->mhd.socket;
766 bool res = true;
767
768 /* Do not add to 'es' only if socket is closed
769 * or not used anymore. */
770 if (MHD_INVALID_SOCKET != conn_sckt)
771 {
772 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
773 (! MHD_add_to_fd_set_ (conn_sckt,
774 rs,
775 max_fd,
776 fd_setsize)) )
777 res = false;
778 if ( (0 != urh->out_buffer_used) &&
779 (! MHD_add_to_fd_set_ (conn_sckt,
780 ws,
781 max_fd,
782 fd_setsize)) )
783 res = false;
784 /* Do not monitor again for errors if error was detected before as
785 * error state is remembered. */
786 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
787 ((0 != urh->in_buffer_size) ||
788 (0 != urh->out_buffer_size) ||
789 (0 != urh->out_buffer_used)))
790 MHD_add_to_fd_set_ (conn_sckt,
791 es,
792 max_fd,
793 fd_setsize);
794 }
795 if (MHD_INVALID_SOCKET != mhd_sckt)
796 {
797 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
798 (! MHD_add_to_fd_set_ (mhd_sckt,
799 rs,
800 max_fd,
801 fd_setsize)) )
802 res = false;
803 if ( (0 != urh->in_buffer_used) &&
804 (! MHD_add_to_fd_set_ (mhd_sckt,
805 ws,
806 max_fd,
807 fd_setsize)) )
808 res = false;
809 /* Do not monitor again for errors if error was detected before as
810 * error state is remembered. */
811 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
812 ((0 != urh->out_buffer_size) ||
813 (0 != urh->in_buffer_size) ||
814 (0 != urh->in_buffer_used)))
815 MHD_add_to_fd_set_ (mhd_sckt,
816 es,
817 max_fd,
818 fd_setsize);
819 }
820
821 return res;
822}
823
824
834static void
835urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
836 const fd_set *rs,
837 const fd_set *ws,
838 const fd_set *es)
839{
840 const MHD_socket conn_sckt = urh->connection->socket_fd;
841 const MHD_socket mhd_sckt = urh->mhd.socket;
842
843 /* Reset read/write ready, preserve error state. */
844 urh->app.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
846 urh->mhd.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
848
849 if (MHD_INVALID_SOCKET != conn_sckt)
850 {
851 if (FD_ISSET (conn_sckt, rs))
852 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
853 if (FD_ISSET (conn_sckt, ws))
854 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
855 if (FD_ISSET (conn_sckt, es))
856 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
857 }
858 if ((MHD_INVALID_SOCKET != mhd_sckt))
859 {
860 if (FD_ISSET (mhd_sckt, rs))
861 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
862 if (FD_ISSET (mhd_sckt, ws))
863 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
864 if (FD_ISSET (mhd_sckt, es))
865 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
866 }
867}
868
869
870#ifdef HAVE_POLL
871
880static void
881urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
882 struct pollfd p[2])
883{
884 p[0].events = 0;
885 p[1].events = 0;
886
887 if (urh->in_buffer_used < urh->in_buffer_size)
888 p[0].events |= POLLIN;
889 if (0 != urh->out_buffer_used)
890 p[0].events |= POLLOUT;
891
892 /* Do not monitor again for errors if error was detected before as
893 * error state is remembered. */
894 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
895 ((0 != urh->in_buffer_size) ||
896 (0 != urh->out_buffer_size) ||
897 (0 != urh->out_buffer_used)))
898 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
899
900 if (urh->out_buffer_used < urh->out_buffer_size)
901 p[1].events |= POLLIN;
902 if (0 != urh->in_buffer_used)
903 p[1].events |= POLLOUT;
904
905 /* Do not monitor again for errors if error was detected before as
906 * error state is remembered. */
907 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
908 ((0 != urh->out_buffer_size) ||
909 (0 != urh->in_buffer_size) ||
910 (0 != urh->in_buffer_used)))
911 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
912}
913
914
921static void
922urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
923 struct pollfd p[2])
924{
925 p[0].fd = urh->connection->socket_fd;
926 p[1].fd = urh->mhd.socket;
927 urh_update_pollfd (urh,
928 p);
929}
930
931
937static void
938urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
939 struct pollfd p[2])
940{
941 /* Reset read/write ready, preserve error state. */
942 urh->app.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
944 urh->mhd.celi &= (~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY)
946
947 if (0 != (p[0].revents & POLLIN))
948 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
949 if (0 != (p[0].revents & POLLOUT))
950 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
951 if (0 != (p[0].revents & POLLHUP))
953 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
954 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
955 if (0 != (p[1].revents & POLLIN))
956 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
957 if (0 != (p[1].revents & POLLOUT))
958 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
959 if (0 != (p[1].revents & POLLHUP))
960 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
961 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
963}
964
965
966#endif /* HAVE_POLL */
967#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
968
969
984static enum MHD_Result
986 fd_set *read_fd_set,
987 fd_set *write_fd_set,
988 fd_set *except_fd_set,
989 MHD_socket *max_fd,
990 unsigned int fd_setsize)
991
992{
993 struct MHD_Connection *pos;
994 struct MHD_Connection *posn;
995 enum MHD_Result result = MHD_YES;
996 MHD_socket ls;
997
998 if (daemon->shutdown)
999 return MHD_NO;
1000
1001 ls = daemon->listen_fd;
1002 if ( (MHD_INVALID_SOCKET != ls) &&
1003 (! daemon->was_quiesced) &&
1004 (! MHD_add_to_fd_set_ (ls,
1005 read_fd_set,
1006 max_fd,
1007 fd_setsize)) )
1008 result = MHD_NO;
1009
1010 /* Add all sockets to 'except_fd_set' as well to watch for
1011 * out-of-band data. However, ignore errors if INFO_READ
1012 * or INFO_WRITE sockets will not fit 'except_fd_set'. */
1013 /* Start from oldest connections. Make sense for W32 FDSETs. */
1014 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1015 {
1016 posn = pos->prev;
1017
1018 switch (pos->event_loop_info)
1019 {
1021 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1022 read_fd_set,
1023 max_fd,
1024 fd_setsize))
1025 result = MHD_NO;
1026#ifdef MHD_POSIX_SOCKETS
1028 except_fd_set,
1029 max_fd,
1030 fd_setsize);
1031#endif /* MHD_POSIX_SOCKETS */
1032 break;
1034 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1035 write_fd_set,
1036 max_fd,
1037 fd_setsize))
1038 result = MHD_NO;
1039#ifdef MHD_POSIX_SOCKETS
1041 except_fd_set,
1042 max_fd,
1043 fd_setsize);
1044#endif /* MHD_POSIX_SOCKETS */
1045 break;
1047 if ( (NULL == except_fd_set) ||
1049 except_fd_set,
1050 max_fd,
1051 fd_setsize))
1052 result = MHD_NO;
1053 break;
1055 /* this should never happen */
1056 break;
1057 }
1058 }
1059#ifdef MHD_WINSOCK_SOCKETS
1060 /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
1061 * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
1062 * not be pushed out. */
1063 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1064 {
1065 posn = pos->prev;
1067 except_fd_set,
1068 max_fd,
1069 fd_setsize);
1070 }
1071#endif /* MHD_WINSOCK_SOCKETS */
1072#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1073 {
1074 struct MHD_UpgradeResponseHandle *urh;
1075
1076 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
1077 {
1078 if (MHD_NO ==
1079 urh_to_fdset (urh,
1080 read_fd_set,
1081 write_fd_set,
1082 except_fd_set,
1083 max_fd,
1084 fd_setsize))
1085 result = MHD_NO;
1086 }
1087 }
1088#endif
1089#if _MHD_DEBUG_CONNECT
1090#ifdef HAVE_MESSAGES
1091 if (NULL != max_fd)
1092 MHD_DLOG (daemon,
1093 _ ("Maximum socket in select set: %d\n"),
1094 *max_fd);
1095#endif
1096#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1097 return result;
1098}
1099
1100
1135enum MHD_Result
1137 fd_set *read_fd_set,
1138 fd_set *write_fd_set,
1139 fd_set *except_fd_set,
1140 MHD_socket *max_fd,
1141 unsigned int fd_setsize)
1142{
1143 fd_set es;
1144
1145 if ( (NULL == daemon) ||
1146 (NULL == read_fd_set) ||
1147 (NULL == write_fd_set) ||
1148 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ||
1149 (0 != (daemon->options & MHD_USE_POLL)))
1150 return MHD_NO;
1151
1152 if (NULL == except_fd_set)
1153 { /* Workaround to maintain backward compatibility. */
1154#ifdef HAVE_MESSAGES
1155 MHD_DLOG (daemon,
1156 _ ("MHD_get_fdset2() called with except_fd_set "
1157 "set to NULL. Such behavior is unsupported.\n"));
1158#endif
1159 FD_ZERO (&es);
1160 except_fd_set = &es;
1161 }
1162
1163#ifdef EPOLL_SUPPORT
1164 if (0 != (daemon->options & MHD_USE_EPOLL))
1165 {
1166 if (daemon->shutdown)
1167 return MHD_NO;
1168
1169 /* we're in epoll mode, use the epoll FD as a stand-in for
1170 the entire event set */
1171
1172 return MHD_add_to_fd_set_ (daemon->epoll_fd,
1173 read_fd_set,
1174 max_fd,
1175 fd_setsize) ? MHD_YES : MHD_NO;
1176 }
1177#endif
1178
1179 return internal_get_fdset2 (daemon,
1180 read_fd_set,
1181 write_fd_set,
1182 except_fd_set,
1183 max_fd,
1184 fd_setsize);
1185}
1186
1187
1201static enum MHD_Result
1203 bool read_ready,
1204 bool write_ready,
1205 bool force_close)
1206{
1207 enum MHD_Result ret;
1208 bool states_info_processed = false;
1209 /* Fast track flag */
1210 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1211
1212#ifdef HTTPS_SUPPORT
1213 if (con->tls_read_ready)
1214 read_ready = true;
1215#endif /* HTTPS_SUPPORT */
1217 (read_ready || (force_close && con->sk_nonblck)) )
1218 {
1219 MHD_connection_handle_read (con, force_close);
1220 mhd_assert (! force_close || MHD_CONNECTION_CLOSED == con->state);
1221 ret = MHD_connection_handle_idle (con);
1222 if (force_close)
1223 return ret;
1224 states_info_processed = true;
1225 }
1226 if (! force_close)
1227 {
1228 /* No need to check value of 'ret' here as closed connection
1229 * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1231 write_ready)
1232 {
1234 ret = MHD_connection_handle_idle (con);
1235 states_info_processed = true;
1236 }
1237 }
1238 else
1239 {
1242 return MHD_connection_handle_idle (con);
1243 }
1244
1245 if (! states_info_processed)
1246 { /* Connection is not read or write ready, but external conditions
1247 * may be changed and need to be processed. */
1248 ret = MHD_connection_handle_idle (con);
1249 }
1250 /* Fast track for fast connections. */
1251 /* If full request was read by single read_handler() invocation
1252 and headers were completely prepared by single MHD_connection_handle_idle()
1253 then try not to wait for next sockets polling and send response
1254 immediately.
1255 As writeability of socket was not checked and it may have
1256 some data pending in system buffers, use this optimization
1257 only for non-blocking sockets. */
1258 /* No need to check 'ret' as connection is always in
1259 * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1260 else if (on_fasttrack && con->sk_nonblck)
1261 {
1263 {
1265 /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1266 ret = MHD_connection_handle_idle (con);
1267 }
1268 /* If all headers were sent by single write_handler() and
1269 * response body is prepared by single MHD_connection_handle_idle()
1270 * call - continue. */
1273 {
1275 ret = MHD_connection_handle_idle (con);
1276 }
1277 }
1278
1279 /* All connection's data and states are processed for this turn.
1280 * If connection already has more data to be processed - use
1281 * zero timeout for next select()/poll(). */
1282 /* Thread-per-connection do not need global zero timeout as
1283 * connections are processed individually. */
1284 /* Note: no need to check for read buffer availability for
1285 * TLS read-ready connection in 'read info' state as connection
1286 * without space in read buffer will be marked as 'info block'. */
1287 if ( (! con->daemon->data_already_pending) &&
1289 {
1291 con->daemon->data_already_pending = true;
1292#ifdef HTTPS_SUPPORT
1293 else if ( (con->tls_read_ready) &&
1295 con->daemon->data_already_pending = true;
1296#endif /* HTTPS_SUPPORT */
1297 }
1298 return ret;
1299}
1300
1301
1302#ifdef UPGRADE_SUPPORT
1310static void
1311cleanup_upgraded_connection (struct MHD_Connection *connection)
1312{
1313 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1314
1315 if (NULL == urh)
1316 return;
1317#ifdef HTTPS_SUPPORT
1318 /* Signal remote client the end of TLS connection by
1319 * gracefully closing TLS session. */
1320 if (0 != (connection->daemon->options & MHD_USE_TLS))
1321 gnutls_bye (connection->tls_session,
1322 GNUTLS_SHUT_WR);
1323
1324 if (MHD_INVALID_SOCKET != urh->mhd.socket)
1325 MHD_socket_close_chk_ (urh->mhd.socket);
1326
1327 if (MHD_INVALID_SOCKET != urh->app.socket)
1328 MHD_socket_close_chk_ (urh->app.socket);
1329#endif /* HTTPS_SUPPORT */
1330 connection->urh = NULL;
1331 free (urh);
1332}
1333
1334
1335#endif /* UPGRADE_SUPPORT */
1336
1337
1338#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1347static void
1348process_urh (struct MHD_UpgradeResponseHandle *urh)
1349{
1350 /* Help compiler to optimize:
1351 * pointers to 'connection' and 'daemon' are not changed
1352 * during this processing, so no need to chain dereference
1353 * each time. */
1354 struct MHD_Connection *const connection = urh->connection;
1355 struct MHD_Daemon *const daemon = connection->daemon;
1356 /* Prevent data races: use same value of 'was_closed' throughout
1357 * this function. If 'was_closed' changed externally in the middle
1358 * of processing - it will be processed on next iteration. */
1359 bool was_closed;
1360
1361#ifdef MHD_USE_THREADS
1362 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1363 MHD_thread_ID_match_current_ (connection->pid) );
1364#endif /* MHD_USE_THREADS */
1365 if (daemon->shutdown)
1366 {
1367 /* Daemon shutting down, application will not receive any more data. */
1368#ifdef HAVE_MESSAGES
1369 if (! urh->was_closed)
1370 {
1371 MHD_DLOG (daemon,
1372 _ (
1373 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1374 }
1375#endif
1376 urh->was_closed = true;
1377 }
1378 was_closed = urh->was_closed;
1379 if (was_closed)
1380 {
1381 /* Application was closed connections: no more data
1382 * can be forwarded to application socket. */
1383 if (0 < urh->in_buffer_used)
1384 {
1385#ifdef HAVE_MESSAGES
1386 MHD_DLOG (daemon,
1387 _ ("Failed to forward to application "
1388 "%" PRIu64 \
1389 " bytes of data received from remote side: application shut down socket.\n"),
1390 (uint64_t) urh->in_buffer_used);
1391#endif
1392
1393 }
1394 /* If application signaled MHD about socket closure then
1395 * check for any pending data even if socket is not marked
1396 * as 'ready' (signal may arrive after poll()/select()).
1397 * Socketpair for forwarding is always in non-blocking mode
1398 * so no risk that recv() will block the thread. */
1399 if (0 != urh->out_buffer_size)
1400 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1401 /* Discard any data received form remote. */
1402 urh->in_buffer_used = 0;
1403 /* Do not try to push data to application. */
1404 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1405 /* Reading from remote client is not required anymore. */
1406 urh->in_buffer_size = 0;
1407 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1408 connection->tls_read_ready = false;
1409 }
1410
1411 /* On some platforms (W32, possibly Darwin) failed send() (send() will
1412 * always fail after remote disconnect was detected) may discard data in
1413 * system buffers received by system but not yet read by recv(). So, before
1414 * trying send() on any socket, recv() must be performed at first otherwise
1415 * last part of incoming data may be lost. If disconnect or error was
1416 * detected - try to read from socket to dry data possibly pending is system
1417 * buffers. */
1418 if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1419 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1420 if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1421 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1422
1423 /*
1424 * handle reading from remote TLS client
1425 */
1426 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1427 (connection->tls_read_ready) ) &&
1428 (urh->in_buffer_used < urh->in_buffer_size) )
1429 {
1430 ssize_t res;
1431 size_t buf_size;
1432
1433 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1434 if (buf_size > SSIZE_MAX)
1435 buf_size = SSIZE_MAX;
1436
1437 connection->tls_read_ready = false;
1438 res = gnutls_record_recv (connection->tls_session,
1439 &urh->in_buffer[urh->in_buffer_used],
1440 buf_size);
1441 if (0 >= res)
1442 {
1443 if (GNUTLS_E_INTERRUPTED != res)
1444 {
1445 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1446 if (GNUTLS_E_AGAIN != res)
1447 {
1448 /* Unrecoverable error on socket was detected or
1449 * socket was disconnected/shut down. */
1450 /* Stop trying to read from this TLS socket. */
1451 urh->in_buffer_size = 0;
1452 }
1453 }
1454 }
1455 else /* 0 < res */
1456 {
1457 urh->in_buffer_used += res;
1458 if (0 < gnutls_record_check_pending (connection->tls_session))
1459 {
1460 connection->tls_read_ready = true;
1461 }
1462 }
1465 {
1466 /* Unrecoverable error on socket was detected and all
1467 * pending data was read from system buffers. */
1468 /* Stop trying to read from this TLS socket. */
1469 urh->in_buffer_size = 0;
1470 }
1471 }
1472
1473 /*
1474 * handle reading from application
1475 */
1476 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1477 (urh->out_buffer_used < urh->out_buffer_size) )
1478 {
1479 ssize_t res;
1480 size_t buf_size;
1481
1482 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1483 if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1484 buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1485
1486 res = MHD_recv_ (urh->mhd.socket,
1487 &urh->out_buffer[urh->out_buffer_used],
1488 buf_size);
1489 if (0 >= res)
1490 {
1491 const int err = MHD_socket_get_error_ ();
1492 if ((0 == res) ||
1493 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1495 {
1496 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1497 if ((0 == res) ||
1498 (was_closed) ||
1499 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1500 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1501 {
1502 /* Socket disconnect/shutdown was detected;
1503 * Application signaled about closure of 'upgraded' socket;
1504 * or persistent / unrecoverable error. */
1505 /* Do not try to pull more data from application. */
1506 urh->out_buffer_size = 0;
1507 }
1508 }
1509 }
1510 else /* 0 < res */
1511 {
1512 urh->out_buffer_used += res;
1513 if (buf_size > (size_t) res)
1514 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1515 }
1516 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1517 ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1518 (was_closed) ) )
1519 {
1520 /* Unrecoverable error on socket was detected and all
1521 * pending data was read from system buffers. */
1522 /* Do not try to pull more data from application. */
1523 urh->out_buffer_size = 0;
1524 }
1525 }
1526
1527 /*
1528 * handle writing to remote HTTPS client
1529 */
1530 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1531 (urh->out_buffer_used > 0) )
1532 {
1533 ssize_t res;
1534 size_t data_size;
1535
1536 data_size = urh->out_buffer_used;
1537 if (data_size > SSIZE_MAX)
1538 data_size = SSIZE_MAX;
1539
1540 res = gnutls_record_send (connection->tls_session,
1541 urh->out_buffer,
1542 data_size);
1543 if (0 >= res)
1544 {
1545 if (GNUTLS_E_INTERRUPTED != res)
1546 {
1547 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1548 if (GNUTLS_E_AGAIN != res)
1549 {
1550 /* TLS connection shut down or
1551 * persistent / unrecoverable error. */
1552#ifdef HAVE_MESSAGES
1553 MHD_DLOG (daemon,
1554 _ (
1555 "Failed to forward to remote client "
1556 "%" PRIu64 \
1557 " bytes of data received from application: %s\n"),
1558 (uint64_t) urh->out_buffer_used,
1559 gnutls_strerror (res));
1560#endif
1561 /* Discard any data unsent to remote. */
1562 urh->out_buffer_used = 0;
1563 /* Do not try to pull more data from application. */
1564 urh->out_buffer_size = 0;
1565 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1566 }
1567 }
1568 }
1569 else /* 0 < res */
1570 {
1571 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1572 if (0 != next_out_buffer_used)
1573 {
1574 memmove (urh->out_buffer,
1575 &urh->out_buffer[res],
1576 next_out_buffer_used);
1577 if (data_size > (size_t) res)
1578 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1579 }
1580 urh->out_buffer_used = next_out_buffer_used;
1581 }
1582 if ( (0 == urh->out_buffer_used) &&
1583 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1584 {
1585 /* Unrecoverable error on socket was detected and all
1586 * pending data was sent to remote. */
1587 /* Do not try to send to remote anymore. */
1588 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1589 /* Do not try to pull more data from application. */
1590 urh->out_buffer_size = 0;
1591 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1592 }
1593 }
1594
1595 /*
1596 * handle writing to application
1597 */
1598 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1599 (urh->in_buffer_used > 0) )
1600 {
1601 ssize_t res;
1602 size_t data_size;
1603
1604 data_size = urh->in_buffer_used;
1605 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1606 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1607
1608 res = MHD_send_ (urh->mhd.socket,
1609 urh->in_buffer,
1610 data_size);
1611 if (0 >= res)
1612 {
1613 const int err = MHD_socket_get_error_ ();
1614 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1616 {
1617 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1618 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1619 {
1620 /* Socketpair connection shut down or
1621 * persistent / unrecoverable error. */
1622#ifdef HAVE_MESSAGES
1623 MHD_DLOG (daemon,
1624 _ (
1625 "Failed to forward to application "
1626 "%" PRIu64 \
1627 " bytes of data received from remote side: %s\n"),
1628 (uint64_t) urh->in_buffer_used,
1629 MHD_socket_strerr_ (err));
1630#endif
1631 /* Discard any data received form remote. */
1632 urh->in_buffer_used = 0;
1633 /* Reading from remote client is not required anymore. */
1634 urh->in_buffer_size = 0;
1635 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1636 connection->tls_read_ready = false;
1637 }
1638 }
1639 }
1640 else /* 0 < res */
1641 {
1642 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1643 if (0 != next_in_buffer_used)
1644 {
1645 memmove (urh->in_buffer,
1646 &urh->in_buffer[res],
1647 next_in_buffer_used);
1648 if (data_size > (size_t) res)
1649 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1650 }
1651 urh->in_buffer_used = next_in_buffer_used;
1652 }
1653 if ( (0 == urh->in_buffer_used) &&
1654 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1655 {
1656 /* Do not try to push data to application. */
1657 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1658 /* Reading from remote client is not required anymore. */
1659 urh->in_buffer_size = 0;
1660 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1661 connection->tls_read_ready = false;
1662 }
1663 }
1664
1665 /* Check whether data is present in TLS buffers
1666 * and incoming forward buffer have some space. */
1667 if ( (connection->tls_read_ready) &&
1668 (urh->in_buffer_used < urh->in_buffer_size) &&
1669 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1670 daemon->data_already_pending = true;
1671
1672 if ( (daemon->shutdown) &&
1673 ( (0 != urh->out_buffer_size) ||
1674 (0 != urh->out_buffer_used) ) )
1675 {
1676 /* Daemon shutting down, discard any remaining forward data. */
1677#ifdef HAVE_MESSAGES
1678 if (0 < urh->out_buffer_used)
1679 MHD_DLOG (daemon,
1680 _ (
1681 "Failed to forward to remote client "
1682 "%" PRIu64 \
1683 " bytes of data received from application: daemon shut down.\n"),
1684 (uint64_t) urh->out_buffer_used);
1685#endif
1686 /* Discard any data unsent to remote. */
1687 urh->out_buffer_used = 0;
1688 /* Do not try to sent to remote anymore. */
1689 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1690 /* Do not try to pull more data from application. */
1691 urh->out_buffer_size = 0;
1692 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1693 }
1694}
1695
1696
1697#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1698
1699#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1700#ifdef UPGRADE_SUPPORT
1709static void
1710thread_main_connection_upgrade (struct MHD_Connection *con)
1711{
1712#ifdef HTTPS_SUPPORT
1713 struct MHD_UpgradeResponseHandle *urh = con->urh;
1714 struct MHD_Daemon *daemon = con->daemon;
1715
1716 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1717 MHD_thread_ID_match_current_ (con->pid) );
1718 /* Here, we need to bi-directionally forward
1719 until the application tells us that it is done
1720 with the socket; */
1721 if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1722 (0 == (daemon->options & MHD_USE_POLL)))
1723 {
1724 while ( (0 != urh->in_buffer_size) ||
1725 (0 != urh->out_buffer_size) ||
1726 (0 != urh->in_buffer_used) ||
1727 (0 != urh->out_buffer_used) )
1728 {
1729 /* use select */
1730 fd_set rs;
1731 fd_set ws;
1732 fd_set es;
1733 MHD_socket max_fd;
1734 int num_ready;
1735 bool result;
1736
1737 FD_ZERO (&rs);
1738 FD_ZERO (&ws);
1739 FD_ZERO (&es);
1740 max_fd = MHD_INVALID_SOCKET;
1741 result = urh_to_fdset (urh,
1742 &rs,
1743 &ws,
1744 &es,
1745 &max_fd,
1746 FD_SETSIZE);
1747 if (! result)
1748 {
1749#ifdef HAVE_MESSAGES
1750 MHD_DLOG (con->daemon,
1751 _ ("Error preparing select.\n"));
1752#endif
1753 break;
1754 }
1755 /* FIXME: does this check really needed? */
1756 if (MHD_INVALID_SOCKET != max_fd)
1757 {
1758 struct timeval *tvp;
1759 struct timeval tv;
1760 if (((con->tls_read_ready) &&
1761 (urh->in_buffer_used < urh->in_buffer_size)) ||
1762 (daemon->shutdown))
1763 { /* No need to wait if incoming data is already pending in TLS buffers. */
1764 tv.tv_sec = 0;
1765 tv.tv_usec = 0;
1766 tvp = &tv;
1767 }
1768 else
1769 tvp = NULL;
1770 num_ready = MHD_SYS_select_ (max_fd + 1,
1771 &rs,
1772 &ws,
1773 &es,
1774 tvp);
1775 }
1776 else
1777 num_ready = 0;
1778 if (num_ready < 0)
1779 {
1780 const int err = MHD_socket_get_error_ ();
1781
1782 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1783 continue;
1784#ifdef HAVE_MESSAGES
1785 MHD_DLOG (con->daemon,
1786 _ ("Error during select (%d): `%s'\n"),
1787 err,
1788 MHD_socket_strerr_ (err));
1789#endif
1790 break;
1791 }
1792 urh_from_fdset (urh,
1793 &rs,
1794 &ws,
1795 &es);
1796 process_urh (urh);
1797 }
1798 }
1799#ifdef HAVE_POLL
1800 else if (0 != (daemon->options & MHD_USE_TLS))
1801 {
1802 /* use poll() */
1803 struct pollfd p[2];
1804 memset (p,
1805 0,
1806 sizeof (p));
1807 p[0].fd = urh->connection->socket_fd;
1808 p[1].fd = urh->mhd.socket;
1809
1810 while ( (0 != urh->in_buffer_size) ||
1811 (0 != urh->out_buffer_size) ||
1812 (0 != urh->in_buffer_used) ||
1813 (0 != urh->out_buffer_used) )
1814 {
1815 int timeout;
1816
1817 urh_update_pollfd (urh, p);
1818
1819 if (((con->tls_read_ready) &&
1820 (urh->in_buffer_used < urh->in_buffer_size)) ||
1821 (daemon->shutdown))
1822 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1823 else
1824 timeout = -1;
1825
1826 if (MHD_sys_poll_ (p,
1827 2,
1828 timeout) < 0)
1829 {
1830 const int err = MHD_socket_get_error_ ();
1831
1832 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1833 continue;
1834#ifdef HAVE_MESSAGES
1835 MHD_DLOG (con->daemon,
1836 _ ("Error during poll: `%s'\n"),
1837 MHD_socket_strerr_ (err));
1838#endif
1839 break;
1840 }
1841 urh_from_pollfd (urh,
1842 p);
1843 process_urh (urh);
1844 }
1845 }
1846 /* end POLL */
1847#endif
1848 /* end HTTPS */
1849#endif /* HTTPS_SUPPORT */
1850 /* TLS forwarding was finished. Cleanup socketpair. */
1852 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1853 * in connection thread for a little while. */
1854}
1855
1856
1857#endif /* UPGRADE_SUPPORT */
1858
1859
1867static uint64_t
1868connection_get_wait (struct MHD_Connection *c)
1869{
1870 const uint64_t now = MHD_monotonic_msec_counter ();
1871 const uint64_t since_actv = now - c->last_activity;
1872 const uint64_t timeout = c->connection_timeout_ms;
1873 uint64_t mseconds_left;
1874
1875 mhd_assert (0 != timeout);
1876 /* Keep the next lines in sync with #connection_check_timedout() to avoid
1877 * undesired side-effects like busy-waiting. */
1878 if (timeout < since_actv)
1879 {
1880 if (UINT64_MAX / 2 < since_actv)
1881 {
1882 const uint64_t jump_back = c->last_activity - now;
1883 /* Very unlikely that it is more than quarter-million years pause.
1884 * More likely that system clock jumps back. */
1885 if (5000 >= jump_back)
1886 { /* Jump back is less than 5 seconds, try to recover. */
1887 return 100; /* Set wait time to 0.1 seconds */
1888 }
1889 /* Too large jump back */
1890 }
1891 return 0; /* Connection has timed out */
1892 }
1893 else if (since_actv == timeout)
1894 {
1895 /* Exact match for timeout and time from last activity.
1896 * Maybe this is just a precise match or this happens because the timer
1897 * resolution is too low.
1898 * Set wait time to 0.1 seconds to avoid busy-waiting with low
1899 * timer resolution as connection is not timed-out yet. */
1900 return 100;
1901 }
1902 mseconds_left = timeout - since_actv;
1903
1904 return mseconds_left;
1905}
1906
1907
1915static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1917{
1918 struct MHD_Connection *con = data;
1919 struct MHD_Daemon *daemon = con->daemon;
1920 int num_ready;
1921 fd_set rs;
1922 fd_set ws;
1923 fd_set es;
1924 MHD_socket maxsock;
1925 struct timeval tv;
1926 struct timeval *tvp;
1927#if WINDOWS
1928#ifdef HAVE_POLL
1929 int extra_slot;
1930#endif /* HAVE_POLL */
1931#define EXTRA_SLOTS 1
1932#else /* !WINDOWS */
1933#define EXTRA_SLOTS 0
1934#endif /* !WINDOWS */
1935#ifdef HAVE_POLL
1936 struct pollfd p[1 + EXTRA_SLOTS];
1937#endif
1938#undef EXTRA_SLOTS
1939#ifdef HAVE_POLL
1940 const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1941#else /* ! HAVE_POLL */
1942 const bool use_poll = 0;
1943#endif /* ! HAVE_POLL */
1944 bool was_suspended = false;
1945 MHD_thread_init_ (&(con->pid));
1946
1947 while ( (! daemon->shutdown) &&
1948 (MHD_CONNECTION_CLOSED != con->state) )
1949 {
1950 uint64_t timeout = con->connection_timeout_ms;
1951#ifdef UPGRADE_SUPPORT
1952 struct MHD_UpgradeResponseHandle *const urh = con->urh;
1953#else /* ! UPGRADE_SUPPORT */
1954 static const void *const urh = NULL;
1955#endif /* ! UPGRADE_SUPPORT */
1956
1957 if ( (con->suspended) &&
1958 (NULL == urh) )
1959 {
1960 /* Connection was suspended, wait for resume. */
1961 was_suspended = true;
1962 if (! use_poll)
1963 {
1964 FD_ZERO (&rs);
1965 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1966 &rs,
1967 NULL,
1968 FD_SETSIZE))
1969 {
1970 #ifdef HAVE_MESSAGES
1971 MHD_DLOG (con->daemon,
1972 _ ("Failed to add FD to fd_set.\n"));
1973 #endif
1974 goto exit;
1975 }
1976 if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
1977 &rs,
1978 NULL,
1979 NULL,
1980 NULL))
1981 {
1982 const int err = MHD_socket_get_error_ ();
1983
1984 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1985 continue;
1986#ifdef HAVE_MESSAGES
1987 MHD_DLOG (con->daemon,
1988 _ ("Error during select (%d): `%s'\n"),
1989 err,
1990 MHD_socket_strerr_ (err));
1991#endif
1992 break;
1993 }
1994 }
1995#ifdef HAVE_POLL
1996 else /* use_poll */
1997 {
1998 p[0].events = POLLIN;
1999 p[0].fd = MHD_itc_r_fd_ (daemon->itc);
2000 p[0].revents = 0;
2001 if (0 > MHD_sys_poll_ (p,
2002 1,
2003 -1))
2004 {
2006 continue;
2007#ifdef HAVE_MESSAGES
2008 MHD_DLOG (con->daemon,
2009 _ ("Error during poll: `%s'\n"),
2011#endif
2012 break;
2013 }
2014 }
2015#endif /* HAVE_POLL */
2016 MHD_itc_clear_ (daemon->itc);
2017 continue; /* Check again for resume. */
2018 } /* End of "suspended" branch. */
2019
2020 if (was_suspended)
2021 {
2022 MHD_update_last_activity_ (con); /* Reset timeout timer. */
2023 /* Process response queued during suspend and update states. */
2025 was_suspended = false;
2026 }
2027
2028 tvp = NULL;
2029
2031#ifdef HTTPS_SUPPORT
2032 || ( (con->tls_read_ready) &&
2034#endif /* HTTPS_SUPPORT */
2035 )
2036 {
2037 /* do not block: more data may be inside of TLS buffers waiting or
2038 * application must provide response data */
2039 tv.tv_sec = 0;
2040 tv.tv_usec = 0;
2041 tvp = &tv;
2042 }
2043 if ( (NULL == tvp) &&
2044 (timeout > 0) )
2045 {
2046 const uint64_t mseconds_left = connection_get_wait (con);
2047#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
2048 if (mseconds_left / 1000 > TIMEVAL_TV_SEC_MAX)
2049 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
2050 else
2051#endif /* (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC */
2052 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) mseconds_left / 1000;
2053
2054 tv.tv_usec = (mseconds_left % 1000) * 1000;
2055
2056 tvp = &tv;
2057 }
2058 if (! use_poll)
2059 {
2060 /* use select */
2061 bool err_state = false;
2062
2063 FD_ZERO (&rs);
2064 FD_ZERO (&ws);
2065 FD_ZERO (&es);
2066 maxsock = MHD_INVALID_SOCKET;
2067 switch (con->event_loop_info)
2068 {
2070 if (! MHD_add_to_fd_set_ (con->socket_fd,
2071 &rs,
2072 &maxsock,
2073 FD_SETSIZE))
2074 err_state = true;
2075 break;
2077 if (! MHD_add_to_fd_set_ (con->socket_fd,
2078 &ws,
2079 &maxsock,
2080 FD_SETSIZE))
2081 err_state = true;
2082 break;
2084 if (! MHD_add_to_fd_set_ (con->socket_fd,
2085 &es,
2086 &maxsock,
2087 FD_SETSIZE))
2088 err_state = true;
2089 break;
2091 /* how did we get here!? */
2092 goto exit;
2093 }
2094#if WINDOWS
2095 if (MHD_ITC_IS_VALID_ (daemon->itc) )
2096 {
2097 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2098 &rs,
2099 &maxsock,
2100 FD_SETSIZE))
2101 err_state = 1;
2102 }
2103#endif
2104 if (err_state)
2105 {
2106#ifdef HAVE_MESSAGES
2107 MHD_DLOG (con->daemon,
2108 _ ("Failed to add FD to fd_set.\n"));
2109#endif
2110 goto exit;
2111 }
2112
2113 num_ready = MHD_SYS_select_ (maxsock + 1,
2114 &rs,
2115 &ws,
2116 &es,
2117 tvp);
2118 if (num_ready < 0)
2119 {
2120 const int err = MHD_socket_get_error_ ();
2121
2122 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2123 continue;
2124#ifdef HAVE_MESSAGES
2125 MHD_DLOG (con->daemon,
2126 _ ("Error during select (%d): `%s'\n"),
2127 err,
2128 MHD_socket_strerr_ (err));
2129#endif
2130 break;
2131 }
2132#if WINDOWS
2133 /* Clear ITC before other processing so additional
2134 * signals will trigger select() again */
2135 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2136 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2137 &rs)) )
2138 MHD_itc_clear_ (daemon->itc);
2139#endif
2140 if (MHD_NO ==
2141 call_handlers (con,
2142 FD_ISSET (con->socket_fd,
2143 &rs),
2144 FD_ISSET (con->socket_fd,
2145 &ws),
2146 FD_ISSET (con->socket_fd,
2147 &es)) )
2148 goto exit;
2149 }
2150#ifdef HAVE_POLL
2151 else
2152 {
2153 /* use poll */
2154 memset (&p,
2155 0,
2156 sizeof (p));
2157 p[0].fd = con->socket_fd;
2158 switch (con->event_loop_info)
2159 {
2161 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2162 break;
2164 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2165 break;
2167 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2168 break;
2170 /* how did we get here!? */
2171 goto exit;
2172 }
2173#if WINDOWS
2174 extra_slot = 0;
2175 if (MHD_ITC_IS_VALID_ (daemon->itc))
2176 {
2177 p[1].events |= POLLIN;
2178 p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2179 p[1].revents = 0;
2180 extra_slot = 1;
2181 }
2182#endif
2183 if (MHD_sys_poll_ (p,
2184#if WINDOWS
2185 1 + extra_slot,
2186#else
2187 1,
2188#endif
2189 (NULL == tvp) ? -1 : (tv.tv_sec * 1000)) < 0)
2190 {
2192 continue;
2193#ifdef HAVE_MESSAGES
2194 MHD_DLOG (con->daemon,
2195 _ ("Error during poll: `%s'\n"),
2197#endif
2198 break;
2199 }
2200#if WINDOWS
2201 /* Clear ITC before other processing so additional
2202 * signals will trigger poll() again */
2203 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2204 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2205 MHD_itc_clear_ (daemon->itc);
2206#endif
2207 if (MHD_NO ==
2208 call_handlers (con,
2209 (0 != (p[0].revents & POLLIN)),
2210 (0 != (p[0].revents & POLLOUT)),
2211 (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC)) ))
2212 goto exit;
2213 }
2214#endif
2215#ifdef UPGRADE_SUPPORT
2216 if (MHD_CONNECTION_UPGRADE == con->state)
2217 {
2218 /* Normal HTTP processing is finished,
2219 * notify application. */
2220 if ( (NULL != daemon->notify_completed) &&
2221 (con->client_aware) )
2222 daemon->notify_completed (daemon->notify_completed_cls,
2223 con,
2224 &con->client_context,
2226 con->client_aware = false;
2227
2228 thread_main_connection_upgrade (con);
2229 /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2230
2231 /* "Upgraded" data will not be used in this thread from this point. */
2232 con->urh->clean_ready = true;
2233 /* If 'urh->was_closed' set to true, connection will be
2234 * moved immediately to cleanup list. Otherwise connection
2235 * will stay in suspended list until 'urh' will be marked
2236 * with 'was_closed' by application. */
2238
2239 /* skip usual clean up */
2240 return (MHD_THRD_RTRN_TYPE_) 0;
2241 }
2242#endif /* UPGRADE_SUPPORT */
2243 }
2244#if _MHD_DEBUG_CLOSE
2245#ifdef HAVE_MESSAGES
2246 MHD_DLOG (con->daemon,
2247 _ ("Processing thread terminating. Closing connection.\n"));
2248#endif
2249#endif
2250 if (MHD_CONNECTION_CLOSED != con->state)
2252 (daemon->shutdown) ?
2256exit:
2257 if (NULL != con->response)
2258 {
2260 con->response = NULL;
2261 }
2262
2263 if (MHD_INVALID_SOCKET != con->socket_fd)
2264 {
2265 shutdown (con->socket_fd,
2266 SHUT_WR);
2267 /* 'socket_fd' can be used in other thread to signal shutdown.
2268 * To avoid data races, do not close socket here. Daemon will
2269 * use more connections only after cleanup anyway. */
2270 }
2271 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2272 (! MHD_itc_activate_ (daemon->itc, "t")) )
2273 {
2274#ifdef HAVE_MESSAGES
2275 MHD_DLOG (daemon,
2276 _ (
2277 "Failed to signal thread termination via inter-thread communication channel.\n"));
2278#endif
2279 }
2280 return (MHD_THRD_RTRN_TYPE_) 0;
2281}
2282
2283
2284#endif
2285
2286
2294static void
2295MHD_cleanup_connections (struct MHD_Daemon *daemon);
2296
2297#if defined(HTTPS_SUPPORT)
2298#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2299 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2300 ! defined(MHD_socket_nosignal_) && \
2301 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2307#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2308#endif /* MHD_SEND_SPIPE_SUPPRESS_NEEDED &&
2309 MHD_SEND_SPIPE_SUPPRESS_POSSIBLE &&
2310 ! MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) &&
2311 MSG_NOSIGNAL */
2312
2313#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2318static ssize_t
2319MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2320 const void *data,
2321 size_t data_size)
2322{
2323#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2324 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2325 data_size = MHD_SCKT_SEND_MAX_SIZE_;
2326#endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2327 return MHD_send_ ((MHD_socket) (intptr_t) (trnsp), data, data_size);
2328}
2329
2330
2331#endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2332
2333
2342static int
2343psk_gnutls_adapter (gnutls_session_t session,
2344 const char *username,
2345 gnutls_datum_t *key)
2346{
2347 struct MHD_Connection *connection;
2348 struct MHD_Daemon *daemon;
2349#if GNUTLS_VERSION_MAJOR >= 3
2350 void *app_psk;
2351 size_t app_psk_size;
2352#endif /* GNUTLS_VERSION_MAJOR >= 3 */
2353
2354 connection = gnutls_session_get_ptr (session);
2355 if (NULL == connection)
2356 {
2357#ifdef HAVE_MESSAGES
2358 /* Cannot use our logger, we don't even have "daemon" */
2359 MHD_PANIC (_ ("Internal server error. This should be impossible.\n"));
2360#endif
2361 return -1;
2362 }
2363 daemon = connection->daemon;
2364#if GNUTLS_VERSION_MAJOR >= 3
2365 if (NULL == daemon->cred_callback)
2366 {
2367#ifdef HAVE_MESSAGES
2368 MHD_DLOG (daemon,
2369 _ ("PSK not supported by this server.\n"));
2370#endif
2371 return -1;
2372 }
2373 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2374 connection,
2375 username,
2376 &app_psk,
2377 &app_psk_size))
2378 return -1;
2379 if (NULL == (key->data = gnutls_malloc (app_psk_size)))
2380 {
2381#ifdef HAVE_MESSAGES
2382 MHD_DLOG (daemon,
2383 _ (
2384 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2385#endif
2386 free (app_psk);
2387 return -1;
2388 }
2389 if (UINT_MAX < app_psk_size)
2390 {
2391#ifdef HAVE_MESSAGES
2392 MHD_DLOG (daemon,
2393 _ ("PSK authentication failed: PSK too long.\n"));
2394#endif
2395 free (app_psk);
2396 return -1;
2397 }
2398 key->size = (unsigned int) app_psk_size;
2399 memcpy (key->data,
2400 app_psk,
2401 app_psk_size);
2402 free (app_psk);
2403 return 0;
2404#else
2405 (void) username; (void) key; /* Mute compiler warning */
2406#ifdef HAVE_MESSAGES
2407 MHD_DLOG (daemon,
2408 _ ("PSK not supported by this server.\n"));
2409#endif
2410 return -1;
2411#endif
2412}
2413
2414
2415#endif /* HTTPS_SUPPORT */
2416
2417
2440static struct MHD_Connection *
2442 MHD_socket client_socket,
2443 const struct sockaddr *addr,
2444 socklen_t addrlen,
2445 bool external_add,
2446 bool non_blck,
2447 bool sk_spipe_supprs,
2448 enum MHD_tristate sk_is_nonip)
2449{
2450 struct MHD_Connection *connection;
2451 int eno = 0;
2452
2453#ifdef HAVE_MESSAGES
2454#if _MHD_DEBUG_CONNECT
2455 MHD_DLOG (daemon,
2456 _ ("Accepted connection on socket %d.\n"),
2457 client_socket);
2458#endif
2459#endif
2462 addr,
2463 addrlen)) )
2464 {
2465 /* above connection limit - reject */
2466#ifdef HAVE_MESSAGES
2467 MHD_DLOG (daemon,
2468 _ (
2469 "Server reached connection limit. Closing inbound connection.\n"));
2470#endif
2471 MHD_socket_close_chk_ (client_socket);
2472#if ENFILE
2473 errno = ENFILE;
2474#endif
2475 return NULL;
2476 }
2477
2478 /* apply connection acceptance policy if present */
2479 if ( (NULL != daemon->apc) &&
2481 addr,
2482 addrlen)) )
2483 {
2484#if _MHD_DEBUG_CLOSE
2485#ifdef HAVE_MESSAGES
2486 MHD_DLOG (daemon,
2487 _ ("Connection rejected by application. Closing connection.\n"));
2488#endif
2489#endif
2490 MHD_socket_close_chk_ (client_socket);
2492 addr,
2493 addrlen);
2494#if EACCESS
2495 errno = EACCESS;
2496#endif
2497 return NULL;
2498 }
2499
2500 if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2501 {
2502 eno = errno;
2503#ifdef HAVE_MESSAGES
2504 MHD_DLOG (daemon,
2505 _ ("Error allocating memory: %s\n"),
2506 MHD_strerror_ (errno));
2507#endif
2508 MHD_socket_close_chk_ (client_socket);
2510 addr,
2511 addrlen);
2512 errno = eno;
2513 return NULL;
2514 }
2515
2516 if (! external_add)
2517 {
2518 connection->sk_corked = _MHD_OFF;
2519 connection->sk_nodelay = _MHD_OFF;
2520 }
2521 else
2522 {
2523 connection->sk_corked = _MHD_UNKNOWN;
2524 connection->sk_nodelay = _MHD_UNKNOWN;
2525 }
2526
2527 if (NULL == (connection->addr = malloc (addrlen)))
2528 {
2529 eno = errno;
2530#ifdef HAVE_MESSAGES
2531 MHD_DLOG (daemon,
2532 _ ("Error allocating memory: %s\n"),
2533 MHD_strerror_ (errno));
2534#endif
2535 MHD_socket_close_chk_ (client_socket);
2537 addr,
2538 addrlen);
2539 free (connection);
2540 errno = eno;
2541 return NULL;
2542 }
2543 memcpy (connection->addr,
2544 addr,
2545 addrlen);
2546 connection->addr_len = addrlen;
2547 connection->socket_fd = client_socket;
2548 connection->sk_nonblck = non_blck;
2549 connection->is_nonip = sk_is_nonip;
2550 connection->sk_spipe_suppress = sk_spipe_supprs;
2551 connection->daemon = daemon;
2553 if (0 != connection->connection_timeout_ms)
2555
2556 if (0 == (daemon->options & MHD_USE_TLS))
2557 {
2558 /* set default connection handlers */
2559 MHD_set_http_callbacks_ (connection);
2560 }
2561 else
2562 {
2563#ifdef HTTPS_SUPPORT
2564#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2565 gnutls_init_flags_t
2566#else
2567 unsigned int
2568#endif
2569 flags;
2570
2571 flags = GNUTLS_SERVER;
2572#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2573 flags |= GNUTLS_NO_SIGNAL;
2574#endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2575#if GNUTLS_VERSION_MAJOR >= 3
2576 flags |= GNUTLS_NONBLOCK;
2577#endif /* GNUTLS_VERSION_MAJOR >= 3*/
2578#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2580 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2581#endif
2582#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2584 flags |= GNUTLS_ENABLE_EARLY_DATA;
2585#endif
2586 connection->tls_state = MHD_TLS_CONN_INIT;
2587 MHD_set_https_callbacks (connection);
2588 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2589 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2590 daemon->priority_cache)))
2591 {
2592 if (NULL != connection->tls_session)
2593 gnutls_deinit (connection->tls_session);
2594 MHD_socket_close_chk_ (client_socket);
2596 addr,
2597 addrlen);
2598 free (connection->addr);
2599 free (connection);
2600#ifdef HAVE_MESSAGES
2601 MHD_DLOG (daemon,
2602 _ ("Failed to initialise TLS session.\n"));
2603#endif
2604#if EPROTO
2605 errno = EPROTO;
2606#endif
2607 return NULL;
2608 }
2609#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2610 if (! daemon->disable_alpn)
2611 {
2612 gnutls_datum_t prts[2];
2613 const char prt1[] = "http/1.1"; /* Registered code for HTTP/1.1 */
2614 const char prt2[] = "http/1.0"; /* Registered code for HTTP/1.0 */
2615
2616 prts[0].data = (void *) prt1;
2617 prts[0].size = MHD_STATICSTR_LEN_ (prt1);
2618 prts[1].data = (void *) prt2;
2619 prts[1].size = MHD_STATICSTR_LEN_ (prt2);
2620 if (GNUTLS_E_SUCCESS !=
2621 gnutls_alpn_set_protocols (connection->tls_session,
2622 prts,
2623 sizeof(prts) / sizeof(prts[0]),
2624 0 /* || GNUTLS_ALPN_SERVER_PRECEDENCE */))
2625 {
2626#ifdef HAVE_MESSAGES
2627 MHD_DLOG (daemon,
2628 _ ("Failed to set ALPN protocols.\n"));
2629#else /* ! HAVE_MESSAGES */
2630 (void) 0; /* Mute compiler warning */
2631#endif /* ! HAVE_MESSAGES */
2632 }
2633 }
2634#endif /* GNUTLS_VERSION_NUMBER >= 0x030200 */
2635 gnutls_session_set_ptr (connection->tls_session,
2636 connection);
2637 switch (daemon->cred_type)
2638 {
2639 /* set needed credentials for certificate authentication. */
2640 case GNUTLS_CRD_CERTIFICATE:
2641 gnutls_credentials_set (connection->tls_session,
2642 GNUTLS_CRD_CERTIFICATE,
2643 daemon->x509_cred);
2644 break;
2645 case GNUTLS_CRD_PSK:
2646 gnutls_credentials_set (connection->tls_session,
2647 GNUTLS_CRD_PSK,
2648 daemon->psk_cred);
2649 gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2650 &psk_gnutls_adapter);
2651 break;
2652 default:
2653#ifdef HAVE_MESSAGES
2654 MHD_DLOG (daemon,
2655 _ (
2656 "Failed to setup TLS credentials: unknown credential type %d.\n"),
2657 daemon->cred_type);
2658#endif
2659 gnutls_deinit (connection->tls_session);
2660 MHD_socket_close_chk_ (client_socket);
2662 addr,
2663 addrlen);
2664 free (connection->addr);
2665 free (connection);
2666 MHD_PANIC (_ ("Unknown credential type.\n"));
2667#if EINVAL
2668 errno = EINVAL;
2669#endif
2670 return NULL;
2671 }
2672#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2673 gnutls_transport_set_int (connection->tls_session,
2674 (int) (client_socket));
2675#else /* GnuTLS before 3.1.9 or Win x64 */
2676 gnutls_transport_set_ptr (connection->tls_session,
2677 (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2678#endif /* GnuTLS before 3.1.9 or Win x64 */
2679#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2680 gnutls_transport_set_push_function (connection->tls_session,
2681 MHD_tls_push_func_);
2682#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2683 if (daemon->https_mem_trust)
2684 gnutls_certificate_server_set_request (connection->tls_session,
2685 GNUTLS_CERT_REQUEST);
2686#else /* ! HTTPS_SUPPORT */
2687 MHD_socket_close_chk_ (client_socket);
2689 addr,
2690 addrlen);
2691 free (connection->addr);
2692 free (connection);
2693 MHD_PANIC (_ ("TLS connection on non-TLS daemon.\n"));
2694 eno = EINVAL;
2695 return NULL;
2696#endif /* ! HTTPS_SUPPORT */
2697 }
2698
2699 return connection;
2700}
2701
2702
2703#ifdef MHD_USE_THREADS
2709static void
2710new_connection_close_ (struct MHD_Daemon *daemon,
2711 struct MHD_Connection *connection)
2712{
2713 mhd_assert (connection->daemon == daemon);
2714 mhd_assert (! connection->in_cleanup);
2715 mhd_assert (NULL == connection->next);
2716 mhd_assert (NULL == connection->nextX);
2717#ifdef EPOLL_SUPPORT
2718 mhd_assert (NULL == connection->nextE);
2719#endif /* EPOLL_SUPPORT */
2720
2721#ifdef HTTPS_SUPPORT
2722 if (NULL != connection->tls_session)
2723 {
2725 gnutls_deinit (connection->tls_session);
2726 }
2727#endif /* HTTPS_SUPPORT */
2728 MHD_socket_close_chk_ (connection->socket_fd);
2730 connection->addr,
2731 connection->addr_len);
2732 free (connection->addr);
2733 free (connection);
2734}
2735
2736
2737#endif /* MHD_USE_THREADS */
2738
2739
2750static enum MHD_Result
2752 struct MHD_Connection *connection)
2753{
2754 int eno = 0;
2755
2756 mhd_assert (connection->daemon == daemon);
2757
2758#ifdef MHD_USE_THREADS
2759 /* Function manipulate connection and timeout DL-lists,
2760 * must be called only within daemon thread. */
2762 MHD_thread_ID_match_current_ (daemon->pid) );
2763#endif /* MHD_USE_THREADS */
2764
2765 /* Allocate memory pool in the processing thread so
2766 * intensively used memory area is allocated in "good"
2767 * (for the thread) memory region. It is important with
2768 * NUMA and/or complex cache hierarchy. */
2769 connection->pool = MHD_pool_create (daemon->pool_size);
2770 if (NULL == connection->pool)
2771 { /* 'pool' creation failed */
2772#ifdef HAVE_MESSAGES
2773 MHD_DLOG (daemon,
2774 _ ("Error allocating memory: %s\n"),
2775 MHD_strerror_ (errno));
2776#endif
2777#if ENOMEM
2778 eno = ENOMEM;
2779#endif
2780 (void) 0; /* Mute possible compiler warning */
2781 }
2782 else
2783 { /* 'pool' creation succeed */
2785 /* Firm check under lock. */
2787 { /* Connections limit */
2788#ifdef HAVE_MESSAGES
2789 MHD_DLOG (daemon,
2790 _ ("Server reached connection limit. "
2791 "Closing inbound connection.\n"));
2792#endif
2793#if ENFILE
2794 eno = ENFILE;
2795#endif
2796 (void) 0; /* Mute possible compiler warning */
2797 }
2798 else
2799 { /* Have space for new connection */
2803 connection);
2805 {
2808 connection);
2809 }
2813 connection,
2814 &connection->socket_context,
2816#ifdef MHD_USE_THREADS
2818 {
2820 if (! MHD_create_named_thread_ (&connection->pid,
2821 "MHD-connection",
2822 daemon->thread_stack_size,
2824 connection))
2825 {
2826 eno = errno;
2827#ifdef HAVE_MESSAGES
2828#ifdef EAGAIN
2829 if (EAGAIN == eno)
2830 MHD_DLOG (daemon,
2831 _ ("Failed to create a new thread because it would "
2832 "have exceeded the system limit on the number of "
2833 "threads or no system resources available.\n"));
2834 else
2835#endif /* EAGAIN */
2836 MHD_DLOG (daemon,
2837 _ ("Failed to create a thread: %s\n"),
2838 MHD_strerror_ (eno));
2839#endif /* HAVE_MESSAGES */
2840 }
2841 else /* New thread has been created successfully */
2842 return MHD_YES; /* *** Function success exit point *** */
2843 }
2844 else
2845#else /* ! MHD_USE_THREADS */
2846 if (1)
2847#endif /* ! MHD_USE_THREADS */
2848 { /* No 'thread-per-connection' */
2849#ifdef MHD_USE_THREADS
2850 connection->pid = daemon->pid;
2851#endif /* MHD_USE_THREADS */
2852#ifdef EPOLL_SUPPORT
2853 if (0 != (daemon->options & MHD_USE_EPOLL))
2854 {
2855 if (0 == (daemon->options & MHD_USE_TURBO))
2856 {
2857 struct epoll_event event;
2858
2859 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2860 event.data.ptr = connection;
2861 if (0 != epoll_ctl (daemon->epoll_fd,
2862 EPOLL_CTL_ADD,
2863 connection->socket_fd,
2864 &event))
2865 {
2866 eno = errno;
2867#ifdef HAVE_MESSAGES
2868 MHD_DLOG (daemon,
2869 _ ("Call to epoll_ctl failed: %s\n"),
2871#endif
2872 }
2873 else
2874 { /* 'socket_fd' has been added to 'epool' */
2875 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2876
2877 return MHD_YES; /* *** Function success exit point *** */
2878 }
2879 }
2880 else
2881 {
2882 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
2885 EDLL_insert (daemon->eready_head,
2886 daemon->eready_tail,
2887 connection);
2888
2889 return MHD_YES; /* *** Function success exit point *** */
2890 }
2891 }
2892 else /* No 'epoll' */
2893#endif /* EPOLL_SUPPORT */
2894 return MHD_YES; /* *** Function success exit point *** */
2895 }
2896
2897 /* ** Below is a cleanup path ** */
2898 if (NULL != daemon->notify_connection)
2900 connection,
2901 &connection->socket_context,
2904 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2905 {
2907 daemon->normal_timeout_tail,
2908 connection);
2909 }
2911 daemon->connections_tail,
2912 connection);
2913 daemon->connections--;
2915 }
2916 MHD_pool_destroy (connection->pool);
2917 }
2918 /* Free resources allocated before the call of this functions */
2919#ifdef HTTPS_SUPPORT
2920 if (NULL != connection->tls_session)
2921 gnutls_deinit (connection->tls_session);
2922#endif /* HTTPS_SUPPORT */
2923 MHD_ip_limit_del (daemon,
2924 connection->addr,
2925 connection->addr_len);
2926 free (connection->addr);
2927 MHD_socket_close_chk_ (connection->socket_fd);
2928 free (connection);
2929 if (0 != eno)
2930 errno = eno;
2931#ifdef EINVAL
2932 else
2933 errno = EINVAL;
2934#endif /* EINVAL */
2935 return MHD_NO; /* *** Function failure exit point *** */
2936}
2937
2938
2967static enum MHD_Result
2969 MHD_socket client_socket,
2970 const struct sockaddr *addr,
2971 socklen_t addrlen,
2972 bool external_add,
2973 bool non_blck,
2974 bool sk_spipe_supprs,
2975 enum MHD_tristate sk_is_nonip)
2976{
2977 struct MHD_Connection *connection;
2978
2979#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2980 /* Direct add to master daemon could never happen. */
2982#endif
2983
2984 if ( (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
2985 (! MHD_SCKT_FD_FITS_FDSET_ (client_socket, NULL)) )
2986 {
2987#ifdef HAVE_MESSAGES
2988 MHD_DLOG (daemon,
2989 _ ("New connection socket descriptor (%d) is not less " \
2990 "than FD_SETSIZE (%d).\n"),
2991 (int) client_socket,
2992 (int) FD_SETSIZE);
2993#endif
2994 MHD_socket_close_chk_ (client_socket);
2995#if ENFILE
2996 errno = ENFILE;
2997#endif
2998 return MHD_NO;
2999 }
3000
3001 if ( (0 == (daemon->options & MHD_USE_EPOLL)) &&
3002 (! non_blck) )
3003 {
3004#ifdef HAVE_MESSAGES
3005 MHD_DLOG (daemon,
3006 _ ("Epoll mode supports only non-blocking sockets\n"));
3007#endif
3008 MHD_socket_close_chk_ (client_socket);
3009#if EINVAL
3010 errno = EINVAL;
3011#endif
3012 return MHD_NO;
3013 }
3014
3015 connection = new_connection_prepare_ (daemon,
3016 client_socket,
3017 addr, addrlen,
3018 external_add,
3019 non_blck,
3020 sk_spipe_supprs,
3021 sk_is_nonip);
3022 if (NULL == connection)
3023 return MHD_NO;
3024
3025 if ((external_add) &&
3027 {
3028 /* Connection is added externally and MHD is handling its own threads. */
3029 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3032 connection);
3033 daemon->have_new = true;
3034 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3035
3036 /* The rest of connection processing must be handled in
3037 * the daemon thread. */
3038 if ((MHD_ITC_IS_VALID_ (daemon->itc)) &&
3039 (! MHD_itc_activate_ (daemon->itc, "n")))
3040 {
3041 #ifdef HAVE_MESSAGES
3042 MHD_DLOG (daemon,
3043 _ ("Failed to signal new connection via inter-thread " \
3044 "communication channel.\n"));
3045 #endif
3046 }
3047 return MHD_YES;
3048 }
3049
3050 return new_connection_process_ (daemon, connection);
3051}
3052
3053
3054static void
3056{
3057 struct MHD_Connection *local_head;
3058 struct MHD_Connection *local_tail;
3061
3062 /* Detach DL-list of new connections from the daemon for
3063 * following local processing. */
3064 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3066 local_head = daemon->new_connections_head;
3067 local_tail = daemon->new_connections_tail;
3070 daemon->have_new = false;
3071 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3072 (void) local_head; /* Mute compiler warning */
3073
3074 /* Process new connections in FIFO order. */
3075 do
3076 {
3077 struct MHD_Connection *c;
3079 c = local_tail;
3080 DLL_remove (local_head,
3081 local_tail,
3082 c);
3083 mhd_assert (daemon == c->daemon);
3085 {
3086#ifdef HAVE_MESSAGES
3087 MHD_DLOG (daemon,
3088 _ ("Failed to start serving new connection.\n"));
3089#endif
3090 (void) 0;
3091 }
3092 } while (NULL != local_tail);
3093
3094}
3095
3096
3106void
3108{
3109 struct MHD_Daemon *daemon = connection->daemon;
3110
3111#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3112 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3113 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3114 MHD_thread_ID_match_current_ (daemon->pid) );
3116#endif
3117 if (connection->resuming)
3118 {
3119 /* suspending again while we didn't even complete resuming yet */
3120 connection->resuming = false;
3121#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3123#endif
3124 return;
3125 }
3126 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3127 {
3128 if (connection->connection_timeout_ms == daemon->connection_timeout_ms)
3130 daemon->normal_timeout_tail,
3131 connection);
3132 else
3134 daemon->manual_timeout_tail,
3135 connection);
3136 }
3138 daemon->connections_tail,
3139 connection);
3140 mhd_assert (! connection->suspended);
3143 connection);
3144 connection->suspended = true;
3145#ifdef EPOLL_SUPPORT
3146 if (0 != (daemon->options & MHD_USE_EPOLL))
3147 {
3148 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3149 {
3150 EDLL_remove (daemon->eready_head,
3151 daemon->eready_tail,
3152 connection);
3153 connection->epoll_state &=
3155 }
3156 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
3157 {
3158 if (0 != epoll_ctl (daemon->epoll_fd,
3159 EPOLL_CTL_DEL,
3160 connection->socket_fd,
3161 NULL))
3162 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3163 connection->epoll_state &=
3165 }
3166 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
3167 }
3168#endif
3169#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3171#endif
3172}
3173
3174
3207void
3209{
3210 struct MHD_Daemon *const daemon = connection->daemon;
3211
3212#ifdef MHD_USE_THREADS
3213 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3214 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3215 MHD_thread_ID_match_current_ (daemon->pid) );
3216#endif /* MHD_USE_THREADS */
3217
3218 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3219 MHD_PANIC (_ (
3220 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3221#ifdef UPGRADE_SUPPORT
3222 if (NULL != connection->urh)
3223 {
3224#ifdef HAVE_MESSAGES
3225 MHD_DLOG (daemon,
3226 _ (
3227 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
3228#endif /* HAVE_MESSAGES */
3229 return;
3230 }
3231#endif /* UPGRADE_SUPPORT */
3232 internal_suspend_connection_ (connection);
3233}
3234
3235
3244void
3246{
3247 struct MHD_Daemon *daemon = connection->daemon;
3248
3249 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3250 MHD_PANIC (_ (
3251 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3252#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3254#endif
3255 connection->resuming = true;
3256 daemon->resuming = true;
3257#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3259#endif
3260 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3261 (! MHD_itc_activate_ (daemon->itc, "r")) )
3262 {
3263#ifdef HAVE_MESSAGES
3264 MHD_DLOG (daemon,
3265 _ (
3266 "Failed to signal resume via inter-thread communication channel.\n"));
3267#endif
3268 }
3269}
3270
3271
3281static enum MHD_Result
3283{
3284 struct MHD_Connection *pos;
3285 struct MHD_Connection *prev = NULL;
3286 enum MHD_Result ret;
3287 const bool used_thr_p_c = (0 != (daemon->options
3289#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3292 MHD_thread_ID_match_current_ (daemon->pid) );
3293#endif
3294
3295 ret = MHD_NO;
3296#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3298#endif
3299
3300 if (daemon->resuming)
3301 {
3303 /* During shutdown check for resuming is forced. */
3304 mhd_assert ((NULL != prev) || (daemon->shutdown) || \
3305 (0 != (daemon->options & MHD_ALLOW_UPGRADE)));
3306 }
3307
3308 daemon->resuming = false;
3309
3310 while (NULL != (pos = prev))
3311 {
3312#ifdef UPGRADE_SUPPORT
3313 struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3314#else /* ! UPGRADE_SUPPORT */
3315 static const void *const urh = NULL;
3316#endif /* ! UPGRADE_SUPPORT */
3317 prev = pos->prev;
3318 if ( (! pos->resuming)
3319#ifdef UPGRADE_SUPPORT
3320 || ( (NULL != urh) &&
3321 ( (! urh->was_closed) ||
3322 (! urh->clean_ready) ) )
3323#endif /* UPGRADE_SUPPORT */
3324 )
3325 continue;
3326 ret = MHD_YES;
3327 mhd_assert (pos->suspended);
3330 pos);
3331 pos->suspended = false;
3332 if (NULL == urh)
3333 {
3335 daemon->connections_tail,
3336 pos);
3337 if (! used_thr_p_c)
3338 {
3339 /* Reset timeout timer on resume. */
3340 if (0 != pos->connection_timeout_ms)
3342
3343 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
3345 daemon->normal_timeout_tail,
3346 pos);
3347 else
3349 daemon->manual_timeout_tail,
3350 pos);
3351 }
3352#ifdef EPOLL_SUPPORT
3353 if (0 != (daemon->options & MHD_USE_EPOLL))
3354 {
3355 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3356 MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3357 /* we always mark resumed connections as ready, as we
3358 might have missed the edge poll event during suspension */
3359 EDLL_insert (daemon->eready_head,
3360 daemon->eready_tail,
3361 pos);
3362 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3365 pos->epoll_state &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_SUSPENDED);
3366 }
3367#endif
3368 }
3369#ifdef UPGRADE_SUPPORT
3370 else
3371 {
3372 /* Data forwarding was finished (for TLS connections) AND
3373 * application was closed upgraded connection.
3374 * Insert connection into cleanup list. */
3375
3376 if ( (NULL != daemon->notify_completed) &&
3377 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3378 (pos->client_aware) )
3379 {
3380 daemon->notify_completed (daemon->notify_completed_cls,
3381 pos,
3382 &pos->client_context,
3384 pos->client_aware = false;
3385 }
3386 DLL_insert (daemon->cleanup_head,
3387 daemon->cleanup_tail,
3388 pos);
3389 daemon->data_already_pending = true;
3390 }
3391#endif /* UPGRADE_SUPPORT */
3392 pos->resuming = false;
3393 }
3394#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3396#endif
3397 if ( (used_thr_p_c) &&
3398 (MHD_NO != ret) )
3399 { /* Wake up suspended connections. */
3400 if (! MHD_itc_activate_ (daemon->itc,
3401 "w"))
3402 {
3403#ifdef HAVE_MESSAGES
3404 MHD_DLOG (daemon,
3405 _ (
3406 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3407#endif
3408 }
3409 }
3410 return ret;
3411}
3412
3413
3441enum MHD_Result
3443 MHD_socket client_socket,
3444 const struct sockaddr *addr,
3445 socklen_t addrlen)
3446{
3447 bool sk_nonbl;
3448 bool sk_spipe_supprs;
3449
3450 /* NOT thread safe with internal thread. TODO: fix thread safety. */
3451 if ((0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3452 (daemon->connection_limit <= daemon->connections))
3453 MHD_cleanup_connections (daemon);
3454
3455#ifdef HAVE_MESSAGES
3456 if ((0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3457 (0 == (daemon->options & MHD_USE_ITC)))
3458 {
3459 MHD_DLOG (daemon,
3460 _ ("MHD_add_connection() has been called for daemon started"
3461 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3462 " added connection until any activity occurs in already"
3463 " added sockets.\n"));
3464 }
3465#endif /* HAVE_MESSAGES */
3466
3467 if (! MHD_socket_nonblocking_ (client_socket))
3468 {
3469#ifdef HAVE_MESSAGES
3470 MHD_DLOG (daemon,
3471 _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3473#endif
3474 sk_nonbl = false;
3475 }
3476 else
3477 sk_nonbl = true;
3478
3479#ifndef MHD_WINSOCK_SOCKETS
3480 sk_spipe_supprs = false;
3481#else /* MHD_WINSOCK_SOCKETS */
3482 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3483#endif /* MHD_WINSOCK_SOCKETS */
3484#if defined(MHD_socket_nosignal_)
3485 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (client_socket))
3486 {
3487#ifdef HAVE_MESSAGES
3488 MHD_DLOG (daemon,
3489 _ (
3490 "Failed to suppress SIGPIPE on new client socket: %s\n"),
3492#else /* ! HAVE_MESSAGES */
3493 (void) 0; /* Mute compiler warning */
3494#endif /* ! HAVE_MESSAGES */
3495#ifndef MSG_NOSIGNAL
3496 /* Application expects that SIGPIPE will be suppressed,
3497 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3498 if (! daemon->sigpipe_blocked)
3499 {
3500 int err = MHD_socket_get_error_ ();
3501 MHD_socket_close_ (client_socket);
3503 return MHD_NO;
3504 }
3505#endif /* MSG_NOSIGNAL */
3506 }
3507 else
3508 sk_spipe_supprs = true;
3509#endif /* MHD_socket_nosignal_ */
3510
3511 if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3512 (! MHD_socket_noninheritable_ (client_socket)) )
3513 {
3514#ifdef HAVE_MESSAGES
3515 MHD_DLOG (daemon,
3516 _ ("Failed to set noninheritable mode on new client socket.\n"));
3517#endif
3518 }
3519
3520#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3521 if (NULL != daemon->worker_pool)
3522 {
3523 unsigned int i;
3524 /* have a pool, try to find a pool with capacity; we use the
3525 socket as the initial offset into the pool for load
3526 balancing */
3527 for (i = 0; i < daemon->worker_pool_size; ++i)
3528 {
3529 struct MHD_Daemon *const worker =
3530 &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
3531 if (worker->connections < worker->connection_limit)
3532 return internal_add_connection (worker,
3533 client_socket,
3534 addr,
3535 addrlen,
3536 true,
3537 sk_nonbl,
3538 sk_spipe_supprs,
3539 _MHD_UNKNOWN);
3540 }
3541 /* all pools are at their connection limit, must refuse */
3542 MHD_socket_close_chk_ (client_socket);
3543#if ENFILE
3544 errno = ENFILE;
3545#endif
3546 return MHD_NO;
3547 }
3548#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
3549
3550 return internal_add_connection (daemon,
3551 client_socket,
3552 addr,
3553 addrlen,
3554 true,
3555 sk_nonbl,
3556 sk_spipe_supprs,
3557 _MHD_UNKNOWN);
3558}
3559
3560
3575static enum MHD_Result
3577{
3578#if HAVE_INET6
3579 struct sockaddr_in6 addrstorage;
3580#else
3581 struct sockaddr_in addrstorage;
3582#endif
3583 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3584 socklen_t addrlen;
3585 MHD_socket s;
3586 MHD_socket fd;
3587 bool sk_nonbl;
3588 bool sk_spipe_supprs;
3589 bool sk_cloexec;
3590
3591#ifdef MHD_USE_THREADS
3592 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3593 MHD_thread_ID_match_current_ (daemon->pid) );
3594#endif /* MHD_USE_THREADS */
3595
3596 addrlen = sizeof (addrstorage);
3597 memset (addr,
3598 0,
3599 sizeof (addrstorage));
3600 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3601 (daemon->was_quiesced) )
3602 return MHD_NO;
3603#ifdef USE_ACCEPT4
3604 s = accept4 (fd,
3605 addr,
3606 &addrlen,
3609 sk_nonbl = (SOCK_NONBLOCK_OR_ZERO != 0);
3610#ifndef MHD_WINSOCK_SOCKETS
3611 sk_spipe_supprs = (SOCK_NOSIGPIPE_OR_ZERO != 0);
3612#else /* MHD_WINSOCK_SOCKETS */
3613 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3614#endif /* MHD_WINSOCK_SOCKETS */
3615 sk_cloexec = (SOCK_CLOEXEC_OR_ZERO != 0);
3616#else /* ! USE_ACCEPT4 */
3617 s = accept (fd,
3618 addr,
3619 &addrlen);
3620#ifdef MHD_ACCEPT_INHERIT_NONBLOCK
3621 sk_nonbl = daemon->listen_nonblk;
3622#else /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
3623 sk_nonbl = false;
3624#endif /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
3625#ifndef MHD_WINSOCK_SOCKETS
3626 sk_spipe_supprs = false;
3627#else /* MHD_WINSOCK_SOCKETS */
3628 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3629#endif /* MHD_WINSOCK_SOCKETS */
3630 sk_cloexec = false;
3631#endif /* ! USE_ACCEPT4 */
3632 if ( (MHD_INVALID_SOCKET == s) ||
3633 (addrlen <= 0) )
3634 {
3635 const int err = MHD_socket_get_error_ ();
3636
3637 /* This could be a common occurrence with multiple worker threads */
3638 if (MHD_SCKT_ERR_IS_ (err,
3640 return MHD_NO; /* can happen during shutdown */
3642 return MHD_NO; /* do not print error if client just disconnected early */
3643#ifdef HAVE_MESSAGES
3644 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3645 MHD_DLOG (daemon,
3646 _ ("Error accepting connection: %s\n"),
3647 MHD_socket_strerr_ (err));
3648#endif
3649 if (MHD_INVALID_SOCKET != s)
3650 {
3652 }
3654 {
3655 /* system/process out of resources */
3656 if (0 == daemon->connections)
3657 {
3658#ifdef HAVE_MESSAGES
3659 /* Not setting 'at_limit' flag, as there is no way it
3660 would ever be cleared. Instead trying to produce
3661 bit fat ugly warning. */
3662 MHD_DLOG (daemon,
3663 _ ("Hit process or system resource limit at FIRST " \
3664 "connection. This is really bad as there is no sane " \
3665 "way to proceed. Will try busy waiting for system " \
3666 "resources to become magically available.\n"));
3667#endif
3668 }
3669 else
3670 {
3671#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3673#endif
3674 daemon->at_limit = true;
3675#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3677#endif
3678#ifdef HAVE_MESSAGES
3679 MHD_DLOG (daemon,
3680 _ ("Hit process or system resource limit at %u " \
3681 "connections, temporarily suspending accept(). " \
3682 "Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3683 (unsigned int) daemon->connections);
3684#endif
3685 }
3686 }
3687 return MHD_NO;
3688 }
3689
3690 if (! sk_nonbl && ! MHD_socket_nonblocking_ (s))
3691 {
3692#ifdef HAVE_MESSAGES
3693 MHD_DLOG (daemon,
3694 _ ("Failed to set nonblocking mode on incoming connection " \
3695 "socket: %s\n"),
3697#else /* ! HAVE_MESSAGES */
3698 (void) 0; /* Mute compiler warning */
3699#endif /* ! HAVE_MESSAGES */
3700 }
3701 else
3702 sk_nonbl = true;
3703
3704 if (! sk_cloexec && ! MHD_socket_noninheritable_ (s))
3705 {
3706#ifdef HAVE_MESSAGES
3707 MHD_DLOG (daemon,
3708 _ ("Failed to set noninheritable mode on incoming connection " \
3709 "socket.\n"));
3710#else /* ! HAVE_MESSAGES */
3711 (void) 0; /* Mute compiler warning */
3712#endif /* ! HAVE_MESSAGES */
3713 }
3714
3715#if defined(MHD_socket_nosignal_)
3716 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
3717 {
3718#ifdef HAVE_MESSAGES
3719 MHD_DLOG (daemon,
3720 _ ("Failed to suppress SIGPIPE on incoming connection " \
3721 "socket: %s\n"),
3723#else /* ! HAVE_MESSAGES */
3724 (void) 0; /* Mute compiler warning */
3725#endif /* ! HAVE_MESSAGES */
3726#ifndef MSG_NOSIGNAL
3727 /* Application expects that SIGPIPE will be suppressed,
3728 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3729 if (! daemon->sigpipe_blocked)
3730 {
3732 return MHD_NO;
3733 }
3734#endif /* MSG_NOSIGNAL */
3735 }
3736 else
3737 sk_spipe_supprs = true;
3738#endif /* MHD_socket_nosignal_ */
3739#ifdef HAVE_MESSAGES
3740#if _MHD_DEBUG_CONNECT
3741 MHD_DLOG (daemon,
3742 _ ("Accepted connection on socket %d\n"),
3743 s);
3744#endif
3745#endif
3746 (void) internal_add_connection (daemon,
3747 s,
3748 addr,
3749 addrlen,
3750 false,
3751 sk_nonbl,
3752 sk_spipe_supprs,
3753 daemon->listen_is_unix);
3754 return MHD_YES;
3755}
3756
3757
3767static void
3769{
3770 struct MHD_Connection *pos;
3771#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3773 MHD_thread_ID_match_current_ (daemon->pid) );
3774
3776#endif
3777 while (NULL != (pos = daemon->cleanup_tail))
3778 {
3781 pos);
3782#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3784 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3785 (! pos->thread_joined) &&
3786 (! MHD_join_thread_ (pos->pid.handle)) )
3787 MHD_PANIC (_ ("Failed to join a thread.\n"));
3788#endif
3789#ifdef UPGRADE_SUPPORT
3790 cleanup_upgraded_connection (pos);
3791#endif /* UPGRADE_SUPPORT */
3792 MHD_pool_destroy (pos->pool);
3793#ifdef HTTPS_SUPPORT
3794 if (NULL != pos->tls_session)
3795 gnutls_deinit (pos->tls_session);
3796#endif /* HTTPS_SUPPORT */
3797
3798 /* clean up the connection */
3801 pos,
3802 &pos->socket_context,
3805 pos->addr,
3806 pos->addr_len);
3807#ifdef EPOLL_SUPPORT
3808 if (0 != (daemon->options & MHD_USE_EPOLL))
3809 {
3810 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3811 {
3812 EDLL_remove (daemon->eready_head,
3813 daemon->eready_tail,
3814 pos);
3815 pos->epoll_state &=
3817 }
3818 if ( (-1 != daemon->epoll_fd) &&
3819 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3820 {
3821 /* epoll documentation suggests that closing a FD
3822 automatically removes it from the epoll set; however,
3823 this is not true as if we fail to do manually remove it,
3824 we are still seeing an event for this fd in epoll,
3825 causing grief (use-after-free...) --- at least on my
3826 system. */
3827 if (0 != epoll_ctl (daemon->epoll_fd,
3828 EPOLL_CTL_DEL,
3829 pos->socket_fd,
3830 NULL))
3831 MHD_PANIC (_ (
3832 "Failed to remove FD from epoll set.\n"));
3833 pos->epoll_state &=
3834 ~((enum MHD_EpollState)
3836 }
3837 }
3838#endif
3839 if (NULL != pos->response)
3840 {
3842 pos->response = NULL;
3843 }
3844 if (MHD_INVALID_SOCKET != pos->socket_fd)
3846 if (NULL != pos->addr)
3847 free (pos->addr);
3848 free (pos);
3849
3850#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3852#endif
3854 daemon->at_limit = false;
3855 }
3856#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3858#endif
3859}
3860
3861
3894enum MHD_Result
3896 MHD_UNSIGNED_LONG_LONG *timeout)
3897{
3898 uint64_t earliest_deadline;
3899 struct MHD_Connection *pos;
3900 struct MHD_Connection *earliest_tmot_conn;
3902#ifdef MHD_USE_THREADS
3904 MHD_thread_ID_match_current_ (daemon->pid) );
3905#endif /* MHD_USE_THREADS */
3906
3908 {
3909#ifdef HAVE_MESSAGES
3910 MHD_DLOG (daemon,
3911 _ ("Illegal call to MHD_get_timeout.\n"));
3912#endif
3913 return MHD_NO;
3914 }
3916 {
3917 /* Some data already waiting to be processed. */
3918 *timeout = 0;
3919 return MHD_YES;
3920 }
3921#ifdef EPOLL_SUPPORT
3922 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3923 ((NULL != daemon->eready_head)
3924#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3925 || (NULL != daemon->eready_urh_head)
3926#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3927 ) )
3928 {
3929 /* Some connection(s) already have some data pending. */
3930 *timeout = 0;
3931 return MHD_YES;
3932 }
3933#endif /* EPOLL_SUPPORT */
3934
3935 earliest_tmot_conn = NULL;
3936 earliest_deadline = 0; /* mute compiler warning */
3937 /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3939 if ( (NULL != pos) &&
3940 (0 != pos->connection_timeout_ms) )
3941 {
3942 earliest_tmot_conn = pos;
3943 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
3944 }
3945
3946 for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3947 {
3948 if (0 != pos->connection_timeout_ms)
3949 {
3950 if ( (NULL == earliest_tmot_conn) ||
3951 (earliest_deadline - pos->last_activity >
3952 pos->connection_timeout_ms) )
3953 {
3954 earliest_tmot_conn = pos;
3955 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
3956 }
3957 }
3958 }
3959
3960 if (NULL != earliest_tmot_conn)
3961 {
3962 const uint64_t mssecond_left = connection_get_wait (earliest_tmot_conn);
3963#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
3964 if (mssecond_left > ULLONG_MAX)
3965 *timeout = ULLONG_MAX;
3966 else
3967#endif /* UINT64 != ULLONG_MAX */
3968 *timeout = (unsigned long long) mssecond_left;
3969 return MHD_YES;
3970 }
3971 return MHD_NO;
3972}
3973
3974
3985static int
3987 int32_t max_timeout)
3988{
3989 MHD_UNSIGNED_LONG_LONG ulltimeout;
3990 if (0 == max_timeout)
3991 return 0;
3992
3993 if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
3994 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3995
3996 if ( (0 > max_timeout) ||
3997 ((uint32_t) max_timeout > ulltimeout) )
3998 return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
3999
4000 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
4001}
4002
4003
4014static enum MHD_Result
4016 const fd_set *read_fd_set,
4017 const fd_set *write_fd_set,
4018 const fd_set *except_fd_set)
4019{
4020 MHD_socket ds;
4021 struct MHD_Connection *pos;
4022 struct MHD_Connection *prev;
4023#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4024 struct MHD_UpgradeResponseHandle *urh;
4025 struct MHD_UpgradeResponseHandle *urhn;
4026#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4027 /* Reset. New value will be set when connections are processed. */
4028 /* Note: no-op for thread-per-connection as it is always false in that mode. */
4029 daemon->data_already_pending = false;
4030
4031 /* Clear ITC to avoid spinning select */
4032 /* Do it before any other processing so new signals
4033 will trigger select again and will be processed */
4034 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4035 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
4036 read_fd_set)) )
4037 MHD_itc_clear_ (daemon->itc);
4038
4039 /* Process externally added connection if any */
4040 if (daemon->have_new)
4042
4043 /* select connection thread handling type */
4044 if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
4045 (! daemon->was_quiesced) &&
4046 (FD_ISSET (ds,
4047 read_fd_set)) )
4048 (void) MHD_accept_connection (daemon);
4049
4050 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4051 {
4052 /* do not have a thread per connection, process all connections now */
4053 prev = daemon->connections_tail;
4054 while (NULL != (pos = prev))
4055 {
4056 prev = pos->prev;
4057 ds = pos->socket_fd;
4058 if (MHD_INVALID_SOCKET == ds)
4059 continue;
4060 call_handlers (pos,
4061 FD_ISSET (ds,
4062 read_fd_set),
4063 FD_ISSET (ds,
4064 write_fd_set),
4065 FD_ISSET (ds,
4066 except_fd_set));
4067 }
4068 }
4069
4070#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4071 /* handle upgraded HTTPS connections */
4072 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4073 {
4074 urhn = urh->prev;
4075 /* update urh state based on select() output */
4076 urh_from_fdset (urh,
4077 read_fd_set,
4078 write_fd_set,
4079 except_fd_set);
4080 /* call generic forwarding function for passing data */
4081 process_urh (urh);
4082 /* Finished forwarding? */
4083 if ( (0 == urh->in_buffer_size) &&
4084 (0 == urh->out_buffer_size) &&
4085 (0 == urh->in_buffer_used) &&
4086 (0 == urh->out_buffer_used) )
4087 {
4088 MHD_connection_finish_forward_ (urh->connection);
4089 urh->clean_ready = true;
4090 /* Resuming will move connection to cleanup list. */
4091 MHD_resume_connection (urh->connection);
4092 }
4093 }
4094#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4095 MHD_cleanup_connections (daemon);
4096 return MHD_YES;
4097}
4098
4099
4126enum MHD_Result
4128 const fd_set *read_fd_set,
4129 const fd_set *write_fd_set,
4130 const fd_set *except_fd_set)
4131{
4132 fd_set es;
4133 if (0 != (daemon->options
4135 return MHD_NO;
4136 if ((NULL == read_fd_set) || (NULL == write_fd_set))
4137 return MHD_NO;
4138 if (NULL == except_fd_set)
4139 { /* Workaround to maintain backward compatibility. */
4140#ifdef HAVE_MESSAGES
4141 MHD_DLOG (daemon,
4142 _ ("MHD_run_from_select() called with except_fd_set "
4143 "set to NULL. Such behavior is deprecated.\n"));
4144#endif
4145 FD_ZERO (&es);
4146 except_fd_set = &es;
4147 }
4148 if (0 != (daemon->options & MHD_USE_EPOLL))
4149 {
4150#ifdef EPOLL_SUPPORT
4151 enum MHD_Result ret = MHD_epoll (daemon,
4152 0);
4153
4154 MHD_cleanup_connections (daemon);
4155 return ret;
4156#else /* ! EPOLL_SUPPORT */
4157 return MHD_NO;
4158#endif /* ! EPOLL_SUPPORT */
4159 }
4160
4161 /* Resuming external connections when using an extern mainloop */
4162 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4164
4165 return internal_run_from_select (daemon,
4166 read_fd_set,
4167 write_fd_set,
4168 except_fd_set);
4169}
4170
4171
4182static enum MHD_Result
4183MHD_select (struct MHD_Daemon *daemon,
4184 int32_t millisec)
4185{
4186 int num_ready;
4187 fd_set rs;
4188 fd_set ws;
4189 fd_set es;
4190 MHD_socket maxsock;
4191 struct timeval timeout;
4192 struct timeval *tv;
4193 int err_state;
4194 MHD_socket ls;
4195
4196 timeout.tv_sec = 0;
4197 timeout.tv_usec = 0;
4198 if (daemon->shutdown)
4199 return MHD_NO;
4200 FD_ZERO (&rs);
4201 FD_ZERO (&ws);
4202 FD_ZERO (&es);
4203 maxsock = MHD_INVALID_SOCKET;
4204 err_state = MHD_NO;
4205 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4206 (MHD_NO != resume_suspended_connections (daemon)) &&
4207 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
4208 millisec = 0;
4209
4210 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4211 {
4212 /* single-threaded, go over everything */
4213 if (MHD_NO ==
4214 internal_get_fdset2 (daemon,
4215 &rs,
4216 &ws,
4217 &es,
4218 &maxsock,
4219 FD_SETSIZE))
4220 {
4221#ifdef HAVE_MESSAGES
4222 MHD_DLOG (daemon,
4223 _ ("Could not obtain daemon fdsets.\n"));
4224#endif
4225 err_state = MHD_YES;
4226 }
4227 }
4228 else
4229 {
4230 /* accept only, have one thread per connection */
4231 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4232 (! daemon->was_quiesced) &&
4233 (! MHD_add_to_fd_set_ (ls,
4234 &rs,
4235 &maxsock,
4236 FD_SETSIZE)) )
4237 {
4238#ifdef HAVE_MESSAGES
4239 MHD_DLOG (daemon,
4240 _ ("Could not add listen socket to fdset.\n"));
4241#endif
4242 return MHD_NO;
4243 }
4244 }
4245 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4246 (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4247 &rs,
4248 &maxsock,
4249 FD_SETSIZE)) )
4250 {
4251#if defined(MHD_WINSOCK_SOCKETS)
4252 /* fdset limit reached, new connections
4253 cannot be handled. Remove listen socket FD
4254 from fdset and retry to add ITC FD. */
4255 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4256 (! daemon->was_quiesced) )
4257 {
4258 FD_CLR (ls,
4259 &rs);
4260 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4261 &rs,
4262 &maxsock,
4263 FD_SETSIZE))
4264 {
4265#endif /* MHD_WINSOCK_SOCKETS */
4266#ifdef HAVE_MESSAGES
4267 MHD_DLOG (daemon,
4268 _ (
4269 "Could not add control inter-thread communication channel FD to fdset.\n"));
4270#endif
4271 err_state = MHD_YES;
4272#if defined(MHD_WINSOCK_SOCKETS)
4273 }
4274}
4275
4276
4277#endif /* MHD_WINSOCK_SOCKETS */
4278 }
4279 /* Stop listening if we are at the configured connection limit */
4280 /* If we're at the connection limit, no point in really
4281 accepting new connections; however, make sure we do not miss
4282 the shutdown OR the termination of an existing connection; so
4283 only do this optimization if we have a signaling ITC in
4284 place. */
4285 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4286 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4287 ( (daemon->connections == daemon->connection_limit) ||
4288 (daemon->at_limit) ) )
4289 {
4290 FD_CLR (ls,
4291 &rs);
4292 }
4293
4294 if (MHD_NO != err_state)
4295 millisec = 0;
4296 tv = NULL;
4297 if (0 == millisec)
4298 {
4299 timeout.tv_usec = 0;
4300 timeout.tv_sec = 0;
4301 tv = &timeout;
4302 }
4303 else
4304 {
4305 MHD_UNSIGNED_LONG_LONG ltimeout;
4306
4307 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
4308 (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
4309 {
4310 tv = &timeout; /* have timeout value */
4311 if ( (0 < millisec) &&
4312 (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
4313 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4314 }
4315 else if (0 < millisec)
4316 {
4317 tv = &timeout; /* have timeout value */
4318 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4319 }
4320
4321 if (NULL != tv)
4322 { /* have timeout value */
4323 if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
4324 {
4325 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
4326 timeout.tv_usec = 0;
4327 }
4328 else
4329 {
4330 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
4331 timeout.tv_usec = (ltimeout % 1000) * 1000;
4332 }
4333 }
4334 }
4335 num_ready = MHD_SYS_select_ (maxsock + 1,
4336 &rs,
4337 &ws,
4338 &es,
4339 tv);
4340 if (daemon->shutdown)
4341 return MHD_NO;
4342 if (num_ready < 0)
4343 {
4344 const int err = MHD_socket_get_error_ ();
4345 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4346 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4347#ifdef HAVE_MESSAGES
4348 MHD_DLOG (daemon,
4349 _ ("select failed: %s\n"),
4350 MHD_socket_strerr_ (err));
4351#endif
4352 return MHD_NO;
4353 }
4354 if (MHD_NO != internal_run_from_select (daemon,
4355 &rs,
4356 &ws,
4357 &es))
4358 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4359 return MHD_NO;
4360}
4361
4362
4363#ifdef HAVE_POLL
4374static enum MHD_Result
4375MHD_poll_all (struct MHD_Daemon *daemon,
4376 int32_t millisec)
4377{
4378 unsigned int num_connections;
4379 struct MHD_Connection *pos;
4380 struct MHD_Connection *prev;
4381#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4382 struct MHD_UpgradeResponseHandle *urh;
4383 struct MHD_UpgradeResponseHandle *urhn;
4384#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4385
4386 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4387 (MHD_NO != resume_suspended_connections (daemon)) )
4388 millisec = 0;
4389
4390 /* count number of connections and thus determine poll set size */
4391 num_connections = 0;
4392 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
4393 num_connections++;
4394#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4395 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
4396 num_connections += 2;
4397#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4398 {
4399 unsigned int i;
4400 int timeout;
4401 unsigned int poll_server;
4402 int poll_listen;
4403 int poll_itc_idx;
4404 struct pollfd *p;
4405 MHD_socket ls;
4406
4407 p = MHD_calloc_ ((2 + (size_t) num_connections),
4408 sizeof (struct pollfd));
4409 if (NULL == p)
4410 {
4411#ifdef HAVE_MESSAGES
4412 MHD_DLOG (daemon,
4413 _ ("Error allocating memory: %s\n"),
4414 MHD_strerror_ (errno));
4415#endif
4416 return MHD_NO;
4417 }
4418 poll_server = 0;
4419 poll_listen = -1;
4420 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4421 (! daemon->was_quiesced) &&
4422 (daemon->connections < daemon->connection_limit) &&
4423 (! daemon->at_limit) )
4424 {
4425 /* only listen if we are not at the connection limit */
4426 p[poll_server].fd = ls;
4427 p[poll_server].events = POLLIN;
4428 p[poll_server].revents = 0;
4429 poll_listen = (int) poll_server;
4430 poll_server++;
4431 }
4432 poll_itc_idx = -1;
4433 if (MHD_ITC_IS_VALID_ (daemon->itc))
4434 {
4435 p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
4436 p[poll_server].events = POLLIN;
4437 p[poll_server].revents = 0;
4438 poll_itc_idx = (int) poll_server;
4439 poll_server++;
4440 }
4441
4442 timeout = get_timeout_millisec_ (daemon, millisec);
4443
4444 i = 0;
4445 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
4446 {
4447 p[poll_server + i].fd = pos->socket_fd;
4448 switch (pos->event_loop_info)
4449 {
4451 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
4452 break;
4454 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
4455 break;
4457 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
4458 break;
4460 timeout = 0; /* clean up "pos" immediately */
4461 break;
4462 }
4463 i++;
4464 }
4465#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4466 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
4467 {
4468 urh_to_pollfd (urh, &(p[poll_server + i]));
4469 i += 2;
4470 }
4471#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4472 if (0 == poll_server + num_connections)
4473 {
4474 free (p);
4475 return MHD_YES;
4476 }
4477 if (MHD_sys_poll_ (p,
4478 poll_server + num_connections,
4479 timeout) < 0)
4480 {
4481 const int err = MHD_socket_get_error_ ();
4482 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4483 {
4484 free (p);
4485 return MHD_YES;
4486 }
4487#ifdef HAVE_MESSAGES
4488 MHD_DLOG (daemon,
4489 _ ("poll failed: %s\n"),
4490 MHD_socket_strerr_ (err));
4491#endif
4492 free (p);
4493 return MHD_NO;
4494 }
4495
4496 /* handle ITC FD */
4497 /* do it before any other processing so
4498 new signals will be processed in next loop */
4499 if ( (-1 != poll_itc_idx) &&
4500 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4501 MHD_itc_clear_ (daemon->itc);
4502
4503 /* handle shutdown */
4504 if (daemon->shutdown)
4505 {
4506 free (p);
4507 return MHD_NO;
4508 }
4509
4510 /* Process externally added connection if any */
4511 if (daemon->have_new)
4513
4514 /* handle 'listen' FD */
4515 if ( (-1 != poll_listen) &&
4516 (0 != (p[poll_listen].revents & POLLIN)) )
4517 (void) MHD_accept_connection (daemon);
4518
4519 /* Reset. New value will be set when connections are processed. */
4520 daemon->data_already_pending = false;
4521
4522 i = 0;
4523 prev = daemon->connections_tail;
4524 while (NULL != (pos = prev))
4525 {
4526 prev = pos->prev;
4527 /* first, sanity checks */
4528 if (i >= num_connections)
4529 break; /* connection list changed somehow, retry later ... */
4530 if (p[poll_server + i].fd != pos->socket_fd)
4531 continue; /* fd mismatch, something else happened, retry later ... */
4532 call_handlers (pos,
4533 0 != (p[poll_server + i].revents & POLLIN),
4534 0 != (p[poll_server + i].revents & POLLOUT),
4535 0 != (p[poll_server + i].revents
4536 & MHD_POLL_REVENTS_ERR_DISC));
4537 i++;
4538 }
4539#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4540 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4541 {
4542 if (i >= num_connections)
4543 break; /* connection list changed somehow, retry later ... */
4544
4545 /* Get next connection here as connection can be removed
4546 * from 'daemon->urh_head' list. */
4547 urhn = urh->prev;
4548 /* Check for fd mismatch. FIXME: required for safety? */
4549 if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
4550 (p[poll_server + i + 1].fd != urh->mhd.socket))
4551 break;
4552 urh_from_pollfd (urh,
4553 &p[poll_server + i]);
4554 i += 2;
4555 process_urh (urh);
4556 /* Finished forwarding? */
4557 if ( (0 == urh->in_buffer_size) &&
4558 (0 == urh->out_buffer_size) &&
4559 (0 == urh->in_buffer_used) &&
4560 (0 == urh->out_buffer_used) )
4561 {
4562 /* MHD_connection_finish_forward_() will remove connection from
4563 * 'daemon->urh_head' list. */
4564 MHD_connection_finish_forward_ (urh->connection);
4565 urh->clean_ready = true;
4566 /* If 'urh->was_closed' already was set to true, connection will be
4567 * moved immediately to cleanup list. Otherwise connection
4568 * will stay in suspended list until 'urh' will be marked
4569 * with 'was_closed' by application. */
4570 MHD_resume_connection (urh->connection);
4571 }
4572 }
4573#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4574
4575 free (p);
4576 }
4577 return MHD_YES;
4578}
4579
4580
4588static enum MHD_Result
4589MHD_poll_listen_socket (struct MHD_Daemon *daemon,
4590 int may_block)
4591{
4592 struct pollfd p[2];
4593 int timeout;
4594 unsigned int poll_count;
4595 int poll_listen;
4596 int poll_itc_idx;
4597 MHD_socket ls;
4598
4599 memset (&p,
4600 0,
4601 sizeof (p));
4602 poll_count = 0;
4603 poll_listen = -1;
4604 poll_itc_idx = -1;
4605 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4606 (! daemon->was_quiesced) )
4607
4608 {
4609 p[poll_count].fd = ls;
4610 p[poll_count].events = POLLIN;
4611 p[poll_count].revents = 0;
4612 poll_listen = poll_count;
4613 poll_count++;
4614 }
4615 if (MHD_ITC_IS_VALID_ (daemon->itc))
4616 {
4617 p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
4618 p[poll_count].events = POLLIN;
4619 p[poll_count].revents = 0;
4620 poll_itc_idx = poll_count;
4621 poll_count++;
4622 }
4623
4624 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4625 (void) resume_suspended_connections (daemon);
4626
4627 if (MHD_NO == may_block)
4628 timeout = 0;
4629 else
4630 timeout = -1;
4631 if (0 == poll_count)
4632 return MHD_YES;
4633 if (MHD_sys_poll_ (p,
4634 poll_count,
4635 timeout) < 0)
4636 {
4637 const int err = MHD_socket_get_error_ ();
4638
4639 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4640 return MHD_YES;
4641#ifdef HAVE_MESSAGES
4642 MHD_DLOG (daemon,
4643 _ ("poll failed: %s\n"),
4644 MHD_socket_strerr_ (err));
4645#endif
4646 return MHD_NO;
4647 }
4648 if ( (-1 != poll_itc_idx) &&
4649 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4650 MHD_itc_clear_ (daemon->itc);
4651
4652 /* handle shutdown */
4653 if (daemon->shutdown)
4654 return MHD_NO;
4655
4656 /* Process externally added connection if any */
4657 if (daemon->have_new)
4659
4660 if ( (-1 != poll_listen) &&
4661 (0 != (p[poll_listen].revents & POLLIN)) )
4662 (void) MHD_accept_connection (daemon);
4663 return MHD_YES;
4664}
4665
4666
4667#endif
4668
4669
4677static enum MHD_Result
4678MHD_poll (struct MHD_Daemon *daemon,
4679 int may_block)
4680{
4681#ifdef HAVE_POLL
4682 if (daemon->shutdown)
4683 return MHD_NO;
4684 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4685 return MHD_poll_all (daemon,
4686 may_block ? -1 : 0);
4687 return MHD_poll_listen_socket (daemon,
4688 may_block);
4689#else
4690 (void) daemon;
4691 (void) may_block;
4692 return MHD_NO;
4693#endif
4694}
4695
4696
4697#ifdef EPOLL_SUPPORT
4698
4707#define MAX_EVENTS 128
4708
4709
4710#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4711
4719static bool
4720is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
4721{
4722 const struct MHD_Connection *const connection = urh->connection;
4723
4724 if ( (0 == urh->in_buffer_size) &&
4725 (0 == urh->out_buffer_size) &&
4726 (0 == urh->in_buffer_used) &&
4727 (0 == urh->out_buffer_used) )
4728 return false;
4729 if (connection->daemon->shutdown)
4730 return true;
4731 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4732 (connection->tls_read_ready) ) &&
4733 (urh->in_buffer_used < urh->in_buffer_size) )
4734 return true;
4735 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4736 (urh->out_buffer_used < urh->out_buffer_size) )
4737 return true;
4738 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4739 (urh->out_buffer_used > 0) )
4740 return true;
4741 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4742 (urh->in_buffer_used > 0) )
4743 return true;
4744 return false;
4745}
4746
4747
4756static enum MHD_Result
4757run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4758{
4759 struct epoll_event events[MAX_EVENTS];
4760 int num_events;
4761 struct MHD_UpgradeResponseHandle *pos;
4762 struct MHD_UpgradeResponseHandle *prev;
4763
4764#ifdef MHD_USE_THREADS
4765 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
4766 MHD_thread_ID_match_current_ (daemon->pid) );
4767#endif /* MHD_USE_THREADS */
4768
4769 num_events = MAX_EVENTS;
4770 while (0 != num_events)
4771 {
4772 unsigned int i;
4773 /* update event masks */
4774 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4775 events,
4776 MAX_EVENTS,
4777 0);
4778 if (-1 == num_events)
4779 {
4780 const int err = MHD_socket_get_error_ ();
4781
4782 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4783 return MHD_YES;
4784#ifdef HAVE_MESSAGES
4785 MHD_DLOG (daemon,
4786 _ ("Call to epoll_wait failed: %s\n"),
4787 MHD_socket_strerr_ (err));
4788#endif
4789 return MHD_NO;
4790 }
4791 for (i = 0; i < (unsigned int) num_events; i++)
4792 {
4793 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
4794 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
4795 bool new_err_state = false;
4796
4797 if (urh->clean_ready)
4798 continue;
4799
4800 /* Update ueh state based on what is ready according to epoll() */
4801 if (0 != (events[i].events & EPOLLIN))
4802 {
4803 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4804 }
4805 if (0 != (events[i].events & EPOLLOUT))
4806 {
4807 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4808 }
4809 if (0 != (events[i].events & EPOLLHUP))
4810 {
4812 }
4813
4814 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4815 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4816 {
4817 /* Process new error state only one time and avoid continuously
4818 * marking this connection as 'ready'. */
4819 ueh->celi |= MHD_EPOLL_STATE_ERROR;
4820 new_err_state = true;
4821 }
4822 if (! urh->in_eready_list)
4823 {
4824 if (new_err_state ||
4825 is_urh_ready (urh))
4826 {
4827 EDLL_insert (daemon->eready_urh_head,
4828 daemon->eready_urh_tail,
4829 urh);
4830 urh->in_eready_list = true;
4831 }
4832 }
4833 }
4834 }
4835 prev = daemon->eready_urh_tail;
4836 while (NULL != (pos = prev))
4837 {
4838 prev = pos->prevE;
4839 process_urh (pos);
4840 if (! is_urh_ready (pos))
4841 {
4842 EDLL_remove (daemon->eready_urh_head,
4843 daemon->eready_urh_tail,
4844 pos);
4845 pos->in_eready_list = false;
4846 }
4847 /* Finished forwarding? */
4848 if ( (0 == pos->in_buffer_size) &&
4849 (0 == pos->out_buffer_size) &&
4850 (0 == pos->in_buffer_used) &&
4851 (0 == pos->out_buffer_used) )
4852 {
4853 MHD_connection_finish_forward_ (pos->connection);
4854 pos->clean_ready = true;
4855 /* If 'pos->was_closed' already was set to true, connection
4856 * will be moved immediately to cleanup list. Otherwise
4857 * connection will stay in suspended list until 'pos' will
4858 * be marked with 'was_closed' by application. */
4859 MHD_resume_connection (pos->connection);
4860 }
4861 }
4862
4863 return MHD_YES;
4864}
4865
4866
4867#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4868
4869
4873static const char *const epoll_itc_marker = "itc_marker";
4874
4875
4885static enum MHD_Result
4886MHD_epoll (struct MHD_Daemon *daemon,
4887 int32_t millisec)
4888{
4889#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4890 static const char *const upgrade_marker = "upgrade_ptr";
4891#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4892 struct MHD_Connection *pos;
4893 struct MHD_Connection *prev;
4894 struct epoll_event events[MAX_EVENTS];
4895 struct epoll_event event;
4896 int timeout_ms;
4897 int num_events;
4898 unsigned int i;
4899 MHD_socket ls;
4900#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4901 bool run_upgraded = false;
4902#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4903 bool need_to_accept;
4904
4905 if (-1 == daemon->epoll_fd)
4906 return MHD_NO; /* we're down! */
4907 if (daemon->shutdown)
4908 return MHD_NO;
4909 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4910 (! daemon->was_quiesced) &&
4911 (daemon->connections < daemon->connection_limit) &&
4912 (! daemon->listen_socket_in_epoll) &&
4913 (! daemon->at_limit) )
4914 {
4915 event.events = EPOLLIN;
4916 event.data.ptr = daemon;
4917 if (0 != epoll_ctl (daemon->epoll_fd,
4918 EPOLL_CTL_ADD,
4919 ls,
4920 &event))
4921 {
4922#ifdef HAVE_MESSAGES
4923 MHD_DLOG (daemon,
4924 _ ("Call to epoll_ctl failed: %s\n"),
4926#endif
4927 return MHD_NO;
4928 }
4929 daemon->listen_socket_in_epoll = true;
4930 }
4931 if ( (daemon->was_quiesced) &&
4932 (daemon->listen_socket_in_epoll) )
4933 {
4934 if ( (0 != epoll_ctl (daemon->epoll_fd,
4935 EPOLL_CTL_DEL,
4936 ls,
4937 NULL)) &&
4938 (ENOENT != errno) ) /* ENOENT can happen due to race with
4939 #MHD_quiesce_daemon() */
4940 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4941 daemon->listen_socket_in_epoll = false;
4942 }
4943
4944#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4945 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4946 (-1 != daemon->epoll_upgrade_fd) ) )
4947 {
4948 event.events = EPOLLIN | EPOLLOUT;
4949 event.data.ptr = (void *) upgrade_marker;
4950 if (0 != epoll_ctl (daemon->epoll_fd,
4951 EPOLL_CTL_ADD,
4952 daemon->epoll_upgrade_fd,
4953 &event))
4954 {
4955#ifdef HAVE_MESSAGES
4956 MHD_DLOG (daemon,
4957 _ ("Call to epoll_ctl failed: %s\n"),
4959#endif
4960 return MHD_NO;
4961 }
4962 daemon->upgrade_fd_in_epoll = true;
4963 }
4964#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4965 if ( (daemon->listen_socket_in_epoll) &&
4966 ( (daemon->connections == daemon->connection_limit) ||
4967 (daemon->at_limit) ||
4968 (daemon->was_quiesced) ) )
4969 {
4970 /* we're at the connection limit, disable listen socket
4971 for event loop for now */
4972 if (0 != epoll_ctl (daemon->epoll_fd,
4973 EPOLL_CTL_DEL,
4974 ls,
4975 NULL))
4976 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
4977 daemon->listen_socket_in_epoll = false;
4978 }
4979
4980 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4981 (MHD_NO != resume_suspended_connections (daemon)) )
4982 millisec = 0;
4983
4984 timeout_ms = get_timeout_millisec_ (daemon, millisec);
4985
4986 /* Reset. New value will be set when connections are processed. */
4987 /* Note: Used mostly for uniformity here as same situation is
4988 * signaled in epoll mode by non-empty eready DLL. */
4989 daemon->data_already_pending = false;
4990
4991 need_to_accept = false;
4992 /* drain 'epoll' event queue; need to iterate as we get at most
4993 MAX_EVENTS in one system call here; in practice this should
4994 pretty much mean only one round, but better an extra loop here
4995 than unfair behavior... */
4996 num_events = MAX_EVENTS;
4997 while (MAX_EVENTS == num_events)
4998 {
4999 /* update event masks */
5000 num_events = epoll_wait (daemon->epoll_fd,
5001 events,
5002 MAX_EVENTS,
5003 timeout_ms);
5004 if (-1 == num_events)
5005 {
5006 const int err = MHD_socket_get_error_ ();
5007 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5008 return MHD_YES;
5009#ifdef HAVE_MESSAGES
5010 MHD_DLOG (daemon,
5011 _ ("Call to epoll_wait failed: %s\n"),
5012 MHD_socket_strerr_ (err));
5013#endif
5014 return MHD_NO;
5015 }
5016 for (i = 0; i < (unsigned int) num_events; i++)
5017 {
5018 /* First, check for the values of `ptr` that would indicate
5019 that this event is not about a normal connection. */
5020 if (NULL == events[i].data.ptr)
5021 continue; /* shutdown signal! */
5022#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5023 if (upgrade_marker == events[i].data.ptr)
5024 {
5025 /* activity on an upgraded connection, we process
5026 those in a separate epoll() */
5027 run_upgraded = true;
5028 continue;
5029 }
5030#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5031 if (epoll_itc_marker == events[i].data.ptr)
5032 {
5033 /* It's OK to clear ITC here as all external
5034 conditions will be processed later. */
5035 MHD_itc_clear_ (daemon->itc);
5036 continue;
5037 }
5038 if (daemon == events[i].data.ptr)
5039 {
5040 /* Check for error conditions on listen socket. */
5041 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
5042 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
5043 need_to_accept = true;
5044 continue;
5045 }
5046 /* this is an event relating to a 'normal' connection,
5047 remember the event and if appropriate mark the
5048 connection as 'eready'. */
5049 pos = events[i].data.ptr;
5050 /* normal processing: update read/write data */
5051 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
5052 {
5053 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
5054 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
5055 {
5056 EDLL_insert (daemon->eready_head,
5057 daemon->eready_tail,
5058 pos);
5059 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5060 }
5061 }
5062 else
5063 {
5064 if (0 != (events[i].events & EPOLLIN))
5065 {
5066 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
5067 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
5068 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
5069 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5070 {
5071 EDLL_insert (daemon->eready_head,
5072 daemon->eready_tail,
5073 pos);
5074 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5075 }
5076 }
5077 if (0 != (events[i].events & EPOLLOUT))
5078 {
5079 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
5081 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5082 {
5083 EDLL_insert (daemon->eready_head,
5084 daemon->eready_tail,
5085 pos);
5086 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5087 }
5088 }
5089 }
5090 }
5091 }
5092
5093 /* Process externally added connection if any */
5094 if (daemon->have_new)
5096
5097 if (need_to_accept)
5098 {
5099 unsigned int series_length = 0;
5100
5101 /* Run 'accept' until it fails or daemon at limit of connections.
5102 * Do not accept more then 10 connections at once. The rest will
5103 * be accepted on next turn (level trigger is used for listen
5104 * socket). */
5105 while ( (MHD_NO != MHD_accept_connection (daemon)) &&
5106 (series_length < 10) &&
5107 (daemon->connections < daemon->connection_limit) &&
5108 (! daemon->at_limit) )
5109 series_length++;
5110 }
5111
5112 /* Handle timed-out connections; we need to do this here
5113 as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
5114 as the other event loops do. As timeouts do not get an explicit
5115 event, we need to find those connections that might have timed out
5116 here.
5117
5118 Connections with custom timeouts must all be looked at, as we
5119 do not bother to sort that (presumably very short) list. */
5120 prev = daemon->manual_timeout_tail;
5121 while (NULL != (pos = prev))
5122 {
5123 prev = pos->prevX;
5125 }
5126 /* Connections with the default timeout are sorted by prepending
5127 them to the head of the list whenever we touch the connection;
5128 thus it suffices to iterate from the tail until the first
5129 connection is NOT timed out */
5130 prev = daemon->normal_timeout_tail;
5131 while (NULL != (pos = prev))
5132 {
5133 prev = pos->prevX;
5135 if (MHD_CONNECTION_CLOSED != pos->state)
5136 break; /* sorted by timeout, no need to visit the rest! */
5137 }
5138
5139#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5140 if (run_upgraded || (NULL != daemon->eready_urh_head))
5141 run_epoll_for_upgrade (daemon);
5142#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5143
5144 /* process events for connections */
5145 prev = daemon->eready_tail;
5146 while (NULL != (pos = prev))
5147 {
5148 prev = pos->prevE;
5149 call_handlers (pos,
5150 0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
5151 0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
5152 0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
5154 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
5156 {
5157 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
5158 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
5160 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
5162 {
5163 EDLL_remove (daemon->eready_head,
5164 daemon->eready_tail,
5165 pos);
5166 pos->epoll_state &=
5168 }
5169 }
5170 }
5171
5172 return MHD_YES;
5173}
5174
5175
5176#endif
5177
5178
5206enum MHD_Result
5207MHD_run (struct MHD_Daemon *daemon)
5208{
5209 if ( (daemon->shutdown) ||
5210 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5211 return MHD_NO;
5212
5213 (void) MHD_run_wait (daemon, 0);
5214 return MHD_YES;
5215}
5216
5217
5257MHD_run_wait (struct MHD_Daemon *daemon,
5258 int32_t millisec)
5259{
5260 enum MHD_Result res;
5261 if ( (daemon->shutdown) ||
5262 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5263 return MHD_NO;
5264
5265 if (0 > millisec)
5266 millisec = -1;
5267 if (false)
5268 {
5269 (void) 0; /* Mute compiler warning */
5270 }
5271#ifdef HAVE_POLL
5272 else if (0 != (daemon->options & MHD_USE_POLL))
5273 {
5274 res = MHD_poll_all (daemon, millisec);
5275 MHD_cleanup_connections (daemon);
5276 }
5277#endif /* HAVE_POLL */
5278#ifdef EPOLL_SUPPORT
5279 else if (0 != (daemon->options & MHD_USE_EPOLL))
5280 {
5281 res = MHD_epoll (daemon, millisec);
5282 MHD_cleanup_connections (daemon);
5283 }
5284#endif
5285 else
5286 {
5287 res = MHD_select (daemon, millisec);
5288 /* MHD_select does MHD_cleanup_connections already */
5289 }
5290 return res;
5291}
5292
5293
5302static void
5304{
5305 struct MHD_Daemon *daemon = pos->daemon;
5306
5307#ifdef MHD_USE_THREADS
5308 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
5309 MHD_thread_ID_match_current_ (daemon->pid) );
5310#endif /* MHD_USE_THREADS */
5311
5312 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5313 {
5315 return; /* must let thread to do the rest */
5316 }
5319#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5321#endif
5322 mhd_assert (! pos->suspended);
5323 mhd_assert (! pos->resuming);
5324 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
5326 daemon->normal_timeout_tail,
5327 pos);
5328 else
5330 daemon->manual_timeout_tail,
5331 pos);
5333 daemon->connections_tail,
5334 pos);
5335 DLL_insert (daemon->cleanup_head,
5336 daemon->cleanup_tail,
5337 pos);
5338 daemon->data_already_pending = true;
5339#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5341#endif
5342}
5343
5344
5345#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5353static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
5354MHD_polling_thread (void *cls)
5355{
5356 struct MHD_Daemon *daemon = cls;
5357#ifdef HAVE_PTHREAD_SIGMASK
5358 sigset_t s_mask;
5359 int err;
5360#endif /* HAVE_PTHREAD_SIGMASK */
5361
5362 MHD_thread_init_ (&(daemon->pid));
5363#ifdef HAVE_PTHREAD_SIGMASK
5364 if ((0 == sigemptyset (&s_mask)) &&
5365 (0 == sigaddset (&s_mask, SIGPIPE)))
5366 {
5367 err = pthread_sigmask (SIG_BLOCK, &s_mask, NULL);
5368 }
5369 else
5370 err = errno;
5371 if (0 == err)
5372 daemon->sigpipe_blocked = true;
5373#ifdef HAVE_MESSAGES
5374 else
5375 MHD_DLOG (daemon,
5376 _ ("Failed to block SIGPIPE on daemon thread: %s\n"),
5377 MHD_strerror_ (errno));
5378#endif /* HAVE_MESSAGES */
5379#endif /* HAVE_PTHREAD_SIGMASK */
5380 while (! daemon->shutdown)
5381 {
5382 if (0 != (daemon->options & MHD_USE_POLL))
5383 MHD_poll (daemon, MHD_YES);
5384#ifdef EPOLL_SUPPORT
5385 else if (0 != (daemon->options & MHD_USE_EPOLL))
5386 MHD_epoll (daemon, -1);
5387#endif
5388 else
5389 MHD_select (daemon, -1);
5390 MHD_cleanup_connections (daemon);
5391 }
5392
5393 /* Resume any pending for resume connections, join
5394 * all connection's threads (if any) and finally cleanup
5395 * everything. */
5396 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
5398 close_all_connections (daemon);
5399
5400 return (MHD_THRD_RTRN_TYPE_) 0;
5401}
5402
5403
5404#endif
5405
5406
5418static size_t
5420 struct MHD_Connection *connection,
5421 char *val)
5422{
5423 (void) cls; /* Mute compiler warning. */
5424
5425 (void) connection; /* Mute compiler warning. */
5426 return MHD_http_unescape (val);
5427}
5428
5429
5450struct MHD_Daemon *
5451MHD_start_daemon (unsigned int flags,
5452 uint16_t port,
5454 void *apc_cls,
5456 void *dh_cls,
5457 ...)
5458{
5459 struct MHD_Daemon *daemon;
5460 va_list ap;
5461
5462 va_start (ap,
5463 dh_cls);
5464 daemon = MHD_start_daemon_va (flags,
5465 port,
5466 apc,
5467 apc_cls,
5468 dh,
5469 dh_cls,
5470 ap);
5471 va_end (ap);
5472 return daemon;
5473}
5474
5475
5497{
5498#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5499 unsigned int i;
5500#endif
5501 MHD_socket ret;
5502
5503 ret = daemon->listen_fd;
5504 if (MHD_INVALID_SOCKET == ret)
5505 return MHD_INVALID_SOCKET;
5506 if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
5507 (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
5508 {
5509#ifdef HAVE_MESSAGES
5510 MHD_DLOG (daemon,
5511 _ (
5512 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n"));
5513#endif
5514 return MHD_INVALID_SOCKET;
5515 }
5516
5517#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5518 if (NULL != daemon->worker_pool)
5519 for (i = 0; i < daemon->worker_pool_size; i++)
5520 {
5521 daemon->worker_pool[i].was_quiesced = true;
5522#ifdef EPOLL_SUPPORT
5523 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5524 (-1 != daemon->worker_pool[i].epoll_fd) &&
5525 (daemon->worker_pool[i].listen_socket_in_epoll) )
5526 {
5527 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
5528 EPOLL_CTL_DEL,
5529 ret,
5530 NULL))
5531 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
5532 daemon->worker_pool[i].listen_socket_in_epoll = false;
5533 }
5534 else
5535#endif
5536 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
5537 {
5538 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
5539 MHD_PANIC (_ (
5540 "Failed to signal quiesce via inter-thread communication channel.\n"));
5541 }
5542 }
5543#endif
5544 daemon->was_quiesced = true;
5545#ifdef EPOLL_SUPPORT
5546 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5547 (-1 != daemon->epoll_fd) &&
5548 (daemon->listen_socket_in_epoll) )
5549 {
5550 if ( (0 != epoll_ctl (daemon->epoll_fd,
5551 EPOLL_CTL_DEL,
5552 ret,
5553 NULL)) &&
5554 (ENOENT != errno) ) /* ENOENT can happen due to race with
5555 #MHD_epoll() */
5556 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
5557 daemon->listen_socket_in_epoll = false;
5558 }
5559#endif
5560 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
5561 (! MHD_itc_activate_ (daemon->itc, "q")) )
5562 MHD_PANIC (_ (
5563 "failed to signal quiesce via inter-thread communication channel.\n"));
5564 return ret;
5565}
5566
5567
5575typedef void
5576(*VfprintfFunctionPointerType)(void *cls,
5577 const char *format,
5578 va_list va);
5579
5580
5589static enum MHD_Result
5590parse_options_va (struct MHD_Daemon *daemon,
5591 const struct sockaddr **servaddr,
5592 va_list ap);
5593
5594
5603static enum MHD_Result
5605 const struct sockaddr **servaddr,
5606 ...)
5607{
5608 va_list ap;
5609 enum MHD_Result ret;
5610
5611 va_start (ap, servaddr);
5612 ret = parse_options_va (daemon,
5613 servaddr,
5614 ap);
5615 va_end (ap);
5616 return ret;
5617}
5618
5619
5628static enum MHD_Result
5630 const struct sockaddr **servaddr,
5631 va_list ap)
5632{
5633 enum MHD_OPTION opt;
5634 struct MHD_OptionItem *oa;
5635 unsigned int i;
5636 unsigned int uv;
5637#ifdef HTTPS_SUPPORT
5638 enum MHD_Result ret;
5639 const char *pstr;
5640#if GNUTLS_VERSION_MAJOR >= 3
5641 gnutls_certificate_retrieve_function2 *pgcrf;
5642#endif
5643#if GNUTLS_VERSION_NUMBER >= 0x030603
5644 gnutls_certificate_retrieve_function3 *pgcrf2;
5645#endif
5646#endif /* HTTPS_SUPPORT */
5647
5648 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
5649 {
5650 /* Increase counter at start, so resulting value is number of
5651 * processed options, including any failed ones. */
5652 daemon->num_opts++;
5653 switch (opt)
5654 {
5656 daemon->pool_size = va_arg (ap,
5657 size_t);
5658 break;
5660 daemon->pool_increment = va_arg (ap,
5661 size_t);
5662 break;
5664 daemon->connection_limit = va_arg (ap,
5665 unsigned int);
5666 break;
5668 uv = va_arg (ap,
5669 unsigned int);
5670#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
5671 if ((UINT64_MAX / 4000 - 1) < uv)
5672 {
5673#ifdef HAVE_MESSAGES
5674 MHD_DLOG (daemon,
5675 _ ("The specified connection timeout (%u) is too large. " \
5676 "Maximum allowed value (%" PRIu64 ") will be used " \
5677 "instead.\n"),
5678 uv,
5679 (UINT64_MAX / 4000 - 1));
5680#endif
5681 uv = UINT64_MAX / 4000 - 1;
5682 }
5683#endif /* (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT */
5684 daemon->connection_timeout_ms = uv * 1000;
5685 break;
5687 daemon->notify_completed = va_arg (ap,
5689 daemon->notify_completed_cls = va_arg (ap,
5690 void *);
5691 break;
5693 daemon->notify_connection = va_arg (ap,
5695 daemon->notify_connection_cls = va_arg (ap,
5696 void *);
5697 break;
5699 daemon->per_ip_connection_limit = va_arg (ap,
5700 unsigned int);
5701 break;
5703 *servaddr = va_arg (ap,
5704 const struct sockaddr *);
5705 break;
5707 daemon->uri_log_callback = va_arg (ap,
5708 LogCallback);
5709 daemon->uri_log_callback_cls = va_arg (ap,
5710 void *);
5711 break;
5713 daemon->insanity_level = (enum MHD_DisableSanityCheck)
5714 va_arg (ap,
5715 unsigned int);
5716 break;
5717#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5719 daemon->worker_pool_size = va_arg (ap,
5720 unsigned int);
5721 if (0 == daemon->worker_pool_size)
5722 {
5723#ifdef HAVE_MESSAGES
5724 MHD_DLOG (daemon,
5725 _ (
5726 "Warning: Zero size, specified for thread pool size, is ignored. "
5727 "Thread pool is not used.\n"));
5728#endif
5729 }
5730 else if (1 == daemon->worker_pool_size)
5731 {
5732#ifdef HAVE_MESSAGES
5733 MHD_DLOG (daemon,
5734 _ (
5735 "Warning: \"1\", specified for thread pool size, is ignored. "
5736 "Thread pool is not used.\n"));
5737#endif
5738 daemon->worker_pool_size = 0;
5739 }
5740#if SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2)
5741 /* Next comparison could be always false on some platforms and whole branch will
5742 * be optimized out on these platforms. On others it will be compiled into real
5743 * check. */
5744 else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct
5745 MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
5746 {
5747#ifdef HAVE_MESSAGES
5748 MHD_DLOG (daemon,
5749 _ ("Specified thread pool size (%u) too big.\n"),
5750 daemon->worker_pool_size);
5751#endif
5752 return MHD_NO;
5753 }
5754#endif /* SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2) */
5755 else
5756 {
5757 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
5758 {
5759#ifdef HAVE_MESSAGES
5760 MHD_DLOG (daemon,
5761 _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5762 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5763#endif
5764 return MHD_NO;
5765 }
5766 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5767 {
5768#ifdef HAVE_MESSAGES
5769 MHD_DLOG (daemon,
5770 _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
5771 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5772#endif
5773 return MHD_NO;
5774 }
5775 }
5776 break;
5777#endif
5778#ifdef HTTPS_SUPPORT
5780 pstr = va_arg (ap,
5781 const char *);
5782 if (0 != (daemon->options & MHD_USE_TLS))
5783 daemon->https_mem_key = pstr;
5784#ifdef HAVE_MESSAGES
5785 else
5786 MHD_DLOG (daemon,
5787 _ (
5788 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5789 opt);
5790#endif
5791 break;
5793 pstr = va_arg (ap,
5794 const char *);
5795 if (0 != (daemon->options & MHD_USE_TLS))
5796 daemon->https_key_password = pstr;
5797#ifdef HAVE_MESSAGES
5798 else
5799 MHD_DLOG (daemon,
5800 _ (
5801 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5802 opt);
5803#endif
5804 break;
5806 pstr = va_arg (ap,
5807 const char *);
5808 if (0 != (daemon->options & MHD_USE_TLS))
5809 daemon->https_mem_cert = pstr;
5810#ifdef HAVE_MESSAGES
5811 else
5812 MHD_DLOG (daemon,
5813 _ (
5814 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5815 opt);
5816#endif
5817 break;
5819 pstr = va_arg (ap,
5820 const char *);
5821 if (0 != (daemon->options & MHD_USE_TLS))
5822 daemon->https_mem_trust = pstr;
5823#ifdef HAVE_MESSAGES
5824 else
5825 MHD_DLOG (daemon,
5826 _ (
5827 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5828 opt);
5829#endif
5830 break;
5832 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5833 int);
5834 break;
5836 pstr = va_arg (ap,
5837 const char *);
5838 if (0 != (daemon->options & MHD_USE_TLS))
5839 {
5840 gnutls_datum_t dhpar;
5841 size_t pstr_len;
5842
5843 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5844 {
5845#ifdef HAVE_MESSAGES
5846 MHD_DLOG (daemon,
5847 _ ("Error initializing DH parameters.\n"));
5848#endif
5849 return MHD_NO;
5850 }
5851 dhpar.data = (unsigned char *) pstr;
5852 pstr_len = strlen (pstr);
5853 if (UINT_MAX < pstr_len)
5854 {
5855#ifdef HAVE_MESSAGES
5856 MHD_DLOG (daemon,
5857 _ ("Diffie-Hellman parameters string too long.\n"));
5858#endif
5859 return MHD_NO;
5860 }
5861 dhpar.size = (unsigned int) pstr_len;
5862 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5863 &dhpar,
5864 GNUTLS_X509_FMT_PEM) < 0)
5865 {
5866#ifdef HAVE_MESSAGES
5867 MHD_DLOG (daemon,
5868 _ ("Bad Diffie-Hellman parameters format.\n"));
5869#endif
5870 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5871 return MHD_NO;
5872 }
5873 daemon->have_dhparams = true;
5874 }
5875#ifdef HAVE_MESSAGES
5876 else
5877 MHD_DLOG (daemon,
5878 _ (
5879 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5880 opt);
5881#endif
5882 break;
5884 pstr = va_arg (ap,
5885 const char *);
5886 if (0 != (daemon->options & MHD_USE_TLS))
5887 {
5888 gnutls_priority_deinit (daemon->priority_cache);
5889 ret = gnutls_priority_init (&daemon->priority_cache,
5890 pstr,
5891 NULL);
5892 if (GNUTLS_E_SUCCESS != ret)
5893 {
5894#ifdef HAVE_MESSAGES
5895 MHD_DLOG (daemon,
5896 _ ("Setting priorities to `%s' failed: %s\n"),
5897 pstr,
5898 gnutls_strerror (ret));
5899#endif
5900 daemon->priority_cache = NULL;
5901 return MHD_NO;
5902 }
5903 }
5904#ifdef HAVE_MESSAGES
5905 else
5906 MHD_DLOG (daemon,
5907 _ (
5908 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5909 opt);
5910#endif
5911 break;
5913#if GNUTLS_VERSION_MAJOR < 3
5914#ifdef HAVE_MESSAGES
5915 MHD_DLOG (daemon,
5916 _ (
5917 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5918#endif
5919 return MHD_NO;
5920#else
5921 pgcrf = va_arg (ap,
5922 gnutls_certificate_retrieve_function2 *);
5923 if (0 != (daemon->options & MHD_USE_TLS))
5924 daemon->cert_callback = pgcrf;
5925#ifdef HAVE_MESSAGES
5926 else
5927 MHD_DLOG (daemon,
5928 _ (
5929 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5930 opt);
5931#endif /* HAVE_MESSAGES */
5932 break;
5933#endif
5935#if GNUTLS_VERSION_NUMBER < 0x030603
5936#ifdef HAVE_MESSAGES
5937 MHD_DLOG (daemon,
5938 _ (
5939 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5940#endif
5941 return MHD_NO;
5942#else
5943 pgcrf2 = va_arg (ap,
5944 gnutls_certificate_retrieve_function3 *);
5945 if (0 != (daemon->options & MHD_USE_TLS))
5946 daemon->cert_callback2 = pgcrf2;
5947#ifdef HAVE_MESSAGES
5948 else
5949 MHD_DLOG (daemon,
5950 _ (
5951 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5952 opt);
5953#endif /* HAVE_MESSAGES */
5954 break;
5955#endif
5956#endif /* HTTPS_SUPPORT */
5957#ifdef DAUTH_SUPPORT
5959 daemon->digest_auth_rand_size = va_arg (ap,
5960 size_t);
5961 daemon->digest_auth_random = va_arg (ap,
5962 const char *);
5963 break;
5965 daemon->nonce_nc_size = va_arg (ap,
5966 unsigned int);
5967 break;
5968#endif
5970 if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5971 {
5972#ifdef HAVE_MESSAGES
5973 MHD_DLOG (daemon,
5974 _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5975 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5976#endif
5977 return MHD_NO;
5978 }
5979 else
5980 {
5981 daemon->listen_fd = va_arg (ap,
5982 MHD_socket);
5983#if defined(SO_DOMAIN) && defined(AF_UNIX)
5984 {
5985 int af;
5986 socklen_t len = sizeof (af);
5987
5988 if (0 == getsockopt (daemon->listen_fd,
5989 SOL_SOCKET,
5990 SO_DOMAIN,
5991 &af,
5992 &len))
5993 {
5994 daemon->listen_is_unix = (AF_UNIX == af) ? _MHD_YES : _MHD_NO;
5995 }
5996 else
5997 daemon->listen_is_unix = _MHD_UNKNOWN;
5998 }
5999#else /* ! SO_DOMAIN || ! AF_UNIX */
6000 daemon->listen_is_unix = _MHD_UNKNOWN;
6001#endif /* ! SO_DOMAIN || ! AF_UNIX */
6002 }
6003 break;
6005#ifdef HAVE_MESSAGES
6006 daemon->custom_error_log = va_arg (ap,
6008 daemon->custom_error_log_cls = va_arg (ap,
6009 void *);
6010 if (1 != daemon->num_opts)
6011 MHD_DLOG (daemon,
6012 _ ("MHD_OPTION_EXTERNAL_LOGGER is not the first option "
6013 "specified for the daemon. Some messages may be "
6014 "printed by the standard MHD logger.\n"));
6015
6016#else
6017 va_arg (ap,
6019 va_arg (ap,
6020 void *);
6021#endif
6022 break;
6023#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6025 daemon->thread_stack_size = va_arg (ap,
6026 size_t);
6027 break;
6028#endif
6030#ifdef TCP_FASTOPEN
6031 daemon->fastopen_queue_size = va_arg (ap,
6032 unsigned int);
6033 break;
6034#else /* ! TCP_FASTOPEN */
6035#ifdef HAVE_MESSAGES
6036 MHD_DLOG (daemon,
6037 _ ("TCP fastopen is not supported on this platform.\n"));
6038#endif /* HAVE_MESSAGES */
6039 return MHD_NO;
6040#endif /* ! TCP_FASTOPEN */
6042 daemon->listening_address_reuse = va_arg (ap,
6043 unsigned int) ? 1 : -1;
6044 break;
6046 daemon->listen_backlog_size = va_arg (ap,
6047 unsigned int);
6048 break;
6050 daemon->strict_for_client = va_arg (ap, int);
6051#ifdef HAVE_MESSAGES
6052 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
6053 (1 != daemon->strict_for_client) )
6054 {
6055 MHD_DLOG (daemon,
6056 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
6057 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
6058 }
6059#endif /* HAVE_MESSAGES */
6060 break;
6061 case MHD_OPTION_ARRAY:
6062 daemon->num_opts--; /* Do not count MHD_OPTION_ARRAY */
6063 oa = va_arg (ap, struct MHD_OptionItem *);
6064 i = 0;
6065 while (MHD_OPTION_END != (opt = oa[i].option))
6066 {
6067 switch (opt)
6068 {
6069 /* all options taking 'size_t' */
6073 if (MHD_NO == parse_options (daemon,
6074 servaddr,
6075 opt,
6076 (size_t) oa[i].value,
6078 return MHD_NO;
6079 break;
6080 /* all options taking 'unsigned int' */
6090 if (MHD_NO == parse_options (daemon,
6091 servaddr,
6092 opt,
6093 (unsigned int) oa[i].value,
6095 return MHD_NO;
6096 break;
6097 /* all options taking 'enum' */
6098#ifdef HTTPS_SUPPORT
6100 if (MHD_NO == parse_options (daemon,
6101 servaddr,
6102 opt,
6103 (gnutls_credentials_type_t) oa[i].value,
6105 return MHD_NO;
6106 break;
6107#endif /* HTTPS_SUPPORT */
6108 /* all options taking 'MHD_socket' */
6110 if (MHD_NO == parse_options (daemon,
6111 servaddr,
6112 opt,
6113 (MHD_socket) oa[i].value,
6115 return MHD_NO;
6116 break;
6117 /* all options taking 'int' */
6121 if (MHD_NO == parse_options (daemon,
6122 servaddr,
6123 opt,
6124 (int) oa[i].value,
6126 return MHD_NO;
6127 break;
6128 /* all options taking one pointer */
6136 case MHD_OPTION_ARRAY:
6139 if (MHD_NO == parse_options (daemon,
6140 servaddr,
6141 opt,
6142 oa[i].ptr_value,
6144 return MHD_NO;
6145 break;
6146 /* all options taking two pointers */
6153 if (MHD_NO == parse_options (daemon,
6154 servaddr,
6155 opt,
6156 (void *) oa[i].value,
6157 oa[i].ptr_value,
6159 return MHD_NO;
6160 break;
6161 /* options taking size_t-number followed by pointer */
6163 if (MHD_NO == parse_options (daemon,
6164 servaddr,
6165 opt,
6166 (size_t) oa[i].value,
6167 oa[i].ptr_value,
6169 return MHD_NO;
6170 break;
6171 default:
6172 return MHD_NO;
6173 }
6174 i++;
6175 }
6176 break;
6178 daemon->unescape_callback = va_arg (ap,
6180 daemon->unescape_callback_cls = va_arg (ap,
6181 void *);
6182 break;
6183#ifdef HTTPS_SUPPORT
6185#if GNUTLS_VERSION_MAJOR >= 3
6186 daemon->cred_callback = va_arg (ap,
6188 daemon->cred_callback_cls = va_arg (ap,
6189 void *);
6190 break;
6191#else
6192 MHD_DLOG (daemon,
6193 _ (
6194 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
6195 opt);
6196 return MHD_NO;
6197#endif
6198#endif /* HTTPS_SUPPORT */
6200 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6201 daemon->sigpipe_blocked = ( (va_arg (ap,
6202 int)) != 0);
6203 else
6204 {
6205 (void) va_arg (ap,
6206 int);
6207 }
6208 break;
6210#ifdef HTTPS_SUPPORT
6211 daemon->disable_alpn = (va_arg (ap,
6212 int) != 0);
6213#else /* ! HTTPS_SUPPORT */
6214 (void) va_arg (ap, int);
6215#endif /* ! HTTPS_SUPPORT */
6216#ifdef HAVE_MESSAGES
6217 if (0 == (daemon->options & MHD_USE_TLS))
6218 MHD_DLOG (daemon,
6219 _ ("MHD HTTPS option %d passed to MHD " \
6220 "but MHD_USE_TLS not set.\n"),
6221 (int) opt);
6222#endif /* HAVE_MESSAGES */
6223 break;
6224 default:
6225#ifdef HAVE_MESSAGES
6226 if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
6227 (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
6228 (opt == MHD_OPTION_HTTPS_MEM_TRUST) ||
6230 {
6231 MHD_DLOG (daemon,
6232 _ (
6233 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
6234 opt);
6235 }
6236 else
6237 {
6238 MHD_DLOG (daemon,
6239 _ (
6240 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
6241 opt);
6242 }
6243#endif
6244 return MHD_NO;
6245 }
6246 }
6247 return MHD_YES;
6248}
6249
6250
6251#ifdef EPOLL_SUPPORT
6252static int
6253setup_epoll_fd (struct MHD_Daemon *daemon)
6254{
6255 int fd;
6256
6257#ifndef HAVE_MESSAGES
6258 (void) daemon; /* Mute compiler warning. */
6259#endif /* ! HAVE_MESSAGES */
6260
6261#ifdef USE_EPOLL_CREATE1
6262 fd = epoll_create1 (EPOLL_CLOEXEC);
6263#else /* ! USE_EPOLL_CREATE1 */
6264 fd = epoll_create (MAX_EVENTS);
6265#endif /* ! USE_EPOLL_CREATE1 */
6266 if (MHD_INVALID_SOCKET == fd)
6267 {
6268#ifdef HAVE_MESSAGES
6269 MHD_DLOG (daemon,
6270 _ ("Call to epoll_create1 failed: %s\n"),
6272#endif
6273 return MHD_INVALID_SOCKET;
6274 }
6275#if ! defined(USE_EPOLL_CREATE1)
6277 {
6278#ifdef HAVE_MESSAGES
6279 MHD_DLOG (daemon,
6280 _ ("Failed to set noninheritable mode on epoll FD.\n"));
6281#endif
6282 }
6283#endif /* ! USE_EPOLL_CREATE1 */
6284 return fd;
6285}
6286
6287
6296static enum MHD_Result
6297setup_epoll_to_listen (struct MHD_Daemon *daemon)
6298{
6299 struct epoll_event event;
6300 MHD_socket ls;
6301
6302 mhd_assert (0 != (daemon->options & MHD_USE_EPOLL));
6304 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
6305 (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) || \
6306 MHD_ITC_IS_VALID_ (daemon->itc) );
6307 daemon->epoll_fd = setup_epoll_fd (daemon);
6308 if (-1 == daemon->epoll_fd)
6309 return MHD_NO;
6310#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6311 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
6312 {
6313 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
6314 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
6315 return MHD_NO;
6316 }
6317#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6318 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
6319 (! daemon->was_quiesced) )
6320 {
6321 event.events = EPOLLIN;
6322 event.data.ptr = daemon;
6323 if (0 != epoll_ctl (daemon->epoll_fd,
6324 EPOLL_CTL_ADD,
6325 ls,
6326 &event))
6327 {
6328#ifdef HAVE_MESSAGES
6329 MHD_DLOG (daemon,
6330 _ ("Call to epoll_ctl failed: %s\n"),
6332#endif
6333 return MHD_NO;
6334 }
6335 daemon->listen_socket_in_epoll = true;
6336 }
6337
6338 if (MHD_ITC_IS_VALID_ (daemon->itc))
6339 {
6340 event.events = EPOLLIN;
6341 event.data.ptr = (void *) epoll_itc_marker;
6342 if (0 != epoll_ctl (daemon->epoll_fd,
6343 EPOLL_CTL_ADD,
6344 MHD_itc_r_fd_ (daemon->itc),
6345 &event))
6346 {
6347#ifdef HAVE_MESSAGES
6348 MHD_DLOG (daemon,
6349 _ ("Call to epoll_ctl failed: %s\n"),
6351#endif
6352 return MHD_NO;
6353 }
6354 }
6355 return MHD_YES;
6356}
6357
6358
6359#endif
6360
6361
6383struct MHD_Daemon *
6384MHD_start_daemon_va (unsigned int flags,
6385 uint16_t port,
6387 void *apc_cls,
6389 void *dh_cls,
6390 va_list ap)
6391{
6392 const MHD_SCKT_OPT_BOOL_ on = 1;
6393 struct MHD_Daemon *daemon;
6395 struct sockaddr_in servaddr4;
6396#if HAVE_INET6
6397 struct sockaddr_in6 servaddr6;
6398#endif
6399 const struct sockaddr *servaddr = NULL;
6400 socklen_t addrlen;
6401#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6402 unsigned int i;
6403#endif
6404 enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
6405 enum MHD_FLAG *pflags;
6406
6408 eflags = (enum MHD_FLAG) flags;
6409 pflags = &eflags;
6410#ifndef HAVE_INET6
6411 if (0 != (*pflags & MHD_USE_IPv6))
6412 return NULL;
6413#endif
6414#ifndef HAVE_POLL
6415 if (0 != (*pflags & MHD_USE_POLL))
6416 return NULL;
6417#endif
6418#ifndef EPOLL_SUPPORT
6419 if (0 != (*pflags & MHD_USE_EPOLL))
6420 return NULL;
6421#endif /* ! EPOLL_SUPPORT */
6422#ifndef HTTPS_SUPPORT
6423 if (0 != (*pflags & MHD_USE_TLS))
6424 return NULL;
6425#endif /* ! HTTPS_SUPPORT */
6426#ifndef TCP_FASTOPEN
6427 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6428 return NULL;
6429#endif
6430 if (0 != (*pflags & MHD_ALLOW_UPGRADE))
6431 {
6432#ifdef UPGRADE_SUPPORT
6433 *pflags |= MHD_ALLOW_SUSPEND_RESUME;
6434#else /* ! UPGRADE_SUPPORT */
6435 return NULL;
6436#endif /* ! UPGRADE_SUPPORT */
6437 }
6438 if (NULL == dh)
6439 return NULL;
6440
6441 /* Check for invalid combinations of flags. */
6442 if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
6443 ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags
6444 &
6446 ||
6447 ((0 != (*pflags & MHD_USE_POLL)) &&
6448 (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
6450 ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL
6451 | MHD_USE_EPOLL)))) )
6452 return NULL;
6453
6454 if (0 != (*pflags & MHD_USE_AUTO))
6455 {
6456 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6457 {
6458 /* Thread per connection with internal polling thread. */
6459#ifdef HAVE_POLL
6460 *pflags |= MHD_USE_POLL;
6461#else /* ! HAVE_POLL */
6462 /* use select() - do not modify flags */
6463#endif /* ! HAVE_POLL */
6464 }
6465 else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
6466 {
6467 /* Internal polling thread. */
6468#if defined(EPOLL_SUPPORT)
6469 *pflags |= MHD_USE_EPOLL;
6470#elif defined(HAVE_POLL)
6471 *pflags |= MHD_USE_POLL;
6472#else /* !HAVE_POLL && !EPOLL_SUPPORT */
6473 /* use select() - do not modify flags */
6474#endif /* !HAVE_POLL && !EPOLL_SUPPORT */
6475 }
6476 else
6477 {
6478 /* Internal threads are not used - "external" polling mode. */
6479#if defined(EPOLL_SUPPORT)
6480 *pflags |= MHD_USE_EPOLL;
6481#else /* ! EPOLL_SUPPORT */
6482 /* use select() - do not modify flags */
6483#endif /* ! EPOLL_SUPPORT */
6484 }
6485 }
6486
6487 if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
6488 return NULL;
6489#ifdef EPOLL_SUPPORT
6490 daemon->epoll_fd = -1;
6491#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6492 daemon->epoll_upgrade_fd = -1;
6493#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6494#endif
6495 /* try to open listen socket */
6496#ifdef HTTPS_SUPPORT
6497 daemon->priority_cache = NULL;
6498 if (0 != (*pflags & MHD_USE_TLS))
6499 {
6500 gnutls_priority_init (&daemon->priority_cache,
6501 "@SYSTEM",
6502 NULL);
6503 }
6504#endif /* HTTPS_SUPPORT */
6505 daemon->listen_fd = MHD_INVALID_SOCKET;
6506 daemon->listen_is_unix = _MHD_NO;
6507 daemon->listening_address_reuse = 0;
6508 daemon->options = *pflags;
6509 pflags = &daemon->options;
6510 daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 :
6511 0;
6512 daemon->port = port;
6513 daemon->apc = apc;
6514 daemon->apc_cls = apc_cls;
6515 daemon->default_handler = dh;
6516 daemon->default_handler_cls = dh_cls;
6517 daemon->connections = 0;
6522 daemon->connection_timeout_ms = 0; /* no timeout */
6523 MHD_itc_set_invalid_ (daemon->itc);
6524#ifdef SOMAXCONN
6525 daemon->listen_backlog_size = SOMAXCONN;
6526#else /* !SOMAXCONN */
6527 daemon->listen_backlog_size = 511; /* should be safe value */
6528#endif /* !SOMAXCONN */
6529#ifdef HAVE_MESSAGES
6530 daemon->custom_error_log = &MHD_default_logger_;
6531 daemon->custom_error_log_cls = stderr;
6532#endif
6533#ifndef MHD_WINSOCK_SOCKETS
6534 daemon->sigpipe_blocked = false;
6535#else /* MHD_WINSOCK_SOCKETS */
6536 /* There is no SIGPIPE on W32, nothing to block. */
6537 daemon->sigpipe_blocked = true;
6538#endif /* _WIN32 && ! __CYGWIN__ */
6539
6540 if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
6541 (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
6542 {
6543 /* Log warning message later, when log parameters are processes */
6545 }
6546 if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
6547 *pflags = (*pflags & ~((enum MHD_FLAG) MHD_USE_ITC)); /* useless if we are using 'external' select */
6548 else
6549 {
6550#ifdef HAVE_LISTEN_SHUTDOWN
6551 if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
6552#endif
6553 *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
6554 }
6555#ifdef DAUTH_SUPPORT
6556 daemon->digest_auth_rand_size = 0;
6557 daemon->digest_auth_random = NULL;
6558 daemon->nonce_nc_size = 4; /* tiny */
6559#endif
6560#ifdef HTTPS_SUPPORT
6561 if (0 != (*pflags & MHD_USE_TLS))
6562 {
6563 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
6564 }
6565#endif /* HTTPS_SUPPORT */
6566
6567
6568 if (MHD_NO == parse_options_va (daemon,
6569 &servaddr,
6570 ap))
6571 {
6572#ifdef HTTPS_SUPPORT
6573 if ( (0 != (*pflags & MHD_USE_TLS)) &&
6574 (NULL != daemon->priority_cache) )
6575 gnutls_priority_deinit (daemon->priority_cache);
6576#endif /* HTTPS_SUPPORT */
6577 free (daemon);
6578 return NULL;
6579 }
6580
6581#ifdef HAVE_MESSAGES
6582 if ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) &&
6583 (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD)) )
6584 {
6585 MHD_DLOG (daemon,
6586 _ (
6587 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
6588 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
6589 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
6590 }
6591#endif
6592
6593 if ( (NULL != daemon->notify_completed) &&
6594 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
6595 *pflags |= MHD_USE_ITC; /* requires ITC */
6596
6597#ifndef NDEBUG
6598#ifdef HAVE_MESSAGES
6599 MHD_DLOG (daemon,
6600 _ ("Using debug build of libmicrohttpd.\n") );
6601#endif /* HAVE_MESSAGES */
6602#endif /* ! NDEBUG */
6603
6604 if ( (0 != (*pflags & MHD_USE_ITC))
6605#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6606 && (0 == daemon->worker_pool_size)
6607#endif
6608 )
6609 {
6610 if (! MHD_itc_init_ (daemon->itc))
6611 {
6612#ifdef HAVE_MESSAGES
6613 MHD_DLOG (daemon,
6614 _ ("Failed to create inter-thread communication channel: %s\n"),
6615 MHD_itc_last_strerror_ ());
6616#endif
6617#ifdef HTTPS_SUPPORT
6618 if (NULL != daemon->priority_cache)
6619 gnutls_priority_deinit (daemon->priority_cache);
6620#endif /* HTTPS_SUPPORT */
6621 free (daemon);
6622 return NULL;
6623 }
6624 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6625 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
6626 NULL)) )
6627 {
6628#ifdef HAVE_MESSAGES
6629 MHD_DLOG (daemon,
6630 _ (
6631 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
6632#endif
6633 MHD_itc_destroy_chk_ (daemon->itc);
6634#ifdef HTTPS_SUPPORT
6635 if (NULL != daemon->priority_cache)
6636 gnutls_priority_deinit (daemon->priority_cache);
6637#endif /* HTTPS_SUPPORT */
6638 free (daemon);
6639 return NULL;
6640 }
6641 }
6642
6643#ifdef DAUTH_SUPPORT
6644 if (daemon->nonce_nc_size > 0)
6645 {
6646 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
6647 / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
6648 {
6649#ifdef HAVE_MESSAGES
6650 MHD_DLOG (daemon,
6651 _ ("Specified value for NC_SIZE too large.\n"));
6652#endif
6653#ifdef HTTPS_SUPPORT
6654 if (0 != (*pflags & MHD_USE_TLS))
6655 gnutls_priority_deinit (daemon->priority_cache);
6656#endif /* HTTPS_SUPPORT */
6657 free (daemon);
6658 return NULL;
6659 }
6660 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
6661 if (NULL == daemon->nnc)
6662 {
6663#ifdef HAVE_MESSAGES
6664 MHD_DLOG (daemon,
6665 _ ("Failed to allocate memory for nonce-nc map: %s\n"),
6666 MHD_strerror_ (errno));
6667#endif
6668#ifdef HTTPS_SUPPORT
6669 if (0 != (*pflags & MHD_USE_TLS))
6670 gnutls_priority_deinit (daemon->priority_cache);
6671#endif /* HTTPS_SUPPORT */
6672 free (daemon);
6673 return NULL;
6674 }
6675 }
6676
6677#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6678 if (! MHD_mutex_init_ (&daemon->nnc_lock))
6679 {
6680#ifdef HAVE_MESSAGES
6681 MHD_DLOG (daemon,
6682 _ ("MHD failed to initialize nonce-nc mutex.\n"));
6683#endif
6684#ifdef HTTPS_SUPPORT
6685 if (0 != (*pflags & MHD_USE_TLS))
6686 gnutls_priority_deinit (daemon->priority_cache);
6687#endif /* HTTPS_SUPPORT */
6688 free (daemon->nnc);
6689 free (daemon);
6690 return NULL;
6691 }
6692#endif
6693#endif
6694
6695 /* Thread polling currently works only with internal select thread mode */
6696#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6697 if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
6698 (daemon->worker_pool_size > 0) )
6699 {
6700#ifdef HAVE_MESSAGES
6701 MHD_DLOG (daemon,
6702 _ (
6703 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6704#endif
6705 goto free_and_fail;
6706 }
6707#endif
6708 if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
6709 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6710 {
6711 /* try to open listen socket */
6712 int domain;
6713
6714#ifdef HAVE_INET6
6715 domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6716#else /* ! HAVE_INET6 */
6717 if (*pflags & MHD_USE_IPv6)
6718 goto free_and_fail;
6719 domain = PF_INET;
6720#endif /* ! HAVE_INET6 */
6721
6722 listen_fd = MHD_socket_create_listen_ (domain);
6723 if (MHD_INVALID_SOCKET == listen_fd)
6724 {
6725#ifdef HAVE_MESSAGES
6726 MHD_DLOG (daemon,
6727 _ ("Failed to create socket for listening: %s\n"),
6729#endif
6730 goto free_and_fail;
6731 }
6732
6733 /* Apply the socket options according to listening_address_reuse. */
6734 if (0 == daemon->listening_address_reuse)
6735 {
6736#ifndef MHD_WINSOCK_SOCKETS
6737 /* No user requirement, use "traditional" default SO_REUSEADDR
6738 * on non-W32 platforms, and do not fail if it doesn't work.
6739 * Don't use it on W32, because on W32 it will allow multiple
6740 * bind to the same address:port, like SO_REUSEPORT on others. */
6741 if (0 > setsockopt (listen_fd,
6742 SOL_SOCKET,
6743 SO_REUSEADDR,
6744 (void *) &on, sizeof (on)))
6745 {
6746#ifdef HAVE_MESSAGES
6747 MHD_DLOG (daemon,
6748 _ ("setsockopt failed: %s\n"),
6750#endif
6751 }
6752#endif /* ! MHD_WINSOCK_SOCKETS */
6753 }
6754 else if (daemon->listening_address_reuse > 0)
6755 {
6756 /* User requested to allow reusing listening address:port. */
6757#ifndef MHD_WINSOCK_SOCKETS
6758 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
6759 * it doesn't work. */
6760 if (0 > setsockopt (listen_fd,
6761 SOL_SOCKET,
6762 SO_REUSEADDR,
6763 (void *) &on, sizeof (on)))
6764 {
6765#ifdef HAVE_MESSAGES
6766 MHD_DLOG (daemon,
6767 _ ("setsockopt failed: %s\n"),
6769#endif
6770 }
6771#endif /* ! MHD_WINSOCK_SOCKETS */
6772 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
6773 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
6774 */
6775 /* SO_REUSEADDR on W32 has the same semantics
6776 as SO_REUSEPORT on BSD/Linux */
6777#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6778 if (0 > setsockopt (listen_fd,
6779 SOL_SOCKET,
6780#ifndef MHD_WINSOCK_SOCKETS
6781 SO_REUSEPORT,
6782#else /* MHD_WINSOCK_SOCKETS */
6783 SO_REUSEADDR,
6784#endif /* MHD_WINSOCK_SOCKETS */
6785 (void *) &on,
6786 sizeof (on)))
6787 {
6788#ifdef HAVE_MESSAGES
6789 MHD_DLOG (daemon,
6790 _ ("setsockopt failed: %s\n"),
6792#endif
6793 goto free_and_fail;
6794 }
6795#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6796 /* we're supposed to allow address:port re-use, but
6797 on this platform we cannot; fail hard */
6798#ifdef HAVE_MESSAGES
6799 MHD_DLOG (daemon,
6800 _ (
6801 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6802#endif
6803 goto free_and_fail;
6804#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6805 }
6806 else /* if (daemon->listening_address_reuse < 0) */
6807 {
6808 /* User requested to disallow reusing listening address:port.
6809 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
6810 * is used and Solaris with SO_EXCLBIND.
6811 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
6812 * or setsockopt fails.
6813 */
6814#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6815 (defined(__sun) && defined(SO_EXCLBIND))
6816 if (0 > setsockopt (listen_fd,
6817 SOL_SOCKET,
6818#ifdef SO_EXCLUSIVEADDRUSE
6819 SO_EXCLUSIVEADDRUSE,
6820#else /* SO_EXCLBIND */
6821 SO_EXCLBIND,
6822#endif /* SO_EXCLBIND */
6823 (void *) &on,
6824 sizeof (on)))
6825 {
6826#ifdef HAVE_MESSAGES
6827 MHD_DLOG (daemon,
6828 _ ("setsockopt failed: %s\n"),
6830#endif
6831 goto free_and_fail;
6832 }
6833#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
6834#ifdef HAVE_MESSAGES
6835 MHD_DLOG (daemon,
6836 _ (
6837 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6838#endif
6839 goto free_and_fail;
6840#endif /* MHD_WINSOCK_SOCKETS */
6841 }
6842
6843 /* check for user supplied sockaddr */
6844#if HAVE_INET6
6845 if (0 != (*pflags & MHD_USE_IPv6))
6846 addrlen = sizeof (struct sockaddr_in6);
6847 else
6848#endif
6849 addrlen = sizeof (struct sockaddr_in);
6850 if (NULL == servaddr)
6851 {
6852#if HAVE_INET6
6853 if (0 != (*pflags & MHD_USE_IPv6))
6854 {
6855#ifdef IN6ADDR_ANY_INIT
6856 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6857#endif
6858 memset (&servaddr6,
6859 0,
6860 sizeof (struct sockaddr_in6));
6861 servaddr6.sin6_family = AF_INET6;
6862 servaddr6.sin6_port = htons (port);
6863#ifdef IN6ADDR_ANY_INIT
6864 servaddr6.sin6_addr = static_in6any;
6865#endif
6866#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6867 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
6868#endif
6869 servaddr = (struct sockaddr *) &servaddr6;
6870 }
6871 else
6872#endif
6873 {
6874 memset (&servaddr4,
6875 0,
6876 sizeof (struct sockaddr_in));
6877 servaddr4.sin_family = AF_INET;
6878 servaddr4.sin_port = htons (port);
6879 if (0 != INADDR_ANY)
6880 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6881#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6882 servaddr4.sin_len = sizeof (struct sockaddr_in);
6883#endif
6884 servaddr = (struct sockaddr *) &servaddr4;
6885 }
6886 }
6887 daemon->listen_fd = listen_fd;
6888 if (0 != (*pflags & MHD_USE_IPv6))
6889 {
6890#ifdef IPPROTO_IPV6
6891#ifdef IPV6_V6ONLY
6892 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
6893 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
6894 and may also be missing on older POSIX systems; good luck if you have any of those,
6895 your IPv6 socket may then also bind against IPv4 anyway... */
6896 const MHD_SCKT_OPT_BOOL_ v6_only =
6897 (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
6898 if (0 > setsockopt (listen_fd,
6899 IPPROTO_IPV6, IPV6_V6ONLY,
6900 (const void *) &v6_only,
6901 sizeof (v6_only)))
6902 {
6903#ifdef HAVE_MESSAGES
6904 MHD_DLOG (daemon,
6905 _ ("setsockopt failed: %s\n"),
6907#endif
6908 }
6909#endif
6910#endif
6911 }
6912 if (-1 == bind (listen_fd, servaddr, addrlen))
6913 {
6914#ifdef HAVE_MESSAGES
6915 MHD_DLOG (daemon,
6916 _ ("Failed to bind to port %u: %s\n"),
6917 (unsigned int) port,
6919#endif
6920 MHD_socket_close_chk_ (listen_fd);
6921 goto free_and_fail;
6922 }
6923#ifdef TCP_FASTOPEN
6924 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6925 {
6926 if (0 == daemon->fastopen_queue_size)
6927 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6928 if (0 != setsockopt (listen_fd,
6929 IPPROTO_TCP,
6930 TCP_FASTOPEN,
6931 (const void *) &daemon->fastopen_queue_size,
6932 sizeof (daemon->fastopen_queue_size)))
6933 {
6934#ifdef HAVE_MESSAGES
6935 MHD_DLOG (daemon,
6936 _ ("setsockopt failed: %s\n"),
6938#endif
6939 }
6940 }
6941#endif
6942 if (listen (listen_fd,
6943 daemon->listen_backlog_size) < 0)
6944 {
6945#ifdef HAVE_MESSAGES
6946 MHD_DLOG (daemon,
6947 _ ("Failed to listen for connections: %s\n"),
6949#endif
6950 MHD_socket_close_chk_ (listen_fd);
6951 goto free_and_fail;
6952 }
6953 }
6954 else
6955 {
6956 listen_fd = daemon->listen_fd;
6957 }
6958
6959#ifdef HAVE_GETSOCKNAME
6960 if ( (0 == daemon->port) &&
6961 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6962 { /* Get port number. */
6963 struct sockaddr_storage bindaddr;
6964
6965 memset (&bindaddr,
6966 0,
6967 sizeof (struct sockaddr_storage));
6968 addrlen = sizeof (struct sockaddr_storage);
6969#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6970 bindaddr.ss_len = addrlen;
6971#endif
6972 if (0 != getsockname (listen_fd,
6973 (struct sockaddr *) &bindaddr,
6974 &addrlen))
6975 {
6976#ifdef HAVE_MESSAGES
6977 MHD_DLOG (daemon,
6978 _ ("Failed to get listen port number: %s\n"),
6980#endif /* HAVE_MESSAGES */
6981 }
6982#ifdef MHD_POSIX_SOCKETS
6983 else if (sizeof (bindaddr) < addrlen)
6984 {
6985 /* should be impossible with `struct sockaddr_storage` */
6986#ifdef HAVE_MESSAGES
6987 MHD_DLOG (daemon,
6988 _ (
6989 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6990#endif /* HAVE_MESSAGES */
6991 }
6992#ifndef __linux__
6993 else if (0 == addrlen)
6994 {
6995 /* Many non-Linux-based platforms return zero addrlen
6996 * for AF_UNIX sockets */
6997 daemon->port = 0; /* special value for UNIX domain sockets */
6998 }
6999#endif /* __linux__ */
7000#endif /* MHD_POSIX_SOCKETS */
7001 else
7002 {
7003 switch (bindaddr.ss_family)
7004 {
7005 case AF_INET:
7006 {
7007 struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
7008
7009 daemon->port = ntohs (s4->sin_port);
7010 break;
7011 }
7012#ifdef HAVE_INET6
7013 case AF_INET6:
7014 {
7015 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
7016
7017 daemon->port = ntohs (s6->sin6_port);
7018 mhd_assert (0 != (*pflags & MHD_USE_IPv6));
7019 break;
7020 }
7021#endif /* HAVE_INET6 */
7022#ifdef AF_UNIX
7023 case AF_UNIX:
7024 daemon->port = 0; /* special value for UNIX domain sockets */
7025 break;
7026#endif
7027 default:
7028#ifdef HAVE_MESSAGES
7029 MHD_DLOG (daemon,
7030 _ ("Unknown address family!\n"));
7031#endif
7032 daemon->port = 0; /* ugh */
7033 break;
7034 }
7035 }
7036 }
7037#endif /* HAVE_GETSOCKNAME */
7038
7039 if (MHD_INVALID_SOCKET != listen_fd)
7040 {
7041 if (! MHD_socket_nonblocking_ (listen_fd))
7042 {
7043#ifdef HAVE_MESSAGES
7044 MHD_DLOG (daemon,
7045 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
7047#endif
7048 if (0 != (*pflags & MHD_USE_EPOLL)
7049#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7050 || (daemon->worker_pool_size > 0)
7051#endif
7052 )
7053 {
7054 /* Accept must be non-blocking. Multiple children may wake up
7055 * to handle a new connection, but only one will win the race.
7056 * The others must immediately return. */
7057 MHD_socket_close_chk_ (listen_fd);
7058 goto free_and_fail;
7059 }
7060 daemon->listen_nonblk = false;
7061 }
7062 else
7063 daemon->listen_nonblk = true;
7064 if ( (! MHD_SCKT_FD_FITS_FDSET_ (listen_fd,
7065 NULL)) &&
7066 (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
7067 {
7068#ifdef HAVE_MESSAGES
7069 MHD_DLOG (daemon,
7070 _ ("Listen socket descriptor (%d) is not " \
7071 "less than FD_SETSIZE (%d).\n"),
7072 (int) listen_fd,
7073 (int) FD_SETSIZE);
7074#endif
7075 MHD_socket_close_chk_ (listen_fd);
7076 goto free_and_fail;
7077 }
7078 }
7079 else
7080 daemon->listen_nonblk = false; /* Actually listen socket does not exist */
7081
7082#ifdef EPOLL_SUPPORT
7083 if ( (0 != (*pflags & MHD_USE_EPOLL))
7084#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7085 && (0 == daemon->worker_pool_size)
7086#endif
7087 )
7088 {
7089 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
7090 {
7091#ifdef HAVE_MESSAGES
7092 MHD_DLOG (daemon,
7093 _ (
7094 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
7095#endif
7096 goto free_and_fail;
7097 }
7098 if (MHD_NO == setup_epoll_to_listen (daemon))
7099 goto free_and_fail;
7100 }
7101#endif /* EPOLL_SUPPORT */
7102
7103#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7105 {
7106#ifdef HAVE_MESSAGES
7107 MHD_DLOG (daemon,
7108 _ ("MHD failed to initialize IP connection limit mutex.\n"));
7109#endif
7110 if (MHD_INVALID_SOCKET != listen_fd)
7111 MHD_socket_close_chk_ (listen_fd);
7112 goto free_and_fail;
7113 }
7115 {
7116#ifdef HAVE_MESSAGES
7117 MHD_DLOG (daemon,
7118 _ ("MHD failed to initialize IP connection limit mutex.\n"));
7119#endif
7120#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7122#endif
7123 if (MHD_INVALID_SOCKET != listen_fd)
7124 MHD_socket_close_chk_ (listen_fd);
7125 goto free_and_fail;
7126 }
7127#endif
7128
7129#ifdef HTTPS_SUPPORT
7130 /* initialize HTTPS daemon certificate aspects & send / recv functions */
7131 if ( (0 != (*pflags & MHD_USE_TLS)) &&
7132 (0 != MHD_TLS_init (daemon)) )
7133 {
7134#ifdef HAVE_MESSAGES
7135 MHD_DLOG (daemon,
7136 _ ("Failed to initialize TLS support.\n"));
7137#endif
7138 if (MHD_INVALID_SOCKET != listen_fd)
7139 MHD_socket_close_chk_ (listen_fd);
7140#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7143#endif
7144 goto free_and_fail;
7145 }
7146#endif /* HTTPS_SUPPORT */
7147#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7148 /* Start threads if requested by parameters */
7149 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7150 {
7151 /* Internal thread (or threads) is used.
7152 * Make sure that MHD will be able to communicate with threads. */
7153 /* If using a thread pool ITC will be initialised later
7154 * for each individual worker thread. */
7155#ifdef HAVE_LISTEN_SHUTDOWN
7156 mhd_assert ((1 < daemon->worker_pool_size) || \
7157 (MHD_ITC_IS_VALID_ (daemon->itc)) || \
7158 (MHD_INVALID_SOCKET != daemon->listen_fd));
7159#else /* ! HAVE_LISTEN_SHUTDOWN */
7160 mhd_assert ((1 < daemon->worker_pool_size) || \
7161 (MHD_ITC_IS_VALID_ (daemon->itc)));
7162#endif /* ! HAVE_LISTEN_SHUTDOWN */
7163 if (0 == daemon->worker_pool_size)
7164 {
7165 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
7166 {
7167#ifdef HAVE_MESSAGES
7168 MHD_DLOG (daemon,
7169 _ ("Failed to initialise mutex.\n"));
7170#endif
7173 if (MHD_INVALID_SOCKET != listen_fd)
7174 MHD_socket_close_chk_ (listen_fd);
7175 goto free_and_fail;
7176 }
7177 if (! MHD_create_named_thread_ (&daemon->pid,
7178 (*pflags
7180 "MHD-listen" : "MHD-single",
7181 daemon->thread_stack_size,
7183 daemon) )
7184 {
7185#ifdef HAVE_MESSAGES
7186#ifdef EAGAIN
7187 if (EAGAIN == errno)
7188 MHD_DLOG (daemon,
7189 _ ("Failed to create a new thread because it would have " \
7190 "exceeded the system limit on the number of threads or " \
7191 "no system resources available.\n"));
7192 else
7193#endif /* EAGAIN */
7194 MHD_DLOG (daemon,
7195 _ ("Failed to create listen thread: %s\n"),
7196 MHD_strerror_ (errno));
7197#endif /* HAVE_MESSAGES */
7198 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7201 if (MHD_INVALID_SOCKET != listen_fd)
7202 MHD_socket_close_chk_ (listen_fd);
7203 goto free_and_fail;
7204 }
7205 }
7206 else /* 0 < daemon->worker_pool_size */
7207 {
7208 /* Coarse-grained count of connections per thread (note error
7209 * due to integer division). Also keep track of how many
7210 * connections are leftover after an equal split. */
7211 unsigned int conns_per_thread = daemon->connection_limit
7212 / daemon->worker_pool_size;
7213 unsigned int leftover_conns = daemon->connection_limit
7214 % daemon->worker_pool_size;
7215
7216 mhd_assert (2 <= daemon->worker_pool_size);
7217 i = 0; /* we need this in case fcntl or malloc fails */
7218
7219 /* Allocate memory for pooled objects */
7220 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
7221 * daemon->worker_pool_size);
7222 if (NULL == daemon->worker_pool)
7223 goto thread_failed;
7224
7225 /* Start the workers in the pool */
7226 for (i = 0; i < daemon->worker_pool_size; ++i)
7227 {
7228 /* Create copy of the Daemon object for each worker */
7229 struct MHD_Daemon *d = &daemon->worker_pool[i];
7230
7231 memcpy (d, daemon, sizeof (struct MHD_Daemon));
7232 /* Adjust polling params for worker daemons; note that memcpy()
7233 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
7234 the worker threads. */
7235 d->master = daemon;
7236 d->worker_pool_size = 0;
7237 d->worker_pool = NULL;
7238 if (! MHD_mutex_init_ (&d->new_connections_mutex))
7239 {
7240 #ifdef HAVE_MESSAGES
7241 MHD_DLOG (daemon,
7242 _ ("Failed to initialise mutex.\n"));
7243 #endif
7244 goto thread_failed;
7245 }
7246 if (0 != (*pflags & MHD_USE_ITC))
7247 {
7248 if (! MHD_itc_init_ (d->itc))
7249 {
7250#ifdef HAVE_MESSAGES
7251 MHD_DLOG (daemon,
7252 _ (
7253 "Failed to create worker inter-thread communication channel: %s\n"),
7254 MHD_itc_last_strerror_ () );
7255#endif
7256 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7257 goto thread_failed;
7258 }
7259 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
7260 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
7261 NULL)) )
7262 {
7263#ifdef HAVE_MESSAGES
7264 MHD_DLOG (daemon,
7265 _ (
7266 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
7267#endif
7268 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7270 goto thread_failed;
7271 }
7272 }
7273 else
7274 MHD_itc_set_invalid_ (d->itc);
7275
7276#ifdef HAVE_LISTEN_SHUTDOWN
7277 mhd_assert ((MHD_ITC_IS_VALID_ (d->itc)) || \
7279#else /* ! HAVE_LISTEN_SHUTDOWN */
7280 mhd_assert (MHD_ITC_IS_VALID_ (d->itc));
7281#endif /* ! HAVE_LISTEN_SHUTDOWN */
7282
7283 /* Divide available connections evenly amongst the threads.
7284 * Thread indexes in [0, leftover_conns) each get one of the
7285 * leftover connections. */
7286 d->connection_limit = conns_per_thread;
7287 if (i < leftover_conns)
7288 ++d->connection_limit;
7289#ifdef EPOLL_SUPPORT
7290 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
7291 (MHD_NO == setup_epoll_to_listen (d)) )
7292 {
7293 if (MHD_ITC_IS_VALID_ (d->itc))
7295 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7296 goto thread_failed;
7297 }
7298#endif
7299 /* Must init cleanup connection mutex for each worker */
7301 {
7302#ifdef HAVE_MESSAGES
7303 MHD_DLOG (daemon,
7304 _ ("MHD failed to initialize cleanup connection mutex.\n"));
7305#endif
7306 if (MHD_ITC_IS_VALID_ (d->itc))
7308 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7309 goto thread_failed;
7310 }
7311
7312 /* Spawn the worker thread */
7313 if (! MHD_create_named_thread_ (&d->pid,
7314 "MHD-worker",
7315 daemon->thread_stack_size,
7317 d))
7318 {
7319#ifdef HAVE_MESSAGES
7320#ifdef EAGAIN
7321 if (EAGAIN == errno)
7322 MHD_DLOG (daemon,
7323 _ ("Failed to create a new pool thread because it would " \
7324 "have exceeded the system limit on the number of " \
7325 "threads or no system resources available.\n"));
7326 else
7327#endif /* EAGAIN */
7328 MHD_DLOG (daemon,
7329 _ ("Failed to create pool thread: %s\n"),
7330 MHD_strerror_ (errno));
7331#endif
7332 /* Free memory for this worker; cleanup below handles
7333 * all previously-created workers. */
7335 if (MHD_ITC_IS_VALID_ (d->itc))
7337 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7338 goto thread_failed;
7339 }
7340 }
7341 }
7342 }
7343 else
7344 { /* Daemon without internal threads */
7345 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
7346 {
7347#ifdef HAVE_MESSAGES
7348 MHD_DLOG (daemon,
7349 _ ("Failed to initialise mutex.\n"));
7350#endif
7351 goto free_and_fail;
7352 }
7353 }
7354#endif
7355#ifdef HTTPS_SUPPORT
7356 /* API promises to never use the password after initialization,
7357 so we additionally NULL it here to not deref a dangling pointer. */
7358 daemon->https_key_password = NULL;
7359#endif /* HTTPS_SUPPORT */
7360
7361 return daemon;
7362
7363#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7364thread_failed:
7365 /* If no worker threads created, then shut down normally. Calling
7366 MHD_stop_daemon (as we do below) doesn't work here since it
7367 assumes a 0-sized thread pool means we had been in the default
7368 MHD_USE_INTERNAL_POLLING_THREAD mode. */
7369 if (0 == i)
7370 {
7374 if (NULL != daemon->worker_pool)
7375 free (daemon->worker_pool);
7376 goto free_and_fail;
7377 }
7378
7379 /* Shutdown worker threads we've already created. Pretend
7380 as though we had fully initialized our daemon, but
7381 with a smaller number of threads than had been
7382 requested. */
7383 daemon->worker_pool_size = i;
7384 MHD_stop_daemon (daemon);
7385 return NULL;
7386#endif
7387
7388free_and_fail:
7389 /* clean up basic memory state in 'daemon' and return NULL to
7390 indicate failure */
7391#ifdef EPOLL_SUPPORT
7392#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7393 if (daemon->upgrade_fd_in_epoll)
7394 {
7395 if (0 != epoll_ctl (daemon->epoll_fd,
7396 EPOLL_CTL_DEL,
7397 daemon->epoll_upgrade_fd,
7398 NULL))
7399 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
7400 daemon->upgrade_fd_in_epoll = false;
7401 }
7402#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7403 if (-1 != daemon->epoll_fd)
7404 close (daemon->epoll_fd);
7405#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7406 if (-1 != daemon->epoll_upgrade_fd)
7407 close (daemon->epoll_upgrade_fd);
7408#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7409#endif /* EPOLL_SUPPORT */
7410#ifdef DAUTH_SUPPORT
7411 free (daemon->nnc);
7412#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7413 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
7414#endif
7415#endif
7416#ifdef HTTPS_SUPPORT
7417 if (0 != (*pflags & MHD_USE_TLS))
7418 {
7419 gnutls_priority_deinit (daemon->priority_cache);
7420 if (daemon->x509_cred)
7421 gnutls_certificate_free_credentials (daemon->x509_cred);
7422 if (daemon->psk_cred)
7423 gnutls_psk_free_server_credentials (daemon->psk_cred);
7424 }
7425#endif /* HTTPS_SUPPORT */
7426 if (MHD_ITC_IS_VALID_ (daemon->itc))
7427 MHD_itc_destroy_chk_ (daemon->itc);
7428 free (daemon);
7429 return NULL;
7430}
7431
7432
7441static void
7443{
7444 struct MHD_Connection *pos;
7445 const bool used_thr_p_c = (0 != (daemon->options
7447#ifdef UPGRADE_SUPPORT
7448 const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
7449#endif /* UPGRADE_SUPPORT */
7450#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7451 struct MHD_UpgradeResponseHandle *urh;
7452 struct MHD_UpgradeResponseHandle *urhn;
7453 const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
7454#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7455
7456#ifdef MHD_USE_THREADS
7457 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
7458 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
7459 MHD_thread_ID_match_current_ (daemon->pid) );
7460 mhd_assert (NULL == daemon->worker_pool);
7461#endif /* MHD_USE_THREADS */
7462 mhd_assert (daemon->shutdown);
7463
7464#ifdef MHD_USE_THREADS
7465/* Remove externally added new connections that are
7466 * not processed by the daemon thread. */
7467 while (NULL != (pos = daemon->new_connections_tail))
7468 {
7471 daemon->new_connections_tail,
7472 pos);
7473 new_connection_close_ (daemon, pos);
7474 }
7475#endif /* MHD_USE_THREADS */
7476
7477#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7478 /* give upgraded HTTPS connections a chance to finish */
7479 /* 'daemon->urh_head' is not used in thread-per-connection mode. */
7480 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
7481 {
7482 mhd_assert (! used_thr_p_c);
7483 urhn = urh->prev;
7484 /* call generic forwarding function for passing data
7485 with chance to detect that application is done. */
7486 process_urh (urh);
7487 MHD_connection_finish_forward_ (urh->connection);
7488 urh->clean_ready = true;
7489 /* Resuming will move connection to cleanup list. */
7490 MHD_resume_connection (urh->connection);
7491 }
7492#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7493
7494 /* Give suspended connections a chance to resume to avoid
7495 running into the check for there not being any suspended
7496 connections left in case of a tight race with a recently
7497 resumed connection. */
7498 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
7499 {
7500 daemon->resuming = true; /* Force check for pending resume. */
7502 }
7503 /* first, make sure all threads are aware of shutdown; need to
7504 traverse DLLs in peace... */
7505#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7507#endif
7508#ifdef UPGRADE_SUPPORT
7509 if (upg_allowed)
7510 {
7511 struct MHD_Connection *susp;
7512
7514 while (NULL != susp)
7515 {
7516 if (NULL == susp->urh) /* "Upgraded" connection? */
7517 MHD_PANIC (_ (
7518 "MHD_stop_daemon() called while we have suspended connections.\n"));
7519#ifdef HTTPS_SUPPORT
7520 else if (used_tls &&
7521 used_thr_p_c &&
7522 (! susp->urh->clean_ready) )
7523 shutdown (susp->urh->app.socket,
7524 SHUT_RDWR); /* Wake thread by shutdown of app socket. */
7525#endif /* HTTPS_SUPPORT */
7526 else
7527 {
7528#ifdef HAVE_MESSAGES
7529 if (! susp->urh->was_closed)
7530 MHD_DLOG (daemon,
7531 _ (
7532 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
7533#endif
7534 susp->urh->was_closed = true;
7535 /* If thread-per-connection is used, connection's thread
7536 * may still processing "upgrade" (exiting). */
7537 if (! used_thr_p_c)
7539 /* Do not use MHD_resume_connection() as mutex is
7540 * already locked. */
7541 susp->resuming = true;
7542 daemon->resuming = true;
7543 }
7544 susp = susp->prev;
7545 }
7546 }
7547 else /* This 'else' is combined with next 'if' */
7548#endif /* UPGRADE_SUPPORT */
7550 MHD_PANIC (_ (
7551 "MHD_stop_daemon() called while we have suspended connections.\n"));
7552#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
7553#ifdef MHD_USE_THREADS
7554 if (upg_allowed && used_tls && used_thr_p_c)
7555 {
7556 /* "Upgraded" threads may be running in parallel. Connection will not be
7557 * moved to the "cleanup list" until connection's thread finishes.
7558 * We must ensure that all "upgraded" connections are finished otherwise
7559 * connection may stay in "suspended" list and will not be cleaned. */
7560 for (pos = daemon->suspended_connections_tail; NULL != pos; pos = pos->prev)
7561 {
7562 /* Any connection found here is "upgraded" connection, normal suspended
7563 * connections are already removed from this list. */
7564 mhd_assert (NULL != pos->urh);
7565 if (! pos->thread_joined)
7566 {
7567 /* While "cleanup" list is not manipulated by "upgraded"
7568 * connection, "cleanup" mutex is required for call of
7569 * MHD_resume_connection() during finishing of "upgraded"
7570 * thread. */
7572 if (! MHD_join_thread_ (pos->pid.handle))
7573 MHD_PANIC (_ ("Failed to join a thread.\n"));
7574 pos->thread_joined = true;
7576 }
7577 }
7578 }
7579#endif /* MHD_USE_THREADS */
7580#endif
7581 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
7582 {
7583 shutdown (pos->socket_fd,
7584 SHUT_RDWR);
7585#if MHD_WINSOCK_SOCKETS
7586 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
7587 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
7588 (! MHD_itc_activate_ (daemon->itc, "e")) )
7589 MHD_PANIC (_ (
7590 "Failed to signal shutdown via inter-thread communication channel.\n"));
7591#endif
7592 }
7593
7594#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7595 /* now, collect per-connection threads */
7596 if (used_thr_p_c)
7597 {
7598 pos = daemon->connections_tail;
7599 while (NULL != pos)
7600 {
7601 if (! pos->thread_joined)
7602 {
7604 if (! MHD_join_thread_ (pos->pid.handle))
7605 MHD_PANIC (_ ("Failed to join a thread.\n"));
7607 pos->thread_joined = true;
7608 /* The thread may have concurrently modified the DLL,
7609 need to restart from the beginning */
7610 pos = daemon->connections_tail;
7611 continue;
7612 }
7613 pos = pos->prev;
7614 }
7615 }
7617#endif
7618
7619#ifdef UPGRADE_SUPPORT
7620 /* Finished threads with "upgraded" connections need to be moved
7621 * to cleanup list by resume_suspended_connections(). */
7622 /* "Upgraded" connections that were not closed explicitly by
7623 * application should be moved to cleanup list too. */
7624 if (upg_allowed)
7625 {
7626 daemon->resuming = true; /* Force check for pending resume. */
7628 }
7629#endif /* UPGRADE_SUPPORT */
7630
7632 /* now that we're alone, move everyone to cleanup */
7633 while (NULL != (pos = daemon->connections_tail))
7634 {
7635#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7636 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
7637 (! pos->thread_joined) )
7638 MHD_PANIC (_ ("Failed to join a thread.\n"));
7639#endif
7640 close_connection (pos);
7641 }
7643}
7644
7645
7652void
7654{
7655 MHD_socket fd;
7656#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7657 unsigned int i;
7658#endif
7659
7660 if (NULL == daemon)
7661 return;
7662 if ( (daemon->shutdown) && (NULL == daemon->master) )
7663 MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
7664 /* Slave daemons must be stopped by master daemon. */
7665 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
7666
7667 daemon->shutdown = true;
7668 if (daemon->was_quiesced)
7669 fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
7670 else
7671 fd = daemon->listen_fd;
7672
7673#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7674 if (NULL != daemon->worker_pool)
7675 { /* Master daemon with worker pool. */
7678
7679 /* Let workers shutdown in parallel. */
7680 for (i = 0; i < daemon->worker_pool_size; ++i)
7681 {
7682 daemon->worker_pool[i].shutdown = true;
7683 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
7684 {
7685 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
7686 "e"))
7687 MHD_PANIC (_ (
7688 "Failed to signal shutdown via inter-thread communication channel.\n"));
7689 }
7690 else
7692 }
7693#ifdef HAVE_LISTEN_SHUTDOWN
7694 if (MHD_INVALID_SOCKET != fd)
7695 {
7696 (void) shutdown (fd,
7697 SHUT_RDWR);
7698 }
7699#endif /* HAVE_LISTEN_SHUTDOWN */
7700 for (i = 0; i < daemon->worker_pool_size; ++i)
7701 {
7703 }
7704 free (daemon->worker_pool);
7706#ifdef EPOLL_SUPPORT
7707 mhd_assert (-1 == daemon->epoll_fd);
7708#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7709 mhd_assert (-1 == daemon->epoll_upgrade_fd);
7710#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7711#endif /* EPOLL_SUPPORT */
7712 }
7713 else
7714#endif
7715 { /* Worker daemon or single daemon. */
7716#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7718 { /* Worker daemon or single daemon with internal thread(s). */
7720 /* Separate thread(s) is used for polling sockets. */
7721 if (MHD_ITC_IS_VALID_ (daemon->itc))
7722 {
7723 if (! MHD_itc_activate_ (daemon->itc,
7724 "e"))
7725 MHD_PANIC (_ (
7726 "Failed to signal shutdown via inter-thread communication channel.\n"));
7727 }
7728 else
7729 {
7730#ifdef HAVE_LISTEN_SHUTDOWN
7731 if (MHD_INVALID_SOCKET != fd)
7732 {
7733 if (NULL == daemon->master)
7734 (void) shutdown (fd,
7735 SHUT_RDWR);
7736 }
7737 else
7738#endif /* HAVE_LISTEN_SHUTDOWN */
7739 mhd_assert (false); /* Should never happen */
7740 }
7741
7742 if (! MHD_join_thread_ (daemon->pid.handle))
7743 {
7744 MHD_PANIC (_ ("Failed to join a thread.\n"));
7745 }
7746 /* close_all_connections() was called in daemon thread. */
7747 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7748 }
7749 else
7750#endif
7751 {
7752 /* No internal threads are used for polling sockets. */
7754#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7755 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7756#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
7757 }
7762#if defined(UPGRADE_SUPPORT) && defined (HTTPS_SUPPORT)
7763 mhd_assert (NULL == daemon->urh_head);
7764#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
7765
7766 if (MHD_ITC_IS_VALID_ (daemon->itc))
7768
7769#ifdef EPOLL_SUPPORT
7770 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
7771 (-1 != daemon->epoll_fd) )
7772 MHD_socket_close_chk_ (daemon->epoll_fd);
7773#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7774 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
7775 (-1 != daemon->epoll_upgrade_fd) )
7776 MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
7777#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7778#endif /* EPOLL_SUPPORT */
7779
7780#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7782#endif
7783 }
7784
7785 if (NULL == daemon->master)
7786 { /* Cleanup that should be done only one time in master/single daemon.
7787 * Do not perform this cleanup in worker daemons. */
7788
7789 if (MHD_INVALID_SOCKET != fd)
7791
7792 /* TLS clean up */
7793#ifdef HTTPS_SUPPORT
7794 if (daemon->have_dhparams)
7795 {
7796 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
7797 daemon->have_dhparams = false;
7798 }
7799 if (0 != (daemon->options & MHD_USE_TLS))
7800 {
7801 gnutls_priority_deinit (daemon->priority_cache);
7802 if (daemon->x509_cred)
7803 gnutls_certificate_free_credentials (daemon->x509_cred);
7804 if (daemon->psk_cred)
7805 gnutls_psk_free_server_credentials (daemon->psk_cred);
7806 }
7807#endif /* HTTPS_SUPPORT */
7808
7809#ifdef DAUTH_SUPPORT
7810 free (daemon->nnc);
7811#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7812 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
7813#endif
7814#endif
7815#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7817#endif
7818 free (daemon);
7819 }
7820}
7821
7822
7834const union MHD_DaemonInfo *
7836 enum MHD_DaemonInfoType info_type,
7837 ...)
7838{
7839 if (NULL == daemon)
7840 return NULL;
7841 switch (info_type)
7842 {
7844 return NULL; /* no longer supported */
7846 return NULL; /* no longer supported */
7848 return (const union MHD_DaemonInfo *) &daemon->listen_fd;
7849#ifdef EPOLL_SUPPORT
7851 return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
7852#endif
7854 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
7855 {
7856 /* Assume that MHD_run() in not called in other thread
7857 * at the same time. */
7858 MHD_cleanup_connections (daemon);
7859 }
7860#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7861 else if (daemon->worker_pool)
7862 {
7863 unsigned int i;
7864 /* Collect the connection information stored in the workers. */
7865 daemon->connections = 0;
7866 for (i = 0; i < daemon->worker_pool_size; i++)
7867 {
7868 /* FIXME: next line is thread-safe only if read is atomic. */
7869 daemon->connections += daemon->worker_pool[i].connections;
7870 }
7871 }
7872#endif
7873 return (const union MHD_DaemonInfo *) &daemon->connections;
7875 return (const union MHD_DaemonInfo *) &daemon->options;
7877 return (const union MHD_DaemonInfo *) &daemon->port;
7878 default:
7879 return NULL;
7880 }
7881}
7882
7883
7900void
7902 void *cls)
7903{
7904 mhd_panic = cb;
7905 mhd_panic_cls = cls;
7906}
7907
7908
7915const char *
7916MHD_get_version (void)
7917{
7918#ifdef PACKAGE_VERSION
7919 return PACKAGE_VERSION;
7920#else /* !PACKAGE_VERSION */
7921 static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
7922 if (0 == ver[0])
7923 {
7924 int res = MHD_snprintf_ (ver,
7925 sizeof(ver),
7926 "%x.%x.%x",
7927 (((int) MHD_VERSION >> 24) & 0xFF),
7928 (((int) MHD_VERSION >> 16) & 0xFF),
7929 (((int) MHD_VERSION >> 8) & 0xFF));
7930 if ((0 >= res) || (sizeof(ver) <= res))
7931 return "0.0.0"; /* Can't return real version*/
7932 }
7933 return ver;
7934#endif /* !PACKAGE_VERSION */
7935}
7936
7937
7949enum MHD_Result
7951{
7952 switch (feature)
7953 {
7955#ifdef HAVE_MESSAGES
7956 return MHD_YES;
7957#else
7958 return MHD_NO;
7959#endif
7960 case MHD_FEATURE_TLS:
7961#ifdef HTTPS_SUPPORT
7962 return MHD_YES;
7963#else /* ! HTTPS_SUPPORT */
7964 return MHD_NO;
7965#endif /* ! HTTPS_SUPPORT */
7967#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7968 return MHD_YES;
7969#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7970 return MHD_NO;
7971#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7973#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7974 return MHD_YES;
7975#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7976 return MHD_NO;
7977#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7978 case MHD_FEATURE_IPv6:
7979#ifdef HAVE_INET6
7980 return MHD_YES;
7981#else
7982 return MHD_NO;
7983#endif
7985#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
7986 return MHD_YES;
7987#else
7988 return MHD_NO;
7989#endif
7990 case MHD_FEATURE_POLL:
7991#ifdef HAVE_POLL
7992 return MHD_YES;
7993#else
7994 return MHD_NO;
7995#endif
7996 case MHD_FEATURE_EPOLL:
7997#ifdef EPOLL_SUPPORT
7998 return MHD_YES;
7999#else
8000 return MHD_NO;
8001#endif
8003#ifdef HAVE_LISTEN_SHUTDOWN
8004 return MHD_YES;
8005#else
8006 return MHD_NO;
8007#endif
8009#ifdef _MHD_ITC_SOCKETPAIR
8010 return MHD_YES;
8011#else
8012 return MHD_NO;
8013#endif
8015#ifdef TCP_FASTOPEN
8016 return MHD_YES;
8017#else
8018 return MHD_NO;
8019#endif
8021#ifdef BAUTH_SUPPORT
8022 return MHD_YES;
8023#else
8024 return MHD_NO;
8025#endif
8027#ifdef DAUTH_SUPPORT
8028 return MHD_YES;
8029#else
8030 return MHD_NO;
8031#endif
8033#ifdef HAVE_POSTPROCESSOR
8034 return MHD_YES;
8035#else
8036 return MHD_NO;
8037#endif
8039#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
8040 return MHD_YES;
8041#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
8042 return MHD_NO;
8043#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
8045#if defined(HAVE_PREAD64) || defined(_WIN32)
8046 return MHD_YES;
8047#elif defined(HAVE_PREAD)
8048 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
8049#elif defined(HAVE_LSEEK64)
8050 return MHD_YES;
8051#else
8052 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
8053#endif
8055#if defined(MHD_USE_THREAD_NAME_)
8056 return MHD_YES;
8057#else
8058 return MHD_NO;
8059#endif
8061#if defined(UPGRADE_SUPPORT)
8062 return MHD_YES;
8063#else
8064 return MHD_NO;
8065#endif
8067#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
8068 return MHD_YES;
8069#else
8070 return MHD_NO;
8071#endif
8073#ifdef MHD_USE_GETSOCKNAME
8074 return MHD_YES;
8075#else
8076 return MHD_NO;
8077#endif
8079#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) || \
8080 ! defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
8081 return MHD_YES;
8082#else
8083 return MHD_NO;
8084#endif
8086#ifdef _MHD_HAVE_SENDFILE
8087 return MHD_YES;
8088#else
8089 return MHD_NO;
8090#endif
8092#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8093 return MHD_YES;
8094#else
8095 return MHD_NO;
8096#endif
8097
8098 }
8099 return MHD_NO;
8100}
8101
8102
8103#ifdef MHD_HTTPS_REQUIRE_GRYPT
8104#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
8105#if defined(MHD_USE_POSIX_THREADS)
8106GCRY_THREAD_OPTION_PTHREAD_IMPL;
8107#elif defined(MHD_W32_MUTEX_)
8108
8109static int
8110gcry_w32_mutex_init (void **ppmtx)
8111{
8112 *ppmtx = malloc (sizeof (MHD_mutex_));
8113
8114 if (NULL == *ppmtx)
8115 return ENOMEM;
8116 if (! MHD_mutex_init_ ((MHD_mutex_ *) *ppmtx))
8117 {
8118 free (*ppmtx);
8119 *ppmtx = NULL;
8120 return EPERM;
8121 }
8122
8123 return 0;
8124}
8125
8126
8127static int
8128gcry_w32_mutex_destroy (void **ppmtx)
8129{
8130 int res = (MHD_mutex_destroy_ ((MHD_mutex_ *) *ppmtx)) ? 0 : EINVAL;
8131 free (*ppmtx);
8132 return res;
8133}
8134
8135
8136static int
8137gcry_w32_mutex_lock (void **ppmtx)
8138{
8139 return MHD_mutex_lock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
8140}
8141
8142
8143static int
8144gcry_w32_mutex_unlock (void **ppmtx)
8145{
8146 return MHD_mutex_unlock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
8147}
8148
8149
8150static struct gcry_thread_cbs gcry_threads_w32 = {
8151 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
8152 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
8153 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
8155};
8156
8157#endif /* defined(MHD_W32_MUTEX_) */
8158#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
8159#endif /* MHD_HTTPS_REQUIRE_GRYPT */
8160
8164void
8166{
8167#if defined(MHD_WINSOCK_SOCKETS)
8168 WSADATA wsd;
8169#endif /* MHD_WINSOCK_SOCKETS */
8170
8171 if (NULL == mhd_panic)
8173
8174#if defined(MHD_WINSOCK_SOCKETS)
8175 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
8176 MHD_PANIC (_ ("Failed to initialize winsock.\n"));
8177 mhd_winsock_inited_ = 1;
8178 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
8179 MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
8180#endif /* MHD_WINSOCK_SOCKETS */
8181#ifdef HTTPS_SUPPORT
8182#ifdef MHD_HTTPS_REQUIRE_GRYPT
8183#if GCRYPT_VERSION_NUMBER < 0x010600
8184#if defined(MHD_USE_POSIX_THREADS)
8185 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8186 &gcry_threads_pthread))
8187 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
8188#elif defined(MHD_W32_MUTEX_)
8189 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8190 &gcry_threads_w32))
8191 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
8192#endif /* defined(MHD_W32_MUTEX_) */
8193 gcry_check_version (NULL);
8194#else
8195 if (NULL == gcry_check_version ("1.6.0"))
8196 MHD_PANIC (_ (
8197 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
8198#endif
8199#endif /* MHD_HTTPS_REQUIRE_GRYPT */
8200 gnutls_global_init ();
8201#endif /* HTTPS_SUPPORT */
8205 /* Check whether sizes were correctly detected by configure */
8206#ifdef _DEBUG
8207 if (1)
8208 {
8209 struct timeval tv;
8210 mhd_assert (sizeof(tv.tv_sec) == SIZEOF_STRUCT_TIMEVAL_TV_SEC);
8211 }
8212#endif /* _DEBUG */
8213 mhd_assert (sizeof(uint64_t) == SIZEOF_UINT64_T);
8214}
8215
8216
8217void
8219{
8220#ifdef HTTPS_SUPPORT
8221 gnutls_global_deinit ();
8222#endif /* HTTPS_SUPPORT */
8223#if defined(MHD_WINSOCK_SOCKETS)
8224 if (mhd_winsock_inited_)
8225 WSACleanup ();
8226#endif /* MHD_WINSOCK_SOCKETS */
8228}
8229
8230
8231#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
8233#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
8234
8235/* end of daemon.c */
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:3852
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:4930
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:4411
void MHD_connection_handle_read(struct MHD_Connection *connection, bool socket_error)
Definition: connection.c:3694
Methods for managing connections.
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_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:261
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:3208
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:7442
MHD_PanicCallback mhd_panic
Definition: daemon.c:153
static int get_timeout_millisec_(struct MHD_Daemon *daemon, int32_t max_timeout)
Definition: daemon.c:3986
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:415
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:3245
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:3107
void MHD_fini(void)
Definition: daemon.c:8218
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:5629
static enum MHD_Result call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1202
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:325
volatile int global_init_count
Definition: daemon.c:184
static enum MHD_Result MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:4678
void MHD_check_global_init_(void)
Definition: daemon.c:201
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:5303
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
Definition: daemon.c:4183
static _MHD_NORETURN void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:129
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:345
static void new_connections_list_process_(struct MHD_Daemon *daemon)
Definition: daemon.c:3055
void MHD_init(void)
Definition: daemon.c:8165
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3768
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:5576
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3576
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:481
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:78
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:5419
static enum MHD_Result new_connection_process_(struct MHD_Daemon *daemon, struct MHD_Connection *connection)
Definition: daemon.c:2751
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:309
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:364
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:5604
static struct MHD_Connection * new_connection_prepare_(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
Definition: daemon.c:2441
void * mhd_panic_cls
Definition: daemon.c:158
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3282
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:86
static enum MHD_Result internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
Definition: daemon.c:2968
_MHD_EXTERN void MHD_free(void *ptr)
Definition: daemon.c:247
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, unsigned int fd_setsize)
Definition: daemon.c:985
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)
Definition: daemon.c:4015
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
Definition: daemon_start.c:619
_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:5451
_MHD_EXTERN enum MHD_Result MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
Definition: daemon.c:728
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:7653
_MHD_EXTERN enum MHD_Result MHD_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)
Definition: daemon.c:4127
_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:6384
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:5207
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3895
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
Definition: daemon.c:5257
_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:1136
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:2364
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: panic.c:56
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:2496
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Definition: microhttpd.h:2470
@ MHD_CONNECTION_NOTIFY_STARTED
Definition: microhttpd.h:2093
@ MHD_CONNECTION_NOTIFY_CLOSED
Definition: microhttpd.h:2099
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
Definition: microhttpd.h:2059
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
Definition: microhttpd.h:2035
@ MHD_REQUEST_TERMINATED_WITH_ERROR
Definition: microhttpd.h:2044
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1948
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:7835
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:5496
_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:3442
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:7950
_MHD_EXTERN const char * MHD_get_version(void)
Definition: version.c:35
#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 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)
Definition: mhd_sockets.c:377
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:442
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:407
MHD_socket MHD_socket_create_listen_(int pf)
Definition: mhd_sockets.c:474
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:675
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:611
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:203
#define MHD_socket_close_(fd)
Definition: mhd_sockets.h:238
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:643
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:656
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:414
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:542
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:549
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:464
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:248
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:634
#define MHD_socket_fset_error_(err)
Definition: mhd_sockets.h:555
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:261
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:623
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:336
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:309
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:216
#define NULL
Definition: reason_phrase.c:30
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
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:50
void MHD_send_init_static_vars_(void)
Definition: mhd_send.c:153
Declarations of send() wrappers.
MHD internal shared structures.
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:650
@ MHD_CONNECTION_INIT
Definition: internal.h:579
@ MHD_CONNECTION_CLOSED
Definition: internal.h:696
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:666
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:676
@ MHD_TLS_CONN_INIT
Definition: internal.h:715
@ MHD_EVENT_LOOP_INFO_READ
Definition: internal.h:246
@ MHD_EVENT_LOOP_INFO_WRITE
Definition: internal.h:251
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition: internal.h:261
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition: internal.h:256
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1574
#define PRIu64
Definition: internal.h:53
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition: internal.h:269
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1588
MHD_tristate
Definition: internal.h:183
@ _MHD_UNKNOWN
Definition: internal.h:184
@ _MHD_YES
Definition: internal.h:188
@ _MHD_OFF
Definition: internal.h:185
@ _MHD_NO
Definition: internal.h:186
void MHD_init_mem_pools_(void)
Definition: memorypool.c:136
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:113
#define MHD_mutex_destroy_(ignore)
Definition: mhd_locks.h:192
#define MHD_mutex_unlock_(ignore)
Definition: mhd_locks.h:196
#define MHD_mutex_lock_(ignore)
Definition: mhd_locks.h:194
#define MHD_mutex_init_(ignore)
Definition: mhd_locks.h:191
uint64_t MHD_monotonic_msec_counter(void)
internal monotonic clock functions implementations
#define SOCK_NONBLOCK_OR_ZERO
Definition: mhd_sockets.h:177
#define SOCK_NOSIGPIPE_OR_ZERO
Definition: mhd_sockets.h:183
#define SOCK_CLOEXEC_OR_ZERO
Definition: mhd_sockets.h:171
int MHD_socket
Definition: microhttpd.h:207
MHD_FEATURE
Definition: microhttpd.h:4435
@ MHD_FEATURE_POSTPROCESSOR
Definition: microhttpd.h:4526
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
Definition: microhttpd.h:4490
@ MHD_FEATURE_THREADS
Definition: microhttpd.h:4594
@ MHD_FEATURE_SENDFILE
Definition: microhttpd.h:4589
@ MHD_FEATURE_AUTODETECT_BIND_PORT
Definition: microhttpd.h:4575
@ MHD_FEATURE_LARGE_FILE
Definition: microhttpd.h:4543
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:4456
@ MHD_FEATURE_BASIC_AUTH
Definition: microhttpd.h:4510
@ MHD_FEATURE_DIGEST_AUTH
Definition: microhttpd.h:4518
@ MHD_FEATURE_IPv6
Definition: microhttpd.h:4462
@ MHD_FEATURE_POLL
Definition: microhttpd.h:4476
@ MHD_FEATURE_THREAD_NAMES
Definition: microhttpd.h:4548
@ MHD_FEATURE_EPOLL
Definition: microhttpd.h:4483
@ MHD_FEATURE_TLS
Definition: microhttpd.h:4449
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:4533
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
Definition: microhttpd.h:4582
@ MHD_FEATURE_RESPONSES_SHARED_FD
Definition: microhttpd.h:4569
@ MHD_FEATURE_MESSAGES
Definition: microhttpd.h:4440
@ MHD_FEATURE_IPv6_ONLY
Definition: microhttpd.h:4470
@ MHD_FEATURE_UPGRADE
Definition: microhttpd.h:4556
@ MHD_FEATURE_SOCKETPAIR
Definition: microhttpd.h:4496
@ MHD_FEATURE_TCP_FASTOPEN
Definition: microhttpd.h:4503
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:4600
MHD_OPTION
MHD options.
Definition: microhttpd.h:1555
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
Definition: microhttpd.h:1793
@ MHD_OPTION_HTTPS_CRED_TYPE
Definition: microhttpd.h:1674
@ MHD_OPTION_URI_LOG_CALLBACK
Definition: microhttpd.h:1651
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:1897
@ MHD_OPTION_SIGPIPE_HANDLED_BY_APP
Definition: microhttpd.h:1919
@ MHD_OPTION_UNESCAPE_CALLBACK
Definition: microhttpd.h:1756
@ MHD_OPTION_EXTERNAL_LOGGER
Definition: microhttpd.h:1703
@ MHD_OPTION_TLS_NO_ALPN
Definition: microhttpd.h:1928
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
Definition: microhttpd.h:1862
@ MHD_OPTION_HTTPS_PRIORITIES
Definition: microhttpd.h:1680
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
Definition: microhttpd.h:1825
@ MHD_OPTION_NOTIFY_CONNECTION
Definition: microhttpd.h:1854
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
Definition: microhttpd.h:1834
@ MHD_OPTION_THREAD_POOL_SIZE
Definition: microhttpd.h:1713
@ MHD_OPTION_CONNECTION_LIMIT
Definition: microhttpd.h:1576
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
Definition: microhttpd.h:1611
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
Definition: microhttpd.h:1818
@ MHD_OPTION_HTTPS_MEM_CERT
Definition: microhttpd.h:1667
@ MHD_OPTION_SERVER_INSANITY
Definition: microhttpd.h:1908
@ MHD_OPTION_LISTEN_SOCKET
Definition: microhttpd.h:1688
@ MHD_OPTION_HTTPS_MEM_KEY
Definition: microhttpd.h:1659
@ MHD_OPTION_DIGEST_AUTH_RANDOM
Definition: microhttpd.h:1767
@ MHD_OPTION_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:1843
@ MHD_OPTION_NONCE_NC_SIZE
Definition: microhttpd.h:1774
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
Definition: microhttpd.h:1570
@ MHD_OPTION_THREAD_STACK_SIZE
Definition: microhttpd.h:1780
@ MHD_OPTION_ARRAY
Definition: microhttpd.h:1734
@ MHD_OPTION_STRICT_FOR_CLIENT
Definition: microhttpd.h:1878
@ MHD_OPTION_SOCK_ADDR
Definition: microhttpd.h:1619
@ MHD_OPTION_CONNECTION_TIMEOUT
Definition: microhttpd.h:1585
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
Definition: microhttpd.h:1886
@ MHD_OPTION_END
Definition: microhttpd.h:1561
@ MHD_OPTION_HTTPS_MEM_TRUST
Definition: microhttpd.h:1787
@ MHD_OPTION_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:1809
@ MHD_OPTION_NOTIFY_COMPLETED
Definition: microhttpd.h:1599
MHD_DisableSanityCheck
Definition: microhttpd.h:1937
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)
Definition: microhttpd.h:2378
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:311
int fd
Definition: microhttpd.h:3642
void * data
Definition: microhttpd.h:3428
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:142
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:208
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 **con_cls)
Definition: microhttpd.h:2447
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
Definition: microhttpd.h:1543
#define MHD_VERSION
Definition: microhttpd.h:99
MHD_DaemonInfoType
Definition: microhttpd.h:2294
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
Definition: microhttpd.h:2303
@ MHD_DAEMON_INFO_BIND_PORT
Definition: microhttpd.h:2349
@ MHD_DAEMON_INFO_EPOLL_FD
Definition: microhttpd.h:2324
@ MHD_DAEMON_INFO_FLAGS
Definition: microhttpd.h:2341
@ MHD_DAEMON_INFO_KEY_SIZE
Definition: microhttpd.h:2298
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
Definition: microhttpd.h:2333
@ MHD_DAEMON_INFO_LISTEN_FD
Definition: microhttpd.h:2309
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:1224
@ MHD_USE_EPOLL
Definition: microhttpd.h:1369
@ MHD_ALLOW_SUSPEND_RESUME
Definition: microhttpd.h:1455
@ MHD_USE_TCP_FASTOPEN
Definition: microhttpd.h:1471
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1261
@ MHD_USE_AUTO
Definition: microhttpd.h:1491
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
Definition: microhttpd.h:1505
@ MHD_USE_TURBO
Definition: microhttpd.h:1440
@ MHD_USE_IPv6
Definition: microhttpd.h:1291
@ MHD_USE_DUAL_STACK
Definition: microhttpd.h:1432
@ MHD_USE_POLL
Definition: microhttpd.h:1319
@ MHD_USE_TLS
Definition: microhttpd.h:1246
@ MHD_USE_INSECURE_TLS_EARLY_DATA
Definition: microhttpd.h:1511
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1478
@ MHD_USE_NO_LISTEN_SOCKET
Definition: microhttpd.h:1360
@ MHD_USE_PEDANTIC_CHECKS
Definition: microhttpd.h:1302
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1273
@ MHD_USE_ITC
Definition: microhttpd.h:1418
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:1207
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:1268
enum MHD_tristate is_nonip
Definition: internal.h:1187
bool tls_read_ready
Definition: internal.h:769
void * socket_context
Definition: internal.h:694
bool suspended
Definition: internal.h:764
struct MHD_Response * response
Definition: internal.h:968
bool sk_nonblck
Definition: internal.h:784
struct MHD_Connection * next
Definition: internal.h:651
struct sockaddr_storage addr
Definition: internal.h:728
struct MemoryPool * pool
Definition: internal.h:685
size_t read_buffer_offset
Definition: internal.h:1086
struct MHD_Connection * prev
Definition: internal.h:656
bool client_aware
Definition: internal.h:1174
MHD_thread_handle_ID_ pid
Definition: internal.h:723
struct MHD_Connection * nextX
Definition: internal.h:665
time_t last_activity
Definition: internal.h:739
void * client_context
Definition: internal.h:986
enum MHD_CONNECTION_STATE state
Definition: internal.h:1263
struct MHD_Daemon * daemon
Definition: internal.h:675
bool sk_spipe_suppress
Definition: internal.h:1197
uint64_t connection_timeout_ms
Definition: internal.h:1162
size_t read_buffer_size
Definition: internal.h:1080
enum MHD_tristate sk_corked
Definition: internal.h:1202
bool thread_joined
Definition: internal.h:779
size_t pool_size
Definition: internal.h:1875
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1782
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1606
LogCallback uri_log_callback
Definition: internal.h:1796
bool data_already_pending
Definition: internal.h:1500
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1259
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:1629
uint16_t port
Definition: internal.h:1819
bool listen_nonblk
Definition: internal.h:1850
bool was_quiesced
Definition: internal.h:1505
unsigned int connection_limit
Definition: internal.h:1985
void * unescape_callback_cls
Definition: internal.h:1811
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
enum MHD_DisableSanityCheck insanity_level
Definition: internal.h:1919
struct MHD_Connection * connections_head
Definition: internal.h:1155
unsigned int listen_backlog_size
Definition: internal.h:2157
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1771
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:1930
uint64_t connection_timeout_ms
Definition: internal.h:1992
void * apc_cls
Definition: internal.h:1765
unsigned int per_ip_connection_limit
Definition: internal.h:1998
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1619
void * notify_connection_cls
Definition: internal.h:1787
bool sigpipe_blocked
Definition: internal.h:2008
UnescapeCallback unescape_callback
Definition: internal.h:1806
void * notify_completed_cls
Definition: internal.h:1776
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
size_t num_opts
Definition: internal.h:2166
bool resuming
Definition: internal.h:1510
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
struct MHD_Connection * new_connections_head
Definition: internal.h:1624
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
enum MHD_tristate listen_is_unix
Definition: internal.h:1664
void * default_handler_cls
Definition: internal.h:1611
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
MHD_AcceptPolicyCallback apc
Definition: internal.h:1760
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:1969
size_t pool_increment
Definition: internal.h:1880
MHD_socket listen_fd
Definition: internal.h:1845
void * uri_log_callback_cls
Definition: internal.h:1801
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
struct MHD_Connection * connections_tail
Definition: internal.h:1160
int strict_for_client
Definition: internal.h:2003
intptr_t value
Definition: microhttpd.h:1962
enum MHD_OPTION option
Definition: microhttpd.h:1955
void * ptr_value
Definition: microhttpd.h:1968