GNU libmicrohttpd 0.9.71
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
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19*/
20
28#include "platform.h"
29#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
30#include "mhd_threads.h"
31#endif
32#include "internal.h"
33#include "response.h"
34#include "connection.h"
35#include "memorypool.h"
36#include "mhd_limits.h"
37#include "autoinit_funcs.h"
38#include "mhd_mono_clock.h"
39#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
40#include "mhd_locks.h"
41#endif
42#include "mhd_sockets.h"
43#include "mhd_itc.h"
44#include "mhd_compat.h"
45
46#if HAVE_SEARCH_H
47#include <search.h>
48#else
49#include "tsearch.h"
50#endif
51
52#ifdef HTTPS_SUPPORT
53#include "connection_https.h"
54#ifdef MHD_HTTPS_REQUIRE_GRYPT
55#include <gcrypt.h>
56#endif /* MHD_HTTPS_REQUIRE_GRYPT */
57#endif /* HTTPS_SUPPORT */
58
59#if defined(_WIN32) && ! defined(__CYGWIN__)
60#ifndef WIN32_LEAN_AND_MEAN
61#define WIN32_LEAN_AND_MEAN 1
62#endif /* !WIN32_LEAN_AND_MEAN */
63#include <windows.h>
64#endif
65
69#ifdef MHD_POSIX_SOCKETS
70#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
71#else
72#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
73#endif
74
78#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
79
84#define DEBUG_CLOSE MHD_NO
85
90#define DEBUG_CONNECT MHD_NO
91
92
93/* Forward declarations. */
94
103static void
104close_all_connections (struct MHD_Daemon *daemon);
105
106#ifdef EPOLL_SUPPORT
107
116static enum MHD_Result
117MHD_epoll (struct MHD_Daemon *daemon,
118 int may_block);
119
120#endif /* EPOLL_SUPPORT */
121
131static void
132mhd_panic_std (void *cls,
133 const char *file,
134 unsigned int line,
135 const char *reason)
136{
137 (void) cls; /* Mute compiler warning. */
138#ifdef HAVE_MESSAGES
139 fprintf (stderr,
140 _ ("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
141 file,
142 line,
143 reason);
144#else /* ! HAVE_MESSAGES */
145 (void) file; /* Mute compiler warning. */
146 (void) line; /* Mute compiler warning. */
147 (void) reason; /* Mute compiler warning. */
148#endif
149 abort ();
150}
151
152
157
162
166void
167MHD_init (void);
168
169
170#if defined(MHD_WINSOCK_SOCKETS)
174static int mhd_winsock_inited_ = 0;
175#endif /* MHD_WINSOCK_SOCKETS */
176
177#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
182#define MHD_check_global_init_() (void) 0
183#else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
187volatile int global_init_count = 0;
188
189#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
190#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
194MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
195#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
196#endif
197
198
203void
205{
206#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
207#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
208 MHD_mutex_lock_chk_ (&global_init_mutex_);
209#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
210#endif
211 if (0 == global_init_count++)
212 MHD_init ();
213#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
214#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
215 MHD_mutex_unlock_chk_ (&global_init_mutex_);
216#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
217#endif
218}
219
220
221#endif /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
222
223
227static void
229 const char *fm,
230 va_list ap)
231{
232 vfprintf ((FILE*) cls, fm, ap);
233#ifdef _DEBUG
234 fflush ((FILE*) cls);
235#endif /* _DEBUG */
236}
237
238
247_MHD_EXTERN void
248MHD_free (void *ptr)
249{
250 free (ptr);
251}
252
253
261static struct MHD_Daemon*
263{
264 while (NULL != daemon->master)
265 daemon = daemon->master;
266 return daemon;
267}
268
269
273struct MHD_IPCount
274{
278 int family;
279
283 union
284 {
288 struct in_addr ipv4;
289#if HAVE_INET6
293 struct in6_addr ipv6;
294#endif
295 } addr;
296
300 unsigned int count;
301};
302
303
309static void
311{
312#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
314#else
315 (void) daemon;
316#endif
317}
318
319
325static void
327{
328#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
330#else
331 (void) daemon;
332#endif
333}
334
335
345static int
346MHD_ip_addr_compare (const void *a1,
347 const void *a2)
348{
349 return memcmp (a1,
350 a2,
351 offsetof (struct MHD_IPCount,
352 count));
353}
354
355
364static enum MHD_Result
365MHD_ip_addr_to_key (const struct sockaddr *addr,
366 socklen_t addrlen,
367 struct MHD_IPCount *key)
368{
369 memset (key,
370 0,
371 sizeof(*key));
372
373 /* IPv4 addresses */
374 if (sizeof (struct sockaddr_in) == addrlen)
375 {
376 const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
377
378 key->family = AF_INET;
379 memcpy (&key->addr.ipv4,
380 &addr4->sin_addr,
381 sizeof(addr4->sin_addr));
382 return MHD_YES;
383 }
384
385#if HAVE_INET6
386 /* IPv6 addresses */
387 if (sizeof (struct sockaddr_in6) == addrlen)
388 {
389 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
390
391 key->family = AF_INET6;
392 memcpy (&key->addr.ipv6,
393 &addr6->sin6_addr,
394 sizeof(addr6->sin6_addr));
395 return MHD_YES;
396 }
397#endif
398
399 /* Some other address */
400 return MHD_NO;
401}
402
403
415static enum MHD_Result
417 const struct sockaddr *addr,
418 socklen_t addrlen)
419{
420 struct MHD_IPCount *key;
421 void **nodep;
422 void *node;
423 enum MHD_Result result;
424
425 daemon = MHD_get_master (daemon);
426 /* Ignore if no connection limit assigned */
427 if (0 == daemon->per_ip_connection_limit)
428 return MHD_YES;
429
430 if (NULL == (key = malloc (sizeof(*key))))
431 return MHD_NO;
432
433 /* Initialize key */
434 if (MHD_NO == MHD_ip_addr_to_key (addr,
435 addrlen,
436 key))
437 {
438 /* Allow unhandled address types through */
439 free (key);
440 return MHD_YES;
441 }
442 MHD_ip_count_lock (daemon);
443
444 /* Search for the IP address */
445 if (NULL == (nodep = tsearch (key,
448 {
449#ifdef HAVE_MESSAGES
450 MHD_DLOG (daemon,
451 _ ("Failed to add IP connection count node.\n"));
452#endif
453 MHD_ip_count_unlock (daemon);
454 free (key);
455 return MHD_NO;
456 }
457 node = *nodep;
458 /* If we got an existing node back, free the one we created */
459 if (node != key)
460 free (key);
461 key = (struct MHD_IPCount *) node;
462 /* Test if there is room for another connection; if so,
463 * increment count */
464 result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
465 if (MHD_YES == result)
466 ++key->count;
467
468 MHD_ip_count_unlock (daemon);
469 return result;
470}
471
472
481static void
483 const struct sockaddr *addr,
484 socklen_t addrlen)
485{
486 struct MHD_IPCount search_key;
487 struct MHD_IPCount *found_key;
488 void **nodep;
489
490 daemon = MHD_get_master (daemon);
491 /* Ignore if no connection limit assigned */
492 if (0 == daemon->per_ip_connection_limit)
493 return;
494 /* Initialize search key */
495 if (MHD_NO == MHD_ip_addr_to_key (addr,
496 addrlen,
497 &search_key))
498 return;
499
500 MHD_ip_count_lock (daemon);
501
502 /* Search for the IP address */
503 if (NULL == (nodep = tfind (&search_key,
506 {
507 /* Something's wrong if we couldn't find an IP address
508 * that was previously added */
509 MHD_PANIC (_ ("Failed to find previously-added IP address.\n"));
510 }
511 found_key = (struct MHD_IPCount *) *nodep;
512 /* Validate existing count for IP address */
513 if (0 == found_key->count)
514 {
515 MHD_PANIC (_ ("Previously-added IP address had counter of zero.\n"));
516 }
517 /* Remove the node entirely if count reduces to 0 */
518 if (0 == --found_key->count)
519 {
520 tdelete (found_key,
523 free (found_key);
524 }
525
526 MHD_ip_count_unlock (daemon);
527}
528
529
530#ifdef HTTPS_SUPPORT
537static int
538MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
539{
540 gnutls_datum_t key;
541 gnutls_datum_t cert;
542 int ret;
543
544#if GNUTLS_VERSION_MAJOR >= 3
545 if (NULL != daemon->cert_callback)
546 {
547 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
548 daemon->cert_callback);
549 }
550#endif
551#if GNUTLS_VERSION_NUMBER >= 0x030603
552 else if (NULL != daemon->cert_callback2)
553 {
554 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
555 daemon->cert_callback2);
556 }
557#endif
558
559 if (NULL != daemon->https_mem_trust)
560 {
561 size_t paramlen;
562 paramlen = strlen (daemon->https_mem_trust);
563 if (UINT_MAX < paramlen)
564 {
565#ifdef HAVE_MESSAGES
566 MHD_DLOG (daemon,
567 "Too long trust certificate.\n");
568#endif
569 return -1;
570 }
571 cert.data = (unsigned char *) daemon->https_mem_trust;
572 cert.size = (unsigned int) paramlen;
573 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
574 &cert,
575 GNUTLS_X509_FMT_PEM) < 0)
576 {
577#ifdef HAVE_MESSAGES
578 MHD_DLOG (daemon,
579 "Bad trust certificate format.\n");
580#endif
581 return -1;
582 }
583 }
584
585 if (daemon->have_dhparams)
586 {
587 gnutls_certificate_set_dh_params (daemon->x509_cred,
588 daemon->https_mem_dhparams);
589 }
590 /* certificate & key loaded from memory */
591 if ( (NULL != daemon->https_mem_cert) &&
592 (NULL != daemon->https_mem_key) )
593 {
594 size_t param1len;
595 size_t param2len;
596
597 param1len = strlen (daemon->https_mem_key);
598 param2len = strlen (daemon->https_mem_cert);
599 if ( (UINT_MAX < param1len) ||
600 (UINT_MAX < param2len) )
601 {
602#ifdef HAVE_MESSAGES
603 MHD_DLOG (daemon,
604 "Too long key or certificate.\n");
605#endif
606 return -1;
607 }
608 key.data = (unsigned char *) daemon->https_mem_key;
609 key.size = (unsigned int) param1len;
610 cert.data = (unsigned char *) daemon->https_mem_cert;
611 cert.size = (unsigned int) param2len;
612
613 if (NULL != daemon->https_key_password)
614 {
615#if GNUTLS_VERSION_NUMBER >= 0x030111
616 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
617 &cert,
618 &key,
619 GNUTLS_X509_FMT_PEM,
620 daemon->https_key_password,
621 0);
622#else
623#ifdef HAVE_MESSAGES
624 MHD_DLOG (daemon,
625 _ ("Failed to setup x509 certificate/key: pre 3.X.X version " \
626 "of GnuTLS does not support setting key password.\n"));
627#endif
628 return -1;
629#endif
630 }
631 else
632 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
633 &cert,
634 &key,
635 GNUTLS_X509_FMT_PEM);
636#ifdef HAVE_MESSAGES
637 if (0 != ret)
638 MHD_DLOG (daemon,
639 "GnuTLS failed to setup x509 certificate/key: %s\n",
640 gnutls_strerror (ret));
641#endif
642 return ret;
643 }
644#if GNUTLS_VERSION_MAJOR >= 3
645 if (NULL != daemon->cert_callback)
646 return 0;
647#endif
648#if GNUTLS_VERSION_NUMBER >= 0x030603
649 else if (NULL != daemon->cert_callback2)
650 return 0;
651#endif
652#ifdef HAVE_MESSAGES
653 MHD_DLOG (daemon,
654 "You need to specify a certificate and key location.\n");
655#endif
656 return -1;
657}
658
659
666static int
667MHD_TLS_init (struct MHD_Daemon *daemon)
668{
669 switch (daemon->cred_type)
670 {
671 case GNUTLS_CRD_CERTIFICATE:
672 if (0 !=
673 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
674 return GNUTLS_E_MEMORY_ERROR;
675 return MHD_init_daemon_certificate (daemon);
676 case GNUTLS_CRD_PSK:
677 if (0 !=
678 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
679 return GNUTLS_E_MEMORY_ERROR;
680 return 0;
681 default:
682#ifdef HAVE_MESSAGES
683 MHD_DLOG (daemon,
684 _ ("Error: invalid credentials type %d specified.\n"),
685 daemon->cred_type);
686#endif
687 return -1;
688 }
689}
690
691
692#endif /* HTTPS_SUPPORT */
693
694
695#undef MHD_get_fdset
696
726enum MHD_Result
727MHD_get_fdset (struct MHD_Daemon *daemon,
728 fd_set *read_fd_set,
729 fd_set *write_fd_set,
730 fd_set *except_fd_set,
731 MHD_socket *max_fd)
732{
733 return MHD_get_fdset2 (daemon,
734 read_fd_set,
735 write_fd_set,
736 except_fd_set,
737 max_fd,
739}
740
741
742#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
755static bool
756urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
757 fd_set *rs,
758 fd_set *ws,
759 fd_set *es,
760 MHD_socket *max_fd,
761 unsigned int fd_setsize)
762{
763 const MHD_socket conn_sckt = urh->connection->socket_fd;
764 const MHD_socket mhd_sckt = urh->mhd.socket;
765 bool res = true;
766
767 /* Do not add to 'es' only if socket is closed
768 * or not used anymore. */
769 if (MHD_INVALID_SOCKET != conn_sckt)
770 {
771 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
772 (! MHD_add_to_fd_set_ (conn_sckt,
773 rs,
774 max_fd,
775 fd_setsize)) )
776 res = false;
777 if ( (0 != urh->out_buffer_used) &&
778 (! MHD_add_to_fd_set_ (conn_sckt,
779 ws,
780 max_fd,
781 fd_setsize)) )
782 res = false;
783 /* Do not monitor again for errors if error was detected before as
784 * error state is remembered. */
785 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
786 ((0 != urh->in_buffer_size) ||
787 (0 != urh->out_buffer_size) ||
788 (0 != urh->out_buffer_used)))
789 MHD_add_to_fd_set_ (conn_sckt,
790 es,
791 max_fd,
792 fd_setsize);
793 }
794 if (MHD_INVALID_SOCKET != mhd_sckt)
795 {
796 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
797 (! MHD_add_to_fd_set_ (mhd_sckt,
798 rs,
799 max_fd,
800 fd_setsize)) )
801 res = false;
802 if ( (0 != urh->in_buffer_used) &&
803 (! MHD_add_to_fd_set_ (mhd_sckt,
804 ws,
805 max_fd,
806 fd_setsize)) )
807 res = false;
808 /* Do not monitor again for errors if error was detected before as
809 * error state is remembered. */
810 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
811 ((0 != urh->out_buffer_size) ||
812 (0 != urh->in_buffer_size) ||
813 (0 != urh->in_buffer_used)))
814 MHD_add_to_fd_set_ (mhd_sckt,
815 es,
816 max_fd,
817 fd_setsize);
818 }
819
820 return res;
821}
822
823
833static void
834urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
835 const fd_set *rs,
836 const fd_set *ws,
837 const fd_set *es)
838{
839 const MHD_socket conn_sckt = urh->connection->socket_fd;
840 const MHD_socket mhd_sckt = urh->mhd.socket;
841
842 /* Reset read/write ready, preserve error state. */
843 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
844 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
845
846 if (MHD_INVALID_SOCKET != conn_sckt)
847 {
848 if (FD_ISSET (conn_sckt, rs))
849 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
850 if (FD_ISSET (conn_sckt, ws))
851 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
852 if (FD_ISSET (conn_sckt, es))
853 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
854 }
855 if ((MHD_INVALID_SOCKET != mhd_sckt))
856 {
857 if (FD_ISSET (mhd_sckt, rs))
858 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
859 if (FD_ISSET (mhd_sckt, ws))
860 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
861 if (FD_ISSET (mhd_sckt, es))
862 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
863 }
864}
865
866
867#ifdef HAVE_POLL
868
877static void
878urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
879 struct pollfd p[2])
880{
881 p[0].events = 0;
882 p[1].events = 0;
883
884 if (urh->in_buffer_used < urh->in_buffer_size)
885 p[0].events |= POLLIN;
886 if (0 != urh->out_buffer_used)
887 p[0].events |= POLLOUT;
888
889 /* Do not monitor again for errors if error was detected before as
890 * error state is remembered. */
891 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
892 ((0 != urh->in_buffer_size) ||
893 (0 != urh->out_buffer_size) ||
894 (0 != urh->out_buffer_used)))
895 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
896
897 if (urh->out_buffer_used < urh->out_buffer_size)
898 p[1].events |= POLLIN;
899 if (0 != urh->in_buffer_used)
900 p[1].events |= POLLOUT;
901
902 /* Do not monitor again for errors if error was detected before as
903 * error state is remembered. */
904 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
905 ((0 != urh->out_buffer_size) ||
906 (0 != urh->in_buffer_size) ||
907 (0 != urh->in_buffer_used)))
908 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
909}
910
911
918static void
919urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
920 struct pollfd p[2])
921{
922 p[0].fd = urh->connection->socket_fd;
923 p[1].fd = urh->mhd.socket;
924 urh_update_pollfd (urh,
925 p);
926}
927
928
934static void
935urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
936 struct pollfd p[2])
937{
938 /* Reset read/write ready, preserve error state. */
939 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
940 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
941
942 if (0 != (p[0].revents & POLLIN))
943 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
944 if (0 != (p[0].revents & POLLOUT))
945 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
946 if (0 != (p[0].revents & POLLHUP))
948 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
949 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
950 if (0 != (p[1].revents & POLLIN))
951 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
952 if (0 != (p[1].revents & POLLOUT))
953 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
954 if (0 != (p[1].revents & POLLHUP))
955 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
956 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
958}
959
960
961#endif /* HAVE_POLL */
962#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
963
964
979static enum MHD_Result
981 fd_set *read_fd_set,
982 fd_set *write_fd_set,
983 fd_set *except_fd_set,
984 MHD_socket *max_fd,
985 unsigned int fd_setsize)
986
987{
988 struct MHD_Connection *pos;
989 struct MHD_Connection *posn;
990 enum MHD_Result result = MHD_YES;
991 MHD_socket ls;
992
993 if (daemon->shutdown)
994 return MHD_NO;
995
996 ls = daemon->listen_fd;
997 if ( (MHD_INVALID_SOCKET != ls) &&
998 (! daemon->was_quiesced) &&
999 (! MHD_add_to_fd_set_ (ls,
1000 read_fd_set,
1001 max_fd,
1002 fd_setsize)) )
1003 result = MHD_NO;
1004
1005 /* Add all sockets to 'except_fd_set' as well to watch for
1006 * out-of-band data. However, ignore errors if INFO_READ
1007 * or INFO_WRITE sockets will not fit 'except_fd_set'. */
1008 /* Start from oldest connections. Make sense for W32 FDSETs. */
1009 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1010 {
1011 posn = pos->prev;
1012
1013 switch (pos->event_loop_info)
1014 {
1016 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1017 read_fd_set,
1018 max_fd,
1019 fd_setsize))
1020 result = MHD_NO;
1021#ifdef MHD_POSIX_SOCKETS
1023 except_fd_set,
1024 max_fd,
1025 fd_setsize);
1026#endif /* MHD_POSIX_SOCKETS */
1027 break;
1029 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1030 write_fd_set,
1031 max_fd,
1032 fd_setsize))
1033 result = MHD_NO;
1034#ifdef MHD_POSIX_SOCKETS
1036 except_fd_set,
1037 max_fd,
1038 fd_setsize);
1039#endif /* MHD_POSIX_SOCKETS */
1040 break;
1042 if ( (NULL == except_fd_set) ||
1044 except_fd_set,
1045 max_fd,
1046 fd_setsize))
1047 result = MHD_NO;
1048 break;
1050 /* this should never happen */
1051 break;
1052 }
1053 }
1054#ifdef MHD_WINSOCK_SOCKETS
1055 /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
1056 * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
1057 * not be pushed out. */
1058 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1059 {
1060 posn = pos->prev;
1062 except_fd_set,
1063 max_fd,
1064 fd_setsize);
1065 }
1066#endif /* MHD_WINSOCK_SOCKETS */
1067#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1068 {
1069 struct MHD_UpgradeResponseHandle *urh;
1070
1071 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
1072 {
1073 if (MHD_NO ==
1074 urh_to_fdset (urh,
1075 read_fd_set,
1076 write_fd_set,
1077 except_fd_set,
1078 max_fd,
1079 fd_setsize))
1080 result = MHD_NO;
1081 }
1082 }
1083#endif
1084#if DEBUG_CONNECT
1085#ifdef HAVE_MESSAGES
1086 if (NULL != max_fd)
1087 MHD_DLOG (daemon,
1088 _ ("Maximum socket in select set: %d\n"),
1089 *max_fd);
1090#endif
1091#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1092 return result;
1093}
1094
1095
1128enum MHD_Result
1130 fd_set *read_fd_set,
1131 fd_set *write_fd_set,
1132 fd_set *except_fd_set,
1133 MHD_socket *max_fd,
1134 unsigned int fd_setsize)
1135{
1136 fd_set es;
1137
1138 if ( (NULL == daemon) ||
1139 (NULL == read_fd_set) ||
1140 (NULL == write_fd_set) ||
1141 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ||
1142 (0 != (daemon->options & MHD_USE_POLL)))
1143 return MHD_NO;
1144
1145 if (NULL == except_fd_set)
1146 { /* Workaround to maintain backward compatibility. */
1147#ifdef HAVE_MESSAGES
1148 MHD_DLOG (daemon,
1149 _ ("MHD_get_fdset2() called with except_fd_set "
1150 "set to NULL. Such behavior is unsupported.\n"));
1151#endif
1152 FD_ZERO (&es);
1153 except_fd_set = &es;
1154 }
1155
1156#ifdef EPOLL_SUPPORT
1157 if (0 != (daemon->options & MHD_USE_EPOLL))
1158 {
1159 if (daemon->shutdown)
1160 return MHD_NO;
1161
1162 /* we're in epoll mode, use the epoll FD as a stand-in for
1163 the entire event set */
1164
1165 return MHD_add_to_fd_set_ (daemon->epoll_fd,
1166 read_fd_set,
1167 max_fd,
1168 fd_setsize) ? MHD_YES : MHD_NO;
1169 }
1170#endif
1171
1172 return internal_get_fdset2 (daemon,
1173 read_fd_set,
1174 write_fd_set,
1175 except_fd_set,
1176 max_fd,
1177 fd_setsize);
1178}
1179
1180
1194static enum MHD_Result
1196 bool read_ready,
1197 bool write_ready,
1198 bool force_close)
1199{
1200 enum MHD_Result ret;
1201 bool states_info_processed = false;
1202 /* Fast track flag */
1203 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1204
1205#ifdef HTTPS_SUPPORT
1206 if (con->tls_read_ready)
1207 read_ready = true;
1208#endif /* HTTPS_SUPPORT */
1209 if (! force_close)
1210 {
1212 read_ready)
1213 {
1215 ret = MHD_connection_handle_idle (con);
1216 states_info_processed = true;
1217 }
1218 /* No need to check value of 'ret' here as closed connection
1219 * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1221 write_ready)
1222 {
1224 ret = MHD_connection_handle_idle (con);
1225 states_info_processed = true;
1226 }
1227 }
1228 else
1229 {
1232 return MHD_connection_handle_idle (con);
1233 }
1234
1235 if (! states_info_processed)
1236 { /* Connection is not read or write ready, but external conditions
1237 * may be changed and need to be processed. */
1238 ret = MHD_connection_handle_idle (con);
1239 }
1240 /* Fast track for fast connections. */
1241 /* If full request was read by single read_handler() invocation
1242 and headers were completely prepared by single MHD_connection_handle_idle()
1243 then try not to wait for next sockets polling and send response
1244 immediately.
1245 As writeability of socket was not checked and it may have
1246 some data pending in system buffers, use this optimization
1247 only for non-blocking sockets. *//* No need to check 'ret' as connection is always in
1248 * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */else if (on_fasttrack && con->sk_nonblck)
1249 {
1251 {
1253 /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1254 ret = MHD_connection_handle_idle (con);
1255 }
1256 /* If all headers were sent by single write_handler() and
1257 * response body is prepared by single MHD_connection_handle_idle()
1258 * call - continue. */
1261 {
1263 ret = MHD_connection_handle_idle (con);
1264 }
1265 }
1266
1267 /* All connection's data and states are processed for this turn.
1268 * If connection already has more data to be processed - use
1269 * zero timeout for next select()/poll(). */
1270 /* Thread-per-connection do not need global zero timeout as
1271 * connections are processed individually. */
1272 /* Note: no need to check for read buffer availability for
1273 * TLS read-ready connection in 'read info' state as connection
1274 * without space in read buffer will be marked as 'info block'. */
1275 if ( (! con->daemon->data_already_pending) &&
1277 {
1279 con->daemon->data_already_pending = true;
1280#ifdef HTTPS_SUPPORT
1281 else if ( (con->tls_read_ready) &&
1283 con->daemon->data_already_pending = true;
1284#endif /* HTTPS_SUPPORT */
1285 }
1286 return ret;
1287}
1288
1289
1290#ifdef UPGRADE_SUPPORT
1298static void
1299cleanup_upgraded_connection (struct MHD_Connection *connection)
1300{
1301 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1302
1303 if (NULL == urh)
1304 return;
1305#ifdef HTTPS_SUPPORT
1306 /* Signal remote client the end of TLS connection by
1307 * gracefully closing TLS session. */
1308 if (0 != (connection->daemon->options & MHD_USE_TLS))
1309 gnutls_bye (connection->tls_session,
1310 GNUTLS_SHUT_WR);
1311
1312 if (MHD_INVALID_SOCKET != urh->mhd.socket)
1313 MHD_socket_close_chk_ (urh->mhd.socket);
1314
1315 if (MHD_INVALID_SOCKET != urh->app.socket)
1316 MHD_socket_close_chk_ (urh->app.socket);
1317#endif /* HTTPS_SUPPORT */
1318 connection->urh = NULL;
1319 free (urh);
1320}
1321
1322
1323#endif /* UPGRADE_SUPPORT */
1324
1325
1326#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1335static void
1336process_urh (struct MHD_UpgradeResponseHandle *urh)
1337{
1338 /* Help compiler to optimize:
1339 * pointers to 'connection' and 'daemon' are not changed
1340 * during this processing, so no need to chain dereference
1341 * each time. */
1342 struct MHD_Connection *const connection = urh->connection;
1343 struct MHD_Daemon *const daemon = connection->daemon;
1344 /* Prevent data races: use same value of 'was_closed' throughout
1345 * this function. If 'was_closed' changed externally in the middle
1346 * of processing - it will be processed on next iteration. */
1347 bool was_closed;
1348 if (daemon->shutdown)
1349 {
1350 /* Daemon shutting down, application will not receive any more data. */
1351#ifdef HAVE_MESSAGES
1352 if (! urh->was_closed)
1353 {
1354 MHD_DLOG (daemon,
1355 _ (
1356 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1357 }
1358#endif
1359 urh->was_closed = true;
1360 }
1361 was_closed = urh->was_closed;
1362 if (was_closed)
1363 {
1364 /* Application was closed connections: no more data
1365 * can be forwarded to application socket. */
1366 if (0 < urh->in_buffer_used)
1367 {
1368#ifdef HAVE_MESSAGES
1369 MHD_DLOG (daemon,
1370 _ (
1371 "Failed to forward to application "
1373 " bytes of data received from remote side: application shut down socket.\n"),
1374 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used);
1375#endif
1376
1377 }
1378 /* If application signaled MHD about socket closure then
1379 * check for any pending data even if socket is not marked
1380 * as 'ready' (signal may arrive after poll()/select()).
1381 * Socketpair for forwarding is always in non-blocking mode
1382 * so no risk that recv() will block the thread. */if (0 != urh->out_buffer_size)
1383 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1384 /* Discard any data received form remote. */
1385 urh->in_buffer_used = 0;
1386 /* Do not try to push data to application. */
1387 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1388 /* Reading from remote client is not required anymore. */
1389 urh->in_buffer_size = 0;
1390 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1391 connection->tls_read_ready = false;
1392 }
1393
1394 /* On some platforms (W32, possibly Darwin) failed send() (send() will always
1395 * fail after remote disconnect was detected) may discard data in system
1396 * buffers received by system but not yet read by recv().
1397 * So, before trying send() on any socket, recv() must be performed at first
1398 * otherwise last part of incoming data may be lost. *//* If disconnect or error was detected - try to read from socket
1399 * to dry data possibly pending is system buffers. */if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1400 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1401 if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1402 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1403
1404 /*
1405 * handle reading from remote TLS client
1406 */
1407 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1408 (connection->tls_read_ready) ) &&
1409 (urh->in_buffer_used < urh->in_buffer_size) )
1410 {
1411 ssize_t res;
1412 size_t buf_size;
1413
1414 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1415 if (buf_size > SSIZE_MAX)
1416 buf_size = SSIZE_MAX;
1417
1418 connection->tls_read_ready = false;
1419 res = gnutls_record_recv (connection->tls_session,
1420 &urh->in_buffer[urh->in_buffer_used],
1421 buf_size);
1422 if (0 >= res)
1423 {
1424 if (GNUTLS_E_INTERRUPTED != res)
1425 {
1426 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1427 if (GNUTLS_E_AGAIN != res)
1428 {
1429 /* Unrecoverable error on socket was detected or
1430 * socket was disconnected/shut down. */
1431 /* Stop trying to read from this TLS socket. */
1432 urh->in_buffer_size = 0;
1433 }
1434 }
1435 }
1436 else /* 0 < res */
1437 {
1438 urh->in_buffer_used += res;
1439 if (buf_size > (size_t) res)
1440 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1441 else if (0 < gnutls_record_check_pending (connection->tls_session))
1442 connection->tls_read_ready = true;
1443 }
1446 {
1447 /* Unrecoverable error on socket was detected and all
1448 * pending data was read from system buffers. */
1449 /* Stop trying to read from this TLS socket. */
1450 urh->in_buffer_size = 0;
1451 }
1452 }
1453
1454 /*
1455 * handle reading from application
1456 */
1457 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1458 (urh->out_buffer_used < urh->out_buffer_size) )
1459 {
1460 ssize_t res;
1461 size_t buf_size;
1462
1463 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1464 if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1465 buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1466
1467 res = MHD_recv_ (urh->mhd.socket,
1468 &urh->out_buffer[urh->out_buffer_used],
1469 buf_size);
1470 if (0 >= res)
1471 {
1472 const int err = MHD_socket_get_error_ ();
1473 if ((0 == res) ||
1474 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1476 {
1477 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1478 if ((0 == res) ||
1479 (was_closed) ||
1480 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1481 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1482 {
1483 /* Socket disconnect/shutdown was detected;
1484 * Application signaled about closure of 'upgraded' socket;
1485 * or persistent / unrecoverable error. */
1486 /* Do not try to pull more data from application. */
1487 urh->out_buffer_size = 0;
1488 }
1489 }
1490 }
1491 else /* 0 < res */
1492 {
1493 urh->out_buffer_used += res;
1494 if (buf_size > (size_t) res)
1495 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1496 }
1497 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1498 ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1499 (was_closed) ) )
1500 {
1501 /* Unrecoverable error on socket was detected and all
1502 * pending data was read from system buffers. */
1503 /* Do not try to pull more data from application. */
1504 urh->out_buffer_size = 0;
1505 }
1506 }
1507
1508 /*
1509 * handle writing to remote HTTPS client
1510 */
1511 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1512 (urh->out_buffer_used > 0) )
1513 {
1514 ssize_t res;
1515 size_t data_size;
1516
1517 data_size = urh->out_buffer_used;
1518 if (data_size > SSIZE_MAX)
1519 data_size = SSIZE_MAX;
1520
1521 res = gnutls_record_send (connection->tls_session,
1522 urh->out_buffer,
1523 data_size);
1524 if (0 >= res)
1525 {
1526 if (GNUTLS_E_INTERRUPTED != res)
1527 {
1528 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1529 if (GNUTLS_E_AGAIN != res)
1530 {
1531 /* TLS connection shut down or
1532 * persistent / unrecoverable error. */
1533#ifdef HAVE_MESSAGES
1534 MHD_DLOG (daemon,
1535 _ (
1536 "Failed to forward to remote client "
1538 " bytes of data received from application: %s\n"),
1539 (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1540 gnutls_strerror (res));
1541#endif
1542 /* Discard any data unsent to remote. */
1543 urh->out_buffer_used = 0;
1544 /* Do not try to pull more data from application. */
1545 urh->out_buffer_size = 0;
1546 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1547 }
1548 }
1549 }
1550 else /* 0 < res */
1551 {
1552 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1553 if (0 != next_out_buffer_used)
1554 {
1555 memmove (urh->out_buffer,
1556 &urh->out_buffer[res],
1557 next_out_buffer_used);
1558 if (data_size > (size_t) res)
1559 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1560 }
1561 urh->out_buffer_used = next_out_buffer_used;
1562 }
1563 if ( (0 == urh->out_buffer_used) &&
1564 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1565 {
1566 /* Unrecoverable error on socket was detected and all
1567 * pending data was sent to remote. */
1568 /* Do not try to send to remote anymore. */
1569 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1570 /* Do not try to pull more data from application. */
1571 urh->out_buffer_size = 0;
1572 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1573 }
1574 }
1575
1576 /*
1577 * handle writing to application
1578 */
1579 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1580 (urh->in_buffer_used > 0) )
1581 {
1582 ssize_t res;
1583 size_t data_size;
1584
1585 data_size = urh->in_buffer_used;
1586 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1587 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1588
1589 res = MHD_send_ (urh->mhd.socket,
1590 urh->in_buffer,
1591 data_size);
1592 if (0 >= res)
1593 {
1594 const int err = MHD_socket_get_error_ ();
1595 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1597 {
1598 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1599 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1600 {
1601 /* Socketpair connection shut down or
1602 * persistent / unrecoverable error. */
1603#ifdef HAVE_MESSAGES
1604 MHD_DLOG (daemon,
1605 _ (
1606 "Failed to forward to application "
1608 " bytes of data received from remote side: %s\n"),
1609 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1610 MHD_socket_strerr_ (err));
1611#endif
1612 /* Discard any data received form remote. */
1613 urh->in_buffer_used = 0;
1614 /* Reading from remote client is not required anymore. */
1615 urh->in_buffer_size = 0;
1616 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1617 connection->tls_read_ready = false;
1618 }
1619 }
1620 }
1621 else /* 0 < res */
1622 {
1623 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1624 if (0 != next_in_buffer_used)
1625 {
1626 memmove (urh->in_buffer,
1627 &urh->in_buffer[res],
1628 next_in_buffer_used);
1629 if (data_size > (size_t) res)
1630 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1631 }
1632 urh->in_buffer_used = next_in_buffer_used;
1633 }
1634 if ( (0 == urh->in_buffer_used) &&
1635 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1636 {
1637 /* Do not try to push data to application. */
1638 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1639 /* Reading from remote client is not required anymore. */
1640 urh->in_buffer_size = 0;
1641 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1642 connection->tls_read_ready = false;
1643 }
1644 }
1645
1646 /* Check whether data is present in TLS buffers
1647 * and incoming forward buffer have some space. */
1648 if ( (connection->tls_read_ready) &&
1649 (urh->in_buffer_used < urh->in_buffer_size) &&
1650 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1651 daemon->data_already_pending = true;
1652
1653 if ( (daemon->shutdown) &&
1654 ( (0 != urh->out_buffer_size) ||
1655 (0 != urh->out_buffer_used) ) )
1656 {
1657 /* Daemon shutting down, discard any remaining forward data. */
1658#ifdef HAVE_MESSAGES
1659 if (0 < urh->out_buffer_used)
1660 MHD_DLOG (daemon,
1661 _ (
1662 "Failed to forward to remote client "
1664 " bytes of data received from application: daemon shut down.\n"),
1665 (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
1666#endif
1667 /* Discard any data unsent to remote. */
1668 urh->out_buffer_used = 0;
1669 /* Do not try to sent to remote anymore. */
1670 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1671 /* Do not try to pull more data from application. */
1672 urh->out_buffer_size = 0;
1673 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1674 }
1675}
1676
1677
1678#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1679
1680#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1681#ifdef UPGRADE_SUPPORT
1690static void
1691thread_main_connection_upgrade (struct MHD_Connection *con)
1692{
1693#ifdef HTTPS_SUPPORT
1694 struct MHD_UpgradeResponseHandle *urh = con->urh;
1695 struct MHD_Daemon *daemon = con->daemon;
1696
1697 /* Here, we need to bi-directionally forward
1698 until the application tells us that it is done
1699 with the socket; */
1700 if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1701 (0 == (daemon->options & MHD_USE_POLL)))
1702 {
1703 while ( (0 != urh->in_buffer_size) ||
1704 (0 != urh->out_buffer_size) ||
1705 (0 != urh->in_buffer_used) ||
1706 (0 != urh->out_buffer_used) )
1707 {
1708 /* use select */
1709 fd_set rs;
1710 fd_set ws;
1711 fd_set es;
1712 MHD_socket max_fd;
1713 int num_ready;
1714 bool result;
1715
1716 FD_ZERO (&rs);
1717 FD_ZERO (&ws);
1718 FD_ZERO (&es);
1719 max_fd = MHD_INVALID_SOCKET;
1720 result = urh_to_fdset (urh,
1721 &rs,
1722 &ws,
1723 &es,
1724 &max_fd,
1725 FD_SETSIZE);
1726 if (! result)
1727 {
1728#ifdef HAVE_MESSAGES
1729 MHD_DLOG (con->daemon,
1730 _ ("Error preparing select.\n"));
1731#endif
1732 break;
1733 }
1734 /* FIXME: does this check really needed? */
1735 if (MHD_INVALID_SOCKET != max_fd)
1736 {
1737 struct timeval*tvp;
1738 struct timeval tv;
1739 if ( (con->tls_read_ready) &&
1740 (urh->in_buffer_used < urh->in_buffer_size))
1741 { /* No need to wait if incoming data is already pending in TLS buffers. */
1742 tv.tv_sec = 0;
1743 tv.tv_usec = 0;
1744 tvp = &tv;
1745 }
1746 else
1747 tvp = NULL;
1748 num_ready = MHD_SYS_select_ (max_fd + 1,
1749 &rs,
1750 &ws,
1751 &es,
1752 tvp);
1753 }
1754 else
1755 num_ready = 0;
1756 if (num_ready < 0)
1757 {
1758 const int err = MHD_socket_get_error_ ();
1759
1760 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1761 continue;
1762#ifdef HAVE_MESSAGES
1763 MHD_DLOG (con->daemon,
1764 _ ("Error during select (%d): `%s'\n"),
1765 err,
1766 MHD_socket_strerr_ (err));
1767#endif
1768 break;
1769 }
1770 urh_from_fdset (urh,
1771 &rs,
1772 &ws,
1773 &es);
1774 process_urh (urh);
1775 }
1776 }
1777#ifdef HAVE_POLL
1778 else if (0 != (daemon->options & MHD_USE_TLS))
1779 {
1780 /* use poll() */
1781 struct pollfd p[2];
1782 memset (p,
1783 0,
1784 sizeof (p));
1785 p[0].fd = urh->connection->socket_fd;
1786 p[1].fd = urh->mhd.socket;
1787
1788 while ( (0 != urh->in_buffer_size) ||
1789 (0 != urh->out_buffer_size) ||
1790 (0 != urh->in_buffer_used) ||
1791 (0 != urh->out_buffer_used) )
1792 {
1793 int timeout;
1794
1795 urh_update_pollfd (urh, p);
1796
1797 if ( (con->tls_read_ready) &&
1798 (urh->in_buffer_used < urh->in_buffer_size))
1799 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1800 else
1801 timeout = -1;
1802
1803 if (MHD_sys_poll_ (p,
1804 2,
1805 timeout) < 0)
1806 {
1807 const int err = MHD_socket_get_error_ ();
1808
1809 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1810 continue;
1811#ifdef HAVE_MESSAGES
1812 MHD_DLOG (con->daemon,
1813 _ ("Error during poll: `%s'\n"),
1814 MHD_socket_strerr_ (err));
1815#endif
1816 break;
1817 }
1818 urh_from_pollfd (urh,
1819 p);
1820 process_urh (urh);
1821 }
1822 }
1823 /* end POLL */
1824#endif
1825 /* end HTTPS */
1826#endif /* HTTPS_SUPPORT */
1827 /* TLS forwarding was finished. Cleanup socketpair. */
1829 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1830 * in connection thread for a little while. */
1831}
1832
1833
1834#endif /* UPGRADE_SUPPORT */
1835
1836
1844static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1846{
1847 struct MHD_Connection *con = data;
1848 struct MHD_Daemon *daemon = con->daemon;
1849 int num_ready;
1850 fd_set rs;
1851 fd_set ws;
1852 fd_set es;
1853 MHD_socket maxsock;
1854 struct timeval tv;
1855 struct timeval *tvp;
1856 time_t now;
1857#if WINDOWS
1858#ifdef HAVE_POLL
1859 int extra_slot;
1860#endif /* HAVE_POLL */
1861#define EXTRA_SLOTS 1
1862#else /* !WINDOWS */
1863#define EXTRA_SLOTS 0
1864#endif /* !WINDOWS */
1865#ifdef HAVE_POLL
1866 struct pollfd p[1 + EXTRA_SLOTS];
1867#endif
1868#undef EXTRA_SLOTS
1869#ifdef HAVE_POLL
1870 const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1871#else /* ! HAVE_POLL */
1872 const bool use_poll = 0;
1873#endif /* ! HAVE_POLL */
1874 bool was_suspended = false;
1875 MHD_thread_init_ (&(con->pid));
1876
1877 while ( (! daemon->shutdown) &&
1878 (MHD_CONNECTION_CLOSED != con->state) )
1879 {
1880 const time_t timeout = daemon->connection_timeout;
1881#ifdef UPGRADE_SUPPORT
1882 struct MHD_UpgradeResponseHandle *const urh = con->urh;
1883#else /* ! UPGRADE_SUPPORT */
1884 static const void *const urh = NULL;
1885#endif /* ! UPGRADE_SUPPORT */
1886
1887 if ( (con->suspended) &&
1888 (NULL == urh) )
1889 {
1890 /* Connection was suspended, wait for resume. */
1891 was_suspended = true;
1892 if (! use_poll)
1893 {
1894 FD_ZERO (&rs);
1895 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1896 &rs,
1897 NULL,
1898 FD_SETSIZE))
1899 {
1900 #ifdef HAVE_MESSAGES
1901 MHD_DLOG (con->daemon,
1902 _ ("Failed to add FD to fd_set.\n"));
1903 #endif
1904 goto exit;
1905 }
1906 if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
1907 &rs,
1908 NULL,
1909 NULL,
1910 NULL))
1911 {
1912 const int err = MHD_socket_get_error_ ();
1913
1914 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1915 continue;
1916#ifdef HAVE_MESSAGES
1917 MHD_DLOG (con->daemon,
1918 _ ("Error during select (%d): `%s'\n"),
1919 err,
1920 MHD_socket_strerr_ (err));
1921#endif
1922 break;
1923 }
1924 }
1925#ifdef HAVE_POLL
1926 else /* use_poll */
1927 {
1928 p[0].events = POLLIN;
1929 p[0].fd = MHD_itc_r_fd_ (daemon->itc);
1930 p[0].revents = 0;
1931 if (0 > MHD_sys_poll_ (p,
1932 1,
1933 -1))
1934 {
1936 continue;
1937#ifdef HAVE_MESSAGES
1938 MHD_DLOG (con->daemon,
1939 _ ("Error during poll: `%s'\n"),
1941#endif
1942 break;
1943 }
1944 }
1945#endif /* HAVE_POLL */
1946 MHD_itc_clear_ (daemon->itc);
1947 continue; /* Check again for resume. */
1948 } /* End of "suspended" branch. */
1949
1950 if (was_suspended)
1951 {
1952 MHD_update_last_activity_ (con); /* Reset timeout timer. */
1953 /* Process response queued during suspend and update states. */
1955 was_suspended = false;
1956 }
1957
1958 tvp = NULL;
1959
1961#ifdef HTTPS_SUPPORT
1962 || ( (con->tls_read_ready) &&
1964#endif /* HTTPS_SUPPORT */
1965 )
1966 {
1967 /* do not block: more data may be inside of TLS buffers waiting or
1968 * application must provide response data */
1969 tv.tv_sec = 0;
1970 tv.tv_usec = 0;
1971 tvp = &tv;
1972 }
1973 if ( (NULL == tvp) &&
1974 (timeout > 0) )
1975 {
1977 if (now - con->last_activity > timeout)
1978 tv.tv_sec = 0;
1979 else
1980 {
1981 const time_t seconds_left = timeout - (now - con->last_activity);
1982#if ! defined(_WIN32) || defined(__CYGWIN__)
1983 tv.tv_sec = seconds_left;
1984#else /* _WIN32 && !__CYGWIN__ */
1985 if (seconds_left > TIMEVAL_TV_SEC_MAX)
1986 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1987 else
1988 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
1989#endif /* _WIN32 && ! __CYGWIN__ */
1990 }
1991 tv.tv_usec = 0;
1992 tvp = &tv;
1993 }
1994 if (! use_poll)
1995 {
1996 /* use select */
1997 bool err_state = false;
1998
1999 FD_ZERO (&rs);
2000 FD_ZERO (&ws);
2001 FD_ZERO (&es);
2002 maxsock = MHD_INVALID_SOCKET;
2003 switch (con->event_loop_info)
2004 {
2006 if (! MHD_add_to_fd_set_ (con->socket_fd,
2007 &rs,
2008 &maxsock,
2009 FD_SETSIZE))
2010 err_state = true;
2011 break;
2013 if (! MHD_add_to_fd_set_ (con->socket_fd,
2014 &ws,
2015 &maxsock,
2016 FD_SETSIZE))
2017 err_state = true;
2018 break;
2020 if (! MHD_add_to_fd_set_ (con->socket_fd,
2021 &es,
2022 &maxsock,
2023 FD_SETSIZE))
2024 err_state = true;
2025 break;
2027 /* how did we get here!? */
2028 goto exit;
2029 }
2030#if WINDOWS
2031 if (MHD_ITC_IS_VALID_ (daemon->itc) )
2032 {
2033 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2034 &rs,
2035 &maxsock,
2036 FD_SETSIZE))
2037 err_state = 1;
2038 }
2039#endif
2040 if (err_state)
2041 {
2042#ifdef HAVE_MESSAGES
2043 MHD_DLOG (con->daemon,
2044 _ ("Failed to add FD to fd_set.\n"));
2045#endif
2046 goto exit;
2047 }
2048
2049 num_ready = MHD_SYS_select_ (maxsock + 1,
2050 &rs,
2051 &ws,
2052 &es,
2053 tvp);
2054 if (num_ready < 0)
2055 {
2056 const int err = MHD_socket_get_error_ ();
2057
2058 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2059 continue;
2060#ifdef HAVE_MESSAGES
2061 MHD_DLOG (con->daemon,
2062 _ ("Error during select (%d): `%s'\n"),
2063 err,
2064 MHD_socket_strerr_ (err));
2065#endif
2066 break;
2067 }
2068#if WINDOWS
2069 /* Clear ITC before other processing so additional
2070 * signals will trigger select() again */
2071 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2072 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2073 &rs)) )
2074 MHD_itc_clear_ (daemon->itc);
2075#endif
2076 if (MHD_NO ==
2077 call_handlers (con,
2078 FD_ISSET (con->socket_fd,
2079 &rs),
2080 FD_ISSET (con->socket_fd,
2081 &ws),
2082 FD_ISSET (con->socket_fd,
2083 &es)) )
2084 goto exit;
2085 }
2086#ifdef HAVE_POLL
2087 else
2088 {
2089 /* use poll */
2090 memset (&p,
2091 0,
2092 sizeof (p));
2093 p[0].fd = con->socket_fd;
2094 switch (con->event_loop_info)
2095 {
2097 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2098 break;
2100 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2101 break;
2103 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2104 break;
2106 /* how did we get here!? */
2107 goto exit;
2108 }
2109#if WINDOWS
2110 extra_slot = 0;
2111 if (MHD_ITC_IS_VALID_ (daemon->itc))
2112 {
2113 p[1].events |= POLLIN;
2114 p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2115 p[1].revents = 0;
2116 extra_slot = 1;
2117 }
2118#endif
2119 if (MHD_sys_poll_ (p,
2120#if WINDOWS
2121 1 + extra_slot,
2122#else
2123 1,
2124#endif
2125 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2126 {
2128 continue;
2129#ifdef HAVE_MESSAGES
2130 MHD_DLOG (con->daemon,
2131 _ ("Error during poll: `%s'\n"),
2133#endif
2134 break;
2135 }
2136#if WINDOWS
2137 /* Clear ITC before other processing so additional
2138 * signals will trigger poll() again */
2139 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2140 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2141 MHD_itc_clear_ (daemon->itc);
2142#endif
2143 if (MHD_NO ==
2144 call_handlers (con,
2145 (0 != (p[0].revents & POLLIN)),
2146 (0 != (p[0].revents & POLLOUT)),
2147 (0 != (p[0].revents & (POLLERR
2148 | MHD_POLL_REVENTS_ERR_DISC))) ))
2149 goto exit;
2150 }
2151#endif
2152#ifdef UPGRADE_SUPPORT
2153 if (MHD_CONNECTION_UPGRADE == con->state)
2154 {
2155 /* Normal HTTP processing is finished,
2156 * notify application. */
2157 if ( (NULL != daemon->notify_completed) &&
2158 (con->client_aware) )
2159 daemon->notify_completed (daemon->notify_completed_cls,
2160 con,
2161 &con->client_context,
2163 con->client_aware = false;
2164
2165 thread_main_connection_upgrade (con);
2166 /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2167
2168 /* "Upgraded" data will not be used in this thread from this point. */
2169 con->urh->clean_ready = true;
2170 /* If 'urh->was_closed' set to true, connection will be
2171 * moved immediately to cleanup list. Otherwise connection
2172 * will stay in suspended list until 'urh' will be marked
2173 * with 'was_closed' by application. */
2175
2176 /* skip usual clean up */
2177 return (MHD_THRD_RTRN_TYPE_) 0;
2178 }
2179#endif /* UPGRADE_SUPPORT */
2180 }
2181#if DEBUG_CLOSE
2182#ifdef HAVE_MESSAGES
2183 MHD_DLOG (con->daemon,
2184 _ ("Processing thread terminating. Closing connection.\n"));
2185#endif
2186#endif
2187 if (MHD_CONNECTION_CLOSED != con->state)
2189 (daemon->shutdown) ?
2193exit:
2194 if (NULL != con->response)
2195 {
2197 con->response = NULL;
2198 }
2199
2200 if (MHD_INVALID_SOCKET != con->socket_fd)
2201 {
2202 shutdown (con->socket_fd,
2203 SHUT_WR);
2204 /* 'socket_fd' can be used in other thread to signal shutdown.
2205 * To avoid data races, do not close socket here. Daemon will
2206 * use more connections only after cleanup anyway. */
2207 }
2208 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2209 (! MHD_itc_activate_ (daemon->itc, "t")) )
2210 {
2211#ifdef HAVE_MESSAGES
2212 MHD_DLOG (daemon,
2213 _ (
2214 "Failed to signal thread termination via inter-thread communication channel.\n"));
2215#endif
2216 }
2217 return (MHD_THRD_RTRN_TYPE_) 0;
2218}
2219
2220
2221#endif
2222
2223
2231static void
2232MHD_cleanup_connections (struct MHD_Daemon *daemon);
2233
2234#if defined(HTTPS_SUPPORT)
2235#if ! defined(MHD_WINSOCK_SOCKETS) && ! defined(MHD_socket_nosignal_) && \
2236 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2242#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2243#endif /* !MHD_WINSOCK_SOCKETS && !MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) */
2244
2245#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2250static ssize_t
2251MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2252 const void *data,
2253 size_t data_size)
2254{
2255#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2256 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2257 data_size = MHD_SCKT_SEND_MAX_SIZE_;
2258#endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2259 return MHD_send_ ((MHD_socket) (intptr_t) (trnsp), data, data_size);
2260}
2261
2262
2263#endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2264
2265
2274static int
2275psk_gnutls_adapter (gnutls_session_t session,
2276 const char *username,
2277 gnutls_datum_t *key)
2278{
2279 struct MHD_Connection *connection;
2280 struct MHD_Daemon *daemon;
2281 void *app_psk;
2282 size_t app_psk_size;
2283
2284 connection = gnutls_session_get_ptr (session);
2285 if (NULL == connection)
2286 {
2287#ifdef HAVE_MESSAGES
2288 /* Cannot use our logger, we don't even have "daemon" */
2289 MHD_PANIC (_ ("Internal server error. This should be impossible.\n"));
2290#endif
2291 return -1;
2292 }
2293 daemon = connection->daemon;
2294#if GNUTLS_VERSION_MAJOR >= 3
2295 if (NULL == daemon->cred_callback)
2296 {
2297#ifdef HAVE_MESSAGES
2298 MHD_DLOG (daemon,
2299 _ ("PSK not supported by this server.\n"));
2300#endif
2301 return -1;
2302 }
2303 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2304 connection,
2305 username,
2306 &app_psk,
2307 &app_psk_size))
2308 return -1;
2309 if (NULL == (key->data = gnutls_malloc (app_psk_size)))
2310 {
2311#ifdef HAVE_MESSAGES
2312 MHD_DLOG (daemon,
2313 _ (
2314 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2315#endif
2316 free (app_psk);
2317 return -1;
2318 }
2319 if (UINT_MAX < app_psk_size)
2320 {
2321#ifdef HAVE_MESSAGES
2322 MHD_DLOG (daemon,
2323 _ ("PSK authentication failed: PSK too long.\n"));
2324#endif
2325 free (app_psk);
2326 return -1;
2327 }
2328 key->size = (unsigned int) app_psk_size;
2329 memcpy (key->data,
2330 app_psk,
2331 app_psk_size);
2332 free (app_psk);
2333 return 0;
2334#else
2335#ifdef HAVE_MESSAGES
2336 MHD_DLOG (daemon,
2337 _ ("PSK not supported by this server.\n"));
2338#endif
2339 return -1;
2340#endif
2341}
2342
2343
2344#endif /* HTTPS_SUPPORT */
2345
2346
2372static enum MHD_Result
2374 MHD_socket client_socket,
2375 const struct sockaddr *addr,
2376 socklen_t addrlen,
2377 bool external_add,
2378 bool non_blck)
2379{
2380 struct MHD_Connection *connection;
2381#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2382 unsigned int i;
2383#endif
2384 int eno = 0;
2385
2386 /* Direct add to master daemon could happen only with "external" add mode. */
2387#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2388 mhd_assert ((NULL == daemon->worker_pool) || (external_add));
2389 if ((external_add) && (NULL != daemon->worker_pool))
2390 {
2391 /* have a pool, try to find a pool with capacity; we use the
2392 socket as the initial offset into the pool for load
2393 balancing */
2394 for (i = 0; i < daemon->worker_pool_size; ++i)
2395 {
2396 struct MHD_Daemon *const worker =
2397 &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
2398 if (worker->connections < worker->connection_limit)
2399 return internal_add_connection (worker,
2400 client_socket,
2401 addr,
2402 addrlen,
2403 true,
2404 non_blck);
2405 }
2406 /* all pools are at their connection limit, must refuse */
2407 MHD_socket_close_chk_ (client_socket);
2408#if ENFILE
2409 errno = ENFILE;
2410#endif
2411 return MHD_NO;
2412 }
2413#endif
2414
2415 if ( (! MHD_SCKT_FD_FITS_FDSET_ (client_socket,
2416 NULL)) &&
2417 (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
2418 {
2419#ifdef HAVE_MESSAGES
2420 MHD_DLOG (daemon,
2421 _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2422 (int) client_socket,
2423 (int) FD_SETSIZE);
2424#endif
2425 MHD_socket_close_chk_ (client_socket);
2426#if EINVAL
2427 errno = EINVAL;
2428#endif
2429 return MHD_NO;
2430 }
2431
2432#ifdef MHD_socket_nosignal_
2433 if (! MHD_socket_nosignal_ (client_socket))
2434 {
2435#ifdef HAVE_MESSAGES
2436 MHD_DLOG (daemon,
2437 _ ("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2439#endif
2440#ifndef MSG_NOSIGNAL
2441 /* Cannot use socket as it can produce SIGPIPE. */
2442#ifdef ENOTSOCK
2443 errno = ENOTSOCK;
2444#endif /* ENOTSOCK */
2445 return MHD_NO;
2446#endif /* ! MSG_NOSIGNAL */
2447 }
2448#endif /* MHD_socket_nosignal_ */
2449
2450
2451#ifdef HAVE_MESSAGES
2452#if DEBUG_CONNECT
2453 MHD_DLOG (daemon,
2454 _ ("Accepted connection on socket %d.\n"),
2455 client_socket);
2456#endif
2457#endif
2458 if ( (daemon->connections == daemon->connection_limit) ||
2459 (MHD_NO == MHD_ip_limit_add (daemon,
2460 addr,
2461 addrlen)) )
2462 {
2463 /* above connection limit - reject */
2464#ifdef HAVE_MESSAGES
2465 MHD_DLOG (daemon,
2466 _ (
2467 "Server reached connection limit. Closing inbound connection.\n"));
2468#endif
2469 MHD_socket_close_chk_ (client_socket);
2470#if ENFILE
2471 errno = ENFILE;
2472#endif
2473 return MHD_NO;
2474 }
2475
2476 /* apply connection acceptance policy if present */
2477 if ( (NULL != daemon->apc) &&
2478 (MHD_NO == daemon->apc (daemon->apc_cls,
2479 addr,
2480 addrlen)) )
2481 {
2482#if DEBUG_CLOSE
2483#ifdef HAVE_MESSAGES
2484 MHD_DLOG (daemon,
2485 _ ("Connection rejected by application. Closing connection.\n"));
2486#endif
2487#endif
2488 MHD_socket_close_chk_ (client_socket);
2489 MHD_ip_limit_del (daemon,
2490 addr,
2491 addrlen);
2492#if EACCESS
2493 errno = EACCESS;
2494#endif
2495 return MHD_NO;
2496 }
2497
2498 if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2499 {
2500 eno = errno;
2501#ifdef HAVE_MESSAGES
2502 MHD_DLOG (daemon,
2503 "Error allocating memory: %s\n",
2504 MHD_strerror_ (errno));
2505#endif
2506 MHD_socket_close_chk_ (client_socket);
2507 MHD_ip_limit_del (daemon,
2508 addr,
2509 addrlen);
2510 errno = eno;
2511 return MHD_NO;
2512 }
2513 connection->sk_cork_on = true; /* default is usually ON */
2514 connection->pool = MHD_pool_create (daemon->pool_size);
2515 if (NULL == connection->pool)
2516 {
2517#ifdef HAVE_MESSAGES
2518 MHD_DLOG (daemon,
2519 _ ("Error allocating memory: %s\n"),
2520 MHD_strerror_ (errno));
2521#endif
2522 MHD_socket_close_chk_ (client_socket);
2523 MHD_ip_limit_del (daemon,
2524 addr,
2525 addrlen);
2526 free (connection);
2527#if ENOMEM
2528 errno = ENOMEM;
2529#endif
2530 return MHD_NO;
2531 }
2532
2533 connection->connection_timeout = daemon->connection_timeout;
2534 if (NULL == (connection->addr = malloc (addrlen)))
2535 {
2536 eno = errno;
2537#ifdef HAVE_MESSAGES
2538 MHD_DLOG (daemon,
2539 _ ("Error allocating memory: %s\n"),
2540 MHD_strerror_ (errno));
2541#endif
2542 MHD_socket_close_chk_ (client_socket);
2543 MHD_ip_limit_del (daemon,
2544 addr,
2545 addrlen);
2546 MHD_pool_destroy (connection->pool);
2547 free (connection);
2548 errno = eno;
2549 return MHD_NO;
2550 }
2551 memcpy (connection->addr,
2552 addr,
2553 addrlen);
2554 connection->addr_len = addrlen;
2555 connection->socket_fd = client_socket;
2556 connection->sk_nonblck = non_blck;
2557 connection->daemon = daemon;
2559
2560 if (0 == (daemon->options & MHD_USE_TLS))
2561 {
2562 /* set default connection handlers */
2563 MHD_set_http_callbacks_ (connection);
2564 }
2565 else
2566 {
2567#ifdef HTTPS_SUPPORT
2568#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2569 gnutls_init_flags_t
2570#else
2571 unsigned int
2572#endif
2573 flags;
2574
2575 flags = GNUTLS_SERVER;
2576#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2577 flags |= GNUTLS_NO_SIGNAL;
2578#endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2579#if GNUTLS_VERSION_MAJOR >= 3
2580 flags |= GNUTLS_NONBLOCK;
2581#endif /* GNUTLS_VERSION_MAJOR >= 3*/
2582#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2583 if (0 != (daemon->options & MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT))
2584 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2585#endif
2586#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2587 if (0 != (daemon->options & MHD_USE_INSECURE_TLS_EARLY_DATA))
2588 flags |= GNUTLS_ENABLE_EARLY_DATA;
2589#endif
2590 connection->tls_state = MHD_TLS_CONN_INIT;
2591 MHD_set_https_callbacks (connection);
2592 gnutls_init (&connection->tls_session,
2593 flags);
2594 gnutls_priority_set (connection->tls_session,
2595 daemon->priority_cache);
2596 gnutls_session_set_ptr (connection->tls_session,
2597 connection);
2598 switch (daemon->cred_type)
2599 {
2600 /* set needed credentials for certificate authentication. */
2601 case GNUTLS_CRD_CERTIFICATE:
2602 gnutls_credentials_set (connection->tls_session,
2603 GNUTLS_CRD_CERTIFICATE,
2604 daemon->x509_cred);
2605 break;
2606 case GNUTLS_CRD_PSK:
2607 gnutls_credentials_set (connection->tls_session,
2608 GNUTLS_CRD_PSK,
2609 daemon->psk_cred);
2610 gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2611 &psk_gnutls_adapter);
2612 break;
2613 default:
2614#ifdef HAVE_MESSAGES
2615 MHD_DLOG (connection->daemon,
2616 _ (
2617 "Failed to setup TLS credentials: unknown credential type %d.\n"),
2618 daemon->cred_type);
2619#endif
2620 MHD_socket_close_chk_ (client_socket);
2621 MHD_ip_limit_del (daemon,
2622 addr,
2623 addrlen);
2624 free (connection->addr);
2625 free (connection);
2626 MHD_PANIC (_ ("Unknown credential type.\n"));
2627#if EINVAL
2628 errno = EINVAL;
2629#endif
2630 return MHD_NO;
2631 }
2632#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2633 gnutls_transport_set_int (connection->tls_session,
2634 (int) (client_socket));
2635#else /* GnuTLS before 3.1.9 or Win x64 */
2636 gnutls_transport_set_ptr (connection->tls_session,
2637 (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2638#endif /* GnuTLS before 3.1.9 */
2639#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2640 gnutls_transport_set_push_function (connection->tls_session,
2641 MHD_tls_push_func_);
2642#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2643 if (daemon->https_mem_trust)
2644 gnutls_certificate_server_set_request (connection->tls_session,
2645 GNUTLS_CERT_REQUEST);
2646#else /* ! HTTPS_SUPPORT */
2647 eno = EINVAL;
2648 goto cleanup;
2649#endif /* ! HTTPS_SUPPORT */
2650 }
2651
2652#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2654#endif
2655 /* Firm check under lock. */
2656 if (daemon->connections >= daemon->connection_limit)
2657 {
2658#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2660#endif
2661 /* above connection limit - reject */
2662#ifdef HAVE_MESSAGES
2663 MHD_DLOG (daemon,
2664 _ (
2665 "Server reached connection limit. Closing inbound connection.\n"));
2666#endif
2667#if ENFILE
2668 eno = ENFILE;
2669#endif
2670 goto cleanup;
2671 }
2672 daemon->connections++;
2673 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2674 {
2676 daemon->normal_timeout_tail,
2677 connection);
2678 }
2680 daemon->connections_tail,
2681 connection);
2682#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2684#endif
2685 if (NULL != daemon->notify_connection)
2687 connection,
2688 &connection->socket_context,
2690#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2691 /* attempt to create handler thread */
2692 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2693 {
2694 if (! MHD_create_named_thread_ (&connection->pid,
2695 "MHD-connection",
2696 daemon->thread_stack_size,
2698 connection))
2699 {
2700 eno = errno;
2701#ifdef HAVE_MESSAGES
2702 MHD_DLOG (daemon,
2703 "Failed to create a thread: %s\n",
2704 MHD_strerror_ (eno));
2705#endif
2706 goto cleanup;
2707 }
2708 }
2709 else
2710 connection->pid = daemon->pid;
2711#endif
2712#ifdef EPOLL_SUPPORT
2713 if (0 != (daemon->options & MHD_USE_EPOLL))
2714 {
2715 if ((0 == (daemon->options & MHD_USE_TURBO)) || (external_add))
2716 { /* Do not manipulate EReady DL-list in 'external_add' mode. */
2717 struct epoll_event event;
2718
2719 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2720 event.data.ptr = connection;
2721 if (0 != epoll_ctl (daemon->epoll_fd,
2722 EPOLL_CTL_ADD,
2723 client_socket,
2724 &event))
2725 {
2726 eno = errno;
2727#ifdef HAVE_MESSAGES
2728 MHD_DLOG (daemon,
2729 _ ("Call to epoll_ctl failed: %s\n"),
2731#endif
2732 goto cleanup;
2733 }
2734 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2735 }
2736 else
2737 {
2738 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
2741 EDLL_insert (daemon->eready_head,
2742 daemon->eready_tail,
2743 connection);
2744 }
2745 }
2746 else /* This 'else' is combined with next 'if'. */
2747#endif
2748 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2749 (external_add) &&
2750 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2751 (! MHD_itc_activate_ (daemon->itc, "n")) )
2752 {
2753#ifdef HAVE_MESSAGES
2754 MHD_DLOG (daemon,
2755 _ (
2756 "Failed to signal new connection via inter-thread communication channel.\n"));
2757#endif
2758 }
2759 return MHD_YES;
2760cleanup:
2761 if (NULL != daemon->notify_connection)
2763 connection,
2764 &connection->socket_context,
2766#ifdef HTTPS_SUPPORT
2767 if (NULL != connection->tls_session)
2768 gnutls_deinit (connection->tls_session);
2769#endif /* HTTPS_SUPPORT */
2770 MHD_socket_close_chk_ (client_socket);
2771 MHD_ip_limit_del (daemon,
2772 addr,
2773 addrlen);
2774#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2776#endif
2777 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2778 {
2780 daemon->normal_timeout_tail,
2781 connection);
2782 }
2784 daemon->connections_tail,
2785 connection);
2786#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2788#endif
2789 MHD_pool_destroy (connection->pool);
2790 free (connection->addr);
2791 free (connection);
2792 if (0 != eno)
2793 errno = eno;
2794 else
2795 errno = EINVAL;
2796 return MHD_NO;
2797}
2798
2799
2809void
2811{
2812 struct MHD_Daemon *daemon = connection->daemon;
2813
2814#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2816#endif
2817 if (connection->resuming)
2818 {
2819 /* suspending again while we didn't even complete resuming yet */
2820 connection->resuming = false;
2821#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2823#endif
2824 return;
2825 }
2826 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2827 {
2828 if (connection->connection_timeout == daemon->connection_timeout)
2830 daemon->normal_timeout_tail,
2831 connection);
2832 else
2834 daemon->manual_timeout_tail,
2835 connection);
2836 }
2838 daemon->connections_tail,
2839 connection);
2840 mhd_assert (! connection->suspended);
2843 connection);
2844 connection->suspended = true;
2845#ifdef EPOLL_SUPPORT
2846 if (0 != (daemon->options & MHD_USE_EPOLL))
2847 {
2848 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2849 {
2850 EDLL_remove (daemon->eready_head,
2851 daemon->eready_tail,
2852 connection);
2853 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2854 }
2855 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2856 {
2857 if (0 != epoll_ctl (daemon->epoll_fd,
2858 EPOLL_CTL_DEL,
2859 connection->socket_fd,
2860 NULL))
2861 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
2862 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2863 }
2864 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2865 }
2866#endif
2867#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2869#endif
2870}
2871
2872
2904void
2906{
2907 struct MHD_Daemon *const daemon = connection->daemon;
2908
2909 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2910 MHD_PANIC (_ (
2911 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2912#ifdef UPGRADE_SUPPORT
2913 if (NULL != connection->urh)
2914 {
2915#ifdef HAVE_MESSAGES
2916 MHD_DLOG (daemon,
2917 _ (
2918 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
2919#endif /* HAVE_MESSAGES */
2920 return;
2921 }
2922#endif /* UPGRADE_SUPPORT */
2923 internal_suspend_connection_ (connection);
2924}
2925
2926
2935void
2937{
2938 struct MHD_Daemon *daemon = connection->daemon;
2939
2940 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2941 MHD_PANIC (_ (
2942 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2943#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2945#endif
2946 connection->resuming = true;
2947 daemon->resuming = true;
2948#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2950#endif
2951 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2952 (! MHD_itc_activate_ (daemon->itc, "r")) )
2953 {
2954#ifdef HAVE_MESSAGES
2955 MHD_DLOG (daemon,
2956 _ (
2957 "Failed to signal resume via inter-thread communication channel.\n"));
2958#endif
2959 }
2960}
2961
2962
2972static enum MHD_Result
2974{
2975 struct MHD_Connection *pos;
2976 struct MHD_Connection *prev = NULL;
2977 enum MHD_Result ret;
2978 const bool used_thr_p_c = (0 != (daemon->options
2980#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2982#endif
2983 ret = MHD_NO;
2984#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2986#endif
2987 if (daemon->resuming)
2988 {
2990 /* During shutdown check for resuming is forced. */
2991 mhd_assert ((NULL != prev) || (daemon->shutdown));
2992 }
2993
2994 daemon->resuming = false;
2995
2996 while (NULL != (pos = prev))
2997 {
2998#ifdef UPGRADE_SUPPORT
2999 struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3000#else /* ! UPGRADE_SUPPORT */
3001 static const void *const urh = NULL;
3002#endif /* ! UPGRADE_SUPPORT */
3003 prev = pos->prev;
3004 if ( (! pos->resuming)
3005#ifdef UPGRADE_SUPPORT
3006 || ( (NULL != urh) &&
3007 ( (! urh->was_closed) ||
3008 (! urh->clean_ready) ) )
3009#endif /* UPGRADE_SUPPORT */
3010 )
3011 continue;
3012 ret = MHD_YES;
3013 mhd_assert (pos->suspended);
3016 pos);
3017 pos->suspended = false;
3018 if (NULL == urh)
3019 {
3021 daemon->connections_tail,
3022 pos);
3023 if (! used_thr_p_c)
3024 {
3025 /* Reset timeout timer on resume. */
3026 if (0 != pos->connection_timeout)
3028
3029 if (pos->connection_timeout == daemon->connection_timeout)
3031 daemon->normal_timeout_tail,
3032 pos);
3033 else
3035 daemon->manual_timeout_tail,
3036 pos);
3037 }
3038#ifdef EPOLL_SUPPORT
3039 if (0 != (daemon->options & MHD_USE_EPOLL))
3040 {
3041 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3042 MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3043 /* we always mark resumed connections as ready, as we
3044 might have missed the edge poll event during suspension */
3045 EDLL_insert (daemon->eready_head,
3046 daemon->eready_tail,
3047 pos);
3048 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3051 pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
3052 }
3053#endif
3054 }
3055#ifdef UPGRADE_SUPPORT
3056 else
3057 {
3058 /* Data forwarding was finished (for TLS connections) AND
3059 * application was closed upgraded connection.
3060 * Insert connection into cleanup list. */
3061
3062 if ( (NULL != daemon->notify_completed) &&
3063 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3064 (pos->client_aware) )
3065 {
3066 daemon->notify_completed (daemon->notify_completed_cls,
3067 pos,
3068 &pos->client_context,
3070 pos->client_aware = false;
3071 }
3072 DLL_insert (daemon->cleanup_head,
3073 daemon->cleanup_tail,
3074 pos);
3075
3076 }
3077#endif /* UPGRADE_SUPPORT */
3078 pos->resuming = false;
3079 }
3080#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3082#endif
3083 if ( (used_thr_p_c) &&
3084 (MHD_NO != ret) )
3085 { /* Wake up suspended connections. */
3086 if (! MHD_itc_activate_ (daemon->itc,
3087 "w"))
3088 {
3089#ifdef HAVE_MESSAGES
3090 MHD_DLOG (daemon,
3091 _ (
3092 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3093#endif
3094 }
3095 }
3096 return ret;
3097}
3098
3099
3127enum MHD_Result
3129 MHD_socket client_socket,
3130 const struct sockaddr *addr,
3131 socklen_t addrlen)
3132{
3133 bool sk_nonbl;
3134
3135 MHD_cleanup_connections (daemon);
3136 if (! MHD_socket_nonblocking_ (client_socket))
3137 {
3138#ifdef HAVE_MESSAGES
3139 MHD_DLOG (daemon,
3140 _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3142#endif
3143 sk_nonbl = false;
3144 }
3145 else
3146 sk_nonbl = true;
3147
3148 if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3149 (! MHD_socket_noninheritable_ (client_socket)) )
3150 {
3151#ifdef HAVE_MESSAGES
3152 MHD_DLOG (daemon,
3153 _ ("Failed to set noninheritable mode on new client socket.\n"));
3154#endif
3155 }
3156
3157 if ( (0 == (daemon->options & MHD_USE_TURBO)) &&
3158 (! MHD_socket_buffering_reset_ (client_socket)) )
3159 {
3160#ifdef HAVE_MESSAGES
3161 MHD_DLOG (daemon,
3162 _ ("Failed to reset buffering mode on new client socket.\n"));
3163#endif
3164 }
3165 return internal_add_connection (daemon,
3166 client_socket,
3167 addr,
3168 addrlen,
3169 true,
3170 sk_nonbl);
3171}
3172
3173
3188static enum MHD_Result
3190{
3191#if HAVE_INET6
3192 struct sockaddr_in6 addrstorage;
3193#else
3194 struct sockaddr_in addrstorage;
3195#endif
3196 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3197 socklen_t addrlen;
3198 MHD_socket s;
3199 MHD_socket fd;
3200 bool sk_nonbl;
3201
3202 addrlen = sizeof (addrstorage);
3203 memset (addr,
3204 0,
3205 sizeof (addrstorage));
3206 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3207 (daemon->was_quiesced) )
3208 return MHD_NO;
3209#ifdef USE_ACCEPT4
3210 s = accept4 (fd,
3211 addr,
3212 &addrlen,
3214 sk_nonbl = (MAYBE_SOCK_NONBLOCK != 0);
3215#else /* ! USE_ACCEPT4 */
3216 s = accept (fd,
3217 addr,
3218 &addrlen);
3219 sk_nonbl = false;
3220#endif /* ! USE_ACCEPT4 */
3221 if ( (MHD_INVALID_SOCKET == s) ||
3222 (addrlen <= 0) )
3223 {
3224 const int err = MHD_socket_get_error_ ();
3225
3226 /* This could be a common occurrence with multiple worker threads */
3227 if (MHD_SCKT_ERR_IS_ (err,
3229 return MHD_NO; /* can happen during shutdown */
3231 return MHD_NO; /* do not print error if client just disconnected early */
3232#ifdef HAVE_MESSAGES
3233 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3234 MHD_DLOG (daemon,
3235 _ ("Error accepting connection: %s\n"),
3236 MHD_socket_strerr_ (err));
3237#endif
3238 if (MHD_INVALID_SOCKET != s)
3239 {
3241 }
3243 {
3244 /* system/process out of resources */
3245 if (0 == daemon->connections)
3246 {
3247#ifdef HAVE_MESSAGES
3248 /* Not setting 'at_limit' flag, as there is no way it
3249 would ever be cleared. Instead trying to produce
3250 bit fat ugly warning. */
3251 MHD_DLOG (daemon,
3252 _ (
3253 "Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
3254#endif
3255 }
3256 else
3257 {
3258#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3260#endif
3261 daemon->at_limit = true;
3262#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3264#endif
3265#ifdef HAVE_MESSAGES
3266 MHD_DLOG (daemon,
3267 _ (
3268 "Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3269 (unsigned int) daemon->connections);
3270#endif
3271 }
3272 }
3273 return MHD_NO;
3274 }
3275#if defined(MHD_TCP_CORK_NOPUSH) || defined(HAVE_MSG_MORE)
3276 /* We will use TCP_CORK or TCP_NOPUSH or MSG_MORE to control
3277 transmission, disable Nagle's algorithm (always) */
3278 if ( (0 != MHD_socket_set_nodelay_ (s,
3279 true)) &&
3280 (EOPNOTSUPP != errno) )
3281 {
3282#ifdef HAVE_MESSAGES
3283 MHD_DLOG (daemon,
3284 _ ("Failed to disable TCP Nagle on socket: %s\n"),
3286#endif
3287 }
3288#endif
3289#if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
3290 if (! MHD_socket_nonblocking_ (s))
3291 {
3292#ifdef HAVE_MESSAGES
3293 MHD_DLOG (daemon,
3294 _ (
3295 "Failed to set nonblocking mode on incoming connection socket: %s\n"),
3297#endif
3298 }
3299 else
3300 sk_nonbl = true;
3301#endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
3302#if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
3304 {
3305#ifdef HAVE_MESSAGES
3306 MHD_DLOG (daemon,
3307 _ (
3308 "Failed to set noninheritable mode on incoming connection socket.\n"));
3309#endif
3310 }
3311#endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
3312#ifdef HAVE_MESSAGES
3313#if DEBUG_CONNECT
3314 MHD_DLOG (daemon,
3315 _ ("Accepted connection on socket %d\n"),
3316 s);
3317#endif
3318#endif
3319 (void) internal_add_connection (daemon,
3320 s,
3321 addr,
3322 addrlen,
3323 false,
3324 sk_nonbl);
3325 return MHD_YES;
3326}
3327
3328
3338static void
3340{
3341 struct MHD_Connection *pos;
3342
3343#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3345#endif
3346 while (NULL != (pos = daemon->cleanup_tail))
3347 {
3350 pos);
3351#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3353 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3354 (! pos->thread_joined) &&
3355 (! MHD_join_thread_ (pos->pid.handle)) )
3356 MHD_PANIC (_ ("Failed to join a thread.\n"));
3357#endif
3358#ifdef UPGRADE_SUPPORT
3359 cleanup_upgraded_connection (pos);
3360#endif /* UPGRADE_SUPPORT */
3361 MHD_pool_destroy (pos->pool);
3362#ifdef HTTPS_SUPPORT
3363 if (NULL != pos->tls_session)
3364 gnutls_deinit (pos->tls_session);
3365#endif /* HTTPS_SUPPORT */
3366
3367 /* clean up the connection */
3370 pos,
3371 &pos->socket_context,
3374 pos->addr,
3375 pos->addr_len);
3376#ifdef EPOLL_SUPPORT
3377 if (0 != (daemon->options & MHD_USE_EPOLL))
3378 {
3379 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3380 {
3381 EDLL_remove (daemon->eready_head,
3382 daemon->eready_tail,
3383 pos);
3384 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3385 }
3386 if ( (-1 != daemon->epoll_fd) &&
3387 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3388 {
3389 /* epoll documentation suggests that closing a FD
3390 automatically removes it from the epoll set; however,
3391 this is not true as if we fail to do manually remove it,
3392 we are still seeing an event for this fd in epoll,
3393 causing grief (use-after-free...) --- at least on my
3394 system. */if (0 != epoll_ctl (daemon->epoll_fd,
3395 EPOLL_CTL_DEL,
3396 pos->socket_fd,
3397 NULL))
3398 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3399 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3400 }
3401 }
3402#endif
3403 if (NULL != pos->response)
3404 {
3406 pos->response = NULL;
3407 }
3408 if (MHD_INVALID_SOCKET != pos->socket_fd)
3410 if (NULL != pos->addr)
3411 free (pos->addr);
3412 free (pos);
3413
3414#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3416#endif
3418 daemon->at_limit = false;
3419 }
3420#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3422#endif
3423}
3424
3425
3446enum MHD_Result
3448 MHD_UNSIGNED_LONG_LONG *timeout)
3449{
3450 time_t earliest_deadline;
3451 time_t now;
3452 struct MHD_Connection *pos;
3453 bool have_timeout;
3454
3456 {
3457#ifdef HAVE_MESSAGES
3458 MHD_DLOG (daemon,
3459 _ ("Illegal call to MHD_get_timeout.\n"));
3460#endif
3461 return MHD_NO;
3462 }
3463
3465 {
3466 /* Some data already waiting to be processed. */
3467 *timeout = 0;
3468 return MHD_YES;
3469 }
3470
3471#ifdef EPOLL_SUPPORT
3472 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3473 ((NULL != daemon->eready_head)
3474#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3475 || (NULL != daemon->eready_urh_head)
3476#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3477 ) )
3478 {
3479 /* Some connection(s) already have some data pending. */
3480 *timeout = 0;
3481 return MHD_YES;
3482 }
3483#endif /* EPOLL_SUPPORT */
3484
3485 have_timeout = false;
3486 earliest_deadline = 0; /* avoid compiler warnings */
3487 for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3488 {
3489 if (0 != pos->connection_timeout)
3490 {
3491 if ( (! have_timeout) ||
3492 (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3493 earliest_deadline = pos->last_activity + pos->connection_timeout;
3494 have_timeout = true;
3495 }
3496 }
3497 /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3499 if ( (NULL != pos) &&
3500 (0 != pos->connection_timeout) )
3501 {
3502 if ( (! have_timeout) ||
3503 (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3504 earliest_deadline = pos->last_activity + pos->connection_timeout;
3505 have_timeout = true;
3506 }
3507
3508 if (! have_timeout)
3509 return MHD_NO;
3511 if (earliest_deadline < now)
3512 *timeout = 0;
3513 else
3514 {
3515 const time_t second_left = earliest_deadline - now;
3516
3517 if (((unsigned long long) second_left) > ULLONG_MAX / 1000)
3518 *timeout = ULLONG_MAX;
3519 else
3520 *timeout = 1000LLU * (unsigned long long) second_left;
3521 }
3522 return MHD_YES;
3523}
3524
3525
3536static enum MHD_Result
3538 const fd_set *read_fd_set,
3539 const fd_set *write_fd_set,
3540 const fd_set *except_fd_set)
3541{
3542 MHD_socket ds;
3543 struct MHD_Connection *pos;
3544 struct MHD_Connection *prev;
3545#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3546 struct MHD_UpgradeResponseHandle *urh;
3547 struct MHD_UpgradeResponseHandle *urhn;
3548#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3549 /* Reset. New value will be set when connections are processed. */
3550 /* Note: no-op for thread-per-connection as it is always false in that mode. */
3551 daemon->data_already_pending = false;
3552
3553 /* Clear ITC to avoid spinning select */
3554 /* Do it before any other processing so new signals
3555 will trigger select again and will be processed */
3556 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3557 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3558 read_fd_set)) )
3559 MHD_itc_clear_ (daemon->itc);
3560
3561 /* select connection thread handling type */
3562 if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3563 (! daemon->was_quiesced) &&
3564 (FD_ISSET (ds,
3565 read_fd_set)) )
3566 (void) MHD_accept_connection (daemon);
3567
3568 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3569 {
3570 /* do not have a thread per connection, process all connections now */
3571 prev = daemon->connections_tail;
3572 while (NULL != (pos = prev))
3573 {
3574 prev = pos->prev;
3575 ds = pos->socket_fd;
3576 if (MHD_INVALID_SOCKET == ds)
3577 continue;
3578 call_handlers (pos,
3579 FD_ISSET (ds,
3580 read_fd_set),
3581 FD_ISSET (ds,
3582 write_fd_set),
3583 FD_ISSET (ds,
3584 except_fd_set));
3585 }
3586 }
3587
3588#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3589 /* handle upgraded HTTPS connections */
3590 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3591 {
3592 urhn = urh->prev;
3593 /* update urh state based on select() output */
3594 urh_from_fdset (urh,
3595 read_fd_set,
3596 write_fd_set,
3597 except_fd_set);
3598 /* call generic forwarding function for passing data */
3599 process_urh (urh);
3600 /* Finished forwarding? */
3601 if ( (0 == urh->in_buffer_size) &&
3602 (0 == urh->out_buffer_size) &&
3603 (0 == urh->in_buffer_used) &&
3604 (0 == urh->out_buffer_used) )
3605 {
3606 MHD_connection_finish_forward_ (urh->connection);
3607 urh->clean_ready = true;
3608 /* Resuming will move connection to cleanup list. */
3609 MHD_resume_connection (urh->connection);
3610 }
3611 }
3612#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3613 MHD_cleanup_connections (daemon);
3614 return MHD_YES;
3615}
3616
3617
3640enum MHD_Result
3642 const fd_set *read_fd_set,
3643 const fd_set *write_fd_set,
3644 const fd_set *except_fd_set)
3645{
3646 fd_set es;
3647 if (0 != (daemon->options
3649 return MHD_NO;
3650 if ((NULL == read_fd_set) || (NULL == write_fd_set))
3651 return MHD_NO;
3652 if (NULL == except_fd_set)
3653 { /* Workaround to maintain backward compatibility. */
3654#ifdef HAVE_MESSAGES
3655 MHD_DLOG (daemon,
3656 _ ("MHD_run_from_select() called with except_fd_set "
3657 "set to NULL. Such behavior is deprecated.\n"));
3658#endif
3659 FD_ZERO (&es);
3660 except_fd_set = &es;
3661 }
3662 if (0 != (daemon->options & MHD_USE_EPOLL))
3663 {
3664#ifdef EPOLL_SUPPORT
3665 enum MHD_Result ret = MHD_epoll (daemon,
3666 MHD_NO);
3667
3668 MHD_cleanup_connections (daemon);
3669 return ret;
3670#else /* ! EPOLL_SUPPORT */
3671 return MHD_NO;
3672#endif /* ! EPOLL_SUPPORT */
3673 }
3674
3675 /* Resuming external connections when using an extern mainloop */
3676 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3678
3679 return internal_run_from_select (daemon,
3680 read_fd_set,
3681 write_fd_set,
3682 except_fd_set);
3683}
3684
3685
3694static enum MHD_Result
3695MHD_select (struct MHD_Daemon *daemon,
3696 int may_block)
3697{
3698 int num_ready;
3699 fd_set rs;
3700 fd_set ws;
3701 fd_set es;
3702 MHD_socket maxsock;
3703 struct timeval timeout;
3704 struct timeval *tv;
3705 MHD_UNSIGNED_LONG_LONG ltimeout;
3706 int err_state;
3707 MHD_socket ls;
3708
3709 timeout.tv_sec = 0;
3710 timeout.tv_usec = 0;
3711 if (daemon->shutdown)
3712 return MHD_NO;
3713 FD_ZERO (&rs);
3714 FD_ZERO (&ws);
3715 FD_ZERO (&es);
3716 maxsock = MHD_INVALID_SOCKET;
3717 err_state = MHD_NO;
3718 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3719 (MHD_YES == resume_suspended_connections (daemon)) &&
3720 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
3721 may_block = MHD_NO;
3722
3723 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3724 {
3725 /* single-threaded, go over everything */
3726 if (MHD_NO ==
3727 internal_get_fdset2 (daemon,
3728 &rs,
3729 &ws,
3730 &es,
3731 &maxsock,
3732 FD_SETSIZE))
3733 {
3734#ifdef HAVE_MESSAGES
3735 MHD_DLOG (daemon,
3736 _ ("Could not obtain daemon fdsets.\n"));
3737#endif
3738 err_state = MHD_YES;
3739 }
3740 }
3741 else
3742 {
3743 /* accept only, have one thread per connection */
3744 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3745 (! daemon->was_quiesced) &&
3746 (! MHD_add_to_fd_set_ (ls,
3747 &rs,
3748 &maxsock,
3749 FD_SETSIZE)) )
3750 {
3751#ifdef HAVE_MESSAGES
3752 MHD_DLOG (daemon,
3753 _ ("Could not add listen socket to fdset.\n"));
3754#endif
3755 return MHD_NO;
3756 }
3757 }
3758 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3759 (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3760 &rs,
3761 &maxsock,
3762 FD_SETSIZE)) )
3763 {
3764#if defined(MHD_WINSOCK_SOCKETS)
3765 /* fdset limit reached, new connections
3766 cannot be handled. Remove listen socket FD
3767 from fdset and retry to add ITC FD. */
3768 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3769 (! daemon->was_quiesced) )
3770 {
3771 FD_CLR (ls,
3772 &rs);
3773 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3774 &rs,
3775 &maxsock,
3776 FD_SETSIZE))
3777 {
3778#endif /* MHD_WINSOCK_SOCKETS */
3779#ifdef HAVE_MESSAGES
3780 MHD_DLOG (daemon,
3781 _ (
3782 "Could not add control inter-thread communication channel FD to fdset.\n"));
3783#endif
3784 err_state = MHD_YES;
3785#if defined(MHD_WINSOCK_SOCKETS)
3786 }
3787}
3788
3789
3790#endif /* MHD_WINSOCK_SOCKETS */
3791 }
3792 /* Stop listening if we are at the configured connection limit */
3793 /* If we're at the connection limit, no point in really
3794 accepting new connections; however, make sure we do not miss
3795 the shutdown OR the termination of an existing connection; so
3796 only do this optimization if we have a signaling ITC in
3797 place. */
3798 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3799 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3800 ( (daemon->connections == daemon->connection_limit) ||
3801 (daemon->at_limit) ) )
3802 {
3803 FD_CLR (ls,
3804 &rs);
3805 }
3806 tv = NULL;
3807 if (MHD_YES == err_state)
3808 may_block = MHD_NO;
3809 if (MHD_NO == may_block)
3810 {
3811 timeout.tv_usec = 0;
3812 timeout.tv_sec = 0;
3813 tv = &timeout;
3814 }
3815 else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3816 (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
3817 {
3818 /* ltimeout is in ms */
3819 timeout.tv_usec = (ltimeout % 1000) * 1000;
3820 if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
3821 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
3822 else
3823 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
3824 tv = &timeout;
3825 }
3826 num_ready = MHD_SYS_select_ (maxsock + 1,
3827 &rs,
3828 &ws,
3829 &es,
3830 tv);
3831 if (daemon->shutdown)
3832 return MHD_NO;
3833 if (num_ready < 0)
3834 {
3835 const int err = MHD_socket_get_error_ ();
3836 if (MHD_SCKT_ERR_IS_EINTR_ (err))
3837 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3838#ifdef HAVE_MESSAGES
3839 MHD_DLOG (daemon,
3840 _ ("select failed: %s\n"),
3841 MHD_socket_strerr_ (err));
3842#endif
3843 return MHD_NO;
3844 }
3845 if (MHD_YES == internal_run_from_select (daemon,
3846 &rs,
3847 &ws,
3848 &es))
3849 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3850 return MHD_NO;
3851}
3852
3853
3854#ifdef HAVE_POLL
3863static enum MHD_Result
3864MHD_poll_all (struct MHD_Daemon *daemon,
3865 int may_block)
3866{
3867 unsigned int num_connections;
3868 struct MHD_Connection *pos;
3869 struct MHD_Connection *prev;
3870#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3871 struct MHD_UpgradeResponseHandle *urh;
3872 struct MHD_UpgradeResponseHandle *urhn;
3873#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3874
3875 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3877 may_block = MHD_NO;
3878
3879 /* count number of connections and thus determine poll set size */
3880 num_connections = 0;
3881 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3882 num_connections++;
3883#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3884 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3885 num_connections += 2;
3886#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3887 {
3888 MHD_UNSIGNED_LONG_LONG ltimeout;
3889 unsigned int i;
3890 int timeout;
3891 unsigned int poll_server;
3892 int poll_listen;
3893 int poll_itc_idx;
3894 struct pollfd *p;
3895 MHD_socket ls;
3896
3897 p = MHD_calloc_ ((2 + (size_t) num_connections),
3898 sizeof (struct pollfd));
3899 if (NULL == p)
3900 {
3901#ifdef HAVE_MESSAGES
3902 MHD_DLOG (daemon,
3903 _ ("Error allocating memory: %s\n"),
3904 MHD_strerror_ (errno));
3905#endif
3906 return MHD_NO;
3907 }
3908 poll_server = 0;
3909 poll_listen = -1;
3910 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3911 (! daemon->was_quiesced) &&
3912 (daemon->connections < daemon->connection_limit) &&
3913 (! daemon->at_limit) )
3914 {
3915 /* only listen if we are not at the connection limit */
3916 p[poll_server].fd = ls;
3917 p[poll_server].events = POLLIN;
3918 p[poll_server].revents = 0;
3919 poll_listen = (int) poll_server;
3920 poll_server++;
3921 }
3922 poll_itc_idx = -1;
3923 if (MHD_ITC_IS_VALID_ (daemon->itc))
3924 {
3925 p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3926 p[poll_server].events = POLLIN;
3927 p[poll_server].revents = 0;
3928 poll_itc_idx = (int) poll_server;
3929 poll_server++;
3930 }
3931 if (may_block == MHD_NO)
3932 timeout = 0;
3933 else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3934 (MHD_YES != MHD_get_timeout (daemon,
3935 &ltimeout)) )
3936 timeout = -1;
3937 else
3938 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3939
3940 i = 0;
3941 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
3942 {
3943 p[poll_server + i].fd = pos->socket_fd;
3944 switch (pos->event_loop_info)
3945 {
3947 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3948 break;
3950 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3951 break;
3953 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
3954 break;
3956 timeout = 0; /* clean up "pos" immediately */
3957 break;
3958 }
3959 i++;
3960 }
3961#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3962 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3963 {
3964 urh_to_pollfd (urh, &(p[poll_server + i]));
3965 i += 2;
3966 }
3967#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3968 if (0 == poll_server + num_connections)
3969 {
3970 free (p);
3971 return MHD_YES;
3972 }
3973 if (MHD_sys_poll_ (p,
3974 poll_server + num_connections,
3975 timeout) < 0)
3976 {
3977 const int err = MHD_socket_get_error_ ();
3978 if (MHD_SCKT_ERR_IS_EINTR_ (err))
3979 {
3980 free (p);
3981 return MHD_YES;
3982 }
3983#ifdef HAVE_MESSAGES
3984 MHD_DLOG (daemon,
3985 _ ("poll failed: %s\n"),
3986 MHD_socket_strerr_ (err));
3987#endif
3988 free (p);
3989 return MHD_NO;
3990 }
3991
3992 /* Reset. New value will be set when connections are processed. */
3993 daemon->data_already_pending = false;
3994
3995 /* handle ITC FD */
3996 /* do it before any other processing so
3997 new signals will be processed in next loop */
3998 if ( (-1 != poll_itc_idx) &&
3999 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4000 MHD_itc_clear_ (daemon->itc);
4001
4002 /* handle shutdown */
4003 if (daemon->shutdown)
4004 {
4005 free (p);
4006 return MHD_NO;
4007 }
4008 i = 0;
4009 prev = daemon->connections_tail;
4010 while (NULL != (pos = prev))
4011 {
4012 prev = pos->prev;
4013 /* first, sanity checks */
4014 if (i >= num_connections)
4015 break; /* connection list changed somehow, retry later ... */
4016 if (p[poll_server + i].fd != pos->socket_fd)
4017 continue; /* fd mismatch, something else happened, retry later ... */
4018 call_handlers (pos,
4019 0 != (p[poll_server + i].revents & POLLIN),
4020 0 != (p[poll_server + i].revents & POLLOUT),
4021 0 != (p[poll_server + i].revents
4022 & MHD_POLL_REVENTS_ERR_DISC));
4023 i++;
4024 }
4025#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4026 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4027 {
4028 if (i >= num_connections)
4029 break; /* connection list changed somehow, retry later ... */
4030
4031 /* Get next connection here as connection can be removed
4032 * from 'daemon->urh_head' list. */
4033 urhn = urh->prev;
4034 /* Check for fd mismatch. FIXME: required for safety? */
4035 if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
4036 (p[poll_server + i + 1].fd != urh->mhd.socket))
4037 break;
4038 urh_from_pollfd (urh,
4039 &p[poll_server + i]);
4040 i += 2;
4041 process_urh (urh);
4042 /* Finished forwarding? */
4043 if ( (0 == urh->in_buffer_size) &&
4044 (0 == urh->out_buffer_size) &&
4045 (0 == urh->in_buffer_used) &&
4046 (0 == urh->out_buffer_used) )
4047 {
4048 /* MHD_connection_finish_forward_() will remove connection from
4049 * 'daemon->urh_head' list. */
4050 MHD_connection_finish_forward_ (urh->connection);
4051 urh->clean_ready = true;
4052 /* If 'urh->was_closed' already was set to true, connection will be
4053 * moved immediately to cleanup list. Otherwise connection
4054 * will stay in suspended list until 'urh' will be marked
4055 * with 'was_closed' by application. */
4056 MHD_resume_connection (urh->connection);
4057 }
4058 }
4059#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4060 /* handle 'listen' FD */
4061 if ( (-1 != poll_listen) &&
4062 (0 != (p[poll_listen].revents & POLLIN)) )
4063 (void) MHD_accept_connection (daemon);
4064
4065 free (p);
4066 }
4067 return MHD_YES;
4068}
4069
4070
4078static enum MHD_Result
4079MHD_poll_listen_socket (struct MHD_Daemon *daemon,
4080 int may_block)
4081{
4082 struct pollfd p[2];
4083 int timeout;
4084 unsigned int poll_count;
4085 int poll_listen;
4086 int poll_itc_idx;
4087 MHD_socket ls;
4088
4089 memset (&p,
4090 0,
4091 sizeof (p));
4092 poll_count = 0;
4093 poll_listen = -1;
4094 poll_itc_idx = -1;
4095 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4096 (! daemon->was_quiesced) )
4097
4098 {
4099 p[poll_count].fd = ls;
4100 p[poll_count].events = POLLIN;
4101 p[poll_count].revents = 0;
4102 poll_listen = poll_count;
4103 poll_count++;
4104 }
4105 if (MHD_ITC_IS_VALID_ (daemon->itc))
4106 {
4107 p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
4108 p[poll_count].events = POLLIN;
4109 p[poll_count].revents = 0;
4110 poll_itc_idx = poll_count;
4111 poll_count++;
4112 }
4113
4114 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4115 (void) resume_suspended_connections (daemon);
4116
4117 if (MHD_NO == may_block)
4118 timeout = 0;
4119 else
4120 timeout = -1;
4121 if (0 == poll_count)
4122 return MHD_YES;
4123 if (MHD_sys_poll_ (p,
4124 poll_count,
4125 timeout) < 0)
4126 {
4127 const int err = MHD_socket_get_error_ ();
4128
4129 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4130 return MHD_YES;
4131#ifdef HAVE_MESSAGES
4132 MHD_DLOG (daemon,
4133 _ ("poll failed: %s\n"),
4134 MHD_socket_strerr_ (err));
4135#endif
4136 return MHD_NO;
4137 }
4138 if ( (-1 != poll_itc_idx) &&
4139 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4140 MHD_itc_clear_ (daemon->itc);
4141
4142 /* handle shutdown */
4143 if (daemon->shutdown)
4144 return MHD_NO;
4145 if ( (-1 != poll_listen) &&
4146 (0 != (p[poll_listen].revents & POLLIN)) )
4147 (void) MHD_accept_connection (daemon);
4148 return MHD_YES;
4149}
4150
4151
4152#endif
4153
4154
4162static enum MHD_Result
4163MHD_poll (struct MHD_Daemon *daemon,
4164 int may_block)
4165{
4166#ifdef HAVE_POLL
4167 if (daemon->shutdown)
4168 return MHD_NO;
4169 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4170 return MHD_poll_all (daemon,
4171 may_block);
4172 return MHD_poll_listen_socket (daemon,
4173 may_block);
4174#else
4175 (void) daemon;
4176 (void) may_block;
4177 return MHD_NO;
4178#endif
4179}
4180
4181
4182#ifdef EPOLL_SUPPORT
4183
4192#define MAX_EVENTS 128
4193
4194
4195#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4196
4204static bool
4205is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
4206{
4207 const struct MHD_Connection *const connection = urh->connection;
4208
4209 if ( (0 == urh->in_buffer_size) &&
4210 (0 == urh->out_buffer_size) &&
4211 (0 == urh->in_buffer_used) &&
4212 (0 == urh->out_buffer_used) )
4213 return false;
4214 if (connection->daemon->shutdown)
4215 return true;
4216 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4217 (connection->tls_read_ready) ) &&
4218 (urh->in_buffer_used < urh->in_buffer_size) )
4219 return true;
4220 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4221 (urh->out_buffer_used < urh->out_buffer_size) )
4222 return true;
4223 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4224 (urh->out_buffer_used > 0) )
4225 return true;
4226 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4227 (urh->in_buffer_used > 0) )
4228 return true;
4229 return false;
4230}
4231
4232
4241static enum MHD_Result
4242run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4243{
4244 struct epoll_event events[MAX_EVENTS];
4245 int num_events;
4246 struct MHD_UpgradeResponseHandle *pos;
4247 struct MHD_UpgradeResponseHandle *prev;
4248
4249 num_events = MAX_EVENTS;
4250 while (0 != num_events)
4251 {
4252 unsigned int i;
4253 /* update event masks */
4254 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4255 events,
4256 MAX_EVENTS,
4257 0);
4258 if (-1 == num_events)
4259 {
4260 const int err = MHD_socket_get_error_ ();
4261
4262 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4263 return MHD_YES;
4264#ifdef HAVE_MESSAGES
4265 MHD_DLOG (daemon,
4266 _ ("Call to epoll_wait failed: %s\n"),
4267 MHD_socket_strerr_ (err));
4268#endif
4269 return MHD_NO;
4270 }
4271 for (i = 0; i < (unsigned int) num_events; i++)
4272 {
4273 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
4274 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
4275 bool new_err_state = false;
4276
4277 if (urh->clean_ready)
4278 continue;
4279
4280 /* Update ueh state based on what is ready according to epoll() */
4281 if (0 != (events[i].events & EPOLLIN))
4282 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4283 if (0 != (events[i].events & EPOLLOUT))
4284 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4285 if (0 != (events[i].events & EPOLLHUP))
4287
4288 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4289 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4290 {
4291 /* Process new error state only one time
4292 * and avoid continuously marking this connection
4293 * as 'ready'. */
4294 ueh->celi |= MHD_EPOLL_STATE_ERROR;
4295 new_err_state = true;
4296 }
4297
4298 if (! urh->in_eready_list)
4299 {
4300 if (new_err_state ||
4301 is_urh_ready (urh))
4302 {
4303 EDLL_insert (daemon->eready_urh_head,
4304 daemon->eready_urh_tail,
4305 urh);
4306 urh->in_eready_list = true;
4307 }
4308 }
4309 }
4310 }
4311 prev = daemon->eready_urh_tail;
4312 while (NULL != (pos = prev))
4313 {
4314 prev = pos->prevE;
4315 process_urh (pos);
4316 if (! is_urh_ready (pos))
4317 {
4318 EDLL_remove (daemon->eready_urh_head,
4319 daemon->eready_urh_tail,
4320 pos);
4321 pos->in_eready_list = false;
4322 }
4323 /* Finished forwarding? */
4324 if ( (0 == pos->in_buffer_size) &&
4325 (0 == pos->out_buffer_size) &&
4326 (0 == pos->in_buffer_used) &&
4327 (0 == pos->out_buffer_used) )
4328 {
4329 MHD_connection_finish_forward_ (pos->connection);
4330 pos->clean_ready = true;
4331 /* If 'pos->was_closed' already was set to true, connection
4332 * will be moved immediately to cleanup list. Otherwise
4333 * connection will stay in suspended list until 'pos' will
4334 * be marked with 'was_closed' by application. */
4335 MHD_resume_connection (pos->connection);
4336 }
4337 }
4338
4339 return MHD_YES;
4340}
4341
4342
4343#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4344
4345
4349static const char *const epoll_itc_marker = "itc_marker";
4350
4351
4360static enum MHD_Result
4361MHD_epoll (struct MHD_Daemon *daemon,
4362 int may_block)
4363{
4364#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4365 static const char *const upgrade_marker = "upgrade_ptr";
4366#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4367 struct MHD_Connection *pos;
4368 struct MHD_Connection *prev;
4369 struct epoll_event events[MAX_EVENTS];
4370 struct epoll_event event;
4371 int timeout_ms;
4372 MHD_UNSIGNED_LONG_LONG timeout_ll;
4373 int num_events;
4374 unsigned int i;
4375 MHD_socket ls;
4376#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4377 bool run_upgraded = false;
4378#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4379
4380 if (-1 == daemon->epoll_fd)
4381 return MHD_NO; /* we're down! */
4382 if (daemon->shutdown)
4383 return MHD_NO;
4384 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4385 (! daemon->was_quiesced) &&
4386 (daemon->connections < daemon->connection_limit) &&
4387 (! daemon->listen_socket_in_epoll) &&
4388 (! daemon->at_limit) )
4389 {
4390 event.events = EPOLLIN;
4391 event.data.ptr = daemon;
4392 if (0 != epoll_ctl (daemon->epoll_fd,
4393 EPOLL_CTL_ADD,
4394 ls,
4395 &event))
4396 {
4397#ifdef HAVE_MESSAGES
4398 MHD_DLOG (daemon,
4399 _ ("Call to epoll_ctl failed: %s\n"),
4401#endif
4402 return MHD_NO;
4403 }
4404 daemon->listen_socket_in_epoll = true;
4405 }
4406 if ( (daemon->was_quiesced) &&
4407 (daemon->listen_socket_in_epoll) )
4408 {
4409 if ( (0 != epoll_ctl (daemon->epoll_fd,
4410 EPOLL_CTL_DEL,
4411 ls,
4412 NULL)) &&
4413 (ENOENT != errno) ) /* ENOENT can happen due to race with
4414 #MHD_quiesce_daemon() */
4415 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4416 daemon->listen_socket_in_epoll = false;
4417 }
4418
4419#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4420 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4421 (-1 != daemon->epoll_upgrade_fd) ) )
4422 {
4423 event.events = EPOLLIN | EPOLLOUT;
4424 event.data.ptr = (void *) upgrade_marker;
4425 if (0 != epoll_ctl (daemon->epoll_fd,
4426 EPOLL_CTL_ADD,
4427 daemon->epoll_upgrade_fd,
4428 &event))
4429 {
4430#ifdef HAVE_MESSAGES
4431 MHD_DLOG (daemon,
4432 _ ("Call to epoll_ctl failed: %s\n"),
4434#endif
4435 return MHD_NO;
4436 }
4437 daemon->upgrade_fd_in_epoll = true;
4438 }
4439#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4440 if ( (daemon->listen_socket_in_epoll) &&
4441 ( (daemon->connections == daemon->connection_limit) ||
4442 (daemon->at_limit) ||
4443 (daemon->was_quiesced) ) )
4444 {
4445 /* we're at the connection limit, disable listen socket
4446 for event loop for now */
4447 if (0 != epoll_ctl (daemon->epoll_fd,
4448 EPOLL_CTL_DEL,
4449 ls,
4450 NULL))
4451 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
4452 daemon->listen_socket_in_epoll = false;
4453 }
4454
4455 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4457 may_block = MHD_NO;
4458
4459 if (MHD_YES == may_block)
4460 {
4461 if (MHD_YES == MHD_get_timeout (daemon,
4462 &timeout_ll))
4463 {
4464 if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4465 timeout_ms = INT_MAX;
4466 else
4467 timeout_ms = (int) timeout_ll;
4468 }
4469 else
4470 timeout_ms = -1;
4471 }
4472 else
4473 timeout_ms = 0;
4474
4475 /* Reset. New value will be set when connections are processed. */
4476 /* Note: Used mostly for uniformity here as same situation is
4477 * signaled in epoll mode by non-empty eready DLL. */
4478 daemon->data_already_pending = false;
4479
4480 /* drain 'epoll' event queue; need to iterate as we get at most
4481 MAX_EVENTS in one system call here; in practice this should
4482 pretty much mean only one round, but better an extra loop here
4483 than unfair behavior... */
4484 num_events = MAX_EVENTS;
4485 while (MAX_EVENTS == num_events)
4486 {
4487 /* update event masks */
4488 num_events = epoll_wait (daemon->epoll_fd,
4489 events,
4490 MAX_EVENTS,
4491 timeout_ms);
4492 if (-1 == num_events)
4493 {
4494 const int err = MHD_socket_get_error_ ();
4495 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4496 return MHD_YES;
4497#ifdef HAVE_MESSAGES
4498 MHD_DLOG (daemon,
4499 _ ("Call to epoll_wait failed: %s\n"),
4500 MHD_socket_strerr_ (err));
4501#endif
4502 return MHD_NO;
4503 }
4504 for (i = 0; i<(unsigned int) num_events; i++)
4505 {
4506 /* First, check for the values of `ptr` that would indicate
4507 that this event is not about a normal connection. */
4508 if (NULL == events[i].data.ptr)
4509 continue; /* shutdown signal! */
4510#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4511 if (upgrade_marker == events[i].data.ptr)
4512 {
4513 /* activity on an upgraded connection, we process
4514 those in a separate epoll() */
4515 run_upgraded = true;
4516 continue;
4517 }
4518#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4519 if (epoll_itc_marker == events[i].data.ptr)
4520 {
4521 /* It's OK to clear ITC here as all external
4522 conditions will be processed later. */
4523 MHD_itc_clear_ (daemon->itc);
4524 continue;
4525 }
4526 if (daemon == events[i].data.ptr)
4527 {
4528 /* Check for error conditions on listen socket. */
4529 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4530 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4531 {
4532 unsigned int series_length = 0;
4533 /* Run 'accept' until it fails or daemon at limit of connections.
4534 * Do not accept more then 10 connections at once. The rest will
4535 * be accepted on next turn (level trigger is used for listen
4536 * socket). */
4537 while ( (MHD_YES == MHD_accept_connection (daemon)) &&
4538 (series_length < 10) &&
4539 (daemon->connections < daemon->connection_limit) &&
4540 (! daemon->at_limit) )
4541 series_length++;
4542 }
4543 continue;
4544 }
4545 /* this is an event relating to a 'normal' connection,
4546 remember the event and if appropriate mark the
4547 connection as 'eready'. */
4548 pos = events[i].data.ptr;
4549 /* normal processing: update read/write data */
4550 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4551 {
4552 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4553 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4554 {
4555 EDLL_insert (daemon->eready_head,
4556 daemon->eready_tail,
4557 pos);
4558 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4559 }
4560 }
4561 else
4562 {
4563 if (0 != (events[i].events & EPOLLIN))
4564 {
4565 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4566 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4567 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4568 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4569 {
4570 EDLL_insert (daemon->eready_head,
4571 daemon->eready_tail,
4572 pos);
4573 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4574 }
4575 }
4576 if (0 != (events[i].events & EPOLLOUT))
4577 {
4578 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4580 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4581 {
4582 EDLL_insert (daemon->eready_head,
4583 daemon->eready_tail,
4584 pos);
4585 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4586 }
4587 }
4588 }
4589 }
4590 }
4591
4592#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4593 if (run_upgraded || (NULL != daemon->eready_urh_head))
4594 run_epoll_for_upgrade (daemon);
4595#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4596
4597 /* process events for connections */
4598 prev = daemon->eready_tail;
4599 while (NULL != (pos = prev))
4600 {
4601 prev = pos->prevE;
4602 call_handlers (pos,
4603 0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
4604 0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
4605 0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
4607 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
4609 {
4610 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
4611 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
4613 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
4615 {
4616 EDLL_remove (daemon->eready_head,
4617 daemon->eready_tail,
4618 pos);
4619 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4620 }
4621 }
4622 }
4623
4624 /* Finally, handle timed-out connections; we need to do this here
4625 as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
4626 as the other event loops do. As timeouts do not get an explicit
4627 event, we need to find those connections that might have timed out
4628 here.
4629
4630 Connections with custom timeouts must all be looked at, as we
4631 do not bother to sort that (presumably very short) list. */prev = daemon->manual_timeout_tail;
4632 while (NULL != (pos = prev))
4633 {
4634 prev = pos->prevX;
4636 }
4637 /* Connections with the default timeout are sorted by prepending
4638 them to the head of the list whenever we touch the connection;
4639 thus it suffices to iterate from the tail until the first
4640 connection is NOT timed out */
4641 prev = daemon->normal_timeout_tail;
4642 while (NULL != (pos = prev))
4643 {
4644 prev = pos->prevX;
4646 if (MHD_CONNECTION_CLOSED != pos->state)
4647 break; /* sorted by timeout, no need to visit the rest! */
4648 }
4649 return MHD_YES;
4650}
4651
4652
4653#endif
4654
4655
4676enum MHD_Result
4677MHD_run (struct MHD_Daemon *daemon)
4678{
4679 if ( (daemon->shutdown) ||
4680 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4681 return MHD_NO;
4682 if (0 != (daemon->options & MHD_USE_POLL))
4683 {
4684 MHD_poll (daemon, MHD_NO);
4685 MHD_cleanup_connections (daemon);
4686 }
4687#ifdef EPOLL_SUPPORT
4688 else if (0 != (daemon->options & MHD_USE_EPOLL))
4689 {
4690 MHD_epoll (daemon, MHD_NO);
4691 MHD_cleanup_connections (daemon);
4692 }
4693#endif
4694 else
4695 {
4696 MHD_select (daemon, MHD_NO);
4697 /* MHD_select does MHD_cleanup_connections already */
4698 }
4699 return MHD_YES;
4700}
4701
4702
4711static void
4713{
4714 struct MHD_Daemon *daemon = pos->daemon;
4715
4716 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4717 {
4719 return; /* must let thread to do the rest */
4720 }
4723#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4725#endif
4726 mhd_assert (! pos->suspended);
4727 mhd_assert (! pos->resuming);
4728 if (pos->connection_timeout == daemon->connection_timeout)
4730 daemon->normal_timeout_tail,
4731 pos);
4732 else
4734 daemon->manual_timeout_tail,
4735 pos);
4737 daemon->connections_tail,
4738 pos);
4739 DLL_insert (daemon->cleanup_head,
4740 daemon->cleanup_tail,
4741 pos);
4742#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4744#endif
4745}
4746
4747
4748#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4756static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4757MHD_polling_thread (void *cls)
4758{
4759 struct MHD_Daemon *daemon = cls;
4760
4761 MHD_thread_init_ (&(daemon->pid));
4762 while (! daemon->shutdown)
4763 {
4764 if (0 != (daemon->options & MHD_USE_POLL))
4765 MHD_poll (daemon, MHD_YES);
4766#ifdef EPOLL_SUPPORT
4767 else if (0 != (daemon->options & MHD_USE_EPOLL))
4768 MHD_epoll (daemon, MHD_YES);
4769#endif
4770 else
4771 MHD_select (daemon, MHD_YES);
4772 MHD_cleanup_connections (daemon);
4773 }
4774
4775 /* Resume any pending for resume connections, join
4776 * all connection's threads (if any) and finally cleanup
4777 * everything. */
4778 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
4780 close_all_connections (daemon);
4781
4782 return (MHD_THRD_RTRN_TYPE_) 0;
4783}
4784
4785
4786#endif
4787
4788
4800static size_t
4802 struct MHD_Connection *connection,
4803 char *val)
4804{
4805 (void) cls; /* Mute compiler warning. */
4806
4807 (void) connection; /* Mute compiler warning. */
4808 return MHD_http_unescape (val);
4809}
4810
4811
4832struct MHD_Daemon *
4833MHD_start_daemon (unsigned int flags,
4834 uint16_t port,
4836 void *apc_cls,
4838 void *dh_cls,
4839 ...)
4840{
4841 struct MHD_Daemon *daemon;
4842 va_list ap;
4843
4844 va_start (ap,
4845 dh_cls);
4846 daemon = MHD_start_daemon_va (flags,
4847 port,
4848 apc,
4849 apc_cls,
4850 dh,
4851 dh_cls,
4852 ap);
4853 va_end (ap);
4854 return daemon;
4855}
4856
4857
4879{
4880#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4881 unsigned int i;
4882#endif
4883 MHD_socket ret;
4884
4885 ret = daemon->listen_fd;
4886 if (MHD_INVALID_SOCKET == ret)
4887 return MHD_INVALID_SOCKET;
4888 if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
4889 (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
4890 {
4891#ifdef HAVE_MESSAGES
4892 MHD_DLOG (daemon,
4893 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n");
4894#endif
4895 return MHD_INVALID_SOCKET;
4896 }
4897
4898#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4899 if (NULL != daemon->worker_pool)
4900 for (i = 0; i < daemon->worker_pool_size; i++)
4901 {
4902 daemon->worker_pool[i].was_quiesced = true;
4903#ifdef EPOLL_SUPPORT
4904 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4905 (-1 != daemon->worker_pool[i].epoll_fd) &&
4906 (daemon->worker_pool[i].listen_socket_in_epoll) )
4907 {
4908 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4909 EPOLL_CTL_DEL,
4910 ret,
4911 NULL))
4912 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
4913 daemon->worker_pool[i].listen_socket_in_epoll = false;
4914 }
4915 else
4916#endif
4917 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
4918 {
4919 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4920 MHD_PANIC (_ (
4921 "Failed to signal quiesce via inter-thread communication channel.\n"));
4922 }
4923 }
4924#endif
4925 daemon->was_quiesced = true;
4926#ifdef EPOLL_SUPPORT
4927 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4928 (-1 != daemon->epoll_fd) &&
4929 (daemon->listen_socket_in_epoll) )
4930 {
4931 if ( (0 != epoll_ctl (daemon->epoll_fd,
4932 EPOLL_CTL_DEL,
4933 ret,
4934 NULL)) &&
4935 (ENOENT != errno) ) /* ENOENT can happen due to race with
4936 #MHD_epoll() */
4937 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4938 daemon->listen_socket_in_epoll = false;
4939 }
4940#endif
4941 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4942 (! MHD_itc_activate_ (daemon->itc, "q")) )
4943 MHD_PANIC (_ (
4944 "failed to signal quiesce via inter-thread communication channel.\n"));
4945 return ret;
4946}
4947
4948
4956typedef void
4957(*VfprintfFunctionPointerType)(void *cls,
4958 const char *format,
4959 va_list va);
4960
4961
4970static enum MHD_Result
4971parse_options_va (struct MHD_Daemon *daemon,
4972 const struct sockaddr **servaddr,
4973 va_list ap);
4974
4975
4984static enum MHD_Result
4986 const struct sockaddr **servaddr,
4987 ...)
4988{
4989 va_list ap;
4990 enum MHD_Result ret;
4991
4992 va_start (ap, servaddr);
4993 ret = parse_options_va (daemon,
4994 servaddr,
4995 ap);
4996 va_end (ap);
4997 return ret;
4998}
4999
5000
5009static enum MHD_Result
5011 const struct sockaddr **servaddr,
5012 va_list ap)
5013{
5014 enum MHD_OPTION opt;
5015 struct MHD_OptionItem *oa;
5016 unsigned int i;
5017 unsigned int uv;
5018#ifdef HTTPS_SUPPORT
5019 enum MHD_Result ret;
5020 const char *pstr;
5021#if GNUTLS_VERSION_MAJOR >= 3
5022 gnutls_certificate_retrieve_function2 *pgcrf;
5023#endif
5024#if GNUTLS_VERSION_NUMBER >= 0x030603
5025 gnutls_certificate_retrieve_function3 *pgcrf2;
5026#endif
5027#endif /* HTTPS_SUPPORT */
5028
5029 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
5030 {
5031 switch (opt)
5032 {
5034 daemon->pool_size = va_arg (ap,
5035 size_t);
5036 break;
5038 daemon->pool_increment = va_arg (ap,
5039 size_t);
5040 break;
5042 daemon->connection_limit = va_arg (ap,
5043 unsigned int);
5044 break;
5046 uv = va_arg (ap,
5047 unsigned int);
5048 daemon->connection_timeout = (time_t) uv;
5049 /* Next comparison could be always false on some platforms and whole branch will
5050 * be optimized out on those platforms. On others it will be compiled into real
5051 * check. */
5052 if ( ( (MHD_TYPE_IS_SIGNED_ (time_t)) &&
5053 (daemon->connection_timeout < 0) ) || /* Compiler may warn on some platforms, ignore warning. */
5054 (uv != (unsigned int) daemon->connection_timeout) )
5055 {
5056#ifdef HAVE_MESSAGES
5057 MHD_DLOG (daemon,
5058 _ ("Warning: Too large timeout value, ignored.\n"));
5059#endif
5060 daemon->connection_timeout = 0;
5061 }
5062 break;
5064 daemon->notify_completed = va_arg (ap,
5066 daemon->notify_completed_cls = va_arg (ap,
5067 void *);
5068 break;
5070 daemon->notify_connection = va_arg (ap,
5072 daemon->notify_connection_cls = va_arg (ap,
5073 void *);
5074 break;
5076 daemon->per_ip_connection_limit = va_arg (ap,
5077 unsigned int);
5078 break;
5080 *servaddr = va_arg (ap,
5081 const struct sockaddr *);
5082 break;
5084 daemon->uri_log_callback = va_arg (ap,
5085 LogCallback);
5086 daemon->uri_log_callback_cls = va_arg (ap,
5087 void *);
5088 break;
5090 daemon->insanity_level = (enum MHD_DisableSanityCheck)
5091 va_arg (ap,
5092 unsigned int);
5093 break;
5094#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5096 daemon->worker_pool_size = va_arg (ap,
5097 unsigned int);
5098 if (0 == daemon->worker_pool_size)
5099 {
5100#ifdef HAVE_MESSAGES
5101 MHD_DLOG (daemon,
5102 _ (
5103 "Warning: Zero size, specified for thread pool size, is ignored. "
5104 "Thread pool is not used.\n"));
5105#endif
5106 }
5107 else if (1 == daemon->worker_pool_size)
5108 {
5109#ifdef HAVE_MESSAGES
5110 MHD_DLOG (daemon,
5111 _ (
5112 "Warning: \"1\", specified for thread pool size, is ignored. "
5113 "Thread pool is not used.\n"));
5114#endif
5115 daemon->worker_pool_size = 0;
5116 }
5117 /* Next comparison could be always false on some platforms and whole branch will
5118 * be optimized out on those platforms. On others it will be compiled into real
5119 * check. */
5120 else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct
5121 MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
5122 {
5123#ifdef HAVE_MESSAGES
5124 MHD_DLOG (daemon,
5125 _ ("Specified thread pool size (%u) too big.\n"),
5126 daemon->worker_pool_size);
5127#endif
5128 return MHD_NO;
5129 }
5130 else
5131 {
5132 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
5133 {
5134#ifdef HAVE_MESSAGES
5135 MHD_DLOG (daemon,
5136 _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5137 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5138#endif
5139 return MHD_NO;
5140 }
5141 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5142 {
5143#ifdef HAVE_MESSAGES
5144 MHD_DLOG (daemon,
5145 _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
5146 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5147#endif
5148 return MHD_NO;
5149 }
5150 }
5151 break;
5152#endif
5153#ifdef HTTPS_SUPPORT
5155 pstr = va_arg (ap,
5156 const char *);
5157 if (0 != (daemon->options & MHD_USE_TLS))
5158 daemon->https_mem_key = pstr;
5159#ifdef HAVE_MESSAGES
5160 else
5161 MHD_DLOG (daemon,
5162 _ (
5163 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5164 opt);
5165#endif
5166 break;
5168 pstr = va_arg (ap,
5169 const char *);
5170 if (0 != (daemon->options & MHD_USE_TLS))
5171 daemon->https_key_password = pstr;
5172#ifdef HAVE_MESSAGES
5173 else
5174 MHD_DLOG (daemon,
5175 _ (
5176 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5177 opt);
5178#endif
5179 break;
5181 pstr = va_arg (ap,
5182 const char *);
5183 if (0 != (daemon->options & MHD_USE_TLS))
5184 daemon->https_mem_cert = pstr;
5185#ifdef HAVE_MESSAGES
5186 else
5187 MHD_DLOG (daemon,
5188 _ (
5189 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5190 opt);
5191#endif
5192 break;
5194 pstr = va_arg (ap,
5195 const char *);
5196 if (0 != (daemon->options & MHD_USE_TLS))
5197 daemon->https_mem_trust = pstr;
5198#ifdef HAVE_MESSAGES
5199 else
5200 MHD_DLOG (daemon,
5201 _ (
5202 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5203 opt);
5204#endif
5205 break;
5207 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5208 int);
5209 break;
5211 pstr = va_arg (ap,
5212 const char *);
5213 if (0 != (daemon->options & MHD_USE_TLS))
5214 {
5215 gnutls_datum_t dhpar;
5216 size_t pstr_len;
5217
5218 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5219 {
5220#ifdef HAVE_MESSAGES
5221 MHD_DLOG (daemon,
5222 _ ("Error initializing DH parameters.\n"));
5223#endif
5224 return MHD_NO;
5225 }
5226 dhpar.data = (unsigned char *) pstr;
5227 pstr_len = strlen (pstr);
5228 if (UINT_MAX < pstr_len)
5229 {
5230#ifdef HAVE_MESSAGES
5231 MHD_DLOG (daemon,
5232 _ ("Diffie-Hellman parameters string too long.\n"));
5233#endif
5234 return MHD_NO;
5235 }
5236 dhpar.size = (unsigned int) pstr_len;
5237 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5238 &dhpar,
5239 GNUTLS_X509_FMT_PEM) < 0)
5240 {
5241#ifdef HAVE_MESSAGES
5242 MHD_DLOG (daemon,
5243 _ ("Bad Diffie-Hellman parameters format.\n"));
5244#endif
5245 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5246 return MHD_NO;
5247 }
5248 daemon->have_dhparams = true;
5249 }
5250#ifdef HAVE_MESSAGES
5251 else
5252 MHD_DLOG (daemon,
5253 _ (
5254 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5255 opt);
5256#endif
5257 break;
5259 pstr = va_arg (ap,
5260 const char *);
5261 if (0 != (daemon->options & MHD_USE_TLS))
5262 {
5263 gnutls_priority_deinit (daemon->priority_cache);
5264 ret = gnutls_priority_init (&daemon->priority_cache,
5265 pstr,
5266 NULL);
5267 if (GNUTLS_E_SUCCESS != ret)
5268 {
5269#ifdef HAVE_MESSAGES
5270 MHD_DLOG (daemon,
5271 _ ("Setting priorities to `%s' failed: %s\n"),
5272 pstr,
5273 gnutls_strerror (ret));
5274#endif
5275 daemon->priority_cache = NULL;
5276 return MHD_NO;
5277 }
5278 }
5279#ifdef HAVE_MESSAGES
5280 else
5281 MHD_DLOG (daemon,
5282 _ (
5283 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5284 opt);
5285#endif
5286 break;
5288#if GNUTLS_VERSION_MAJOR < 3
5289#ifdef HAVE_MESSAGES
5290 MHD_DLOG (daemon,
5291 _ (
5292 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5293#endif
5294 return MHD_NO;
5295#else
5296 pgcrf = va_arg (ap,
5297 gnutls_certificate_retrieve_function2 *);
5298 if (0 != (daemon->options & MHD_USE_TLS))
5299 daemon->cert_callback = pgcrf;
5300 else
5301#ifdef HAVE_MESSAGES
5302 MHD_DLOG (daemon,
5303 _ (
5304 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5305 opt);
5306#endif
5307 break;
5308#endif
5310#if GNUTLS_VERSION_NUMBER < 0x030603
5311#ifdef HAVE_MESSAGES
5312 MHD_DLOG (daemon,
5313 _ (
5314 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5315#endif
5316 return MHD_NO;
5317#else
5318 pgcrf2 = va_arg (ap,
5319 gnutls_certificate_retrieve_function3 *);
5320 if (0 != (daemon->options & MHD_USE_TLS))
5321 daemon->cert_callback2 = pgcrf2;
5322 else
5323#ifdef HAVE_MESSAGES
5324 MHD_DLOG (daemon,
5325 _ (
5326 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5327 opt);
5328#endif
5329 break;
5330#endif
5331#endif /* HTTPS_SUPPORT */
5332#ifdef DAUTH_SUPPORT
5334 daemon->digest_auth_rand_size = va_arg (ap,
5335 size_t);
5336 daemon->digest_auth_random = va_arg (ap,
5337 const char *);
5338 break;
5340 daemon->nonce_nc_size = va_arg (ap,
5341 unsigned int);
5342 break;
5343#endif
5345 if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5346 {
5347#ifdef HAVE_MESSAGES
5348 MHD_DLOG (daemon,
5349 _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5350 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5351#endif
5352 return MHD_NO;
5353 }
5354 else
5355 daemon->listen_fd = va_arg (ap,
5356 MHD_socket);
5357 break;
5359#ifdef HAVE_MESSAGES
5360 daemon->custom_error_log = va_arg (ap,
5362 daemon->custom_error_log_cls = va_arg (ap,
5363 void *);
5364#else
5365 va_arg (ap,
5367 va_arg (ap,
5368 void *);
5369#endif
5370 break;
5371#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5373 daemon->thread_stack_size = va_arg (ap,
5374 size_t);
5375 break;
5376#endif
5378#ifdef TCP_FASTOPEN
5379 daemon->fastopen_queue_size = va_arg (ap,
5380 unsigned int);
5381 break;
5382#else /* ! TCP_FASTOPEN */
5383#ifdef HAVE_MESSAGES
5384 MHD_DLOG (daemon,
5385 _ ("TCP fastopen is not supported on this platform.\n"));
5386 return MHD_NO;
5387#endif /* HAVE_MESSAGES */
5388#endif /* ! TCP_FASTOPEN */
5390 daemon->listening_address_reuse = va_arg (ap,
5391 unsigned int) ? 1 : -1;
5392 break;
5394 daemon->listen_backlog_size = va_arg (ap,
5395 unsigned int);
5396 break;
5398 daemon->strict_for_client = va_arg (ap, int);
5399#ifdef HAVE_MESSAGES
5400 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
5401 (1 != daemon->strict_for_client) )
5402 {
5403 MHD_DLOG (daemon,
5404 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5405 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5406 }
5407#endif /* HAVE_MESSAGES */
5408 break;
5409 case MHD_OPTION_ARRAY:
5410 oa = va_arg (ap, struct MHD_OptionItem*);
5411 i = 0;
5412 while (MHD_OPTION_END != (opt = oa[i].option))
5413 {
5414 switch (opt)
5415 {
5416 /* all options taking 'size_t' */
5420 if (MHD_YES != parse_options (daemon,
5421 servaddr,
5422 opt,
5423 (size_t) oa[i].value,
5425 return MHD_NO;
5426 break;
5427 /* all options taking 'unsigned int' */
5437 if (MHD_YES != parse_options (daemon,
5438 servaddr,
5439 opt,
5440 (unsigned int) oa[i].value,
5442 return MHD_NO;
5443 break;
5444 /* all options taking 'enum' */
5445#ifdef HTTPS_SUPPORT
5447 if (MHD_YES != parse_options (daemon,
5448 servaddr,
5449 opt,
5450 (gnutls_credentials_type_t) oa[i].value,
5452 return MHD_NO;
5453 break;
5454#endif /* HTTPS_SUPPORT */
5455 /* all options taking 'MHD_socket' */
5457 if (MHD_YES != parse_options (daemon,
5458 servaddr,
5459 opt,
5460 (MHD_socket) oa[i].value,
5462 return MHD_NO;
5463 break;
5464 /* all options taking 'int' */
5466 if (MHD_YES != parse_options (daemon,
5467 servaddr,
5468 opt,
5469 (int) oa[i].value,
5471 return MHD_NO;
5472 break;
5473 /* all options taking one pointer */
5481 case MHD_OPTION_ARRAY:
5484 if (MHD_YES != parse_options (daemon,
5485 servaddr,
5486 opt,
5487 oa[i].ptr_value,
5489 return MHD_NO;
5490 break;
5491 /* all options taking two pointers */
5498 if (MHD_YES != parse_options (daemon,
5499 servaddr,
5500 opt,
5501 (void *) oa[i].value,
5502 oa[i].ptr_value,
5504 return MHD_NO;
5505 break;
5506 /* options taking size_t-number followed by pointer */
5508 if (MHD_YES != parse_options (daemon,
5509 servaddr,
5510 opt,
5511 (size_t) oa[i].value,
5512 oa[i].ptr_value,
5514 return MHD_NO;
5515 break;
5516 default:
5517 return MHD_NO;
5518 }
5519 i++;
5520 }
5521 break;
5523 daemon->unescape_callback = va_arg (ap,
5525 daemon->unescape_callback_cls = va_arg (ap,
5526 void *);
5527 break;
5528#ifdef HTTPS_SUPPORT
5530#if GNUTLS_VERSION_MAJOR >= 3
5531 daemon->cred_callback = va_arg (ap,
5533 daemon->cred_callback_cls = va_arg (ap,
5534 void *);
5535 break;
5536#else
5537 MHD_DLOG (daemon,
5538 _ (
5539 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
5540 opt);
5541 return MHD_NO;
5542#endif
5543#endif /* HTTPS_SUPPORT */
5544 default:
5545#ifdef HAVE_MESSAGES
5546 if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
5547 (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
5548 (opt == MHD_OPTION_HTTPS_MEM_TRUST) ||
5550 {
5551 MHD_DLOG (daemon,
5552 _ (
5553 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
5554 opt);
5555 }
5556 else
5557 {
5558 MHD_DLOG (daemon,
5559 _ (
5560 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
5561 opt);
5562 }
5563#endif
5564 return MHD_NO;
5565 }
5566 }
5567 return MHD_YES;
5568}
5569
5570
5571#ifdef EPOLL_SUPPORT
5572static int
5573setup_epoll_fd (struct MHD_Daemon *daemon)
5574{
5575 int fd;
5576
5577#ifndef HAVE_MESSAGES
5578 (void) daemon; /* Mute compiler warning. */
5579#endif /* ! HAVE_MESSAGES */
5580
5581#ifdef USE_EPOLL_CREATE1
5582 fd = epoll_create1 (EPOLL_CLOEXEC);
5583#else /* ! USE_EPOLL_CREATE1 */
5584 fd = epoll_create (MAX_EVENTS);
5585#endif /* ! USE_EPOLL_CREATE1 */
5586 if (MHD_INVALID_SOCKET == fd)
5587 {
5588#ifdef HAVE_MESSAGES
5589 MHD_DLOG (daemon,
5590 _ ("Call to epoll_create1 failed: %s\n"),
5592#endif
5593 return MHD_INVALID_SOCKET;
5594 }
5595#if ! defined(USE_EPOLL_CREATE1)
5597 {
5598#ifdef HAVE_MESSAGES
5599 MHD_DLOG (daemon,
5600 _ ("Failed to set noninheritable mode on epoll FD.\n"));
5601#endif
5602 }
5603#endif /* ! USE_EPOLL_CREATE1 */
5604 return fd;
5605}
5606
5607
5617static enum MHD_Result
5618setup_epoll_to_listen (struct MHD_Daemon *daemon)
5619{
5620 struct epoll_event event;
5621 MHD_socket ls;
5622
5623 daemon->epoll_fd = setup_epoll_fd (daemon);
5624 if (-1 == daemon->epoll_fd)
5625 return MHD_NO;
5626#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5627 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
5628 {
5629 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5630 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
5631 return MHD_NO;
5632 }
5633#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5634 if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
5635 (daemon->was_quiesced) )
5636 return MHD_YES; /* non-listening daemon */
5637 event.events = EPOLLIN;
5638 event.data.ptr = daemon;
5639 if (0 != epoll_ctl (daemon->epoll_fd,
5640 EPOLL_CTL_ADD,
5641 ls,
5642 &event))
5643 {
5644#ifdef HAVE_MESSAGES
5645 MHD_DLOG (daemon,
5646 _ ("Call to epoll_ctl failed: %s\n"),
5648#endif
5649 return MHD_NO;
5650 }
5651 daemon->listen_socket_in_epoll = true;
5652 if (MHD_ITC_IS_VALID_ (daemon->itc))
5653 {
5654 event.events = EPOLLIN;
5655 event.data.ptr = (void *) epoll_itc_marker;
5656 if (0 != epoll_ctl (daemon->epoll_fd,
5657 EPOLL_CTL_ADD,
5658 MHD_itc_r_fd_ (daemon->itc),
5659 &event))
5660 {
5661#ifdef HAVE_MESSAGES
5662 MHD_DLOG (daemon,
5663 _ ("Call to epoll_ctl failed: %s\n"),
5665#endif
5666 return MHD_NO;
5667 }
5668 }
5669 return MHD_YES;
5670}
5671
5672
5673#endif
5674
5675
5697struct MHD_Daemon *
5698MHD_start_daemon_va (unsigned int flags,
5699 uint16_t port,
5701 void *apc_cls,
5703 void *dh_cls,
5704 va_list ap)
5705{
5706 const MHD_SCKT_OPT_BOOL_ on = 1;
5707 struct MHD_Daemon *daemon;
5709 struct sockaddr_in servaddr4;
5710#if HAVE_INET6
5711 struct sockaddr_in6 servaddr6;
5712#endif
5713 const struct sockaddr *servaddr = NULL;
5714 socklen_t addrlen;
5715#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5716 unsigned int i;
5717#endif
5718 enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
5719 enum MHD_FLAG *pflags;
5720
5722 eflags = (enum MHD_FLAG) flags;
5723 pflags = &eflags;
5724#ifndef HAVE_INET6
5725 if (0 != (*pflags & MHD_USE_IPv6))
5726 return NULL;
5727#endif
5728#ifndef HAVE_POLL
5729 if (0 != (*pflags & MHD_USE_POLL))
5730 return NULL;
5731#endif
5732#ifndef EPOLL_SUPPORT
5733 if (0 != (*pflags & MHD_USE_EPOLL))
5734 return NULL;
5735#endif /* ! EPOLL_SUPPORT */
5736#ifndef HTTPS_SUPPORT
5737 if (0 != (*pflags & MHD_USE_TLS))
5738 return NULL;
5739#endif /* ! HTTPS_SUPPORT */
5740#ifndef TCP_FASTOPEN
5741 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5742 return NULL;
5743#endif
5744 if (0 != (*pflags & MHD_ALLOW_UPGRADE))
5745 {
5746#ifdef UPGRADE_SUPPORT
5747 *pflags |= MHD_ALLOW_SUSPEND_RESUME;
5748#else /* ! UPGRADE_SUPPORT */
5749 return NULL;
5750#endif /* ! UPGRADE_SUPPORT */
5751 }
5752 if (NULL == dh)
5753 return NULL;
5754
5755 /* Check for invalid combinations of flags. */
5756 if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5757 ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags
5758 &
5760 ||
5761 ((0 != (*pflags & MHD_USE_POLL)) &&
5762 (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
5764 ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL
5765 | MHD_USE_EPOLL)))) )
5766 return NULL;
5767
5768 if (0 != (*pflags & MHD_USE_AUTO))
5769 {
5770 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5771 {
5772 /* Thread per connection with internal polling thread. */
5773#ifdef HAVE_POLL
5774 *pflags |= MHD_USE_POLL;
5775#else /* ! HAVE_POLL */
5776 /* use select() - do not modify flags */
5777#endif /* ! HAVE_POLL */
5778 }
5779 else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5780 {
5781 /* Internal polling thread. */
5782#if defined(EPOLL_SUPPORT)
5783 *pflags |= MHD_USE_EPOLL;
5784#elif defined(HAVE_POLL)
5785 *pflags |= MHD_USE_POLL;
5786#else /* !HAVE_POLL && !EPOLL_SUPPORT */
5787 /* use select() - do not modify flags */
5788#endif /* !HAVE_POLL && !EPOLL_SUPPORT */
5789 }
5790 else
5791 {
5792 /* Internal threads are not used - "external" polling mode. */
5793#if defined(EPOLL_SUPPORT)
5794 *pflags |= MHD_USE_EPOLL;
5795#else /* ! EPOLL_SUPPORT */
5796 /* use select() - do not modify flags */
5797#endif /* ! EPOLL_SUPPORT */
5798 }
5799 }
5800
5801 if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
5802 return NULL;
5803#ifdef EPOLL_SUPPORT
5804 daemon->epoll_fd = -1;
5805#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5806 daemon->epoll_upgrade_fd = -1;
5807#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5808#endif
5809 /* try to open listen socket */
5810#ifdef HTTPS_SUPPORT
5811 daemon->priority_cache = NULL;
5812 if (0 != (*pflags & MHD_USE_TLS))
5813 {
5814 gnutls_priority_init (&daemon->priority_cache,
5815 "@SYSTEM",
5816 NULL);
5817 }
5818#endif /* HTTPS_SUPPORT */
5819 daemon->listen_fd = MHD_INVALID_SOCKET;
5820 daemon->listening_address_reuse = 0;
5821 daemon->options = *pflags;
5822 pflags = &daemon->options;
5823 daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 :
5824 0;
5825 daemon->port = port;
5826 daemon->apc = apc;
5827 daemon->apc_cls = apc_cls;
5828 daemon->default_handler = dh;
5829 daemon->default_handler_cls = dh_cls;
5830 daemon->connections = 0;
5835 daemon->connection_timeout = 0; /* no timeout */
5836 MHD_itc_set_invalid_ (daemon->itc);
5837#ifdef SOMAXCONN
5838 daemon->listen_backlog_size = SOMAXCONN;
5839#else /* !SOMAXCONN */
5840 daemon->listen_backlog_size = 511; /* should be safe value */
5841#endif /* !SOMAXCONN */
5842#ifdef HAVE_MESSAGES
5843 daemon->custom_error_log = &MHD_default_logger_;
5844 daemon->custom_error_log_cls = stderr;
5845#endif
5846 if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
5847 (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
5848 {
5849#ifdef HAVE_MESSAGES
5850 MHD_DLOG (daemon,
5851 _ (
5852 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5853 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5854 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5855#endif
5857 }
5858 if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5859 *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
5860 else
5861 {
5862#ifdef HAVE_LISTEN_SHUTDOWN
5863 if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
5864#endif
5865 *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
5866 }
5867#ifdef DAUTH_SUPPORT
5868 daemon->digest_auth_rand_size = 0;
5869 daemon->digest_auth_random = NULL;
5870 daemon->nonce_nc_size = 4; /* tiny */
5871#endif
5872#ifdef HTTPS_SUPPORT
5873 if (0 != (*pflags & MHD_USE_TLS))
5874 {
5875 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5876 }
5877#endif /* HTTPS_SUPPORT */
5878
5879
5880 if (MHD_YES != parse_options_va (daemon,
5881 &servaddr,
5882 ap))
5883 {
5884#ifdef HTTPS_SUPPORT
5885 if ( (0 != (*pflags & MHD_USE_TLS)) &&
5886 (NULL != daemon->priority_cache) )
5887 gnutls_priority_deinit (daemon->priority_cache);
5888#endif /* HTTPS_SUPPORT */
5889 free (daemon);
5890 return NULL;
5891 }
5892
5893 if ( (NULL != daemon->notify_completed) &&
5894 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
5895 *pflags |= MHD_USE_ITC; /* requires ITC */
5896
5897#ifndef NDEBUG
5898#ifdef HAVE_MESSAGES
5899 MHD_DLOG (daemon,
5900 _ ("Using debug build of libmicrohttpd.\n") );
5901#endif /* HAVE_MESSAGES */
5902#endif /* ! NDEBUG */
5903
5904 if ( (0 != (*pflags & MHD_USE_ITC))
5905#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5906 && (0 == daemon->worker_pool_size)
5907#endif
5908 )
5909 {
5910 if (! MHD_itc_init_ (daemon->itc))
5911 {
5912#ifdef HAVE_MESSAGES
5913 MHD_DLOG (daemon,
5914 _ ("Failed to create inter-thread communication channel: %s\n"),
5915 MHD_itc_last_strerror_ ());
5916#endif
5917#ifdef HTTPS_SUPPORT
5918 if (NULL != daemon->priority_cache)
5919 gnutls_priority_deinit (daemon->priority_cache);
5920#endif /* HTTPS_SUPPORT */
5921 free (daemon);
5922 return NULL;
5923 }
5924 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5925 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
5926 NULL)) )
5927 {
5928#ifdef HAVE_MESSAGES
5929 MHD_DLOG (daemon,
5930 _ (
5931 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
5932#endif
5933 MHD_itc_destroy_chk_ (daemon->itc);
5934#ifdef HTTPS_SUPPORT
5935 if (NULL != daemon->priority_cache)
5936 gnutls_priority_deinit (daemon->priority_cache);
5937#endif /* HTTPS_SUPPORT */
5938 free (daemon);
5939 return NULL;
5940 }
5941 }
5942
5943#ifdef DAUTH_SUPPORT
5944 if (daemon->nonce_nc_size > 0)
5945 {
5946 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
5947 / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
5948 {
5949#ifdef HAVE_MESSAGES
5950 MHD_DLOG (daemon,
5951 _ ("Specified value for NC_SIZE too large.\n"));
5952#endif
5953#ifdef HTTPS_SUPPORT
5954 if (0 != (*pflags & MHD_USE_TLS))
5955 gnutls_priority_deinit (daemon->priority_cache);
5956#endif /* HTTPS_SUPPORT */
5957 free (daemon);
5958 return NULL;
5959 }
5960 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
5961 if (NULL == daemon->nnc)
5962 {
5963#ifdef HAVE_MESSAGES
5964 MHD_DLOG (daemon,
5965 _ ("Failed to allocate memory for nonce-nc map: %s\n"),
5966 MHD_strerror_ (errno));
5967#endif
5968#ifdef HTTPS_SUPPORT
5969 if (0 != (*pflags & MHD_USE_TLS))
5970 gnutls_priority_deinit (daemon->priority_cache);
5971#endif /* HTTPS_SUPPORT */
5972 free (daemon);
5973 return NULL;
5974 }
5975 }
5976
5977#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5978 if (! MHD_mutex_init_ (&daemon->nnc_lock))
5979 {
5980#ifdef HAVE_MESSAGES
5981 MHD_DLOG (daemon,
5982 _ ("MHD failed to initialize nonce-nc mutex.\n"));
5983#endif
5984#ifdef HTTPS_SUPPORT
5985 if (0 != (*pflags & MHD_USE_TLS))
5986 gnutls_priority_deinit (daemon->priority_cache);
5987#endif /* HTTPS_SUPPORT */
5988 free (daemon->nnc);
5989 free (daemon);
5990 return NULL;
5991 }
5992#endif
5993#endif
5994
5995 /* Thread polling currently works only with internal select thread mode */
5996#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5997 if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5998 (daemon->worker_pool_size > 0) )
5999 {
6000#ifdef HAVE_MESSAGES
6001 MHD_DLOG (daemon,
6002 _ (
6003 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6004#endif
6005 goto free_and_fail;
6006 }
6007#endif
6008 if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
6009 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6010 {
6011 /* try to open listen socket */
6012 int domain;
6013
6014#ifdef HAVE_INET6
6015 domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6016#else /* ! HAVE_INET6 */
6017 if (*pflags & MHD_USE_IPv6)
6018 goto free_and_fail;
6019 domain = PF_INET;
6020#endif /* ! HAVE_INET6 */
6021
6022 listen_fd = MHD_socket_create_listen_ (domain);
6023 if (MHD_INVALID_SOCKET == listen_fd)
6024 {
6025#ifdef HAVE_MESSAGES
6026 MHD_DLOG (daemon,
6027 _ ("Failed to create socket for listening: %s\n"),
6029#endif
6030 goto free_and_fail;
6031 }
6032
6033 /* Apply the socket options according to listening_address_reuse. */
6034 if (0 == daemon->listening_address_reuse)
6035 {
6036#ifndef MHD_WINSOCK_SOCKETS
6037 /* No user requirement, use "traditional" default SO_REUSEADDR
6038 * on non-W32 platforms, and do not fail if it doesn't work.
6039 * Don't use it on W32, because on W32 it will allow multiple
6040 * bind to the same address:port, like SO_REUSEPORT on others. */
6041 if (0 > setsockopt (listen_fd,
6042 SOL_SOCKET,
6043 SO_REUSEADDR,
6044 (void*) &on, sizeof (on)))
6045 {
6046#ifdef HAVE_MESSAGES
6047 MHD_DLOG (daemon,
6048 _ ("setsockopt failed: %s\n"),
6050#endif
6051 }
6052#endif /* ! MHD_WINSOCK_SOCKETS */
6053 }
6054 else if (daemon->listening_address_reuse > 0)
6055 {
6056 /* User requested to allow reusing listening address:port. */
6057#ifndef MHD_WINSOCK_SOCKETS
6058 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
6059 * it doesn't work. */
6060 if (0 > setsockopt (listen_fd,
6061 SOL_SOCKET,
6062 SO_REUSEADDR,
6063 (void*) &on, sizeof (on)))
6064 {
6065#ifdef HAVE_MESSAGES
6066 MHD_DLOG (daemon,
6067 _ ("setsockopt failed: %s\n"),
6069#endif
6070 }
6071#endif /* ! MHD_WINSOCK_SOCKETS */
6072 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
6073 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
6074 */
6075 /* SO_REUSEADDR on W32 has the same semantics
6076 as SO_REUSEPORT on BSD/Linux */
6077#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6078 if (0 > setsockopt (listen_fd,
6079 SOL_SOCKET,
6080#ifndef MHD_WINSOCK_SOCKETS
6081 SO_REUSEPORT,
6082#else /* MHD_WINSOCK_SOCKETS */
6083 SO_REUSEADDR,
6084#endif /* MHD_WINSOCK_SOCKETS */
6085 (void *) &on,
6086 sizeof (on)))
6087 {
6088#ifdef HAVE_MESSAGES
6089 MHD_DLOG (daemon,
6090 _ ("setsockopt failed: %s\n"),
6092#endif
6093 goto free_and_fail;
6094 }
6095#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6096 /* we're supposed to allow address:port re-use, but
6097 on this platform we cannot; fail hard */
6098#ifdef HAVE_MESSAGES
6099 MHD_DLOG (daemon,
6100 _ (
6101 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6102#endif
6103 goto free_and_fail;
6104#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6105 }
6106 else /* if (daemon->listening_address_reuse < 0) */
6107 {
6108 /* User requested to disallow reusing listening address:port.
6109 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
6110 * is used and Solaris with SO_EXCLBIND.
6111 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
6112 * or setsockopt fails.
6113 */
6114#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6115 (defined(__sun) && defined(SO_EXCLBIND))
6116 if (0 > setsockopt (listen_fd,
6117 SOL_SOCKET,
6118#ifdef SO_EXCLUSIVEADDRUSE
6119 SO_EXCLUSIVEADDRUSE,
6120#else /* SO_EXCLBIND */
6121 SO_EXCLBIND,
6122#endif /* SO_EXCLBIND */
6123 (void *) &on,
6124 sizeof (on)))
6125 {
6126#ifdef HAVE_MESSAGES
6127 MHD_DLOG (daemon,
6128 _ ("setsockopt failed: %s\n"),
6130#endif
6131 goto free_and_fail;
6132 }
6133#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
6134#ifdef HAVE_MESSAGES
6135 MHD_DLOG (daemon,
6136 _ (
6137 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6138#endif
6139 goto free_and_fail;
6140#endif /* MHD_WINSOCK_SOCKETS */
6141 }
6142
6143 /* check for user supplied sockaddr */
6144#if HAVE_INET6
6145 if (0 != (*pflags & MHD_USE_IPv6))
6146 addrlen = sizeof (struct sockaddr_in6);
6147 else
6148#endif
6149 addrlen = sizeof (struct sockaddr_in);
6150 if (NULL == servaddr)
6151 {
6152#if HAVE_INET6
6153 if (0 != (*pflags & MHD_USE_IPv6))
6154 {
6155#ifdef IN6ADDR_ANY_INIT
6156 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6157#endif
6158 memset (&servaddr6,
6159 0,
6160 sizeof (struct sockaddr_in6));
6161 servaddr6.sin6_family = AF_INET6;
6162 servaddr6.sin6_port = htons (port);
6163#ifdef IN6ADDR_ANY_INIT
6164 servaddr6.sin6_addr = static_in6any;
6165#endif
6166#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6167 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
6168#endif
6169 servaddr = (struct sockaddr *) &servaddr6;
6170 }
6171 else
6172#endif
6173 {
6174 memset (&servaddr4,
6175 0,
6176 sizeof (struct sockaddr_in));
6177 servaddr4.sin_family = AF_INET;
6178 servaddr4.sin_port = htons (port);
6179 if (0 != INADDR_ANY)
6180 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6181#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6182 servaddr4.sin_len = sizeof (struct sockaddr_in);
6183#endif
6184 servaddr = (struct sockaddr *) &servaddr4;
6185 }
6186 }
6187 daemon->listen_fd = listen_fd;
6188
6189 if (0 != (*pflags & MHD_USE_IPv6))
6190 {
6191#ifdef IPPROTO_IPV6
6192#ifdef IPV6_V6ONLY
6193 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
6194 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
6195 and may also be missing on older POSIX systems; good luck if you have any of those,
6196 your IPv6 socket may then also bind against IPv4 anyway... */
6197 const MHD_SCKT_OPT_BOOL_ v6_only =
6198 (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
6199 if (0 > setsockopt (listen_fd,
6200 IPPROTO_IPV6, IPV6_V6ONLY,
6201 (const void *) &v6_only,
6202 sizeof (v6_only)))
6203 {
6204#ifdef HAVE_MESSAGES
6205 MHD_DLOG (daemon,
6206 _ ("setsockopt failed: %s\n"),
6208#endif
6209 }
6210#endif
6211#endif
6212 }
6213 if (-1 == bind (listen_fd, servaddr, addrlen))
6214 {
6215#ifdef HAVE_MESSAGES
6216 MHD_DLOG (daemon,
6217 _ ("Failed to bind to port %u: %s\n"),
6218 (unsigned int) port,
6220#endif
6221 MHD_socket_close_chk_ (listen_fd);
6222 goto free_and_fail;
6223 }
6224#ifdef TCP_FASTOPEN
6225 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6226 {
6227 if (0 == daemon->fastopen_queue_size)
6228 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6229 if (0 != setsockopt (listen_fd,
6230 IPPROTO_TCP,
6231 TCP_FASTOPEN,
6232 (const void*) &daemon->fastopen_queue_size,
6233 sizeof (daemon->fastopen_queue_size)))
6234 {
6235#ifdef HAVE_MESSAGES
6236 MHD_DLOG (daemon,
6237 _ ("setsockopt failed: %s\n"),
6239#endif
6240 }
6241 }
6242#endif
6243 if (listen (listen_fd,
6244 daemon->listen_backlog_size) < 0)
6245 {
6246#ifdef HAVE_MESSAGES
6247 MHD_DLOG (daemon,
6248 _ ("Failed to listen for connections: %s\n"),
6250#endif
6251 MHD_socket_close_chk_ (listen_fd);
6252 goto free_and_fail;
6253 }
6254 }
6255 else
6256 {
6257 listen_fd = daemon->listen_fd;
6258 }
6259
6260#ifdef HAVE_GETSOCKNAME
6261 if ( (0 == daemon->port) &&
6262 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6263 { /* Get port number. */
6264 struct sockaddr_storage bindaddr;
6265
6266 memset (&bindaddr,
6267 0,
6268 sizeof (struct sockaddr_storage));
6269 addrlen = sizeof (struct sockaddr_storage);
6270#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6271 bindaddr.ss_len = addrlen;
6272#endif
6273 if (0 != getsockname (listen_fd,
6274 (struct sockaddr *) &bindaddr,
6275 &addrlen))
6276 {
6277#ifdef HAVE_MESSAGES
6278 MHD_DLOG (daemon,
6279 _ ("Failed to get listen port number: %s\n"),
6281#endif /* HAVE_MESSAGES */
6282 }
6283#ifdef MHD_POSIX_SOCKETS
6284 else if (sizeof (bindaddr) < addrlen)
6285 {
6286 /* should be impossible with `struct sockaddr_storage` */
6287#ifdef HAVE_MESSAGES
6288 MHD_DLOG (daemon,
6289 _ (
6290 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6291#endif /* HAVE_MESSAGES */
6292 }
6293#ifndef __linux__
6294 else if (0 == addrlen)
6295 {
6296 /* Many non-Linux-based platforms return zero addrlen
6297 * for AF_UNIX sockets */
6298 daemon->port = 0; /* special value for UNIX domain sockets */
6299 }
6300#endif /* __linux__ */
6301#endif /* MHD_POSIX_SOCKETS */
6302 else
6303 {
6304 switch (bindaddr.ss_family)
6305 {
6306 case AF_INET:
6307 {
6308 struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
6309
6310 daemon->port = ntohs (s4->sin_port);
6311 break;
6312 }
6313#ifdef HAVE_INET6
6314 case AF_INET6:
6315 {
6316 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
6317
6318 daemon->port = ntohs (s6->sin6_port);
6319 mhd_assert (0 != (*pflags & MHD_USE_IPv6));
6320 break;
6321 }
6322#endif /* HAVE_INET6 */
6323#ifdef AF_UNIX
6324 case AF_UNIX:
6325 daemon->port = 0; /* special value for UNIX domain sockets */
6326 break;
6327#endif
6328 default:
6329#ifdef HAVE_MESSAGES
6330 MHD_DLOG (daemon,
6331 _ ("Unknown address family!\n"));
6332#endif
6333 daemon->port = 0; /* ugh */
6334 break;
6335 }
6336 }
6337 }
6338#endif /* HAVE_GETSOCKNAME */
6339 if ( (MHD_INVALID_SOCKET != listen_fd) &&
6340 (! MHD_socket_nonblocking_ (listen_fd)) )
6341 {
6342#ifdef HAVE_MESSAGES
6343 MHD_DLOG (daemon,
6344 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
6346#endif
6347 if (0 != (*pflags & MHD_USE_EPOLL)
6348#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6349 || (daemon->worker_pool_size > 0)
6350#endif
6351 )
6352 {
6353 /* Accept must be non-blocking. Multiple children may wake up
6354 * to handle a new connection, but only one will win the race.
6355 * The others must immediately return. */
6356 MHD_socket_close_chk_ (listen_fd);
6357 goto free_and_fail;
6358 }
6359 }
6360 if ( (MHD_INVALID_SOCKET != listen_fd) &&
6361 (! MHD_SCKT_FD_FITS_FDSET_ (listen_fd,
6362 NULL)) &&
6363 (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
6364 {
6365#ifdef HAVE_MESSAGES
6366 MHD_DLOG (daemon,
6367 _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
6368 listen_fd,
6369 FD_SETSIZE);
6370#endif
6371 MHD_socket_close_chk_ (listen_fd);
6372 goto free_and_fail;
6373 }
6374
6375#ifdef EPOLL_SUPPORT
6376 if ( (0 != (*pflags & MHD_USE_EPOLL))
6377#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6378 && (0 == daemon->worker_pool_size)
6379#endif
6380 )
6381 {
6382 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6383 {
6384#ifdef HAVE_MESSAGES
6385 MHD_DLOG (daemon,
6386 _ (
6387 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
6388#endif
6389 goto free_and_fail;
6390 }
6391 if (MHD_YES != setup_epoll_to_listen (daemon))
6392 goto free_and_fail;
6393 }
6394#endif /* EPOLL_SUPPORT */
6395
6396#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6397 if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
6398 {
6399#ifdef HAVE_MESSAGES
6400 MHD_DLOG (daemon,
6401 _ ("MHD failed to initialize IP connection limit mutex.\n"));
6402#endif
6403 if (MHD_INVALID_SOCKET != listen_fd)
6404 MHD_socket_close_chk_ (listen_fd);
6405 goto free_and_fail;
6406 }
6407 if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
6408 {
6409#ifdef HAVE_MESSAGES
6410 MHD_DLOG (daemon,
6411 _ ("MHD failed to initialize IP connection limit mutex.\n"));
6412#endif
6413#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6415#endif
6416 if (MHD_INVALID_SOCKET != listen_fd)
6417 MHD_socket_close_chk_ (listen_fd);
6418 goto free_and_fail;
6419 }
6420#endif
6421
6422#ifdef HTTPS_SUPPORT
6423 /* initialize HTTPS daemon certificate aspects & send / recv functions */
6424 if ( (0 != (*pflags & MHD_USE_TLS)) &&
6425 (0 != MHD_TLS_init (daemon)) )
6426 {
6427#ifdef HAVE_MESSAGES
6428 MHD_DLOG (daemon,
6429 _ ("Failed to initialize TLS support.\n"));
6430#endif
6431 if (MHD_INVALID_SOCKET != listen_fd)
6432 MHD_socket_close_chk_ (listen_fd);
6433#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6436#endif
6437 goto free_and_fail;
6438 }
6439#endif /* HTTPS_SUPPORT */
6440#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6441 if ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
6442 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6443 {
6444 if (0 == daemon->worker_pool_size)
6445 {
6446 if (! MHD_create_named_thread_ (&daemon->pid,
6447 (*pflags
6449 "MHD-listen" : "MHD-single",
6450 daemon->thread_stack_size,
6452 daemon) )
6453 {
6454#ifdef HAVE_MESSAGES
6455 MHD_DLOG (daemon,
6456 _ ("Failed to create listen thread: %s\n"),
6457 MHD_strerror_ (errno));
6458#endif
6461 if (MHD_INVALID_SOCKET != listen_fd)
6462 MHD_socket_close_chk_ (listen_fd);
6463 goto free_and_fail;
6464 }
6465 }
6466 else /* 0 < daemon->worker_pool_size */
6467 {
6468 /* Coarse-grained count of connections per thread (note error
6469 * due to integer division). Also keep track of how many
6470 * connections are leftover after an equal split. */
6471 unsigned int conns_per_thread = daemon->connection_limit
6472 / daemon->worker_pool_size;
6473 unsigned int leftover_conns = daemon->connection_limit
6474 % daemon->worker_pool_size;
6475
6476 i = 0; /* we need this in case fcntl or malloc fails */
6477
6478 /* Allocate memory for pooled objects */
6479 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
6480 * daemon->worker_pool_size);
6481 if (NULL == daemon->worker_pool)
6482 goto thread_failed;
6483
6484 /* Start the workers in the pool */
6485 for (i = 0; i < daemon->worker_pool_size; ++i)
6486 {
6487 /* Create copy of the Daemon object for each worker */
6488 struct MHD_Daemon *d = &daemon->worker_pool[i];
6489
6490 memcpy (d, daemon, sizeof (struct MHD_Daemon));
6491 /* Adjust polling params for worker daemons; note that memcpy()
6492 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
6493 the worker threads. */
6494 d->master = daemon;
6495 d->worker_pool_size = 0;
6496 d->worker_pool = NULL;
6497
6498 if (0 != (*pflags & MHD_USE_ITC))
6499 {
6500 if (! MHD_itc_init_ (d->itc))
6501 {
6502#ifdef HAVE_MESSAGES
6503 MHD_DLOG (daemon,
6504 _ (
6505 "Failed to create worker inter-thread communication channel: %s\n"),
6506 MHD_itc_last_strerror_ () );
6507#endif
6508 goto thread_failed;
6509 }
6510 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6511 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
6512 NULL)) )
6513 {
6514#ifdef HAVE_MESSAGES
6515 MHD_DLOG (daemon,
6516 _ (
6517 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
6518#endif
6520 goto thread_failed;
6521 }
6522 }
6523 else
6524 MHD_itc_set_invalid_ (d->itc);
6525
6526 /* Divide available connections evenly amongst the threads.
6527 * Thread indexes in [0, leftover_conns) each get one of the
6528 * leftover connections. */
6529 d->connection_limit = conns_per_thread;
6530 if (i < leftover_conns)
6531 ++d->connection_limit;
6532#ifdef EPOLL_SUPPORT
6533 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6534 (MHD_YES != setup_epoll_to_listen (d)) )
6535 goto thread_failed;
6536#endif
6537 /* Must init cleanup connection mutex for each worker */
6538 if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
6539 {
6540#ifdef HAVE_MESSAGES
6541 MHD_DLOG (daemon,
6542 _ ("MHD failed to initialize cleanup connection mutex.\n"));
6543#endif
6544 goto thread_failed;
6545 }
6546
6547 /* Spawn the worker thread */
6548 if (! MHD_create_named_thread_ (&d->pid,
6549 "MHD-worker",
6550 daemon->thread_stack_size,
6552 d))
6553 {
6554#ifdef HAVE_MESSAGES
6555 MHD_DLOG (daemon,
6556 _ ("Failed to create pool thread: %s\n"),
6557 MHD_strerror_ (errno));
6558#endif
6559 /* Free memory for this worker; cleanup below handles
6560 * all previously-created workers. */
6562 goto thread_failed;
6563 }
6564 }
6565 }
6566 }
6567#endif
6568#ifdef HTTPS_SUPPORT
6569 /* API promises to never use the password after initialization,
6570 so we additionally NULL it here to not deref a dangling pointer. */
6571 daemon->https_key_password = NULL;
6572#endif /* HTTPS_SUPPORT */
6573
6574 return daemon;
6575
6576#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6577thread_failed:
6578 /* If no worker threads created, then shut down normally. Calling
6579 MHD_stop_daemon (as we do below) doesn't work here since it
6580 assumes a 0-sized thread pool means we had been in the default
6581 MHD_USE_INTERNAL_POLLING_THREAD mode. */
6582 if (0 == i)
6583 {
6587 if (NULL != daemon->worker_pool)
6588 free (daemon->worker_pool);
6589 goto free_and_fail;
6590 }
6591
6592 /* Shutdown worker threads we've already created. Pretend
6593 as though we had fully initialized our daemon, but
6594 with a smaller number of threads than had been
6595 requested. */
6596 daemon->worker_pool_size = i;
6597 MHD_stop_daemon (daemon);
6598 return NULL;
6599#endif
6600
6601free_and_fail:
6602 /* clean up basic memory state in 'daemon' and return NULL to
6603 indicate failure */
6604#ifdef EPOLL_SUPPORT
6605#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6606 if (daemon->upgrade_fd_in_epoll)
6607 {
6608 if (0 != epoll_ctl (daemon->epoll_fd,
6609 EPOLL_CTL_DEL,
6610 daemon->epoll_upgrade_fd,
6611 NULL))
6612 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
6613 daemon->upgrade_fd_in_epoll = false;
6614 }
6615#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6616 if (-1 != daemon->epoll_fd)
6617 close (daemon->epoll_fd);
6618#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6619 if (-1 != daemon->epoll_upgrade_fd)
6620 close (daemon->epoll_upgrade_fd);
6621#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6622#endif /* EPOLL_SUPPORT */
6623#ifdef DAUTH_SUPPORT
6624 free (daemon->nnc);
6625#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6626 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6627#endif
6628#endif
6629#ifdef HTTPS_SUPPORT
6630 if (0 != (*pflags & MHD_USE_TLS))
6631 {
6632 gnutls_priority_deinit (daemon->priority_cache);
6633 if (daemon->x509_cred)
6634 gnutls_certificate_free_credentials (daemon->x509_cred);
6635 if (daemon->psk_cred)
6636 gnutls_psk_free_server_credentials (daemon->psk_cred);
6637 }
6638#endif /* HTTPS_SUPPORT */
6639 if (MHD_ITC_IS_VALID_ (daemon->itc))
6640 MHD_itc_destroy_chk_ (daemon->itc);
6641 free (daemon);
6642 return NULL;
6643}
6644
6645
6654static void
6656{
6657 struct MHD_Connection *pos;
6658 const bool used_thr_p_c = (0 != (daemon->options
6660#ifdef UPGRADE_SUPPORT
6661 const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
6662#endif /* UPGRADE_SUPPORT */
6663#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6664 struct MHD_UpgradeResponseHandle *urh;
6665 struct MHD_UpgradeResponseHandle *urhn;
6666 const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
6667
6668#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6669 mhd_assert (NULL == daemon->worker_pool);
6670#endif
6671 mhd_assert (daemon->shutdown);
6672 /* give upgraded HTTPS connections a chance to finish */
6673 /* 'daemon->urh_head' is not used in thread-per-connection mode. */
6674 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
6675 {
6676 urhn = urh->prev;
6677 /* call generic forwarding function for passing data
6678 with chance to detect that application is done. */
6679 process_urh (urh);
6680 MHD_connection_finish_forward_ (urh->connection);
6681 urh->clean_ready = true;
6682 /* Resuming will move connection to cleanup list. */
6683 MHD_resume_connection (urh->connection);
6684 }
6685#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6686
6687 /* Give suspended connections a chance to resume to avoid
6688 running into the check for there not being any suspended
6689 connections left in case of a tight race with a recently
6690 resumed connection. */
6691 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6692 {
6693 daemon->resuming = true; /* Force check for pending resume. */
6695 }
6696 /* first, make sure all threads are aware of shutdown; need to
6697 traverse DLLs in peace... */
6698#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6700#endif
6701#ifdef UPGRADE_SUPPORT
6702 if (upg_allowed)
6703 {
6704 struct MHD_Connection *susp;
6705
6707 while (NULL != susp)
6708 {
6709 if (NULL == susp->urh) /* "Upgraded" connection? */
6710 MHD_PANIC (_ (
6711 "MHD_stop_daemon() called while we have suspended connections.\n"));
6712#ifdef HTTPS_SUPPORT
6713 else if (used_tls &&
6714 used_thr_p_c &&
6715 (! susp->urh->clean_ready) )
6716 shutdown (susp->urh->app.socket,
6717 SHUT_RDWR); /* Wake thread by shutdown of app socket. */
6718#endif /* HTTPS_SUPPORT */
6719 else
6720 {
6721#ifdef HAVE_MESSAGES
6722 if (! susp->urh->was_closed)
6723 MHD_DLOG (daemon,
6724 _ (
6725 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6726#endif
6727 susp->urh->was_closed = true;
6728 /* If thread-per-connection is used, connection's thread
6729 * may still processing "upgrade" (exiting). */
6730 if (! used_thr_p_c)
6732 /* Do not use MHD_resume_connection() as mutex is
6733 * already locked. */
6734 susp->resuming = true;
6735 daemon->resuming = true;
6736 }
6737 susp = susp->prev;
6738 }
6739 }
6740 else /* This 'else' is combined with next 'if' */
6741#endif /* UPGRADE_SUPPORT */
6743 MHD_PANIC (_ (
6744 "MHD_stop_daemon() called while we have suspended connections.\n"));
6745 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
6746 {
6747 shutdown (pos->socket_fd,
6748 SHUT_RDWR);
6749#if MHD_WINSOCK_SOCKETS
6750 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6751 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
6752 (! MHD_itc_activate_ (daemon->itc, "e")) )
6753 MHD_PANIC (_ (
6754 "Failed to signal shutdown via inter-thread communication channel.\n"));
6755#endif
6756 }
6757
6758#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6759 /* now, collect per-connection threads */
6760 if (used_thr_p_c)
6761 {
6762 pos = daemon->connections_tail;
6763 while (NULL != pos)
6764 {
6765 if (! pos->thread_joined)
6766 {
6768 if (! MHD_join_thread_ (pos->pid.handle))
6769 MHD_PANIC (_ ("Failed to join a thread.\n"));
6771 pos->thread_joined = true;
6772 /* The thread may have concurrently modified the DLL,
6773 need to restart from the beginning */
6774 pos = daemon->connections_tail;
6775 continue;
6776 }
6777 pos = pos->prev;
6778 }
6779 }
6781#endif
6782
6783#ifdef UPGRADE_SUPPORT
6784 /* Finished threads with "upgraded" connections need to be moved
6785 * to cleanup list by resume_suspended_connections(). */
6786 /* "Upgraded" connections that were not closed explicitly by
6787 * application should be moved to cleanup list too. */
6788 if (upg_allowed)
6789 {
6790 daemon->resuming = true; /* Force check for pending resume. */
6792 }
6793#endif /* UPGRADE_SUPPORT */
6794
6795 /* now that we're alone, move everyone to cleanup */
6796 while (NULL != (pos = daemon->connections_tail))
6797 {
6798#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6799 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6800 (! pos->thread_joined) )
6801 MHD_PANIC (_ ("Failed to join a thread.\n"));
6802#endif
6803 close_connection (pos);
6804 }
6806}
6807
6808
6815void
6817{
6818 MHD_socket fd;
6819#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6820 unsigned int i;
6821#endif
6822
6823 if (NULL == daemon)
6824 return;
6825
6826 daemon->shutdown = true;
6827 if (daemon->was_quiesced)
6828 fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
6829 else
6830 fd = daemon->listen_fd;
6831
6832#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6833 if (NULL != daemon->worker_pool)
6834 { /* Master daemon with worker pool. */
6837
6838 /* Let workers shutdown in parallel. */
6839 for (i = 0; i < daemon->worker_pool_size; ++i)
6840 {
6841 daemon->worker_pool[i].shutdown = true;
6842 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
6843 {
6844 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
6845 "e"))
6846 MHD_PANIC (_ (
6847 "Failed to signal shutdown via inter-thread communication channel.\n"));
6848 }
6849 else
6851 }
6852#ifdef HAVE_LISTEN_SHUTDOWN
6853 if (MHD_INVALID_SOCKET != fd)
6854 {
6855 (void) shutdown (fd,
6856 SHUT_RDWR);
6857 }
6858#endif /* HAVE_LISTEN_SHUTDOWN */
6859 for (i = 0; i < daemon->worker_pool_size; ++i)
6860 {
6862 }
6863 free (daemon->worker_pool);
6865#ifdef EPOLL_SUPPORT
6866 mhd_assert (-1 == daemon->epoll_fd);
6867#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6868 mhd_assert (-1 == daemon->epoll_upgrade_fd);
6869#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6870#endif /* EPOLL_SUPPORT */
6871 }
6872 else
6873#endif
6874 { /* Worker daemon or single daemon. */
6875#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6877 { /* Worker daemon or single daemon with internal thread(s). */
6879 /* Separate thread(s) is used for polling sockets. */
6880 if (MHD_ITC_IS_VALID_ (daemon->itc))
6881 {
6882 if (! MHD_itc_activate_ (daemon->itc,
6883 "e"))
6884 MHD_PANIC (_ (
6885 "Failed to signal shutdown via inter-thread communication channel.\n"));
6886 }
6887 else
6888 {
6889#ifdef HAVE_LISTEN_SHUTDOWN
6890 if (MHD_INVALID_SOCKET != fd)
6891 {
6892 if (NULL == daemon->master)
6893 (void) shutdown (fd,
6894 SHUT_RDWR);
6895 }
6896 else
6897#endif /* HAVE_LISTEN_SHUTDOWN */
6898 mhd_assert (false); /* Should never happen */
6899 }
6900
6901 if (! MHD_join_thread_ (daemon->pid.handle))
6902 {
6903 MHD_PANIC (_ ("Failed to join a thread.\n"));
6904 }
6905 /* close_all_connections() was called in daemon thread. */
6906 }
6907 else
6908#endif
6909 {
6910 /* No internal threads are used for polling sockets. */
6912 }
6913 if (MHD_ITC_IS_VALID_ (daemon->itc))
6915
6916#ifdef EPOLL_SUPPORT
6917 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6918 (-1 != daemon->epoll_fd) )
6919 MHD_socket_close_chk_ (daemon->epoll_fd);
6920#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6921 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6922 (-1 != daemon->epoll_upgrade_fd) )
6923 MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
6924#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6925#endif /* EPOLL_SUPPORT */
6926
6927#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6929#endif
6930 }
6931
6932 if (NULL == daemon->master)
6933 { /* Cleanup that should be done only one time in master/single daemon.
6934 * Do not perform this cleanup in worker daemons. */
6935
6936 if (MHD_INVALID_SOCKET != fd)
6938
6939 /* TLS clean up */
6940#ifdef HTTPS_SUPPORT
6941 if (daemon->have_dhparams)
6942 {
6943 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6944 daemon->have_dhparams = false;
6945 }
6946 if (0 != (daemon->options & MHD_USE_TLS))
6947 {
6948 gnutls_priority_deinit (daemon->priority_cache);
6949 if (daemon->x509_cred)
6950 gnutls_certificate_free_credentials (daemon->x509_cred);
6951 if (daemon->psk_cred)
6952 gnutls_psk_free_server_credentials (daemon->psk_cred);
6953 }
6954#endif /* HTTPS_SUPPORT */
6955
6956#ifdef DAUTH_SUPPORT
6957 free (daemon->nnc);
6958#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6959 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6960#endif
6961#endif
6962#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6964#endif
6965 free (daemon);
6966 }
6967}
6968
6969
6981const union MHD_DaemonInfo *
6983 enum MHD_DaemonInfoType info_type,
6984 ...)
6985{
6986 if (NULL == daemon)
6987 return NULL;
6988 switch (info_type)
6989 {
6991 return NULL; /* no longer supported */
6993 return NULL; /* no longer supported */
6995 return (const union MHD_DaemonInfo *) &daemon->listen_fd;
6996#ifdef EPOLL_SUPPORT
6998 return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
6999#endif
7001 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
7002 {
7003 /* Assume that MHD_run() in not called in other thread
7004 * at the same time. */
7005 MHD_cleanup_connections (daemon);
7006 }
7007#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7008 else if (daemon->worker_pool)
7009 {
7010 unsigned int i;
7011 /* Collect the connection information stored in the workers. */
7012 daemon->connections = 0;
7013 for (i = 0; i < daemon->worker_pool_size; i++)
7014 {
7015 /* FIXME: next line is thread-safe only if read is atomic. */
7016 daemon->connections += daemon->worker_pool[i].connections;
7017 }
7018 }
7019#endif
7020 return (const union MHD_DaemonInfo *) &daemon->connections;
7022 return (const union MHD_DaemonInfo *) &daemon->options;
7024 return (const union MHD_DaemonInfo *) &daemon->port;
7025 default:
7026 return NULL;
7027 }
7028}
7029
7030
7047void
7049 void *cls)
7050{
7051 mhd_panic = cb;
7052 mhd_panic_cls = cls;
7053}
7054
7055
7062const char *
7063MHD_get_version (void)
7064{
7065#ifdef PACKAGE_VERSION
7066 return PACKAGE_VERSION;
7067#else /* !PACKAGE_VERSION */
7068 static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
7069 if (0 == ver[0])
7070 {
7071 int res = MHD_snprintf_ (ver,
7072 sizeof(ver),
7073 "%x.%x.%x",
7074 (((int) MHD_VERSION >> 24) & 0xFF),
7075 (((int) MHD_VERSION >> 16) & 0xFF),
7076 (((int) MHD_VERSION >> 8) & 0xFF));
7077 if ((0 >= res) || (sizeof(ver) <= res))
7078 return "0.0.0"; /* Can't return real version*/
7079 }
7080 return ver;
7081#endif /* !PACKAGE_VERSION */
7082}
7083
7084
7096enum MHD_Result
7098{
7099 switch (feature)
7100 {
7102#ifdef HAVE_MESSAGES
7103 return MHD_YES;
7104#else
7105 return MHD_NO;
7106#endif
7107 case MHD_FEATURE_TLS:
7108#ifdef HTTPS_SUPPORT
7109 return MHD_YES;
7110#else /* ! HTTPS_SUPPORT */
7111 return MHD_NO;
7112#endif /* ! HTTPS_SUPPORT */
7114#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7115 return MHD_YES;
7116#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7117 return MHD_NO;
7118#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7120#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7121 return MHD_YES;
7122#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7123 return MHD_NO;
7124#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7125 case MHD_FEATURE_IPv6:
7126#ifdef HAVE_INET6
7127 return MHD_YES;
7128#else
7129 return MHD_NO;
7130#endif
7132#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
7133 return MHD_YES;
7134#else
7135 return MHD_NO;
7136#endif
7137 case MHD_FEATURE_POLL:
7138#ifdef HAVE_POLL
7139 return MHD_YES;
7140#else
7141 return MHD_NO;
7142#endif
7143 case MHD_FEATURE_EPOLL:
7144#ifdef EPOLL_SUPPORT
7145 return MHD_YES;
7146#else
7147 return MHD_NO;
7148#endif
7150#ifdef HAVE_LISTEN_SHUTDOWN
7151 return MHD_YES;
7152#else
7153 return MHD_NO;
7154#endif
7156#ifdef _MHD_ITC_SOCKETPAIR
7157 return MHD_YES;
7158#else
7159 return MHD_NO;
7160#endif
7162#ifdef TCP_FASTOPEN
7163 return MHD_YES;
7164#else
7165 return MHD_NO;
7166#endif
7168#ifdef BAUTH_SUPPORT
7169 return MHD_YES;
7170#else
7171 return MHD_NO;
7172#endif
7174#ifdef DAUTH_SUPPORT
7175 return MHD_YES;
7176#else
7177 return MHD_NO;
7178#endif
7180#ifdef HAVE_POSTPROCESSOR
7181 return MHD_YES;
7182#else
7183 return MHD_NO;
7184#endif
7186#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
7187 return MHD_YES;
7188#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
7189 return MHD_NO;
7190#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
7192#if defined(HAVE_PREAD64) || defined(_WIN32)
7193 return MHD_YES;
7194#elif defined(HAVE_PREAD)
7195 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
7196#elif defined(HAVE_LSEEK64)
7197 return MHD_YES;
7198#else
7199 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
7200#endif
7202#if defined(MHD_USE_THREAD_NAME_)
7203 return MHD_YES;
7204#else
7205 return MHD_NO;
7206#endif
7208#if defined(UPGRADE_SUPPORT)
7209 return MHD_YES;
7210#else
7211 return MHD_NO;
7212#endif
7214#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
7215 return MHD_YES;
7216#else
7217 return MHD_NO;
7218#endif
7220#ifdef MHD_USE_GETSOCKNAME
7221 return MHD_YES;
7222#else
7223 return MHD_NO;
7224#endif
7226#if defined(MHD_WINSOCK_SOCKETS) || defined(MHD_socket_nosignal_) || \
7227 defined (MSG_NOSIGNAL)
7228 return MHD_YES;
7229#else
7230 return MHD_NO;
7231#endif
7233#ifdef _MHD_HAVE_SENDFILE
7234 return MHD_YES;
7235#else
7236 return MHD_NO;
7237#endif
7239#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7240 return MHD_YES;
7241#else
7242 return MHD_NO;
7243#endif
7244
7245 }
7246 return MHD_NO;
7247}
7248
7249
7250#ifdef MHD_HTTPS_REQUIRE_GRYPT
7251#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
7252#if defined(MHD_USE_POSIX_THREADS)
7253GCRY_THREAD_OPTION_PTHREAD_IMPL;
7254#elif defined(MHD_W32_MUTEX_)
7255
7256static int
7257gcry_w32_mutex_init (void **ppmtx)
7258{
7259 *ppmtx = malloc (sizeof (MHD_mutex_));
7260
7261 if (NULL == *ppmtx)
7262 return ENOMEM;
7263 if (! MHD_mutex_init_ ((MHD_mutex_*) *ppmtx))
7264 {
7265 free (*ppmtx);
7266 *ppmtx = NULL;
7267 return EPERM;
7268 }
7269
7270 return 0;
7271}
7272
7273
7274static int
7275gcry_w32_mutex_destroy (void **ppmtx)
7276{
7277 int res = (MHD_mutex_destroy_ ((MHD_mutex_*) *ppmtx)) ? 0 : EINVAL;
7278 free (*ppmtx);
7279 return res;
7280}
7281
7282
7283static int
7284gcry_w32_mutex_lock (void **ppmtx)
7285{
7286 return MHD_mutex_lock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7287}
7288
7289
7290static int
7291gcry_w32_mutex_unlock (void **ppmtx)
7292{
7293 return MHD_mutex_unlock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7294}
7295
7296
7297static struct gcry_thread_cbs gcry_threads_w32 = {
7298 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
7299 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
7300 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
7302};
7303
7304#endif /* defined(MHD_W32_MUTEX_) */
7305#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
7306#endif /* MHD_HTTPS_REQUIRE_GRYPT */
7307
7311void
7313{
7314#if defined(MHD_WINSOCK_SOCKETS)
7315 WSADATA wsd;
7316#endif /* MHD_WINSOCK_SOCKETS */
7317
7318 if (NULL == mhd_panic)
7320
7321#if defined(MHD_WINSOCK_SOCKETS)
7322 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
7323 MHD_PANIC (_ ("Failed to initialize winsock.\n"));
7324 mhd_winsock_inited_ = 1;
7325 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
7326 MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
7327#endif /* MHD_WINSOCK_SOCKETS */
7328#ifdef HTTPS_SUPPORT
7329#ifdef MHD_HTTPS_REQUIRE_GRYPT
7330#if GCRYPT_VERSION_NUMBER < 0x010600
7331#if defined(MHD_USE_POSIX_THREADS)
7332 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7333 &gcry_threads_pthread))
7334 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
7335#elif defined(MHD_W32_MUTEX_)
7336 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7337 &gcry_threads_w32))
7338 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
7339#endif /* defined(MHD_W32_MUTEX_) */
7340 gcry_check_version (NULL);
7341#else
7342 if (NULL == gcry_check_version ("1.6.0"))
7343 MHD_PANIC (_ (
7344 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
7345#endif
7346#endif /* MHD_HTTPS_REQUIRE_GRYPT */
7347 gnutls_global_init ();
7348#endif /* HTTPS_SUPPORT */
7350#ifdef HAVE_FREEBSD_SENDFILE
7351 MHD_conn_init_static_ ();
7352#endif /* HAVE_FREEBSD_SENDFILE */
7354}
7355
7356
7357void
7359{
7360#ifdef HTTPS_SUPPORT
7361 gnutls_global_deinit ();
7362#endif /* HTTPS_SUPPORT */
7363#if defined(MHD_WINSOCK_SOCKETS)
7364 if (mhd_winsock_inited_)
7365 WSACleanup ();
7366#endif /* MHD_WINSOCK_SOCKETS */
7368}
7369
7370
7371#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
7373#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
7374
7375/* end of daemon.c */
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2756
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2869
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3760
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3222
Methods for managing connections.
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
#define EXTRA_SLOTS
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:262
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2905
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:6655
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3695
MHD_PanicCallback mhd_panic
Definition: daemon.c:156
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)
Definition: daemon.c:2373
static void MHD_default_logger_(void *cls, const char *fm, va_list ap)
Definition: daemon.c:228
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:416
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2936
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2810
void MHD_fini(void)
Definition: daemon.c:7358
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:5010
static enum MHD_Result call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1195
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:326
volatile int global_init_count
Definition: daemon.c:187
static enum MHD_Result MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:4163
void MHD_check_global_init_(void)
Definition: daemon.c:204
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:4712
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:346
void MHD_init(void)
Definition: daemon.c:7312
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3339
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:4957
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3189
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:482
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:70
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:4801
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:310
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:365
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:4985
void * mhd_panic_cls
Definition: daemon.c:161
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2973
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:78
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:132
_MHD_EXTERN void MHD_free(void *ptr)
Definition: daemon.c:248
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:980
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:3537
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
Definition: daemon_start.c:619
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls,...)
Definition: daemon.c:4833
_MHD_EXTERN enum MHD_Result MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
Definition: daemon.c:727
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:6816
_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:3641
_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:5698
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:4677
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3447
_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:1129
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:2116
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: panic.c:56
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:2224
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Definition: microhttpd.h:2198
@ MHD_CONNECTION_NOTIFY_STARTED
Definition: microhttpd.h:1881
@ MHD_CONNECTION_NOTIFY_CLOSED
Definition: microhttpd.h:1887
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
Definition: microhttpd.h:1846
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
Definition: microhttpd.h:1823
@ MHD_REQUEST_TERMINATED_WITH_ERROR
Definition: microhttpd.h:1831
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1214
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:6982
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:4878
_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:3128
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:7097
_MHD_EXTERN const char * MHD_get_version(void)
Definition: version.c:35
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
@ 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 MHD_TYPE_IS_SIGNED_(type)
Definition: mhd_limits.h:39
#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)
time_t MHD_monotonic_sec_counter(void)
void MHD_monotonic_sec_counter_init(void)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: mhd_sockets.c:377
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:442
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:407
MHD_socket MHD_socket_create_listen_(int pf)
Definition: mhd_sockets.c:474
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:675
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:611
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:203
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:643
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:656
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:414
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:542
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:549
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:464
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:163
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:248
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:634
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:157
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:261
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:623
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:336
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:309
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:216
#define NULL
Definition: reason_phrase.c:30
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:63
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:95
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:50
internal shared structures
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:480
@ MHD_CONNECTION_INIT
Definition: internal.h:427
@ MHD_CONNECTION_CLOSED
Definition: internal.h:526
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:490
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:501
@ MHD_TLS_CONN_INIT
Definition: internal.h:545
@ MHD_EVENT_LOOP_INFO_READ
Definition: internal.h:189
@ MHD_EVENT_LOOP_INFO_WRITE
Definition: internal.h:194
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition: internal.h:204
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition: internal.h:199
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1226
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition: internal.h:212
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1240
void MHD_init_mem_pools_(void)
Definition: memorypool.c:85
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:111
internal monotonic clock functions implementations
int MHD_socket_buffering_reset_(MHD_socket sock)
Definition: mhd_sockets.c:552
int MHD_socket_set_nodelay_(MHD_socket sock, bool on)
Definition: mhd_sockets.c:471
#define MAYBE_SOCK_NOSIGPIPE
Definition: mhd_sockets.h:174
int MHD_socket
Definition: microhttpd.h:195
MHD_FEATURE
Definition: microhttpd.h:3873
@ MHD_FEATURE_POSTPROCESSOR
Definition: microhttpd.h:3964
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
Definition: microhttpd.h:3928
@ MHD_FEATURE_THREADS
Definition: microhttpd.h:4032
@ MHD_FEATURE_SENDFILE
Definition: microhttpd.h:4027
@ MHD_FEATURE_AUTODETECT_BIND_PORT
Definition: microhttpd.h:4013
@ MHD_FEATURE_LARGE_FILE
Definition: microhttpd.h:3981
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:3894
@ MHD_FEATURE_BASIC_AUTH
Definition: microhttpd.h:3948
@ MHD_FEATURE_DIGEST_AUTH
Definition: microhttpd.h:3956
@ MHD_FEATURE_IPv6
Definition: microhttpd.h:3900
@ MHD_FEATURE_POLL
Definition: microhttpd.h:3914
@ MHD_FEATURE_THREAD_NAMES
Definition: microhttpd.h:3986
@ MHD_FEATURE_EPOLL
Definition: microhttpd.h:3921
@ MHD_FEATURE_TLS
Definition: microhttpd.h:3887
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:3971
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
Definition: microhttpd.h:4020
@ MHD_FEATURE_RESPONSES_SHARED_FD
Definition: microhttpd.h:4007
@ MHD_FEATURE_MESSAGES
Definition: microhttpd.h:3878
@ MHD_FEATURE_IPv6_ONLY
Definition: microhttpd.h:3908
@ MHD_FEATURE_UPGRADE
Definition: microhttpd.h:3994
@ MHD_FEATURE_SOCKETPAIR
Definition: microhttpd.h:3934
@ MHD_FEATURE_TCP_FASTOPEN
Definition: microhttpd.h:3941
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:4038
MHD_OPTION
MHD options.
Definition: microhttpd.h:1367
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
Definition: microhttpd.h:1601
@ MHD_OPTION_HTTPS_CRED_TYPE
Definition: microhttpd.h:1484
@ MHD_OPTION_URI_LOG_CALLBACK
Definition: microhttpd.h:1461
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:1705
@ MHD_OPTION_UNESCAPE_CALLBACK
Definition: microhttpd.h:1564
@ MHD_OPTION_EXTERNAL_LOGGER
Definition: microhttpd.h:1511
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
Definition: microhttpd.h:1670
@ MHD_OPTION_HTTPS_PRIORITIES
Definition: microhttpd.h:1490
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
Definition: microhttpd.h:1633
@ MHD_OPTION_NOTIFY_CONNECTION
Definition: microhttpd.h:1662
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
Definition: microhttpd.h:1642
@ MHD_OPTION_THREAD_POOL_SIZE
Definition: microhttpd.h:1521
@ MHD_OPTION_CONNECTION_LIMIT
Definition: microhttpd.h:1388
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
Definition: microhttpd.h:1421
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
Definition: microhttpd.h:1626
@ MHD_OPTION_HTTPS_MEM_CERT
Definition: microhttpd.h:1477
@ MHD_OPTION_SERVER_INSANITY
Definition: microhttpd.h:1716
@ MHD_OPTION_LISTEN_SOCKET
Definition: microhttpd.h:1498
@ MHD_OPTION_HTTPS_MEM_KEY
Definition: microhttpd.h:1469
@ MHD_OPTION_DIGEST_AUTH_RANDOM
Definition: microhttpd.h:1575
@ MHD_OPTION_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:1651
@ MHD_OPTION_NONCE_NC_SIZE
Definition: microhttpd.h:1582
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
Definition: microhttpd.h:1382
@ MHD_OPTION_THREAD_STACK_SIZE
Definition: microhttpd.h:1588
@ MHD_OPTION_ARRAY
Definition: microhttpd.h:1542
@ MHD_OPTION_STRICT_FOR_CLIENT
Definition: microhttpd.h:1686
@ MHD_OPTION_SOCK_ADDR
Definition: microhttpd.h:1429
@ MHD_OPTION_CONNECTION_TIMEOUT
Definition: microhttpd.h:1395
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
Definition: microhttpd.h:1694
@ MHD_OPTION_END
Definition: microhttpd.h:1373
@ MHD_OPTION_HTTPS_MEM_TRUST
Definition: microhttpd.h:1595
@ MHD_OPTION_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:1617
@ MHD_OPTION_NOTIFY_COMPLETED
Definition: microhttpd.h:1409
MHD_DisableSanityCheck
Definition: microhttpd.h:1725
MHD_Result
Definition: microhttpd.h:141
@ MHD_YES
Definition: microhttpd.h:150
@ MHD_NO
Definition: microhttpd.h:145
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:2130
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:298
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:312
int fd
Definition: microhttpd.h:3166
void * data
Definition: microhttpd.h:3038
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:142
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:196
enum MHD_Result(* MHD_AccessHandlerCallback)(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
Definition: microhttpd.h:2175
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
Definition: microhttpd.h:1355
#define MHD_VERSION
Definition: microhttpd.h:135
MHD_DaemonInfoType
Definition: microhttpd.h:2052
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
Definition: microhttpd.h:2061
@ MHD_DAEMON_INFO_BIND_PORT
Definition: microhttpd.h:2101
@ MHD_DAEMON_INFO_EPOLL_FD
Definition: microhttpd.h:2076
@ MHD_DAEMON_INFO_FLAGS
Definition: microhttpd.h:2093
@ MHD_DAEMON_INFO_KEY_SIZE
Definition: microhttpd.h:2056
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
Definition: microhttpd.h:2085
@ MHD_DAEMON_INFO_LISTEN_FD
Definition: microhttpd.h:2067
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:1038
@ MHD_USE_EPOLL
Definition: microhttpd.h:1181
@ MHD_ALLOW_SUSPEND_RESUME
Definition: microhttpd.h:1267
@ MHD_USE_TCP_FASTOPEN
Definition: microhttpd.h:1283
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1075
@ MHD_USE_AUTO
Definition: microhttpd.h:1303
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
Definition: microhttpd.h:1317
@ MHD_USE_TURBO
Definition: microhttpd.h:1252
@ MHD_USE_IPv6
Definition: microhttpd.h:1104
@ MHD_USE_DUAL_STACK
Definition: microhttpd.h:1244
@ MHD_USE_POLL
Definition: microhttpd.h:1131
@ MHD_USE_TLS
Definition: microhttpd.h:1060
@ MHD_USE_INSECURE_TLS_EARLY_DATA
Definition: microhttpd.h:1323
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1290
@ MHD_USE_NO_LISTEN_SOCKET
Definition: microhttpd.h:1172
@ MHD_USE_PEDANTIC_CHECKS
Definition: microhttpd.h:1115
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1086
@ MHD_USE_ITC
Definition: microhttpd.h:1230
platform-specific includes for libmicrohttpd
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
Methods for managing response objects.
MHD_socket socket_fd
Definition: internal.h:752
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:929
bool sk_cork_on
Definition: internal.h:885
bool tls_read_ready
Definition: internal.h:769
void * socket_context
Definition: internal.h:694
bool suspended
Definition: internal.h:764
struct MHD_Response * response
Definition: internal.h:680
bool sk_nonblck
Definition: internal.h:784
struct MHD_Connection * next
Definition: internal.h:651
time_t connection_timeout
Definition: internal.h:745
struct sockaddr_storage addr
Definition: internal.h:728
struct MemoryPool * pool
Definition: internal.h:685
size_t read_buffer_offset
Definition: internal.h:789
struct MHD_Connection * prev
Definition: internal.h:656
bool client_aware
Definition: internal.h:867
MHD_thread_handle_ID_ pid
Definition: internal.h:723
time_t last_activity
Definition: internal.h:739
void * client_context
Definition: internal.h:698
enum MHD_CONNECTION_STATE state
Definition: internal.h:924
struct MHD_Daemon * daemon
Definition: internal.h:675
size_t read_buffer_size
Definition: internal.h:783
bool thread_joined
Definition: internal.h:779
size_t pool_size
Definition: internal.h:1447
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1383
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1258
LogCallback uri_log_callback
Definition: internal.h:1397
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
uint16_t port
Definition: internal.h:1605
bool was_quiesced
Definition: internal.h:1505
unsigned int connection_limit
Definition: internal.h:1583
void * unescape_callback_cls
Definition: internal.h:1412
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
enum MHD_DisableSanityCheck insanity_level
Definition: internal.h:1486
struct MHD_Connection * connections_head
Definition: internal.h:1155
unsigned int listen_backlog_size
Definition: internal.h:1754
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1372
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:1502
void * apc_cls
Definition: internal.h:1366
unsigned int per_ip_connection_limit
Definition: internal.h:1595
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1600
void * notify_connection_cls
Definition: internal.h:1388
UnescapeCallback unescape_callback
Definition: internal.h:1407
void * notify_completed_cls
Definition: internal.h:1377
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
bool resuming
Definition: internal.h:1510
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
void * default_handler_cls
Definition: internal.h:1263
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
time_t connection_timeout
Definition: internal.h:1589
MHD_AcceptPolicyCallback apc
Definition: internal.h:1361
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
size_t pool_increment
Definition: internal.h:1452
MHD_socket listen_fd
Definition: internal.h:1491
void * uri_log_callback_cls
Definition: internal.h:1402
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:1610
intptr_t value
Definition: microhttpd.h:1750
enum MHD_OPTION option
Definition: microhttpd.h:1743
void * ptr_value
Definition: microhttpd.h:1756