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