GNU libmicrohttpd 0.9.73
Loading...
Searching...
No Matches
daemon.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
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#include "mhd_send.h"
46
47#if HAVE_SEARCH_H
48#include <search.h>
49#else
50#include "tsearch.h"
51#endif
52
53#ifdef HTTPS_SUPPORT
54#include "connection_https.h"
55#ifdef MHD_HTTPS_REQUIRE_GRYPT
56#include <gcrypt.h>
57#endif /* MHD_HTTPS_REQUIRE_GRYPT */
58#endif /* HTTPS_SUPPORT */
59
60#if defined(_WIN32) && ! defined(__CYGWIN__)
61#ifndef WIN32_LEAN_AND_MEAN
62#define WIN32_LEAN_AND_MEAN 1
63#endif /* !WIN32_LEAN_AND_MEAN */
64#include <windows.h>
65#endif
66
67#ifdef MHD_USE_POSIX_THREADS
68#ifdef HAVE_SIGNAL_H
69#include <signal.h>
70#endif /* HAVE_SIGNAL_H */
71#endif /* MHD_USE_POSIX_THREADS */
72
76#ifdef MHD_POSIX_SOCKETS
77#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
78#else
79#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
80#endif
81
85#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
86
87
88/* Forward declarations. */
89
98static void
99close_all_connections (struct MHD_Daemon *daemon);
100
101#ifdef EPOLL_SUPPORT
102
112static enum MHD_Result
113MHD_epoll (struct MHD_Daemon *daemon,
114 int32_t millisec);
115
116#endif /* EPOLL_SUPPORT */
117
127static void
128mhd_panic_std (void *cls,
129 const char *file,
130 unsigned int line,
131 const char *reason)
132{
133 (void) cls; /* Mute compiler warning. */
134#ifdef HAVE_MESSAGES
135 fprintf (stderr,
136 _ ("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
137 file,
138 line,
139 reason);
140#else /* ! HAVE_MESSAGES */
141 (void) file; /* Mute compiler warning. */
142 (void) line; /* Mute compiler warning. */
143 (void) reason; /* Mute compiler warning. */
144#endif
145 abort ();
146}
147
148
153
158
162void
163MHD_init (void);
164
165
166#if defined(MHD_WINSOCK_SOCKETS)
170static int mhd_winsock_inited_ = 0;
171#endif /* MHD_WINSOCK_SOCKETS */
172
173#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
178#define MHD_check_global_init_() (void) 0
179#else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
183volatile int global_init_count = 0;
184
185#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
186#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
190MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
191#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
192#endif
193
194
199void
201{
202#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
203#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
204 MHD_mutex_lock_chk_ (&global_init_mutex_);
205#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
206#endif
207 if (0 == global_init_count++)
208 MHD_init ();
209#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
210#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
211 MHD_mutex_unlock_chk_ (&global_init_mutex_);
212#endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
213#endif
214}
215
216
217#endif /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
218
219#ifdef HAVE_MESSAGES
223static void
224MHD_default_logger_ (void *cls,
225 const char *fm,
226 va_list ap)
227{
228 vfprintf ((FILE*) cls, fm, ap);
229#ifdef _DEBUG
230 fflush ((FILE*) cls);
231#endif /* _DEBUG */
232}
233
234
235#endif /* HAVE_MESSAGES */
236
237
245_MHD_EXTERN void
246MHD_free (void *ptr)
247{
248 free (ptr);
249}
250
251
259static struct MHD_Daemon*
261{
262 while (NULL != daemon->master)
263 daemon = daemon->master;
264 return daemon;
265}
266
267
271struct MHD_IPCount
272{
276 int family;
277
281 union
282 {
286 struct in_addr ipv4;
287#if HAVE_INET6
291 struct in6_addr ipv6;
292#endif
293 } addr;
294
298 unsigned int count;
299};
300
301
307static void
309{
310#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
312#else
313 (void) daemon;
314#endif
315}
316
317
323static void
325{
326#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
328#else
329 (void) daemon;
330#endif
331}
332
333
343static int
344MHD_ip_addr_compare (const void *a1,
345 const void *a2)
346{
347 return memcmp (a1,
348 a2,
349 offsetof (struct MHD_IPCount,
350 count));
351}
352
353
362static enum MHD_Result
363MHD_ip_addr_to_key (const struct sockaddr *addr,
364 socklen_t addrlen,
365 struct MHD_IPCount *key)
366{
367 memset (key,
368 0,
369 sizeof(*key));
370
371 /* IPv4 addresses */
372 if (sizeof (struct sockaddr_in) == addrlen)
373 {
374 const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
375
376 key->family = AF_INET;
377 memcpy (&key->addr.ipv4,
378 &addr4->sin_addr,
379 sizeof(addr4->sin_addr));
380 return MHD_YES;
381 }
382
383#if HAVE_INET6
384 /* IPv6 addresses */
385 if (sizeof (struct sockaddr_in6) == addrlen)
386 {
387 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
388
389 key->family = AF_INET6;
390 memcpy (&key->addr.ipv6,
391 &addr6->sin6_addr,
392 sizeof(addr6->sin6_addr));
393 return MHD_YES;
394 }
395#endif
396
397 /* Some other address */
398 return MHD_NO;
399}
400
401
413static enum MHD_Result
415 const struct sockaddr *addr,
416 socklen_t addrlen)
417{
418 struct MHD_IPCount *key;
419 void **nodep;
420 void *node;
421 enum MHD_Result result;
422
423 daemon = MHD_get_master (daemon);
424 /* Ignore if no connection limit assigned */
425 if (0 == daemon->per_ip_connection_limit)
426 return MHD_YES;
427
428 if (NULL == (key = malloc (sizeof(*key))))
429 return MHD_NO;
430
431 /* Initialize key */
432 if (MHD_NO == MHD_ip_addr_to_key (addr,
433 addrlen,
434 key))
435 {
436 /* Allow unhandled address types through */
437 free (key);
438 return MHD_YES;
439 }
440 MHD_ip_count_lock (daemon);
441
442 /* Search for the IP address */
443 if (NULL == (nodep = tsearch (key,
446 {
447#ifdef HAVE_MESSAGES
448 MHD_DLOG (daemon,
449 _ ("Failed to add IP connection count node.\n"));
450#endif
451 MHD_ip_count_unlock (daemon);
452 free (key);
453 return MHD_NO;
454 }
455 node = *nodep;
456 /* If we got an existing node back, free the one we created */
457 if (node != key)
458 free (key);
459 key = (struct MHD_IPCount *) node;
460 /* Test if there is room for another connection; if so,
461 * increment count */
462 result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
463 if (MHD_NO != result)
464 ++key->count;
465
466 MHD_ip_count_unlock (daemon);
467 return result;
468}
469
470
479static void
481 const struct sockaddr *addr,
482 socklen_t addrlen)
483{
484 struct MHD_IPCount search_key;
485 struct MHD_IPCount *found_key;
486 void **nodep;
487
488 daemon = MHD_get_master (daemon);
489 /* Ignore if no connection limit assigned */
490 if (0 == daemon->per_ip_connection_limit)
491 return;
492 /* Initialize search key */
493 if (MHD_NO == MHD_ip_addr_to_key (addr,
494 addrlen,
495 &search_key))
496 return;
497
498 MHD_ip_count_lock (daemon);
499
500 /* Search for the IP address */
501 if (NULL == (nodep = tfind (&search_key,
504 {
505 /* Something's wrong if we couldn't find an IP address
506 * that was previously added */
507 MHD_PANIC (_ ("Failed to find previously-added IP address.\n"));
508 }
509 found_key = (struct MHD_IPCount *) *nodep;
510 /* Validate existing count for IP address */
511 if (0 == found_key->count)
512 {
513 MHD_PANIC (_ ("Previously-added IP address had counter of zero.\n"));
514 }
515 /* Remove the node entirely if count reduces to 0 */
516 if (0 == --found_key->count)
517 {
518 tdelete (found_key,
521 free (found_key);
522 }
523
524 MHD_ip_count_unlock (daemon);
525}
526
527
528#ifdef HTTPS_SUPPORT
535static int
536MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
537{
538 gnutls_datum_t key;
539 gnutls_datum_t cert;
540 int ret;
541
542#if GNUTLS_VERSION_MAJOR >= 3
543 if (NULL != daemon->cert_callback)
544 {
545 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
546 daemon->cert_callback);
547 }
548#endif
549#if GNUTLS_VERSION_NUMBER >= 0x030603
550 else if (NULL != daemon->cert_callback2)
551 {
552 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
553 daemon->cert_callback2);
554 }
555#endif
556
557 if (NULL != daemon->https_mem_trust)
558 {
559 size_t paramlen;
560 paramlen = strlen (daemon->https_mem_trust);
561 if (UINT_MAX < paramlen)
562 {
563#ifdef HAVE_MESSAGES
564 MHD_DLOG (daemon,
565 _ ("Too long trust certificate.\n"));
566#endif
567 return -1;
568 }
569 cert.data = (unsigned char *) daemon->https_mem_trust;
570 cert.size = (unsigned int) paramlen;
571 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
572 &cert,
573 GNUTLS_X509_FMT_PEM) < 0)
574 {
575#ifdef HAVE_MESSAGES
576 MHD_DLOG (daemon,
577 _ ("Bad trust certificate format.\n"));
578#endif
579 return -1;
580 }
581 }
582
583 if (daemon->have_dhparams)
584 {
585 gnutls_certificate_set_dh_params (daemon->x509_cred,
586 daemon->https_mem_dhparams);
587 }
588 /* certificate & key loaded from memory */
589 if ( (NULL != daemon->https_mem_cert) &&
590 (NULL != daemon->https_mem_key) )
591 {
592 size_t param1len;
593 size_t param2len;
594
595 param1len = strlen (daemon->https_mem_key);
596 param2len = strlen (daemon->https_mem_cert);
597 if ( (UINT_MAX < param1len) ||
598 (UINT_MAX < param2len) )
599 {
600#ifdef HAVE_MESSAGES
601 MHD_DLOG (daemon,
602 _ ("Too long key or certificate.\n"));
603#endif
604 return -1;
605 }
606 key.data = (unsigned char *) daemon->https_mem_key;
607 key.size = (unsigned int) param1len;
608 cert.data = (unsigned char *) daemon->https_mem_cert;
609 cert.size = (unsigned int) param2len;
610
611 if (NULL != daemon->https_key_password)
612 {
613#if GNUTLS_VERSION_NUMBER >= 0x030111
614 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
615 &cert,
616 &key,
617 GNUTLS_X509_FMT_PEM,
618 daemon->https_key_password,
619 0);
620#else
621#ifdef HAVE_MESSAGES
622 MHD_DLOG (daemon,
623 _ ("Failed to setup x509 certificate/key: pre 3.X.X version " \
624 "of GnuTLS does not support setting key password.\n"));
625#endif
626 return -1;
627#endif
628 }
629 else
630 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
631 &cert,
632 &key,
633 GNUTLS_X509_FMT_PEM);
634#ifdef HAVE_MESSAGES
635 if (0 != ret)
636 MHD_DLOG (daemon,
637 _ ("GnuTLS failed to setup x509 certificate/key: %s\n"),
638 gnutls_strerror (ret));
639#endif
640 return ret;
641 }
642#if GNUTLS_VERSION_MAJOR >= 3
643 if (NULL != daemon->cert_callback)
644 return 0;
645#endif
646#if GNUTLS_VERSION_NUMBER >= 0x030603
647 else if (NULL != daemon->cert_callback2)
648 return 0;
649#endif
650#ifdef HAVE_MESSAGES
651 MHD_DLOG (daemon,
652 _ ("You need to specify a certificate and key location.\n"));
653#endif
654 return -1;
655}
656
657
664static int
665MHD_TLS_init (struct MHD_Daemon *daemon)
666{
667 switch (daemon->cred_type)
668 {
669 case GNUTLS_CRD_CERTIFICATE:
670 if (0 !=
671 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
672 return GNUTLS_E_MEMORY_ERROR;
673 return MHD_init_daemon_certificate (daemon);
674 case GNUTLS_CRD_PSK:
675 if (0 !=
676 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
677 return GNUTLS_E_MEMORY_ERROR;
678 return 0;
679 default:
680#ifdef HAVE_MESSAGES
681 MHD_DLOG (daemon,
682 _ ("Error: invalid credentials type %d specified.\n"),
683 daemon->cred_type);
684#endif
685 return -1;
686 }
687}
688
689
690#endif /* HTTPS_SUPPORT */
691
692
693#undef MHD_get_fdset
694
724enum MHD_Result
725MHD_get_fdset (struct MHD_Daemon *daemon,
726 fd_set *read_fd_set,
727 fd_set *write_fd_set,
728 fd_set *except_fd_set,
729 MHD_socket *max_fd)
730{
731 return MHD_get_fdset2 (daemon,
732 read_fd_set,
733 write_fd_set,
734 except_fd_set,
735 max_fd,
737}
738
739
740#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
753static bool
754urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
755 fd_set *rs,
756 fd_set *ws,
757 fd_set *es,
758 MHD_socket *max_fd,
759 unsigned int fd_setsize)
760{
761 const MHD_socket conn_sckt = urh->connection->socket_fd;
762 const MHD_socket mhd_sckt = urh->mhd.socket;
763 bool res = true;
764
765 /* Do not add to 'es' only if socket is closed
766 * or not used anymore. */
767 if (MHD_INVALID_SOCKET != conn_sckt)
768 {
769 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
770 (! MHD_add_to_fd_set_ (conn_sckt,
771 rs,
772 max_fd,
773 fd_setsize)) )
774 res = false;
775 if ( (0 != urh->out_buffer_used) &&
776 (! MHD_add_to_fd_set_ (conn_sckt,
777 ws,
778 max_fd,
779 fd_setsize)) )
780 res = false;
781 /* Do not monitor again for errors if error was detected before as
782 * error state is remembered. */
783 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
784 ((0 != urh->in_buffer_size) ||
785 (0 != urh->out_buffer_size) ||
786 (0 != urh->out_buffer_used)))
787 MHD_add_to_fd_set_ (conn_sckt,
788 es,
789 max_fd,
790 fd_setsize);
791 }
792 if (MHD_INVALID_SOCKET != mhd_sckt)
793 {
794 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
795 (! MHD_add_to_fd_set_ (mhd_sckt,
796 rs,
797 max_fd,
798 fd_setsize)) )
799 res = false;
800 if ( (0 != urh->in_buffer_used) &&
801 (! MHD_add_to_fd_set_ (mhd_sckt,
802 ws,
803 max_fd,
804 fd_setsize)) )
805 res = false;
806 /* Do not monitor again for errors if error was detected before as
807 * error state is remembered. */
808 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
809 ((0 != urh->out_buffer_size) ||
810 (0 != urh->in_buffer_size) ||
811 (0 != urh->in_buffer_used)))
812 MHD_add_to_fd_set_ (mhd_sckt,
813 es,
814 max_fd,
815 fd_setsize);
816 }
817
818 return res;
819}
820
821
831static void
832urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
833 const fd_set *rs,
834 const fd_set *ws,
835 const fd_set *es)
836{
837 const MHD_socket conn_sckt = urh->connection->socket_fd;
838 const MHD_socket mhd_sckt = urh->mhd.socket;
839
840 /* Reset read/write ready, preserve error state. */
841 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
842 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
843
844 if (MHD_INVALID_SOCKET != conn_sckt)
845 {
846 if (FD_ISSET (conn_sckt, rs))
847 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
848 if (FD_ISSET (conn_sckt, ws))
849 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
850 if (FD_ISSET (conn_sckt, es))
851 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
852 }
853 if ((MHD_INVALID_SOCKET != mhd_sckt))
854 {
855 if (FD_ISSET (mhd_sckt, rs))
856 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
857 if (FD_ISSET (mhd_sckt, ws))
858 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
859 if (FD_ISSET (mhd_sckt, es))
860 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
861 }
862}
863
864
865#ifdef HAVE_POLL
866
875static void
876urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
877 struct pollfd p[2])
878{
879 p[0].events = 0;
880 p[1].events = 0;
881
882 if (urh->in_buffer_used < urh->in_buffer_size)
883 p[0].events |= POLLIN;
884 if (0 != urh->out_buffer_used)
885 p[0].events |= POLLOUT;
886
887 /* Do not monitor again for errors if error was detected before as
888 * error state is remembered. */
889 if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
890 ((0 != urh->in_buffer_size) ||
891 (0 != urh->out_buffer_size) ||
892 (0 != urh->out_buffer_used)))
893 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
894
895 if (urh->out_buffer_used < urh->out_buffer_size)
896 p[1].events |= POLLIN;
897 if (0 != urh->in_buffer_used)
898 p[1].events |= POLLOUT;
899
900 /* Do not monitor again for errors if error was detected before as
901 * error state is remembered. */
902 if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
903 ((0 != urh->out_buffer_size) ||
904 (0 != urh->in_buffer_size) ||
905 (0 != urh->in_buffer_used)))
906 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
907}
908
909
916static void
917urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
918 struct pollfd p[2])
919{
920 p[0].fd = urh->connection->socket_fd;
921 p[1].fd = urh->mhd.socket;
922 urh_update_pollfd (urh,
923 p);
924}
925
926
932static void
933urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
934 struct pollfd p[2])
935{
936 /* Reset read/write ready, preserve error state. */
937 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
938 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
939
940 if (0 != (p[0].revents & POLLIN))
941 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
942 if (0 != (p[0].revents & POLLOUT))
943 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
944 if (0 != (p[0].revents & POLLHUP))
946 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
947 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
948 if (0 != (p[1].revents & POLLIN))
949 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
950 if (0 != (p[1].revents & POLLOUT))
951 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
952 if (0 != (p[1].revents & POLLHUP))
953 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
954 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
956}
957
958
959#endif /* HAVE_POLL */
960#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
961
962
977static enum MHD_Result
979 fd_set *read_fd_set,
980 fd_set *write_fd_set,
981 fd_set *except_fd_set,
982 MHD_socket *max_fd,
983 unsigned int fd_setsize)
984
985{
986 struct MHD_Connection *pos;
987 struct MHD_Connection *posn;
988 enum MHD_Result result = MHD_YES;
989 MHD_socket ls;
990
991 if (daemon->shutdown)
992 return MHD_NO;
993
994 ls = daemon->listen_fd;
995 if ( (MHD_INVALID_SOCKET != ls) &&
996 (! daemon->was_quiesced) &&
997 (! MHD_add_to_fd_set_ (ls,
998 read_fd_set,
999 max_fd,
1000 fd_setsize)) )
1001 result = MHD_NO;
1002
1003 /* Add all sockets to 'except_fd_set' as well to watch for
1004 * out-of-band data. However, ignore errors if INFO_READ
1005 * or INFO_WRITE sockets will not fit 'except_fd_set'. */
1006 /* Start from oldest connections. Make sense for W32 FDSETs. */
1007 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1008 {
1009 posn = pos->prev;
1010
1011 switch (pos->event_loop_info)
1012 {
1014 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1015 read_fd_set,
1016 max_fd,
1017 fd_setsize))
1018 result = MHD_NO;
1019#ifdef MHD_POSIX_SOCKETS
1021 except_fd_set,
1022 max_fd,
1023 fd_setsize);
1024#endif /* MHD_POSIX_SOCKETS */
1025 break;
1027 if (! MHD_add_to_fd_set_ (pos->socket_fd,
1028 write_fd_set,
1029 max_fd,
1030 fd_setsize))
1031 result = MHD_NO;
1032#ifdef MHD_POSIX_SOCKETS
1034 except_fd_set,
1035 max_fd,
1036 fd_setsize);
1037#endif /* MHD_POSIX_SOCKETS */
1038 break;
1040 if ( (NULL == except_fd_set) ||
1042 except_fd_set,
1043 max_fd,
1044 fd_setsize))
1045 result = MHD_NO;
1046 break;
1048 /* this should never happen */
1049 break;
1050 }
1051 }
1052#ifdef MHD_WINSOCK_SOCKETS
1053 /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
1054 * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
1055 * not be pushed out. */
1056 for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1057 {
1058 posn = pos->prev;
1060 except_fd_set,
1061 max_fd,
1062 fd_setsize);
1063 }
1064#endif /* MHD_WINSOCK_SOCKETS */
1065#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1066 {
1067 struct MHD_UpgradeResponseHandle *urh;
1068
1069 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
1070 {
1071 if (MHD_NO ==
1072 urh_to_fdset (urh,
1073 read_fd_set,
1074 write_fd_set,
1075 except_fd_set,
1076 max_fd,
1077 fd_setsize))
1078 result = MHD_NO;
1079 }
1080 }
1081#endif
1082#if _MHD_DEBUG_CONNECT
1083#ifdef HAVE_MESSAGES
1084 if (NULL != max_fd)
1085 MHD_DLOG (daemon,
1086 _ ("Maximum socket in select set: %d\n"),
1087 *max_fd);
1088#endif
1089#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1090 return result;
1091}
1092
1093
1126enum MHD_Result
1128 fd_set *read_fd_set,
1129 fd_set *write_fd_set,
1130 fd_set *except_fd_set,
1131 MHD_socket *max_fd,
1132 unsigned int fd_setsize)
1133{
1134 fd_set es;
1135
1136 if ( (NULL == daemon) ||
1137 (NULL == read_fd_set) ||
1138 (NULL == write_fd_set) ||
1139 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ||
1140 (0 != (daemon->options & MHD_USE_POLL)))
1141 return MHD_NO;
1142
1143 if (NULL == except_fd_set)
1144 { /* Workaround to maintain backward compatibility. */
1145#ifdef HAVE_MESSAGES
1146 MHD_DLOG (daemon,
1147 _ ("MHD_get_fdset2() called with except_fd_set "
1148 "set to NULL. Such behavior is unsupported.\n"));
1149#endif
1150 FD_ZERO (&es);
1151 except_fd_set = &es;
1152 }
1153
1154#ifdef EPOLL_SUPPORT
1155 if (0 != (daemon->options & MHD_USE_EPOLL))
1156 {
1157 if (daemon->shutdown)
1158 return MHD_NO;
1159
1160 /* we're in epoll mode, use the epoll FD as a stand-in for
1161 the entire event set */
1162
1163 return MHD_add_to_fd_set_ (daemon->epoll_fd,
1164 read_fd_set,
1165 max_fd,
1166 fd_setsize) ? MHD_YES : MHD_NO;
1167 }
1168#endif
1169
1170 return internal_get_fdset2 (daemon,
1171 read_fd_set,
1172 write_fd_set,
1173 except_fd_set,
1174 max_fd,
1175 fd_setsize);
1176}
1177
1178
1192static enum MHD_Result
1194 bool read_ready,
1195 bool write_ready,
1196 bool force_close)
1197{
1198 enum MHD_Result ret;
1199 bool states_info_processed = false;
1200 /* Fast track flag */
1201 bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1202
1203#ifdef HTTPS_SUPPORT
1204 if (con->tls_read_ready)
1205 read_ready = true;
1206#endif /* HTTPS_SUPPORT */
1207 if (! force_close)
1208 {
1210 read_ready)
1211 {
1213 ret = MHD_connection_handle_idle (con);
1214 states_info_processed = true;
1215 }
1216 /* No need to check value of 'ret' here as closed connection
1217 * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1219 write_ready)
1220 {
1222 ret = MHD_connection_handle_idle (con);
1223 states_info_processed = true;
1224 }
1225 }
1226 else
1227 {
1230 return MHD_connection_handle_idle (con);
1231 }
1232
1233 if (! states_info_processed)
1234 { /* Connection is not read or write ready, but external conditions
1235 * may be changed and need to be processed. */
1236 ret = MHD_connection_handle_idle (con);
1237 }
1238 /* Fast track for fast connections. */
1239 /* If full request was read by single read_handler() invocation
1240 and headers were completely prepared by single MHD_connection_handle_idle()
1241 then try not to wait for next sockets polling and send response
1242 immediately.
1243 As writeability of socket was not checked and it may have
1244 some data pending in system buffers, use this optimization
1245 only for non-blocking sockets. */
1246 /* No need to check 'ret' as connection is always in
1247 * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1248 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
1349#ifdef MHD_USE_THREADS
1350 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1351 MHD_thread_ID_match_current_ (connection->pid) );
1352#endif /* MHD_USE_THREADS */
1353 if (daemon->shutdown)
1354 {
1355 /* Daemon shutting down, application will not receive any more data. */
1356#ifdef HAVE_MESSAGES
1357 if (! urh->was_closed)
1358 {
1359 MHD_DLOG (daemon,
1360 _ (
1361 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1362 }
1363#endif
1364 urh->was_closed = true;
1365 }
1366 was_closed = urh->was_closed;
1367 if (was_closed)
1368 {
1369 /* Application was closed connections: no more data
1370 * can be forwarded to application socket. */
1371 if (0 < urh->in_buffer_used)
1372 {
1373#ifdef HAVE_MESSAGES
1374 MHD_DLOG (daemon,
1375 _ ("Failed to forward to application "
1377 " bytes of data received from remote side: application shut down socket.\n"),
1378 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used);
1379#endif
1380
1381 }
1382 /* If application signaled MHD about socket closure then
1383 * check for any pending data even if socket is not marked
1384 * as 'ready' (signal may arrive after poll()/select()).
1385 * Socketpair for forwarding is always in non-blocking mode
1386 * so no risk that recv() will block the thread. */
1387 if (0 != urh->out_buffer_size)
1388 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1389 /* Discard any data received form remote. */
1390 urh->in_buffer_used = 0;
1391 /* Do not try to push data to application. */
1392 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1393 /* Reading from remote client is not required anymore. */
1394 urh->in_buffer_size = 0;
1395 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1396 connection->tls_read_ready = false;
1397 }
1398
1399 /* On some platforms (W32, possibly Darwin) failed send() (send() will
1400 * always fail after remote disconnect was detected) may discard data in
1401 * system buffers received by system but not yet read by recv(). So, before
1402 * trying send() on any socket, recv() must be performed at first otherwise
1403 * last part of incoming data may be lost. If disconnect or error was
1404 * detected - try to read from socket to dry data possibly pending is system
1405 * buffers. */
1406 if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1407 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1408 if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1409 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1410
1411 /*
1412 * handle reading from remote TLS client
1413 */
1414 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1415 (connection->tls_read_ready) ) &&
1416 (urh->in_buffer_used < urh->in_buffer_size) )
1417 {
1418 ssize_t res;
1419 size_t buf_size;
1420
1421 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1422 if (buf_size > SSIZE_MAX)
1423 buf_size = SSIZE_MAX;
1424
1425 connection->tls_read_ready = false;
1426 res = gnutls_record_recv (connection->tls_session,
1427 &urh->in_buffer[urh->in_buffer_used],
1428 buf_size);
1429 if (0 >= res)
1430 {
1431 if (GNUTLS_E_INTERRUPTED != res)
1432 {
1433 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1434 if (GNUTLS_E_AGAIN != res)
1435 {
1436 /* Unrecoverable error on socket was detected or
1437 * socket was disconnected/shut down. */
1438 /* Stop trying to read from this TLS socket. */
1439 urh->in_buffer_size = 0;
1440 }
1441 }
1442 }
1443 else /* 0 < res */
1444 {
1445 urh->in_buffer_used += res;
1446 if (0 < gnutls_record_check_pending (connection->tls_session))
1447 {
1448 connection->tls_read_ready = true;
1449 }
1450 }
1453 {
1454 /* Unrecoverable error on socket was detected and all
1455 * pending data was read from system buffers. */
1456 /* Stop trying to read from this TLS socket. */
1457 urh->in_buffer_size = 0;
1458 }
1459 }
1460
1461 /*
1462 * handle reading from application
1463 */
1464 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1465 (urh->out_buffer_used < urh->out_buffer_size) )
1466 {
1467 ssize_t res;
1468 size_t buf_size;
1469
1470 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1471 if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1472 buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1473
1474 res = MHD_recv_ (urh->mhd.socket,
1475 &urh->out_buffer[urh->out_buffer_used],
1476 buf_size);
1477 if (0 >= res)
1478 {
1479 const int err = MHD_socket_get_error_ ();
1480 if ((0 == res) ||
1481 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1483 {
1484 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1485 if ((0 == res) ||
1486 (was_closed) ||
1487 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1488 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1489 {
1490 /* Socket disconnect/shutdown was detected;
1491 * Application signaled about closure of 'upgraded' socket;
1492 * or persistent / unrecoverable error. */
1493 /* Do not try to pull more data from application. */
1494 urh->out_buffer_size = 0;
1495 }
1496 }
1497 }
1498 else /* 0 < res */
1499 {
1500 urh->out_buffer_used += res;
1501 if (buf_size > (size_t) res)
1502 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1503 }
1504 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1505 ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1506 (was_closed) ) )
1507 {
1508 /* Unrecoverable error on socket was detected and all
1509 * pending data was read from system buffers. */
1510 /* Do not try to pull more data from application. */
1511 urh->out_buffer_size = 0;
1512 }
1513 }
1514
1515 /*
1516 * handle writing to remote HTTPS client
1517 */
1518 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1519 (urh->out_buffer_used > 0) )
1520 {
1521 ssize_t res;
1522 size_t data_size;
1523
1524 data_size = urh->out_buffer_used;
1525 if (data_size > SSIZE_MAX)
1526 data_size = SSIZE_MAX;
1527
1528 res = gnutls_record_send (connection->tls_session,
1529 urh->out_buffer,
1530 data_size);
1531 if (0 >= res)
1532 {
1533 if (GNUTLS_E_INTERRUPTED != res)
1534 {
1535 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1536 if (GNUTLS_E_AGAIN != res)
1537 {
1538 /* TLS connection shut down or
1539 * persistent / unrecoverable error. */
1540#ifdef HAVE_MESSAGES
1541 MHD_DLOG (daemon,
1542 _ (
1543 "Failed to forward to remote client "
1545 " bytes of data received from application: %s\n"),
1546 (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1547 gnutls_strerror (res));
1548#endif
1549 /* Discard any data unsent to remote. */
1550 urh->out_buffer_used = 0;
1551 /* Do not try to pull more data from application. */
1552 urh->out_buffer_size = 0;
1553 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1554 }
1555 }
1556 }
1557 else /* 0 < res */
1558 {
1559 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1560 if (0 != next_out_buffer_used)
1561 {
1562 memmove (urh->out_buffer,
1563 &urh->out_buffer[res],
1564 next_out_buffer_used);
1565 if (data_size > (size_t) res)
1566 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1567 }
1568 urh->out_buffer_used = next_out_buffer_used;
1569 }
1570 if ( (0 == urh->out_buffer_used) &&
1571 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1572 {
1573 /* Unrecoverable error on socket was detected and all
1574 * pending data was sent to remote. */
1575 /* Do not try to send to remote anymore. */
1576 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1577 /* Do not try to pull more data from application. */
1578 urh->out_buffer_size = 0;
1579 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1580 }
1581 }
1582
1583 /*
1584 * handle writing to application
1585 */
1586 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1587 (urh->in_buffer_used > 0) )
1588 {
1589 ssize_t res;
1590 size_t data_size;
1591
1592 data_size = urh->in_buffer_used;
1593 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1594 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1595
1596 res = MHD_send_ (urh->mhd.socket,
1597 urh->in_buffer,
1598 data_size);
1599 if (0 >= res)
1600 {
1601 const int err = MHD_socket_get_error_ ();
1602 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1604 {
1605 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1606 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1607 {
1608 /* Socketpair connection shut down or
1609 * persistent / unrecoverable error. */
1610#ifdef HAVE_MESSAGES
1611 MHD_DLOG (daemon,
1612 _ (
1613 "Failed to forward to application "
1615 " bytes of data received from remote side: %s\n"),
1616 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1617 MHD_socket_strerr_ (err));
1618#endif
1619 /* Discard any data received form remote. */
1620 urh->in_buffer_used = 0;
1621 /* Reading from remote client is not required anymore. */
1622 urh->in_buffer_size = 0;
1623 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1624 connection->tls_read_ready = false;
1625 }
1626 }
1627 }
1628 else /* 0 < res */
1629 {
1630 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1631 if (0 != next_in_buffer_used)
1632 {
1633 memmove (urh->in_buffer,
1634 &urh->in_buffer[res],
1635 next_in_buffer_used);
1636 if (data_size > (size_t) res)
1637 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1638 }
1639 urh->in_buffer_used = next_in_buffer_used;
1640 }
1641 if ( (0 == urh->in_buffer_used) &&
1642 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1643 {
1644 /* Do not try to push data to application. */
1645 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1646 /* Reading from remote client is not required anymore. */
1647 urh->in_buffer_size = 0;
1648 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1649 connection->tls_read_ready = false;
1650 }
1651 }
1652
1653 /* Check whether data is present in TLS buffers
1654 * and incoming forward buffer have some space. */
1655 if ( (connection->tls_read_ready) &&
1656 (urh->in_buffer_used < urh->in_buffer_size) &&
1657 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1658 daemon->data_already_pending = true;
1659
1660 if ( (daemon->shutdown) &&
1661 ( (0 != urh->out_buffer_size) ||
1662 (0 != urh->out_buffer_used) ) )
1663 {
1664 /* Daemon shutting down, discard any remaining forward data. */
1665#ifdef HAVE_MESSAGES
1666 if (0 < urh->out_buffer_used)
1667 MHD_DLOG (daemon,
1668 _ (
1669 "Failed to forward to remote client "
1671 " bytes of data received from application: daemon shut down.\n"),
1672 (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
1673#endif
1674 /* Discard any data unsent to remote. */
1675 urh->out_buffer_used = 0;
1676 /* Do not try to sent to remote anymore. */
1677 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1678 /* Do not try to pull more data from application. */
1679 urh->out_buffer_size = 0;
1680 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1681 }
1682}
1683
1684
1685#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1686
1687#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1688#ifdef UPGRADE_SUPPORT
1697static void
1698thread_main_connection_upgrade (struct MHD_Connection *con)
1699{
1700#ifdef HTTPS_SUPPORT
1701 struct MHD_UpgradeResponseHandle *urh = con->urh;
1702 struct MHD_Daemon *daemon = con->daemon;
1703
1704 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1705 MHD_thread_ID_match_current_ (con->pid) );
1706 /* Here, we need to bi-directionally forward
1707 until the application tells us that it is done
1708 with the socket; */
1709 if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1710 (0 == (daemon->options & MHD_USE_POLL)))
1711 {
1712 while ( (0 != urh->in_buffer_size) ||
1713 (0 != urh->out_buffer_size) ||
1714 (0 != urh->in_buffer_used) ||
1715 (0 != urh->out_buffer_used) )
1716 {
1717 /* use select */
1718 fd_set rs;
1719 fd_set ws;
1720 fd_set es;
1721 MHD_socket max_fd;
1722 int num_ready;
1723 bool result;
1724
1725 FD_ZERO (&rs);
1726 FD_ZERO (&ws);
1727 FD_ZERO (&es);
1728 max_fd = MHD_INVALID_SOCKET;
1729 result = urh_to_fdset (urh,
1730 &rs,
1731 &ws,
1732 &es,
1733 &max_fd,
1734 FD_SETSIZE);
1735 if (! result)
1736 {
1737#ifdef HAVE_MESSAGES
1738 MHD_DLOG (con->daemon,
1739 _ ("Error preparing select.\n"));
1740#endif
1741 break;
1742 }
1743 /* FIXME: does this check really needed? */
1744 if (MHD_INVALID_SOCKET != max_fd)
1745 {
1746 struct timeval*tvp;
1747 struct timeval tv;
1748 if (((con->tls_read_ready) &&
1749 (urh->in_buffer_used < urh->in_buffer_size)) ||
1750 (daemon->shutdown))
1751 { /* No need to wait if incoming data is already pending in TLS buffers. */
1752 tv.tv_sec = 0;
1753 tv.tv_usec = 0;
1754 tvp = &tv;
1755 }
1756 else
1757 tvp = NULL;
1758 num_ready = MHD_SYS_select_ (max_fd + 1,
1759 &rs,
1760 &ws,
1761 &es,
1762 tvp);
1763 }
1764 else
1765 num_ready = 0;
1766 if (num_ready < 0)
1767 {
1768 const int err = MHD_socket_get_error_ ();
1769
1770 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1771 continue;
1772#ifdef HAVE_MESSAGES
1773 MHD_DLOG (con->daemon,
1774 _ ("Error during select (%d): `%s'\n"),
1775 err,
1776 MHD_socket_strerr_ (err));
1777#endif
1778 break;
1779 }
1780 urh_from_fdset (urh,
1781 &rs,
1782 &ws,
1783 &es);
1784 process_urh (urh);
1785 }
1786 }
1787#ifdef HAVE_POLL
1788 else if (0 != (daemon->options & MHD_USE_TLS))
1789 {
1790 /* use poll() */
1791 struct pollfd p[2];
1792 memset (p,
1793 0,
1794 sizeof (p));
1795 p[0].fd = urh->connection->socket_fd;
1796 p[1].fd = urh->mhd.socket;
1797
1798 while ( (0 != urh->in_buffer_size) ||
1799 (0 != urh->out_buffer_size) ||
1800 (0 != urh->in_buffer_used) ||
1801 (0 != urh->out_buffer_used) )
1802 {
1803 int timeout;
1804
1805 urh_update_pollfd (urh, p);
1806
1807 if (((con->tls_read_ready) &&
1808 (urh->in_buffer_used < urh->in_buffer_size)) ||
1809 (daemon->shutdown))
1810 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1811 else
1812 timeout = -1;
1813
1814 if (MHD_sys_poll_ (p,
1815 2,
1816 timeout) < 0)
1817 {
1818 const int err = MHD_socket_get_error_ ();
1819
1820 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1821 continue;
1822#ifdef HAVE_MESSAGES
1823 MHD_DLOG (con->daemon,
1824 _ ("Error during poll: `%s'\n"),
1825 MHD_socket_strerr_ (err));
1826#endif
1827 break;
1828 }
1829 urh_from_pollfd (urh,
1830 p);
1831 process_urh (urh);
1832 }
1833 }
1834 /* end POLL */
1835#endif
1836 /* end HTTPS */
1837#endif /* HTTPS_SUPPORT */
1838 /* TLS forwarding was finished. Cleanup socketpair. */
1840 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1841 * in connection thread for a little while. */
1842}
1843
1844
1845#endif /* UPGRADE_SUPPORT */
1846
1847
1855static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1857{
1858 struct MHD_Connection *con = data;
1859 struct MHD_Daemon *daemon = con->daemon;
1860 int num_ready;
1861 fd_set rs;
1862 fd_set ws;
1863 fd_set es;
1864 MHD_socket maxsock;
1865 struct timeval tv;
1866 struct timeval *tvp;
1867 time_t now;
1868#if WINDOWS
1869#ifdef HAVE_POLL
1870 int extra_slot;
1871#endif /* HAVE_POLL */
1872#define EXTRA_SLOTS 1
1873#else /* !WINDOWS */
1874#define EXTRA_SLOTS 0
1875#endif /* !WINDOWS */
1876#ifdef HAVE_POLL
1877 struct pollfd p[1 + EXTRA_SLOTS];
1878#endif
1879#undef EXTRA_SLOTS
1880#ifdef HAVE_POLL
1881 const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1882#else /* ! HAVE_POLL */
1883 const bool use_poll = 0;
1884#endif /* ! HAVE_POLL */
1885 bool was_suspended = false;
1886 MHD_thread_init_ (&(con->pid));
1887
1888 while ( (! daemon->shutdown) &&
1889 (MHD_CONNECTION_CLOSED != con->state) )
1890 {
1891 const time_t timeout = daemon->connection_timeout;
1892#ifdef UPGRADE_SUPPORT
1893 struct MHD_UpgradeResponseHandle *const urh = con->urh;
1894#else /* ! UPGRADE_SUPPORT */
1895 static const void *const urh = NULL;
1896#endif /* ! UPGRADE_SUPPORT */
1897
1898 if ( (con->suspended) &&
1899 (NULL == urh) )
1900 {
1901 /* Connection was suspended, wait for resume. */
1902 was_suspended = true;
1903 if (! use_poll)
1904 {
1905 FD_ZERO (&rs);
1906 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1907 &rs,
1908 NULL,
1909 FD_SETSIZE))
1910 {
1911 #ifdef HAVE_MESSAGES
1912 MHD_DLOG (con->daemon,
1913 _ ("Failed to add FD to fd_set.\n"));
1914 #endif
1915 goto exit;
1916 }
1917 if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
1918 &rs,
1919 NULL,
1920 NULL,
1921 NULL))
1922 {
1923 const int err = MHD_socket_get_error_ ();
1924
1925 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1926 continue;
1927#ifdef HAVE_MESSAGES
1928 MHD_DLOG (con->daemon,
1929 _ ("Error during select (%d): `%s'\n"),
1930 err,
1931 MHD_socket_strerr_ (err));
1932#endif
1933 break;
1934 }
1935 }
1936#ifdef HAVE_POLL
1937 else /* use_poll */
1938 {
1939 p[0].events = POLLIN;
1940 p[0].fd = MHD_itc_r_fd_ (daemon->itc);
1941 p[0].revents = 0;
1942 if (0 > MHD_sys_poll_ (p,
1943 1,
1944 -1))
1945 {
1947 continue;
1948#ifdef HAVE_MESSAGES
1949 MHD_DLOG (con->daemon,
1950 _ ("Error during poll: `%s'\n"),
1952#endif
1953 break;
1954 }
1955 }
1956#endif /* HAVE_POLL */
1957 MHD_itc_clear_ (daemon->itc);
1958 continue; /* Check again for resume. */
1959 } /* End of "suspended" branch. */
1960
1961 if (was_suspended)
1962 {
1963 MHD_update_last_activity_ (con); /* Reset timeout timer. */
1964 /* Process response queued during suspend and update states. */
1966 was_suspended = false;
1967 }
1968
1969 tvp = NULL;
1970
1972#ifdef HTTPS_SUPPORT
1973 || ( (con->tls_read_ready) &&
1975#endif /* HTTPS_SUPPORT */
1976 )
1977 {
1978 /* do not block: more data may be inside of TLS buffers waiting or
1979 * application must provide response data */
1980 tv.tv_sec = 0;
1981 tv.tv_usec = 0;
1982 tvp = &tv;
1983 }
1984 if ( (NULL == tvp) &&
1985 (timeout > 0) )
1986 {
1988 if (now - con->last_activity > timeout)
1989 tv.tv_sec = 0;
1990 else
1991 {
1992 const time_t seconds_left = timeout - (now - con->last_activity);
1993#if ! defined(_WIN32) || defined(__CYGWIN__)
1994 tv.tv_sec = seconds_left;
1995#else /* _WIN32 && !__CYGWIN__ */
1996 if (seconds_left > TIMEVAL_TV_SEC_MAX)
1997 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1998 else
1999 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
2000#endif /* _WIN32 && ! __CYGWIN__ */
2001 }
2002 tv.tv_usec = 0;
2003 tvp = &tv;
2004 }
2005 if (! use_poll)
2006 {
2007 /* use select */
2008 bool err_state = false;
2009
2010 FD_ZERO (&rs);
2011 FD_ZERO (&ws);
2012 FD_ZERO (&es);
2013 maxsock = MHD_INVALID_SOCKET;
2014 switch (con->event_loop_info)
2015 {
2017 if (! MHD_add_to_fd_set_ (con->socket_fd,
2018 &rs,
2019 &maxsock,
2020 FD_SETSIZE))
2021 err_state = true;
2022 break;
2024 if (! MHD_add_to_fd_set_ (con->socket_fd,
2025 &ws,
2026 &maxsock,
2027 FD_SETSIZE))
2028 err_state = true;
2029 break;
2031 if (! MHD_add_to_fd_set_ (con->socket_fd,
2032 &es,
2033 &maxsock,
2034 FD_SETSIZE))
2035 err_state = true;
2036 break;
2038 /* how did we get here!? */
2039 goto exit;
2040 }
2041#if WINDOWS
2042 if (MHD_ITC_IS_VALID_ (daemon->itc) )
2043 {
2044 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2045 &rs,
2046 &maxsock,
2047 FD_SETSIZE))
2048 err_state = 1;
2049 }
2050#endif
2051 if (err_state)
2052 {
2053#ifdef HAVE_MESSAGES
2054 MHD_DLOG (con->daemon,
2055 _ ("Failed to add FD to fd_set.\n"));
2056#endif
2057 goto exit;
2058 }
2059
2060 num_ready = MHD_SYS_select_ (maxsock + 1,
2061 &rs,
2062 &ws,
2063 &es,
2064 tvp);
2065 if (num_ready < 0)
2066 {
2067 const int err = MHD_socket_get_error_ ();
2068
2069 if (MHD_SCKT_ERR_IS_EINTR_ (err))
2070 continue;
2071#ifdef HAVE_MESSAGES
2072 MHD_DLOG (con->daemon,
2073 _ ("Error during select (%d): `%s'\n"),
2074 err,
2075 MHD_socket_strerr_ (err));
2076#endif
2077 break;
2078 }
2079#if WINDOWS
2080 /* Clear ITC before other processing so additional
2081 * signals will trigger select() again */
2082 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2083 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2084 &rs)) )
2085 MHD_itc_clear_ (daemon->itc);
2086#endif
2087 if (MHD_NO ==
2088 call_handlers (con,
2089 FD_ISSET (con->socket_fd,
2090 &rs),
2091 FD_ISSET (con->socket_fd,
2092 &ws),
2093 FD_ISSET (con->socket_fd,
2094 &es)) )
2095 goto exit;
2096 }
2097#ifdef HAVE_POLL
2098 else
2099 {
2100 /* use poll */
2101 memset (&p,
2102 0,
2103 sizeof (p));
2104 p[0].fd = con->socket_fd;
2105 switch (con->event_loop_info)
2106 {
2108 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2109 break;
2111 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2112 break;
2114 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2115 break;
2117 /* how did we get here!? */
2118 goto exit;
2119 }
2120#if WINDOWS
2121 extra_slot = 0;
2122 if (MHD_ITC_IS_VALID_ (daemon->itc))
2123 {
2124 p[1].events |= POLLIN;
2125 p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2126 p[1].revents = 0;
2127 extra_slot = 1;
2128 }
2129#endif
2130 if (MHD_sys_poll_ (p,
2131#if WINDOWS
2132 1 + extra_slot,
2133#else
2134 1,
2135#endif
2136 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2137 {
2139 continue;
2140#ifdef HAVE_MESSAGES
2141 MHD_DLOG (con->daemon,
2142 _ ("Error during poll: `%s'\n"),
2144#endif
2145 break;
2146 }
2147#if WINDOWS
2148 /* Clear ITC before other processing so additional
2149 * signals will trigger poll() again */
2150 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2151 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2152 MHD_itc_clear_ (daemon->itc);
2153#endif
2154 if (MHD_NO ==
2155 call_handlers (con,
2156 (0 != (p[0].revents & POLLIN)),
2157 (0 != (p[0].revents & POLLOUT)),
2158 (0 != (p[0].revents & (POLLERR
2159 | MHD_POLL_REVENTS_ERR_DISC))) ))
2160 goto exit;
2161 }
2162#endif
2163#ifdef UPGRADE_SUPPORT
2164 if (MHD_CONNECTION_UPGRADE == con->state)
2165 {
2166 /* Normal HTTP processing is finished,
2167 * notify application. */
2168 if ( (NULL != daemon->notify_completed) &&
2169 (con->client_aware) )
2170 daemon->notify_completed (daemon->notify_completed_cls,
2171 con,
2172 &con->client_context,
2174 con->client_aware = false;
2175
2176 thread_main_connection_upgrade (con);
2177 /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2178
2179 /* "Upgraded" data will not be used in this thread from this point. */
2180 con->urh->clean_ready = true;
2181 /* If 'urh->was_closed' set to true, connection will be
2182 * moved immediately to cleanup list. Otherwise connection
2183 * will stay in suspended list until 'urh' will be marked
2184 * with 'was_closed' by application. */
2186
2187 /* skip usual clean up */
2188 return (MHD_THRD_RTRN_TYPE_) 0;
2189 }
2190#endif /* UPGRADE_SUPPORT */
2191 }
2192#if _MHD_DEBUG_CLOSE
2193#ifdef HAVE_MESSAGES
2194 MHD_DLOG (con->daemon,
2195 _ ("Processing thread terminating. Closing connection.\n"));
2196#endif
2197#endif
2198 if (MHD_CONNECTION_CLOSED != con->state)
2200 (daemon->shutdown) ?
2204exit:
2205 if (NULL != con->response)
2206 {
2208 con->response = NULL;
2209 }
2210
2211 if (MHD_INVALID_SOCKET != con->socket_fd)
2212 {
2213 shutdown (con->socket_fd,
2214 SHUT_WR);
2215 /* 'socket_fd' can be used in other thread to signal shutdown.
2216 * To avoid data races, do not close socket here. Daemon will
2217 * use more connections only after cleanup anyway. */
2218 }
2219 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2220 (! MHD_itc_activate_ (daemon->itc, "t")) )
2221 {
2222#ifdef HAVE_MESSAGES
2223 MHD_DLOG (daemon,
2224 _ (
2225 "Failed to signal thread termination via inter-thread communication channel.\n"));
2226#endif
2227 }
2228 return (MHD_THRD_RTRN_TYPE_) 0;
2229}
2230
2231
2232#endif
2233
2234
2242static void
2243MHD_cleanup_connections (struct MHD_Daemon *daemon);
2244
2245#if defined(HTTPS_SUPPORT)
2246#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2247 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2248 ! defined(MHD_socket_nosignal_) && \
2249 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2255#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2256#endif /* MHD_SEND_SPIPE_SUPPRESS_NEEDED &&
2257 MHD_SEND_SPIPE_SUPPRESS_POSSIBLE &&
2258 ! MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) &&
2259 MSG_NOSIGNAL */
2260
2261#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2266static ssize_t
2267MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2268 const void *data,
2269 size_t data_size)
2270{
2271#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2272 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2273 data_size = MHD_SCKT_SEND_MAX_SIZE_;
2274#endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2275 return MHD_send_ ((MHD_socket) (intptr_t) (trnsp), data, data_size);
2276}
2277
2278
2279#endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2280
2281
2290static int
2291psk_gnutls_adapter (gnutls_session_t session,
2292 const char *username,
2293 gnutls_datum_t *key)
2294{
2295 struct MHD_Connection *connection;
2296 struct MHD_Daemon *daemon;
2297 void *app_psk;
2298 size_t app_psk_size;
2299
2300 connection = gnutls_session_get_ptr (session);
2301 if (NULL == connection)
2302 {
2303#ifdef HAVE_MESSAGES
2304 /* Cannot use our logger, we don't even have "daemon" */
2305 MHD_PANIC (_ ("Internal server error. This should be impossible.\n"));
2306#endif
2307 return -1;
2308 }
2309 daemon = connection->daemon;
2310#if GNUTLS_VERSION_MAJOR >= 3
2311 if (NULL == daemon->cred_callback)
2312 {
2313#ifdef HAVE_MESSAGES
2314 MHD_DLOG (daemon,
2315 _ ("PSK not supported by this server.\n"));
2316#endif
2317 return -1;
2318 }
2319 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2320 connection,
2321 username,
2322 &app_psk,
2323 &app_psk_size))
2324 return -1;
2325 if (NULL == (key->data = gnutls_malloc (app_psk_size)))
2326 {
2327#ifdef HAVE_MESSAGES
2328 MHD_DLOG (daemon,
2329 _ (
2330 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2331#endif
2332 free (app_psk);
2333 return -1;
2334 }
2335 if (UINT_MAX < app_psk_size)
2336 {
2337#ifdef HAVE_MESSAGES
2338 MHD_DLOG (daemon,
2339 _ ("PSK authentication failed: PSK too long.\n"));
2340#endif
2341 free (app_psk);
2342 return -1;
2343 }
2344 key->size = (unsigned int) app_psk_size;
2345 memcpy (key->data,
2346 app_psk,
2347 app_psk_size);
2348 free (app_psk);
2349 return 0;
2350#else
2351#ifdef HAVE_MESSAGES
2352 MHD_DLOG (daemon,
2353 _ ("PSK not supported by this server.\n"));
2354#endif
2355 return -1;
2356#endif
2357}
2358
2359
2360#endif /* HTTPS_SUPPORT */
2361
2362
2385static struct MHD_Connection *
2387 MHD_socket client_socket,
2388 const struct sockaddr *addr,
2389 socklen_t addrlen,
2390 bool external_add,
2391 bool non_blck,
2392 bool sk_spipe_supprs,
2393 enum MHD_tristate sk_is_nonip)
2394{
2395 struct MHD_Connection *connection;
2396 int eno = 0;
2397
2398#ifdef HAVE_MESSAGES
2399#if _MHD_DEBUG_CONNECT
2400 MHD_DLOG (daemon,
2401 _ ("Accepted connection on socket %d.\n"),
2402 client_socket);
2403#endif
2404#endif
2407 addr,
2408 addrlen)) )
2409 {
2410 /* above connection limit - reject */
2411#ifdef HAVE_MESSAGES
2412 MHD_DLOG (daemon,
2413 _ (
2414 "Server reached connection limit. Closing inbound connection.\n"));
2415#endif
2416 MHD_socket_close_chk_ (client_socket);
2417#if ENFILE
2418 errno = ENFILE;
2419#endif
2420 return NULL;
2421 }
2422
2423 /* apply connection acceptance policy if present */
2424 if ( (NULL != daemon->apc) &&
2426 addr,
2427 addrlen)) )
2428 {
2429#if _MHD_DEBUG_CLOSE
2430#ifdef HAVE_MESSAGES
2431 MHD_DLOG (daemon,
2432 _ ("Connection rejected by application. Closing connection.\n"));
2433#endif
2434#endif
2435 MHD_socket_close_chk_ (client_socket);
2437 addr,
2438 addrlen);
2439#if EACCESS
2440 errno = EACCESS;
2441#endif
2442 return NULL;
2443 }
2444
2445 if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2446 {
2447 eno = errno;
2448#ifdef HAVE_MESSAGES
2449 MHD_DLOG (daemon,
2450 _ ("Error allocating memory: %s\n"),
2451 MHD_strerror_ (errno));
2452#endif
2453 MHD_socket_close_chk_ (client_socket);
2455 addr,
2456 addrlen);
2457 errno = eno;
2458 return NULL;
2459 }
2460
2461 if (! external_add)
2462 {
2463 connection->sk_corked = _MHD_OFF;
2464 connection->sk_nodelay = _MHD_OFF;
2465 }
2466 else
2467 {
2468 connection->sk_corked = _MHD_UNKNOWN;
2469 connection->sk_nodelay = _MHD_UNKNOWN;
2470 }
2471
2473 if (NULL == (connection->addr = malloc (addrlen)))
2474 {
2475 eno = errno;
2476#ifdef HAVE_MESSAGES
2477 MHD_DLOG (daemon,
2478 _ ("Error allocating memory: %s\n"),
2479 MHD_strerror_ (errno));
2480#endif
2481 MHD_socket_close_chk_ (client_socket);
2483 addr,
2484 addrlen);
2485 free (connection);
2486 errno = eno;
2487 return NULL;
2488 }
2489 memcpy (connection->addr,
2490 addr,
2491 addrlen);
2492 connection->addr_len = addrlen;
2493 connection->socket_fd = client_socket;
2494 connection->sk_nonblck = non_blck;
2495 connection->is_nonip = sk_is_nonip;
2496 connection->sk_spipe_suppress = sk_spipe_supprs;
2497 connection->daemon = daemon;
2499
2500 if (0 == (daemon->options & MHD_USE_TLS))
2501 {
2502 /* set default connection handlers */
2503 MHD_set_http_callbacks_ (connection);
2504 }
2505 else
2506 {
2507#ifdef HTTPS_SUPPORT
2508#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2509 gnutls_init_flags_t
2510#else
2511 unsigned int
2512#endif
2513 flags;
2514
2515 flags = GNUTLS_SERVER;
2516#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2517 flags |= GNUTLS_NO_SIGNAL;
2518#endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2519#if GNUTLS_VERSION_MAJOR >= 3
2520 flags |= GNUTLS_NONBLOCK;
2521#endif /* GNUTLS_VERSION_MAJOR >= 3*/
2522#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2524 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2525#endif
2526#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2528 flags |= GNUTLS_ENABLE_EARLY_DATA;
2529#endif
2530 connection->tls_state = MHD_TLS_CONN_INIT;
2531 MHD_set_https_callbacks (connection);
2532 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2533 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2534 daemon->priority_cache)))
2535 {
2536 if (NULL != connection->tls_session)
2537 gnutls_deinit (connection->tls_session);
2538 MHD_socket_close_chk_ (client_socket);
2540 addr,
2541 addrlen);
2542 free (connection->addr);
2543 free (connection);
2544#ifdef HAVE_MESSAGES
2545 MHD_DLOG (daemon,
2546 _ ("Failed to initialise TLS session.\n"));
2547#endif
2548#if EPROTO
2549 errno = EPROTO;
2550#endif
2551 return NULL;
2552 }
2553#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2554 if (! daemon->disable_alpn)
2555 {
2556 gnutls_datum_t prts[2];
2557 const char prt1[] = "http/1.1"; /* Registered code for HTTP/1.1 */
2558 const char prt2[] = "http/1.0"; /* Registered code for HTTP/1.0 */
2559
2560 prts[0].data = (void*) prt1;
2561 prts[0].size = MHD_STATICSTR_LEN_ (prt1);
2562 prts[1].data = (void*) prt2;
2563 prts[1].size = MHD_STATICSTR_LEN_ (prt2);
2564 if (GNUTLS_E_SUCCESS !=
2565 gnutls_alpn_set_protocols (connection->tls_session,
2566 prts,
2567 sizeof(prts) / sizeof(prts[0]),
2568 0 /* || GNUTLS_ALPN_SERVER_PRECEDENCE */))
2569 {
2570#ifdef HAVE_MESSAGES
2571 MHD_DLOG (daemon,
2572 _ ("Failed to set ALPN protocols.\n"));
2573#else /* ! HAVE_MESSAGES */
2574 (void) 0; /* Mute compiler warning */
2575#endif /* ! HAVE_MESSAGES */
2576 }
2577 }
2578#endif /* GNUTLS_VERSION_NUMBER >= 0x030200 */
2579 gnutls_session_set_ptr (connection->tls_session,
2580 connection);
2581 switch (daemon->cred_type)
2582 {
2583 /* set needed credentials for certificate authentication. */
2584 case GNUTLS_CRD_CERTIFICATE:
2585 gnutls_credentials_set (connection->tls_session,
2586 GNUTLS_CRD_CERTIFICATE,
2587 daemon->x509_cred);
2588 break;
2589 case GNUTLS_CRD_PSK:
2590 gnutls_credentials_set (connection->tls_session,
2591 GNUTLS_CRD_PSK,
2592 daemon->psk_cred);
2593 gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2594 &psk_gnutls_adapter);
2595 break;
2596 default:
2597#ifdef HAVE_MESSAGES
2598 MHD_DLOG (daemon,
2599 _ (
2600 "Failed to setup TLS credentials: unknown credential type %d.\n"),
2601 daemon->cred_type);
2602#endif
2603 gnutls_deinit (connection->tls_session);
2604 MHD_socket_close_chk_ (client_socket);
2606 addr,
2607 addrlen);
2608 free (connection->addr);
2609 free (connection);
2610 MHD_PANIC (_ ("Unknown credential type.\n"));
2611#if EINVAL
2612 errno = EINVAL;
2613#endif
2614 return NULL;
2615 }
2616#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2617 gnutls_transport_set_int (connection->tls_session,
2618 (int) (client_socket));
2619#else /* GnuTLS before 3.1.9 or Win x64 */
2620 gnutls_transport_set_ptr (connection->tls_session,
2621 (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2622#endif /* GnuTLS before 3.1.9 */
2623#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2624 gnutls_transport_set_push_function (connection->tls_session,
2625 MHD_tls_push_func_);
2626#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2627 if (daemon->https_mem_trust)
2628 gnutls_certificate_server_set_request (connection->tls_session,
2629 GNUTLS_CERT_REQUEST);
2630#else /* ! HTTPS_SUPPORT */
2631 MHD_socket_close_chk_ (client_socket);
2633 addr,
2634 addrlen);
2635 free (connection->addr);
2636 free (connection);
2637 MHD_PANIC (_ ("TLS connection on non-TLS daemon.\n"));
2638 eno = EINVAL;
2639 return NULL;
2640#endif /* ! HTTPS_SUPPORT */
2641 }
2642
2643 return connection;
2644}
2645
2646
2647#ifdef MHD_USE_THREADS
2653static void
2654new_connection_close_ (struct MHD_Daemon *daemon,
2655 struct MHD_Connection *connection)
2656{
2657 mhd_assert (connection->daemon == daemon);
2658 mhd_assert (! connection->in_cleanup);
2659 mhd_assert (NULL == connection->next);
2660 mhd_assert (NULL == connection->nextX);
2661#ifdef EPOLL_SUPPORT
2662 mhd_assert (NULL == connection->nextE);
2663#endif /* EPOLL_SUPPORT */
2664
2665#ifdef HTTPS_SUPPORT
2666 if (NULL != connection->tls_session)
2667 {
2669 gnutls_deinit (connection->tls_session);
2670 }
2671#endif /* HTTPS_SUPPORT */
2672 MHD_socket_close_chk_ (connection->socket_fd);
2674 connection->addr,
2675 connection->addr_len);
2676 free (connection->addr);
2677 free (connection);
2678}
2679
2680
2681#endif /* MHD_USE_THREADS */
2682
2683
2694static enum MHD_Result
2696 struct MHD_Connection *connection)
2697{
2698 int eno = 0;
2699
2700 mhd_assert (connection->daemon == daemon);
2701
2702#ifdef MHD_USE_THREADS
2703 /* Function manipulate connection and timeout DL-lists,
2704 * must be called only within daemon thread. */
2706 MHD_thread_ID_match_current_ (daemon->pid) );
2707#endif /* MHD_USE_THREADS */
2708
2709 /* Allocate memory pool in the processing thread so
2710 * intensively used memory area is allocated in "good"
2711 * (for the thread) memory region. It is important with
2712 * NUMA and/or complex cache hierarchy. */
2713 connection->pool = MHD_pool_create (daemon->pool_size);
2714 if (NULL == connection->pool)
2715 {
2716#ifdef HAVE_MESSAGES
2717 MHD_DLOG (daemon,
2718 _ ("Error allocating memory: %s\n"),
2719 MHD_strerror_ (errno));
2720#endif
2721 MHD_socket_close_chk_ (connection->socket_fd);
2723 connection->addr,
2724 connection->addr_len);
2725 free (connection);
2726#if ENOMEM
2727 errno = ENOMEM;
2728#endif
2729 return MHD_NO;
2730 }
2731
2732#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2734#endif
2735 /* Firm check under lock. */
2737 {
2738#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2740#endif
2741 /* above connection limit - reject */
2742#ifdef HAVE_MESSAGES
2743 MHD_DLOG (daemon,
2744 _ (
2745 "Server reached connection limit. Closing inbound connection.\n"));
2746#endif
2747#if ENFILE
2748 eno = ENFILE;
2749#endif
2750 goto cleanup;
2751 }
2754 {
2757 connection);
2758 }
2761 connection);
2762#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2764#endif
2767 connection,
2768 &connection->socket_context,
2770#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2771 /* attempt to create handler thread */
2773 {
2774 if (! MHD_create_named_thread_ (&connection->pid,
2775 "MHD-connection",
2776 daemon->thread_stack_size,
2778 connection))
2779 {
2780 eno = errno;
2781#ifdef HAVE_MESSAGES
2782 MHD_DLOG (daemon,
2783 _ ("Failed to create a thread: %s\n"),
2784 MHD_strerror_ (eno));
2785#endif
2786 goto cleanup;
2787 }
2788 }
2789 else
2790 connection->pid = daemon->pid;
2791#endif
2792#ifdef EPOLL_SUPPORT
2793 if (0 != (daemon->options & MHD_USE_EPOLL))
2794 {
2795 if (0 == (daemon->options & MHD_USE_TURBO))
2796 {
2797 struct epoll_event event;
2798
2799 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2800 event.data.ptr = connection;
2801 if (0 != epoll_ctl (daemon->epoll_fd,
2802 EPOLL_CTL_ADD,
2803 connection->socket_fd,
2804 &event))
2805 {
2806 eno = errno;
2807#ifdef HAVE_MESSAGES
2808 MHD_DLOG (daemon,
2809 _ ("Call to epoll_ctl failed: %s\n"),
2811#endif
2812 goto cleanup;
2813 }
2814 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2815 }
2816 else
2817 {
2818 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
2821 EDLL_insert (daemon->eready_head,
2822 daemon->eready_tail,
2823 connection);
2824 }
2825 }
2826#endif
2827
2828 return MHD_YES;
2829
2830cleanup:
2831 if (NULL != daemon->notify_connection)
2833 connection,
2834 &connection->socket_context,
2836#ifdef HTTPS_SUPPORT
2837 if (NULL != connection->tls_session)
2838 gnutls_deinit (connection->tls_session);
2839#endif /* HTTPS_SUPPORT */
2840 MHD_socket_close_chk_ (connection->socket_fd);
2841 MHD_ip_limit_del (daemon,
2842 connection->addr,
2843 connection->addr_len);
2844#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2846#endif
2847 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2848 {
2850 daemon->normal_timeout_tail,
2851 connection);
2852 }
2854 daemon->connections_tail,
2855 connection);
2856#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2858#endif
2859 MHD_pool_destroy (connection->pool);
2860 free (connection->addr);
2861 free (connection);
2862 if (0 != eno)
2863 errno = eno;
2864 else
2865 errno = EINVAL;
2866 return MHD_NO;
2867}
2868
2869
2898static enum MHD_Result
2900 MHD_socket client_socket,
2901 const struct sockaddr *addr,
2902 socklen_t addrlen,
2903 bool external_add,
2904 bool non_blck,
2905 bool sk_spipe_supprs,
2906 enum MHD_tristate sk_is_nonip)
2907{
2908 struct MHD_Connection *connection;
2909
2910#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2911 /* Direct add to master daemon could never happen. */
2913#endif
2914
2915 if ( (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
2916 (! MHD_SCKT_FD_FITS_FDSET_ (client_socket, NULL)) )
2917 {
2918#ifdef HAVE_MESSAGES
2919 MHD_DLOG (daemon,
2920 _ ("New connection socket descriptor (%d) is not less " \
2921 "than FD_SETSIZE (%d).\n"),
2922 (int) client_socket,
2923 (int) FD_SETSIZE);
2924#endif
2925 MHD_socket_close_chk_ (client_socket);
2926#if ENFILE
2927 errno = ENFILE;
2928#endif
2929 return MHD_NO;
2930 }
2931
2932 if ( (0 == (daemon->options & MHD_USE_EPOLL)) &&
2933 (! non_blck) )
2934 {
2935#ifdef HAVE_MESSAGES
2936 MHD_DLOG (daemon,
2937 _ ("Epoll mode supports only non-blocking sockets\n"));
2938#endif
2939 MHD_socket_close_chk_ (client_socket);
2940#if EINVAL
2941 errno = EINVAL;
2942#endif
2943 return MHD_NO;
2944 }
2945
2946 connection = new_connection_prepare_ (daemon,
2947 client_socket,
2948 addr, addrlen,
2949 external_add,
2950 non_blck,
2951 sk_spipe_supprs,
2952 sk_is_nonip);
2953 if (NULL == connection)
2954 return MHD_NO;
2955
2956 if ((external_add) &&
2958 {
2959 /* Connection is added externally and MHD is handling its own threads. */
2960 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
2963 connection);
2964 daemon->have_new = true;
2965 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
2966
2967 /* The rest of connection processing must be handled in
2968 * the daemon thread. */
2969 if ((MHD_ITC_IS_VALID_ (daemon->itc)) &&
2970 (! MHD_itc_activate_ (daemon->itc, "n")))
2971 {
2972 #ifdef HAVE_MESSAGES
2973 MHD_DLOG (daemon,
2974 _ ("Failed to signal new connection via inter-thread " \
2975 "communication channel.\n"));
2976 #endif
2977 }
2978 return MHD_YES;
2979 }
2980
2981 return new_connection_process_ (daemon, connection);
2982}
2983
2984
2985static void
2987{
2988 struct MHD_Connection *local_head;
2989 struct MHD_Connection *local_tail;
2992
2993 /* Detach DL-list of new connections from the daemon for
2994 * following local processing. */
2995 MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
2997 local_head = daemon->new_connections_head;
2998 local_tail = daemon->new_connections_tail;
3001 daemon->have_new = false;
3002 MHD_mutex_unlock_chk_ (&daemon->new_connections_mutex);
3003 (void) local_head; /* Mute compiler warning */
3004
3005 /* Process new connections in FIFO order. */
3006 do
3007 {
3008 struct MHD_Connection *c;
3010 c = local_tail;
3011 DLL_remove (local_head,
3012 local_tail,
3013 c);
3014 mhd_assert (daemon == c->daemon);
3016 {
3017#ifdef HAVE_MESSAGES
3018 MHD_DLOG (daemon,
3019 _ ("Failed to start serving new connection.\n"));
3020#endif
3021 (void) 0;
3022 }
3023 } while (NULL != local_tail);
3024
3025}
3026
3027
3037void
3039{
3040 struct MHD_Daemon *daemon = connection->daemon;
3041
3042#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3043 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3044 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3045 MHD_thread_ID_match_current_ (daemon->pid) );
3047#endif
3048 if (connection->resuming)
3049 {
3050 /* suspending again while we didn't even complete resuming yet */
3051 connection->resuming = false;
3052#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3054#endif
3055 return;
3056 }
3057 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3058 {
3059 if (connection->connection_timeout == daemon->connection_timeout)
3061 daemon->normal_timeout_tail,
3062 connection);
3063 else
3065 daemon->manual_timeout_tail,
3066 connection);
3067 }
3069 daemon->connections_tail,
3070 connection);
3071 mhd_assert (! connection->suspended);
3074 connection);
3075 connection->suspended = true;
3076#ifdef EPOLL_SUPPORT
3077 if (0 != (daemon->options & MHD_USE_EPOLL))
3078 {
3079 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3080 {
3081 EDLL_remove (daemon->eready_head,
3082 daemon->eready_tail,
3083 connection);
3084 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3085 }
3086 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
3087 {
3088 if (0 != epoll_ctl (daemon->epoll_fd,
3089 EPOLL_CTL_DEL,
3090 connection->socket_fd,
3091 NULL))
3092 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3093 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3094 }
3095 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
3096 }
3097#endif
3098#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3100#endif
3101}
3102
3103
3135void
3137{
3138 struct MHD_Daemon *const daemon = connection->daemon;
3139
3140#ifdef MHD_USE_THREADS
3141 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3142 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
3143 MHD_thread_ID_match_current_ (daemon->pid) );
3144#endif /* MHD_USE_THREADS */
3145
3146 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3147 MHD_PANIC (_ (
3148 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3149#ifdef UPGRADE_SUPPORT
3150 if (NULL != connection->urh)
3151 {
3152#ifdef HAVE_MESSAGES
3153 MHD_DLOG (daemon,
3154 _ (
3155 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
3156#endif /* HAVE_MESSAGES */
3157 return;
3158 }
3159#endif /* UPGRADE_SUPPORT */
3160 internal_suspend_connection_ (connection);
3161}
3162
3163
3172void
3174{
3175 struct MHD_Daemon *daemon = connection->daemon;
3176
3177 if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3178 MHD_PANIC (_ (
3179 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3180#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3182#endif
3183 connection->resuming = true;
3184 daemon->resuming = true;
3185#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3187#endif
3188 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3189 (! MHD_itc_activate_ (daemon->itc, "r")) )
3190 {
3191#ifdef HAVE_MESSAGES
3192 MHD_DLOG (daemon,
3193 _ (
3194 "Failed to signal resume via inter-thread communication channel.\n"));
3195#endif
3196 }
3197}
3198
3199
3209static enum MHD_Result
3211{
3212 struct MHD_Connection *pos;
3213 struct MHD_Connection *prev = NULL;
3214 enum MHD_Result ret;
3215 const bool used_thr_p_c = (0 != (daemon->options
3217#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3220 MHD_thread_ID_match_current_ (daemon->pid) );
3221#endif
3222
3223 ret = MHD_NO;
3224#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3226#endif
3227
3228 if (daemon->resuming)
3229 {
3231 /* During shutdown check for resuming is forced. */
3232 mhd_assert ((NULL != prev) || (daemon->shutdown) || \
3233 (0 != (daemon->options & MHD_ALLOW_UPGRADE)));
3234 }
3235
3236 daemon->resuming = false;
3237
3238 while (NULL != (pos = prev))
3239 {
3240#ifdef UPGRADE_SUPPORT
3241 struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3242#else /* ! UPGRADE_SUPPORT */
3243 static const void *const urh = NULL;
3244#endif /* ! UPGRADE_SUPPORT */
3245 prev = pos->prev;
3246 if ( (! pos->resuming)
3247#ifdef UPGRADE_SUPPORT
3248 || ( (NULL != urh) &&
3249 ( (! urh->was_closed) ||
3250 (! urh->clean_ready) ) )
3251#endif /* UPGRADE_SUPPORT */
3252 )
3253 continue;
3254 ret = MHD_YES;
3255 mhd_assert (pos->suspended);
3258 pos);
3259 pos->suspended = false;
3260 if (NULL == urh)
3261 {
3263 daemon->connections_tail,
3264 pos);
3265 if (! used_thr_p_c)
3266 {
3267 /* Reset timeout timer on resume. */
3268 if (0 != pos->connection_timeout)
3270
3271 if (pos->connection_timeout == daemon->connection_timeout)
3273 daemon->normal_timeout_tail,
3274 pos);
3275 else
3277 daemon->manual_timeout_tail,
3278 pos);
3279 }
3280#ifdef EPOLL_SUPPORT
3281 if (0 != (daemon->options & MHD_USE_EPOLL))
3282 {
3283 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3284 MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3285 /* we always mark resumed connections as ready, as we
3286 might have missed the edge poll event during suspension */
3287 EDLL_insert (daemon->eready_head,
3288 daemon->eready_tail,
3289 pos);
3290 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3293 pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
3294 }
3295#endif
3296 }
3297#ifdef UPGRADE_SUPPORT
3298 else
3299 {
3300 /* Data forwarding was finished (for TLS connections) AND
3301 * application was closed upgraded connection.
3302 * Insert connection into cleanup list. */
3303
3304 if ( (NULL != daemon->notify_completed) &&
3305 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3306 (pos->client_aware) )
3307 {
3308 daemon->notify_completed (daemon->notify_completed_cls,
3309 pos,
3310 &pos->client_context,
3312 pos->client_aware = false;
3313 }
3314 DLL_insert (daemon->cleanup_head,
3315 daemon->cleanup_tail,
3316 pos);
3317 daemon->data_already_pending = true;
3318 }
3319#endif /* UPGRADE_SUPPORT */
3320 pos->resuming = false;
3321 }
3322#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3324#endif
3325 if ( (used_thr_p_c) &&
3326 (MHD_NO != ret) )
3327 { /* Wake up suspended connections. */
3328 if (! MHD_itc_activate_ (daemon->itc,
3329 "w"))
3330 {
3331#ifdef HAVE_MESSAGES
3332 MHD_DLOG (daemon,
3333 _ (
3334 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3335#endif
3336 }
3337 }
3338 return ret;
3339}
3340
3341
3369enum MHD_Result
3371 MHD_socket client_socket,
3372 const struct sockaddr *addr,
3373 socklen_t addrlen)
3374{
3375 bool sk_nonbl;
3376 bool sk_spipe_supprs;
3377
3378 /* NOT thread safe with internal thread. TODO: fix thread safety. */
3379 if ((0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3380 (daemon->connection_limit <= daemon->connections))
3381 MHD_cleanup_connections (daemon);
3382
3383#ifdef HAVE_MESSAGES
3384 if ((0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3385 (0 == (daemon->options & MHD_USE_ITC)))
3386 {
3387 MHD_DLOG (daemon,
3388 _ ("MHD_add_connection() has been called for daemon started"
3389 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3390 " added connection until any activity occurs in already"
3391 " added sockets.\n"));
3392 }
3393#endif /* HAVE_MESSAGES */
3394
3395 if (! MHD_socket_nonblocking_ (client_socket))
3396 {
3397#ifdef HAVE_MESSAGES
3398 MHD_DLOG (daemon,
3399 _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3401#endif
3402 sk_nonbl = false;
3403 }
3404 else
3405 sk_nonbl = true;
3406
3407#ifndef MHD_WINSOCK_SOCKETS
3408 sk_spipe_supprs = false;
3409#else /* MHD_WINSOCK_SOCKETS */
3410 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3411#endif /* MHD_WINSOCK_SOCKETS */
3412#if defined(MHD_socket_nosignal_)
3413 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (client_socket))
3414 {
3415#ifdef HAVE_MESSAGES
3416 MHD_DLOG (daemon,
3417 _ (
3418 "Failed to suppress SIGPIPE on new client socket: %s\n"),
3420#else /* ! HAVE_MESSAGES */
3421 (void) 0; /* Mute compiler warning */
3422#endif /* ! HAVE_MESSAGES */
3423#ifndef MSG_NOSIGNAL
3424 /* Application expects that SIGPIPE will be suppressed,
3425 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3426 if (! daemon->sigpipe_blocked)
3427 {
3428 int err = MHD_socket_get_error_ ();
3429 MHD_socket_close_ (client_socket);
3431 return MHD_NO;
3432 }
3433#endif /* MSG_NOSIGNAL */
3434 }
3435 else
3436 sk_spipe_supprs = true;
3437#endif /* MHD_socket_nosignal_ */
3438
3439 if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3440 (! MHD_socket_noninheritable_ (client_socket)) )
3441 {
3442#ifdef HAVE_MESSAGES
3443 MHD_DLOG (daemon,
3444 _ ("Failed to set noninheritable mode on new client socket.\n"));
3445#endif
3446 }
3447
3448#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3449 if (NULL != daemon->worker_pool)
3450 {
3451 unsigned int i;
3452 /* have a pool, try to find a pool with capacity; we use the
3453 socket as the initial offset into the pool for load
3454 balancing */
3455 for (i = 0; i < daemon->worker_pool_size; ++i)
3456 {
3457 struct MHD_Daemon *const worker =
3458 &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
3459 if (worker->connections < worker->connection_limit)
3460 return internal_add_connection (worker,
3461 client_socket,
3462 addr,
3463 addrlen,
3464 true,
3465 sk_nonbl,
3466 sk_spipe_supprs,
3467 _MHD_UNKNOWN);
3468 }
3469 /* all pools are at their connection limit, must refuse */
3470 MHD_socket_close_chk_ (client_socket);
3471#if ENFILE
3472 errno = ENFILE;
3473#endif
3474 return MHD_NO;
3475 }
3476#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
3477
3478 return internal_add_connection (daemon,
3479 client_socket,
3480 addr,
3481 addrlen,
3482 true,
3483 sk_nonbl,
3484 sk_spipe_supprs,
3485 _MHD_UNKNOWN);
3486}
3487
3488
3503static enum MHD_Result
3505{
3506#if HAVE_INET6
3507 struct sockaddr_in6 addrstorage;
3508#else
3509 struct sockaddr_in addrstorage;
3510#endif
3511 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3512 socklen_t addrlen;
3513 MHD_socket s;
3514 MHD_socket fd;
3515 bool sk_nonbl;
3516 bool sk_spipe_supprs;
3517
3518#ifdef MHD_USE_THREADS
3519 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3520 MHD_thread_ID_match_current_ (daemon->pid) );
3521#endif /* MHD_USE_THREADS */
3522
3523 addrlen = sizeof (addrstorage);
3524 memset (addr,
3525 0,
3526 sizeof (addrstorage));
3527 if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3528 (daemon->was_quiesced) )
3529 return MHD_NO;
3530#ifdef USE_ACCEPT4
3531 s = accept4 (fd,
3532 addr,
3533 &addrlen,
3536 sk_nonbl = (SOCK_NONBLOCK_OR_ZERO != 0);
3537#ifndef MHD_WINSOCK_SOCKETS
3538 sk_spipe_supprs = (SOCK_NOSIGPIPE_OR_ZERO != 0);
3539#else /* MHD_WINSOCK_SOCKETS */
3540 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3541#endif /* MHD_WINSOCK_SOCKETS */
3542#else /* ! USE_ACCEPT4 */
3543 s = accept (fd,
3544 addr,
3545 &addrlen);
3546 sk_nonbl = false;
3547#ifndef MHD_WINSOCK_SOCKETS
3548 sk_spipe_supprs = false;
3549#else /* MHD_WINSOCK_SOCKETS */
3550 sk_spipe_supprs = true; /* Nothing to suppress on W32 */
3551#endif /* MHD_WINSOCK_SOCKETS */
3552#endif /* ! USE_ACCEPT4 */
3553 if ( (MHD_INVALID_SOCKET == s) ||
3554 (addrlen <= 0) )
3555 {
3556 const int err = MHD_socket_get_error_ ();
3557
3558 /* This could be a common occurrence with multiple worker threads */
3559 if (MHD_SCKT_ERR_IS_ (err,
3561 return MHD_NO; /* can happen during shutdown */
3563 return MHD_NO; /* do not print error if client just disconnected early */
3564#ifdef HAVE_MESSAGES
3565 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3566 MHD_DLOG (daemon,
3567 _ ("Error accepting connection: %s\n"),
3568 MHD_socket_strerr_ (err));
3569#endif
3570 if (MHD_INVALID_SOCKET != s)
3571 {
3573 }
3575 {
3576 /* system/process out of resources */
3577 if (0 == daemon->connections)
3578 {
3579#ifdef HAVE_MESSAGES
3580 /* Not setting 'at_limit' flag, as there is no way it
3581 would ever be cleared. Instead trying to produce
3582 bit fat ugly warning. */
3583 MHD_DLOG (daemon,
3584 _ (
3585 "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"));
3586#endif
3587 }
3588 else
3589 {
3590#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3592#endif
3593 daemon->at_limit = true;
3594#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3596#endif
3597#ifdef HAVE_MESSAGES
3598 MHD_DLOG (daemon,
3599 _ (
3600 "Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3601 (unsigned int) daemon->connections);
3602#endif
3603 }
3604 }
3605 return MHD_NO;
3606 }
3607#if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
3608 if (! MHD_socket_nonblocking_ (s))
3609 {
3610#ifdef HAVE_MESSAGES
3611 MHD_DLOG (daemon,
3612 _ (
3613 "Failed to set nonblocking mode on incoming connection socket: %s\n"),
3615#endif
3616 }
3617 else
3618 sk_nonbl = true;
3619#endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
3620#if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
3622 {
3623#ifdef HAVE_MESSAGES
3624 MHD_DLOG (daemon,
3625 _ (
3626 "Failed to set noninheritable mode on incoming connection socket.\n"));
3627#endif
3628 }
3629#endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
3630#if defined(MHD_socket_nosignal_)
3631 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
3632 {
3633#ifdef HAVE_MESSAGES
3634 MHD_DLOG (daemon,
3635 _ (
3636 "Failed to suppress SIGPIPE on incoming connection socket: %s\n"),
3638#else /* ! HAVE_MESSAGES */
3639 (void) 0; /* Mute compiler warning */
3640#endif /* ! HAVE_MESSAGES */
3641#ifndef MSG_NOSIGNAL
3642 /* Application expects that SIGPIPE will be suppressed,
3643 * but suppression failed and SIGPIPE cannot be suppressed with send(). */
3644 if (! daemon->sigpipe_blocked)
3645 {
3647 return MHD_NO;
3648 }
3649#endif /* MSG_NOSIGNAL */
3650 }
3651 else
3652 sk_spipe_supprs = true;
3653#endif /* MHD_socket_nosignal_ */
3654#ifdef HAVE_MESSAGES
3655#if _MHD_DEBUG_CONNECT
3656 MHD_DLOG (daemon,
3657 _ ("Accepted connection on socket %d\n"),
3658 s);
3659#endif
3660#endif
3661 (void) internal_add_connection (daemon,
3662 s,
3663 addr,
3664 addrlen,
3665 false,
3666 sk_nonbl,
3667 sk_spipe_supprs,
3668 daemon->listen_is_unix);
3669 return MHD_YES;
3670}
3671
3672
3682static void
3684{
3685 struct MHD_Connection *pos;
3686#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3688 MHD_thread_ID_match_current_ (daemon->pid) );
3689
3691#endif
3692 while (NULL != (pos = daemon->cleanup_tail))
3693 {
3696 pos);
3697#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3699 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3700 (! pos->thread_joined) &&
3701 (! MHD_join_thread_ (pos->pid.handle)) )
3702 MHD_PANIC (_ ("Failed to join a thread.\n"));
3703#endif
3704#ifdef UPGRADE_SUPPORT
3705 cleanup_upgraded_connection (pos);
3706#endif /* UPGRADE_SUPPORT */
3707 MHD_pool_destroy (pos->pool);
3708#ifdef HTTPS_SUPPORT
3709 if (NULL != pos->tls_session)
3710 gnutls_deinit (pos->tls_session);
3711#endif /* HTTPS_SUPPORT */
3712
3713 /* clean up the connection */
3716 pos,
3717 &pos->socket_context,
3720 pos->addr,
3721 pos->addr_len);
3722#ifdef EPOLL_SUPPORT
3723 if (0 != (daemon->options & MHD_USE_EPOLL))
3724 {
3725 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3726 {
3727 EDLL_remove (daemon->eready_head,
3728 daemon->eready_tail,
3729 pos);
3730 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3731 }
3732 if ( (-1 != daemon->epoll_fd) &&
3733 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3734 {
3735 /* epoll documentation suggests that closing a FD
3736 automatically removes it from the epoll set; however,
3737 this is not true as if we fail to do manually remove it,
3738 we are still seeing an event for this fd in epoll,
3739 causing grief (use-after-free...) --- at least on my
3740 system. */
3741 if (0 != epoll_ctl (daemon->epoll_fd,
3742 EPOLL_CTL_DEL,
3743 pos->socket_fd,
3744 NULL))
3745 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3746 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3747 }
3748 }
3749#endif
3750 if (NULL != pos->response)
3751 {
3753 pos->response = NULL;
3754 }
3755 if (MHD_INVALID_SOCKET != pos->socket_fd)
3757 if (NULL != pos->addr)
3758 free (pos->addr);
3759 free (pos);
3760
3761#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3763#endif
3765 daemon->at_limit = false;
3766 }
3767#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3769#endif
3770}
3771
3772
3793enum MHD_Result
3795 MHD_UNSIGNED_LONG_LONG *timeout)
3796{
3797 time_t earliest_deadline;
3798 time_t now;
3799 struct MHD_Connection *pos;
3800 bool have_timeout;
3801
3802#ifdef MHD_USE_THREADS
3804 MHD_thread_ID_match_current_ (daemon->pid) );
3805#endif /* MHD_USE_THREADS */
3806
3808 {
3809#ifdef HAVE_MESSAGES
3810 MHD_DLOG (daemon,
3811 _ ("Illegal call to MHD_get_timeout.\n"));
3812#endif
3813 return MHD_NO;
3814 }
3816 {
3817 /* Some data already waiting to be processed. */
3818 *timeout = 0;
3819 return MHD_YES;
3820 }
3821#ifdef EPOLL_SUPPORT
3822 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3823 ((NULL != daemon->eready_head)
3824#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3825 || (NULL != daemon->eready_urh_head)
3826#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3827 ) )
3828 {
3829 /* Some connection(s) already have some data pending. */
3830 *timeout = 0;
3831 return MHD_YES;
3832 }
3833#endif /* EPOLL_SUPPORT */
3834
3835 have_timeout = false;
3836 earliest_deadline = 0; /* avoid compiler warnings */
3837 for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3838 {
3839 if (0 != pos->connection_timeout)
3840 {
3841 if ( (! have_timeout) ||
3842 (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3843 earliest_deadline = pos->last_activity + pos->connection_timeout;
3844 have_timeout = true;
3845 }
3846 }
3847 /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3849 if ( (NULL != pos) &&
3850 (0 != pos->connection_timeout) )
3851 {
3852 if ( (! have_timeout) ||
3853 (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3854 earliest_deadline = pos->last_activity + pos->connection_timeout;
3855 have_timeout = true;
3856 }
3857
3858 if (! have_timeout)
3859 return MHD_NO;
3861 if (earliest_deadline < now)
3862 *timeout = 0;
3863 else
3864 {
3865 const time_t second_left = earliest_deadline - now;
3866
3867 if (((unsigned long long) second_left) > ULLONG_MAX / 1000)
3868 *timeout = ULLONG_MAX;
3869 else
3870 *timeout = 1000LLU * (unsigned long long) second_left;
3871 }
3872 return MHD_YES;
3873}
3874
3875
3886static int
3888 int32_t max_timeout)
3889{
3890 MHD_UNSIGNED_LONG_LONG ulltimeout;
3891 if (0 == max_timeout)
3892 return 0;
3893
3894 if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
3895 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3896
3897 if ( (0 > max_timeout) ||
3898 ((uint32_t) max_timeout > ulltimeout) )
3899 return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
3900
3901 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3902}
3903
3904
3915static enum MHD_Result
3917 const fd_set *read_fd_set,
3918 const fd_set *write_fd_set,
3919 const fd_set *except_fd_set)
3920{
3921 MHD_socket ds;
3922 struct MHD_Connection *pos;
3923 struct MHD_Connection *prev;
3924#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3925 struct MHD_UpgradeResponseHandle *urh;
3926 struct MHD_UpgradeResponseHandle *urhn;
3927#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3928 /* Reset. New value will be set when connections are processed. */
3929 /* Note: no-op for thread-per-connection as it is always false in that mode. */
3930 daemon->data_already_pending = false;
3931
3932 /* Clear ITC to avoid spinning select */
3933 /* Do it before any other processing so new signals
3934 will trigger select again and will be processed */
3935 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3936 (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3937 read_fd_set)) )
3938 MHD_itc_clear_ (daemon->itc);
3939
3940 /* Process externally added connection if any */
3941 if (daemon->have_new)
3943
3944 /* select connection thread handling type */
3945 if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3946 (! daemon->was_quiesced) &&
3947 (FD_ISSET (ds,
3948 read_fd_set)) )
3949 (void) MHD_accept_connection (daemon);
3950
3951 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3952 {
3953 /* do not have a thread per connection, process all connections now */
3954 prev = daemon->connections_tail;
3955 while (NULL != (pos = prev))
3956 {
3957 prev = pos->prev;
3958 ds = pos->socket_fd;
3959 if (MHD_INVALID_SOCKET == ds)
3960 continue;
3961 call_handlers (pos,
3962 FD_ISSET (ds,
3963 read_fd_set),
3964 FD_ISSET (ds,
3965 write_fd_set),
3966 FD_ISSET (ds,
3967 except_fd_set));
3968 }
3969 }
3970
3971#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3972 /* handle upgraded HTTPS connections */
3973 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3974 {
3975 urhn = urh->prev;
3976 /* update urh state based on select() output */
3977 urh_from_fdset (urh,
3978 read_fd_set,
3979 write_fd_set,
3980 except_fd_set);
3981 /* call generic forwarding function for passing data */
3982 process_urh (urh);
3983 /* Finished forwarding? */
3984 if ( (0 == urh->in_buffer_size) &&
3985 (0 == urh->out_buffer_size) &&
3986 (0 == urh->in_buffer_used) &&
3987 (0 == urh->out_buffer_used) )
3988 {
3989 MHD_connection_finish_forward_ (urh->connection);
3990 urh->clean_ready = true;
3991 /* Resuming will move connection to cleanup list. */
3992 MHD_resume_connection (urh->connection);
3993 }
3994 }
3995#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3996 MHD_cleanup_connections (daemon);
3997 return MHD_YES;
3998}
3999
4000
4023enum MHD_Result
4025 const fd_set *read_fd_set,
4026 const fd_set *write_fd_set,
4027 const fd_set *except_fd_set)
4028{
4029 fd_set es;
4030 if (0 != (daemon->options
4032 return MHD_NO;
4033 if ((NULL == read_fd_set) || (NULL == write_fd_set))
4034 return MHD_NO;
4035 if (NULL == except_fd_set)
4036 { /* Workaround to maintain backward compatibility. */
4037#ifdef HAVE_MESSAGES
4038 MHD_DLOG (daemon,
4039 _ ("MHD_run_from_select() called with except_fd_set "
4040 "set to NULL. Such behavior is deprecated.\n"));
4041#endif
4042 FD_ZERO (&es);
4043 except_fd_set = &es;
4044 }
4045 if (0 != (daemon->options & MHD_USE_EPOLL))
4046 {
4047#ifdef EPOLL_SUPPORT
4048 enum MHD_Result ret = MHD_epoll (daemon,
4049 0);
4050
4051 MHD_cleanup_connections (daemon);
4052 return ret;
4053#else /* ! EPOLL_SUPPORT */
4054 return MHD_NO;
4055#endif /* ! EPOLL_SUPPORT */
4056 }
4057
4058 /* Resuming external connections when using an extern mainloop */
4059 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4061
4062 return internal_run_from_select (daemon,
4063 read_fd_set,
4064 write_fd_set,
4065 except_fd_set);
4066}
4067
4068
4079static enum MHD_Result
4080MHD_select (struct MHD_Daemon *daemon,
4081 int32_t millisec)
4082{
4083 int num_ready;
4084 fd_set rs;
4085 fd_set ws;
4086 fd_set es;
4087 MHD_socket maxsock;
4088 struct timeval timeout;
4089 struct timeval *tv;
4090 int err_state;
4091 MHD_socket ls;
4092
4093 timeout.tv_sec = 0;
4094 timeout.tv_usec = 0;
4095 if (daemon->shutdown)
4096 return MHD_NO;
4097 FD_ZERO (&rs);
4098 FD_ZERO (&ws);
4099 FD_ZERO (&es);
4100 maxsock = MHD_INVALID_SOCKET;
4101 err_state = MHD_NO;
4102 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4103 (MHD_NO != resume_suspended_connections (daemon)) &&
4104 (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
4105 millisec = 0;
4106
4107 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4108 {
4109 /* single-threaded, go over everything */
4110 if (MHD_NO ==
4111 internal_get_fdset2 (daemon,
4112 &rs,
4113 &ws,
4114 &es,
4115 &maxsock,
4116 FD_SETSIZE))
4117 {
4118#ifdef HAVE_MESSAGES
4119 MHD_DLOG (daemon,
4120 _ ("Could not obtain daemon fdsets.\n"));
4121#endif
4122 err_state = MHD_YES;
4123 }
4124 }
4125 else
4126 {
4127 /* accept only, have one thread per connection */
4128 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4129 (! daemon->was_quiesced) &&
4130 (! MHD_add_to_fd_set_ (ls,
4131 &rs,
4132 &maxsock,
4133 FD_SETSIZE)) )
4134 {
4135#ifdef HAVE_MESSAGES
4136 MHD_DLOG (daemon,
4137 _ ("Could not add listen socket to fdset.\n"));
4138#endif
4139 return MHD_NO;
4140 }
4141 }
4142 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4143 (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4144 &rs,
4145 &maxsock,
4146 FD_SETSIZE)) )
4147 {
4148#if defined(MHD_WINSOCK_SOCKETS)
4149 /* fdset limit reached, new connections
4150 cannot be handled. Remove listen socket FD
4151 from fdset and retry to add ITC FD. */
4152 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4153 (! daemon->was_quiesced) )
4154 {
4155 FD_CLR (ls,
4156 &rs);
4157 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
4158 &rs,
4159 &maxsock,
4160 FD_SETSIZE))
4161 {
4162#endif /* MHD_WINSOCK_SOCKETS */
4163#ifdef HAVE_MESSAGES
4164 MHD_DLOG (daemon,
4165 _ (
4166 "Could not add control inter-thread communication channel FD to fdset.\n"));
4167#endif
4168 err_state = MHD_YES;
4169#if defined(MHD_WINSOCK_SOCKETS)
4170 }
4171}
4172
4173
4174#endif /* MHD_WINSOCK_SOCKETS */
4175 }
4176 /* Stop listening if we are at the configured connection limit */
4177 /* If we're at the connection limit, no point in really
4178 accepting new connections; however, make sure we do not miss
4179 the shutdown OR the termination of an existing connection; so
4180 only do this optimization if we have a signaling ITC in
4181 place. */
4182 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4183 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4184 ( (daemon->connections == daemon->connection_limit) ||
4185 (daemon->at_limit) ) )
4186 {
4187 FD_CLR (ls,
4188 &rs);
4189 }
4190
4191 if (MHD_NO != err_state)
4192 millisec = 0;
4193 tv = NULL;
4194 if (0 == millisec)
4195 {
4196 timeout.tv_usec = 0;
4197 timeout.tv_sec = 0;
4198 tv = &timeout;
4199 }
4200 else
4201 {
4202 MHD_UNSIGNED_LONG_LONG ltimeout;
4203
4204 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
4205 (MHD_NO != MHD_get_timeout (daemon, &ltimeout)) )
4206 {
4207 tv = &timeout; /* have timeout value */
4208 if ( (0 < millisec) &&
4209 (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
4210 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4211 }
4212 else if (0 < millisec)
4213 {
4214 tv = &timeout; /* have timeout value */
4215 ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
4216 }
4217
4218 if (NULL != tv)
4219 { /* have timeout value */
4220 if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
4221 {
4222 timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
4223 timeout.tv_usec = 0;
4224 }
4225 else
4226 {
4227 timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
4228 timeout.tv_usec = (ltimeout % 1000) * 1000;
4229 }
4230 }
4231 }
4232 num_ready = MHD_SYS_select_ (maxsock + 1,
4233 &rs,
4234 &ws,
4235 &es,
4236 tv);
4237 if (daemon->shutdown)
4238 return MHD_NO;
4239 if (num_ready < 0)
4240 {
4241 const int err = MHD_socket_get_error_ ();
4242 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4243 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4244#ifdef HAVE_MESSAGES
4245 MHD_DLOG (daemon,
4246 _ ("select failed: %s\n"),
4247 MHD_socket_strerr_ (err));
4248#endif
4249 return MHD_NO;
4250 }
4251 if (MHD_NO != internal_run_from_select (daemon,
4252 &rs,
4253 &ws,
4254 &es))
4255 return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
4256 return MHD_NO;
4257}
4258
4259
4260#ifdef HAVE_POLL
4271static enum MHD_Result
4272MHD_poll_all (struct MHD_Daemon *daemon,
4273 int32_t millisec)
4274{
4275 unsigned int num_connections;
4276 struct MHD_Connection *pos;
4277 struct MHD_Connection *prev;
4278#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4279 struct MHD_UpgradeResponseHandle *urh;
4280 struct MHD_UpgradeResponseHandle *urhn;
4281#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4282
4283 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4284 (MHD_NO != resume_suspended_connections (daemon)) )
4285 millisec = 0;
4286
4287 /* count number of connections and thus determine poll set size */
4288 num_connections = 0;
4289 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
4290 num_connections++;
4291#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4292 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
4293 num_connections += 2;
4294#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4295 {
4296 unsigned int i;
4297 int timeout;
4298 unsigned int poll_server;
4299 int poll_listen;
4300 int poll_itc_idx;
4301 struct pollfd *p;
4302 MHD_socket ls;
4303
4304 p = MHD_calloc_ ((2 + (size_t) num_connections),
4305 sizeof (struct pollfd));
4306 if (NULL == p)
4307 {
4308#ifdef HAVE_MESSAGES
4309 MHD_DLOG (daemon,
4310 _ ("Error allocating memory: %s\n"),
4311 MHD_strerror_ (errno));
4312#endif
4313 return MHD_NO;
4314 }
4315 poll_server = 0;
4316 poll_listen = -1;
4317 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4318 (! daemon->was_quiesced) &&
4319 (daemon->connections < daemon->connection_limit) &&
4320 (! daemon->at_limit) )
4321 {
4322 /* only listen if we are not at the connection limit */
4323 p[poll_server].fd = ls;
4324 p[poll_server].events = POLLIN;
4325 p[poll_server].revents = 0;
4326 poll_listen = (int) poll_server;
4327 poll_server++;
4328 }
4329 poll_itc_idx = -1;
4330 if (MHD_ITC_IS_VALID_ (daemon->itc))
4331 {
4332 p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
4333 p[poll_server].events = POLLIN;
4334 p[poll_server].revents = 0;
4335 poll_itc_idx = (int) poll_server;
4336 poll_server++;
4337 }
4338
4339 timeout = get_timeout_millisec_ (daemon, millisec);
4340
4341 i = 0;
4342 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
4343 {
4344 p[poll_server + i].fd = pos->socket_fd;
4345 switch (pos->event_loop_info)
4346 {
4348 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
4349 break;
4351 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
4352 break;
4354 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
4355 break;
4357 timeout = 0; /* clean up "pos" immediately */
4358 break;
4359 }
4360 i++;
4361 }
4362#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4363 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
4364 {
4365 urh_to_pollfd (urh, &(p[poll_server + i]));
4366 i += 2;
4367 }
4368#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4369 if (0 == poll_server + num_connections)
4370 {
4371 free (p);
4372 return MHD_YES;
4373 }
4374 if (MHD_sys_poll_ (p,
4375 poll_server + num_connections,
4376 timeout) < 0)
4377 {
4378 const int err = MHD_socket_get_error_ ();
4379 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4380 {
4381 free (p);
4382 return MHD_YES;
4383 }
4384#ifdef HAVE_MESSAGES
4385 MHD_DLOG (daemon,
4386 _ ("poll failed: %s\n"),
4387 MHD_socket_strerr_ (err));
4388#endif
4389 free (p);
4390 return MHD_NO;
4391 }
4392
4393 /* handle ITC FD */
4394 /* do it before any other processing so
4395 new signals will be processed in next loop */
4396 if ( (-1 != poll_itc_idx) &&
4397 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4398 MHD_itc_clear_ (daemon->itc);
4399
4400 /* handle shutdown */
4401 if (daemon->shutdown)
4402 {
4403 free (p);
4404 return MHD_NO;
4405 }
4406
4407 /* Process externally added connection if any */
4408 if (daemon->have_new)
4410
4411 /* handle 'listen' FD */
4412 if ( (-1 != poll_listen) &&
4413 (0 != (p[poll_listen].revents & POLLIN)) )
4414 (void) MHD_accept_connection (daemon);
4415
4416 /* Reset. New value will be set when connections are processed. */
4417 daemon->data_already_pending = false;
4418
4419 i = 0;
4420 prev = daemon->connections_tail;
4421 while (NULL != (pos = prev))
4422 {
4423 prev = pos->prev;
4424 /* first, sanity checks */
4425 if (i >= num_connections)
4426 break; /* connection list changed somehow, retry later ... */
4427 if (p[poll_server + i].fd != pos->socket_fd)
4428 continue; /* fd mismatch, something else happened, retry later ... */
4429 call_handlers (pos,
4430 0 != (p[poll_server + i].revents & POLLIN),
4431 0 != (p[poll_server + i].revents & POLLOUT),
4432 0 != (p[poll_server + i].revents
4433 & MHD_POLL_REVENTS_ERR_DISC));
4434 i++;
4435 }
4436#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4437 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4438 {
4439 if (i >= num_connections)
4440 break; /* connection list changed somehow, retry later ... */
4441
4442 /* Get next connection here as connection can be removed
4443 * from 'daemon->urh_head' list. */
4444 urhn = urh->prev;
4445 /* Check for fd mismatch. FIXME: required for safety? */
4446 if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
4447 (p[poll_server + i + 1].fd != urh->mhd.socket))
4448 break;
4449 urh_from_pollfd (urh,
4450 &p[poll_server + i]);
4451 i += 2;
4452 process_urh (urh);
4453 /* Finished forwarding? */
4454 if ( (0 == urh->in_buffer_size) &&
4455 (0 == urh->out_buffer_size) &&
4456 (0 == urh->in_buffer_used) &&
4457 (0 == urh->out_buffer_used) )
4458 {
4459 /* MHD_connection_finish_forward_() will remove connection from
4460 * 'daemon->urh_head' list. */
4461 MHD_connection_finish_forward_ (urh->connection);
4462 urh->clean_ready = true;
4463 /* If 'urh->was_closed' already was set to true, connection will be
4464 * moved immediately to cleanup list. Otherwise connection
4465 * will stay in suspended list until 'urh' will be marked
4466 * with 'was_closed' by application. */
4467 MHD_resume_connection (urh->connection);
4468 }
4469 }
4470#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4471
4472 free (p);
4473 }
4474 return MHD_YES;
4475}
4476
4477
4485static enum MHD_Result
4486MHD_poll_listen_socket (struct MHD_Daemon *daemon,
4487 int may_block)
4488{
4489 struct pollfd p[2];
4490 int timeout;
4491 unsigned int poll_count;
4492 int poll_listen;
4493 int poll_itc_idx;
4494 MHD_socket ls;
4495
4496 memset (&p,
4497 0,
4498 sizeof (p));
4499 poll_count = 0;
4500 poll_listen = -1;
4501 poll_itc_idx = -1;
4502 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4503 (! daemon->was_quiesced) )
4504
4505 {
4506 p[poll_count].fd = ls;
4507 p[poll_count].events = POLLIN;
4508 p[poll_count].revents = 0;
4509 poll_listen = poll_count;
4510 poll_count++;
4511 }
4512 if (MHD_ITC_IS_VALID_ (daemon->itc))
4513 {
4514 p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
4515 p[poll_count].events = POLLIN;
4516 p[poll_count].revents = 0;
4517 poll_itc_idx = poll_count;
4518 poll_count++;
4519 }
4520
4521 if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4522 (void) resume_suspended_connections (daemon);
4523
4524 if (MHD_NO == may_block)
4525 timeout = 0;
4526 else
4527 timeout = -1;
4528 if (0 == poll_count)
4529 return MHD_YES;
4530 if (MHD_sys_poll_ (p,
4531 poll_count,
4532 timeout) < 0)
4533 {
4534 const int err = MHD_socket_get_error_ ();
4535
4536 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4537 return MHD_YES;
4538#ifdef HAVE_MESSAGES
4539 MHD_DLOG (daemon,
4540 _ ("poll failed: %s\n"),
4541 MHD_socket_strerr_ (err));
4542#endif
4543 return MHD_NO;
4544 }
4545 if ( (-1 != poll_itc_idx) &&
4546 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4547 MHD_itc_clear_ (daemon->itc);
4548
4549 /* handle shutdown */
4550 if (daemon->shutdown)
4551 return MHD_NO;
4552
4553 /* Process externally added connection if any */
4554 if (daemon->have_new)
4556
4557 if ( (-1 != poll_listen) &&
4558 (0 != (p[poll_listen].revents & POLLIN)) )
4559 (void) MHD_accept_connection (daemon);
4560 return MHD_YES;
4561}
4562
4563
4564#endif
4565
4566
4574static enum MHD_Result
4575MHD_poll (struct MHD_Daemon *daemon,
4576 int may_block)
4577{
4578#ifdef HAVE_POLL
4579 if (daemon->shutdown)
4580 return MHD_NO;
4581 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4582 return MHD_poll_all (daemon,
4583 may_block ? -1 : 0);
4584 return MHD_poll_listen_socket (daemon,
4585 may_block);
4586#else
4587 (void) daemon;
4588 (void) may_block;
4589 return MHD_NO;
4590#endif
4591}
4592
4593
4594#ifdef EPOLL_SUPPORT
4595
4604#define MAX_EVENTS 128
4605
4606
4607#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4608
4616static bool
4617is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
4618{
4619 const struct MHD_Connection *const connection = urh->connection;
4620
4621 if ( (0 == urh->in_buffer_size) &&
4622 (0 == urh->out_buffer_size) &&
4623 (0 == urh->in_buffer_used) &&
4624 (0 == urh->out_buffer_used) )
4625 return false;
4626 if (connection->daemon->shutdown)
4627 return true;
4628 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4629 (connection->tls_read_ready) ) &&
4630 (urh->in_buffer_used < urh->in_buffer_size) )
4631 return true;
4632 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4633 (urh->out_buffer_used < urh->out_buffer_size) )
4634 return true;
4635 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4636 (urh->out_buffer_used > 0) )
4637 return true;
4638 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4639 (urh->in_buffer_used > 0) )
4640 return true;
4641 return false;
4642}
4643
4644
4653static enum MHD_Result
4654run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4655{
4656 struct epoll_event events[MAX_EVENTS];
4657 int num_events;
4658 struct MHD_UpgradeResponseHandle *pos;
4659 struct MHD_UpgradeResponseHandle *prev;
4660
4661#ifdef MHD_USE_THREADS
4662 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
4663 MHD_thread_ID_match_current_ (daemon->pid) );
4664#endif /* MHD_USE_THREADS */
4665
4666 num_events = MAX_EVENTS;
4667 while (0 != num_events)
4668 {
4669 unsigned int i;
4670 /* update event masks */
4671 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4672 events,
4673 MAX_EVENTS,
4674 0);
4675 if (-1 == num_events)
4676 {
4677 const int err = MHD_socket_get_error_ ();
4678
4679 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4680 return MHD_YES;
4681#ifdef HAVE_MESSAGES
4682 MHD_DLOG (daemon,
4683 _ ("Call to epoll_wait failed: %s\n"),
4684 MHD_socket_strerr_ (err));
4685#endif
4686 return MHD_NO;
4687 }
4688 for (i = 0; i < (unsigned int) num_events; i++)
4689 {
4690 struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
4691 struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
4692 bool new_err_state = false;
4693
4694 if (urh->clean_ready)
4695 continue;
4696
4697 /* Update ueh state based on what is ready according to epoll() */
4698 if (0 != (events[i].events & EPOLLIN))
4699 {
4700 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4701 }
4702 if (0 != (events[i].events & EPOLLOUT))
4703 {
4704 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4705 }
4706 if (0 != (events[i].events & EPOLLHUP))
4707 {
4709 }
4710
4711 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4712 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4713 {
4714 /* Process new error state only one time and avoid continuously
4715 * marking this connection as 'ready'. */
4716 ueh->celi |= MHD_EPOLL_STATE_ERROR;
4717 new_err_state = true;
4718 }
4719 if (! urh->in_eready_list)
4720 {
4721 if (new_err_state ||
4722 is_urh_ready (urh))
4723 {
4724 EDLL_insert (daemon->eready_urh_head,
4725 daemon->eready_urh_tail,
4726 urh);
4727 urh->in_eready_list = true;
4728 }
4729 }
4730 }
4731 }
4732 prev = daemon->eready_urh_tail;
4733 while (NULL != (pos = prev))
4734 {
4735 prev = pos->prevE;
4736 process_urh (pos);
4737 if (! is_urh_ready (pos))
4738 {
4739 EDLL_remove (daemon->eready_urh_head,
4740 daemon->eready_urh_tail,
4741 pos);
4742 pos->in_eready_list = false;
4743 }
4744 /* Finished forwarding? */
4745 if ( (0 == pos->in_buffer_size) &&
4746 (0 == pos->out_buffer_size) &&
4747 (0 == pos->in_buffer_used) &&
4748 (0 == pos->out_buffer_used) )
4749 {
4750 MHD_connection_finish_forward_ (pos->connection);
4751 pos->clean_ready = true;
4752 /* If 'pos->was_closed' already was set to true, connection
4753 * will be moved immediately to cleanup list. Otherwise
4754 * connection will stay in suspended list until 'pos' will
4755 * be marked with 'was_closed' by application. */
4756 MHD_resume_connection (pos->connection);
4757 }
4758 }
4759
4760 return MHD_YES;
4761}
4762
4763
4764#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4765
4766
4770static const char *const epoll_itc_marker = "itc_marker";
4771
4772
4782static enum MHD_Result
4783MHD_epoll (struct MHD_Daemon *daemon,
4784 int32_t millisec)
4785{
4786#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4787 static const char *const upgrade_marker = "upgrade_ptr";
4788#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4789 struct MHD_Connection *pos;
4790 struct MHD_Connection *prev;
4791 struct epoll_event events[MAX_EVENTS];
4792 struct epoll_event event;
4793 int timeout_ms;
4794 int num_events;
4795 unsigned int i;
4796 MHD_socket ls;
4797#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4798 bool run_upgraded = false;
4799#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4800 bool need_to_accept;
4801
4802 if (-1 == daemon->epoll_fd)
4803 return MHD_NO; /* we're down! */
4804 if (daemon->shutdown)
4805 return MHD_NO;
4806 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4807 (! daemon->was_quiesced) &&
4808 (daemon->connections < daemon->connection_limit) &&
4809 (! daemon->listen_socket_in_epoll) &&
4810 (! daemon->at_limit) )
4811 {
4812 event.events = EPOLLIN;
4813 event.data.ptr = daemon;
4814 if (0 != epoll_ctl (daemon->epoll_fd,
4815 EPOLL_CTL_ADD,
4816 ls,
4817 &event))
4818 {
4819#ifdef HAVE_MESSAGES
4820 MHD_DLOG (daemon,
4821 _ ("Call to epoll_ctl failed: %s\n"),
4823#endif
4824 return MHD_NO;
4825 }
4826 daemon->listen_socket_in_epoll = true;
4827 }
4828 if ( (daemon->was_quiesced) &&
4829 (daemon->listen_socket_in_epoll) )
4830 {
4831 if ( (0 != epoll_ctl (daemon->epoll_fd,
4832 EPOLL_CTL_DEL,
4833 ls,
4834 NULL)) &&
4835 (ENOENT != errno) ) /* ENOENT can happen due to race with
4836 #MHD_quiesce_daemon() */
4837 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4838 daemon->listen_socket_in_epoll = false;
4839 }
4840
4841#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4842 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4843 (-1 != daemon->epoll_upgrade_fd) ) )
4844 {
4845 event.events = EPOLLIN | EPOLLOUT;
4846 event.data.ptr = (void *) upgrade_marker;
4847 if (0 != epoll_ctl (daemon->epoll_fd,
4848 EPOLL_CTL_ADD,
4849 daemon->epoll_upgrade_fd,
4850 &event))
4851 {
4852#ifdef HAVE_MESSAGES
4853 MHD_DLOG (daemon,
4854 _ ("Call to epoll_ctl failed: %s\n"),
4856#endif
4857 return MHD_NO;
4858 }
4859 daemon->upgrade_fd_in_epoll = true;
4860 }
4861#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4862 if ( (daemon->listen_socket_in_epoll) &&
4863 ( (daemon->connections == daemon->connection_limit) ||
4864 (daemon->at_limit) ||
4865 (daemon->was_quiesced) ) )
4866 {
4867 /* we're at the connection limit, disable listen socket
4868 for event loop for now */
4869 if (0 != epoll_ctl (daemon->epoll_fd,
4870 EPOLL_CTL_DEL,
4871 ls,
4872 NULL))
4873 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
4874 daemon->listen_socket_in_epoll = false;
4875 }
4876
4877 if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4878 (MHD_NO != resume_suspended_connections (daemon)) )
4879 millisec = 0;
4880
4881 timeout_ms = get_timeout_millisec_ (daemon, millisec);
4882
4883 /* Reset. New value will be set when connections are processed. */
4884 /* Note: Used mostly for uniformity here as same situation is
4885 * signaled in epoll mode by non-empty eready DLL. */
4886 daemon->data_already_pending = false;
4887
4888 need_to_accept = false;
4889 /* drain 'epoll' event queue; need to iterate as we get at most
4890 MAX_EVENTS in one system call here; in practice this should
4891 pretty much mean only one round, but better an extra loop here
4892 than unfair behavior... */
4893 num_events = MAX_EVENTS;
4894 while (MAX_EVENTS == num_events)
4895 {
4896 /* update event masks */
4897 num_events = epoll_wait (daemon->epoll_fd,
4898 events,
4899 MAX_EVENTS,
4900 timeout_ms);
4901 if (-1 == num_events)
4902 {
4903 const int err = MHD_socket_get_error_ ();
4904 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4905 return MHD_YES;
4906#ifdef HAVE_MESSAGES
4907 MHD_DLOG (daemon,
4908 _ ("Call to epoll_wait failed: %s\n"),
4909 MHD_socket_strerr_ (err));
4910#endif
4911 return MHD_NO;
4912 }
4913 for (i = 0; i<(unsigned int) num_events; i++)
4914 {
4915 /* First, check for the values of `ptr` that would indicate
4916 that this event is not about a normal connection. */
4917 if (NULL == events[i].data.ptr)
4918 continue; /* shutdown signal! */
4919#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4920 if (upgrade_marker == events[i].data.ptr)
4921 {
4922 /* activity on an upgraded connection, we process
4923 those in a separate epoll() */
4924 run_upgraded = true;
4925 continue;
4926 }
4927#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4928 if (epoll_itc_marker == events[i].data.ptr)
4929 {
4930 /* It's OK to clear ITC here as all external
4931 conditions will be processed later. */
4932 MHD_itc_clear_ (daemon->itc);
4933 continue;
4934 }
4935 if (daemon == events[i].data.ptr)
4936 {
4937 /* Check for error conditions on listen socket. */
4938 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4939 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4940 need_to_accept = true;
4941 continue;
4942 }
4943 /* this is an event relating to a 'normal' connection,
4944 remember the event and if appropriate mark the
4945 connection as 'eready'. */
4946 pos = events[i].data.ptr;
4947 /* normal processing: update read/write data */
4948 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4949 {
4950 pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4951 if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4952 {
4953 EDLL_insert (daemon->eready_head,
4954 daemon->eready_tail,
4955 pos);
4956 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4957 }
4958 }
4959 else
4960 {
4961 if (0 != (events[i].events & EPOLLIN))
4962 {
4963 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4964 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4965 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4966 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4967 {
4968 EDLL_insert (daemon->eready_head,
4969 daemon->eready_tail,
4970 pos);
4971 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4972 }
4973 }
4974 if (0 != (events[i].events & EPOLLOUT))
4975 {
4976 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4978 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4979 {
4980 EDLL_insert (daemon->eready_head,
4981 daemon->eready_tail,
4982 pos);
4983 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4984 }
4985 }
4986 }
4987 }
4988 }
4989
4990 /* Process externally added connection if any */
4991 if (daemon->have_new)
4993
4994 if (need_to_accept)
4995 {
4996 unsigned int series_length = 0;
4997
4998 /* Run 'accept' until it fails or daemon at limit of connections.
4999 * Do not accept more then 10 connections at once. The rest will
5000 * be accepted on next turn (level trigger is used for listen
5001 * socket). */
5002 while ( (MHD_NO != MHD_accept_connection (daemon)) &&
5003 (series_length < 10) &&
5004 (daemon->connections < daemon->connection_limit) &&
5005 (! daemon->at_limit) )
5006 series_length++;
5007 }
5008
5009 /* Handle timed-out connections; we need to do this here
5010 as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
5011 as the other event loops do. As timeouts do not get an explicit
5012 event, we need to find those connections that might have timed out
5013 here.
5014
5015 Connections with custom timeouts must all be looked at, as we
5016 do not bother to sort that (presumably very short) list. */
5017 prev = daemon->manual_timeout_tail;
5018 while (NULL != (pos = prev))
5019 {
5020 prev = pos->prevX;
5022 }
5023 /* Connections with the default timeout are sorted by prepending
5024 them to the head of the list whenever we touch the connection;
5025 thus it suffices to iterate from the tail until the first
5026 connection is NOT timed out */
5027 prev = daemon->normal_timeout_tail;
5028 while (NULL != (pos = prev))
5029 {
5030 prev = pos->prevX;
5032 if (MHD_CONNECTION_CLOSED != pos->state)
5033 break; /* sorted by timeout, no need to visit the rest! */
5034 }
5035
5036#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5037 if (run_upgraded || (NULL != daemon->eready_urh_head))
5038 run_epoll_for_upgrade (daemon);
5039#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5040
5041 /* process events for connections */
5042 prev = daemon->eready_tail;
5043 while (NULL != (pos = prev))
5044 {
5045 prev = pos->prevE;
5046 call_handlers (pos,
5047 0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
5048 0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
5049 0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
5051 (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
5053 {
5054 if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
5055 (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
5057 (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
5059 {
5060 EDLL_remove (daemon->eready_head,
5061 daemon->eready_tail,
5062 pos);
5063 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
5064 }
5065 }
5066 }
5067
5068 return MHD_YES;
5069}
5070
5071
5072#endif
5073
5074
5095enum MHD_Result
5096MHD_run (struct MHD_Daemon *daemon)
5097{
5098 if ( (daemon->shutdown) ||
5099 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5100 return MHD_NO;
5101
5102 (void) MHD_run_wait (daemon, 0);
5103 return MHD_YES;
5104}
5105
5106
5136MHD_run_wait (struct MHD_Daemon *daemon,
5137 int32_t millisec)
5138{
5139 enum MHD_Result res;
5140 if ( (daemon->shutdown) ||
5141 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
5142 return MHD_NO;
5143
5144 if (0 > millisec)
5145 millisec = -1;
5146 if (false)
5147 {
5148 (void) 0; /* Mute compiler warning */
5149 }
5150#ifdef HAVE_POLL
5151 else if (0 != (daemon->options & MHD_USE_POLL))
5152 {
5153 res = MHD_poll_all (daemon, millisec);
5154 MHD_cleanup_connections (daemon);
5155 }
5156#endif /* HAVE_POLL */
5157#ifdef EPOLL_SUPPORT
5158 else if (0 != (daemon->options & MHD_USE_EPOLL))
5159 {
5160 res = MHD_epoll (daemon, millisec);
5161 MHD_cleanup_connections (daemon);
5162 }
5163#endif
5164 else
5165 {
5166 res = MHD_select (daemon, millisec);
5167 /* MHD_select does MHD_cleanup_connections already */
5168 }
5169 return res;
5170}
5171
5172
5181static void
5183{
5184 struct MHD_Daemon *daemon = pos->daemon;
5185
5186#ifdef MHD_USE_THREADS
5187 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
5188 MHD_thread_ID_match_current_ (daemon->pid) );
5189#endif /* MHD_USE_THREADS */
5190
5191 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5192 {
5194 return; /* must let thread to do the rest */
5195 }
5198#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5200#endif
5201 mhd_assert (! pos->suspended);
5202 mhd_assert (! pos->resuming);
5203 if (pos->connection_timeout == daemon->connection_timeout)
5205 daemon->normal_timeout_tail,
5206 pos);
5207 else
5209 daemon->manual_timeout_tail,
5210 pos);
5212 daemon->connections_tail,
5213 pos);
5214 DLL_insert (daemon->cleanup_head,
5215 daemon->cleanup_tail,
5216 pos);
5217 daemon->data_already_pending = true;
5218#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5220#endif
5221}
5222
5223
5224#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5232static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
5233MHD_polling_thread (void *cls)
5234{
5235 struct MHD_Daemon *daemon = cls;
5236#ifdef HAVE_PTHREAD_SIGMASK
5237 sigset_t s_mask;
5238 int err;
5239#endif /* HAVE_PTHREAD_SIGMASK */
5240
5241 MHD_thread_init_ (&(daemon->pid));
5242#ifdef HAVE_PTHREAD_SIGMASK
5243 if ((0 == sigemptyset (&s_mask)) &&
5244 (0 == sigaddset (&s_mask, SIGPIPE)))
5245 {
5246 err = pthread_sigmask (SIG_BLOCK, &s_mask, NULL);
5247 }
5248 else
5249 err = errno;
5250 if (0 == err)
5251 daemon->sigpipe_blocked = true;
5252#ifdef HAVE_MESSAGES
5253 else
5254 MHD_DLOG (daemon,
5255 _ ("Failed to block SIGPIPE on daemon thread: %s\n"),
5256 MHD_strerror_ (errno));
5257#endif /* HAVE_MESSAGES */
5258#endif /* HAVE_PTHREAD_SIGMASK */
5259 while (! daemon->shutdown)
5260 {
5261 if (0 != (daemon->options & MHD_USE_POLL))
5262 MHD_poll (daemon, MHD_YES);
5263#ifdef EPOLL_SUPPORT
5264 else if (0 != (daemon->options & MHD_USE_EPOLL))
5265 MHD_epoll (daemon, -1);
5266#endif
5267 else
5268 MHD_select (daemon, -1);
5269 MHD_cleanup_connections (daemon);
5270 }
5271
5272 /* Resume any pending for resume connections, join
5273 * all connection's threads (if any) and finally cleanup
5274 * everything. */
5275 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
5277 close_all_connections (daemon);
5278
5279 return (MHD_THRD_RTRN_TYPE_) 0;
5280}
5281
5282
5283#endif
5284
5285
5297static size_t
5299 struct MHD_Connection *connection,
5300 char *val)
5301{
5302 (void) cls; /* Mute compiler warning. */
5303
5304 (void) connection; /* Mute compiler warning. */
5305 return MHD_http_unescape (val);
5306}
5307
5308
5329struct MHD_Daemon *
5330MHD_start_daemon (unsigned int flags,
5331 uint16_t port,
5333 void *apc_cls,
5335 void *dh_cls,
5336 ...)
5337{
5338 struct MHD_Daemon *daemon;
5339 va_list ap;
5340
5341 va_start (ap,
5342 dh_cls);
5343 daemon = MHD_start_daemon_va (flags,
5344 port,
5345 apc,
5346 apc_cls,
5347 dh,
5348 dh_cls,
5349 ap);
5350 va_end (ap);
5351 return daemon;
5352}
5353
5354
5376{
5377#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5378 unsigned int i;
5379#endif
5380 MHD_socket ret;
5381
5382 ret = daemon->listen_fd;
5383 if (MHD_INVALID_SOCKET == ret)
5384 return MHD_INVALID_SOCKET;
5385 if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
5386 (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
5387 {
5388#ifdef HAVE_MESSAGES
5389 MHD_DLOG (daemon,
5390 _ (
5391 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n"));
5392#endif
5393 return MHD_INVALID_SOCKET;
5394 }
5395
5396#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5397 if (NULL != daemon->worker_pool)
5398 for (i = 0; i < daemon->worker_pool_size; i++)
5399 {
5400 daemon->worker_pool[i].was_quiesced = true;
5401#ifdef EPOLL_SUPPORT
5402 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5403 (-1 != daemon->worker_pool[i].epoll_fd) &&
5404 (daemon->worker_pool[i].listen_socket_in_epoll) )
5405 {
5406 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
5407 EPOLL_CTL_DEL,
5408 ret,
5409 NULL))
5410 MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
5411 daemon->worker_pool[i].listen_socket_in_epoll = false;
5412 }
5413 else
5414#endif
5415 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
5416 {
5417 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
5418 MHD_PANIC (_ (
5419 "Failed to signal quiesce via inter-thread communication channel.\n"));
5420 }
5421 }
5422#endif
5423 daemon->was_quiesced = true;
5424#ifdef EPOLL_SUPPORT
5425 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5426 (-1 != daemon->epoll_fd) &&
5427 (daemon->listen_socket_in_epoll) )
5428 {
5429 if ( (0 != epoll_ctl (daemon->epoll_fd,
5430 EPOLL_CTL_DEL,
5431 ret,
5432 NULL)) &&
5433 (ENOENT != errno) ) /* ENOENT can happen due to race with
5434 #MHD_epoll() */
5435 MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
5436 daemon->listen_socket_in_epoll = false;
5437 }
5438#endif
5439 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
5440 (! MHD_itc_activate_ (daemon->itc, "q")) )
5441 MHD_PANIC (_ (
5442 "failed to signal quiesce via inter-thread communication channel.\n"));
5443 return ret;
5444}
5445
5446
5454typedef void
5455(*VfprintfFunctionPointerType)(void *cls,
5456 const char *format,
5457 va_list va);
5458
5459
5468static enum MHD_Result
5469parse_options_va (struct MHD_Daemon *daemon,
5470 const struct sockaddr **servaddr,
5471 va_list ap);
5472
5473
5482static enum MHD_Result
5484 const struct sockaddr **servaddr,
5485 ...)
5486{
5487 va_list ap;
5488 enum MHD_Result ret;
5489
5490 va_start (ap, servaddr);
5491 ret = parse_options_va (daemon,
5492 servaddr,
5493 ap);
5494 va_end (ap);
5495 return ret;
5496}
5497
5498
5507static enum MHD_Result
5509 const struct sockaddr **servaddr,
5510 va_list ap)
5511{
5512 enum MHD_OPTION opt;
5513 struct MHD_OptionItem *oa;
5514 unsigned int i;
5515 unsigned int uv;
5516#ifdef HTTPS_SUPPORT
5517 enum MHD_Result ret;
5518 const char *pstr;
5519#if GNUTLS_VERSION_MAJOR >= 3
5520 gnutls_certificate_retrieve_function2 *pgcrf;
5521#endif
5522#if GNUTLS_VERSION_NUMBER >= 0x030603
5523 gnutls_certificate_retrieve_function3 *pgcrf2;
5524#endif
5525#endif /* HTTPS_SUPPORT */
5526
5527 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
5528 {
5529 /* Increase counter at start, so resulting value is number of
5530 * processed options, including any failed ones. */
5531 daemon->num_opts++;
5532 switch (opt)
5533 {
5535 daemon->pool_size = va_arg (ap,
5536 size_t);
5537 break;
5539 daemon->pool_increment = va_arg (ap,
5540 size_t);
5541 break;
5543 daemon->connection_limit = va_arg (ap,
5544 unsigned int);
5545 break;
5547 uv = va_arg (ap,
5548 unsigned int);
5549 daemon->connection_timeout = (time_t) uv;
5550 /* Next comparison could be always false on some platforms and whole branch will
5551 * be optimized out on those platforms. On others it will be compiled into real
5552 * check. */
5553 if ( ( (MHD_TYPE_IS_SIGNED_ (time_t)) &&
5554 (daemon->connection_timeout < 0) ) || /* Compiler may warn on some platforms, ignore warning. */
5555 (uv != (unsigned int) daemon->connection_timeout) )
5556 {
5557#ifdef HAVE_MESSAGES
5558 MHD_DLOG (daemon,
5559 _ ("Warning: Too large timeout value, ignored.\n"));
5560#endif
5561 daemon->connection_timeout = 0;
5562 }
5563 break;
5565 daemon->notify_completed = va_arg (ap,
5567 daemon->notify_completed_cls = va_arg (ap,
5568 void *);
5569 break;
5571 daemon->notify_connection = va_arg (ap,
5573 daemon->notify_connection_cls = va_arg (ap,
5574 void *);
5575 break;
5577 daemon->per_ip_connection_limit = va_arg (ap,
5578 unsigned int);
5579 break;
5581 *servaddr = va_arg (ap,
5582 const struct sockaddr *);
5583 break;
5585 daemon->uri_log_callback = va_arg (ap,
5586 LogCallback);
5587 daemon->uri_log_callback_cls = va_arg (ap,
5588 void *);
5589 break;
5591 daemon->insanity_level = (enum MHD_DisableSanityCheck)
5592 va_arg (ap,
5593 unsigned int);
5594 break;
5595#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5597 daemon->worker_pool_size = va_arg (ap,
5598 unsigned int);
5599 if (0 == daemon->worker_pool_size)
5600 {
5601#ifdef HAVE_MESSAGES
5602 MHD_DLOG (daemon,
5603 _ (
5604 "Warning: Zero size, specified for thread pool size, is ignored. "
5605 "Thread pool is not used.\n"));
5606#endif
5607 }
5608 else if (1 == daemon->worker_pool_size)
5609 {
5610#ifdef HAVE_MESSAGES
5611 MHD_DLOG (daemon,
5612 _ (
5613 "Warning: \"1\", specified for thread pool size, is ignored. "
5614 "Thread pool is not used.\n"));
5615#endif
5616 daemon->worker_pool_size = 0;
5617 }
5618#if (0 == (UINT_MAX + 0)) || (UINT_MAX >= (SIZE_MAX / (64 * 1024)))
5619 /* Next comparison could be always false on some platforms and whole branch will
5620 * be optimized out on these platforms. On others it will be compiled into real
5621 * check. */
5622 else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct
5623 MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
5624 {
5625#ifdef HAVE_MESSAGES
5626 MHD_DLOG (daemon,
5627 _ ("Specified thread pool size (%u) too big.\n"),
5628 daemon->worker_pool_size);
5629#endif
5630 return MHD_NO;
5631 }
5632#endif /* (UINT_MAX >= (SIZE_MAX/(64*1024))) */
5633 else
5634 {
5635 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
5636 {
5637#ifdef HAVE_MESSAGES
5638 MHD_DLOG (daemon,
5639 _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5640 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5641#endif
5642 return MHD_NO;
5643 }
5644 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5645 {
5646#ifdef HAVE_MESSAGES
5647 MHD_DLOG (daemon,
5648 _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
5649 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5650#endif
5651 return MHD_NO;
5652 }
5653 }
5654 break;
5655#endif
5656#ifdef HTTPS_SUPPORT
5658 pstr = va_arg (ap,
5659 const char *);
5660 if (0 != (daemon->options & MHD_USE_TLS))
5661 daemon->https_mem_key = pstr;
5662#ifdef HAVE_MESSAGES
5663 else
5664 MHD_DLOG (daemon,
5665 _ (
5666 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5667 opt);
5668#endif
5669 break;
5671 pstr = va_arg (ap,
5672 const char *);
5673 if (0 != (daemon->options & MHD_USE_TLS))
5674 daemon->https_key_password = pstr;
5675#ifdef HAVE_MESSAGES
5676 else
5677 MHD_DLOG (daemon,
5678 _ (
5679 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5680 opt);
5681#endif
5682 break;
5684 pstr = va_arg (ap,
5685 const char *);
5686 if (0 != (daemon->options & MHD_USE_TLS))
5687 daemon->https_mem_cert = pstr;
5688#ifdef HAVE_MESSAGES
5689 else
5690 MHD_DLOG (daemon,
5691 _ (
5692 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5693 opt);
5694#endif
5695 break;
5697 pstr = va_arg (ap,
5698 const char *);
5699 if (0 != (daemon->options & MHD_USE_TLS))
5700 daemon->https_mem_trust = pstr;
5701#ifdef HAVE_MESSAGES
5702 else
5703 MHD_DLOG (daemon,
5704 _ (
5705 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5706 opt);
5707#endif
5708 break;
5710 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5711 int);
5712 break;
5714 pstr = va_arg (ap,
5715 const char *);
5716 if (0 != (daemon->options & MHD_USE_TLS))
5717 {
5718 gnutls_datum_t dhpar;
5719 size_t pstr_len;
5720
5721 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5722 {
5723#ifdef HAVE_MESSAGES
5724 MHD_DLOG (daemon,
5725 _ ("Error initializing DH parameters.\n"));
5726#endif
5727 return MHD_NO;
5728 }
5729 dhpar.data = (unsigned char *) pstr;
5730 pstr_len = strlen (pstr);
5731 if (UINT_MAX < pstr_len)
5732 {
5733#ifdef HAVE_MESSAGES
5734 MHD_DLOG (daemon,
5735 _ ("Diffie-Hellman parameters string too long.\n"));
5736#endif
5737 return MHD_NO;
5738 }
5739 dhpar.size = (unsigned int) pstr_len;
5740 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5741 &dhpar,
5742 GNUTLS_X509_FMT_PEM) < 0)
5743 {
5744#ifdef HAVE_MESSAGES
5745 MHD_DLOG (daemon,
5746 _ ("Bad Diffie-Hellman parameters format.\n"));
5747#endif
5748 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5749 return MHD_NO;
5750 }
5751 daemon->have_dhparams = true;
5752 }
5753#ifdef HAVE_MESSAGES
5754 else
5755 MHD_DLOG (daemon,
5756 _ (
5757 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5758 opt);
5759#endif
5760 break;
5762 pstr = va_arg (ap,
5763 const char *);
5764 if (0 != (daemon->options & MHD_USE_TLS))
5765 {
5766 gnutls_priority_deinit (daemon->priority_cache);
5767 ret = gnutls_priority_init (&daemon->priority_cache,
5768 pstr,
5769 NULL);
5770 if (GNUTLS_E_SUCCESS != ret)
5771 {
5772#ifdef HAVE_MESSAGES
5773 MHD_DLOG (daemon,
5774 _ ("Setting priorities to `%s' failed: %s\n"),
5775 pstr,
5776 gnutls_strerror (ret));
5777#endif
5778 daemon->priority_cache = NULL;
5779 return MHD_NO;
5780 }
5781 }
5782#ifdef HAVE_MESSAGES
5783 else
5784 MHD_DLOG (daemon,
5785 _ (
5786 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5787 opt);
5788#endif
5789 break;
5791#if GNUTLS_VERSION_MAJOR < 3
5792#ifdef HAVE_MESSAGES
5793 MHD_DLOG (daemon,
5794 _ (
5795 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5796#endif
5797 return MHD_NO;
5798#else
5799 pgcrf = va_arg (ap,
5800 gnutls_certificate_retrieve_function2 *);
5801 if (0 != (daemon->options & MHD_USE_TLS))
5802 daemon->cert_callback = pgcrf;
5803#ifdef HAVE_MESSAGES
5804 else
5805 MHD_DLOG (daemon,
5806 _ (
5807 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5808 opt);
5809#endif /* HAVE_MESSAGES */
5810 break;
5811#endif
5813#if GNUTLS_VERSION_NUMBER < 0x030603
5814#ifdef HAVE_MESSAGES
5815 MHD_DLOG (daemon,
5816 _ (
5817 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5818#endif
5819 return MHD_NO;
5820#else
5821 pgcrf2 = va_arg (ap,
5822 gnutls_certificate_retrieve_function3 *);
5823 if (0 != (daemon->options & MHD_USE_TLS))
5824 daemon->cert_callback2 = pgcrf2;
5825#ifdef HAVE_MESSAGES
5826 else
5827 MHD_DLOG (daemon,
5828 _ (
5829 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5830 opt);
5831#endif /* HAVE_MESSAGES */
5832 break;
5833#endif
5834#endif /* HTTPS_SUPPORT */
5835#ifdef DAUTH_SUPPORT
5837 daemon->digest_auth_rand_size = va_arg (ap,
5838 size_t);
5839 daemon->digest_auth_random = va_arg (ap,
5840 const char *);
5841 break;
5843 daemon->nonce_nc_size = va_arg (ap,
5844 unsigned int);
5845 break;
5846#endif
5848 if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5849 {
5850#ifdef HAVE_MESSAGES
5851 MHD_DLOG (daemon,
5852 _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5853 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5854#endif
5855 return MHD_NO;
5856 }
5857 else
5858 {
5859 daemon->listen_fd = va_arg (ap,
5860 MHD_socket);
5861#if defined(SO_DOMAIN) && defined(AF_UNIX)
5862 {
5863 int af;
5864 socklen_t len = sizeof (af);
5865
5866 if (0 == getsockopt (daemon->listen_fd,
5867 SOL_SOCKET,
5868 SO_DOMAIN,
5869 &af,
5870 &len))
5871 {
5872 daemon->listen_is_unix = (AF_UNIX == af) ? _MHD_YES : _MHD_NO;
5873 }
5874 else
5875 daemon->listen_is_unix = _MHD_UNKNOWN;
5876 }
5877#else /* ! SO_DOMAIN || ! AF_UNIX */
5878 daemon->listen_is_unix = _MHD_UNKNOWN;
5879#endif /* ! SO_DOMAIN || ! AF_UNIX */
5880 }
5881 break;
5883#ifdef HAVE_MESSAGES
5884 daemon->custom_error_log = va_arg (ap,
5886 daemon->custom_error_log_cls = va_arg (ap,
5887 void *);
5888 if (1 != daemon->num_opts)
5889 MHD_DLOG (daemon,
5890 _ ("MHD_OPTION_EXTERNAL_LOGGER is not the first option "
5891 "specified for the daemon. Some messages may be "
5892 "printed by the standard MHD logger.\n"));
5893
5894#else
5895 va_arg (ap,
5897 va_arg (ap,
5898 void *);
5899#endif
5900 break;
5901#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5903 daemon->thread_stack_size = va_arg (ap,
5904 size_t);
5905 break;
5906#endif
5908#ifdef TCP_FASTOPEN
5909 daemon->fastopen_queue_size = va_arg (ap,
5910 unsigned int);
5911 break;
5912#else /* ! TCP_FASTOPEN */
5913#ifdef HAVE_MESSAGES
5914 MHD_DLOG (daemon,
5915 _ ("TCP fastopen is not supported on this platform.\n"));
5916#endif /* HAVE_MESSAGES */
5917 return MHD_NO;
5918#endif /* ! TCP_FASTOPEN */
5920 daemon->listening_address_reuse = va_arg (ap,
5921 unsigned int) ? 1 : -1;
5922 break;
5924 daemon->listen_backlog_size = va_arg (ap,
5925 unsigned int);
5926 break;
5928 daemon->strict_for_client = va_arg (ap, int);
5929#ifdef HAVE_MESSAGES
5930 if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
5931 (1 != daemon->strict_for_client) )
5932 {
5933 MHD_DLOG (daemon,
5934 _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5935 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5936 }
5937#endif /* HAVE_MESSAGES */
5938 break;
5939 case MHD_OPTION_ARRAY:
5940 daemon->num_opts--; /* Do not count MHD_OPTION_ARRAY */
5941 oa = va_arg (ap, struct MHD_OptionItem*);
5942 i = 0;
5943 while (MHD_OPTION_END != (opt = oa[i].option))
5944 {
5945 switch (opt)
5946 {
5947 /* all options taking 'size_t' */
5951 if (MHD_NO == parse_options (daemon,
5952 servaddr,
5953 opt,
5954 (size_t) oa[i].value,
5956 return MHD_NO;
5957 break;
5958 /* all options taking 'unsigned int' */
5968 if (MHD_NO == parse_options (daemon,
5969 servaddr,
5970 opt,
5971 (unsigned int) oa[i].value,
5973 return MHD_NO;
5974 break;
5975 /* all options taking 'enum' */
5976#ifdef HTTPS_SUPPORT
5978 if (MHD_NO == parse_options (daemon,
5979 servaddr,
5980 opt,
5981 (gnutls_credentials_type_t) oa[i].value,
5983 return MHD_NO;
5984 break;
5985#endif /* HTTPS_SUPPORT */
5986 /* all options taking 'MHD_socket' */
5988 if (MHD_NO == parse_options (daemon,
5989 servaddr,
5990 opt,
5991 (MHD_socket) oa[i].value,
5993 return MHD_NO;
5994 break;
5995 /* all options taking 'int' */
5999 if (MHD_NO == parse_options (daemon,
6000 servaddr,
6001 opt,
6002 (int) oa[i].value,
6004 return MHD_NO;
6005 break;
6006 /* all options taking one pointer */
6014 case MHD_OPTION_ARRAY:
6017 if (MHD_NO == parse_options (daemon,
6018 servaddr,
6019 opt,
6020 oa[i].ptr_value,
6022 return MHD_NO;
6023 break;
6024 /* all options taking two pointers */
6031 if (MHD_NO == parse_options (daemon,
6032 servaddr,
6033 opt,
6034 (void *) oa[i].value,
6035 oa[i].ptr_value,
6037 return MHD_NO;
6038 break;
6039 /* options taking size_t-number followed by pointer */
6041 if (MHD_NO == parse_options (daemon,
6042 servaddr,
6043 opt,
6044 (size_t) oa[i].value,
6045 oa[i].ptr_value,
6047 return MHD_NO;
6048 break;
6049 default:
6050 return MHD_NO;
6051 }
6052 i++;
6053 }
6054 break;
6056 daemon->unescape_callback = va_arg (ap,
6058 daemon->unescape_callback_cls = va_arg (ap,
6059 void *);
6060 break;
6061#ifdef HTTPS_SUPPORT
6063#if GNUTLS_VERSION_MAJOR >= 3
6064 daemon->cred_callback = va_arg (ap,
6066 daemon->cred_callback_cls = va_arg (ap,
6067 void *);
6068 break;
6069#else
6070 MHD_DLOG (daemon,
6071 _ (
6072 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
6073 opt);
6074 return MHD_NO;
6075#endif
6076#endif /* HTTPS_SUPPORT */
6078 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6079 daemon->sigpipe_blocked = ( (va_arg (ap,
6080 int)) != 0);
6081 else
6082 {
6083 (void) va_arg (ap,
6084 int);
6085 }
6086 break;
6088#ifdef HTTPS_SUPPORT
6089 daemon->disable_alpn = (va_arg (ap,
6090 int) != 0);
6091#else /* ! HTTPS_SUPPORT */
6092 (void) va_arg (ap, int);
6093#endif /* ! HTTPS_SUPPORT */
6094#ifdef HAVE_MESSAGES
6095 if (0 == (daemon->options & MHD_USE_TLS))
6096 MHD_DLOG (daemon,
6097 _ ("MHD HTTPS option %d passed to MHD " \
6098 "but MHD_USE_TLS not set.\n"),
6099 (int) opt);
6100#endif /* HAVE_MESSAGES */
6101 break;
6102 default:
6103#ifdef HAVE_MESSAGES
6104 if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
6105 (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
6106 (opt == MHD_OPTION_HTTPS_MEM_TRUST) ||
6108 {
6109 MHD_DLOG (daemon,
6110 _ (
6111 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
6112 opt);
6113 }
6114 else
6115 {
6116 MHD_DLOG (daemon,
6117 _ (
6118 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
6119 opt);
6120 }
6121#endif
6122 return MHD_NO;
6123 }
6124 }
6125 return MHD_YES;
6126}
6127
6128
6129#ifdef EPOLL_SUPPORT
6130static int
6131setup_epoll_fd (struct MHD_Daemon *daemon)
6132{
6133 int fd;
6134
6135#ifndef HAVE_MESSAGES
6136 (void) daemon; /* Mute compiler warning. */
6137#endif /* ! HAVE_MESSAGES */
6138
6139#ifdef USE_EPOLL_CREATE1
6140 fd = epoll_create1 (EPOLL_CLOEXEC);
6141#else /* ! USE_EPOLL_CREATE1 */
6142 fd = epoll_create (MAX_EVENTS);
6143#endif /* ! USE_EPOLL_CREATE1 */
6144 if (MHD_INVALID_SOCKET == fd)
6145 {
6146#ifdef HAVE_MESSAGES
6147 MHD_DLOG (daemon,
6148 _ ("Call to epoll_create1 failed: %s\n"),
6150#endif
6151 return MHD_INVALID_SOCKET;
6152 }
6153#if ! defined(USE_EPOLL_CREATE1)
6155 {
6156#ifdef HAVE_MESSAGES
6157 MHD_DLOG (daemon,
6158 _ ("Failed to set noninheritable mode on epoll FD.\n"));
6159#endif
6160 }
6161#endif /* ! USE_EPOLL_CREATE1 */
6162 return fd;
6163}
6164
6165
6174static enum MHD_Result
6175setup_epoll_to_listen (struct MHD_Daemon *daemon)
6176{
6177 struct epoll_event event;
6178 MHD_socket ls;
6179
6180 mhd_assert (0 != (daemon->options & MHD_USE_EPOLL));
6182 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
6183 (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) || \
6184 MHD_ITC_IS_VALID_ (daemon->itc) );
6185 daemon->epoll_fd = setup_epoll_fd (daemon);
6186 if (-1 == daemon->epoll_fd)
6187 return MHD_NO;
6188#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6189 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
6190 {
6191 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
6192 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
6193 return MHD_NO;
6194 }
6195#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6196 if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
6197 (! daemon->was_quiesced) )
6198 {
6199 event.events = EPOLLIN;
6200 event.data.ptr = daemon;
6201 if (0 != epoll_ctl (daemon->epoll_fd,
6202 EPOLL_CTL_ADD,
6203 ls,
6204 &event))
6205 {
6206#ifdef HAVE_MESSAGES
6207 MHD_DLOG (daemon,
6208 _ ("Call to epoll_ctl failed: %s\n"),
6210#endif
6211 return MHD_NO;
6212 }
6213 daemon->listen_socket_in_epoll = true;
6214 }
6215
6216 if (MHD_ITC_IS_VALID_ (daemon->itc))
6217 {
6218 event.events = EPOLLIN;
6219 event.data.ptr = (void *) epoll_itc_marker;
6220 if (0 != epoll_ctl (daemon->epoll_fd,
6221 EPOLL_CTL_ADD,
6222 MHD_itc_r_fd_ (daemon->itc),
6223 &event))
6224 {
6225#ifdef HAVE_MESSAGES
6226 MHD_DLOG (daemon,
6227 _ ("Call to epoll_ctl failed: %s\n"),
6229#endif
6230 return MHD_NO;
6231 }
6232 }
6233 return MHD_YES;
6234}
6235
6236
6237#endif
6238
6239
6261struct MHD_Daemon *
6262MHD_start_daemon_va (unsigned int flags,
6263 uint16_t port,
6265 void *apc_cls,
6267 void *dh_cls,
6268 va_list ap)
6269{
6270 const MHD_SCKT_OPT_BOOL_ on = 1;
6271 struct MHD_Daemon *daemon;
6273 struct sockaddr_in servaddr4;
6274#if HAVE_INET6
6275 struct sockaddr_in6 servaddr6;
6276#endif
6277 const struct sockaddr *servaddr = NULL;
6278 socklen_t addrlen;
6279#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6280 unsigned int i;
6281#endif
6282 enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
6283 enum MHD_FLAG *pflags;
6284
6286 eflags = (enum MHD_FLAG) flags;
6287 pflags = &eflags;
6288#ifndef HAVE_INET6
6289 if (0 != (*pflags & MHD_USE_IPv6))
6290 return NULL;
6291#endif
6292#ifndef HAVE_POLL
6293 if (0 != (*pflags & MHD_USE_POLL))
6294 return NULL;
6295#endif
6296#ifndef EPOLL_SUPPORT
6297 if (0 != (*pflags & MHD_USE_EPOLL))
6298 return NULL;
6299#endif /* ! EPOLL_SUPPORT */
6300#ifndef HTTPS_SUPPORT
6301 if (0 != (*pflags & MHD_USE_TLS))
6302 return NULL;
6303#endif /* ! HTTPS_SUPPORT */
6304#ifndef TCP_FASTOPEN
6305 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6306 return NULL;
6307#endif
6308 if (0 != (*pflags & MHD_ALLOW_UPGRADE))
6309 {
6310#ifdef UPGRADE_SUPPORT
6311 *pflags |= MHD_ALLOW_SUSPEND_RESUME;
6312#else /* ! UPGRADE_SUPPORT */
6313 return NULL;
6314#endif /* ! UPGRADE_SUPPORT */
6315 }
6316 if (NULL == dh)
6317 return NULL;
6318
6319 /* Check for invalid combinations of flags. */
6320 if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
6321 ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags
6322 &
6324 ||
6325 ((0 != (*pflags & MHD_USE_POLL)) &&
6326 (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
6328 ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL
6329 | MHD_USE_EPOLL)))) )
6330 return NULL;
6331
6332 if (0 != (*pflags & MHD_USE_AUTO))
6333 {
6334 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6335 {
6336 /* Thread per connection with internal polling thread. */
6337#ifdef HAVE_POLL
6338 *pflags |= MHD_USE_POLL;
6339#else /* ! HAVE_POLL */
6340 /* use select() - do not modify flags */
6341#endif /* ! HAVE_POLL */
6342 }
6343 else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
6344 {
6345 /* Internal polling thread. */
6346#if defined(EPOLL_SUPPORT)
6347 *pflags |= MHD_USE_EPOLL;
6348#elif defined(HAVE_POLL)
6349 *pflags |= MHD_USE_POLL;
6350#else /* !HAVE_POLL && !EPOLL_SUPPORT */
6351 /* use select() - do not modify flags */
6352#endif /* !HAVE_POLL && !EPOLL_SUPPORT */
6353 }
6354 else
6355 {
6356 /* Internal threads are not used - "external" polling mode. */
6357#if defined(EPOLL_SUPPORT)
6358 *pflags |= MHD_USE_EPOLL;
6359#else /* ! EPOLL_SUPPORT */
6360 /* use select() - do not modify flags */
6361#endif /* ! EPOLL_SUPPORT */
6362 }
6363 }
6364
6365 if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
6366 return NULL;
6367#ifdef EPOLL_SUPPORT
6368 daemon->epoll_fd = -1;
6369#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6370 daemon->epoll_upgrade_fd = -1;
6371#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6372#endif
6373 /* try to open listen socket */
6374#ifdef HTTPS_SUPPORT
6375 daemon->priority_cache = NULL;
6376 if (0 != (*pflags & MHD_USE_TLS))
6377 {
6378 gnutls_priority_init (&daemon->priority_cache,
6379 "@SYSTEM",
6380 NULL);
6381 }
6382#endif /* HTTPS_SUPPORT */
6383 daemon->listen_fd = MHD_INVALID_SOCKET;
6384 daemon->listen_is_unix = _MHD_NO;
6385 daemon->listening_address_reuse = 0;
6386 daemon->options = *pflags;
6387 pflags = &daemon->options;
6388 daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 :
6389 0;
6390 daemon->port = port;
6391 daemon->apc = apc;
6392 daemon->apc_cls = apc_cls;
6393 daemon->default_handler = dh;
6394 daemon->default_handler_cls = dh_cls;
6395 daemon->connections = 0;
6400 daemon->connection_timeout = 0; /* no timeout */
6401 MHD_itc_set_invalid_ (daemon->itc);
6402#ifdef SOMAXCONN
6403 daemon->listen_backlog_size = SOMAXCONN;
6404#else /* !SOMAXCONN */
6405 daemon->listen_backlog_size = 511; /* should be safe value */
6406#endif /* !SOMAXCONN */
6407#ifdef HAVE_MESSAGES
6408 daemon->custom_error_log = &MHD_default_logger_;
6409 daemon->custom_error_log_cls = stderr;
6410#endif
6411#ifndef MHD_WINSOCK_SOCKETS
6412 daemon->sigpipe_blocked = false;
6413#else /* MHD_WINSOCK_SOCKETS */
6414 /* There is no SIGPIPE on W32, nothing to block. */
6415 daemon->sigpipe_blocked = true;
6416#endif /* _WIN32 && ! __CYGWIN__ */
6417
6418 if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
6419 (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
6420 {
6421 /* Log warning message later, when log parameters are processes */
6423 }
6424 if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
6425 *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
6426 else
6427 {
6428#ifdef HAVE_LISTEN_SHUTDOWN
6429 if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
6430#endif
6431 *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
6432 }
6433#ifdef DAUTH_SUPPORT
6434 daemon->digest_auth_rand_size = 0;
6435 daemon->digest_auth_random = NULL;
6436 daemon->nonce_nc_size = 4; /* tiny */
6437#endif
6438#ifdef HTTPS_SUPPORT
6439 if (0 != (*pflags & MHD_USE_TLS))
6440 {
6441 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
6442 }
6443#endif /* HTTPS_SUPPORT */
6444
6445
6446 if (MHD_NO == parse_options_va (daemon,
6447 &servaddr,
6448 ap))
6449 {
6450#ifdef HTTPS_SUPPORT
6451 if ( (0 != (*pflags & MHD_USE_TLS)) &&
6452 (NULL != daemon->priority_cache) )
6453 gnutls_priority_deinit (daemon->priority_cache);
6454#endif /* HTTPS_SUPPORT */
6455 free (daemon);
6456 return NULL;
6457 }
6458
6459#ifdef HAVE_MESSAGES
6460 if ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) &&
6461 (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD)) )
6462 {
6463 MHD_DLOG (daemon,
6464 _ (
6465 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
6466 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
6467 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
6468 }
6469#endif
6470
6471 if ( (NULL != daemon->notify_completed) &&
6472 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
6473 *pflags |= MHD_USE_ITC; /* requires ITC */
6474
6475#ifndef NDEBUG
6476#ifdef HAVE_MESSAGES
6477 MHD_DLOG (daemon,
6478 _ ("Using debug build of libmicrohttpd.\n") );
6479#endif /* HAVE_MESSAGES */
6480#endif /* ! NDEBUG */
6481
6482 if ( (0 != (*pflags & MHD_USE_ITC))
6483#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6484 && (0 == daemon->worker_pool_size)
6485#endif
6486 )
6487 {
6488 if (! MHD_itc_init_ (daemon->itc))
6489 {
6490#ifdef HAVE_MESSAGES
6491 MHD_DLOG (daemon,
6492 _ ("Failed to create inter-thread communication channel: %s\n"),
6493 MHD_itc_last_strerror_ ());
6494#endif
6495#ifdef HTTPS_SUPPORT
6496 if (NULL != daemon->priority_cache)
6497 gnutls_priority_deinit (daemon->priority_cache);
6498#endif /* HTTPS_SUPPORT */
6499 free (daemon);
6500 return NULL;
6501 }
6502 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6503 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
6504 NULL)) )
6505 {
6506#ifdef HAVE_MESSAGES
6507 MHD_DLOG (daemon,
6508 _ (
6509 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
6510#endif
6511 MHD_itc_destroy_chk_ (daemon->itc);
6512#ifdef HTTPS_SUPPORT
6513 if (NULL != daemon->priority_cache)
6514 gnutls_priority_deinit (daemon->priority_cache);
6515#endif /* HTTPS_SUPPORT */
6516 free (daemon);
6517 return NULL;
6518 }
6519 }
6520
6521#ifdef DAUTH_SUPPORT
6522 if (daemon->nonce_nc_size > 0)
6523 {
6524 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
6525 / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
6526 {
6527#ifdef HAVE_MESSAGES
6528 MHD_DLOG (daemon,
6529 _ ("Specified value for NC_SIZE too large.\n"));
6530#endif
6531#ifdef HTTPS_SUPPORT
6532 if (0 != (*pflags & MHD_USE_TLS))
6533 gnutls_priority_deinit (daemon->priority_cache);
6534#endif /* HTTPS_SUPPORT */
6535 free (daemon);
6536 return NULL;
6537 }
6538 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
6539 if (NULL == daemon->nnc)
6540 {
6541#ifdef HAVE_MESSAGES
6542 MHD_DLOG (daemon,
6543 _ ("Failed to allocate memory for nonce-nc map: %s\n"),
6544 MHD_strerror_ (errno));
6545#endif
6546#ifdef HTTPS_SUPPORT
6547 if (0 != (*pflags & MHD_USE_TLS))
6548 gnutls_priority_deinit (daemon->priority_cache);
6549#endif /* HTTPS_SUPPORT */
6550 free (daemon);
6551 return NULL;
6552 }
6553 }
6554
6555#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6556 if (! MHD_mutex_init_ (&daemon->nnc_lock))
6557 {
6558#ifdef HAVE_MESSAGES
6559 MHD_DLOG (daemon,
6560 _ ("MHD failed to initialize nonce-nc mutex.\n"));
6561#endif
6562#ifdef HTTPS_SUPPORT
6563 if (0 != (*pflags & MHD_USE_TLS))
6564 gnutls_priority_deinit (daemon->priority_cache);
6565#endif /* HTTPS_SUPPORT */
6566 free (daemon->nnc);
6567 free (daemon);
6568 return NULL;
6569 }
6570#endif
6571#endif
6572
6573 /* Thread polling currently works only with internal select thread mode */
6574#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6575 if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
6576 (daemon->worker_pool_size > 0) )
6577 {
6578#ifdef HAVE_MESSAGES
6579 MHD_DLOG (daemon,
6580 _ (
6581 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6582#endif
6583 goto free_and_fail;
6584 }
6585#endif
6586 if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
6587 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6588 {
6589 /* try to open listen socket */
6590 int domain;
6591
6592#ifdef HAVE_INET6
6593 domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6594#else /* ! HAVE_INET6 */
6595 if (*pflags & MHD_USE_IPv6)
6596 goto free_and_fail;
6597 domain = PF_INET;
6598#endif /* ! HAVE_INET6 */
6599
6600 listen_fd = MHD_socket_create_listen_ (domain);
6601 if (MHD_INVALID_SOCKET == listen_fd)
6602 {
6603#ifdef HAVE_MESSAGES
6604 MHD_DLOG (daemon,
6605 _ ("Failed to create socket for listening: %s\n"),
6607#endif
6608 goto free_and_fail;
6609 }
6610
6611 /* Apply the socket options according to listening_address_reuse. */
6612 if (0 == daemon->listening_address_reuse)
6613 {
6614#ifndef MHD_WINSOCK_SOCKETS
6615 /* No user requirement, use "traditional" default SO_REUSEADDR
6616 * on non-W32 platforms, and do not fail if it doesn't work.
6617 * Don't use it on W32, because on W32 it will allow multiple
6618 * bind to the same address:port, like SO_REUSEPORT on others. */
6619 if (0 > setsockopt (listen_fd,
6620 SOL_SOCKET,
6621 SO_REUSEADDR,
6622 (void*) &on, sizeof (on)))
6623 {
6624#ifdef HAVE_MESSAGES
6625 MHD_DLOG (daemon,
6626 _ ("setsockopt failed: %s\n"),
6628#endif
6629 }
6630#endif /* ! MHD_WINSOCK_SOCKETS */
6631 }
6632 else if (daemon->listening_address_reuse > 0)
6633 {
6634 /* User requested to allow reusing listening address:port. */
6635#ifndef MHD_WINSOCK_SOCKETS
6636 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
6637 * it doesn't work. */
6638 if (0 > setsockopt (listen_fd,
6639 SOL_SOCKET,
6640 SO_REUSEADDR,
6641 (void*) &on, sizeof (on)))
6642 {
6643#ifdef HAVE_MESSAGES
6644 MHD_DLOG (daemon,
6645 _ ("setsockopt failed: %s\n"),
6647#endif
6648 }
6649#endif /* ! MHD_WINSOCK_SOCKETS */
6650 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
6651 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
6652 */
6653 /* SO_REUSEADDR on W32 has the same semantics
6654 as SO_REUSEPORT on BSD/Linux */
6655#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6656 if (0 > setsockopt (listen_fd,
6657 SOL_SOCKET,
6658#ifndef MHD_WINSOCK_SOCKETS
6659 SO_REUSEPORT,
6660#else /* MHD_WINSOCK_SOCKETS */
6661 SO_REUSEADDR,
6662#endif /* MHD_WINSOCK_SOCKETS */
6663 (void *) &on,
6664 sizeof (on)))
6665 {
6666#ifdef HAVE_MESSAGES
6667 MHD_DLOG (daemon,
6668 _ ("setsockopt failed: %s\n"),
6670#endif
6671 goto free_and_fail;
6672 }
6673#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6674 /* we're supposed to allow address:port re-use, but
6675 on this platform we cannot; fail hard */
6676#ifdef HAVE_MESSAGES
6677 MHD_DLOG (daemon,
6678 _ (
6679 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6680#endif
6681 goto free_and_fail;
6682#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6683 }
6684 else /* if (daemon->listening_address_reuse < 0) */
6685 {
6686 /* User requested to disallow reusing listening address:port.
6687 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
6688 * is used and Solaris with SO_EXCLBIND.
6689 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
6690 * or setsockopt fails.
6691 */
6692#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6693 (defined(__sun) && defined(SO_EXCLBIND))
6694 if (0 > setsockopt (listen_fd,
6695 SOL_SOCKET,
6696#ifdef SO_EXCLUSIVEADDRUSE
6697 SO_EXCLUSIVEADDRUSE,
6698#else /* SO_EXCLBIND */
6699 SO_EXCLBIND,
6700#endif /* SO_EXCLBIND */
6701 (void *) &on,
6702 sizeof (on)))
6703 {
6704#ifdef HAVE_MESSAGES
6705 MHD_DLOG (daemon,
6706 _ ("setsockopt failed: %s\n"),
6708#endif
6709 goto free_and_fail;
6710 }
6711#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
6712#ifdef HAVE_MESSAGES
6713 MHD_DLOG (daemon,
6714 _ (
6715 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6716#endif
6717 goto free_and_fail;
6718#endif /* MHD_WINSOCK_SOCKETS */
6719 }
6720
6721 /* check for user supplied sockaddr */
6722#if HAVE_INET6
6723 if (0 != (*pflags & MHD_USE_IPv6))
6724 addrlen = sizeof (struct sockaddr_in6);
6725 else
6726#endif
6727 addrlen = sizeof (struct sockaddr_in);
6728 if (NULL == servaddr)
6729 {
6730#if HAVE_INET6
6731 if (0 != (*pflags & MHD_USE_IPv6))
6732 {
6733#ifdef IN6ADDR_ANY_INIT
6734 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6735#endif
6736 memset (&servaddr6,
6737 0,
6738 sizeof (struct sockaddr_in6));
6739 servaddr6.sin6_family = AF_INET6;
6740 servaddr6.sin6_port = htons (port);
6741#ifdef IN6ADDR_ANY_INIT
6742 servaddr6.sin6_addr = static_in6any;
6743#endif
6744#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6745 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
6746#endif
6747 servaddr = (struct sockaddr *) &servaddr6;
6748 }
6749 else
6750#endif
6751 {
6752 memset (&servaddr4,
6753 0,
6754 sizeof (struct sockaddr_in));
6755 servaddr4.sin_family = AF_INET;
6756 servaddr4.sin_port = htons (port);
6757 if (0 != INADDR_ANY)
6758 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6759#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6760 servaddr4.sin_len = sizeof (struct sockaddr_in);
6761#endif
6762 servaddr = (struct sockaddr *) &servaddr4;
6763 }
6764 }
6765 daemon->listen_fd = listen_fd;
6766 if (0 != (*pflags & MHD_USE_IPv6))
6767 {
6768#ifdef IPPROTO_IPV6
6769#ifdef IPV6_V6ONLY
6770 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
6771 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
6772 and may also be missing on older POSIX systems; good luck if you have any of those,
6773 your IPv6 socket may then also bind against IPv4 anyway... */
6774 const MHD_SCKT_OPT_BOOL_ v6_only =
6775 (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
6776 if (0 > setsockopt (listen_fd,
6777 IPPROTO_IPV6, IPV6_V6ONLY,
6778 (const void *) &v6_only,
6779 sizeof (v6_only)))
6780 {
6781#ifdef HAVE_MESSAGES
6782 MHD_DLOG (daemon,
6783 _ ("setsockopt failed: %s\n"),
6785#endif
6786 }
6787#endif
6788#endif
6789 }
6790 if (-1 == bind (listen_fd, servaddr, addrlen))
6791 {
6792#ifdef HAVE_MESSAGES
6793 MHD_DLOG (daemon,
6794 _ ("Failed to bind to port %u: %s\n"),
6795 (unsigned int) port,
6797#endif
6798 MHD_socket_close_chk_ (listen_fd);
6799 goto free_and_fail;
6800 }
6801#ifdef TCP_FASTOPEN
6802 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6803 {
6804 if (0 == daemon->fastopen_queue_size)
6805 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6806 if (0 != setsockopt (listen_fd,
6807 IPPROTO_TCP,
6808 TCP_FASTOPEN,
6809 (const void*) &daemon->fastopen_queue_size,
6810 sizeof (daemon->fastopen_queue_size)))
6811 {
6812#ifdef HAVE_MESSAGES
6813 MHD_DLOG (daemon,
6814 _ ("setsockopt failed: %s\n"),
6816#endif
6817 }
6818 }
6819#endif
6820 if (listen (listen_fd,
6821 daemon->listen_backlog_size) < 0)
6822 {
6823#ifdef HAVE_MESSAGES
6824 MHD_DLOG (daemon,
6825 _ ("Failed to listen for connections: %s\n"),
6827#endif
6828 MHD_socket_close_chk_ (listen_fd);
6829 goto free_and_fail;
6830 }
6831 }
6832 else
6833 {
6834 listen_fd = daemon->listen_fd;
6835 }
6836
6837#ifdef HAVE_GETSOCKNAME
6838 if ( (0 == daemon->port) &&
6839 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6840 { /* Get port number. */
6841 struct sockaddr_storage bindaddr;
6842
6843 memset (&bindaddr,
6844 0,
6845 sizeof (struct sockaddr_storage));
6846 addrlen = sizeof (struct sockaddr_storage);
6847#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6848 bindaddr.ss_len = addrlen;
6849#endif
6850 if (0 != getsockname (listen_fd,
6851 (struct sockaddr *) &bindaddr,
6852 &addrlen))
6853 {
6854#ifdef HAVE_MESSAGES
6855 MHD_DLOG (daemon,
6856 _ ("Failed to get listen port number: %s\n"),
6858#endif /* HAVE_MESSAGES */
6859 }
6860#ifdef MHD_POSIX_SOCKETS
6861 else if (sizeof (bindaddr) < addrlen)
6862 {
6863 /* should be impossible with `struct sockaddr_storage` */
6864#ifdef HAVE_MESSAGES
6865 MHD_DLOG (daemon,
6866 _ (
6867 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6868#endif /* HAVE_MESSAGES */
6869 }
6870#ifndef __linux__
6871 else if (0 == addrlen)
6872 {
6873 /* Many non-Linux-based platforms return zero addrlen
6874 * for AF_UNIX sockets */
6875 daemon->port = 0; /* special value for UNIX domain sockets */
6876 }
6877#endif /* __linux__ */
6878#endif /* MHD_POSIX_SOCKETS */
6879 else
6880 {
6881 switch (bindaddr.ss_family)
6882 {
6883 case AF_INET:
6884 {
6885 struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
6886
6887 daemon->port = ntohs (s4->sin_port);
6888 break;
6889 }
6890#ifdef HAVE_INET6
6891 case AF_INET6:
6892 {
6893 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
6894
6895 daemon->port = ntohs (s6->sin6_port);
6896 mhd_assert (0 != (*pflags & MHD_USE_IPv6));
6897 break;
6898 }
6899#endif /* HAVE_INET6 */
6900#ifdef AF_UNIX
6901 case AF_UNIX:
6902 daemon->port = 0; /* special value for UNIX domain sockets */
6903 break;
6904#endif
6905 default:
6906#ifdef HAVE_MESSAGES
6907 MHD_DLOG (daemon,
6908 _ ("Unknown address family!\n"));
6909#endif
6910 daemon->port = 0; /* ugh */
6911 break;
6912 }
6913 }
6914 }
6915#endif /* HAVE_GETSOCKNAME */
6916 if ( (MHD_INVALID_SOCKET != listen_fd) &&
6917 (! MHD_socket_nonblocking_ (listen_fd)) )
6918 {
6919#ifdef HAVE_MESSAGES
6920 MHD_DLOG (daemon,
6921 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
6923#endif
6924 if (0 != (*pflags & MHD_USE_EPOLL)
6925#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6926 || (daemon->worker_pool_size > 0)
6927#endif
6928 )
6929 {
6930 /* Accept must be non-blocking. Multiple children may wake up
6931 * to handle a new connection, but only one will win the race.
6932 * The others must immediately return. */
6933 MHD_socket_close_chk_ (listen_fd);
6934 goto free_and_fail;
6935 }
6936 }
6937 if ( (MHD_INVALID_SOCKET != listen_fd) &&
6938 (! MHD_SCKT_FD_FITS_FDSET_ (listen_fd,
6939 NULL)) &&
6940 (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
6941 {
6942#ifdef HAVE_MESSAGES
6943 MHD_DLOG (daemon,
6944 _ ("Listen socket descriptor (%d) is not " \
6945 "less than FD_SETSIZE (%d).\n"),
6946 (int) listen_fd,
6947 (int) FD_SETSIZE);
6948#endif
6949 MHD_socket_close_chk_ (listen_fd);
6950 goto free_and_fail;
6951 }
6952
6953#ifdef EPOLL_SUPPORT
6954 if ( (0 != (*pflags & MHD_USE_EPOLL))
6955#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6956 && (0 == daemon->worker_pool_size)
6957#endif
6958 )
6959 {
6960 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6961 {
6962#ifdef HAVE_MESSAGES
6963 MHD_DLOG (daemon,
6964 _ (
6965 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
6966#endif
6967 goto free_and_fail;
6968 }
6969 if (MHD_NO == setup_epoll_to_listen (daemon))
6970 goto free_and_fail;
6971 }
6972#endif /* EPOLL_SUPPORT */
6973
6974#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6976 {
6977#ifdef HAVE_MESSAGES
6978 MHD_DLOG (daemon,
6979 _ ("MHD failed to initialize IP connection limit mutex.\n"));
6980#endif
6981 if (MHD_INVALID_SOCKET != listen_fd)
6982 MHD_socket_close_chk_ (listen_fd);
6983 goto free_and_fail;
6984 }
6986 {
6987#ifdef HAVE_MESSAGES
6988 MHD_DLOG (daemon,
6989 _ ("MHD failed to initialize IP connection limit mutex.\n"));
6990#endif
6991#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6993#endif
6994 if (MHD_INVALID_SOCKET != listen_fd)
6995 MHD_socket_close_chk_ (listen_fd);
6996 goto free_and_fail;
6997 }
6998#endif
6999
7000#ifdef HTTPS_SUPPORT
7001 /* initialize HTTPS daemon certificate aspects & send / recv functions */
7002 if ( (0 != (*pflags & MHD_USE_TLS)) &&
7003 (0 != MHD_TLS_init (daemon)) )
7004 {
7005#ifdef HAVE_MESSAGES
7006 MHD_DLOG (daemon,
7007 _ ("Failed to initialize TLS support.\n"));
7008#endif
7009 if (MHD_INVALID_SOCKET != listen_fd)
7010 MHD_socket_close_chk_ (listen_fd);
7011#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7014#endif
7015 goto free_and_fail;
7016 }
7017#endif /* HTTPS_SUPPORT */
7018#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7019 /* Start threads if requested by parameters */
7020 if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
7021 {
7022 /* Internal thread (or threads) is used.
7023 * Make sure that MHD will be able to communicate with threads. */
7024 /* If using a thread pool ITC will be initialised later
7025 * for each individual worker thread. */
7026#ifdef HAVE_LISTEN_SHUTDOWN
7027 mhd_assert ((1 < daemon->worker_pool_size) || \
7028 (MHD_ITC_IS_VALID_ (daemon->itc)) || \
7029 (MHD_INVALID_SOCKET != daemon->listen_fd));
7030#else /* ! HAVE_LISTEN_SHUTDOWN */
7031 mhd_assert ((1 < daemon->worker_pool_size) || \
7032 (MHD_ITC_IS_VALID_ (daemon->itc)));
7033#endif /* ! HAVE_LISTEN_SHUTDOWN */
7034 if (0 == daemon->worker_pool_size)
7035 {
7036 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
7037 {
7038#ifdef HAVE_MESSAGES
7039 MHD_DLOG (daemon,
7040 _ ("Failed to initialise mutex.\n"));
7041#endif
7044 if (MHD_INVALID_SOCKET != listen_fd)
7045 MHD_socket_close_chk_ (listen_fd);
7046 goto free_and_fail;
7047 }
7048 if (! MHD_create_named_thread_ (&daemon->pid,
7049 (*pflags
7051 "MHD-listen" : "MHD-single",
7052 daemon->thread_stack_size,
7054 daemon) )
7055 {
7056#ifdef HAVE_MESSAGES
7057 MHD_DLOG (daemon,
7058 _ ("Failed to create listen thread: %s\n"),
7059 MHD_strerror_ (errno));
7060#endif
7061 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7064 if (MHD_INVALID_SOCKET != listen_fd)
7065 MHD_socket_close_chk_ (listen_fd);
7066 goto free_and_fail;
7067 }
7068 }
7069 else /* 0 < daemon->worker_pool_size */
7070 {
7071 /* Coarse-grained count of connections per thread (note error
7072 * due to integer division). Also keep track of how many
7073 * connections are leftover after an equal split. */
7074 unsigned int conns_per_thread = daemon->connection_limit
7075 / daemon->worker_pool_size;
7076 unsigned int leftover_conns = daemon->connection_limit
7077 % daemon->worker_pool_size;
7078
7079 mhd_assert (2 <= daemon->worker_pool_size);
7080 i = 0; /* we need this in case fcntl or malloc fails */
7081
7082 /* Allocate memory for pooled objects */
7083 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
7084 * daemon->worker_pool_size);
7085 if (NULL == daemon->worker_pool)
7086 goto thread_failed;
7087
7088 /* Start the workers in the pool */
7089 for (i = 0; i < daemon->worker_pool_size; ++i)
7090 {
7091 /* Create copy of the Daemon object for each worker */
7092 struct MHD_Daemon *d = &daemon->worker_pool[i];
7093
7094 memcpy (d, daemon, sizeof (struct MHD_Daemon));
7095 /* Adjust polling params for worker daemons; note that memcpy()
7096 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
7097 the worker threads. */
7098 d->master = daemon;
7099 d->worker_pool_size = 0;
7100 d->worker_pool = NULL;
7101 if (! MHD_mutex_init_ (&d->new_connections_mutex))
7102 {
7103 #ifdef HAVE_MESSAGES
7104 MHD_DLOG (daemon,
7105 _ ("Failed to initialise mutex.\n"));
7106 #endif
7107 goto thread_failed;
7108 }
7109 if (0 != (*pflags & MHD_USE_ITC))
7110 {
7111 if (! MHD_itc_init_ (d->itc))
7112 {
7113#ifdef HAVE_MESSAGES
7114 MHD_DLOG (daemon,
7115 _ (
7116 "Failed to create worker inter-thread communication channel: %s\n"),
7117 MHD_itc_last_strerror_ () );
7118#endif
7119 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7120 goto thread_failed;
7121 }
7122 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
7123 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
7124 NULL)) )
7125 {
7126#ifdef HAVE_MESSAGES
7127 MHD_DLOG (daemon,
7128 _ (
7129 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
7130#endif
7131 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7133 goto thread_failed;
7134 }
7135 }
7136 else
7137 MHD_itc_set_invalid_ (d->itc);
7138
7139#ifdef HAVE_LISTEN_SHUTDOWN
7140 mhd_assert ((MHD_ITC_IS_VALID_ (d->itc)) || \
7142#else /* ! HAVE_LISTEN_SHUTDOWN */
7143 mhd_assert (MHD_ITC_IS_VALID_ (d->itc));
7144#endif /* ! HAVE_LISTEN_SHUTDOWN */
7145
7146 /* Divide available connections evenly amongst the threads.
7147 * Thread indexes in [0, leftover_conns) each get one of the
7148 * leftover connections. */
7149 d->connection_limit = conns_per_thread;
7150 if (i < leftover_conns)
7151 ++d->connection_limit;
7152#ifdef EPOLL_SUPPORT
7153 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
7154 (MHD_NO == setup_epoll_to_listen (d)) )
7155 {
7156 if (MHD_ITC_IS_VALID_ (d->itc))
7158 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7159 goto thread_failed;
7160 }
7161#endif
7162 /* Must init cleanup connection mutex for each worker */
7164 {
7165#ifdef HAVE_MESSAGES
7166 MHD_DLOG (daemon,
7167 _ ("MHD failed to initialize cleanup connection mutex.\n"));
7168#endif
7169 if (MHD_ITC_IS_VALID_ (d->itc))
7171 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7172 goto thread_failed;
7173 }
7174
7175 /* Spawn the worker thread */
7176 if (! MHD_create_named_thread_ (&d->pid,
7177 "MHD-worker",
7178 daemon->thread_stack_size,
7180 d))
7181 {
7182#ifdef HAVE_MESSAGES
7183 MHD_DLOG (daemon,
7184 _ ("Failed to create pool thread: %s\n"),
7185 MHD_strerror_ (errno));
7186#endif
7187 /* Free memory for this worker; cleanup below handles
7188 * all previously-created workers. */
7190 if (MHD_ITC_IS_VALID_ (d->itc))
7192 MHD_mutex_destroy_chk_ (&d->new_connections_mutex);
7193 goto thread_failed;
7194 }
7195 }
7196 }
7197 }
7198 else
7199 { /* Daemon without internal threads */
7200 if (! MHD_mutex_init_ (&daemon->new_connections_mutex))
7201 {
7202#ifdef HAVE_MESSAGES
7203 MHD_DLOG (daemon,
7204 _ ("Failed to initialise mutex.\n"));
7205#endif
7206 goto free_and_fail;
7207 }
7208 }
7209#endif
7210#ifdef HTTPS_SUPPORT
7211 /* API promises to never use the password after initialization,
7212 so we additionally NULL it here to not deref a dangling pointer. */
7213 daemon->https_key_password = NULL;
7214#endif /* HTTPS_SUPPORT */
7215
7216 return daemon;
7217
7218#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7219thread_failed:
7220 /* If no worker threads created, then shut down normally. Calling
7221 MHD_stop_daemon (as we do below) doesn't work here since it
7222 assumes a 0-sized thread pool means we had been in the default
7223 MHD_USE_INTERNAL_POLLING_THREAD mode. */
7224 if (0 == i)
7225 {
7229 if (NULL != daemon->worker_pool)
7230 free (daemon->worker_pool);
7231 goto free_and_fail;
7232 }
7233
7234 /* Shutdown worker threads we've already created. Pretend
7235 as though we had fully initialized our daemon, but
7236 with a smaller number of threads than had been
7237 requested. */
7238 daemon->worker_pool_size = i;
7239 MHD_stop_daemon (daemon);
7240 return NULL;
7241#endif
7242
7243free_and_fail:
7244 /* clean up basic memory state in 'daemon' and return NULL to
7245 indicate failure */
7246#ifdef EPOLL_SUPPORT
7247#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7248 if (daemon->upgrade_fd_in_epoll)
7249 {
7250 if (0 != epoll_ctl (daemon->epoll_fd,
7251 EPOLL_CTL_DEL,
7252 daemon->epoll_upgrade_fd,
7253 NULL))
7254 MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
7255 daemon->upgrade_fd_in_epoll = false;
7256 }
7257#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7258 if (-1 != daemon->epoll_fd)
7259 close (daemon->epoll_fd);
7260#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7261 if (-1 != daemon->epoll_upgrade_fd)
7262 close (daemon->epoll_upgrade_fd);
7263#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7264#endif /* EPOLL_SUPPORT */
7265#ifdef DAUTH_SUPPORT
7266 free (daemon->nnc);
7267#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7268 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
7269#endif
7270#endif
7271#ifdef HTTPS_SUPPORT
7272 if (0 != (*pflags & MHD_USE_TLS))
7273 {
7274 gnutls_priority_deinit (daemon->priority_cache);
7275 if (daemon->x509_cred)
7276 gnutls_certificate_free_credentials (daemon->x509_cred);
7277 if (daemon->psk_cred)
7278 gnutls_psk_free_server_credentials (daemon->psk_cred);
7279 }
7280#endif /* HTTPS_SUPPORT */
7281 if (MHD_ITC_IS_VALID_ (daemon->itc))
7282 MHD_itc_destroy_chk_ (daemon->itc);
7283 free (daemon);
7284 return NULL;
7285}
7286
7287
7296static void
7298{
7299 struct MHD_Connection *pos;
7300 const bool used_thr_p_c = (0 != (daemon->options
7302#ifdef UPGRADE_SUPPORT
7303 const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
7304#endif /* UPGRADE_SUPPORT */
7305#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7306 struct MHD_UpgradeResponseHandle *urh;
7307 struct MHD_UpgradeResponseHandle *urhn;
7308 const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
7309#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7310
7311#ifdef MHD_USE_THREADS
7312 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
7313 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
7314 MHD_thread_ID_match_current_ (daemon->pid) );
7315 mhd_assert (NULL == daemon->worker_pool);
7316#endif /* MHD_USE_THREADS */
7317 mhd_assert (daemon->shutdown);
7318
7319#ifdef MHD_USE_THREADS
7320/* Remove externally added new connections that are
7321 * not processed by the daemon thread. */
7322 while (NULL != (pos = daemon->new_connections_tail))
7323 {
7326 daemon->new_connections_tail,
7327 pos);
7328 new_connection_close_ (daemon, pos);
7329 }
7330#endif /* MHD_USE_THREADS */
7331
7332#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7333 /* give upgraded HTTPS connections a chance to finish */
7334 /* 'daemon->urh_head' is not used in thread-per-connection mode. */
7335 for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
7336 {
7337 mhd_assert (! used_thr_p_c);
7338 urhn = urh->prev;
7339 /* call generic forwarding function for passing data
7340 with chance to detect that application is done. */
7341 process_urh (urh);
7342 MHD_connection_finish_forward_ (urh->connection);
7343 urh->clean_ready = true;
7344 /* Resuming will move connection to cleanup list. */
7345 MHD_resume_connection (urh->connection);
7346 }
7347#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7348
7349 /* Give suspended connections a chance to resume to avoid
7350 running into the check for there not being any suspended
7351 connections left in case of a tight race with a recently
7352 resumed connection. */
7353 if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
7354 {
7355 daemon->resuming = true; /* Force check for pending resume. */
7357 }
7358 /* first, make sure all threads are aware of shutdown; need to
7359 traverse DLLs in peace... */
7360#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7362#endif
7363#ifdef UPGRADE_SUPPORT
7364 if (upg_allowed)
7365 {
7366 struct MHD_Connection *susp;
7367
7369 while (NULL != susp)
7370 {
7371 if (NULL == susp->urh) /* "Upgraded" connection? */
7372 MHD_PANIC (_ (
7373 "MHD_stop_daemon() called while we have suspended connections.\n"));
7374#ifdef HTTPS_SUPPORT
7375 else if (used_tls &&
7376 used_thr_p_c &&
7377 (! susp->urh->clean_ready) )
7378 shutdown (susp->urh->app.socket,
7379 SHUT_RDWR); /* Wake thread by shutdown of app socket. */
7380#endif /* HTTPS_SUPPORT */
7381 else
7382 {
7383#ifdef HAVE_MESSAGES
7384 if (! susp->urh->was_closed)
7385 MHD_DLOG (daemon,
7386 _ (
7387 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
7388#endif
7389 susp->urh->was_closed = true;
7390 /* If thread-per-connection is used, connection's thread
7391 * may still processing "upgrade" (exiting). */
7392 if (! used_thr_p_c)
7394 /* Do not use MHD_resume_connection() as mutex is
7395 * already locked. */
7396 susp->resuming = true;
7397 daemon->resuming = true;
7398 }
7399 susp = susp->prev;
7400 }
7401 }
7402 else /* This 'else' is combined with next 'if' */
7403#endif /* UPGRADE_SUPPORT */
7405 MHD_PANIC (_ (
7406 "MHD_stop_daemon() called while we have suspended connections.\n"));
7407#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
7408#ifdef MHD_USE_THREADS
7409 if (upg_allowed && used_tls && used_thr_p_c)
7410 {
7411 /* "Upgraded" threads may be running in parallel. Connection will not be
7412 * moved to the "cleanup list" until connection's thread finishes.
7413 * We must ensure that all "upgraded" connections are finished otherwise
7414 * connection may stay in "suspended" list and will not be cleaned. */
7415 for (pos = daemon->suspended_connections_tail; NULL != pos; pos = pos->prev)
7416 {
7417 /* Any connection found here is "upgraded" connection, normal suspended
7418 * connections are already removed from this list. */
7419 mhd_assert (NULL != pos->urh);
7420 if (! pos->thread_joined)
7421 {
7422 /* While "cleanup" list is not manipulated by "upgraded"
7423 * connection, "cleanup" mutex is required for call of
7424 * MHD_resume_connection() during finishing of "upgraded"
7425 * thread. */
7427 if (! MHD_join_thread_ (pos->pid.handle))
7428 MHD_PANIC (_ ("Failed to join a thread.\n"));
7429 pos->thread_joined = true;
7431 }
7432 }
7433 }
7434#endif /* MHD_USE_THREADS */
7435#endif
7436 for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
7437 {
7438 shutdown (pos->socket_fd,
7439 SHUT_RDWR);
7440#if MHD_WINSOCK_SOCKETS
7441 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
7442 (MHD_ITC_IS_VALID_ (daemon->itc)) &&
7443 (! MHD_itc_activate_ (daemon->itc, "e")) )
7444 MHD_PANIC (_ (
7445 "Failed to signal shutdown via inter-thread communication channel.\n"));
7446#endif
7447 }
7448
7449#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7450 /* now, collect per-connection threads */
7451 if (used_thr_p_c)
7452 {
7453 pos = daemon->connections_tail;
7454 while (NULL != pos)
7455 {
7456 if (! pos->thread_joined)
7457 {
7459 if (! MHD_join_thread_ (pos->pid.handle))
7460 MHD_PANIC (_ ("Failed to join a thread.\n"));
7462 pos->thread_joined = true;
7463 /* The thread may have concurrently modified the DLL,
7464 need to restart from the beginning */
7465 pos = daemon->connections_tail;
7466 continue;
7467 }
7468 pos = pos->prev;
7469 }
7470 }
7472#endif
7473
7474#ifdef UPGRADE_SUPPORT
7475 /* Finished threads with "upgraded" connections need to be moved
7476 * to cleanup list by resume_suspended_connections(). */
7477 /* "Upgraded" connections that were not closed explicitly by
7478 * application should be moved to cleanup list too. */
7479 if (upg_allowed)
7480 {
7481 daemon->resuming = true; /* Force check for pending resume. */
7483 }
7484#endif /* UPGRADE_SUPPORT */
7485
7487 /* now that we're alone, move everyone to cleanup */
7488 while (NULL != (pos = daemon->connections_tail))
7489 {
7490#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7491 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
7492 (! pos->thread_joined) )
7493 MHD_PANIC (_ ("Failed to join a thread.\n"));
7494#endif
7495 close_connection (pos);
7496 }
7498}
7499
7500
7507void
7509{
7510 MHD_socket fd;
7511#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7512 unsigned int i;
7513#endif
7514
7515 if (NULL == daemon)
7516 return;
7517 if ( (daemon->shutdown) && (NULL == daemon->master) )
7518 MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
7519 /* Slave daemons must be stopped by master daemon. */
7520 mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
7521
7522 daemon->shutdown = true;
7523 if (daemon->was_quiesced)
7524 fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
7525 else
7526 fd = daemon->listen_fd;
7527
7528#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7529 if (NULL != daemon->worker_pool)
7530 { /* Master daemon with worker pool. */
7533
7534 /* Let workers shutdown in parallel. */
7535 for (i = 0; i < daemon->worker_pool_size; ++i)
7536 {
7537 daemon->worker_pool[i].shutdown = true;
7538 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
7539 {
7540 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
7541 "e"))
7542 MHD_PANIC (_ (
7543 "Failed to signal shutdown via inter-thread communication channel.\n"));
7544 }
7545 else
7547 }
7548#ifdef HAVE_LISTEN_SHUTDOWN
7549 if (MHD_INVALID_SOCKET != fd)
7550 {
7551 (void) shutdown (fd,
7552 SHUT_RDWR);
7553 }
7554#endif /* HAVE_LISTEN_SHUTDOWN */
7555 for (i = 0; i < daemon->worker_pool_size; ++i)
7556 {
7558 }
7559 free (daemon->worker_pool);
7561#ifdef EPOLL_SUPPORT
7562 mhd_assert (-1 == daemon->epoll_fd);
7563#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7564 mhd_assert (-1 == daemon->epoll_upgrade_fd);
7565#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7566#endif /* EPOLL_SUPPORT */
7567 }
7568 else
7569#endif
7570 { /* Worker daemon or single daemon. */
7571#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7573 { /* Worker daemon or single daemon with internal thread(s). */
7575 /* Separate thread(s) is used for polling sockets. */
7576 if (MHD_ITC_IS_VALID_ (daemon->itc))
7577 {
7578 if (! MHD_itc_activate_ (daemon->itc,
7579 "e"))
7580 MHD_PANIC (_ (
7581 "Failed to signal shutdown via inter-thread communication channel.\n"));
7582 }
7583 else
7584 {
7585#ifdef HAVE_LISTEN_SHUTDOWN
7586 if (MHD_INVALID_SOCKET != fd)
7587 {
7588 if (NULL == daemon->master)
7589 (void) shutdown (fd,
7590 SHUT_RDWR);
7591 }
7592 else
7593#endif /* HAVE_LISTEN_SHUTDOWN */
7594 mhd_assert (false); /* Should never happen */
7595 }
7596
7597 if (! MHD_join_thread_ (daemon->pid.handle))
7598 {
7599 MHD_PANIC (_ ("Failed to join a thread.\n"));
7600 }
7601 /* close_all_connections() was called in daemon thread. */
7602 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7603 }
7604 else
7605#endif
7606 {
7607 /* No internal threads are used for polling sockets. */
7609#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7610 MHD_mutex_destroy_chk_ (&daemon->new_connections_mutex);
7611#endif /* MHD_USE_POSIX_THREADS || MHD_USE_W32_THREADS */
7612 }
7617#if defined(UPGRADE_SUPPORT) && defined (HTTPS_SUPPORT)
7618 mhd_assert (NULL == daemon->urh_head);
7619#endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
7620
7621 if (MHD_ITC_IS_VALID_ (daemon->itc))
7623
7624#ifdef EPOLL_SUPPORT
7625 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
7626 (-1 != daemon->epoll_fd) )
7627 MHD_socket_close_chk_ (daemon->epoll_fd);
7628#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7629 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
7630 (-1 != daemon->epoll_upgrade_fd) )
7631 MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
7632#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
7633#endif /* EPOLL_SUPPORT */
7634
7635#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7637#endif
7638 }
7639
7640 if (NULL == daemon->master)
7641 { /* Cleanup that should be done only one time in master/single daemon.
7642 * Do not perform this cleanup in worker daemons. */
7643
7644 if (MHD_INVALID_SOCKET != fd)
7646
7647 /* TLS clean up */
7648#ifdef HTTPS_SUPPORT
7649 if (daemon->have_dhparams)
7650 {
7651 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
7652 daemon->have_dhparams = false;
7653 }
7654 if (0 != (daemon->options & MHD_USE_TLS))
7655 {
7656 gnutls_priority_deinit (daemon->priority_cache);
7657 if (daemon->x509_cred)
7658 gnutls_certificate_free_credentials (daemon->x509_cred);
7659 if (daemon->psk_cred)
7660 gnutls_psk_free_server_credentials (daemon->psk_cred);
7661 }
7662#endif /* HTTPS_SUPPORT */
7663
7664#ifdef DAUTH_SUPPORT
7665 free (daemon->nnc);
7666#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7667 MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
7668#endif
7669#endif
7670#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7672#endif
7673 free (daemon);
7674 }
7675}
7676
7677
7689const union MHD_DaemonInfo *
7691 enum MHD_DaemonInfoType info_type,
7692 ...)
7693{
7694 if (NULL == daemon)
7695 return NULL;
7696 switch (info_type)
7697 {
7699 return NULL; /* no longer supported */
7701 return NULL; /* no longer supported */
7703 return (const union MHD_DaemonInfo *) &daemon->listen_fd;
7704#ifdef EPOLL_SUPPORT
7706 return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
7707#endif
7709 if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
7710 {
7711 /* Assume that MHD_run() in not called in other thread
7712 * at the same time. */
7713 MHD_cleanup_connections (daemon);
7714 }
7715#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7716 else if (daemon->worker_pool)
7717 {
7718 unsigned int i;
7719 /* Collect the connection information stored in the workers. */
7720 daemon->connections = 0;
7721 for (i = 0; i < daemon->worker_pool_size; i++)
7722 {
7723 /* FIXME: next line is thread-safe only if read is atomic. */
7724 daemon->connections += daemon->worker_pool[i].connections;
7725 }
7726 }
7727#endif
7728 return (const union MHD_DaemonInfo *) &daemon->connections;
7730 return (const union MHD_DaemonInfo *) &daemon->options;
7732 return (const union MHD_DaemonInfo *) &daemon->port;
7733 default:
7734 return NULL;
7735 }
7736}
7737
7738
7755void
7757 void *cls)
7758{
7759 mhd_panic = cb;
7760 mhd_panic_cls = cls;
7761}
7762
7763
7770const char *
7771MHD_get_version (void)
7772{
7773#ifdef PACKAGE_VERSION
7774 return PACKAGE_VERSION;
7775#else /* !PACKAGE_VERSION */
7776 static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
7777 if (0 == ver[0])
7778 {
7779 int res = MHD_snprintf_ (ver,
7780 sizeof(ver),
7781 "%x.%x.%x",
7782 (((int) MHD_VERSION >> 24) & 0xFF),
7783 (((int) MHD_VERSION >> 16) & 0xFF),
7784 (((int) MHD_VERSION >> 8) & 0xFF));
7785 if ((0 >= res) || (sizeof(ver) <= res))
7786 return "0.0.0"; /* Can't return real version*/
7787 }
7788 return ver;
7789#endif /* !PACKAGE_VERSION */
7790}
7791
7792
7804enum MHD_Result
7806{
7807 switch (feature)
7808 {
7810#ifdef HAVE_MESSAGES
7811 return MHD_YES;
7812#else
7813 return MHD_NO;
7814#endif
7815 case MHD_FEATURE_TLS:
7816#ifdef HTTPS_SUPPORT
7817 return MHD_YES;
7818#else /* ! HTTPS_SUPPORT */
7819 return MHD_NO;
7820#endif /* ! HTTPS_SUPPORT */
7822#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7823 return MHD_YES;
7824#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7825 return MHD_NO;
7826#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7828#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7829 return MHD_YES;
7830#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7831 return MHD_NO;
7832#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7833 case MHD_FEATURE_IPv6:
7834#ifdef HAVE_INET6
7835 return MHD_YES;
7836#else
7837 return MHD_NO;
7838#endif
7840#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
7841 return MHD_YES;
7842#else
7843 return MHD_NO;
7844#endif
7845 case MHD_FEATURE_POLL:
7846#ifdef HAVE_POLL
7847 return MHD_YES;
7848#else
7849 return MHD_NO;
7850#endif
7851 case MHD_FEATURE_EPOLL:
7852#ifdef EPOLL_SUPPORT
7853 return MHD_YES;
7854#else
7855 return MHD_NO;
7856#endif
7858#ifdef HAVE_LISTEN_SHUTDOWN
7859 return MHD_YES;
7860#else
7861 return MHD_NO;
7862#endif
7864#ifdef _MHD_ITC_SOCKETPAIR
7865 return MHD_YES;
7866#else
7867 return MHD_NO;
7868#endif
7870#ifdef TCP_FASTOPEN
7871 return MHD_YES;
7872#else
7873 return MHD_NO;
7874#endif
7876#ifdef BAUTH_SUPPORT
7877 return MHD_YES;
7878#else
7879 return MHD_NO;
7880#endif
7882#ifdef DAUTH_SUPPORT
7883 return MHD_YES;
7884#else
7885 return MHD_NO;
7886#endif
7888#ifdef HAVE_POSTPROCESSOR
7889 return MHD_YES;
7890#else
7891 return MHD_NO;
7892#endif
7894#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
7895 return MHD_YES;
7896#else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
7897 return MHD_NO;
7898#endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
7900#if defined(HAVE_PREAD64) || defined(_WIN32)
7901 return MHD_YES;
7902#elif defined(HAVE_PREAD)
7903 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
7904#elif defined(HAVE_LSEEK64)
7905 return MHD_YES;
7906#else
7907 return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
7908#endif
7910#if defined(MHD_USE_THREAD_NAME_)
7911 return MHD_YES;
7912#else
7913 return MHD_NO;
7914#endif
7916#if defined(UPGRADE_SUPPORT)
7917 return MHD_YES;
7918#else
7919 return MHD_NO;
7920#endif
7922#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
7923 return MHD_YES;
7924#else
7925 return MHD_NO;
7926#endif
7928#ifdef MHD_USE_GETSOCKNAME
7929 return MHD_YES;
7930#else
7931 return MHD_NO;
7932#endif
7934#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
7935 defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
7936 return MHD_YES;
7937#else
7938 return MHD_NO;
7939#endif
7941#ifdef _MHD_HAVE_SENDFILE
7942 return MHD_YES;
7943#else
7944 return MHD_NO;
7945#endif
7947#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7948 return MHD_YES;
7949#else
7950 return MHD_NO;
7951#endif
7952
7953 }
7954 return MHD_NO;
7955}
7956
7957
7958#ifdef MHD_HTTPS_REQUIRE_GRYPT
7959#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
7960#if defined(MHD_USE_POSIX_THREADS)
7961GCRY_THREAD_OPTION_PTHREAD_IMPL;
7962#elif defined(MHD_W32_MUTEX_)
7963
7964static int
7965gcry_w32_mutex_init (void **ppmtx)
7966{
7967 *ppmtx = malloc (sizeof (MHD_mutex_));
7968
7969 if (NULL == *ppmtx)
7970 return ENOMEM;
7971 if (! MHD_mutex_init_ ((MHD_mutex_*) *ppmtx))
7972 {
7973 free (*ppmtx);
7974 *ppmtx = NULL;
7975 return EPERM;
7976 }
7977
7978 return 0;
7979}
7980
7981
7982static int
7983gcry_w32_mutex_destroy (void **ppmtx)
7984{
7985 int res = (MHD_mutex_destroy_ ((MHD_mutex_*) *ppmtx)) ? 0 : EINVAL;
7986 free (*ppmtx);
7987 return res;
7988}
7989
7990
7991static int
7992gcry_w32_mutex_lock (void **ppmtx)
7993{
7994 return MHD_mutex_lock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7995}
7996
7997
7998static int
7999gcry_w32_mutex_unlock (void **ppmtx)
8000{
8001 return MHD_mutex_unlock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
8002}
8003
8004
8005static struct gcry_thread_cbs gcry_threads_w32 = {
8006 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
8007 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
8008 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
8010};
8011
8012#endif /* defined(MHD_W32_MUTEX_) */
8013#endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
8014#endif /* MHD_HTTPS_REQUIRE_GRYPT */
8015
8019void
8021{
8022#if defined(MHD_WINSOCK_SOCKETS)
8023 WSADATA wsd;
8024#endif /* MHD_WINSOCK_SOCKETS */
8025
8026 if (NULL == mhd_panic)
8028
8029#if defined(MHD_WINSOCK_SOCKETS)
8030 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
8031 MHD_PANIC (_ ("Failed to initialize winsock.\n"));
8032 mhd_winsock_inited_ = 1;
8033 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
8034 MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
8035#endif /* MHD_WINSOCK_SOCKETS */
8036#ifdef HTTPS_SUPPORT
8037#ifdef MHD_HTTPS_REQUIRE_GRYPT
8038#if GCRYPT_VERSION_NUMBER < 0x010600
8039#if defined(MHD_USE_POSIX_THREADS)
8040 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8041 &gcry_threads_pthread))
8042 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
8043#elif defined(MHD_W32_MUTEX_)
8044 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8045 &gcry_threads_w32))
8046 MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
8047#endif /* defined(MHD_W32_MUTEX_) */
8048 gcry_check_version (NULL);
8049#else
8050 if (NULL == gcry_check_version ("1.6.0"))
8051 MHD_PANIC (_ (
8052 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
8053#endif
8054#endif /* MHD_HTTPS_REQUIRE_GRYPT */
8055 gnutls_global_init ();
8056#endif /* HTTPS_SUPPORT */
8060}
8061
8062
8063void
8065{
8066#ifdef HTTPS_SUPPORT
8067 gnutls_global_deinit ();
8068#endif /* HTTPS_SUPPORT */
8069#if defined(MHD_WINSOCK_SOCKETS)
8070 if (mhd_winsock_inited_)
8071 WSACleanup ();
8072#endif /* MHD_WINSOCK_SOCKETS */
8074}
8075
8076
8077#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
8079#endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
8080
8081/* end of daemon.c */
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2818
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2936
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3892
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3348
Methods for managing connections.
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:163
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
#define EXTRA_SLOTS
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:260
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:3136
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:7297
MHD_PanicCallback mhd_panic
Definition: daemon.c:152
static int get_timeout_millisec_(struct MHD_Daemon *daemon, int32_t max_timeout)
Definition: daemon.c:3887
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:414
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:3173
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:3038
void MHD_fini(void)
Definition: daemon.c:8064
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:5508
static enum MHD_Result call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1193
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:324
volatile int global_init_count
Definition: daemon.c:183
static enum MHD_Result MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:4575
void MHD_check_global_init_(void)
Definition: daemon.c:200
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:5182
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
Definition: daemon.c:4080
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:344
static void new_connections_list_process_(struct MHD_Daemon *daemon)
Definition: daemon.c:2986
void MHD_init(void)
Definition: daemon.c:8020
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3683
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:5455
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3504
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:480
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:77
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:5298
static enum MHD_Result new_connection_process_(struct MHD_Daemon *daemon, struct MHD_Connection *connection)
Definition: daemon.c:2695
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:308
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:363
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:5483
static struct MHD_Connection * new_connection_prepare_(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
Definition: daemon.c:2386
void * mhd_panic_cls
Definition: daemon.c:157
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3210
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:85
static enum MHD_Result internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
Definition: daemon.c:2899
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:128
_MHD_EXTERN void MHD_free(void *ptr)
Definition: daemon.c:246
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:978
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:3916
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:5330
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:7508
_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:4024
_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:6262
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:5096
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3794
#define MHD_get_fdset(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd)
Definition: microhttpd.h:2653
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
Definition: daemon.c:5136
_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:1127
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:2168
_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:2276
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Definition: microhttpd.h:2250
@ MHD_CONNECTION_NOTIFY_STARTED
Definition: microhttpd.h:1915
@ MHD_CONNECTION_NOTIFY_CLOSED
Definition: microhttpd.h:1921
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
Definition: microhttpd.h:1880
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
Definition: microhttpd.h:1857
@ MHD_REQUEST_TERMINATED_WITH_ERROR
Definition: microhttpd.h:1865
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1397
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:7690
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:5375
_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:3370
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:7805
_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_socket_close_(fd)
Definition: mhd_sockets.h:238
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:643
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:656
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:414
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:542
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:549
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:464
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:248
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:634
#define MHD_socket_fset_error_(err)
Definition: mhd_sockets.h:555
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:261
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:623
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:336
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:309
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:216
#define NULL
Definition: reason_phrase.c:30
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:63
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:95
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:50
void MHD_send_init_static_vars_(void)
Definition: mhd_send.c:153
Declarations of send() wrappers.
internal shared structures
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:596
@ MHD_CONNECTION_INIT
Definition: internal.h:543
@ MHD_CONNECTION_CLOSED
Definition: internal.h:642
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:606
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:617
@ MHD_TLS_CONN_INIT
Definition: internal.h:661
@ MHD_EVENT_LOOP_INFO_READ
Definition: internal.h:237
@ MHD_EVENT_LOOP_INFO_WRITE
Definition: internal.h:242
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition: internal.h:252
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition: internal.h:247
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1366
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition: internal.h:260
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1380
MHD_tristate
Definition: internal.h:174
@ _MHD_UNKNOWN
Definition: internal.h:175
@ _MHD_YES
Definition: internal.h:179
@ _MHD_OFF
Definition: internal.h:176
@ _MHD_NO
Definition: internal.h:177
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
#define MHD_mutex_destroy_(ignore)
Definition: mhd_locks.h:190
#define MHD_mutex_unlock_(ignore)
Definition: mhd_locks.h:194
#define MHD_mutex_lock_(ignore)
Definition: mhd_locks.h:192
#define MHD_mutex_init_(ignore)
Definition: mhd_locks.h:189
internal monotonic clock functions implementations
#define SOCK_NONBLOCK_OR_ZERO
Definition: mhd_sockets.h:172
#define SOCK_NOSIGPIPE_OR_ZERO
Definition: mhd_sockets.h:178
#define SOCK_CLOEXEC_OR_ZERO
Definition: mhd_sockets.h:166
int MHD_socket
Definition: microhttpd.h:193
MHD_FEATURE
Definition: microhttpd.h:4003
@ MHD_FEATURE_POSTPROCESSOR
Definition: microhttpd.h:4094
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
Definition: microhttpd.h:4058
@ MHD_FEATURE_THREADS
Definition: microhttpd.h:4162
@ MHD_FEATURE_SENDFILE
Definition: microhttpd.h:4157
@ MHD_FEATURE_AUTODETECT_BIND_PORT
Definition: microhttpd.h:4143
@ MHD_FEATURE_LARGE_FILE
Definition: microhttpd.h:4111
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:4024
@ MHD_FEATURE_BASIC_AUTH
Definition: microhttpd.h:4078
@ MHD_FEATURE_DIGEST_AUTH
Definition: microhttpd.h:4086
@ MHD_FEATURE_IPv6
Definition: microhttpd.h:4030
@ MHD_FEATURE_POLL
Definition: microhttpd.h:4044
@ MHD_FEATURE_THREAD_NAMES
Definition: microhttpd.h:4116
@ MHD_FEATURE_EPOLL
Definition: microhttpd.h:4051
@ MHD_FEATURE_TLS
Definition: microhttpd.h:4017
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:4101
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
Definition: microhttpd.h:4150
@ MHD_FEATURE_RESPONSES_SHARED_FD
Definition: microhttpd.h:4137
@ MHD_FEATURE_MESSAGES
Definition: microhttpd.h:4008
@ MHD_FEATURE_IPv6_ONLY
Definition: microhttpd.h:4038
@ MHD_FEATURE_UPGRADE
Definition: microhttpd.h:4124
@ MHD_FEATURE_SOCKETPAIR
Definition: microhttpd.h:4064
@ MHD_FEATURE_TCP_FASTOPEN
Definition: microhttpd.h:4071
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:4168
MHD_OPTION
MHD options.
Definition: microhttpd.h:1379
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
Definition: microhttpd.h:1615
@ MHD_OPTION_HTTPS_CRED_TYPE
Definition: microhttpd.h:1496
@ MHD_OPTION_URI_LOG_CALLBACK
Definition: microhttpd.h:1473
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:1719
@ MHD_OPTION_SIGPIPE_HANDLED_BY_APP
Definition: microhttpd.h:1741
@ MHD_OPTION_UNESCAPE_CALLBACK
Definition: microhttpd.h:1578
@ MHD_OPTION_EXTERNAL_LOGGER
Definition: microhttpd.h:1525
@ MHD_OPTION_TLS_NO_ALPN
Definition: microhttpd.h:1750
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
Definition: microhttpd.h:1684
@ MHD_OPTION_HTTPS_PRIORITIES
Definition: microhttpd.h:1502
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
Definition: microhttpd.h:1647
@ MHD_OPTION_NOTIFY_CONNECTION
Definition: microhttpd.h:1676
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
Definition: microhttpd.h:1656
@ MHD_OPTION_THREAD_POOL_SIZE
Definition: microhttpd.h:1535
@ MHD_OPTION_CONNECTION_LIMIT
Definition: microhttpd.h:1400
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
Definition: microhttpd.h:1433
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
Definition: microhttpd.h:1640
@ MHD_OPTION_HTTPS_MEM_CERT
Definition: microhttpd.h:1489
@ MHD_OPTION_SERVER_INSANITY
Definition: microhttpd.h:1730
@ MHD_OPTION_LISTEN_SOCKET
Definition: microhttpd.h:1510
@ MHD_OPTION_HTTPS_MEM_KEY
Definition: microhttpd.h:1481
@ MHD_OPTION_DIGEST_AUTH_RANDOM
Definition: microhttpd.h:1589
@ MHD_OPTION_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:1665
@ MHD_OPTION_NONCE_NC_SIZE
Definition: microhttpd.h:1596
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
Definition: microhttpd.h:1394
@ MHD_OPTION_THREAD_STACK_SIZE
Definition: microhttpd.h:1602
@ MHD_OPTION_ARRAY
Definition: microhttpd.h:1556
@ MHD_OPTION_STRICT_FOR_CLIENT
Definition: microhttpd.h:1700
@ MHD_OPTION_SOCK_ADDR
Definition: microhttpd.h:1441
@ MHD_OPTION_CONNECTION_TIMEOUT
Definition: microhttpd.h:1407
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
Definition: microhttpd.h:1708
@ MHD_OPTION_END
Definition: microhttpd.h:1385
@ MHD_OPTION_HTTPS_MEM_TRUST
Definition: microhttpd.h:1609
@ MHD_OPTION_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:1631
@ MHD_OPTION_NOTIFY_COMPLETED
Definition: microhttpd.h:1421
MHD_DisableSanityCheck
Definition: microhttpd.h:1759
MHD_Result
Definition: microhttpd.h:139
@ MHD_YES
Definition: microhttpd.h:148
@ MHD_NO
Definition: microhttpd.h:143
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:2182
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:296
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:310
int fd
Definition: microhttpd.h:3269
void * data
Definition: microhttpd.h:3125
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:142
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:194
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:2227
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
Definition: microhttpd.h:1367
#define MHD_VERSION
Definition: microhttpd.h:133
MHD_DaemonInfoType
Definition: microhttpd.h:2104
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
Definition: microhttpd.h:2113
@ MHD_DAEMON_INFO_BIND_PORT
Definition: microhttpd.h:2153
@ MHD_DAEMON_INFO_EPOLL_FD
Definition: microhttpd.h:2128
@ MHD_DAEMON_INFO_FLAGS
Definition: microhttpd.h:2145
@ MHD_DAEMON_INFO_KEY_SIZE
Definition: microhttpd.h:2108
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
Definition: microhttpd.h:2137
@ MHD_DAEMON_INFO_LISTEN_FD
Definition: microhttpd.h:2119
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:1050
@ MHD_USE_EPOLL
Definition: microhttpd.h:1193
@ MHD_ALLOW_SUSPEND_RESUME
Definition: microhttpd.h:1279
@ MHD_USE_TCP_FASTOPEN
Definition: microhttpd.h:1295
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1087
@ MHD_USE_AUTO
Definition: microhttpd.h:1315
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
Definition: microhttpd.h:1329
@ MHD_USE_TURBO
Definition: microhttpd.h:1264
@ MHD_USE_IPv6
Definition: microhttpd.h:1116
@ MHD_USE_DUAL_STACK
Definition: microhttpd.h:1256
@ MHD_USE_POLL
Definition: microhttpd.h:1143
@ MHD_USE_TLS
Definition: microhttpd.h:1072
@ MHD_USE_INSECURE_TLS_EARLY_DATA
Definition: microhttpd.h:1335
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1302
@ MHD_USE_NO_LISTEN_SOCKET
Definition: microhttpd.h:1184
@ MHD_USE_PEDANTIC_CHECKS
Definition: microhttpd.h:1127
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1098
@ MHD_USE_ITC
Definition: microhttpd.h:1242
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
enum MHD_tristate sk_nodelay
Definition: internal.h:1025
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:1069
enum MHD_tristate is_nonip
Definition: internal.h:1005
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:796
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:905
struct MHD_Connection * prev
Definition: internal.h:656
bool client_aware
Definition: internal.h:992
MHD_thread_handle_ID_ pid
Definition: internal.h:723
struct MHD_Connection * nextX
Definition: internal.h:665
time_t last_activity
Definition: internal.h:739
void * client_context
Definition: internal.h:814
enum MHD_CONNECTION_STATE state
Definition: internal.h:1064
struct MHD_Daemon * daemon
Definition: internal.h:675
bool sk_spipe_suppress
Definition: internal.h:1015
size_t read_buffer_size
Definition: internal.h:899
enum MHD_tristate sk_corked
Definition: internal.h:1020
bool thread_joined
Definition: internal.h:779
size_t pool_size
Definition: internal.h:1662
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1574
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1398
LogCallback uri_log_callback
Definition: internal.h:1588
bool data_already_pending
Definition: internal.h:1500
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1259
void * per_ip_connection_count
Definition: internal.h:1187
bool at_limit
Definition: internal.h:1483
struct MHD_Connection * new_connections_tail
Definition: internal.h:1421
uint16_t port
Definition: internal.h:1611
bool was_quiesced
Definition: internal.h:1505
unsigned int connection_limit
Definition: internal.h:1772
void * unescape_callback_cls
Definition: internal.h:1603
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
enum MHD_DisableSanityCheck insanity_level
Definition: internal.h:1706
struct MHD_Connection * connections_head
Definition: internal.h:1155
unsigned int listen_backlog_size
Definition: internal.h:1943
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1563
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:1717
void * apc_cls
Definition: internal.h:1557
unsigned int per_ip_connection_limit
Definition: internal.h:1784
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1411
void * notify_connection_cls
Definition: internal.h:1579
bool sigpipe_blocked
Definition: internal.h:1794
UnescapeCallback unescape_callback
Definition: internal.h:1598
void * notify_completed_cls
Definition: internal.h:1568
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
size_t num_opts
Definition: internal.h:1952
bool resuming
Definition: internal.h:1510
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
struct MHD_Connection * new_connections_head
Definition: internal.h:1416
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
enum MHD_tristate listen_is_unix
Definition: internal.h:1456
void * default_handler_cls
Definition: internal.h:1403
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
time_t connection_timeout
Definition: internal.h:1778
MHD_AcceptPolicyCallback apc
Definition: internal.h:1552
struct MHD_Connection * cleanup_head
Definition: internal.h:1177
struct MHD_Daemon * master
Definition: internal.h:1068
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
volatile bool have_new
Definition: internal.h:1756
size_t pool_increment
Definition: internal.h:1667
MHD_socket listen_fd
Definition: internal.h:1637
void * uri_log_callback_cls
Definition: internal.h:1593
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:1789
intptr_t value
Definition: microhttpd.h:1784
enum MHD_OPTION option
Definition: microhttpd.h:1777
void * ptr_value
Definition: microhttpd.h:1790