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