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