GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
daemon.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4 Copyright (C) 2015-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#ifdef MHD_USE_SYS_TSEARCH
49#include <search.h>
50#else /* ! MHD_USE_SYS_TSEARCH */
51#include "tsearch.h"
52#endif /* ! MHD_USE_SYS_TSEARCH */
53
54#ifdef HTTPS_SUPPORT
55#include "connection_https.h"
56#ifdef MHD_HTTPS_REQUIRE_GCRYPT
57#include <gcrypt.h>
58#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
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
260struct 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 ret = MHD_YES;
1212
1213#ifdef HTTPS_SUPPORT
1214 if (con->tls_read_ready)
1215 read_ready = true;
1216#endif /* HTTPS_SUPPORT */
1218 (read_ready || (force_close && con->sk_nonblck)) )
1219 {
1220 MHD_connection_handle_read (con, force_close);
1221 mhd_assert (! force_close || MHD_CONNECTION_CLOSED == con->state);
1222 ret = MHD_connection_handle_idle (con);
1223 if (force_close)
1224 return ret;
1225 states_info_processed = true;
1226 }
1227 if (! force_close)
1228 {
1229 /* No need to check value of 'ret' here as closed connection
1230 * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1232 write_ready)
1233 {
1235 ret = MHD_connection_handle_idle (con);
1236 states_info_processed = true;
1237 }
1238 }
1239 else
1240 {
1243 return MHD_connection_handle_idle (con);
1244 }
1245
1246 if (! states_info_processed)
1247 { /* Connection is not read or write ready, but external conditions
1248 * may be changed and need to be processed. */
1249 ret = MHD_connection_handle_idle (con);
1250 }
1251 /* Fast track for fast connections. */
1252 /* If full request was read by single read_handler() invocation
1253 and headers were completely prepared by single MHD_connection_handle_idle()
1254 then try not to wait for next sockets polling and send response
1255 immediately.
1256 As writeability of socket was not checked and it may have
1257 some data pending in system buffers, use this optimization
1258 only for non-blocking sockets. */
1259 /* No need to check 'ret' as connection is always in
1260 * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1261 else if (on_fasttrack && con->sk_nonblck)
1262 {
1264 {
1266 /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1267 ret = MHD_connection_handle_idle (con);
1268 }
1269 /* If all headers were sent by single write_handler() and
1270 * response body is prepared by single MHD_connection_handle_idle()
1271 * call - continue. */
1274 {
1276 ret = MHD_connection_handle_idle (con);
1277 }
1278 }
1279
1280 /* All connection's data and states are processed for this turn.
1281 * If connection already has more data to be processed - use
1282 * zero timeout for next select()/poll(). */
1283 /* Thread-per-connection do not need global zero timeout as
1284 * connections are processed individually. */
1285 /* Note: no need to check for read buffer availability for
1286 * TLS read-ready connection in 'read info' state as connection
1287 * without space in read buffer will be marked as 'info block'. */
1288 if ( (! con->daemon->data_already_pending) &&
1290 {
1292 con->daemon->data_already_pending = true;
1293#ifdef HTTPS_SUPPORT
1294 else if ( (con->tls_read_ready) &&
1296 con->daemon->data_already_pending = true;
1297#endif /* HTTPS_SUPPORT */
1298 }
1299 return ret;
1300}
1301
1302
1303#ifdef UPGRADE_SUPPORT
1311static void
1312cleanup_upgraded_connection (struct MHD_Connection *connection)
1313{
1314 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1315
1316 if (NULL == urh)
1317 return;
1318#ifdef HTTPS_SUPPORT
1319 /* Signal remote client the end of TLS connection by
1320 * gracefully closing TLS session. */
1321 if (0 != (connection->daemon->options & MHD_USE_TLS))
1322 gnutls_bye (connection->tls_session,
1323 GNUTLS_SHUT_WR);
1324
1325 if (MHD_INVALID_SOCKET != urh->mhd.socket)
1326 MHD_socket_close_chk_ (urh->mhd.socket);
1327
1328 if (MHD_INVALID_SOCKET != urh->app.socket)
1329 MHD_socket_close_chk_ (urh->app.socket);
1330#endif /* HTTPS_SUPPORT */
1331 connection->urh = NULL;
1332 free (urh);
1333}
1334
1335
1336#endif /* UPGRADE_SUPPORT */
1337
1338
1339#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1348static void
1349process_urh (struct MHD_UpgradeResponseHandle *urh)
1350{
1351 /* Help compiler to optimize:
1352 * pointers to 'connection' and 'daemon' are not changed
1353 * during this processing, so no need to chain dereference
1354 * each time. */
1355 struct MHD_Connection *const connection = urh->connection;
1356 struct MHD_Daemon *const daemon = connection->daemon;
1357 /* Prevent data races: use same value of 'was_closed' throughout
1358 * this function. If 'was_closed' changed externally in the middle
1359 * of processing - it will be processed on next iteration. */
1360 bool was_closed;
1361
1362#ifdef MHD_USE_THREADS
1363 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1364 MHD_thread_ID_match_current_ (connection->pid) );
1365#endif /* MHD_USE_THREADS */
1366 if (daemon->shutdown)
1367 {
1368 /* Daemon shutting down, application will not receive any more data. */
1369#ifdef HAVE_MESSAGES
1370 if (! urh->was_closed)
1371 {
1372 MHD_DLOG (daemon,
1373 _ (
1374 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1375 }
1376#endif
1377 urh->was_closed = true;
1378 }
1379 was_closed = urh->was_closed;
1380 if (was_closed)
1381 {
1382 /* Application was closed connections: no more data
1383 * can be forwarded to application socket. */
1384 if (0 < urh->in_buffer_used)
1385 {
1386#ifdef HAVE_MESSAGES
1387 MHD_DLOG (daemon,
1388 _ ("Failed to forward to application "
1389 "%" PRIu64 \
1390 " bytes of data received from remote side: application shut down socket.\n"),
1391 (uint64_t) urh->in_buffer_used);
1392#endif
1393
1394 }
1395 /* If application signaled MHD about socket closure then
1396 * check for any pending data even if socket is not marked
1397 * as 'ready' (signal may arrive after poll()/select()).
1398 * Socketpair for forwarding is always in non-blocking mode
1399 * so no risk that recv() will block the thread. */
1400 if (0 != urh->out_buffer_size)
1401 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1402 /* Discard any data received form remote. */
1403 urh->in_buffer_used = 0;
1404 /* Do not try to push data to application. */
1405 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1406 /* Reading from remote client is not required anymore. */
1407 urh->in_buffer_size = 0;
1408 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1409 connection->tls_read_ready = false;
1410 }
1411
1412 /* On some platforms (W32, possibly Darwin) failed send() (send() will
1413 * always fail after remote disconnect was detected) may discard data in
1414 * system buffers received by system but not yet read by recv(). So, before
1415 * trying send() on any socket, recv() must be performed at first otherwise
1416 * last part of incoming data may be lost. If disconnect or error was
1417 * detected - try to read from socket to dry data possibly pending is system
1418 * buffers. */
1419 if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1420 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1421 if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1422 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1423
1424 /*
1425 * handle reading from remote TLS client
1426 */
1427 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1428 (connection->tls_read_ready) ) &&
1429 (urh->in_buffer_used < urh->in_buffer_size) )
1430 {
1431 ssize_t res;
1432 size_t buf_size;
1433
1434 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1435 if (buf_size > SSIZE_MAX)
1436 buf_size = SSIZE_MAX;
1437
1438 connection->tls_read_ready = false;
1439 res = gnutls_record_recv (connection->tls_session,
1440 &urh->in_buffer[urh->in_buffer_used],
1441 buf_size);
1442 if (0 >= res)
1443 {
1444 if (GNUTLS_E_INTERRUPTED != res)
1445 {
1446 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1447 if (GNUTLS_E_AGAIN != res)
1448 {
1449 /* Unrecoverable error on socket was detected or
1450 * socket was disconnected/shut down. */
1451 /* Stop trying to read from this TLS socket. */
1452 urh->in_buffer_size = 0;
1453 }
1454 }
1455 }
1456 else /* 0 < res */
1457 {
1458 urh->in_buffer_used += res;
1459 if (0 < gnutls_record_check_pending (connection->tls_session))
1460 {
1461 connection->tls_read_ready = true;
1462 }
1463 }
1466 {
1467 /* Unrecoverable error on socket was detected and all
1468 * pending data was read from system buffers. */
1469 /* Stop trying to read from this TLS socket. */
1470 urh->in_buffer_size = 0;
1471 }
1472 }
1473
1474 /*
1475 * handle reading from application
1476 */
1477 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1478 (urh->out_buffer_used < urh->out_buffer_size) )
1479 {
1480 ssize_t res;
1481 size_t buf_size;
1482
1483 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1484 if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1485 buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1486
1487 res = MHD_recv_ (urh->mhd.socket,
1488 &urh->out_buffer[urh->out_buffer_used],
1489 buf_size);
1490 if (0 >= res)
1491 {
1492 const int err = MHD_socket_get_error_ ();
1493 if ((0 == res) ||
1494 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1496 {
1497 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1498 if ((0 == res) ||
1499 (was_closed) ||
1500 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1501 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1502 {
1503 /* Socket disconnect/shutdown was detected;
1504 * Application signaled about closure of 'upgraded' socket;
1505 * or persistent / unrecoverable error. */
1506 /* Do not try to pull more data from application. */
1507 urh->out_buffer_size = 0;
1508 }
1509 }
1510 }
1511 else /* 0 < res */
1512 {
1513 urh->out_buffer_used += res;
1514 if (buf_size > (size_t) res)
1515 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1516 }
1517 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1518 ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1519 (was_closed) ) )
1520 {
1521 /* Unrecoverable error on socket was detected and all
1522 * pending data was read from system buffers. */
1523 /* Do not try to pull more data from application. */
1524 urh->out_buffer_size = 0;
1525 }
1526 }
1527
1528 /*
1529 * handle writing to remote HTTPS client
1530 */
1531 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1532 (urh->out_buffer_used > 0) )
1533 {
1534 ssize_t res;
1535 size_t data_size;
1536
1537 data_size = urh->out_buffer_used;
1538 if (data_size > SSIZE_MAX)
1539 data_size = SSIZE_MAX;
1540
1541 res = gnutls_record_send (connection->tls_session,
1542 urh->out_buffer,
1543 data_size);
1544 if (0 >= res)
1545 {
1546 if (GNUTLS_E_INTERRUPTED != res)
1547 {
1548 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1549 if (GNUTLS_E_AGAIN != res)
1550 {
1551 /* TLS connection shut down or
1552 * persistent / unrecoverable error. */
1553#ifdef HAVE_MESSAGES
1554 MHD_DLOG (daemon,
1555 _ (
1556 "Failed to forward to remote client "
1557 "%" PRIu64 \
1558 " bytes of data received from application: %s\n"),
1559 (uint64_t) urh->out_buffer_used,
1560 gnutls_strerror (res));
1561#endif
1562 /* Discard any data unsent to remote. */
1563 urh->out_buffer_used = 0;
1564 /* Do not try to pull more data from application. */
1565 urh->out_buffer_size = 0;
1566 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1567 }
1568 }
1569 }
1570 else /* 0 < res */
1571 {
1572 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1573 if (0 != next_out_buffer_used)
1574 {
1575 memmove (urh->out_buffer,
1576 &urh->out_buffer[res],
1577 next_out_buffer_used);
1578 if (data_size > (size_t) res)
1579 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1580 }
1581 urh->out_buffer_used = next_out_buffer_used;
1582 }
1583 if ( (0 == urh->out_buffer_used) &&
1584 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1585 {
1586 /* Unrecoverable error on socket was detected and all
1587 * pending data was sent to remote. */
1588 /* Do not try to send to remote anymore. */
1589 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1590 /* Do not try to pull more data from application. */
1591 urh->out_buffer_size = 0;
1592 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1593 }
1594 }
1595
1596 /*
1597 * handle writing to application
1598 */
1599 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1600 (urh->in_buffer_used > 0) )
1601 {
1602 ssize_t res;
1603 size_t data_size;
1604
1605 data_size = urh->in_buffer_used;
1606 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1607 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1608
1609 res = MHD_send_ (urh->mhd.socket,
1610 urh->in_buffer,
1611 data_size);
1612 if (0 >= res)
1613 {
1614 const int err = MHD_socket_get_error_ ();
1615 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1617 {
1618 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1619 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1620 {
1621 /* Socketpair connection shut down or
1622 * persistent / unrecoverable error. */
1623#ifdef HAVE_MESSAGES
1624 MHD_DLOG (daemon,
1625 _ (
1626 "Failed to forward to application "
1627 "%" PRIu64 \
1628 " bytes of data received from remote side: %s\n"),
1629 (uint64_t) urh->in_buffer_used,
1630 MHD_socket_strerr_ (err));
1631#endif
1632 /* Discard any data received form remote. */
1633 urh->in_buffer_used = 0;
1634 /* Reading from remote client is not required anymore. */
1635 urh->in_buffer_size = 0;
1636 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1637 connection->tls_read_ready = false;
1638 }
1639 }
1640 }
1641 else /* 0 < res */
1642 {
1643 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1644 if (0 != next_in_buffer_used)
1645 {
1646 memmove (urh->in_buffer,
1647 &urh->in_buffer[res],
1648 next_in_buffer_used);
1649 if (data_size > (size_t) res)
1650 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1651 }
1652 urh->in_buffer_used = next_in_buffer_used;
1653 }
1654 if ( (0 == urh->in_buffer_used) &&
1655 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1656 {
1657 /* Do not try to push data to application. */
1658 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1659 /* Reading from remote client is not required anymore. */
1660 urh->in_buffer_size = 0;
1661 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1662 connection->tls_read_ready = false;
1663 }
1664 }
1665
1666 /* Check whether data is present in TLS buffers
1667 * and incoming forward buffer have some space. */
1668 if ( (connection->tls_read_ready) &&
1669 (urh->in_buffer_used < urh->in_buffer_size) &&
1670 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1671 daemon->data_already_pending = true;
1672
1673 if ( (daemon->shutdown) &&
1674 ( (0 != urh->out_buffer_size) ||
1675 (0 != urh->out_buffer_used) ) )
1676 {
1677 /* Daemon shutting down, discard any remaining forward data. */
1678#ifdef HAVE_MESSAGES
1679 if (0 < urh->out_buffer_used)
1680 MHD_DLOG (daemon,
1681 _ (
1682 "Failed to forward to remote client "
1683 "%" PRIu64 \
1684 " bytes of data received from application: daemon shut down.\n"),
1685 (uint64_t) urh->out_buffer_used);
1686#endif
1687 /* Discard any data unsent to remote. */
1688 urh->out_buffer_used = 0;
1689 /* Do not try to sent to remote anymore. */
1690 urh->app.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_WRITE_READY);
1691 /* Do not try to pull more data from application. */
1692 urh->out_buffer_size = 0;
1693 urh->mhd.celi &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_READ_READY);
1694 }
1695}
1696
1697
1698#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1699
1700#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1701#ifdef UPGRADE_SUPPORT
1710static void
1711thread_main_connection_upgrade (struct MHD_Connection *con)
1712{
1713#ifdef HTTPS_SUPPORT
1714 struct MHD_UpgradeResponseHandle *urh = con->urh;
1715 struct MHD_Daemon *daemon = con->daemon;
1716
1717 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1718 MHD_thread_ID_match_current_ (con->pid) );
1719 /* Here, we need to bi-directionally forward
1720 until the application tells us that it is done
1721 with the socket; */
1722 if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1723 (0 == (daemon->options & MHD_USE_POLL)))
1724 {
1725 while ( (0 != urh->in_buffer_size) ||
1726 (0 != urh->out_buffer_size) ||
1727 (0 != urh->in_buffer_used) ||
1728 (0 != urh->out_buffer_used) )
1729 {
1730 /* use select */
1731 fd_set rs;
1732 fd_set ws;
1733 fd_set es;
1734 MHD_socket max_fd;
1735 int num_ready;
1736 bool result;
1737
1738 FD_ZERO (&rs);
1739 FD_ZERO (&ws);
1740 FD_ZERO (&es);
1741 max_fd = MHD_INVALID_SOCKET;
1742 result = urh_to_fdset (urh,
1743 &rs,
1744 &ws,
1745 &es,
1746 &max_fd,
1747 FD_SETSIZE);
1748 if (! result)
1749 {
1750#ifdef HAVE_MESSAGES
1751 MHD_DLOG (con->daemon,
1752 _ ("Error preparing select.\n"));
1753#endif
1754 break;
1755 }
1756 /* FIXME: does this check really needed? */
1757 if (MHD_INVALID_SOCKET != max_fd)
1758 {
1759 struct timeval *tvp;
1760 struct timeval tv;
1761 if (((con->tls_read_ready) &&
1762 (urh->in_buffer_used < urh->in_buffer_size)) ||
1763 (daemon->shutdown))
1764 { /* No need to wait if incoming data is already pending in TLS buffers. */
1765 tv.tv_sec = 0;
1766 tv.tv_usec = 0;
1767 tvp = &tv;
1768 }
1769 else
1770 tvp = NULL;
1771 num_ready = MHD_SYS_select_ (max_fd + 1,
1772 &rs,
1773 &ws,
1774 &es,
1775 tvp);
1776 }
1777 else
1778 num_ready = 0;
1779 if (num_ready < 0)
1780 {
1781 const int err = MHD_socket_get_error_ ();
1782
1783 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1784 continue;
1785#ifdef HAVE_MESSAGES
1786 MHD_DLOG (con->daemon,
1787 _ ("Error during select (%d): `%s'\n"),
1788 err,
1789 MHD_socket_strerr_ (err));
1790#endif
1791 break;
1792 }
1793 urh_from_fdset (urh,
1794 &rs,
1795 &ws,
1796 &es);
1797 process_urh (urh);
1798 }
1799 }
1800#ifdef HAVE_POLL
1801 else if (0 != (daemon->options & MHD_USE_TLS))
1802 {
1803 /* use poll() */
1804 struct pollfd p[2];
1805 memset (p,
1806 0,
1807 sizeof (p));
1808 p[0].fd = urh->connection->socket_fd;
1809 p[1].fd = urh->mhd.socket;
1810
1811 while ( (0 != urh->in_buffer_size) ||
1812 (0 != urh->out_buffer_size) ||
1813 (0 != urh->in_buffer_used) ||
1814 (0 != urh->out_buffer_used) )
1815 {
1816 int timeout;
1817
1818 urh_update_pollfd (urh, p);
1819
1820 if (((con->tls_read_ready) &&
1821 (urh->in_buffer_used < urh->in_buffer_size)) ||
1822 (daemon->shutdown))
1823 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1824 else
1825 timeout = -1;
1826
1827 if (MHD_sys_poll_ (p,
1828 2,
1829 timeout) < 0)
1830 {
1831 const int err = MHD_socket_get_error_ ();
1832
1833 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1834 continue;
1835#ifdef HAVE_MESSAGES
1836 MHD_DLOG (con->daemon,
1837 _ ("Error during poll: `%s'\n"),
1838 MHD_socket_strerr_ (err));
1839#endif
1840 break;
1841 }
1842 urh_from_pollfd (urh,
1843 p);
1844 process_urh (urh);
1845 }
1846 }
1847 /* end POLL */
1848#endif
1849 /* end HTTPS */
1850#endif /* HTTPS_SUPPORT */
1851 /* TLS forwarding was finished. Cleanup socketpair. */
1853 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1854 * in connection thread for a little while. */
1855}
1856
1857
1858#endif /* UPGRADE_SUPPORT */
1859
1860
1868static uint64_t
1869connection_get_wait (struct MHD_Connection *c)
1870{
1871 const uint64_t now = MHD_monotonic_msec_counter ();
1872 const uint64_t since_actv = now - c->last_activity;
1873 const uint64_t timeout = c->connection_timeout_ms;
1874 uint64_t mseconds_left;
1875
1876 mhd_assert (0 != timeout);
1877 /* Keep the next lines in sync with #connection_check_timedout() to avoid
1878 * undesired side-effects like busy-waiting. */
1879 if (timeout < since_actv)
1880 {
1881 if (UINT64_MAX / 2 < since_actv)
1882 {
1883 const uint64_t jump_back = c->last_activity - now;
1884 /* Very unlikely that it is more than quarter-million years pause.
1885 * More likely that system clock jumps back. */
1886 if (5000 >= jump_back)
1887 { /* Jump back is less than 5 seconds, try to recover. */
1888 return 100; /* Set wait time to 0.1 seconds */
1889 }
1890 /* Too large jump back */
1891 }
1892 return 0; /* Connection has timed out */
1893 }
1894 else if (since_actv == timeout)
1895 {
1896 /* Exact match for timeout and time from last activity.
1897 * Maybe this is just a precise match or this happens because the timer
1898 * resolution is too low.
1899 * Set wait time to 0.1 seconds to avoid busy-waiting with low
1900 * timer resolution as connection is not timed-out yet. */
1901 return 100;
1902 }
1903 mseconds_left = timeout - since_actv;
1904
1905 return mseconds_left;
1906}
1907
1908
1916static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1918{
1919 struct MHD_Connection *con = data;
1920 struct MHD_Daemon *daemon = con->daemon;
1921 int num_ready;
1922 fd_set rs;
1923 fd_set ws;
1924 fd_set es;
1925 MHD_socket maxsock;
1926 struct timeval tv;
1927 struct timeval *tvp;
1928#if WINDOWS
1929#ifdef HAVE_POLL
1930 int extra_slot;
1931#endif /* HAVE_POLL */
1932#define EXTRA_SLOTS 1
1933#else /* !WINDOWS */
1934#define EXTRA_SLOTS 0
1935#endif /* !WINDOWS */
1936#ifdef HAVE_POLL
1937 struct pollfd p[1 + EXTRA_SLOTS];
1938#endif
1939#undef EXTRA_SLOTS
1940#ifdef HAVE_POLL
1941 const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1942#else /* ! HAVE_POLL */
1943 const bool use_poll = 0;
1944#endif /* ! HAVE_POLL */
1945 bool was_suspended = false;
1946 MHD_thread_init_ (&(con->pid));
1947
1948 while ( (! daemon->shutdown) &&
1949 (MHD_CONNECTION_CLOSED != con->state) )
1950 {
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 (con->connection_timeout_ms > 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#if 0
2695 /* Unreachable code */
2696 eno = EINVAL;
2697 return NULL;
2698#endif
2699#endif /* ! HTTPS_SUPPORT */
2700 }
2701
2702 return connection;
2703}
2704
2705
2706#ifdef MHD_USE_THREADS
2712static void
2713new_connection_close_ (struct MHD_Daemon *daemon,
2714 struct MHD_Connection *connection)
2715{
2716 mhd_assert (connection->daemon == daemon);
2717 mhd_assert (! connection->in_cleanup);
2718 mhd_assert (NULL == connection->next);
2719 mhd_assert (NULL == connection->nextX);
2720#ifdef EPOLL_SUPPORT
2721 mhd_assert (NULL == connection->nextE);
2722#endif /* EPOLL_SUPPORT */
2723
2724#ifdef HTTPS_SUPPORT
2725 if (NULL != connection->tls_session)
2726 {
2728 gnutls_deinit (connection->tls_session);
2729 }
2730#endif /* HTTPS_SUPPORT */
2731 MHD_socket_close_chk_ (connection->socket_fd);
2733 connection->addr,
2734 connection->addr_len);
2735 free (connection->addr);
2736 free (connection);
2737}
2738
2739
2740#endif /* MHD_USE_THREADS */
2741
2742
2753static enum MHD_Result
2755 struct MHD_Connection *connection)
2756{
2757 int eno = 0;
2758
2759 mhd_assert (connection->daemon == daemon);
2760
2761#ifdef MHD_USE_THREADS
2762 /* Function manipulate connection and timeout DL-lists,
2763 * must be called only within daemon thread. */
2765 MHD_thread_ID_match_current_ (daemon->pid) );
2766#endif /* MHD_USE_THREADS */
2767
2768 /* Allocate memory pool in the processing thread so
2769 * intensively used memory area is allocated in "good"
2770 * (for the thread) memory region. It is important with
2771 * NUMA and/or complex cache hierarchy. */
2772 connection->pool = MHD_pool_create (daemon->pool_size);
2773 if (NULL == connection->pool)
2774 { /* 'pool' creation failed */
2775#ifdef HAVE_MESSAGES
2776 MHD_DLOG (daemon,
2777 _ ("Error allocating memory: %s\n"),
2778 MHD_strerror_ (errno));
2779#endif
2780#if ENOMEM
2781 eno = ENOMEM;
2782#endif
2783 (void) 0; /* Mute possible compiler warning */
2784 }
2785 else
2786 { /* 'pool' creation succeed */
2788 /* Firm check under lock. */
2790 { /* Connections limit */
2791#ifdef HAVE_MESSAGES
2792 MHD_DLOG (daemon,
2793 _ ("Server reached connection limit. "
2794 "Closing inbound connection.\n"));
2795#endif
2796#if ENFILE
2797 eno = ENFILE;
2798#endif
2799 (void) 0; /* Mute possible compiler warning */
2800 }
2801 else
2802 { /* Have space for new connection */
2806 connection);
2808 {
2811 connection);
2812 }
2816 connection,
2817 &connection->socket_context,
2819#ifdef MHD_USE_THREADS
2821 {
2823 if (! MHD_create_named_thread_ (&connection->pid,
2824 "MHD-connection",
2825 daemon->thread_stack_size,
2827 connection))
2828 {
2829 eno = errno;
2830#ifdef HAVE_MESSAGES
2831#ifdef EAGAIN
2832 if (EAGAIN == eno)
2833 MHD_DLOG (daemon,
2834 _ ("Failed to create a new thread because it would "
2835 "have exceeded the system limit on the number of "
2836 "threads or no system resources available.\n"));
2837 else
2838#endif /* EAGAIN */
2839 MHD_DLOG (daemon,
2840 _ ("Failed to create a thread: %s\n"),
2841 MHD_strerror_ (eno));
2842#endif /* HAVE_MESSAGES */
2843 }
2844 else /* New thread has been created successfully */
2845 return MHD_YES; /* *** Function success exit point *** */
2846 }
2847 else
2848#else /* ! MHD_USE_THREADS */
2849 if (1)
2850#endif /* ! MHD_USE_THREADS */
2851 { /* No 'thread-per-connection' */
2852#ifdef MHD_USE_THREADS
2853 connection->pid = daemon->pid;
2854#endif /* MHD_USE_THREADS */
2855#ifdef EPOLL_SUPPORT
2856 if (0 != (daemon->options & MHD_USE_EPOLL))
2857 {
2858 if (0 == (daemon->options & MHD_USE_TURBO))
2859 {
2860 struct epoll_event event;
2861
2862 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2863 event.data.ptr = connection;
2864 if (0 != epoll_ctl (daemon->epoll_fd,
2865 EPOLL_CTL_ADD,
2866 connection->socket_fd,
2867 &event))
2868 {
2869 eno = errno;
2870#ifdef HAVE_MESSAGES
2871 MHD_DLOG (daemon,
2872 _ ("Call to epoll_ctl failed: %s\n"),
2874#endif
2875 }
2876 else
2877 { /* 'socket_fd' has been added to 'epool' */
2878 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2879
2880 return MHD_YES; /* *** Function success exit point *** */
2881 }
2882 }
2883 else
2884 {
2885 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
2888 EDLL_insert (daemon->eready_head,
2889 daemon->eready_tail,
2890 connection);
2891
2892 return MHD_YES; /* *** Function success exit point *** */
2893 }
2894 }
2895 else /* No 'epoll' */
2896#endif /* EPOLL_SUPPORT */
2897 return MHD_YES; /* *** Function success exit point *** */
2898 }
2899
2900 /* ** Below is a cleanup path ** */
2901 if (NULL != daemon->notify_connection)
2903 connection,
2904 &connection->socket_context,
2907 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2908 {
2910 daemon->normal_timeout_tail,
2911 connection);
2912 }
2914 daemon->connections_tail,
2915 connection);
2916 daemon->connections--;
2918 }
2919 MHD_pool_destroy (connection->pool);
2920 }
2921 /* Free resources allocated before the call of this functions */
2922#ifdef HTTPS_SUPPORT
2923 if (NULL != connection->tls_session)
2924 gnutls_deinit (connection->tls_session);
2925#endif /* HTTPS_SUPPORT */
2926 MHD_ip_limit_del (daemon,
2927 connection->addr,
2928 connection->addr_len);
2929 free (connection->addr);
2930 MHD_socket_close_chk_ (connection->socket_fd);
2931 free (connection);
2932 if (0 != eno)
2933 errno = eno;
2934#ifdef EINVAL
2935 else
2936 errno = EINVAL;
2937#endif /* EINVAL */
2938 return MHD_NO; /* *** Function failure exit point *** */
2939}
2940
2941
2970static enum MHD_Result
2972 MHD_socket client_socket,
2973 const struct sockaddr *addr,
2974 socklen_t addrlen,
2975 bool external_add,
2976 bool non_blck,
2977 bool sk_spipe_supprs,
2978 enum MHD_tristate sk_is_nonip)
2979{
2980 struct MHD_Connection *connection;
2981
2982#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2983 /* Direct add to master daemon could never happen. */
2985#endif
2986
2987 if ( (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
2988 (! MHD_SCKT_FD_FITS_FDSET_ (client_socket, NULL)) )
2989 {
2990#ifdef HAVE_MESSAGES
2991 MHD_DLOG (daemon,
2992 _ ("New connection socket descriptor (%d) is not less " \
2993 "than FD_SETSIZE (%d).\n"),
2994 (int) client_socket,
2995 (int) FD_SETSIZE);
2996#endif
2997 MHD_socket_close_chk_ (client_socket);
2998#if ENFILE
2999 errno = ENFILE;
3000#endif
3001 return MHD_NO;
3002 }
3003
3004 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3005 (! non_blck) )
3006 {
3007#ifdef HAVE_MESSAGES
3008 MHD_DLOG (daemon,
3009 _ ("Epoll mode supports only non-blocking sockets\n"));
3010#endif
3011 MHD_socket_close_chk_ (client_socket);
3012#if EINVAL
3013 errno = EINVAL;
3014#endif
3015 return MHD_NO;
3016 }
3017
3018 connection = new_connection_prepare_ (daemon,
3019 client_socket,
3020 addr, addrlen,
3021 external_add,
3022 non_blck,
3023 sk_spipe_supprs,
3024 sk_is_nonip);
3025 if (NULL == connection)
3026 return MHD_NO;
3027
3028 if ((external_add) &&
3030 {
3031 /* Connection is added externally and MHD is handling its own threads. */
3032 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3035 connection);
3036 daemon->have_new = true;
3037 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3038
3039 /* The rest of connection processing must be handled in
3040 * the daemon thread. */
3041 if ((MHD_ITC_IS_VALID_ (daemon->itc)) &&
3042 (! MHD_itc_activate_ (daemon->itc, "n")))
3043 {
3044 #ifdef HAVE_MESSAGES
3045 MHD_DLOG (daemon,
3046 _ ("Failed to signal new connection via inter-thread " \
3047 "communication channel.\n"));
3048 #endif
3049 }
3050 return MHD_YES;
3051 }
3052
3053 return new_connection_process_ (daemon, connection);
3054}
3055
3056
3057static void
3059{
3060 struct MHD_Connection *local_head;
3061 struct MHD_Connection *local_tail;
3064
3065 /* Detach DL-list of new connections from the daemon for
3066 * following local processing. */
3067 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
3069 local_head = daemon->new_connections_head;
3070 local_tail = daemon->new_connections_tail;
3073 daemon->have_new = false;
3074 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3075 (void) local_head; /* Mute compiler warning */
3076
3077 /* Process new connections in FIFO order. */
3078 do
3079 {
3080 struct MHD_Connection *c;
3082 c = local_tail;
3083 DLL_remove (local_head,
3084 local_tail,
3085 c);
3086 mhd_assert (daemon == c->daemon);
3088 {
3089#ifdef HAVE_MESSAGES
3090 MHD_DLOG (daemon,
3091 _ ("Failed to start serving new connection.\n"));
3092#endif
3093 (void) 0;
3094 }
3095 } while (NULL != local_tail);
3096
3097}
3098
3099
3109void
3111{
3112 struct MHD_Daemon *daemon = connection->daemon;
3113
3114#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3115 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3116 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3117 MHD_thread_ID_match_current_ (daemon->pid) );
3119#endif
3120 if (connection->resuming)
3121 {
3122 /* suspending again while we didn't even complete resuming yet */
3123 connection->resuming = false;
3124#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3126#endif
3127 return;
3128 }
3129 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3130 {
3131 if (connection->connection_timeout_ms == daemon->connection_timeout_ms)
3133 daemon->normal_timeout_tail,
3134 connection);
3135 else
3137 daemon->manual_timeout_tail,
3138 connection);
3139 }
3141 daemon->connections_tail,
3142 connection);
3143 mhd_assert (! connection->suspended);
3146 connection);
3147 connection->suspended = true;
3148#ifdef EPOLL_SUPPORT
3149 if (0 != (daemon->options & MHD_USE_EPOLL))
3150 {
3151 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3152 {
3153 EDLL_remove (daemon->eready_head,
3154 daemon->eready_tail,
3155 connection);
3156 connection->epoll_state &=
3158 }
3159 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
3160 {
3161 if (0 != epoll_ctl (daemon->epoll_fd,
3162 EPOLL_CTL_DEL,
3163 connection->socket_fd,
3164 NULL))
3165 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3166 connection->epoll_state &=
3168 }
3169 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
3170 }
3171#endif
3172#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3174#endif
3175}
3176
3177
3210void
3212{
3213 struct MHD_Daemon *const daemon = connection->daemon;
3214
3215#ifdef MHD_USE_THREADS
3216 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3217 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3218 MHD_thread_ID_match_current_ (daemon->pid) );
3219#endif /* MHD_USE_THREADS */
3220
3221 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3222 MHD_PANIC (_ (
3223 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3224#ifdef UPGRADE_SUPPORT
3225 if (NULL != connection->urh)
3226 {
3227#ifdef HAVE_MESSAGES
3228 MHD_DLOG (daemon,
3229 _ (
3230 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
3231#endif /* HAVE_MESSAGES */
3232 return;
3233 }
3234#endif /* UPGRADE_SUPPORT */
3235 internal_suspend_connection_ (connection);
3236}
3237
3238
3247void
3249{
3250 struct MHD_Daemon *daemon = connection->daemon;
3251
3252 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3253 MHD_PANIC (_ (
3254 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3255#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3257#endif
3258 connection->resuming = true;
3259 daemon->resuming = true;
3260#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3262#endif
3263 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3264 (! MHD_itc_activate_ (daemon->itc, "r")) )
3265 {
3266#ifdef HAVE_MESSAGES
3267 MHD_DLOG (daemon,
3268 _ (
3269 "Failed to signal resume via inter-thread communication channel.\n"));
3270#endif
3271 }
3272}
3273
3274
3275#ifdef UPGRADE_SUPPORT
3283void
3284MHD_upgraded_connection_mark_app_closed_ (struct MHD_Connection *connection)
3285{
3286 /* Cache 'daemon' here to avoid data races */
3287 struct MHD_Daemon *const daemon = connection->daemon;
3288#if defined(MHD_USE_THREADS)
3289 mhd_assert (NULL == daemon->worker_pool);
3290#endif /* MHD_USE_THREADS */
3291 mhd_assert (NULL != connection->urh);
3293
3295 connection->urh->was_closed = true;
3296 connection->resuming = true;
3297 daemon->resuming = true;
3299 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3300 (! MHD_itc_activate_ (daemon->itc, "r")) )
3301 {
3302#ifdef HAVE_MESSAGES
3303 MHD_DLOG (daemon,
3304 _ ("Failed to signal resume via " \
3305 "inter-thread communication channel.\n"));
3306#endif
3307 }
3308}
3309
3310
3311#endif /* UPGRADE_SUPPORT */
3312
3322static enum MHD_Result
3324{
3325 struct MHD_Connection *pos;
3326 struct MHD_Connection *prev = NULL;
3327 enum MHD_Result ret;
3328 const bool used_thr_p_c = (0 != (daemon->options
3330#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3333 MHD_thread_ID_match_current_ (daemon->pid) );
3334#endif
3335
3336 ret = MHD_NO;
3337#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3339#endif
3340
3341 if (daemon->resuming)
3342 {
3344 /* During shutdown check for resuming is forced. */
3345 mhd_assert ((NULL != prev) || (daemon->shutdown) || \
3346 (0 != (daemon->options & MHD_ALLOW_UPGRADE)));
3347 }
3348
3349 daemon->resuming = false;
3350
3351 while (NULL != (pos = prev))
3352 {
3353#ifdef UPGRADE_SUPPORT
3354 struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3355#else /* ! UPGRADE_SUPPORT */
3356 static const void *const urh = NULL;
3357#endif /* ! UPGRADE_SUPPORT */
3358 prev = pos->prev;
3359 if ( (! pos->resuming)
3360#ifdef UPGRADE_SUPPORT
3361 || ( (NULL != urh) &&
3362 ( (! urh->was_closed) ||
3363 (! urh->clean_ready) ) )
3364#endif /* UPGRADE_SUPPORT */
3365 )
3366 continue;
3367 ret = MHD_YES;
3368 mhd_assert (pos->suspended);
3371 pos);
3372 pos->suspended = false;
3373 if (NULL == urh)
3374 {
3376 daemon->connections_tail,
3377 pos);
3378 if (! used_thr_p_c)
3379 {
3380 /* Reset timeout timer on resume. */
3381 if (0 != pos->connection_timeout_ms)
3383
3384 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
3386 daemon->normal_timeout_tail,
3387 pos);
3388 else
3390 daemon->manual_timeout_tail,
3391 pos);
3392 }
3393#ifdef EPOLL_SUPPORT
3394 if (0 != (daemon->options & MHD_USE_EPOLL))
3395 {
3396 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3397 MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3398 /* we always mark resumed connections as ready, as we
3399 might have missed the edge poll event during suspension */
3400 EDLL_insert (daemon->eready_head,
3401 daemon->eready_tail,
3402 pos);
3403 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3406 pos->epoll_state &= ~((enum MHD_EpollState) MHD_EPOLL_STATE_SUSPENDED);
3407 }
3408#endif
3409 }
3410#ifdef UPGRADE_SUPPORT
3411 else
3412 {
3413 /* Data forwarding was finished (for TLS connections) AND
3414 * application was closed upgraded connection.
3415 * Insert connection into cleanup list. */
3416
3417 if ( (NULL != daemon->notify_completed) &&
3418 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3419 (pos->client_aware) )
3420 {
3421 daemon->notify_completed (daemon->notify_completed_cls,
3422 pos,
3423 &pos->client_context,
3425 pos->client_aware = false;
3426 }
3427 DLL_insert (daemon->cleanup_head,
3428 daemon->cleanup_tail,
3429 pos);
3430 daemon->data_already_pending = true;
3431 }
3432#endif /* UPGRADE_SUPPORT */
3433 pos->resuming = false;
3434 }
3435#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3437#endif
3438 if ( (used_thr_p_c) &&
3439 (MHD_NO != ret) )
3440 { /* Wake up suspended connections. */
3441 if (! MHD_itc_activate_ (daemon->itc,
3442 "w"))
3443 {
3444#ifdef HAVE_MESSAGES
3445 MHD_DLOG (daemon,
3446 _ (
3447 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3448#endif
3449 }
3450 }
3451 return ret;
3452}
3453
3454
3482enum MHD_Result
3484 MHD_socket client_socket,
3485 const struct sockaddr *addr,
3486 socklen_t addrlen)
3487{
3488 bool sk_nonbl;
3489 bool sk_spipe_supprs;
3490
3491 /* NOT thread safe with internal thread. TODO: fix thread safety. */
3492 if ((0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3493 (daemon->connection_limit <= daemon->connections))
3494 MHD_cleanup_connections (daemon);
3495
3496#ifdef HAVE_MESSAGES
3497 if ((0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3498 (0 == (daemon->options & MHD_USE_ITC)))
3499 {
3500 MHD_DLOG (daemon,
3501 _ ("MHD_add_connection() has been called for daemon started"
3502 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3503 " added connection until any activity occurs in already"
3504 " added sockets.\n"));
3505 }
3506#endif /* HAVE_MESSAGES */
3507
3508 if (! MHD_socket_nonblocking_ (client_socket))
3509 {
3510#ifdef HAVE_MESSAGES
3511 MHD_DLOG (daemon,
3512 _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3514#endif
3515 sk_nonbl = false;
3516 }
3517 else
3518 sk_nonbl = true;
3519
3520#ifndef MHD_WINSOCK_SOCKETS
3521 sk_spipe_supprs = false;
3522#else /* MHD_WINSOCK_SOCKETS */
3523 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3524#endif /* MHD_WINSOCK_SOCKETS */
3525#if defined(MHD_socket_nosignal_)
3526 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (client_socket))
3527 {
3528#ifdef HAVE_MESSAGES
3529 MHD_DLOG (daemon,
3530 _ (
3531 "Failed to suppress SIGPIPE on new client socket: %s\n"),
3533#else /* ! HAVE_MESSAGES */
3534 (void) 0; /* Mute compiler warning */
3535#endif /* ! HAVE_MESSAGES */
3536#ifndef MSG_NOSIGNAL
3537 /* Application expects that SIGPIPE will be suppressed,
3538 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3539 if (! daemon->sigpipe_blocked)
3540 {
3541 int err = MHD_socket_get_error_ ();
3542 MHD_socket_close_ (client_socket);
3544 return MHD_NO;
3545 }
3546#endif /* MSG_NOSIGNAL */
3547 }
3548 else
3549 sk_spipe_supprs = true;
3550#endif /* MHD_socket_nosignal_ */
3551
3552 if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3553 (! MHD_socket_noninheritable_ (client_socket)) )
3554 {
3555#ifdef HAVE_MESSAGES
3556 MHD_DLOG (daemon,
3557 _ ("Failed to set noninheritable mode on new client socket.\n"));
3558#endif
3559 }
3560
3561#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3562 if (NULL != daemon->worker_pool)
3563 {
3564 unsigned int i;
3565 /* have a pool, try to find a pool with capacity; we use the
3566 socket as the initial offset into the pool for load
3567 balancing */
3568 for (i = 0; i < daemon->worker_pool_size; ++i)
3569 {
3570 struct MHD_Daemon *const worker =
3571 &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
3572 if (worker->connections < worker->connection_limit)
3573 return internal_add_connection (worker,
3574 client_socket,
3575 addr,
3576 addrlen,
3577 true,
3578 sk_nonbl,
3579 sk_spipe_supprs,
3580 _MHD_UNKNOWN);
3581 }
3582 /* all pools are at their connection limit, must refuse */
3583 MHD_socket_close_chk_ (client_socket);
3584#if ENFILE
3585 errno = ENFILE;
3586#endif
3587 return MHD_NO;
3588 }
3589#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
3590
3591 return internal_add_connection (daemon,
3592 client_socket,
3593 addr,
3594 addrlen,
3595 true,
3596 sk_nonbl,
3597 sk_spipe_supprs,
3598 _MHD_UNKNOWN);
3599}
3600
3601
3616static enum MHD_Result
3618{
3619#if HAVE_INET6
3620 struct sockaddr_in6 addrstorage;
3621#else
3622 struct sockaddr_in addrstorage;
3623#endif
3624 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3625 socklen_t addrlen;
3626 MHD_socket s;
3627 MHD_socket fd;
3628 bool sk_nonbl;
3629 bool sk_spipe_supprs;
3630 bool sk_cloexec;
3631
3632#ifdef MHD_USE_THREADS
3633 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3634 MHD_thread_ID_match_current_ (daemon->pid) );
3635#endif /* MHD_USE_THREADS */
3636
3637 addrlen = sizeof (addrstorage);
3638 memset (addr,
3639 0,
3640 sizeof (addrstorage));
3641 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3642 (daemon->was_quiesced) )
3643 return MHD_NO;
3644#ifdef USE_ACCEPT4
3645 s = accept4 (fd,
3646 addr,
3647 &addrlen,
3650 sk_nonbl = (SOCK_NONBLOCK_OR_ZERO != 0);
3651#ifndef MHD_WINSOCK_SOCKETS
3652 sk_spipe_supprs = (SOCK_NOSIGPIPE_OR_ZERO != 0);
3653#else /* MHD_WINSOCK_SOCKETS */
3654 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3655#endif /* MHD_WINSOCK_SOCKETS */
3656 sk_cloexec = (SOCK_CLOEXEC_OR_ZERO != 0);
3657#else /* ! USE_ACCEPT4 */
3658 s = accept (fd,
3659 addr,
3660 &addrlen);
3661#ifdef MHD_ACCEPT_INHERIT_NONBLOCK
3662 sk_nonbl = daemon->listen_nonblk;
3663#else /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
3664 sk_nonbl = false;
3665#endif /* ! MHD_ACCEPT_INHERIT_NONBLOCK */
3666#ifndef MHD_WINSOCK_SOCKETS
3667 sk_spipe_supprs = false;
3668#else /* MHD_WINSOCK_SOCKETS */
3669 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3670#endif /* MHD_WINSOCK_SOCKETS */
3671 sk_cloexec = false;
3672#endif /* ! USE_ACCEPT4 */
3673 if ( (MHD_INVALID_SOCKET == s) ||
3674 (addrlen <= 0) )
3675 {
3676 const int err = MHD_socket_get_error_ ();
3677
3678 /* This could be a common occurrence with multiple worker threads */
3679 if (MHD_SCKT_ERR_IS_ (err,
3681 return MHD_NO; /* can happen during shutdown */
3683 return MHD_NO; /* do not print error if client just disconnected early */
3684#ifdef HAVE_MESSAGES
3685 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3686 MHD_DLOG (daemon,
3687 _ ("Error accepting connection: %s\n"),
3688 MHD_socket_strerr_ (err));
3689#endif
3690 if (MHD_INVALID_SOCKET != s)
3691 {
3693 }
3695 {
3696 /* system/process out of resources */
3697 if (0 == daemon->connections)
3698 {
3699#ifdef HAVE_MESSAGES
3700 /* Not setting 'at_limit' flag, as there is no way it
3701 would ever be cleared. Instead trying to produce
3702 bit fat ugly warning. */
3703 MHD_DLOG (daemon,
3704 _ ("Hit process or system resource limit at FIRST " \
3705 "connection. This is really bad as there is no sane " \
3706 "way to proceed. Will try busy waiting for system " \
3707 "resources to become magically available.\n"));
3708#endif
3709 }
3710 else
3711 {
3712#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3714#endif
3715 daemon->at_limit = true;
3716#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3718#endif
3719#ifdef HAVE_MESSAGES
3720 MHD_DLOG (daemon,
3721 _ ("Hit process or system resource limit at %u " \
3722 "connections, temporarily suspending accept(). " \
3723 "Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3724 (unsigned int) daemon->connections);
3725#endif
3726 }
3727 }
3728 return MHD_NO;
3729 }
3730
3731 if (! sk_nonbl && ! MHD_socket_nonblocking_ (s))
3732 {
3733#ifdef HAVE_MESSAGES
3734 MHD_DLOG (daemon,
3735 _ ("Failed to set nonblocking mode on incoming connection " \
3736 "socket: %s\n"),
3738#else /* ! HAVE_MESSAGES */
3739 (void) 0; /* Mute compiler warning */
3740#endif /* ! HAVE_MESSAGES */
3741 }
3742 else
3743 sk_nonbl = true;
3744
3745 if (! sk_cloexec && ! MHD_socket_noninheritable_ (s))
3746 {
3747#ifdef HAVE_MESSAGES
3748 MHD_DLOG (daemon,
3749 _ ("Failed to set noninheritable mode on incoming connection " \
3750 "socket.\n"));
3751#else /* ! HAVE_MESSAGES */
3752 (void) 0; /* Mute compiler warning */
3753#endif /* ! HAVE_MESSAGES */
3754 }
3755
3756#if defined(MHD_socket_nosignal_)
3757 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
3758 {
3759#ifdef HAVE_MESSAGES
3760 MHD_DLOG (daemon,
3761 _ ("Failed to suppress SIGPIPE on incoming connection " \
3762 "socket: %s\n"),
3764#else /* ! HAVE_MESSAGES */
3765 (void) 0; /* Mute compiler warning */
3766#endif /* ! HAVE_MESSAGES */
3767#ifndef MSG_NOSIGNAL
3768 /* Application expects that SIGPIPE will be suppressed,
3769 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3770 if (! daemon->sigpipe_blocked)
3771 {
3773 return MHD_NO;
3774 }
3775#endif /* MSG_NOSIGNAL */
3776 }
3777 else
3778 sk_spipe_supprs = true;
3779#endif /* MHD_socket_nosignal_ */
3780#ifdef HAVE_MESSAGES
3781#if _MHD_DEBUG_CONNECT
3782 MHD_DLOG (daemon,
3783 _ ("Accepted connection on socket %d\n"),
3784 s);
3785#endif
3786#endif
3787 (void) internal_add_connection (daemon,
3788 s,
3789 addr,
3790 addrlen,
3791 false,
3792 sk_nonbl,
3793 sk_spipe_supprs,
3794 daemon->listen_is_unix);
3795 return MHD_YES;
3796}
3797
3798
3808static void
3810{
3811 struct MHD_Connection *pos;
3812#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3814 MHD_thread_ID_match_current_ (daemon->pid) );
3815
3817#endif
3818 while (NULL != (pos = daemon->cleanup_tail))
3819 {
3822 pos);
3823#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3825 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3826 (! pos->thread_joined) &&
3827 (! MHD_join_thread_ (pos->pid.handle)) )
3828 MHD_PANIC (_ ("Failed to join a thread.\n"));
3829#endif
3830#ifdef UPGRADE_SUPPORT
3831 cleanup_upgraded_connection (pos);
3832#endif /* UPGRADE_SUPPORT */
3833 MHD_pool_destroy (pos->pool);
3834#ifdef HTTPS_SUPPORT
3835 if (NULL != pos->tls_session)
3836 gnutls_deinit (pos->tls_session);
3837#endif /* HTTPS_SUPPORT */
3838
3839 /* clean up the connection */
3842 pos,
3843 &pos->socket_context,
3846 pos->addr,
3847 pos->addr_len);
3848#ifdef EPOLL_SUPPORT
3849 if (0 != (daemon->options & MHD_USE_EPOLL))
3850 {
3851 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3852 {
3853 EDLL_remove (daemon->eready_head,
3854 daemon->eready_tail,
3855 pos);
3856 pos->epoll_state &=
3858 }
3859 if ( (-1 != daemon->epoll_fd) &&
3860 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3861 {
3862 /* epoll documentation suggests that closing a FD
3863 automatically removes it from the epoll set; however,
3864 this is not true as if we fail to do manually remove it,
3865 we are still seeing an event for this fd in epoll,
3866 causing grief (use-after-free...) --- at least on my
3867 system. */
3868 if (0 != epoll_ctl (daemon->epoll_fd,
3869 EPOLL_CTL_DEL,
3870 pos->socket_fd,
3871 NULL))
3872 MHD_PANIC (_ (
3873 "Failed to remove FD from epoll set.\n"));
3874 pos->epoll_state &=
3875 ~((enum MHD_EpollState)
3877 }
3878 }
3879#endif
3880 if (NULL != pos->response)
3881 {
3883 pos->response = NULL;
3884 }
3885 if (MHD_INVALID_SOCKET != pos->socket_fd)
3887 if (NULL != pos->addr)
3888 free (pos->addr);
3889 free (pos);
3890
3891#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3893#endif
3895 daemon->at_limit = false;
3896 }
3897#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3899#endif
3900}
3901
3902
3935enum MHD_Result
3937 MHD_UNSIGNED_LONG_LONG *timeout)
3938{
3939 uint64_t earliest_deadline;
3940 struct MHD_Connection *pos;
3941 struct MHD_Connection *earliest_tmot_conn;
3943#ifdef MHD_USE_THREADS
3945 MHD_thread_ID_match_current_ (daemon->pid) );
3946#endif /* MHD_USE_THREADS */
3947
3949 {
3950#ifdef HAVE_MESSAGES
3951 MHD_DLOG (daemon,
3952 _ ("Illegal call to MHD_get_timeout.\n"));
3953#endif
3954 return MHD_NO;
3955 }
3957 {
3958 /* Some data already waiting to be processed. */
3959 *timeout = 0;
3960 return MHD_YES;
3961 }
3962#ifdef EPOLL_SUPPORT
3963 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3964 ((NULL != daemon->eready_head)
3965#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3966 || (NULL != daemon->eready_urh_head)
3967#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3968 ) )
3969 {
3970 /* Some connection(s) already have some data pending. */
3971 *timeout = 0;
3972 return MHD_YES;
3973 }
3974#endif /* EPOLL_SUPPORT */
3975
3976 earliest_tmot_conn = NULL;
3977 earliest_deadline = 0; /* mute compiler warning */
3978 /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3980 if ( (NULL != pos) &&
3981 (0 != pos->connection_timeout_ms) )
3982 {
3983 earliest_tmot_conn = pos;
3984 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
3985 }
3986
3987 for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3988 {
3989 if (0 != pos->connection_timeout_ms)
3990 {
3991 if ( (NULL == earliest_tmot_conn) ||
3992 (earliest_deadline - pos->last_activity >
3993 pos->connection_timeout_ms) )
3994 {
3995 earliest_tmot_conn = pos;
3996 earliest_deadline = pos->last_activity + pos->connection_timeout_ms;
3997 }
3998 }
3999 }
4000
4001 if (NULL != earliest_tmot_conn)
4002 {
4003 const uint64_t mssecond_left = connection_get_wait (earliest_tmot_conn);
4004#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
4005 if (mssecond_left > ULLONG_MAX)
4006 *timeout = ULLONG_MAX;
4007 else
4008#endif /* UINT64 != ULLONG_MAX */
4009 *timeout = (unsigned long long) mssecond_left;
4010 return MHD_YES;
4011 }
4012 return MHD_NO;
4013}
4014
4015
4016#if defined(HAVE_POLL) || defined(EPOLL_SUPPORT)
4027static int
4028get_timeout_millisec_ (struct MHD_Daemon *daemon,
4029 int32_t max_timeout)
4030{
4031 MHD_UNSIGNED_LONG_LONG ulltimeout;
4032 if (0 == max_timeout)
4033 return 0;
4034
4035 if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
4036 return (INT_MAX <= max_timeout) ? INT_MAX : (int) max_timeout;
4037
4038 if ( (0 > max_timeout) ||
4039 ((uint32_t) max_timeout > ulltimeout) )
4040 return (INT_MAX <= ulltimeout) ? INT_MAX : (int) ulltimeout;
4041
4042 return (INT_MAX <= max_timeout) ? INT_MAX : (int) max_timeout;
4043}
4044
4045
4046#endif /* HAVE_POLL || EPOLL_SUPPORT */
4047
4058static enum MHD_Result
4060 const fd_set *read_fd_set,
4061 const fd_set *write_fd_set,
4062 const fd_set *except_fd_set)
4063{
4064 MHD_socket ds;
4065 struct MHD_Connection *pos;
4066 struct MHD_Connection *prev;
4067#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4068 struct MHD_UpgradeResponseHandle *urh;
4069 struct MHD_UpgradeResponseHandle *urhn;
4070#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4071 /* Reset. New value will be set when connections are processed. */
4072 /* Note: no-op for thread-per-connection as it is always false in that mode. */
4073 daemon->data_already_pending = false;
4074
4075 /* Clear ITC to avoid spinning select */
4076 /* Do it before any other processing so new signals
4077 will trigger select again and will be processed */
4078 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4079 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
4080 read_fd_set)) )
4081 MHD_itc_clear_ (daemon->itc);
4082
4083 /* Process externally added connection if any */
4084 if (daemon->have_new)
4086
4087 /* select connection thread handling type */
4088 if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
4089 (! daemon->was_quiesced) &&
4090 (FD_ISSET (ds,
4091 read_fd_set)) )
4092 (void) MHD_accept_connection (daemon);
4093
4094 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4095 {
4096 /* do not have a thread per connection, process all connections now */
4097 prev = daemon->connections_tail;
4098 while (NULL != (pos = prev))
4099 {
4100 prev = pos->prev;
4101 ds = pos->socket_fd;
4102 if (MHD_INVALID_SOCKET == ds)
4103 continue;
4104 call_handlers (pos,
4105 FD_ISSET (ds,
4106 read_fd_set),
4107 FD_ISSET (ds,
4108 write_fd_set),
4109 FD_ISSET (ds,
4110 except_fd_set));
4111 }
4112 }
4113
4114#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4115 /* handle upgraded HTTPS connections */
4116 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4117 {
4118 urhn = urh->prev;
4119 /* update urh state based on select() output */
4120 urh_from_fdset (urh,
4121 read_fd_set,
4122 write_fd_set,
4123 except_fd_set);
4124 /* call generic forwarding function for passing data */
4125 process_urh (urh);
4126 /* Finished forwarding? */
4127 if ( (0 == urh->in_buffer_size) &&
4128 (0 == urh->out_buffer_size) &&
4129 (0 == urh->in_buffer_used) &&
4130 (0 == urh->out_buffer_used) )
4131 {
4132 MHD_connection_finish_forward_ (urh->connection);
4133 urh->clean_ready = true;
4134 /* Resuming will move connection to cleanup list. */
4135 MHD_resume_connection (urh->connection);
4136 }
4137 }
4138#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4139 MHD_cleanup_connections (daemon);
4140 return MHD_YES;
4141}
4142
4143
4170enum MHD_Result
4172 const fd_set *read_fd_set,
4173 const fd_set *write_fd_set,
4174 const fd_set *except_fd_set)
4175{
4176 fd_set es;
4177 if (0 != (daemon->options
4179 return MHD_NO;
4180 if ((NULL == read_fd_set) || (NULL == write_fd_set))
4181 return MHD_NO;
4182 if (NULL == except_fd_set)
4183 { /* Workaround to maintain backward compatibility. */
4184#ifdef HAVE_MESSAGES
4185 MHD_DLOG (daemon,
4186 _ ("MHD_run_from_select() called with except_fd_set "
4187 "set to NULL. Such behavior is deprecated.\n"));
4188#endif
4189 FD_ZERO (&es);
4190 except_fd_set = &es;
4191 }
4192 if (0 != (daemon->options & MHD_USE_EPOLL))
4193 {
4194#ifdef EPOLL_SUPPORT
4195 enum MHD_Result ret = MHD_epoll (daemon,
4196 0);
4197
4198 MHD_cleanup_connections (daemon);
4199 return ret;
4200#else /* ! EPOLL_SUPPORT */
4201 return MHD_NO;
4202#endif /* ! EPOLL_SUPPORT */
4203 }
4204
4205 /* Resuming external connections when using an extern mainloop */
4206 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4208
4209 return internal_run_from_select (daemon,
4210 read_fd_set,
4211 write_fd_set,
4212 except_fd_set);
4213}
4214
4215
4226static enum MHD_Result
4227MHD_select (struct MHD_Daemon *daemon,
4228 int32_t millisec)
4229{
4230 int num_ready;
4231 fd_set rs;
4232 fd_set ws;
4233 fd_set es;
4234 MHD_socket maxsock;
4235 struct timeval timeout;
4236 struct timeval *tv;
4237 int err_state;
4238 MHD_socket ls;
4239
4240 timeout.tv_sec = 0;
4241 timeout.tv_usec = 0;
4242 if (daemon->shutdown)
4243 return MHD_NO;
4244 FD_ZERO (&rs);
4245 FD_ZERO (&ws);
4246 FD_ZERO (&es);
4247 maxsock = MHD_INVALID_SOCKET;
4248 err_state = MHD_NO;
4249 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4250 (MHD_NO != resume_suspended_connections (daemon)) &&
4251 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
4252 millisec = 0;
4253
4254 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4255 {
4256 /* single-threaded, go over everything */
4257 if (MHD_NO ==
4258 internal_get_fdset2 (daemon,
4259 &rs,
4260 &ws,
4261 &es,
4262 &maxsock,
4263 FD_SETSIZE))
4264 {
4265#ifdef HAVE_MESSAGES
4266 MHD_DLOG (daemon,
4267 _ ("Could not obtain daemon fdsets.\n"));
4268#endif
4269 err_state = MHD_YES;
4270 }
4271 }
4272 else
4273 {
4274 /* accept only, have one thread per connection */
4275 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4276 (! daemon->was_quiesced) &&
4277 (! MHD_add_to_fd_set_ (ls,
4278 &rs,
4279 &maxsock,
4280 FD_SETSIZE)) )
4281 {
4282#ifdef HAVE_MESSAGES
4283 MHD_DLOG (daemon,
4284 _ ("Could not add listen socket to fdset.\n"));
4285#endif
4286 return MHD_NO;
4287 }
4288 }
4289 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4290 (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4291 &rs,
4292 &maxsock,
4293 FD_SETSIZE)) )
4294 {
4295 bool retry_succeed;
4296
4297 retry_succeed = false;
4298#if defined(MHD_WINSOCK_SOCKETS)
4299 /* fdset limit reached, new connections
4300 cannot be handled. Remove listen socket FD
4301 from fdset and retry to add ITC FD. */
4302 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4303 (! daemon->was_quiesced) )
4304 {
4305 FD_CLR (ls,
4306 &rs);
4307 if (MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4308 &rs,
4309 &maxsock,
4310 FD_SETSIZE))
4311 retry_succeed = true;
4312 }
4313#endif /* MHD_WINSOCK_SOCKETS */
4314
4315 if (! retry_succeed)
4316 {
4317#ifdef HAVE_MESSAGES
4318 MHD_DLOG (daemon,
4319 _ ("Could not add control inter-thread communication " \
4320 "channel FD to fdset.\n"));
4321#endif
4322 err_state = MHD_YES;
4323 }
4324 }
4325 /* Stop listening if we are at the configured connection limit */
4326 /* If we're at the connection limit, no point in really
4327 accepting new connections; however, make sure we do not miss
4328 the shutdown OR the termination of an existing connection; so
4329 only do this optimization if we have a signaling ITC in
4330 place. */
4331 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4332 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4333 ( (daemon->connections == daemon->connection_limit) ||
4334 (daemon->at_limit) ) )
4335 {
4336 FD_CLR (ls,
4337 &rs);
4338 }
4339
4340 if (MHD_NO != err_state)
4341 millisec = 0;
4342 tv = NULL;
4343 if (0 == millisec)
4344 {
4345 timeout.tv_usec = 0;
4346 timeout.tv_sec = 0;
4347 tv = &timeout;
4348 }
4349 else
4350 {
4351 MHD_UNSIGNED_LONG_LONG ltimeout;
4352
4353 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
4354 (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
4355 {
4356 tv = &timeout; /* have timeout value */
4357 if ( (0 < millisec) &&
4358 (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
4359 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4360 }
4361 else if (0 < millisec)
4362 {
4363 tv = &timeout; /* have timeout value */
4364 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4365 }
4366
4367 if (NULL != tv)
4368 { /* have timeout value */
4369 if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
4370 {
4371 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
4372 timeout.tv_usec = 0;
4373 }
4374 else
4375 {
4376 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
4377 timeout.tv_usec = (ltimeout % 1000) * 1000;
4378 }
4379 }
4380 }
4381 num_ready = MHD_SYS_select_ (maxsock + 1,
4382 &rs,
4383 &ws,
4384 &es,
4385 tv);
4386 if (daemon->shutdown)
4387 return MHD_NO;
4388 if (num_ready < 0)
4389 {
4390 const int err = MHD_socket_get_error_ ();
4391 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4392 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4393#ifdef HAVE_MESSAGES
4394 MHD_DLOG (daemon,
4395 _ ("select failed: %s\n"),
4396 MHD_socket_strerr_ (err));
4397#endif
4398 return MHD_NO;
4399 }
4400 if (MHD_NO != internal_run_from_select (daemon,
4401 &rs,
4402 &ws,
4403 &es))
4404 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4405 return MHD_NO;
4406}
4407
4408
4409#ifdef HAVE_POLL
4420static enum MHD_Result
4421MHD_poll_all (struct MHD_Daemon *daemon,
4422 int32_t millisec)
4423{
4424 unsigned int num_connections;
4425 struct MHD_Connection *pos;
4426 struct MHD_Connection *prev;
4427#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4428 struct MHD_UpgradeResponseHandle *urh;
4429 struct MHD_UpgradeResponseHandle *urhn;
4430#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4431
4432 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4433 (MHD_NO != resume_suspended_connections (daemon)) )
4434 millisec = 0;
4435
4436 /* count number of connections and thus determine poll set size */
4437 num_connections = 0;
4438 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
4439 num_connections++;
4440#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4441 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
4442 num_connections += 2;
4443#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4444 {
4445 unsigned int i;
4446 int timeout;
4447 unsigned int poll_server;
4448 int poll_listen;
4449 int poll_itc_idx;
4450 struct pollfd *p;
4451 MHD_socket ls;
4452
4453 p = MHD_calloc_ ((2 + (size_t) num_connections),
4454 sizeof (struct pollfd));
4455 if (NULL == p)
4456 {
4457#ifdef HAVE_MESSAGES
4458 MHD_DLOG (daemon,
4459 _ ("Error allocating memory: %s\n"),
4460 MHD_strerror_ (errno));
4461#endif
4462 return MHD_NO;
4463 }
4464 poll_server = 0;
4465 poll_listen = -1;
4466 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4467 (! daemon->was_quiesced) &&
4468 (daemon->connections < daemon->connection_limit) &&
4469 (! daemon->at_limit) )
4470 {
4471 /* only listen if we are not at the connection limit */
4472 p[poll_server].fd = ls;
4473 p[poll_server].events = POLLIN;
4474 p[poll_server].revents = 0;
4475 poll_listen = (int) poll_server;
4476 poll_server++;
4477 }
4478 poll_itc_idx = -1;
4479 if (MHD_ITC_IS_VALID_ (daemon->itc))
4480 {
4481 p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
4482 p[poll_server].events = POLLIN;
4483 p[poll_server].revents = 0;
4484 poll_itc_idx = (int) poll_server;
4485 poll_server++;
4486 }
4487
4488 timeout = get_timeout_millisec_ (daemon, millisec);
4489
4490 i = 0;
4491 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
4492 {
4493 p[poll_server + i].fd = pos->socket_fd;
4494 switch (pos->event_loop_info)
4495 {
4497 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
4498 break;
4500 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
4501 break;
4503 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
4504 break;
4506 timeout = 0; /* clean up "pos" immediately */
4507 break;
4508 }
4509 i++;
4510 }
4511#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4512 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
4513 {
4514 urh_to_pollfd (urh, &(p[poll_server + i]));
4515 i += 2;
4516 }
4517#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4518 if (0 == poll_server + num_connections)
4519 {
4520 free (p);
4521 return MHD_YES;
4522 }
4523 if (MHD_sys_poll_ (p,
4524 poll_server + num_connections,
4525 timeout) < 0)
4526 {
4527 const int err = MHD_socket_get_error_ ();
4528 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4529 {
4530 free (p);
4531 return MHD_YES;
4532 }
4533#ifdef HAVE_MESSAGES
4534 MHD_DLOG (daemon,
4535 _ ("poll failed: %s\n"),
4536 MHD_socket_strerr_ (err));
4537#endif
4538 free (p);
4539 return MHD_NO;
4540 }
4541
4542 /* handle ITC FD */
4543 /* do it before any other processing so
4544 new signals will be processed in next loop */
4545 if ( (-1 != poll_itc_idx) &&
4546 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4547 MHD_itc_clear_ (daemon->itc);
4548
4549 /* handle shutdown */
4550 if (daemon->shutdown)
4551 {
4552 free (p);
4553 return MHD_NO;
4554 }
4555
4556 /* Process externally added connection if any */
4557 if (daemon->have_new)
4559
4560 /* handle 'listen' FD */
4561 if ( (-1 != poll_listen) &&
4562 (0 != (p[poll_listen].revents & POLLIN)) )
4563 (void) MHD_accept_connection (daemon);
4564
4565 /* Reset. New value will be set when connections are processed. */
4566 daemon->data_already_pending = false;
4567
4568 i = 0;
4569 prev = daemon->connections_tail;
4570 while (NULL != (pos = prev))
4571 {
4572 prev = pos->prev;
4573 /* first, sanity checks */
4574 if (i >= num_connections)
4575 break; /* connection list changed somehow, retry later ... */
4576 if (p[poll_server + i].fd != pos->socket_fd)
4577 continue; /* fd mismatch, something else happened, retry later ... */
4578 call_handlers (pos,
4579 0 != (p[poll_server + i].revents & POLLIN),
4580 0 != (p[poll_server + i].revents & POLLOUT),
4581 0 != (p[poll_server + i].revents
4582 & MHD_POLL_REVENTS_ERR_DISC));
4583 i++;
4584 }
4585#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4586 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4587 {
4588 if (i >= num_connections)
4589 break; /* connection list changed somehow, retry later ... */
4590
4591 /* Get next connection here as connection can be removed
4592 * from 'daemon->urh_head' list. */
4593 urhn = urh->prev;
4594 /* Check for fd mismatch. FIXME: required for safety? */
4595 if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
4596 (p[poll_server + i + 1].fd != urh->mhd.socket))
4597 break;
4598 urh_from_pollfd (urh,
4599 &p[poll_server + i]);
4600 i += 2;
4601 process_urh (urh);
4602 /* Finished forwarding? */
4603 if ( (0 == urh->in_buffer_size) &&
4604 (0 == urh->out_buffer_size) &&
4605 (0 == urh->in_buffer_used) &&
4606 (0 == urh->out_buffer_used) )
4607 {
4608 /* MHD_connection_finish_forward_() will remove connection from
4609 * 'daemon->urh_head' list. */
4610 MHD_connection_finish_forward_ (urh->connection);
4611 urh->clean_ready = true;
4612 /* If 'urh->was_closed' already was set to true, connection will be
4613 * moved immediately to cleanup list. Otherwise connection
4614 * will stay in suspended list until 'urh' will be marked
4615 * with 'was_closed' by application. */
4616 MHD_resume_connection (urh->connection);
4617 }
4618 }
4619#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4620
4621 free (p);
4622 }
4623 return MHD_YES;
4624}
4625
4626
4634static enum MHD_Result
4635MHD_poll_listen_socket (struct MHD_Daemon *daemon,
4636 int may_block)
4637{
4638 struct pollfd p[2];
4639 int timeout;
4640 unsigned int poll_count;
4641 int poll_listen;
4642 int poll_itc_idx;
4643 MHD_socket ls;
4644
4645 memset (&p,
4646 0,
4647 sizeof (p));
4648 poll_count = 0;
4649 poll_listen = -1;
4650 poll_itc_idx = -1;
4651 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4652 (! daemon->was_quiesced) )
4653
4654 {
4655 p[poll_count].fd = ls;
4656 p[poll_count].events = POLLIN;
4657 p[poll_count].revents = 0;
4658 poll_listen = poll_count;
4659 poll_count++;
4660 }
4661 if (MHD_ITC_IS_VALID_ (daemon->itc))
4662 {
4663 p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
4664 p[poll_count].events = POLLIN;
4665 p[poll_count].revents = 0;
4666 poll_itc_idx = poll_count;
4667 poll_count++;
4668 }
4669
4670 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4671 (void) resume_suspended_connections (daemon);
4672
4673 if (MHD_NO == may_block)
4674 timeout = 0;
4675 else
4676 timeout = -1;
4677 if (0 == poll_count)
4678 return MHD_YES;
4679 if (MHD_sys_poll_ (p,
4680 poll_count,
4681 timeout) < 0)
4682 {
4683 const int err = MHD_socket_get_error_ ();
4684
4685 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4686 return MHD_YES;
4687#ifdef HAVE_MESSAGES
4688 MHD_DLOG (daemon,
4689 _ ("poll failed: %s\n"),
4690 MHD_socket_strerr_ (err));
4691#endif
4692 return MHD_NO;
4693 }
4694 if ( (-1 != poll_itc_idx) &&
4695 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4696 MHD_itc_clear_ (daemon->itc);
4697
4698 /* handle shutdown */
4699 if (daemon->shutdown)
4700 return MHD_NO;
4701
4702 /* Process externally added connection if any */
4703 if (daemon->have_new)
4705
4706 if ( (-1 != poll_listen) &&
4707 (0 != (p[poll_listen].revents & POLLIN)) )
4708 (void) MHD_accept_connection (daemon);
4709 return MHD_YES;
4710}
4711
4712
4713#endif
4714
4715
4723static enum MHD_Result
4724MHD_poll (struct MHD_Daemon *daemon,
4725 int may_block)
4726{
4727#ifdef HAVE_POLL
4728 if (daemon->shutdown)
4729 return MHD_NO;
4730 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4731 return MHD_poll_all (daemon,
4732 may_block ? -1 : 0);
4733 return MHD_poll_listen_socket (daemon,
4734 may_block);
4735#else
4736 (void) daemon;
4737 (void) may_block;
4738 return MHD_NO;
4739#endif
4740}
4741
4742
4743#ifdef EPOLL_SUPPORT
4744
4753#define MAX_EVENTS 128
4754
4755
4756#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4757
4765static bool
4766is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
4767{
4768 const struct MHD_Connection *const connection = urh->connection;
4769
4770 if ( (0 == urh->in_buffer_size) &&
4771 (0 == urh->out_buffer_size) &&
4772 (0 == urh->in_buffer_used) &&
4773 (0 == urh->out_buffer_used) )
4774 return false;
4775 if (connection->daemon->shutdown)
4776 return true;
4777 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4778 (connection->tls_read_ready) ) &&
4779 (urh->in_buffer_used < urh->in_buffer_size) )
4780 return true;
4781 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4782 (urh->out_buffer_used < urh->out_buffer_size) )
4783 return true;
4784 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4785 (urh->out_buffer_used > 0) )
4786 return true;
4787 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4788 (urh->in_buffer_used > 0) )
4789 return true;
4790 return false;
4791}
4792
4793
4802static enum MHD_Result
4803run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4804{
4805 struct epoll_event events[MAX_EVENTS];
4806 int num_events;
4807 struct MHD_UpgradeResponseHandle *pos;
4808 struct MHD_UpgradeResponseHandle *prev;
4809
4810#ifdef MHD_USE_THREADS
4811 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
4812 MHD_thread_ID_match_current_ (daemon->pid) );
4813#endif /* MHD_USE_THREADS */
4814
4815 num_events = MAX_EVENTS;
4816 while (0 != num_events)
4817 {
4818 unsigned int i;
4819 /* update event masks */
4820 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4821 events,
4822 MAX_EVENTS,
4823 0);
4824 if (-1 == num_events)
4825 {
4826 const int err = MHD_socket_get_error_ ();
4827
4828 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4829 return MHD_YES;
4830#ifdef HAVE_MESSAGES
4831 MHD_DLOG (daemon,
4832 _ ("Call to epoll_wait failed: %s\n"),
4833 MHD_socket_strerr_ (err));
4834#endif
4835 return MHD_NO;
4836 }
4837 for (i = 0; i < (unsigned int) num_events; i++)
4838 {
4839 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
4840 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
4841 bool new_err_state = false;
4842
4843 if (urh->clean_ready)
4844 continue;
4845
4846 /* Update ueh state based on what is ready according to epoll() */
4847 if (0 != (events[i].events & EPOLLIN))
4848 {
4849 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4850 }
4851 if (0 != (events[i].events & EPOLLOUT))
4852 {
4853 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4854 }
4855 if (0 != (events[i].events & EPOLLHUP))
4856 {
4858 }
4859
4860 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4861 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4862 {
4863 /* Process new error state only one time and avoid continuously
4864 * marking this connection as 'ready'. */
4865 ueh->celi |= MHD_EPOLL_STATE_ERROR;
4866 new_err_state = true;
4867 }
4868 if (! urh->in_eready_list)
4869 {
4870 if (new_err_state ||
4871 is_urh_ready (urh))
4872 {
4873 EDLL_insert (daemon->eready_urh_head,
4874 daemon->eready_urh_tail,
4875 urh);
4876 urh->in_eready_list = true;
4877 }
4878 }
4879 }
4880 }
4881 prev = daemon->eready_urh_tail;
4882 while (NULL != (pos = prev))
4883 {
4884 prev = pos->prevE;
4885 process_urh (pos);
4886 if (! is_urh_ready (pos))
4887 {
4888 EDLL_remove (daemon->eready_urh_head,
4889 daemon->eready_urh_tail,
4890 pos);
4891 pos->in_eready_list = false;
4892 }
4893 /* Finished forwarding? */
4894 if ( (0 == pos->in_buffer_size) &&
4895 (0 == pos->out_buffer_size) &&
4896 (0 == pos->in_buffer_used) &&
4897 (0 == pos->out_buffer_used) )
4898 {
4899 MHD_connection_finish_forward_ (pos->connection);
4900 pos->clean_ready = true;
4901 /* If 'pos->was_closed' already was set to true, connection
4902 * will be moved immediately to cleanup list. Otherwise
4903 * connection will stay in suspended list until 'pos' will
4904 * be marked with 'was_closed' by application. */
4905 MHD_resume_connection (pos->connection);
4906 }
4907 }
4908
4909 return MHD_YES;
4910}
4911
4912
4913#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4914
4915
4919static const char *const epoll_itc_marker = "itc_marker";
4920
4921
4931static enum MHD_Result
4932MHD_epoll (struct MHD_Daemon *daemon,
4933 int32_t millisec)
4934{
4935#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4936 static const char *const upgrade_marker = "upgrade_ptr";
4937#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4938 struct MHD_Connection *pos;
4939 struct MHD_Connection *prev;
4940 struct epoll_event events[MAX_EVENTS];
4941 struct epoll_event event;
4942 int timeout_ms;
4943 int num_events;
4944 unsigned int i;
4945 MHD_socket ls;
4946#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4947 bool run_upgraded = false;
4948#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4949 bool need_to_accept;
4950
4951 if (-1 == daemon->epoll_fd)
4952 return MHD_NO; /* we're down! */
4953 if (daemon->shutdown)
4954 return MHD_NO;
4955 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4956 (! daemon->was_quiesced) &&
4957 (daemon->connections < daemon->connection_limit) &&
4958 (! daemon->listen_socket_in_epoll) &&
4959 (! daemon->at_limit) )
4960 {
4961 event.events = EPOLLIN;
4962 event.data.ptr = daemon;
4963 if (0 != epoll_ctl (daemon->epoll_fd,
4964 EPOLL_CTL_ADD,
4965 ls,
4966 &event))
4967 {
4968#ifdef HAVE_MESSAGES
4969 MHD_DLOG (daemon,
4970 _ ("Call to epoll_ctl failed: %s\n"),
4972#endif
4973 return MHD_NO;
4974 }
4975 daemon->listen_socket_in_epoll = true;
4976 }
4977 if ( (daemon->was_quiesced) &&
4978 (daemon->listen_socket_in_epoll) )
4979 {
4980 if ( (0 != epoll_ctl (daemon->epoll_fd,
4981 EPOLL_CTL_DEL,
4982 ls,
4983 NULL)) &&
4984 (ENOENT != errno) ) /* ENOENT can happen due to race with
4985 #MHD_quiesce_daemon() */
4986 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4987 daemon->listen_socket_in_epoll = false;
4988 }
4989
4990#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4991 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4992 (-1 != daemon->epoll_upgrade_fd) ) )
4993 {
4994 event.events = EPOLLIN | EPOLLOUT;
4995 event.data.ptr = (void *) upgrade_marker;
4996 if (0 != epoll_ctl (daemon->epoll_fd,
4997 EPOLL_CTL_ADD,
4998 daemon->epoll_upgrade_fd,
4999 &event))
5000 {
5001#ifdef HAVE_MESSAGES
5002 MHD_DLOG (daemon,
5003 _ ("Call to epoll_ctl failed: %s\n"),
5005#endif
5006 return MHD_NO;
5007 }
5008 daemon->upgrade_fd_in_epoll = true;
5009 }
5010#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5011 if ( (daemon->listen_socket_in_epoll) &&
5012 ( (daemon->connections == daemon->connection_limit) ||
5013 (daemon->at_limit) ||
5014 (daemon->was_quiesced) ) )
5015 {
5016 /* we're at the connection limit, disable listen socket
5017 for event loop for now */
5018 if (0 != epoll_ctl (daemon->epoll_fd,
5019 EPOLL_CTL_DEL,
5020 ls,
5021 NULL))
5022 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
5023 daemon->listen_socket_in_epoll = false;
5024 }
5025
5026 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
5027 (MHD_NO != resume_suspended_connections (daemon)) )
5028 millisec = 0;
5029
5030 timeout_ms = get_timeout_millisec_ (daemon, millisec);
5031
5032 /* Reset. New value will be set when connections are processed. */
5033 /* Note: Used mostly for uniformity here as same situation is
5034 * signaled in epoll mode by non-empty eready DLL. */
5035 daemon->data_already_pending = false;
5036
5037 need_to_accept = false;
5038 /* drain 'epoll' event queue; need to iterate as we get at most
5039 MAX_EVENTS in one system call here; in practice this should
5040 pretty much mean only one round, but better an extra loop here
5041 than unfair behavior... */
5042 num_events = MAX_EVENTS;
5043 while (MAX_EVENTS == num_events)
5044 {
5045 /* update event masks */
5046 num_events = epoll_wait (daemon->epoll_fd,
5047 events,
5048 MAX_EVENTS,
5049 timeout_ms);
5050 if (-1 == num_events)
5051 {
5052 const int err = MHD_socket_get_error_ ();
5053 if (MHD_SCKT_ERR_IS_EINTR_ (err))
5054 return MHD_YES;
5055#ifdef HAVE_MESSAGES
5056 MHD_DLOG (daemon,
5057 _ ("Call to epoll_wait failed: %s\n"),
5058 MHD_socket_strerr_ (err));
5059#endif
5060 return MHD_NO;
5061 }
5062 for (i = 0; i < (unsigned int) num_events; i++)
5063 {
5064 /* First, check for the values of `ptr` that would indicate
5065 that this event is not about a normal connection. */
5066 if (NULL == events[i].data.ptr)
5067 continue; /* shutdown signal! */
5068#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5069 if (upgrade_marker == events[i].data.ptr)
5070 {
5071 /* activity on an upgraded connection, we process
5072 those in a separate epoll() */
5073 run_upgraded = true;
5074 continue;
5075 }
5076#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5077 if (epoll_itc_marker == events[i].data.ptr)
5078 {
5079 /* It's OK to clear ITC here as all external
5080 conditions will be processed later. */
5081 MHD_itc_clear_ (daemon->itc);
5082 continue;
5083 }
5084 if (daemon == events[i].data.ptr)
5085 {
5086 /* Check for error conditions on listen socket. */
5087 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
5088 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
5089 need_to_accept = true;
5090 continue;
5091 }
5092 /* this is an event relating to a 'normal' connection,
5093 remember the event and if appropriate mark the
5094 connection as 'eready'. */
5095 pos = events[i].data.ptr;
5096 /* normal processing: update read/write data */
5097 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
5098 {
5099 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
5100 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
5101 {
5102 EDLL_insert (daemon->eready_head,
5103 daemon->eready_tail,
5104 pos);
5105 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5106 }
5107 }
5108 else
5109 {
5110 if (0 != (events[i].events & EPOLLIN))
5111 {
5112 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
5113 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
5114 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
5115 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5116 {
5117 EDLL_insert (daemon->eready_head,
5118 daemon->eready_tail,
5119 pos);
5120 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5121 }
5122 }
5123 if (0 != (events[i].events & EPOLLOUT))
5124 {
5125 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
5127 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
5128 {
5129 EDLL_insert (daemon->eready_head,
5130 daemon->eready_tail,
5131 pos);
5132 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
5133 }
5134 }
5135 }
5136 }
5137 }
5138
5139 /* Process externally added connection if any */
5140 if (daemon->have_new)
5142
5143 if (need_to_accept)
5144 {
5145 unsigned int series_length = 0;
5146
5147 /* Run 'accept' until it fails or daemon at limit of connections.
5148 * Do not accept more then 10 connections at once. The rest will
5149 * be accepted on next turn (level trigger is used for listen
5150 * socket). */
5151 while ( (MHD_NO != MHD_accept_connection (daemon)) &&
5152 (series_length < 10) &&
5153 (daemon->connections < daemon->connection_limit) &&
5154 (! daemon->at_limit) )
5155 series_length++;
5156 }
5157
5158 /* Handle timed-out connections; we need to do this here
5159 as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
5160 as the other event loops do. As timeouts do not get an explicit
5161 event, we need to find those connections that might have timed out
5162 here.
5163
5164 Connections with custom timeouts must all be looked at, as we
5165 do not bother to sort that (presumably very short) list. */
5166 prev = daemon->manual_timeout_tail;
5167 while (NULL != (pos = prev))
5168 {
5169 prev = pos->prevX;
5171 }
5172 /* Connections with the default timeout are sorted by prepending
5173 them to the head of the list whenever we touch the connection;
5174 thus it suffices to iterate from the tail until the first
5175 connection is NOT timed out */
5176 prev = daemon->normal_timeout_tail;
5177 while (NULL != (pos = prev))
5178 {
5179 prev = pos->prevX;
5181 if (MHD_CONNECTION_CLOSED != pos->state)
5182 break; /* sorted by timeout, no need to visit the rest! */
5183 }
5184
5185#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5186 if (run_upgraded || (NULL != daemon->eready_urh_head))
5187 run_epoll_for_upgrade (daemon);
5188#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5189
5190 /* process events for connections */
5191 prev = daemon->eready_tail;
5192 while (NULL != (pos = prev))
5193 {
5194 prev = pos->prevE;
5195 call_handlers (pos,
5196 0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
5197 0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
5198 0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
5200 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
5202 {
5203 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
5204 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
5206 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
5208 {
5209 EDLL_remove (daemon->eready_head,
5210 daemon->eready_tail,
5211 pos);
5212 pos->epoll_state &=
5214 }
5215 }
5216 }
5217
5218 return MHD_YES;
5219}
5220
5221
5222#endif
5223
5224
5252enum MHD_Result
5253MHD_run (struct MHD_Daemon *daemon)
5254{
5255 if ( (daemon->shutdown) ||
5256 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5257 return MHD_NO;
5258
5259 (void) MHD_run_wait (daemon, 0);
5260 return MHD_YES;
5261}
5262
5263
5303MHD_run_wait (struct MHD_Daemon *daemon,
5304 int32_t millisec)
5305{
5306 enum MHD_Result res;
5307 if ( (daemon->shutdown) ||
5308 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5309 return MHD_NO;
5310
5311 if (0 > millisec)
5312 millisec = -1;
5313 if (false)
5314 {
5315 (void) 0; /* Mute compiler warning */
5316 }
5317#ifdef HAVE_POLL
5318 else if (0 != (daemon->options & MHD_USE_POLL))
5319 {
5320 res = MHD_poll_all (daemon, millisec);
5321 MHD_cleanup_connections (daemon);
5322 }
5323#endif /* HAVE_POLL */
5324#ifdef EPOLL_SUPPORT
5325 else if (0 != (daemon->options & MHD_USE_EPOLL))
5326 {
5327 res = MHD_epoll (daemon, millisec);
5328 MHD_cleanup_connections (daemon);
5329 }
5330#endif
5331 else
5332 {
5333 res = MHD_select (daemon, millisec);
5334 /* MHD_select does MHD_cleanup_connections already */
5335 }
5336 return res;
5337}
5338
5339
5348static void
5350{
5351 struct MHD_Daemon *daemon = pos->daemon;
5352
5353#ifdef MHD_USE_THREADS
5354 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
5355 MHD_thread_ID_match_current_ (daemon->pid) );
5356#endif /* MHD_USE_THREADS */
5357
5358 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5359 {
5361 return; /* must let thread to do the rest */
5362 }
5365#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5367#endif
5368 mhd_assert (! pos->suspended);
5369 mhd_assert (! pos->resuming);
5370 if (pos->connection_timeout_ms == daemon->connection_timeout_ms)
5372 daemon->normal_timeout_tail,
5373 pos);
5374 else
5376 daemon->manual_timeout_tail,
5377 pos);
5379 daemon->connections_tail,
5380 pos);
5381 DLL_insert (daemon->cleanup_head,
5382 daemon->cleanup_tail,
5383 pos);
5384 daemon->data_already_pending = true;
5385#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5387#endif
5388}
5389
5390
5391#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5399static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
5400MHD_polling_thread (void *cls)
5401{
5402 struct MHD_Daemon *daemon = cls;
5403#ifdef HAVE_PTHREAD_SIGMASK
5404 sigset_t s_mask;
5405 int err;
5406#endif /* HAVE_PTHREAD_SIGMASK */
5407
5408 MHD_thread_init_ (&(daemon->pid));
5409#ifdef HAVE_PTHREAD_SIGMASK
5410 if ((0 == sigemptyset (&s_mask)) &&
5411 (0 == sigaddset (&s_mask, SIGPIPE)))
5412 {
5413 err = pthread_sigmask (SIG_BLOCK, &s_mask, NULL);
5414 }
5415 else
5416 err = errno;
5417 if (0 == err)
5418 daemon->sigpipe_blocked = true;
5419#ifdef HAVE_MESSAGES
5420 else
5421 MHD_DLOG (daemon,
5422 _ ("Failed to block SIGPIPE on daemon thread: %s\n"),
5423 MHD_strerror_ (errno));
5424#endif /* HAVE_MESSAGES */
5425#endif /* HAVE_PTHREAD_SIGMASK */
5426 while (! daemon->shutdown)
5427 {
5428 if (0 != (daemon->options & MHD_USE_POLL))
5429 MHD_poll (daemon, MHD_YES);
5430#ifdef EPOLL_SUPPORT
5431 else if (0 != (daemon->options & MHD_USE_EPOLL))
5432 MHD_epoll (daemon, -1);
5433#endif
5434 else
5435 MHD_select (daemon, -1);
5436 MHD_cleanup_connections (daemon);
5437 }
5438
5439 /* Resume any pending for resume connections, join
5440 * all connection's threads (if any) and finally cleanup
5441 * everything. */
5442 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
5444 close_all_connections (daemon);
5445
5446 return (MHD_THRD_RTRN_TYPE_) 0;
5447}
5448
5449
5450#endif
5451
5452
5464static size_t
5466 struct MHD_Connection *connection,
5467 char *val)
5468{
5469 (void) cls; /* Mute compiler warning. */
5470
5471 (void) connection; /* Mute compiler warning. */
5472 return MHD_http_unescape (val);
5473}
5474
5475
5496struct MHD_Daemon *
5497MHD_start_daemon (unsigned int flags,
5498 uint16_t port,
5500 void *apc_cls,
5502 void *dh_cls,
5503 ...)
5504{
5505 struct MHD_Daemon *daemon;
5506 va_list ap;
5507
5508 va_start (ap,
5509 dh_cls);
5510 daemon = MHD_start_daemon_va (flags,
5511 port,
5512 apc,
5513 apc_cls,
5514 dh,
5515 dh_cls,
5516 ap);
5517 va_end (ap);
5518 return daemon;
5519}
5520
5521
5543{
5544#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5545 unsigned int i;
5546#endif
5547 MHD_socket ret;
5548
5549 ret = daemon->listen_fd;
5550 if (MHD_INVALID_SOCKET == ret)
5551 return MHD_INVALID_SOCKET;
5552 if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
5553 (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
5554 {
5555#ifdef HAVE_MESSAGES
5556 MHD_DLOG (daemon,
5557 _ (
5558 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n"));
5559#endif
5560 return MHD_INVALID_SOCKET;
5561 }
5562
5563#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5564 if (NULL != daemon->worker_pool)
5565 for (i = 0; i < daemon->worker_pool_size; i++)
5566 {
5567 daemon->worker_pool[i].was_quiesced = true;
5568#ifdef EPOLL_SUPPORT
5569 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5570 (-1 != daemon->worker_pool[i].epoll_fd) &&
5571 (daemon->worker_pool[i].listen_socket_in_epoll) )
5572 {
5573 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
5574 EPOLL_CTL_DEL,
5575 ret,
5576 NULL))
5577 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
5578 daemon->worker_pool[i].listen_socket_in_epoll = false;
5579 }
5580 else
5581#endif
5582 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
5583 {
5584 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
5585 MHD_PANIC (_ (
5586 "Failed to signal quiesce via inter-thread communication channel.\n"));
5587 }
5588 }
5589#endif
5590 daemon->was_quiesced = true;
5591#ifdef EPOLL_SUPPORT
5592 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5593 (-1 != daemon->epoll_fd) &&
5594 (daemon->listen_socket_in_epoll) )
5595 {
5596 if ( (0 != epoll_ctl (daemon->epoll_fd,
5597 EPOLL_CTL_DEL,
5598 ret,
5599 NULL)) &&
5600 (ENOENT != errno) ) /* ENOENT can happen due to race with
5601 #MHD_epoll() */
5602 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
5603 daemon->listen_socket_in_epoll = false;
5604 }
5605#endif
5606 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
5607 (! MHD_itc_activate_ (daemon->itc, "q")) )
5608 MHD_PANIC (_ (
5609 "failed to signal quiesce via inter-thread communication channel.\n"));
5610 return ret;
5611}
5612
5613
5621typedef void
5622(*VfprintfFunctionPointerType)(void *cls,
5623 const char *format,
5624 va_list va);
5625
5626
5635static enum MHD_Result
5636parse_options_va (struct MHD_Daemon *daemon,
5637 const struct sockaddr **servaddr,
5638 va_list ap);
5639
5640
5649static enum MHD_Result
5651 const struct sockaddr **servaddr,
5652 ...)
5653{
5654 va_list ap;
5655 enum MHD_Result ret;
5656
5657 va_start (ap, servaddr);
5658 ret = parse_options_va (daemon,
5659 servaddr,
5660 ap);
5661 va_end (ap);
5662 return ret;
5663}
5664
5665
5674static enum MHD_Result
5676 const struct sockaddr **servaddr,
5677 va_list ap)
5678{
5679 enum MHD_OPTION opt;
5680 struct MHD_OptionItem *oa;
5681 unsigned int i;
5682 unsigned int uv;
5683#ifdef HTTPS_SUPPORT
5684 const char *pstr;
5685#if GNUTLS_VERSION_MAJOR >= 3
5686 gnutls_certificate_retrieve_function2 *pgcrf;
5687#endif
5688#if GNUTLS_VERSION_NUMBER >= 0x030603
5689 gnutls_certificate_retrieve_function3 *pgcrf2;
5690#endif
5691#endif /* HTTPS_SUPPORT */
5692
5693 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
5694 {
5695 /* Increase counter at start, so resulting value is number of
5696 * processed options, including any failed ones. */
5697 daemon->num_opts++;
5698 switch (opt)
5699 {
5701 daemon->pool_size = va_arg (ap,
5702 size_t);
5703 break;
5705 daemon->pool_increment = va_arg (ap,
5706 size_t);
5707 break;
5709 daemon->connection_limit = va_arg (ap,
5710 unsigned int);
5711 break;
5713 uv = va_arg (ap,
5714 unsigned int);
5715#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
5716 if ((UINT64_MAX / 4000 - 1) < uv)
5717 {
5718#ifdef HAVE_MESSAGES
5719 MHD_DLOG (daemon,
5720 _ ("The specified connection timeout (%u) is too large. " \
5721 "Maximum allowed value (%" PRIu64 ") will be used " \
5722 "instead.\n"),
5723 uv,
5724 (UINT64_MAX / 4000 - 1));
5725#endif
5726 uv = UINT64_MAX / 4000 - 1;
5727 }
5728#endif /* (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT */
5729 daemon->connection_timeout_ms = uv * 1000;
5730 break;
5732 daemon->notify_completed = va_arg (ap,
5734 daemon->notify_completed_cls = va_arg (ap,
5735 void *);
5736 break;
5738 daemon->notify_connection = va_arg (ap,
5740 daemon->notify_connection_cls = va_arg (ap,
5741 void *);
5742 break;
5744 daemon->per_ip_connection_limit = va_arg (ap,
5745 unsigned int);
5746 break;
5748 *servaddr = va_arg (ap,
5749 const struct sockaddr *);
5750 break;
5752 daemon->uri_log_callback = va_arg (ap,
5753 LogCallback);
5754 daemon->uri_log_callback_cls = va_arg (ap,
5755 void *);
5756 break;
5758 daemon->insanity_level = (enum MHD_DisableSanityCheck)
5759 va_arg (ap,
5760 unsigned int);
5761 break;
5762#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5764 daemon->worker_pool_size = va_arg (ap,
5765 unsigned int);
5766 if (0 == daemon->worker_pool_size)
5767 {
5768#ifdef HAVE_MESSAGES
5769 MHD_DLOG (daemon,
5770 _ (
5771 "Warning: Zero size, specified for thread pool size, is ignored. "
5772 "Thread pool is not used.\n"));
5773#endif
5774 }
5775 else if (1 == daemon->worker_pool_size)
5776 {
5777#ifdef HAVE_MESSAGES
5778 MHD_DLOG (daemon,
5779 _ (
5780 "Warning: \"1\", specified for thread pool size, is ignored. "
5781 "Thread pool is not used.\n"));
5782#endif
5783 daemon->worker_pool_size = 0;
5784 }
5785#if SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2)
5786 /* Next comparison could be always false on some platforms and whole branch will
5787 * be optimized out on these platforms. On others it will be compiled into real
5788 * check. */
5789 else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct
5790 MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
5791 {
5792#ifdef HAVE_MESSAGES
5793 MHD_DLOG (daemon,
5794 _ ("Specified thread pool size (%u) too big.\n"),
5795 daemon->worker_pool_size);
5796#endif
5797 return MHD_NO;
5798 }
5799#endif /* SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2) */
5800 else
5801 {
5802 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
5803 {
5804#ifdef HAVE_MESSAGES
5805 MHD_DLOG (daemon,
5806 _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5807 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5808#endif
5809 return MHD_NO;
5810 }
5811 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5812 {
5813#ifdef HAVE_MESSAGES
5814 MHD_DLOG (daemon,
5815 _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
5816 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5817#endif
5818 return MHD_NO;
5819 }
5820 }
5821 break;
5822#endif
5823#ifdef HTTPS_SUPPORT
5825 pstr = va_arg (ap,
5826 const char *);
5827 if (0 != (daemon->options & MHD_USE_TLS))
5828 daemon->https_mem_key = pstr;
5829#ifdef HAVE_MESSAGES
5830 else
5831 MHD_DLOG (daemon,
5832 _ (
5833 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5834 opt);
5835#endif
5836 break;
5838 pstr = va_arg (ap,
5839 const char *);
5840 if (0 != (daemon->options & MHD_USE_TLS))
5841 daemon->https_key_password = pstr;
5842#ifdef HAVE_MESSAGES
5843 else
5844 MHD_DLOG (daemon,
5845 _ (
5846 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5847 opt);
5848#endif
5849 break;
5851 pstr = va_arg (ap,
5852 const char *);
5853 if (0 != (daemon->options & MHD_USE_TLS))
5854 daemon->https_mem_cert = pstr;
5855#ifdef HAVE_MESSAGES
5856 else
5857 MHD_DLOG (daemon,
5858 _ (
5859 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5860 opt);
5861#endif
5862 break;
5864 pstr = va_arg (ap,
5865 const char *);
5866 if (0 != (daemon->options & MHD_USE_TLS))
5867 daemon->https_mem_trust = pstr;
5868#ifdef HAVE_MESSAGES
5869 else
5870 MHD_DLOG (daemon,
5871 _ (
5872 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5873 opt);
5874#endif
5875 break;
5877 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5878 int);
5879 break;
5881 pstr = va_arg (ap,
5882 const char *);
5883 if (0 != (daemon->options & MHD_USE_TLS))
5884 {
5885 gnutls_datum_t dhpar;
5886 size_t pstr_len;
5887
5888 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5889 {
5890#ifdef HAVE_MESSAGES
5891 MHD_DLOG (daemon,
5892 _ ("Error initializing DH parameters.\n"));
5893#endif
5894 return MHD_NO;
5895 }
5896 dhpar.data = (unsigned char *) pstr;
5897 pstr_len = strlen (pstr);
5898 if (UINT_MAX < pstr_len)
5899 {
5900#ifdef HAVE_MESSAGES
5901 MHD_DLOG (daemon,
5902 _ ("Diffie-Hellman parameters string too long.\n"));
5903#endif
5904 return MHD_NO;
5905 }
5906 dhpar.size = (unsigned int) pstr_len;
5907 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5908 &dhpar,
5909 GNUTLS_X509_FMT_PEM) < 0)
5910 {
5911#ifdef HAVE_MESSAGES
5912 MHD_DLOG (daemon,
5913 _ ("Bad Diffie-Hellman parameters format.\n"));
5914#endif
5915 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5916 return MHD_NO;
5917 }
5918 daemon->have_dhparams = true;
5919 }
5920#ifdef HAVE_MESSAGES
5921 else
5922 MHD_DLOG (daemon,
5923 _ (
5924 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5925 opt);
5926#endif
5927 break;
5929 pstr = va_arg (ap,
5930 const char *);
5931 if (0 != (daemon->options & MHD_USE_TLS))
5932 {
5933 int init_res;
5934 gnutls_priority_deinit (daemon->priority_cache);
5935 init_res = gnutls_priority_init (&daemon->priority_cache,
5936 pstr,
5937 NULL);
5938 if (GNUTLS_E_SUCCESS != init_res)
5939 {
5940#ifdef HAVE_MESSAGES
5941 MHD_DLOG (daemon,
5942 _ ("Setting priorities to `%s' failed: %s\n"),
5943 pstr,
5944 gnutls_strerror (init_res));
5945#endif
5946 daemon->priority_cache = NULL;
5947 return MHD_NO;
5948 }
5949 }
5950#ifdef HAVE_MESSAGES
5951 else
5952 MHD_DLOG (daemon,
5953 _ (
5954 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5955 opt);
5956#endif
5957 break;
5959#if GNUTLS_VERSION_MAJOR < 3
5960#ifdef HAVE_MESSAGES
5961 MHD_DLOG (daemon,
5962 _ (
5963 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5964#endif
5965 return MHD_NO;
5966#else
5967 pgcrf = va_arg (ap,
5968 gnutls_certificate_retrieve_function2 *);
5969 if (0 != (daemon->options & MHD_USE_TLS))
5970 daemon->cert_callback = pgcrf;
5971#ifdef HAVE_MESSAGES
5972 else
5973 MHD_DLOG (daemon,
5974 _ (
5975 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5976 opt);
5977#endif /* HAVE_MESSAGES */
5978 break;
5979#endif
5981#if GNUTLS_VERSION_NUMBER < 0x030603
5982#ifdef HAVE_MESSAGES
5983 MHD_DLOG (daemon,
5984 _ (
5985 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5986#endif
5987 return MHD_NO;
5988#else
5989 pgcrf2 = va_arg (ap,
5990 gnutls_certificate_retrieve_function3 *);
5991 if (0 != (daemon->options & MHD_USE_TLS))
5992 daemon->cert_callback2 = pgcrf2;
5993#ifdef HAVE_MESSAGES
5994 else
5995 MHD_DLOG (daemon,
5996 _ (
5997 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5998 opt);
5999#endif /* HAVE_MESSAGES */
6000 break;
6001#endif
6002#endif /* HTTPS_SUPPORT */
6003#ifdef DAUTH_SUPPORT
6005 daemon->digest_auth_rand_size = va_arg (ap,
6006 size_t);
6007 daemon->digest_auth_random = va_arg (ap,
6008 const char *);
6009 break;
6011 daemon->nonce_nc_size = va_arg (ap,
6012 unsigned int);
6013 break;
6014#endif
6016 if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
6017 {
6018#ifdef HAVE_MESSAGES
6019 MHD_DLOG (daemon,
6020 _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
6021 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
6022#endif
6023 return MHD_NO;
6024 }
6025 else
6026 {
6027 daemon->listen_fd = va_arg (ap,
6028 MHD_socket);
6029#if defined(SO_DOMAIN) && defined(AF_UNIX)
6030 {
6031 int af;
6032 socklen_t len = sizeof (af);
6033
6034 if (0 == getsockopt (daemon->listen_fd,
6035 SOL_SOCKET,
6036 SO_DOMAIN,
6037 &af,
6038 &len))
6039 {
6040 daemon->listen_is_unix = (AF_UNIX == af) ? _MHD_YES : _MHD_NO;
6041 }
6042 else
6043 daemon->listen_is_unix = _MHD_UNKNOWN;
6044 }
6045#else /* ! SO_DOMAIN || ! AF_UNIX */
6046 daemon->listen_is_unix = _MHD_UNKNOWN;
6047#endif /* ! SO_DOMAIN || ! AF_UNIX */
6048 }
6049 break;
6051#ifdef HAVE_MESSAGES
6052 daemon->custom_error_log = va_arg (ap,
6054 daemon->custom_error_log_cls = va_arg (ap,
6055 void *);
6056 if (1 != daemon->num_opts)
6057 MHD_DLOG (daemon,
6058 _ ("MHD_OPTION_EXTERNAL_LOGGER is not the first option "
6059 "specified for the daemon. Some messages may be "
6060 "printed by the standard MHD logger.\n"));
6061
6062#else
6063 va_arg (ap,
6065 va_arg (ap,
6066 void *);
6067#endif
6068 break;
6069#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6071 daemon->thread_stack_size = va_arg (ap,
6072 size_t);
6073 break;
6074#endif
6076#ifdef TCP_FASTOPEN
6077 daemon->fastopen_queue_size = va_arg (ap,
6078 unsigned int);
6079 break;
6080#else /* ! TCP_FASTOPEN */
6081#ifdef HAVE_MESSAGES
6082 MHD_DLOG (daemon,
6083 _ ("TCP fastopen is not supported on this platform.\n"));
6084#endif /* HAVE_MESSAGES */
6085 return MHD_NO;
6086#endif /* ! TCP_FASTOPEN */
6088 daemon->listening_address_reuse = va_arg (ap,
6089 unsigned int) ? 1 : -1;
6090 break;
6092 daemon->listen_backlog_size = va_arg (ap,
6093 unsigned int);
6094 break;
6096 daemon->strict_for_client = va_arg (ap, int);
6097#ifdef HAVE_MESSAGES
6098 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
6099 (1 != daemon->strict_for_client) )
6100 {
6101 MHD_DLOG (daemon,
6102 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
6103 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
6104 }
6105#endif /* HAVE_MESSAGES */
6106 break;
6107 case MHD_OPTION_ARRAY:
6108 daemon->num_opts--; /* Do not count MHD_OPTION_ARRAY */
6109 oa = va_arg (ap, struct MHD_OptionItem *);
6110 i = 0;
6111 while (MHD_OPTION_END != (opt = oa[i].option))
6112 {
6113 switch (opt)
6114 {
6115 /* all options taking 'size_t' */
6119 if (MHD_NO == parse_options (daemon,
6120 servaddr,
6121 opt,
6122 (size_t) oa[i].value,
6124 return MHD_NO;
6125 break;
6126 /* all options taking 'unsigned int' */
6136 if (MHD_NO == parse_options (daemon,
6137 servaddr,
6138 opt,
6139 (unsigned int) oa[i].value,
6141 return MHD_NO;
6142 break;
6143 /* all options taking 'enum' */
6144#ifdef HTTPS_SUPPORT
6146 if (MHD_NO == parse_options (daemon,
6147 servaddr,
6148 opt,
6149 (gnutls_credentials_type_t) oa[i].value,
6151 return MHD_NO;
6152 break;
6153#endif /* HTTPS_SUPPORT */
6154 /* all options taking 'MHD_socket' */
6156 if (MHD_NO == parse_options (daemon,
6157 servaddr,
6158 opt,
6159 (MHD_socket) oa[i].value,
6161 return MHD_NO;
6162 break;
6163 /* all options taking 'int' */
6167 if (MHD_NO == parse_options (daemon,
6168 servaddr,
6169 opt,
6170 (int) oa[i].value,
6172 return MHD_NO;
6173 break;
6174 /* all options taking one pointer */
6182 case MHD_OPTION_ARRAY:
6185 if (MHD_NO == parse_options (daemon,
6186 servaddr,
6187 opt,
6188 oa[i].ptr_value,
6190 return MHD_NO;
6191 break;
6192 /* all options taking two pointers */
6199 if (MHD_NO == parse_options (daemon,
6200 servaddr,
6201 opt,
6202 (void *) oa[i].value,
6203 oa[i].ptr_value,
6205 return MHD_NO;
6206 break;
6207 /* options taking size_t-number followed by pointer */
6209 if (MHD_NO == parse_options (daemon,
6210 servaddr,
6211 opt,
6212 (size_t) oa[i].value,
6213 oa[i].ptr_value,
6215 return MHD_NO;
6216 break;
6217 default:
6218 return MHD_NO;
6219 }
6220 i++;
6221 }
6222 break;
6224 daemon->unescape_callback = va_arg (ap,
6226 daemon->unescape_callback_cls = va_arg (ap,
6227 void *);
6228 break;
6229#ifdef HTTPS_SUPPORT
6231#if GNUTLS_VERSION_MAJOR >= 3
6232 daemon->cred_callback = va_arg (ap,
6234 daemon->cred_callback_cls = va_arg (ap,
6235 void *);
6236 break;
6237#else
6238 MHD_DLOG (daemon,
6239 _ (
6240 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
6241 opt);
6242 return MHD_NO;
6243#endif
6244#endif /* HTTPS_SUPPORT */
6246 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6247 daemon->sigpipe_blocked = ( (va_arg (ap,
6248 int)) != 0);
6249 else
6250 {
6251 (void) va_arg (ap,
6252 int);
6253 }
6254 break;
6256#ifdef HTTPS_SUPPORT
6257 daemon->disable_alpn = (va_arg (ap,
6258 int) != 0);
6259#else /* ! HTTPS_SUPPORT */
6260 (void) va_arg (ap, int);
6261#endif /* ! HTTPS_SUPPORT */
6262#ifdef HAVE_MESSAGES
6263 if (0 == (daemon->options & MHD_USE_TLS))
6264 MHD_DLOG (daemon,
6265 _ ("MHD HTTPS option %d passed to MHD " \
6266 "but MHD_USE_TLS not set.\n"),
6267 (int) opt);
6268#endif /* HAVE_MESSAGES */
6269 break;
6270 default:
6271#ifdef HAVE_MESSAGES
6272 if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
6273 (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
6274 (opt == MHD_OPTION_HTTPS_MEM_TRUST) ||
6276 {
6277 MHD_DLOG (daemon,
6278 _ (
6279 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
6280 opt);
6281 }
6282 else
6283 {
6284 MHD_DLOG (daemon,
6285 _ (
6286 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
6287 opt);
6288 }
6289#endif
6290 return MHD_NO;
6291 }
6292 }
6293 return MHD_YES;
6294}
6295
6296
6297#ifdef EPOLL_SUPPORT
6298static int
6299setup_epoll_fd (struct MHD_Daemon *daemon)
6300{
6301 int fd;
6302
6303#ifndef HAVE_MESSAGES
6304 (void) daemon; /* Mute compiler warning. */
6305#endif /* ! HAVE_MESSAGES */
6306
6307#ifdef USE_EPOLL_CREATE1
6308 fd = epoll_create1 (EPOLL_CLOEXEC);
6309#else /* ! USE_EPOLL_CREATE1 */
6310 fd = epoll_create (MAX_EVENTS);
6311#endif /* ! USE_EPOLL_CREATE1 */
6312 if (MHD_INVALID_SOCKET == fd)
6313 {
6314#ifdef HAVE_MESSAGES
6315 MHD_DLOG (daemon,
6316 _ ("Call to epoll_create1 failed: %s\n"),
6318#endif
6319 return MHD_INVALID_SOCKET;
6320 }
6321#if ! defined(USE_EPOLL_CREATE1)
6323 {
6324#ifdef HAVE_MESSAGES
6325 MHD_DLOG (daemon,
6326 _ ("Failed to set noninheritable mode on epoll FD.\n"));
6327#endif
6328 }
6329#endif /* ! USE_EPOLL_CREATE1 */
6330 return fd;
6331}
6332
6333
6342static enum MHD_Result
6343setup_epoll_to_listen (struct MHD_Daemon *daemon)
6344{
6345 struct epoll_event event;
6346 MHD_socket ls;
6347
6348 mhd_assert (0 != (daemon->options & MHD_USE_EPOLL));
6350 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
6351 (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) || \
6352 MHD_ITC_IS_VALID_ (daemon->itc) );
6353 daemon->epoll_fd = setup_epoll_fd (daemon);
6354 if (-1 == daemon->epoll_fd)
6355 return MHD_NO;
6356#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6357 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
6358 {
6359 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
6360 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
6361 return MHD_NO;
6362 }
6363#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6364 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
6365 (! daemon->was_quiesced) )
6366 {
6367 event.events = EPOLLIN;
6368 event.data.ptr = daemon;
6369 if (0 != epoll_ctl (daemon->epoll_fd,
6370 EPOLL_CTL_ADD,
6371 ls,
6372 &event))
6373 {
6374#ifdef HAVE_MESSAGES
6375 MHD_DLOG (daemon,
6376 _ ("Call to epoll_ctl failed: %s\n"),
6378#endif
6379 return MHD_NO;
6380 }
6381 daemon->listen_socket_in_epoll = true;
6382 }
6383
6384 if (MHD_ITC_IS_VALID_ (daemon->itc))
6385 {
6386 event.events = EPOLLIN;
6387 event.data.ptr = (void *) epoll_itc_marker;
6388 if (0 != epoll_ctl (daemon->epoll_fd,
6389 EPOLL_CTL_ADD,
6390 MHD_itc_r_fd_ (daemon->itc),
6391 &event))
6392 {
6393#ifdef HAVE_MESSAGES
6394 MHD_DLOG (daemon,
6395 _ ("Call to epoll_ctl failed: %s\n"),
6397#endif
6398 return MHD_NO;
6399 }
6400 }
6401 return MHD_YES;
6402}
6403
6404
6405#endif
6406
6407
6429struct MHD_Daemon *
6430MHD_start_daemon_va (unsigned int flags,
6431 uint16_t port,
6433 void *apc_cls,
6435 void *dh_cls,
6436 va_list ap)
6437{
6438 const MHD_SCKT_OPT_BOOL_ on = 1;
6439 struct MHD_Daemon *daemon;
6441 struct sockaddr_in servaddr4;
6442#if HAVE_INET6
6443 struct sockaddr_in6 servaddr6;
6444#endif
6445 const struct sockaddr *servaddr = NULL;
6446 socklen_t addrlen;
6447#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6448 unsigned int i;
6449#endif
6450 enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
6451 enum MHD_FLAG *pflags;
6452
6454 eflags = (enum MHD_FLAG) flags;
6455 pflags = &eflags;
6456#ifndef HAVE_INET6
6457 if (0 != (*pflags & MHD_USE_IPv6))
6458 return NULL;
6459#endif
6460#ifndef HAVE_POLL
6461 if (0 != (*pflags & MHD_USE_POLL))
6462 return NULL;
6463#endif
6464#ifndef EPOLL_SUPPORT
6465 if (0 != (*pflags & MHD_USE_EPOLL))
6466 return NULL;
6467#endif /* ! EPOLL_SUPPORT */
6468#ifndef HTTPS_SUPPORT
6469 if (0 != (*pflags & MHD_USE_TLS))
6470 return NULL;
6471#endif /* ! HTTPS_SUPPORT */
6472#ifndef TCP_FASTOPEN
6473 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6474 return NULL;
6475#endif
6476 if (0 != (*pflags & MHD_ALLOW_UPGRADE))
6477 {
6478#ifdef UPGRADE_SUPPORT
6479 *pflags |= MHD_ALLOW_SUSPEND_RESUME;
6480#else /* ! UPGRADE_SUPPORT */
6481 return NULL;
6482#endif /* ! UPGRADE_SUPPORT */
6483 }
6484 if (NULL == dh)
6485 return NULL;
6486
6487 /* Check for invalid combinations of flags. */
6488 if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
6489 ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags
6490 &
6492 ||
6493 ((0 != (*pflags & MHD_USE_POLL)) &&
6494 (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
6496 ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL
6497 | MHD_USE_EPOLL)))) )
6498 return NULL;
6499
6500 if (0 != (*pflags & MHD_USE_AUTO))
6501 {
6502 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6503 {
6504 /* Thread per connection with internal polling thread. */
6505#ifdef HAVE_POLL
6506 *pflags |= MHD_USE_POLL;
6507#else /* ! HAVE_POLL */
6508 /* use select() - do not modify flags */
6509#endif /* ! HAVE_POLL */
6510 }
6511 else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
6512 {
6513 /* Internal polling thread. */
6514#if defined(EPOLL_SUPPORT)
6515 *pflags |= MHD_USE_EPOLL;
6516#elif defined(HAVE_POLL)
6517 *pflags |= MHD_USE_POLL;
6518#else /* !HAVE_POLL && !EPOLL_SUPPORT */
6519 /* use select() - do not modify flags */
6520#endif /* !HAVE_POLL && !EPOLL_SUPPORT */
6521 }
6522 else
6523 {
6524 /* Internal threads are not used - "external" polling mode. */
6525#if defined(EPOLL_SUPPORT)
6526 *pflags |= MHD_USE_EPOLL;
6527#else /* ! EPOLL_SUPPORT */
6528 /* use select() - do not modify flags */
6529#endif /* ! EPOLL_SUPPORT */
6530 }
6531 }
6532
6533 if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
6534 return NULL;
6535#ifdef EPOLL_SUPPORT
6536 daemon->epoll_fd = -1;
6537#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6538 daemon->epoll_upgrade_fd = -1;
6539#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6540#endif
6541 /* try to open listen socket */
6542#ifdef HTTPS_SUPPORT
6543 daemon->priority_cache = NULL;
6544 if (0 != (*pflags & MHD_USE_TLS))
6545 {
6546 gnutls_priority_init (&daemon->priority_cache,
6547 "@SYSTEM",
6548 NULL);
6549 }
6550#endif /* HTTPS_SUPPORT */
6551 daemon->listen_fd = MHD_INVALID_SOCKET;
6552 daemon->listen_is_unix = _MHD_NO;
6553 daemon->listening_address_reuse = 0;
6554 daemon->options = *pflags;
6555 pflags = &daemon->options;
6556 daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 :
6557 0;
6558 daemon->port = port;
6559 daemon->apc = apc;
6560 daemon->apc_cls = apc_cls;
6561 daemon->default_handler = dh;
6562 daemon->default_handler_cls = dh_cls;
6563 daemon->connections = 0;
6568 daemon->connection_timeout_ms = 0; /* no timeout */
6569 MHD_itc_set_invalid_ (daemon->itc);
6570#ifdef SOMAXCONN
6571 daemon->listen_backlog_size = SOMAXCONN;
6572#else /* !SOMAXCONN */
6573 daemon->listen_backlog_size = 511; /* should be safe value */
6574#endif /* !SOMAXCONN */
6575#ifdef HAVE_MESSAGES
6576 daemon->custom_error_log = &MHD_default_logger_;
6577 daemon->custom_error_log_cls = stderr;
6578#endif
6579#ifndef MHD_WINSOCK_SOCKETS
6580 daemon->sigpipe_blocked = false;
6581#else /* MHD_WINSOCK_SOCKETS */
6582 /* There is no SIGPIPE on W32, nothing to block. */
6583 daemon->sigpipe_blocked = true;
6584#endif /* _WIN32 && ! __CYGWIN__ */
6585
6586 if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
6587 (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
6588 {
6589 /* Log warning message later, when log parameters are processes */
6591 }
6592 if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
6593 *pflags = (*pflags & ~((enum MHD_FLAG) MHD_USE_ITC)); /* useless if we are using 'external' select */
6594 else
6595 {
6596#ifdef HAVE_LISTEN_SHUTDOWN
6597 if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
6598#endif
6599 *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
6600 }
6601#ifdef DAUTH_SUPPORT
6602 daemon->digest_auth_rand_size = 0;
6603 daemon->digest_auth_random = NULL;
6604 daemon->nonce_nc_size = 4; /* tiny */
6605#endif
6606#ifdef HTTPS_SUPPORT
6607 if (0 != (*pflags & MHD_USE_TLS))
6608 {
6609 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
6610 }
6611#endif /* HTTPS_SUPPORT */
6612
6613
6614 if (MHD_NO == parse_options_va (daemon,
6615 &servaddr,
6616 ap))
6617 {
6618#ifdef HTTPS_SUPPORT
6619 if ( (0 != (*pflags & MHD_USE_TLS)) &&
6620 (NULL != daemon->priority_cache) )
6621 gnutls_priority_deinit (daemon->priority_cache);
6622#endif /* HTTPS_SUPPORT */
6623 free (daemon);
6624 return NULL;
6625 }
6626
6627#ifdef HAVE_MESSAGES
6628 if ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) &&
6629 (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD)) )
6630 {
6631 MHD_DLOG (daemon,
6632 _ (
6633 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
6634 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
6635 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
6636 }
6637#endif
6638
6639 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
6640 && ((NULL != daemon->notify_completed)
6641 || (NULL != daemon->notify_connection)) )
6642 *pflags |= MHD_USE_ITC; /* requires ITC */
6643
6644#ifndef NDEBUG
6645#ifdef HAVE_MESSAGES
6646 MHD_DLOG (daemon,
6647 _ ("Using debug build of libmicrohttpd.\n") );
6648#endif /* HAVE_MESSAGES */
6649#endif /* ! NDEBUG */
6650
6651 if ( (0 != (*pflags & MHD_USE_ITC))
6652#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6653 && (0 == daemon->worker_pool_size)
6654#endif
6655 )
6656 {
6657 if (! MHD_itc_init_ (daemon->itc))
6658 {
6659#ifdef HAVE_MESSAGES
6660 MHD_DLOG (daemon,
6661 _ ("Failed to create inter-thread communication channel: %s\n"),
6662 MHD_itc_last_strerror_ ());
6663#endif
6664#ifdef HTTPS_SUPPORT
6665 if (NULL != daemon->priority_cache)
6666 gnutls_priority_deinit (daemon->priority_cache);
6667#endif /* HTTPS_SUPPORT */
6668 free (daemon);
6669 return NULL;
6670 }
6671 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6672 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
6673 NULL)) )
6674 {
6675#ifdef HAVE_MESSAGES
6676 MHD_DLOG (daemon,
6677 _ (
6678 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
6679#endif
6680 MHD_itc_destroy_chk_ (daemon->itc);
6681#ifdef HTTPS_SUPPORT
6682 if (NULL != daemon->priority_cache)
6683 gnutls_priority_deinit (daemon->priority_cache);
6684#endif /* HTTPS_SUPPORT */
6685 free (daemon);
6686 return NULL;
6687 }
6688 }
6689
6690#ifdef DAUTH_SUPPORT
6691 if (daemon->nonce_nc_size > 0)
6692 {
6693 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
6694 / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
6695 {
6696#ifdef HAVE_MESSAGES
6697 MHD_DLOG (daemon,
6698 _ ("Specified value for NC_SIZE too large.\n"));
6699#endif
6700#ifdef HTTPS_SUPPORT
6701 if (0 != (*pflags & MHD_USE_TLS))
6702 gnutls_priority_deinit (daemon->priority_cache);
6703#endif /* HTTPS_SUPPORT */
6704 free (daemon);
6705 return NULL;
6706 }
6707 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
6708 if (NULL == daemon->nnc)
6709 {
6710#ifdef HAVE_MESSAGES
6711 MHD_DLOG (daemon,
6712 _ ("Failed to allocate memory for nonce-nc map: %s\n"),
6713 MHD_strerror_ (errno));
6714#endif
6715#ifdef HTTPS_SUPPORT
6716 if (0 != (*pflags & MHD_USE_TLS))
6717 gnutls_priority_deinit (daemon->priority_cache);
6718#endif /* HTTPS_SUPPORT */
6719 free (daemon);
6720 return NULL;
6721 }
6722 }
6723
6724#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6725 if (! MHD_mutex_init_ (&daemon->nnc_lock))
6726 {
6727#ifdef HAVE_MESSAGES
6728 MHD_DLOG (daemon,
6729 _ ("MHD failed to initialize nonce-nc mutex.\n"));
6730#endif
6731#ifdef HTTPS_SUPPORT
6732 if (0 != (*pflags & MHD_USE_TLS))
6733 gnutls_priority_deinit (daemon->priority_cache);
6734#endif /* HTTPS_SUPPORT */
6735 free (daemon->nnc);
6736 free (daemon);
6737 return NULL;
6738 }
6739#endif
6740#endif
6741
6742 /* Thread polling currently works only with internal select thread mode */
6743#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6744 if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
6745 (daemon->worker_pool_size > 0) )
6746 {
6747#ifdef HAVE_MESSAGES
6748 MHD_DLOG (daemon,
6749 _ (
6750 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6751#endif
6752 goto free_and_fail;
6753 }
6754#endif
6755 if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
6756 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6757 {
6758 /* try to open listen socket */
6759 int domain;
6760
6761#ifdef HAVE_INET6
6762 domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6763#else /* ! HAVE_INET6 */
6764 if (*pflags & MHD_USE_IPv6)
6765 goto free_and_fail;
6766 domain = PF_INET;
6767#endif /* ! HAVE_INET6 */
6768
6769 listen_fd = MHD_socket_create_listen_ (domain);
6770 if (MHD_INVALID_SOCKET == listen_fd)
6771 {
6772#ifdef HAVE_MESSAGES
6773 MHD_DLOG (daemon,
6774 _ ("Failed to create socket for listening: %s\n"),
6776#endif
6777 goto free_and_fail;
6778 }
6779
6780 /* Apply the socket options according to listening_address_reuse. */
6781 if (0 == daemon->listening_address_reuse)
6782 {
6783#ifndef MHD_WINSOCK_SOCKETS
6784 /* No user requirement, use "traditional" default SO_REUSEADDR
6785 * on non-W32 platforms, and do not fail if it doesn't work.
6786 * Don't use it on W32, because on W32 it will allow multiple
6787 * bind to the same address:port, like SO_REUSEPORT on others. */
6788 if (0 > setsockopt (listen_fd,
6789 SOL_SOCKET,
6790 SO_REUSEADDR,
6791 (void *) &on, sizeof (on)))
6792 {
6793#ifdef HAVE_MESSAGES
6794 MHD_DLOG (daemon,
6795 _ ("setsockopt failed: %s\n"),
6797#endif
6798 }
6799#endif /* ! MHD_WINSOCK_SOCKETS */
6800 }
6801 else if (daemon->listening_address_reuse > 0)
6802 {
6803 /* User requested to allow reusing listening address:port. */
6804#ifndef MHD_WINSOCK_SOCKETS
6805 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
6806 * it doesn't work. */
6807 if (0 > setsockopt (listen_fd,
6808 SOL_SOCKET,
6809 SO_REUSEADDR,
6810 (void *) &on, sizeof (on)))
6811 {
6812#ifdef HAVE_MESSAGES
6813 MHD_DLOG (daemon,
6814 _ ("setsockopt failed: %s\n"),
6816#endif
6817 }
6818#endif /* ! MHD_WINSOCK_SOCKETS */
6819 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
6820 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
6821 */
6822 /* SO_REUSEADDR on W32 has the same semantics
6823 as SO_REUSEPORT on BSD/Linux */
6824#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6825 if (0 > setsockopt (listen_fd,
6826 SOL_SOCKET,
6827#ifndef MHD_WINSOCK_SOCKETS
6828 SO_REUSEPORT,
6829#else /* MHD_WINSOCK_SOCKETS */
6830 SO_REUSEADDR,
6831#endif /* MHD_WINSOCK_SOCKETS */
6832 (void *) &on,
6833 sizeof (on)))
6834 {
6835#ifdef HAVE_MESSAGES
6836 MHD_DLOG (daemon,
6837 _ ("setsockopt failed: %s\n"),
6839#endif
6840 goto free_and_fail;
6841 }
6842#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6843 /* we're supposed to allow address:port re-use, but
6844 on this platform we cannot; fail hard */
6845#ifdef HAVE_MESSAGES
6846 MHD_DLOG (daemon,
6847 _ (
6848 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6849#endif
6850 goto free_and_fail;
6851#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6852 }
6853 else /* if (daemon->listening_address_reuse < 0) */
6854 {
6855 /* User requested to disallow reusing listening address:port.
6856 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
6857 * is used and Solaris with SO_EXCLBIND.
6858 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
6859 * or setsockopt fails.
6860 */
6861#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6862 (defined(__sun) && defined(SO_EXCLBIND))
6863 if (0 > setsockopt (listen_fd,
6864 SOL_SOCKET,
6865#ifdef SO_EXCLUSIVEADDRUSE
6866 SO_EXCLUSIVEADDRUSE,
6867#else /* SO_EXCLBIND */
6868 SO_EXCLBIND,
6869#endif /* SO_EXCLBIND */
6870 (void *) &on,
6871 sizeof (on)))
6872 {
6873#ifdef HAVE_MESSAGES
6874 MHD_DLOG (daemon,
6875 _ ("setsockopt failed: %s\n"),
6877#endif
6878 goto free_and_fail;
6879 }
6880#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
6881#ifdef HAVE_MESSAGES
6882 MHD_DLOG (daemon,
6883 _ (
6884 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6885#endif
6886 goto free_and_fail;
6887#endif /* MHD_WINSOCK_SOCKETS */
6888 }
6889
6890 /* check for user supplied sockaddr */
6891#if HAVE_INET6
6892 if (0 != (*pflags & MHD_USE_IPv6))
6893 addrlen = sizeof (struct sockaddr_in6);
6894 else
6895#endif
6896 addrlen = sizeof (struct sockaddr_in);
6897 if (NULL == servaddr)
6898 {
6899#if HAVE_INET6
6900 if (0 != (*pflags & MHD_USE_IPv6))
6901 {
6902#ifdef IN6ADDR_ANY_INIT
6903 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6904#endif
6905 memset (&servaddr6,
6906 0,
6907 sizeof (struct sockaddr_in6));
6908 servaddr6.sin6_family = AF_INET6;
6909 servaddr6.sin6_port = htons (port);
6910#ifdef IN6ADDR_ANY_INIT
6911 servaddr6.sin6_addr = static_in6any;
6912#endif
6913#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6914 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
6915#endif
6916 servaddr = (struct sockaddr *) &servaddr6;
6917 }
6918 else
6919#endif
6920 {
6921 memset (&servaddr4,
6922 0,
6923 sizeof (struct sockaddr_in));
6924 servaddr4.sin_family = AF_INET;
6925 servaddr4.sin_port = htons (port);
6926 if (0 != INADDR_ANY)
6927 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6928#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6929 servaddr4.sin_len = sizeof (struct sockaddr_in);
6930#endif
6931 servaddr = (struct sockaddr *) &servaddr4;
6932 }
6933 }
6934 daemon->listen_fd = listen_fd;
6935 if (0 != (*pflags & MHD_USE_IPv6))
6936 {
6937#ifdef IPPROTO_IPV6
6938#ifdef IPV6_V6ONLY
6939 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
6940 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
6941 and may also be missing on older POSIX systems; good luck if you have any of those,
6942 your IPv6 socket may then also bind against IPv4 anyway... */
6943 const MHD_SCKT_OPT_BOOL_ v6_only =
6944 (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
6945 if (0 > setsockopt (listen_fd,
6946 IPPROTO_IPV6, IPV6_V6ONLY,
6947 (const void *) &v6_only,
6948 sizeof (v6_only)))
6949 {
6950#ifdef HAVE_MESSAGES
6951 MHD_DLOG (daemon,
6952 _ ("setsockopt failed: %s\n"),
6954#endif
6955 }
6956#endif
6957#endif
6958 }
6959 if (-1 == bind (listen_fd, servaddr, addrlen))
6960 {
6961#ifdef HAVE_MESSAGES
6962 MHD_DLOG (daemon,
6963 _ ("Failed to bind to port %u: %s\n"),
6964 (unsigned int) port,
6966#endif
6967 MHD_socket_close_chk_ (listen_fd);
6968 goto free_and_fail;
6969 }
6970#ifdef TCP_FASTOPEN
6971 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6972 {
6973 if (0 == daemon->fastopen_queue_size)
6974 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6975 if (0 != setsockopt (listen_fd,
6976 IPPROTO_TCP,
6977 TCP_FASTOPEN,
6978 (const void *) &daemon->fastopen_queue_size,
6979 sizeof (daemon->fastopen_queue_size)))
6980 {
6981#ifdef HAVE_MESSAGES
6982 MHD_DLOG (daemon,
6983 _ ("setsockopt failed: %s\n"),
6985#endif
6986 }
6987 }
6988#endif
6989 if (listen (listen_fd,
6990 daemon->listen_backlog_size) < 0)
6991 {
6992#ifdef HAVE_MESSAGES
6993 MHD_DLOG (daemon,
6994 _ ("Failed to listen for connections: %s\n"),
6996#endif
6997 MHD_socket_close_chk_ (listen_fd);
6998 goto free_and_fail;
6999 }
7000 }
7001 else
7002 {
7003 listen_fd = daemon->listen_fd;
7004 }
7005
7006#ifdef MHD_USE_GETSOCKNAME
7007 if ( (0 == daemon->port) &&
7008 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
7009 { /* Get port number. */
7010 struct sockaddr_storage bindaddr;
7011
7012 memset (&bindaddr,
7013 0,
7014 sizeof (struct sockaddr_storage));
7015 addrlen = sizeof (struct sockaddr_storage);
7016#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
7017 bindaddr.ss_len = addrlen;
7018#endif
7019 if (0 != getsockname (listen_fd,
7020 (struct sockaddr *) &bindaddr,
7021 &addrlen))
7022 {
7023#ifdef HAVE_MESSAGES
7024 MHD_DLOG (daemon,
7025 _ ("Failed to get listen port number: %s\n"),
7027#endif /* HAVE_MESSAGES */
7028 }
7029#ifdef MHD_POSIX_SOCKETS
7030 else if (sizeof (bindaddr) < addrlen)
7031 {
7032 /* should be impossible with `struct sockaddr_storage` */
7033#ifdef HAVE_MESSAGES
7034 MHD_DLOG (daemon,
7035 _ (
7036 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
7037#endif /* HAVE_MESSAGES */
7038 }
7039#ifndef __linux__
7040 else if (0 == addrlen)
7041 {
7042 /* Many non-Linux-based platforms return zero addrlen
7043 * for AF_UNIX sockets */
7044 daemon->port = 0; /* special value for UNIX domain sockets */
7045 }
7046#endif /* __linux__ */
7047#endif /* MHD_POSIX_SOCKETS */
7048 else
7049 {
7050 switch (bindaddr.ss_family)
7051 {
7052 case AF_INET:
7053 {
7054 struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
7055
7056 daemon->port = ntohs (s4->sin_port);
7057 break;
7058 }
7059#ifdef HAVE_INET6
7060 case AF_INET6:
7061 {
7062 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
7063
7064 daemon->port = ntohs (s6->sin6_port);
7065 mhd_assert (0 != (*pflags & MHD_USE_IPv6));
7066 break;
7067 }
7068#endif /* HAVE_INET6 */
7069#ifdef AF_UNIX
7070 case AF_UNIX:
7071 daemon->port = 0; /* special value for UNIX domain sockets */
7072 break;
7073#endif
7074 default:
7075#ifdef HAVE_MESSAGES
7076 MHD_DLOG (daemon,
7077 _ ("Unknown address family!\n"));
7078#endif
7079 daemon->port = 0; /* ugh */
7080 break;
7081 }
7082 }
7083 }
7084#endif /* MHD_USE_GETSOCKNAME */
7085
7086 if (MHD_INVALID_SOCKET != listen_fd)
7087 {
7088 if (! MHD_socket_nonblocking_ (listen_fd))
7089 {
7090#ifdef HAVE_MESSAGES
7091 MHD_DLOG (daemon,
7092 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
7094#endif
7095 if (0 != (*pflags & MHD_USE_EPOLL)
7096#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7097 || (daemon->worker_pool_size > 0)
7098#endif
7099 )
7100 {
7101 /* Accept must be non-blocking. Multiple children may wake up
7102 * to handle a new connection, but only one will win the race.
7103 * The others must immediately return. */
7104 MHD_socket_close_chk_ (listen_fd);
7105 goto free_and_fail;
7106 }
7107 daemon->listen_nonblk = false;
7108 }
7109 else
7110 daemon->listen_nonblk = true;
7111 if ( (! MHD_SCKT_FD_FITS_FDSET_ (listen_fd,
7112 NULL)) &&
7113 (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
7114 {
7115#ifdef HAVE_MESSAGES
7116 MHD_DLOG (daemon,
7117 _ ("Listen socket descriptor (%d) is not " \
7118 "less than FD_SETSIZE (%d).\n"),
7119 (int) listen_fd,
7120 (int) FD_SETSIZE);
7121#endif
7122 MHD_socket_close_chk_ (listen_fd);
7123 goto free_and_fail;
7124 }
7125 }
7126 else
7127 daemon->listen_nonblk = false; /* Actually listen socket does not exist */
7128
7129#ifdef EPOLL_SUPPORT
7130 if ( (0 != (*pflags & MHD_USE_EPOLL))
7131#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7132 && (0 == daemon->worker_pool_size)
7133#endif
7134 )
7135 {
7136 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
7137 {
7138#ifdef HAVE_MESSAGES
7139 MHD_DLOG (daemon,
7140 _ (
7141 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
7142#endif
7143 goto free_and_fail;
7144 }
7145 if (MHD_NO == setup_epoll_to_listen (daemon))
7146 goto free_and_fail;
7147 }
7148#endif /* EPOLL_SUPPORT */
7149
7150#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7152 {
7153#ifdef HAVE_MESSAGES
7154 MHD_DLOG (daemon,
7155 _ ("MHD failed to initialize IP connection limit mutex.\n"));
7156#endif
7157 if (MHD_INVALID_SOCKET != listen_fd)
7158 MHD_socket_close_chk_ (listen_fd);
7159 goto free_and_fail;
7160 }
7162 {
7163#ifdef HAVE_MESSAGES
7164 MHD_DLOG (daemon,
7165 _ ("MHD failed to initialize IP connection limit mutex.\n"));
7166#endif
7167#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7169#endif
7170 if (MHD_INVALID_SOCKET != listen_fd)
7171 MHD_socket_close_chk_ (listen_fd);
7172 goto free_and_fail;
7173 }
7174#endif
7175
7176#ifdef HTTPS_SUPPORT
7177 /* initialize HTTPS daemon certificate aspects & send / recv functions */
7178 if ( (0 != (*pflags & MHD_USE_TLS)) &&
7179 (0 != MHD_TLS_init (daemon)) )
7180 {
7181#ifdef HAVE_MESSAGES
7182 MHD_DLOG (daemon,
7183 _ ("Failed to initialize TLS support.\n"));
7184#endif
7185 if (MHD_INVALID_SOCKET != listen_fd)
7186 MHD_socket_close_chk_ (listen_fd);
7187#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7190#endif
7191 goto free_and_fail;
7192 }
7193#endif /* HTTPS_SUPPORT */
7194#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7195 /* Start threads if requested by parameters */
7196 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7197 {
7198 /* Internal thread (or threads) is used.
7199 * Make sure that MHD will be able to communicate with threads. */
7200 /* If using a thread pool ITC will be initialised later
7201 * for each individual worker thread. */
7202#ifdef HAVE_LISTEN_SHUTDOWN
7203 mhd_assert ((1 < daemon->worker_pool_size) || \
7204 (MHD_ITC_IS_VALID_ (daemon->itc)) || \
7205 (MHD_INVALID_SOCKET != daemon->listen_fd));
7206#else /* ! HAVE_LISTEN_SHUTDOWN */
7207 mhd_assert ((1 < daemon->worker_pool_size) || \
7208 (MHD_ITC_IS_VALID_ (daemon->itc)));
7209#endif /* ! HAVE_LISTEN_SHUTDOWN */
7210 if (0 == daemon->worker_pool_size)
7211 {
7212 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
7213 {
7214#ifdef HAVE_MESSAGES
7215 MHD_DLOG (daemon,
7216 _ ("Failed to initialise mutex.\n"));
7217#endif
7220 if (MHD_INVALID_SOCKET != listen_fd)
7221 MHD_socket_close_chk_ (listen_fd);
7222 goto free_and_fail;
7223 }
7224 if (! MHD_create_named_thread_ (&daemon->pid,
7225 (*pflags
7227 "MHD-listen" : "MHD-single",
7228 daemon->thread_stack_size,
7230 daemon) )
7231 {
7232#ifdef HAVE_MESSAGES
7233#ifdef EAGAIN
7234 if (EAGAIN == errno)
7235 MHD_DLOG (daemon,
7236 _ ("Failed to create a new thread because it would have " \
7237 "exceeded the system limit on the number of threads or " \
7238 "no system resources available.\n"));
7239 else
7240#endif /* EAGAIN */
7241 MHD_DLOG (daemon,
7242 _ ("Failed to create listen thread: %s\n"),
7243 MHD_strerror_ (errno));
7244#endif /* HAVE_MESSAGES */
7245 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7248 if (MHD_INVALID_SOCKET != listen_fd)
7249 MHD_socket_close_chk_ (listen_fd);
7250 goto free_and_fail;
7251 }
7252 }
7253 else /* 0 < daemon->worker_pool_size */
7254 {
7255 /* Coarse-grained count of connections per thread (note error
7256 * due to integer division). Also keep track of how many
7257 * connections are leftover after an equal split. */
7258 unsigned int conns_per_thread = daemon->connection_limit
7259 / daemon->worker_pool_size;
7260 unsigned int leftover_conns = daemon->connection_limit
7261 % daemon->worker_pool_size;
7262
7263 mhd_assert (2 <= daemon->worker_pool_size);
7264 i = 0; /* we need this in case fcntl or malloc fails */
7265
7266 /* Allocate memory for pooled objects */
7267 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
7268 * daemon->worker_pool_size);
7269 if (NULL == daemon->worker_pool)
7270 goto thread_failed;
7271
7272 /* Start the workers in the pool */
7273 for (i = 0; i < daemon->worker_pool_size; ++i)
7274 {
7275 /* Create copy of the Daemon object for each worker */
7276 struct MHD_Daemon *d = &daemon->worker_pool[i];
7277
7278 memcpy (d, daemon, sizeof (struct MHD_Daemon));
7279 /* Adjust polling params for worker daemons; note that memcpy()
7280 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
7281 the worker threads. */
7282 d->master = daemon;
7283 d->worker_pool_size = 0;
7284 d->worker_pool = NULL;
7285#if defined(DAUTH_SUPPORT) && defined(MHD_USE_THREADS)
7286 /* Avoid accidental re-use of the mutex copies */
7287 memset (&d->nnc_lock, -1, sizeof(d->nnc_lock));
7288#endif /* DAUTH_SUPPORT && MHD_USE_THREADS */
7289 if (! MHD_mutex_init_ (&d->new_connections_mutex))
7290 {
7291 #ifdef HAVE_MESSAGES
7292 MHD_DLOG (daemon,
7293 _ ("Failed to initialise mutex.\n"));
7294 #endif
7295 goto thread_failed;
7296 }
7297 if (0 != (*pflags & MHD_USE_ITC))
7298 {
7299 if (! MHD_itc_init_ (d->itc))
7300 {
7301#ifdef HAVE_MESSAGES
7302 MHD_DLOG (daemon,
7303 _ (
7304 "Failed to create worker inter-thread communication channel: %s\n"),
7305 MHD_itc_last_strerror_ () );
7306#endif
7307 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7308 goto thread_failed;
7309 }
7310 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
7311 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
7312 NULL)) )
7313 {
7314#ifdef HAVE_MESSAGES
7315 MHD_DLOG (daemon,
7316 _ (
7317 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
7318#endif
7319 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7321 goto thread_failed;
7322 }
7323 }
7324 else
7325 MHD_itc_set_invalid_ (d->itc);
7326
7327#ifdef HAVE_LISTEN_SHUTDOWN
7328 mhd_assert ((MHD_ITC_IS_VALID_ (d->itc)) || \
7330#else /* ! HAVE_LISTEN_SHUTDOWN */
7331 mhd_assert (MHD_ITC_IS_VALID_ (d->itc));
7332#endif /* ! HAVE_LISTEN_SHUTDOWN */
7333
7334 /* Divide available connections evenly amongst the threads.
7335 * Thread indexes in [0, leftover_conns) each get one of the
7336 * leftover connections. */
7337 d->connection_limit = conns_per_thread;
7338 if (i < leftover_conns)
7339 ++d->connection_limit;
7340#ifdef EPOLL_SUPPORT
7341 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
7342 (MHD_NO == setup_epoll_to_listen (d)) )
7343 {
7344 if (MHD_ITC_IS_VALID_ (d->itc))
7346 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7347 goto thread_failed;
7348 }
7349#endif
7350 /* Must init cleanup connection mutex for each worker */
7352 {
7353#ifdef HAVE_MESSAGES
7354 MHD_DLOG (daemon,
7355 _ ("MHD failed to initialize cleanup connection mutex.\n"));
7356#endif
7357 if (MHD_ITC_IS_VALID_ (d->itc))
7359 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7360 goto thread_failed;
7361 }
7362
7363 /* Spawn the worker thread */
7364 if (! MHD_create_named_thread_ (&d->pid,
7365 "MHD-worker",
7366 daemon->thread_stack_size,
7368 d))
7369 {
7370#ifdef HAVE_MESSAGES
7371#ifdef EAGAIN
7372 if (EAGAIN == errno)
7373 MHD_DLOG (daemon,
7374 _ ("Failed to create a new pool thread because it would " \
7375 "have exceeded the system limit on the number of " \
7376 "threads or no system resources available.\n"));
7377 else
7378#endif /* EAGAIN */
7379 MHD_DLOG (daemon,
7380 _ ("Failed to create pool thread: %s\n"),
7381 MHD_strerror_ (errno));
7382#endif
7383 /* Free memory for this worker; cleanup below handles
7384 * all previously-created workers. */
7386 if (MHD_ITC_IS_VALID_ (d->itc))
7388 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7389 goto thread_failed;
7390 }
7391 }
7392 }
7393 }
7394 else
7395 { /* Daemon without internal threads */
7396 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
7397 {
7398#ifdef HAVE_MESSAGES
7399 MHD_DLOG (daemon,
7400 _ ("Failed to initialise mutex.\n"));
7401#endif
7402 goto free_and_fail;
7403 }
7404 }
7405#endif
7406#ifdef HTTPS_SUPPORT
7407 /* API promises to never use the password after initialization,
7408 so we additionally NULL it here to not deref a dangling pointer. */
7409 daemon->https_key_password = NULL;
7410#endif /* HTTPS_SUPPORT */
7411
7412 return daemon;
7413
7414#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7415thread_failed:
7416 /* If no worker threads created, then shut down normally. Calling
7417 MHD_stop_daemon (as we do below) doesn't work here since it
7418 assumes a 0-sized thread pool means we had been in the default
7419 MHD_USE_INTERNAL_POLLING_THREAD mode. */
7420 if (0 == i)
7421 {
7425 if (NULL != daemon->worker_pool)
7426 free (daemon->worker_pool);
7427 goto free_and_fail;
7428 }
7429
7430 /* Shutdown worker threads we've already created. Pretend
7431 as though we had fully initialized our daemon, but
7432 with a smaller number of threads than had been
7433 requested. */
7434 daemon->worker_pool_size = i;
7435 MHD_stop_daemon (daemon);
7436 return NULL;
7437#endif
7438
7439free_and_fail:
7440 /* clean up basic memory state in 'daemon' and return NULL to
7441 indicate failure */
7442#ifdef EPOLL_SUPPORT
7443#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7444 if (daemon->upgrade_fd_in_epoll)
7445 {
7446 if (0 != epoll_ctl (daemon->epoll_fd,
7447 EPOLL_CTL_DEL,
7448 daemon->epoll_upgrade_fd,
7449 NULL))
7450 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
7451 daemon->upgrade_fd_in_epoll = false;
7452 }
7453#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7454 if (-1 != daemon->epoll_fd)
7455 close (daemon->epoll_fd);
7456#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7457 if (-1 != daemon->epoll_upgrade_fd)
7458 close (daemon->epoll_upgrade_fd);
7459#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7460#endif /* EPOLL_SUPPORT */
7461#ifdef DAUTH_SUPPORT
7462 free (daemon->nnc);
7463#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7464 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
7465#endif
7466#endif
7467#ifdef HTTPS_SUPPORT
7468 if (0 != (*pflags & MHD_USE_TLS))
7469 {
7470 gnutls_priority_deinit (daemon->priority_cache);
7471 if (daemon->x509_cred)
7472 gnutls_certificate_free_credentials (daemon->x509_cred);
7473 if (daemon->psk_cred)
7474 gnutls_psk_free_server_credentials (daemon->psk_cred);
7475 }
7476#endif /* HTTPS_SUPPORT */
7477 if (MHD_ITC_IS_VALID_ (daemon->itc))
7478 MHD_itc_destroy_chk_ (daemon->itc);
7479 free (daemon);
7480 return NULL;
7481}
7482
7483
7492static void
7494{
7495 struct MHD_Connection *pos;
7496 const bool used_thr_p_c = (0 != (daemon->options
7498#ifdef UPGRADE_SUPPORT
7499 const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
7500#endif /* UPGRADE_SUPPORT */
7501#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7502 struct MHD_UpgradeResponseHandle *urh;
7503 struct MHD_UpgradeResponseHandle *urhn;
7504 const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
7505#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7506
7507#ifdef MHD_USE_THREADS
7508 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
7509 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
7510 MHD_thread_ID_match_current_ (daemon->pid) );
7511 mhd_assert (NULL == daemon->worker_pool);
7512#endif /* MHD_USE_THREADS */
7513 mhd_assert (daemon->shutdown);
7514
7515#ifdef MHD_USE_THREADS
7516/* Remove externally added new connections that are
7517 * not processed by the daemon thread. */
7518 while (NULL != (pos = daemon->new_connections_tail))
7519 {
7522 daemon->new_connections_tail,
7523 pos);
7524 new_connection_close_ (daemon, pos);
7525 }
7526#endif /* MHD_USE_THREADS */
7527
7528#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7529 /* give upgraded HTTPS connections a chance to finish */
7530 /* 'daemon->urh_head' is not used in thread-per-connection mode. */
7531 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
7532 {
7533 mhd_assert (! used_thr_p_c);
7534 urhn = urh->prev;
7535 /* call generic forwarding function for passing data
7536 with chance to detect that application is done. */
7537 process_urh (urh);
7538 MHD_connection_finish_forward_ (urh->connection);
7539 urh->clean_ready = true;
7540 /* Resuming will move connection to cleanup list. */
7541 MHD_resume_connection (urh->connection);
7542 }
7543#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7544
7545 /* Give suspended connections a chance to resume to avoid
7546 running into the check for there not being any suspended
7547 connections left in case of a tight race with a recently
7548 resumed connection. */
7549 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
7550 {
7551 daemon->resuming = true; /* Force check for pending resume. */
7553 }
7554 /* first, make sure all threads are aware of shutdown; need to
7555 traverse DLLs in peace... */
7556#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7558#endif
7559#ifdef UPGRADE_SUPPORT
7560 if (upg_allowed)
7561 {
7562 struct MHD_Connection *susp;
7563
7565 while (NULL != susp)
7566 {
7567 if (NULL == susp->urh) /* "Upgraded" connection? */
7568 MHD_PANIC (_ (
7569 "MHD_stop_daemon() called while we have suspended connections.\n"));
7570#ifdef HTTPS_SUPPORT
7571 else if (used_tls &&
7572 used_thr_p_c &&
7573 (! susp->urh->clean_ready) )
7574 shutdown (susp->urh->app.socket,
7575 SHUT_RDWR); /* Wake thread by shutdown of app socket. */
7576#endif /* HTTPS_SUPPORT */
7577 else
7578 {
7579#ifdef HAVE_MESSAGES
7580 if (! susp->urh->was_closed)
7581 MHD_DLOG (daemon,
7582 _ (
7583 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
7584#endif
7585 susp->urh->was_closed = true;
7586 /* If thread-per-connection is used, connection's thread
7587 * may still processing "upgrade" (exiting). */
7588 if (! used_thr_p_c)
7590 /* Do not use MHD_resume_connection() as mutex is
7591 * already locked. */
7592 susp->resuming = true;
7593 daemon->resuming = true;
7594 }
7595 susp = susp->prev;
7596 }
7597 }
7598 else /* This 'else' is combined with next 'if' */
7599#endif /* UPGRADE_SUPPORT */
7601 MHD_PANIC (_ (
7602 "MHD_stop_daemon() called while we have suspended connections.\n"));
7603#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
7604#ifdef MHD_USE_THREADS
7605 if (upg_allowed && used_tls && used_thr_p_c)
7606 {
7607 /* "Upgraded" threads may be running in parallel. Connection will not be
7608 * moved to the "cleanup list" until connection's thread finishes.
7609 * We must ensure that all "upgraded" connections are finished otherwise
7610 * connection may stay in "suspended" list and will not be cleaned. */
7611 for (pos = daemon->suspended_connections_tail; NULL != pos; pos = pos->prev)
7612 {
7613 /* Any connection found here is "upgraded" connection, normal suspended
7614 * connections are already removed from this list. */
7615 mhd_assert (NULL != pos->urh);
7616 if (! pos->thread_joined)
7617 {
7618 /* While "cleanup" list is not manipulated by "upgraded"
7619 * connection, "cleanup" mutex is required for call of
7620 * MHD_resume_connection() during finishing of "upgraded"
7621 * thread. */
7623 if (! MHD_join_thread_ (pos->pid.handle))
7624 MHD_PANIC (_ ("Failed to join a thread.\n"));
7625 pos->thread_joined = true;
7627 }
7628 }
7629 }
7630#endif /* MHD_USE_THREADS */
7631#endif
7632 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
7633 {
7634 shutdown (pos->socket_fd,
7635 SHUT_RDWR);
7636#if MHD_WINSOCK_SOCKETS
7637 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
7638 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
7639 (! MHD_itc_activate_ (daemon->itc, "e")) )
7640 MHD_PANIC (_ (
7641 "Failed to signal shutdown via inter-thread communication channel.\n"));
7642#endif
7643 }
7644
7645#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7646 /* now, collect per-connection threads */
7647 if (used_thr_p_c)
7648 {
7649 pos = daemon->connections_tail;
7650 while (NULL != pos)
7651 {
7652 if (! pos->thread_joined)
7653 {
7655 if (! MHD_join_thread_ (pos->pid.handle))
7656 MHD_PANIC (_ ("Failed to join a thread.\n"));
7658 pos->thread_joined = true;
7659 /* The thread may have concurrently modified the DLL,
7660 need to restart from the beginning */
7661 pos = daemon->connections_tail;
7662 continue;
7663 }
7664 pos = pos->prev;
7665 }
7666 }
7668#endif
7669
7670#ifdef UPGRADE_SUPPORT
7671 /* Finished threads with "upgraded" connections need to be moved
7672 * to cleanup list by resume_suspended_connections(). */
7673 /* "Upgraded" connections that were not closed explicitly by
7674 * application should be moved to cleanup list too. */
7675 if (upg_allowed)
7676 {
7677 daemon->resuming = true; /* Force check for pending resume. */
7679 }
7680#endif /* UPGRADE_SUPPORT */
7681
7683 /* now that we're alone, move everyone to cleanup */
7684 while (NULL != (pos = daemon->connections_tail))
7685 {
7686#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7687 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
7688 (! pos->thread_joined) )
7689 MHD_PANIC (_ ("Failed to join a thread.\n"));
7690#endif
7691 close_connection (pos);
7692 }
7694}
7695
7696
7703void
7705{
7706 MHD_socket fd;
7707#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7708 unsigned int i;
7709#endif
7710
7711 if (NULL == daemon)
7712 return;
7713 if ( (daemon->shutdown) && (NULL == daemon->master) )
7714 MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
7715 /* Slave daemons must be stopped by master daemon. */
7716 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
7717
7718 daemon->shutdown = true;
7719 if (daemon->was_quiesced)
7720 fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
7721 else
7722 fd = daemon->listen_fd;
7723
7724#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7725 if (NULL != daemon->worker_pool)
7726 { /* Master daemon with worker pool. */
7729
7730 /* Let workers shutdown in parallel. */
7731 for (i = 0; i < daemon->worker_pool_size; ++i)
7732 {
7733 daemon->worker_pool[i].shutdown = true;
7734 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
7735 {
7736 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
7737 "e"))
7738 MHD_PANIC (_ (
7739 "Failed to signal shutdown via inter-thread communication channel.\n"));
7740 }
7741 else
7743 }
7744#ifdef HAVE_LISTEN_SHUTDOWN
7745 if (MHD_INVALID_SOCKET != fd)
7746 {
7747 (void) shutdown (fd,
7748 SHUT_RDWR);
7749 }
7750#endif /* HAVE_LISTEN_SHUTDOWN */
7751 for (i = 0; i < daemon->worker_pool_size; ++i)
7752 {
7754 }
7755 free (daemon->worker_pool);
7757#ifdef EPOLL_SUPPORT
7758 mhd_assert (-1 == daemon->epoll_fd);
7759#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7760 mhd_assert (-1 == daemon->epoll_upgrade_fd);
7761#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7762#endif /* EPOLL_SUPPORT */
7763 }
7764 else
7765#endif
7766 { /* Worker daemon or single daemon. */
7767#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7769 { /* Worker daemon or single daemon with internal thread(s). */
7771 /* Separate thread(s) is used for polling sockets. */
7772 if (MHD_ITC_IS_VALID_ (daemon->itc))
7773 {
7774 if (! MHD_itc_activate_ (daemon->itc,
7775 "e"))
7776 MHD_PANIC (_ (
7777 "Failed to signal shutdown via inter-thread communication channel.\n"));
7778 }
7779 else
7780 {
7781#ifdef HAVE_LISTEN_SHUTDOWN
7782 if (MHD_INVALID_SOCKET != fd)
7783 {
7784 if (NULL == daemon->master)
7785 (void) shutdown (fd,
7786 SHUT_RDWR);
7787 }
7788 else
7789#endif /* HAVE_LISTEN_SHUTDOWN */
7790 mhd_assert (false); /* Should never happen */
7791 }
7792
7793 if (! MHD_join_thread_ (daemon->pid.handle))
7794 {
7795 MHD_PANIC (_ ("Failed to join a thread.\n"));
7796 }
7797 /* close_all_connections() was called in daemon thread. */
7798 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7799 }
7800 else
7801#endif
7802 {
7803 /* No internal threads are used for polling sockets. */
7805#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7806 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7807#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
7808 }
7813#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
7814 mhd_assert (NULL == daemon->urh_head);
7815#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
7816
7817 if (MHD_ITC_IS_VALID_ (daemon->itc))
7819
7820#ifdef EPOLL_SUPPORT
7821 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
7822 (-1 != daemon->epoll_fd) )
7823 MHD_socket_close_chk_ (daemon->epoll_fd);
7824#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7825 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
7826 (-1 != daemon->epoll_upgrade_fd) )
7827 MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
7828#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7829#endif /* EPOLL_SUPPORT */
7830
7831#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7833#endif
7834 }
7835
7836 if (NULL == daemon->master)
7837 { /* Cleanup that should be done only one time in master/single daemon.
7838 * Do not perform this cleanup in worker daemons. */
7839
7840 if (MHD_INVALID_SOCKET != fd)
7842
7843 /* TLS clean up */
7844#ifdef HTTPS_SUPPORT
7845 if (daemon->have_dhparams)
7846 {
7847 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
7848 daemon->have_dhparams = false;
7849 }
7850 if (0 != (daemon->options & MHD_USE_TLS))
7851 {
7852 gnutls_priority_deinit (daemon->priority_cache);
7853 if (daemon->x509_cred)
7854 gnutls_certificate_free_credentials (daemon->x509_cred);
7855 if (daemon->psk_cred)
7856 gnutls_psk_free_server_credentials (daemon->psk_cred);
7857 }
7858#endif /* HTTPS_SUPPORT */
7859
7860#ifdef DAUTH_SUPPORT
7861 free (daemon->nnc);
7862#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7863 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
7864#endif
7865#endif
7866#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7868#endif
7869 free (daemon);
7870 }
7871}
7872
7873
7885const union MHD_DaemonInfo *
7887 enum MHD_DaemonInfoType info_type,
7888 ...)
7889{
7890 if (NULL == daemon)
7891 return NULL;
7892 switch (info_type)
7893 {
7895 return NULL; /* no longer supported */
7897 return NULL; /* no longer supported */
7899 return (const union MHD_DaemonInfo *) &daemon->listen_fd;
7900#ifdef EPOLL_SUPPORT
7902 return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
7903#endif
7905 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
7906 {
7907 /* Assume that MHD_run() in not called in other thread
7908 * at the same time. */
7909 MHD_cleanup_connections (daemon);
7910 }
7911#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7912 else if (daemon->worker_pool)
7913 {
7914 unsigned int i;
7915 /* Collect the connection information stored in the workers. */
7916 daemon->connections = 0;
7917 for (i = 0; i < daemon->worker_pool_size; i++)
7918 {
7919 /* FIXME: next line is thread-safe only if read is atomic. */
7920 daemon->connections += daemon->worker_pool[i].connections;
7921 }
7922 }
7923#endif
7924 return (const union MHD_DaemonInfo *) &daemon->connections;
7926 return (const union MHD_DaemonInfo *) &daemon->options;
7928 return (const union MHD_DaemonInfo *) &daemon->port;
7929 default:
7930 return NULL;
7931 }
7932}
7933
7934
7951void
7953 void *cls)
7954{
7955 mhd_panic = cb;
7956 mhd_panic_cls = cls;
7957}
7958
7959
7966const char *
7967MHD_get_version (void)
7968{
7969#ifdef PACKAGE_VERSION
7970 return PACKAGE_VERSION;
7971#else /* !PACKAGE_VERSION */
7972 static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
7973 if (0 == ver[0])
7974 {
7975 int res = MHD_snprintf_ (ver,
7976 sizeof(ver),
7977 "%x.%x.%x",
7978 (int) (((uint32_t) MHD_VERSION >> 24) & 0xFF),
7979 (int) (((uint32_t) MHD_VERSION >> 16) & 0xFF),
7980 (int) (((uint32_t) MHD_VERSION >> 8) & 0xFF));
7981 if ((0 >= res) || (sizeof(ver) <= res))
7982 return "0.0.0"; /* Can't return real version */
7983 }
7984 return ver;
7985#endif /* !PACKAGE_VERSION */
7986}
7987
7988
7997_MHD_EXTERN uint32_t
7999{
8000 return (uint32_t) MHD_VERSION;
8001}
8002
8003
8015enum MHD_Result
8017{
8018 switch (feature)
8019 {
8021#ifdef HAVE_MESSAGES
8022 return MHD_YES;
8023#else
8024 return MHD_NO;
8025#endif
8026 case MHD_FEATURE_TLS:
8027#ifdef HTTPS_SUPPORT
8028 return MHD_YES;
8029#else /* ! HTTPS_SUPPORT */
8030 return MHD_NO;
8031#endif /* ! HTTPS_SUPPORT */
8033#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
8034 return MHD_YES;
8035#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
8036 return MHD_NO;
8037#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
8039#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
8040 return MHD_YES;
8041#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
8042 return MHD_NO;
8043#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
8044 case MHD_FEATURE_IPv6:
8045#ifdef HAVE_INET6
8046 return MHD_YES;
8047#else
8048 return MHD_NO;
8049#endif
8051#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
8052 return MHD_YES;
8053#else
8054 return MHD_NO;
8055#endif
8056 case MHD_FEATURE_POLL:
8057#ifdef HAVE_POLL
8058 return MHD_YES;
8059#else
8060 return MHD_NO;
8061#endif
8062 case MHD_FEATURE_EPOLL:
8063#ifdef EPOLL_SUPPORT
8064 return MHD_YES;
8065#else
8066 return MHD_NO;
8067#endif
8069#ifdef HAVE_LISTEN_SHUTDOWN
8070 return MHD_YES;
8071#else
8072 return MHD_NO;
8073#endif
8075#ifdef _MHD_ITC_SOCKETPAIR
8076 return MHD_YES;
8077#else
8078 return MHD_NO;
8079#endif
8081#ifdef TCP_FASTOPEN
8082 return MHD_YES;
8083#else
8084 return MHD_NO;
8085#endif
8087#ifdef BAUTH_SUPPORT
8088 return MHD_YES;
8089#else
8090 return MHD_NO;
8091#endif
8093#ifdef DAUTH_SUPPORT
8094 return MHD_YES;
8095#else
8096 return MHD_NO;
8097#endif
8099#ifdef HAVE_POSTPROCESSOR
8100 return MHD_YES;
8101#else
8102 return MHD_NO;
8103#endif
8105#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
8106 return MHD_YES;
8107#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
8108 return MHD_NO;
8109#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
8111#if defined(HAVE_PREAD64) || defined(_WIN32)
8112 return MHD_YES;
8113#elif defined(HAVE_PREAD)
8114 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
8115#elif defined(HAVE_LSEEK64)
8116 return MHD_YES;
8117#else
8118 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
8119#endif
8121#if defined(MHD_USE_THREAD_NAME_)
8122 return MHD_YES;
8123#else
8124 return MHD_NO;
8125#endif
8127#if defined(UPGRADE_SUPPORT)
8128 return MHD_YES;
8129#else
8130 return MHD_NO;
8131#endif
8133#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
8134 return MHD_YES;
8135#else
8136 return MHD_NO;
8137#endif
8139#ifdef MHD_USE_GETSOCKNAME
8140 return MHD_YES;
8141#else
8142 return MHD_NO;
8143#endif
8145#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) || \
8146 ! defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
8147 return MHD_YES;
8148#else
8149 return MHD_NO;
8150#endif
8152#ifdef _MHD_HAVE_SENDFILE
8153 return MHD_YES;
8154#else
8155 return MHD_NO;
8156#endif
8158#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8159 return MHD_YES;
8160#else
8161 return MHD_NO;
8162#endif
8163
8164 }
8165 return MHD_NO;
8166}
8167
8168
8169#ifdef MHD_HTTPS_REQUIRE_GCRYPT
8170#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
8171#if defined(MHD_USE_POSIX_THREADS)
8172GCRY_THREAD_OPTION_PTHREAD_IMPL;
8173#elif defined(MHD_W32_MUTEX_)
8174
8175static int
8176gcry_w32_mutex_init (void **ppmtx)
8177{
8178 *ppmtx = malloc (sizeof (MHD_mutex_));
8179
8180 if (NULL == *ppmtx)
8181 return ENOMEM;
8182 if (! MHD_mutex_init_ ((MHD_mutex_ *) *ppmtx))
8183 {
8184 free (*ppmtx);
8185 *ppmtx = NULL;
8186 return EPERM;
8187 }
8188
8189 return 0;
8190}
8191
8192
8193static int
8194gcry_w32_mutex_destroy (void **ppmtx)
8195{
8196 int res = (MHD_mutex_destroy_ ((MHD_mutex_ *) *ppmtx)) ? 0 : EINVAL;
8197 free (*ppmtx);
8198 return res;
8199}
8200
8201
8202static int
8203gcry_w32_mutex_lock (void **ppmtx)
8204{
8205 return MHD_mutex_lock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
8206}
8207
8208
8209static int
8210gcry_w32_mutex_unlock (void **ppmtx)
8211{
8212 return MHD_mutex_unlock_ ((MHD_mutex_ *) *ppmtx) ? 0 : EINVAL;
8213}
8214
8215
8216static struct gcry_thread_cbs gcry_threads_w32 = {
8217 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
8218 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
8219 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
8221};
8222
8223#endif /* defined(MHD_W32_MUTEX_) */
8224#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
8225#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
8226
8230void
8232{
8233#if defined(MHD_WINSOCK_SOCKETS)
8234 WSADATA wsd;
8235#endif /* MHD_WINSOCK_SOCKETS */
8236
8237 if (NULL == mhd_panic)
8239
8240#if defined(MHD_WINSOCK_SOCKETS)
8241 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
8242 MHD_PANIC (_ ("Failed to initialize winsock.\n"));
8243 mhd_winsock_inited_ = 1;
8244 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
8245 MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
8246#endif /* MHD_WINSOCK_SOCKETS */
8247#ifdef HTTPS_SUPPORT
8248#ifdef MHD_HTTPS_REQUIRE_GCRYPT
8249#if GCRYPT_VERSION_NUMBER < 0x010600
8250#if defined(MHD_USE_POSIX_THREADS)
8251 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8252 &gcry_threads_pthread))
8253 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
8254#elif defined(MHD_W32_MUTEX_)
8255 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8256 &gcry_threads_w32))
8257 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
8258#endif /* defined(MHD_W32_MUTEX_) */
8259 gcry_check_version (NULL);
8260#else
8261 if (NULL == gcry_check_version ("1.6.0"))
8262 MHD_PANIC (_ (
8263 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
8264#endif
8265#endif /* MHD_HTTPS_REQUIRE_GCRYPT */
8266 gnutls_global_init ();
8267#endif /* HTTPS_SUPPORT */
8271 /* Check whether sizes were correctly detected by configure */
8272#ifdef _DEBUG
8273 if (1)
8274 {
8275 struct timeval tv;
8276 mhd_assert (sizeof(tv.tv_sec) == SIZEOF_STRUCT_TIMEVAL_TV_SEC);
8277 }
8278#endif /* _DEBUG */
8279 mhd_assert (sizeof(uint64_t) == SIZEOF_UINT64_T);
8280}
8281
8282
8283void
8285{
8286#ifdef HTTPS_SUPPORT
8287 gnutls_global_deinit ();
8288#endif /* HTTPS_SUPPORT */
8289#if defined(MHD_WINSOCK_SOCKETS)
8290 if (mhd_winsock_inited_)
8291 WSACleanup ();
8292#endif /* MHD_WINSOCK_SOCKETS */
8294}
8295
8296
8297#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
8299#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
8300
8301/* end of daemon.c */
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_handle_write(struct MHD_Connection *connection)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
void MHD_connection_handle_read(struct MHD_Connection *connection, bool socket_error)
Methods for managing connections.
#define MHD_connection_finish_forward_(conn)
Definition connection.h:165
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
#define EXTRA_SLOTS
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition daemon.c:3211
static void close_all_connections(struct MHD_Daemon *daemon)
Definition daemon.c:7493
MHD_PanicCallback mhd_panic
Definition daemon.c:153
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:3248
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition daemon.c:3110
void MHD_fini(void)
Definition daemon.c:8284
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition daemon.c:5675
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:4724
void MHD_check_global_init_(void)
Definition daemon.c:201
static void close_connection(struct MHD_Connection *pos)
Definition daemon.c:5349
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
Definition daemon.c:4227
struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition daemon.c:261
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:3058
void MHD_init(void)
Definition daemon.c:8231
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition daemon.c:3809
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition daemon.c:5622
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition daemon.c:3617
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:5465
static enum MHD_Result new_connection_process_(struct MHD_Daemon *daemon, struct MHD_Connection *connection)
Definition daemon.c:2754
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:5650
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:3323
#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:2971
_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:4059
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
_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:5497
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition daemon.c:7704
_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:4171
_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:6430
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition daemon.c:5253
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition daemon.c:3936
#define MHD_get_fdset(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd)
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
Definition daemon.c:5303
_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)
_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)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
@ MHD_CONNECTION_NOTIFY_STARTED
@ MHD_CONNECTION_NOTIFY_CLOSED
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_WITH_ERROR
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition response.c:1966
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition daemon.c:7886
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition daemon.c:5542
_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:3483
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition daemon.c:8016
_MHD_EXTERN uint32_t MHD_get_version_bin(void)
Definition daemon.c:7998
_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)
int MHD_socket_noninheritable_(MHD_socket sock)
int MHD_socket_nonblocking_(MHD_socket sock)
MHD_socket MHD_socket_create_listen_(int pf)
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
#define MHD_SCKT_ERR_IS_(err, code)
int MHD_SCKT_OPT_BOOL_
#define MHD_socket_close_(fd)
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define MHD_SCKT_EINTR_
#define _MHD_SYS_DEFAULT_FD_SETSIZE
#define MHD_socket_strerr_(err)
#define MHD_socket_last_strerr_()
#define MHD_socket_get_error_()
#define MHD_SCKT_EINVAL_
#define MHD_socket_close_chk_(fd)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_socket_fset_error_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MHD_recv_(s, b, l)
#define MHD_send_(s, b, l)
#define MHD_SCKT_LAST_ERR_IS_(code)
#define MHD_SYS_select_(n, r, w, e, t)
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
#define MHD_STATICSTR_LEN_(macro)
Definition mhd_str.h:45
#define MHD_create_named_thread_(t, n, s, r, a)
#define NULL
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:63
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:95
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:27
#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
#define SOCK_NOSIGPIPE_OR_ZERO
#define SOCK_CLOEXEC_OR_ZERO
int MHD_socket
Definition microhttpd.h:207
MHD_FEATURE
@ MHD_FEATURE_POSTPROCESSOR
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
@ MHD_FEATURE_THREADS
@ MHD_FEATURE_SENDFILE
@ MHD_FEATURE_AUTODETECT_BIND_PORT
@ MHD_FEATURE_LARGE_FILE
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
@ MHD_FEATURE_BASIC_AUTH
@ MHD_FEATURE_DIGEST_AUTH
@ MHD_FEATURE_IPv6
@ MHD_FEATURE_POLL
@ MHD_FEATURE_THREAD_NAMES
@ MHD_FEATURE_EPOLL
@ MHD_FEATURE_TLS
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
@ MHD_FEATURE_RESPONSES_SHARED_FD
@ MHD_FEATURE_MESSAGES
@ MHD_FEATURE_IPv6_ONLY
@ MHD_FEATURE_UPGRADE
@ MHD_FEATURE_SOCKETPAIR
@ MHD_FEATURE_TCP_FASTOPEN
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
MHD_OPTION
MHD options.
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
@ MHD_OPTION_HTTPS_CRED_TYPE
@ MHD_OPTION_URI_LOG_CALLBACK
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_SIGPIPE_HANDLED_BY_APP
@ MHD_OPTION_UNESCAPE_CALLBACK
@ MHD_OPTION_EXTERNAL_LOGGER
@ MHD_OPTION_TLS_NO_ALPN
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
@ MHD_OPTION_HTTPS_PRIORITIES
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
@ MHD_OPTION_NOTIFY_CONNECTION
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
@ MHD_OPTION_THREAD_POOL_SIZE
@ MHD_OPTION_CONNECTION_LIMIT
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
@ MHD_OPTION_HTTPS_MEM_CERT
@ MHD_OPTION_SERVER_INSANITY
@ MHD_OPTION_LISTEN_SOCKET
@ MHD_OPTION_HTTPS_MEM_KEY
@ MHD_OPTION_DIGEST_AUTH_RANDOM
@ MHD_OPTION_HTTPS_KEY_PASSWORD
@ MHD_OPTION_NONCE_NC_SIZE
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
@ MHD_OPTION_THREAD_STACK_SIZE
@ MHD_OPTION_ARRAY
@ MHD_OPTION_STRICT_FOR_CLIENT
@ MHD_OPTION_SOCK_ADDR
@ MHD_OPTION_CONNECTION_TIMEOUT
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
@ MHD_OPTION_END
@ MHD_OPTION_HTTPS_MEM_TRUST
@ MHD_OPTION_HTTPS_CERT_CALLBACK
@ MHD_OPTION_NOTIFY_COMPLETED
MHD_DisableSanityCheck
MHD_Result
Definition microhttpd.h:158
@ MHD_YES
Definition microhttpd.h:167
@ MHD_NO
Definition microhttpd.h:162
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_UNSIGNED_LONG_LONG
Definition microhttpd.h:311
int fd
void * data
_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)
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
#define MHD_VERSION
Definition microhttpd.h:99
MHD_DaemonInfoType
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
@ MHD_DAEMON_INFO_BIND_PORT
@ MHD_DAEMON_INFO_EPOLL_FD
@ MHD_DAEMON_INFO_FLAGS
@ MHD_DAEMON_INFO_KEY_SIZE
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
@ MHD_DAEMON_INFO_LISTEN_FD
MHD_FLAG
Flags for the struct MHD_Daemon.
@ MHD_USE_EPOLL
@ MHD_ALLOW_SUSPEND_RESUME
@ MHD_USE_TCP_FASTOPEN
@ MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_AUTO
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
@ MHD_USE_TURBO
@ MHD_USE_IPv6
@ MHD_USE_DUAL_STACK
@ MHD_USE_POLL
@ MHD_USE_TLS
@ MHD_USE_INSECURE_TLS_EARLY_DATA
@ MHD_ALLOW_UPGRADE
@ MHD_USE_NO_LISTEN_SOCKET
@ MHD_USE_PEDANTIC_CHECKS
@ MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_USE_ITC
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
struct MHD_Response * response
Definition internal.h:968
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
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
enum MHD_OPTION option