GNU libmicrohttpd  0.9.71
daemon.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
28 #include "platform.h"
29 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
30 #include "mhd_threads.h"
31 #endif
32 #include "internal.h"
33 #include "response.h"
34 #include "connection.h"
35 #include "memorypool.h"
36 #include "mhd_limits.h"
37 #include "autoinit_funcs.h"
38 #include "mhd_mono_clock.h"
39 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
40 #include "mhd_locks.h"
41 #endif
42 #include "mhd_sockets.h"
43 #include "mhd_itc.h"
44 #include "mhd_compat.h"
45 
46 #if HAVE_SEARCH_H
47 #include <search.h>
48 #else
49 #include "tsearch.h"
50 #endif
51 
52 #ifdef HTTPS_SUPPORT
53 #include "connection_https.h"
54 #ifdef MHD_HTTPS_REQUIRE_GRYPT
55 #include <gcrypt.h>
56 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
57 #endif /* HTTPS_SUPPORT */
58 
59 #if defined(_WIN32) && ! defined(__CYGWIN__)
60 #ifndef WIN32_LEAN_AND_MEAN
61 #define WIN32_LEAN_AND_MEAN 1
62 #endif /* !WIN32_LEAN_AND_MEAN */
63 #include <windows.h>
64 #endif
65 
69 #ifdef MHD_POSIX_SOCKETS
70 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
71 #else
72 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
73 #endif
74 
78 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
79 
84 #define DEBUG_CLOSE MHD_NO
85 
90 #define DEBUG_CONNECT MHD_NO
91 
92 
93 /* Forward declarations. */
94 
103 static void
104 close_all_connections (struct MHD_Daemon *daemon);
105 
106 #ifdef EPOLL_SUPPORT
107 
116 static enum MHD_Result
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 enum MHD_Result
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 enum MHD_Result
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  enum MHD_Result result;
424 
425  daemon = MHD_get_master (daemon);
426  /* Ignore if no connection limit assigned */
427  if (0 == daemon->per_ip_connection_limit)
428  return MHD_YES;
429 
430  if (NULL == (key = malloc (sizeof(*key))))
431  return MHD_NO;
432 
433  /* Initialize key */
434  if (MHD_NO == MHD_ip_addr_to_key (addr,
435  addrlen,
436  key))
437  {
438  /* Allow unhandled address types through */
439  free (key);
440  return MHD_YES;
441  }
442  MHD_ip_count_lock (daemon);
443 
444  /* Search for the IP address */
445  if (NULL == (nodep = tsearch (key,
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.\n"));
627 #endif
628  return -1;
629 #endif
630  }
631  else
632  ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
633  &cert,
634  &key,
635  GNUTLS_X509_FMT_PEM);
636 #ifdef HAVE_MESSAGES
637  if (0 != ret)
638  MHD_DLOG (daemon,
639  "GnuTLS failed to setup x509 certificate/key: %s\n",
640  gnutls_strerror (ret));
641 #endif
642  return ret;
643  }
644 #if GNUTLS_VERSION_MAJOR >= 3
645  if (NULL != daemon->cert_callback)
646  return 0;
647 #endif
648 #if GNUTLS_VERSION_NUMBER >= 0x030603
649  else if (NULL != daemon->cert_callback2)
650  return 0;
651 #endif
652 #ifdef HAVE_MESSAGES
653  MHD_DLOG (daemon,
654  "You need to specify a certificate and key location.\n");
655 #endif
656  return -1;
657 }
658 
659 
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 enum MHD_Result
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 enum MHD_Result
980 internal_get_fdset2 (struct MHD_Daemon *daemon,
981  fd_set *read_fd_set,
982  fd_set *write_fd_set,
983  fd_set *except_fd_set,
984  MHD_socket *max_fd,
985  unsigned int fd_setsize)
986 
987 {
988  struct MHD_Connection *pos;
989  struct MHD_Connection *posn;
990  enum MHD_Result result = MHD_YES;
991  MHD_socket ls;
992 
993  if (daemon->shutdown)
994  return MHD_NO;
995 
996  ls = daemon->listen_fd;
997  if ( (MHD_INVALID_SOCKET != ls) &&
998  (! daemon->was_quiesced) &&
999  (! MHD_add_to_fd_set_ (ls,
1000  read_fd_set,
1001  max_fd,
1002  fd_setsize)) )
1003  result = MHD_NO;
1004 
1005  /* Add all sockets to 'except_fd_set' as well to watch for
1006  * out-of-band data. However, ignore errors if INFO_READ
1007  * or INFO_WRITE sockets will not fit 'except_fd_set'. */
1008  /* Start from oldest connections. Make sense for W32 FDSETs. */
1009  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1010  {
1011  posn = pos->prev;
1012 
1013  switch (pos->event_loop_info)
1014  {
1016  if (! MHD_add_to_fd_set_ (pos->socket_fd,
1017  read_fd_set,
1018  max_fd,
1019  fd_setsize))
1020  result = MHD_NO;
1021 #ifdef MHD_POSIX_SOCKETS
1023  except_fd_set,
1024  max_fd,
1025  fd_setsize);
1026 #endif /* MHD_POSIX_SOCKETS */
1027  break;
1029  if (! MHD_add_to_fd_set_ (pos->socket_fd,
1030  write_fd_set,
1031  max_fd,
1032  fd_setsize))
1033  result = MHD_NO;
1034 #ifdef MHD_POSIX_SOCKETS
1036  except_fd_set,
1037  max_fd,
1038  fd_setsize);
1039 #endif /* MHD_POSIX_SOCKETS */
1040  break;
1042  if ( (NULL == except_fd_set) ||
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 enum MHD_Result
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 enum MHD_Result
1195 call_handlers (struct MHD_Connection *con,
1196  bool read_ready,
1197  bool write_ready,
1198  bool force_close)
1199 {
1200  enum MHD_Result ret;
1201  bool states_info_processed = false;
1202  /* Fast track flag */
1203  bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1204 
1205 #ifdef HTTPS_SUPPORT
1206  if (con->tls_read_ready)
1207  read_ready = true;
1208 #endif /* HTTPS_SUPPORT */
1209  if (! force_close)
1210  {
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.\n"));
2215 #endif
2216  }
2217  return (MHD_THRD_RTRN_TYPE_) 0;
2218 }
2219 
2220 
2221 #endif
2222 
2223 
2231 static void
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 enum MHD_Result
2373 internal_add_connection (struct MHD_Daemon *daemon,
2374  MHD_socket client_socket,
2375  const struct sockaddr *addr,
2376  socklen_t addrlen,
2377  bool external_add,
2378  bool non_blck)
2379 {
2380  struct MHD_Connection *connection;
2381 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2382  unsigned int i;
2383 #endif
2384  int eno = 0;
2385 
2386  /* Direct add to master daemon could happen only with "external" add mode. */
2387 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2388  mhd_assert ((NULL == daemon->worker_pool) || (external_add));
2389  if ((external_add) && (NULL != daemon->worker_pool))
2390  {
2391  /* have a pool, try to find a pool with capacity; we use the
2392  socket as the initial offset into the pool for load
2393  balancing */
2394  for (i = 0; i < daemon->worker_pool_size; ++i)
2395  {
2396  struct MHD_Daemon *const worker =
2397  &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
2398  if (worker->connections < worker->connection_limit)
2399  return internal_add_connection (worker,
2400  client_socket,
2401  addr,
2402  addrlen,
2403  true,
2404  non_blck);
2405  }
2406  /* all pools are at their connection limit, must refuse */
2407  MHD_socket_close_chk_ (client_socket);
2408 #if ENFILE
2409  errno = ENFILE;
2410 #endif
2411  return MHD_NO;
2412  }
2413 #endif
2414 
2415  if ( (! MHD_SCKT_FD_FITS_FDSET_ (client_socket,
2416  NULL)) &&
2417  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
2418  {
2419 #ifdef HAVE_MESSAGES
2420  MHD_DLOG (daemon,
2421  _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2422  (int) client_socket,
2423  (int) FD_SETSIZE);
2424 #endif
2425  MHD_socket_close_chk_ (client_socket);
2426 #if EINVAL
2427  errno = EINVAL;
2428 #endif
2429  return MHD_NO;
2430  }
2431 
2432 #ifdef MHD_socket_nosignal_
2433  if (! MHD_socket_nosignal_ (client_socket))
2434  {
2435 #ifdef HAVE_MESSAGES
2436  MHD_DLOG (daemon,
2437  _ ("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2439 #endif
2440 #ifndef MSG_NOSIGNAL
2441  /* Cannot use socket as it can produce SIGPIPE. */
2442 #ifdef ENOTSOCK
2443  errno = ENOTSOCK;
2444 #endif /* ENOTSOCK */
2445  return MHD_NO;
2446 #endif /* ! MSG_NOSIGNAL */
2447  }
2448 #endif /* MHD_socket_nosignal_ */
2449 
2450 
2451 #ifdef HAVE_MESSAGES
2452 #if DEBUG_CONNECT
2453  MHD_DLOG (daemon,
2454  _ ("Accepted connection on socket %d.\n"),
2455  client_socket);
2456 #endif
2457 #endif
2458  if ( (daemon->connections == daemon->connection_limit) ||
2459  (MHD_NO == MHD_ip_limit_add (daemon,
2460  addr,
2461  addrlen)) )
2462  {
2463  /* above connection limit - reject */
2464 #ifdef HAVE_MESSAGES
2465  MHD_DLOG (daemon,
2466  _ (
2467  "Server reached connection limit. Closing inbound connection.\n"));
2468 #endif
2469  MHD_socket_close_chk_ (client_socket);
2470 #if ENFILE
2471  errno = ENFILE;
2472 #endif
2473  return MHD_NO;
2474  }
2475 
2476  /* apply connection acceptance policy if present */
2477  if ( (NULL != daemon->apc) &&
2478  (MHD_NO == daemon->apc (daemon->apc_cls,
2479  addr,
2480  addrlen)) )
2481  {
2482 #if DEBUG_CLOSE
2483 #ifdef HAVE_MESSAGES
2484  MHD_DLOG (daemon,
2485  _ ("Connection rejected by application. Closing connection.\n"));
2486 #endif
2487 #endif
2488  MHD_socket_close_chk_ (client_socket);
2489  MHD_ip_limit_del (daemon,
2490  addr,
2491  addrlen);
2492 #if EACCESS
2493  errno = EACCESS;
2494 #endif
2495  return MHD_NO;
2496  }
2497 
2498  if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2499  {
2500  eno = errno;
2501 #ifdef HAVE_MESSAGES
2502  MHD_DLOG (daemon,
2503  "Error allocating memory: %s\n",
2504  MHD_strerror_ (errno));
2505 #endif
2506  MHD_socket_close_chk_ (client_socket);
2507  MHD_ip_limit_del (daemon,
2508  addr,
2509  addrlen);
2510  errno = eno;
2511  return MHD_NO;
2512  }
2513  connection->sk_cork_on = true; /* default is usually ON */
2514  connection->pool = MHD_pool_create (daemon->pool_size);
2515  if (NULL == connection->pool)
2516  {
2517 #ifdef HAVE_MESSAGES
2518  MHD_DLOG (daemon,
2519  _ ("Error allocating memory: %s\n"),
2520  MHD_strerror_ (errno));
2521 #endif
2522  MHD_socket_close_chk_ (client_socket);
2523  MHD_ip_limit_del (daemon,
2524  addr,
2525  addrlen);
2526  free (connection);
2527 #if ENOMEM
2528  errno = ENOMEM;
2529 #endif
2530  return MHD_NO;
2531  }
2532 
2533  connection->connection_timeout = daemon->connection_timeout;
2534  if (NULL == (connection->addr = malloc (addrlen)))
2535  {
2536  eno = errno;
2537 #ifdef HAVE_MESSAGES
2538  MHD_DLOG (daemon,
2539  _ ("Error allocating memory: %s\n"),
2540  MHD_strerror_ (errno));
2541 #endif
2542  MHD_socket_close_chk_ (client_socket);
2543  MHD_ip_limit_del (daemon,
2544  addr,
2545  addrlen);
2546  MHD_pool_destroy (connection->pool);
2547  free (connection);
2548  errno = eno;
2549  return MHD_NO;
2550  }
2551  memcpy (connection->addr,
2552  addr,
2553  addrlen);
2554  connection->addr_len = addrlen;
2555  connection->socket_fd = client_socket;
2556  connection->sk_nonblck = non_blck;
2557  connection->daemon = daemon;
2558  connection->last_activity = MHD_monotonic_sec_counter ();
2559 
2560  if (0 == (daemon->options & MHD_USE_TLS))
2561  {
2562  /* set default connection handlers */
2563  MHD_set_http_callbacks_ (connection);
2564  }
2565  else
2566  {
2567 #ifdef HTTPS_SUPPORT
2568 #if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2569  gnutls_init_flags_t
2570 #else
2571  unsigned int
2572 #endif
2573  flags;
2574 
2575  flags = GNUTLS_SERVER;
2576 #if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2577  flags |= GNUTLS_NO_SIGNAL;
2578 #endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2579 #if GNUTLS_VERSION_MAJOR >= 3
2580  flags |= GNUTLS_NONBLOCK;
2581 #endif /* GNUTLS_VERSION_MAJOR >= 3*/
2582 #if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2583  if (0 != (daemon->options & MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT))
2584  flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2585 #endif
2586 #if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2587  if (0 != (daemon->options & MHD_USE_INSECURE_TLS_EARLY_DATA))
2588  flags |= GNUTLS_ENABLE_EARLY_DATA;
2589 #endif
2590  connection->tls_state = MHD_TLS_CONN_INIT;
2591  MHD_set_https_callbacks (connection);
2592  gnutls_init (&connection->tls_session,
2593  flags);
2594  gnutls_priority_set (connection->tls_session,
2595  daemon->priority_cache);
2596  gnutls_session_set_ptr (connection->tls_session,
2597  connection);
2598  switch (daemon->cred_type)
2599  {
2600  /* set needed credentials for certificate authentication. */
2601  case GNUTLS_CRD_CERTIFICATE:
2602  gnutls_credentials_set (connection->tls_session,
2603  GNUTLS_CRD_CERTIFICATE,
2604  daemon->x509_cred);
2605  break;
2606  case GNUTLS_CRD_PSK:
2607  gnutls_credentials_set (connection->tls_session,
2608  GNUTLS_CRD_PSK,
2609  daemon->psk_cred);
2610  gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2611  &psk_gnutls_adapter);
2612  break;
2613  default:
2614 #ifdef HAVE_MESSAGES
2615  MHD_DLOG (connection->daemon,
2616  _ (
2617  "Failed to setup TLS credentials: unknown credential type %d.\n"),
2618  daemon->cred_type);
2619 #endif
2620  MHD_socket_close_chk_ (client_socket);
2621  MHD_ip_limit_del (daemon,
2622  addr,
2623  addrlen);
2624  free (connection->addr);
2625  free (connection);
2626  MHD_PANIC (_ ("Unknown credential type.\n"));
2627 #if EINVAL
2628  errno = EINVAL;
2629 #endif
2630  return MHD_NO;
2631  }
2632 #if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2633  gnutls_transport_set_int (connection->tls_session,
2634  (int) (client_socket));
2635 #else /* GnuTLS before 3.1.9 or Win x64 */
2636  gnutls_transport_set_ptr (connection->tls_session,
2637  (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2638 #endif /* GnuTLS before 3.1.9 */
2639 #ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2640  gnutls_transport_set_push_function (connection->tls_session,
2641  MHD_tls_push_func_);
2642 #endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2643  if (daemon->https_mem_trust)
2644  gnutls_certificate_server_set_request (connection->tls_session,
2645  GNUTLS_CERT_REQUEST);
2646 #else /* ! HTTPS_SUPPORT */
2647  eno = EINVAL;
2648  goto cleanup;
2649 #endif /* ! HTTPS_SUPPORT */
2650  }
2651 
2652 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2654 #endif
2655  /* Firm check under lock. */
2656  if (daemon->connections >= daemon->connection_limit)
2657  {
2658 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2660 #endif
2661  /* above connection limit - reject */
2662 #ifdef HAVE_MESSAGES
2663  MHD_DLOG (daemon,
2664  _ (
2665  "Server reached connection limit. Closing inbound connection.\n"));
2666 #endif
2667 #if ENFILE
2668  eno = ENFILE;
2669 #endif
2670  goto cleanup;
2671  }
2672  daemon->connections++;
2673  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2674  {
2676  daemon->normal_timeout_tail,
2677  connection);
2678  }
2679  DLL_insert (daemon->connections_head,
2680  daemon->connections_tail,
2681  connection);
2682 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2684 #endif
2685  if (NULL != daemon->notify_connection)
2686  daemon->notify_connection (daemon->notify_connection_cls,
2687  connection,
2688  &connection->socket_context,
2690 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2691  /* attempt to create handler thread */
2692  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2693  {
2694  if (! MHD_create_named_thread_ (&connection->pid,
2695  "MHD-connection",
2696  daemon->thread_stack_size,
2698  connection))
2699  {
2700  eno = errno;
2701 #ifdef HAVE_MESSAGES
2702  MHD_DLOG (daemon,
2703  "Failed to create a thread: %s\n",
2704  MHD_strerror_ (eno));
2705 #endif
2706  goto cleanup;
2707  }
2708  }
2709  else
2710  connection->pid = daemon->pid;
2711 #endif
2712 #ifdef EPOLL_SUPPORT
2713  if (0 != (daemon->options & MHD_USE_EPOLL))
2714  {
2715  if ((0 == (daemon->options & MHD_USE_TURBO)) || (external_add))
2716  { /* Do not manipulate EReady DL-list in 'external_add' mode. */
2717  struct epoll_event event;
2718 
2719  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2720  event.data.ptr = connection;
2721  if (0 != epoll_ctl (daemon->epoll_fd,
2722  EPOLL_CTL_ADD,
2723  client_socket,
2724  &event))
2725  {
2726  eno = errno;
2727 #ifdef HAVE_MESSAGES
2728  MHD_DLOG (daemon,
2729  _ ("Call to epoll_ctl failed: %s\n"),
2731 #endif
2732  goto cleanup;
2733  }
2734  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2735  }
2736  else
2737  {
2738  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY
2741  EDLL_insert (daemon->eready_head,
2742  daemon->eready_tail,
2743  connection);
2744  }
2745  }
2746  else /* This 'else' is combined with next 'if'. */
2747 #endif
2748  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2749  (external_add) &&
2750  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2751  (! MHD_itc_activate_ (daemon->itc, "n")) )
2752  {
2753 #ifdef HAVE_MESSAGES
2754  MHD_DLOG (daemon,
2755  _ (
2756  "Failed to signal new connection via inter-thread communication channel.\n"));
2757 #endif
2758  }
2759  return MHD_YES;
2760 cleanup:
2761  if (NULL != daemon->notify_connection)
2762  daemon->notify_connection (daemon->notify_connection_cls,
2763  connection,
2764  &connection->socket_context,
2766 #ifdef HTTPS_SUPPORT
2767  if (NULL != connection->tls_session)
2768  gnutls_deinit (connection->tls_session);
2769 #endif /* HTTPS_SUPPORT */
2770  MHD_socket_close_chk_ (client_socket);
2771  MHD_ip_limit_del (daemon,
2772  addr,
2773  addrlen);
2774 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2776 #endif
2777  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2778  {
2780  daemon->normal_timeout_tail,
2781  connection);
2782  }
2783  DLL_remove (daemon->connections_head,
2784  daemon->connections_tail,
2785  connection);
2786 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2788 #endif
2789  MHD_pool_destroy (connection->pool);
2790  free (connection->addr);
2791  free (connection);
2792  if (0 != eno)
2793  errno = eno;
2794  else
2795  errno = EINVAL;
2796  return MHD_NO;
2797 }
2798 
2799 
2809 void
2811 {
2812  struct MHD_Daemon *daemon = connection->daemon;
2813 
2814 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2816 #endif
2817  if (connection->resuming)
2818  {
2819  /* suspending again while we didn't even complete resuming yet */
2820  connection->resuming = false;
2821 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2823 #endif
2824  return;
2825  }
2826  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2827  {
2828  if (connection->connection_timeout == daemon->connection_timeout)
2830  daemon->normal_timeout_tail,
2831  connection);
2832  else
2834  daemon->manual_timeout_tail,
2835  connection);
2836  }
2837  DLL_remove (daemon->connections_head,
2838  daemon->connections_tail,
2839  connection);
2840  mhd_assert (! connection->suspended);
2843  connection);
2844  connection->suspended = true;
2845 #ifdef EPOLL_SUPPORT
2846  if (0 != (daemon->options & MHD_USE_EPOLL))
2847  {
2848  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2849  {
2850  EDLL_remove (daemon->eready_head,
2851  daemon->eready_tail,
2852  connection);
2853  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2854  }
2855  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2856  {
2857  if (0 != epoll_ctl (daemon->epoll_fd,
2858  EPOLL_CTL_DEL,
2859  connection->socket_fd,
2860  NULL))
2861  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
2862  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2863  }
2864  connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2865  }
2866 #endif
2867 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2869 #endif
2870 }
2871 
2872 
2904 void
2906 {
2907  struct MHD_Daemon *const daemon = connection->daemon;
2908 
2909  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2910  MHD_PANIC (_ (
2911  "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2912 #ifdef UPGRADE_SUPPORT
2913  if (NULL != connection->urh)
2914  {
2915 #ifdef HAVE_MESSAGES
2916  MHD_DLOG (daemon,
2917  _ (
2918  "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
2919 #endif /* HAVE_MESSAGES */
2920  return;
2921  }
2922 #endif /* UPGRADE_SUPPORT */
2923  internal_suspend_connection_ (connection);
2924 }
2925 
2926 
2935 void
2937 {
2938  struct MHD_Daemon *daemon = connection->daemon;
2939 
2940  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2941  MHD_PANIC (_ (
2942  "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2943 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2945 #endif
2946  connection->resuming = true;
2947  daemon->resuming = true;
2948 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2950 #endif
2951  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2952  (! MHD_itc_activate_ (daemon->itc, "r")) )
2953  {
2954 #ifdef HAVE_MESSAGES
2955  MHD_DLOG (daemon,
2956  _ (
2957  "Failed to signal resume via inter-thread communication channel.\n"));
2958 #endif
2959  }
2960 }
2961 
2962 
2972 static enum MHD_Result
2974 {
2975  struct MHD_Connection *pos;
2976  struct MHD_Connection *prev = NULL;
2977  enum MHD_Result ret;
2978  const bool used_thr_p_c = (0 != (daemon->options
2980 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2982 #endif
2983  ret = MHD_NO;
2984 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2986 #endif
2987  if (daemon->resuming)
2988  {
2990  /* During shutdown check for resuming is forced. */
2991  mhd_assert ((NULL != prev) || (daemon->shutdown));
2992  }
2993 
2994  daemon->resuming = false;
2995 
2996  while (NULL != (pos = prev))
2997  {
2998 #ifdef UPGRADE_SUPPORT
2999  struct MHD_UpgradeResponseHandle *const urh = pos->urh;
3000 #else /* ! UPGRADE_SUPPORT */
3001  static const void *const urh = NULL;
3002 #endif /* ! UPGRADE_SUPPORT */
3003  prev = pos->prev;
3004  if ( (! pos->resuming)
3005 #ifdef UPGRADE_SUPPORT
3006  || ( (NULL != urh) &&
3007  ( (! urh->was_closed) ||
3008  (! urh->clean_ready) ) )
3009 #endif /* UPGRADE_SUPPORT */
3010  )
3011  continue;
3012  ret = MHD_YES;
3013  mhd_assert (pos->suspended);
3016  pos);
3017  pos->suspended = false;
3018  if (NULL == urh)
3019  {
3020  DLL_insert (daemon->connections_head,
3021  daemon->connections_tail,
3022  pos);
3023  if (! used_thr_p_c)
3024  {
3025  /* Reset timeout timer on resume. */
3026  if (0 != pos->connection_timeout)
3028 
3029  if (pos->connection_timeout == daemon->connection_timeout)
3031  daemon->normal_timeout_tail,
3032  pos);
3033  else
3035  daemon->manual_timeout_tail,
3036  pos);
3037  }
3038 #ifdef EPOLL_SUPPORT
3039  if (0 != (daemon->options & MHD_USE_EPOLL))
3040  {
3041  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3042  MHD_PANIC ("Resumed connection was already in EREADY set.\n");
3043  /* we always mark resumed connections as ready, as we
3044  might have missed the edge poll event during suspension */
3045  EDLL_insert (daemon->eready_head,
3046  daemon->eready_tail,
3047  pos);
3048  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL \
3051  pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
3052  }
3053 #endif
3054  }
3055 #ifdef UPGRADE_SUPPORT
3056  else
3057  {
3058  /* Data forwarding was finished (for TLS connections) AND
3059  * application was closed upgraded connection.
3060  * Insert connection into cleanup list. */
3061 
3062  if ( (NULL != daemon->notify_completed) &&
3063  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3064  (pos->client_aware) )
3065  {
3066  daemon->notify_completed (daemon->notify_completed_cls,
3067  pos,
3068  &pos->client_context,
3070  pos->client_aware = false;
3071  }
3072  DLL_insert (daemon->cleanup_head,
3073  daemon->cleanup_tail,
3074  pos);
3075 
3076  }
3077 #endif /* UPGRADE_SUPPORT */
3078  pos->resuming = false;
3079  }
3080 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3082 #endif
3083  if ( (used_thr_p_c) &&
3084  (MHD_NO != ret) )
3085  { /* Wake up suspended connections. */
3086  if (! MHD_itc_activate_ (daemon->itc,
3087  "w"))
3088  {
3089 #ifdef HAVE_MESSAGES
3090  MHD_DLOG (daemon,
3091  _ (
3092  "Failed to signal resume of connection via inter-thread communication channel.\n"));
3093 #endif
3094  }
3095  }
3096  return ret;
3097 }
3098 
3099 
3127 enum MHD_Result
3128 MHD_add_connection (struct MHD_Daemon *daemon,
3129  MHD_socket client_socket,
3130  const struct sockaddr *addr,
3131  socklen_t addrlen)
3132 {
3133  bool sk_nonbl;
3134 
3135  MHD_cleanup_connections (daemon);
3136  if (! MHD_socket_nonblocking_ (client_socket))
3137  {
3138 #ifdef HAVE_MESSAGES
3139  MHD_DLOG (daemon,
3140  _ ("Failed to set nonblocking mode on new client socket: %s\n"),
3142 #endif
3143  sk_nonbl = false;
3144  }
3145  else
3146  sk_nonbl = true;
3147 
3148  if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3149  (! MHD_socket_noninheritable_ (client_socket)) )
3150  {
3151 #ifdef HAVE_MESSAGES
3152  MHD_DLOG (daemon,
3153  _ ("Failed to set noninheritable mode on new client socket.\n"));
3154 #endif
3155  }
3156 
3157  if ( (0 == (daemon->options & MHD_USE_TURBO)) &&
3158  (! MHD_socket_buffering_reset_ (client_socket)) )
3159  {
3160 #ifdef HAVE_MESSAGES
3161  MHD_DLOG (daemon,
3162  _ ("Failed to reset buffering mode on new client socket.\n"));
3163 #endif
3164  }
3165  return internal_add_connection (daemon,
3166  client_socket,
3167  addr,
3168  addrlen,
3169  true,
3170  sk_nonbl);
3171 }
3172 
3173 
3188 static enum MHD_Result
3189 MHD_accept_connection (struct MHD_Daemon *daemon)
3190 {
3191 #if HAVE_INET6
3192  struct sockaddr_in6 addrstorage;
3193 #else
3194  struct sockaddr_in addrstorage;
3195 #endif
3196  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3197  socklen_t addrlen;
3198  MHD_socket s;
3199  MHD_socket fd;
3200  bool sk_nonbl;
3201 
3202  addrlen = sizeof (addrstorage);
3203  memset (addr,
3204  0,
3205  sizeof (addrstorage));
3206  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3207  (daemon->was_quiesced) )
3208  return MHD_NO;
3209 #ifdef USE_ACCEPT4
3210  s = accept4 (fd,
3211  addr,
3212  &addrlen,
3214  sk_nonbl = (MAYBE_SOCK_NONBLOCK != 0);
3215 #else /* ! USE_ACCEPT4 */
3216  s = accept (fd,
3217  addr,
3218  &addrlen);
3219  sk_nonbl = false;
3220 #endif /* ! USE_ACCEPT4 */
3221  if ( (MHD_INVALID_SOCKET == s) ||
3222  (addrlen <= 0) )
3223  {
3224  const int err = MHD_socket_get_error_ ();
3225 
3226  /* This could be a common occurrence with multiple worker threads */
3227  if (MHD_SCKT_ERR_IS_ (err,
3229  return MHD_NO; /* can happen during shutdown */
3231  return MHD_NO; /* do not print error if client just disconnected early */
3232 #ifdef HAVE_MESSAGES
3233  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3234  MHD_DLOG (daemon,
3235  _ ("Error accepting connection: %s\n"),
3236  MHD_socket_strerr_ (err));
3237 #endif
3238  if (MHD_INVALID_SOCKET != s)
3239  {
3241  }
3242  if (MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
3243  {
3244  /* system/process out of resources */
3245  if (0 == daemon->connections)
3246  {
3247 #ifdef HAVE_MESSAGES
3248  /* Not setting 'at_limit' flag, as there is no way it
3249  would ever be cleared. Instead trying to produce
3250  bit fat ugly warning. */
3251  MHD_DLOG (daemon,
3252  _ (
3253  "Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
3254 #endif
3255  }
3256  else
3257  {
3258 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3260 #endif
3261  daemon->at_limit = true;
3262 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3264 #endif
3265 #ifdef HAVE_MESSAGES
3266  MHD_DLOG (daemon,
3267  _ (
3268  "Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3269  (unsigned int) daemon->connections);
3270 #endif
3271  }
3272  }
3273  return MHD_NO;
3274  }
3275 #if defined(MHD_TCP_CORK_NOPUSH) || defined(HAVE_MSG_MORE)
3276  /* We will use TCP_CORK or TCP_NOPUSH or MSG_MORE to control
3277  transmission, disable Nagle's algorithm (always) */
3278  if ( (0 != MHD_socket_set_nodelay_ (s,
3279  true)) &&
3280  (EOPNOTSUPP != errno) )
3281  {
3282 #ifdef HAVE_MESSAGES
3283  MHD_DLOG (daemon,
3284  _ ("Failed to disable TCP Nagle on socket: %s\n"),
3286 #endif
3287  }
3288 #endif
3289 #if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
3290  if (! MHD_socket_nonblocking_ (s))
3291  {
3292 #ifdef HAVE_MESSAGES
3293  MHD_DLOG (daemon,
3294  _ (
3295  "Failed to set nonblocking mode on incoming connection socket: %s\n"),
3297 #endif
3298  }
3299  else
3300  sk_nonbl = true;
3301 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
3302 #if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
3303  if (! MHD_socket_noninheritable_ (s))
3304  {
3305 #ifdef HAVE_MESSAGES
3306  MHD_DLOG (daemon,
3307  _ (
3308  "Failed to set noninheritable mode on incoming connection socket.\n"));
3309 #endif
3310  }
3311 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
3312 #ifdef HAVE_MESSAGES
3313 #if DEBUG_CONNECT
3314  MHD_DLOG (daemon,
3315  _ ("Accepted connection on socket %d\n"),
3316  s);
3317 #endif
3318 #endif
3319  (void) internal_add_connection (daemon,
3320  s,
3321  addr,
3322  addrlen,
3323  false,
3324  sk_nonbl);
3325  return MHD_YES;
3326 }
3327 
3328 
3338 static void
3340 {
3341  struct MHD_Connection *pos;
3342 
3343 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3345 #endif
3346  while (NULL != (pos = daemon->cleanup_tail))
3347  {
3350  pos);
3351 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3353  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3354  (! pos->thread_joined) &&
3355  (! MHD_join_thread_ (pos->pid.handle)) )
3356  MHD_PANIC (_ ("Failed to join a thread.\n"));
3357 #endif
3358 #ifdef UPGRADE_SUPPORT
3359  cleanup_upgraded_connection (pos);
3360 #endif /* UPGRADE_SUPPORT */
3361  MHD_pool_destroy (pos->pool);
3362 #ifdef HTTPS_SUPPORT
3363  if (NULL != pos->tls_session)
3364  gnutls_deinit (pos->tls_session);
3365 #endif /* HTTPS_SUPPORT */
3366 
3367  /* clean up the connection */
3368  if (NULL != daemon->notify_connection)
3370  pos,
3371  &pos->socket_context,
3374  pos->addr,
3375  pos->addr_len);
3376 #ifdef EPOLL_SUPPORT
3377  if (0 != (daemon->options & MHD_USE_EPOLL))
3378  {
3379  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3380  {
3381  EDLL_remove (daemon->eready_head,
3382  daemon->eready_tail,
3383  pos);
3384  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3385  }
3386  if ( (-1 != daemon->epoll_fd) &&
3387  (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3388  {
3389  /* epoll documentation suggests that closing a FD
3390  automatically removes it from the epoll set; however,
3391  this is not true as if we fail to do manually remove it,
3392  we are still seeing an event for this fd in epoll,
3393  causing grief (use-after-free...) --- at least on my
3394  system. */if (0 != epoll_ctl (daemon->epoll_fd,
3395  EPOLL_CTL_DEL,
3396  pos->socket_fd,
3397  NULL))
3398  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
3399  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3400  }
3401  }
3402 #endif
3403  if (NULL != pos->response)
3404  {
3406  pos->response = NULL;
3407  }
3408  if (MHD_INVALID_SOCKET != pos->socket_fd)
3410  if (NULL != pos->addr)
3411  free (pos->addr);
3412  free (pos);
3413 
3414 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3416 #endif
3417  daemon->connections--;
3418  daemon->at_limit = false;
3419  }
3420 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3422 #endif
3423 }
3424 
3425 
3446 enum MHD_Result
3448  MHD_UNSIGNED_LONG_LONG *timeout)
3449 {
3450  time_t earliest_deadline;
3451  time_t now;
3452  struct MHD_Connection *pos;
3453  bool have_timeout;
3454 
3456  {
3457 #ifdef HAVE_MESSAGES
3458  MHD_DLOG (daemon,
3459  _ ("Illegal call to MHD_get_timeout.\n"));
3460 #endif
3461  return MHD_NO;
3462  }
3463 
3465  {
3466  /* Some data already waiting to be processed. */
3467  *timeout = 0;
3468  return MHD_YES;
3469  }
3470 
3471 #ifdef EPOLL_SUPPORT
3472  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3473  ((NULL != daemon->eready_head)
3474 #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3475  || (NULL != daemon->eready_urh_head)
3476 #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3477  ) )
3478  {
3479  /* Some connection(s) already have some data pending. */
3480  *timeout = 0;
3481  return MHD_YES;
3482  }
3483 #endif /* EPOLL_SUPPORT */
3484 
3485  have_timeout = false;
3486  earliest_deadline = 0; /* avoid compiler warnings */
3487  for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3488  {
3489  if (0 != pos->connection_timeout)
3490  {
3491  if ( (! have_timeout) ||
3492  (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3493  earliest_deadline = pos->last_activity + pos->connection_timeout;
3494  have_timeout = true;
3495  }
3496  }
3497  /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3498  pos = daemon->normal_timeout_tail;
3499  if ( (NULL != pos) &&
3500  (0 != pos->connection_timeout) )
3501  {
3502  if ( (! have_timeout) ||
3503  (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3504  earliest_deadline = pos->last_activity + pos->connection_timeout;
3505  have_timeout = true;
3506  }
3507 
3508  if (! have_timeout)
3509  return MHD_NO;
3510  now = MHD_monotonic_sec_counter ();
3511  if (earliest_deadline < now)
3512  *timeout = 0;
3513  else
3514  {
3515  const time_t second_left = earliest_deadline - now;
3516 
3517  if (((unsigned long long) second_left) > ULLONG_MAX / 1000)
3518  *timeout = ULLONG_MAX;
3519  else
3520  *timeout = 1000LLU * (unsigned long long) second_left;
3521  }
3522  return MHD_YES;
3523 }
3524 
3525 
3536 static enum MHD_Result
3538  const fd_set *read_fd_set,
3539  const fd_set *write_fd_set,
3540  const fd_set *except_fd_set)
3541 {
3542  MHD_socket ds;
3543  struct MHD_Connection *pos;
3544  struct MHD_Connection *prev;
3545 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3546  struct MHD_UpgradeResponseHandle *urh;
3547  struct MHD_UpgradeResponseHandle *urhn;
3548 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3549  /* Reset. New value will be set when connections are processed. */
3550  /* Note: no-op for thread-per-connection as it is always false in that mode. */
3551  daemon->data_already_pending = false;
3552 
3553  /* Clear ITC to avoid spinning select */
3554  /* Do it before any other processing so new signals
3555  will trigger select again and will be processed */
3556  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3557  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3558  read_fd_set)) )
3559  MHD_itc_clear_ (daemon->itc);
3560 
3561  /* select connection thread handling type */
3562  if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3563  (! daemon->was_quiesced) &&
3564  (FD_ISSET (ds,
3565  read_fd_set)) )
3566  (void) MHD_accept_connection (daemon);
3567 
3568  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3569  {
3570  /* do not have a thread per connection, process all connections now */
3571  prev = daemon->connections_tail;
3572  while (NULL != (pos = prev))
3573  {
3574  prev = pos->prev;
3575  ds = pos->socket_fd;
3576  if (MHD_INVALID_SOCKET == ds)
3577  continue;
3578  call_handlers (pos,
3579  FD_ISSET (ds,
3580  read_fd_set),
3581  FD_ISSET (ds,
3582  write_fd_set),
3583  FD_ISSET (ds,
3584  except_fd_set));
3585  }
3586  }
3587 
3588 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3589  /* handle upgraded HTTPS connections */
3590  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3591  {
3592  urhn = urh->prev;
3593  /* update urh state based on select() output */
3594  urh_from_fdset (urh,
3595  read_fd_set,
3596  write_fd_set,
3597  except_fd_set);
3598  /* call generic forwarding function for passing data */
3599  process_urh (urh);
3600  /* Finished forwarding? */
3601  if ( (0 == urh->in_buffer_size) &&
3602  (0 == urh->out_buffer_size) &&
3603  (0 == urh->in_buffer_used) &&
3604  (0 == urh->out_buffer_used) )
3605  {
3606  MHD_connection_finish_forward_ (urh->connection);
3607  urh->clean_ready = true;
3608  /* Resuming will move connection to cleanup list. */
3609  MHD_resume_connection (urh->connection);
3610  }
3611  }
3612 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3613  MHD_cleanup_connections (daemon);
3614  return MHD_YES;
3615 }
3616 
3617 
3640 enum MHD_Result
3641 MHD_run_from_select (struct MHD_Daemon *daemon,
3642  const fd_set *read_fd_set,
3643  const fd_set *write_fd_set,
3644  const fd_set *except_fd_set)
3645 {
3646  fd_set es;
3647  if (0 != (daemon->options
3649  return MHD_NO;
3650  if ((NULL == read_fd_set) || (NULL == write_fd_set))
3651  return MHD_NO;
3652  if (NULL == except_fd_set)
3653  { /* Workaround to maintain backward compatibility. */
3654 #ifdef HAVE_MESSAGES
3655  MHD_DLOG (daemon,
3656  _ ("MHD_run_from_select() called with except_fd_set "
3657  "set to NULL. Such behavior is deprecated.\n"));
3658 #endif
3659  FD_ZERO (&es);
3660  except_fd_set = &es;
3661  }
3662  if (0 != (daemon->options & MHD_USE_EPOLL))
3663  {
3664 #ifdef EPOLL_SUPPORT
3665  enum MHD_Result ret = MHD_epoll (daemon,
3666  MHD_NO);
3667 
3668  MHD_cleanup_connections (daemon);
3669  return ret;
3670 #else /* ! EPOLL_SUPPORT */
3671  return MHD_NO;
3672 #endif /* ! EPOLL_SUPPORT */
3673  }
3674 
3675  /* Resuming external connections when using an extern mainloop */
3676  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3678 
3679  return internal_run_from_select (daemon,
3680  read_fd_set,
3681  write_fd_set,
3682  except_fd_set);
3683 }
3684 
3685 
3694 static enum MHD_Result
3695 MHD_select (struct MHD_Daemon *daemon,
3696  int may_block)
3697 {
3698  int num_ready;
3699  fd_set rs;
3700  fd_set ws;
3701  fd_set es;
3702  MHD_socket maxsock;
3703  struct timeval timeout;
3704  struct timeval *tv;
3705  MHD_UNSIGNED_LONG_LONG ltimeout;
3706  int err_state;
3707  MHD_socket ls;
3708 
3709  timeout.tv_sec = 0;
3710  timeout.tv_usec = 0;
3711  if (daemon->shutdown)
3712  return MHD_NO;
3713  FD_ZERO (&rs);
3714  FD_ZERO (&ws);
3715  FD_ZERO (&es);
3716  maxsock = MHD_INVALID_SOCKET;
3717  err_state = MHD_NO;
3718  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3719  (MHD_YES == resume_suspended_connections (daemon)) &&
3720  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
3721  may_block = MHD_NO;
3722 
3723  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3724  {
3725  /* single-threaded, go over everything */
3726  if (MHD_NO ==
3727  internal_get_fdset2 (daemon,
3728  &rs,
3729  &ws,
3730  &es,
3731  &maxsock,
3732  FD_SETSIZE))
3733  {
3734 #ifdef HAVE_MESSAGES
3735  MHD_DLOG (daemon,
3736  _ ("Could not obtain daemon fdsets.\n"));
3737 #endif
3738  err_state = MHD_YES;
3739  }
3740  }
3741  else
3742  {
3743  /* accept only, have one thread per connection */
3744  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3745  (! daemon->was_quiesced) &&
3746  (! MHD_add_to_fd_set_ (ls,
3747  &rs,
3748  &maxsock,
3749  FD_SETSIZE)) )
3750  {
3751 #ifdef HAVE_MESSAGES
3752  MHD_DLOG (daemon,
3753  _ ("Could not add listen socket to fdset.\n"));
3754 #endif
3755  return MHD_NO;
3756  }
3757  }
3758  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3759  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3760  &rs,
3761  &maxsock,
3762  FD_SETSIZE)) )
3763  {
3764 #if defined(MHD_WINSOCK_SOCKETS)
3765  /* fdset limit reached, new connections
3766  cannot be handled. Remove listen socket FD
3767  from fdset and retry to add ITC FD. */
3768  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3769  (! daemon->was_quiesced) )
3770  {
3771  FD_CLR (ls,
3772  &rs);
3773  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3774  &rs,
3775  &maxsock,
3776  FD_SETSIZE))
3777  {
3778 #endif /* MHD_WINSOCK_SOCKETS */
3779 #ifdef HAVE_MESSAGES
3780  MHD_DLOG (daemon,
3781  _ (
3782  "Could not add control inter-thread communication channel FD to fdset.\n"));
3783 #endif
3784  err_state = MHD_YES;
3785 #if defined(MHD_WINSOCK_SOCKETS)
3786  }
3787 }
3788 
3789 
3790 #endif /* MHD_WINSOCK_SOCKETS */
3791  }
3792  /* Stop listening if we are at the configured connection limit */
3793  /* If we're at the connection limit, no point in really
3794  accepting new connections; however, make sure we do not miss
3795  the shutdown OR the termination of an existing connection; so
3796  only do this optimization if we have a signaling ITC in
3797  place. */
3798  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3799  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3800  ( (daemon->connections == daemon->connection_limit) ||
3801  (daemon->at_limit) ) )
3802  {
3803  FD_CLR (ls,
3804  &rs);
3805  }
3806  tv = NULL;
3807  if (MHD_YES == err_state)
3808  may_block = MHD_NO;
3809  if (MHD_NO == may_block)
3810  {
3811  timeout.tv_usec = 0;
3812  timeout.tv_sec = 0;
3813  tv = &timeout;
3814  }
3815  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3816  (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
3817  {
3818  /* ltimeout is in ms */
3819  timeout.tv_usec = (ltimeout % 1000) * 1000;
3820  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
3821  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
3822  else
3823  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
3824  tv = &timeout;
3825  }
3826  num_ready = MHD_SYS_select_ (maxsock + 1,
3827  &rs,
3828  &ws,
3829  &es,
3830  tv);
3831  if (daemon->shutdown)
3832  return MHD_NO;
3833  if (num_ready < 0)
3834  {
3835  const int err = MHD_socket_get_error_ ();
3836  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3837  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3838 #ifdef HAVE_MESSAGES
3839  MHD_DLOG (daemon,
3840  _ ("select failed: %s\n"),
3841  MHD_socket_strerr_ (err));
3842 #endif
3843  return MHD_NO;
3844  }
3845  if (MHD_YES == internal_run_from_select (daemon,
3846  &rs,
3847  &ws,
3848  &es))
3849  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3850  return MHD_NO;
3851 }
3852 
3853 
3854 #ifdef HAVE_POLL
3855 
3863 static enum MHD_Result
3864 MHD_poll_all (struct MHD_Daemon *daemon,
3865  int may_block)
3866 {
3867  unsigned int num_connections;
3868  struct MHD_Connection *pos;
3869  struct MHD_Connection *prev;
3870 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3871  struct MHD_UpgradeResponseHandle *urh;
3872  struct MHD_UpgradeResponseHandle *urhn;
3873 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3874 
3875  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3876  (MHD_YES == resume_suspended_connections (daemon)) )
3877  may_block = MHD_NO;
3878 
3879  /* count number of connections and thus determine poll set size */
3880  num_connections = 0;
3881  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3882  num_connections++;
3883 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3884  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3885  num_connections += 2;
3886 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3887  {
3888  MHD_UNSIGNED_LONG_LONG ltimeout;
3889  unsigned int i;
3890  int timeout;
3891  unsigned int poll_server;
3892  int poll_listen;
3893  int poll_itc_idx;
3894  struct pollfd *p;
3895  MHD_socket ls;
3896 
3897  p = MHD_calloc_ ((2 + (size_t) num_connections),
3898  sizeof (struct pollfd));
3899  if (NULL == p)
3900  {
3901 #ifdef HAVE_MESSAGES
3902  MHD_DLOG (daemon,
3903  _ ("Error allocating memory: %s\n"),
3904  MHD_strerror_ (errno));
3905 #endif
3906  return MHD_NO;
3907  }
3908  poll_server = 0;
3909  poll_listen = -1;
3910  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3911  (! daemon->was_quiesced) &&
3912  (daemon->connections < daemon->connection_limit) &&
3913  (! daemon->at_limit) )
3914  {
3915  /* only listen if we are not at the connection limit */
3916  p[poll_server].fd = ls;
3917  p[poll_server].events = POLLIN;
3918  p[poll_server].revents = 0;
3919  poll_listen = (int) poll_server;
3920  poll_server++;
3921  }
3922  poll_itc_idx = -1;
3923  if (MHD_ITC_IS_VALID_ (daemon->itc))
3924  {
3925  p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3926  p[poll_server].events = POLLIN;
3927  p[poll_server].revents = 0;
3928  poll_itc_idx = (int) poll_server;
3929  poll_server++;
3930  }
3931  if (may_block == MHD_NO)
3932  timeout = 0;
3933  else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3934  (MHD_YES != MHD_get_timeout (daemon,
3935  &ltimeout)) )
3936  timeout = -1;
3937  else
3938  timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3939 
3940  i = 0;
3941  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
3942  {
3943  p[poll_server + i].fd = pos->socket_fd;
3944  switch (pos->event_loop_info)
3945  {
3947  p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3948  break;
3950  p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3951  break;
3953  p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
3954  break;
3956  timeout = 0; /* clean up "pos" immediately */
3957  break;
3958  }
3959  i++;
3960  }
3961 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3962  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3963  {
3964  urh_to_pollfd (urh, &(p[poll_server + i]));
3965  i += 2;
3966  }
3967 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3968  if (0 == poll_server + num_connections)
3969  {
3970  free (p);
3971  return MHD_YES;
3972  }
3973  if (MHD_sys_poll_ (p,
3974  poll_server + num_connections,
3975  timeout) < 0)
3976  {
3977  const int err = MHD_socket_get_error_ ();
3978  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3979  {
3980  free (p);
3981  return MHD_YES;
3982  }
3983 #ifdef HAVE_MESSAGES
3984  MHD_DLOG (daemon,
3985  _ ("poll failed: %s\n"),
3986  MHD_socket_strerr_ (err));
3987 #endif
3988  free (p);
3989  return MHD_NO;
3990  }
3991 
3992  /* Reset. New value will be set when connections are processed. */
3993  daemon->data_already_pending = false;
3994 
3995  /* handle ITC FD */
3996  /* do it before any other processing so
3997  new signals will be processed in next loop */
3998  if ( (-1 != poll_itc_idx) &&
3999  (0 != (p[poll_itc_idx].revents & POLLIN)) )
4000  MHD_itc_clear_ (daemon->itc);
4001 
4002  /* handle shutdown */
4003  if (daemon->shutdown)
4004  {
4005  free (p);
4006  return MHD_NO;
4007  }
4008  i = 0;
4009  prev = daemon->connections_tail;
4010  while (NULL != (pos = prev))
4011  {
4012  prev = pos->prev;
4013  /* first, sanity checks */
4014  if (i >= num_connections)
4015  break; /* connection list changed somehow, retry later ... */
4016  if (p[poll_server + i].fd != pos->socket_fd)
4017  continue; /* fd mismatch, something else happened, retry later ... */
4018  call_handlers (pos,
4019  0 != (p[poll_server + i].revents & POLLIN),
4020  0 != (p[poll_server + i].revents & POLLOUT),
4021  0 != (p[poll_server + i].revents
4022  & MHD_POLL_REVENTS_ERR_DISC));
4023  i++;
4024  }
4025 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4026  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
4027  {
4028  if (i >= num_connections)
4029  break; /* connection list changed somehow, retry later ... */
4030 
4031  /* Get next connection here as connection can be removed
4032  * from 'daemon->urh_head' list. */
4033  urhn = urh->prev;
4034  /* Check for fd mismatch. FIXME: required for safety? */
4035  if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
4036  (p[poll_server + i + 1].fd != urh->mhd.socket))
4037  break;
4038  urh_from_pollfd (urh,
4039  &p[poll_server + i]);
4040  i += 2;
4041  process_urh (urh);
4042  /* Finished forwarding? */
4043  if ( (0 == urh->in_buffer_size) &&
4044  (0 == urh->out_buffer_size) &&
4045  (0 == urh->in_buffer_used) &&
4046  (0 == urh->out_buffer_used) )
4047  {
4048  /* MHD_connection_finish_forward_() will remove connection from
4049  * 'daemon->urh_head' list. */
4050  MHD_connection_finish_forward_ (urh->connection);
4051  urh->clean_ready = true;
4052  /* If 'urh->was_closed' already was set to true, connection will be
4053  * moved immediately to cleanup list. Otherwise connection
4054  * will stay in suspended list until 'urh' will be marked
4055  * with 'was_closed' by application. */
4056  MHD_resume_connection (urh->connection);
4057  }
4058  }
4059 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4060  /* handle 'listen' FD */
4061  if ( (-1 != poll_listen) &&
4062  (0 != (p[poll_listen].revents & POLLIN)) )
4063  (void) MHD_accept_connection (daemon);
4064 
4065  free (p);
4066  }
4067  return MHD_YES;
4068 }
4069 
4070 
4078 static enum MHD_Result
4079 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
4080  int may_block)
4081 {
4082  struct pollfd p[2];
4083  int timeout;
4084  unsigned int poll_count;
4085  int poll_listen;
4086  int poll_itc_idx;
4087  MHD_socket ls;
4088 
4089  memset (&p,
4090  0,
4091  sizeof (p));
4092  poll_count = 0;
4093  poll_listen = -1;
4094  poll_itc_idx = -1;
4095  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4096  (! daemon->was_quiesced) )
4097 
4098  {
4099  p[poll_count].fd = ls;
4100  p[poll_count].events = POLLIN;
4101  p[poll_count].revents = 0;
4102  poll_listen = poll_count;
4103  poll_count++;
4104  }
4105  if (MHD_ITC_IS_VALID_ (daemon->itc))
4106  {
4107  p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
4108  p[poll_count].events = POLLIN;
4109  p[poll_count].revents = 0;
4110  poll_itc_idx = poll_count;
4111  poll_count++;
4112  }
4113 
4114  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4115  (void) resume_suspended_connections (daemon);
4116 
4117  if (MHD_NO == may_block)
4118  timeout = 0;
4119  else
4120  timeout = -1;
4121  if (0 == poll_count)
4122  return MHD_YES;
4123  if (MHD_sys_poll_ (p,
4124  poll_count,
4125  timeout) < 0)
4126  {
4127  const int err = MHD_socket_get_error_ ();
4128 
4129  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4130  return MHD_YES;
4131 #ifdef HAVE_MESSAGES
4132  MHD_DLOG (daemon,
4133  _ ("poll failed: %s\n"),
4134  MHD_socket_strerr_ (err));
4135 #endif
4136  return MHD_NO;
4137  }
4138  if ( (-1 != poll_itc_idx) &&
4139  (0 != (p[poll_itc_idx].revents & POLLIN)) )
4140  MHD_itc_clear_ (daemon->itc);
4141 
4142  /* handle shutdown */
4143  if (daemon->shutdown)
4144  return MHD_NO;
4145  if ( (-1 != poll_listen) &&
4146  (0 != (p[poll_listen].revents & POLLIN)) )
4147  (void) MHD_accept_connection (daemon);
4148  return MHD_YES;
4149 }
4150 
4151 
4152 #endif
4153 
4154 
4162 static enum MHD_Result
4163 MHD_poll (struct MHD_Daemon *daemon,
4164  int may_block)
4165 {
4166 #ifdef HAVE_POLL
4167  if (daemon->shutdown)
4168  return MHD_NO;
4169  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4170  return MHD_poll_all (daemon,
4171  may_block);
4172  return MHD_poll_listen_socket (daemon,
4173  may_block);
4174 #else
4175  (void) daemon;
4176  (void) may_block;
4177  return MHD_NO;
4178 #endif
4179 }
4180 
4181 
4182 #ifdef EPOLL_SUPPORT
4183 
4192 #define MAX_EVENTS 128
4193 
4194 
4195 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4196 
4204 static bool
4205 is_urh_ready (struct MHD_UpgradeResponseHandle *const urh)
4206 {
4207  const struct MHD_Connection *const connection = urh->connection;
4208 
4209  if ( (0 == urh->in_buffer_size) &&
4210  (0 == urh->out_buffer_size) &&
4211  (0 == urh->in_buffer_used) &&
4212  (0 == urh->out_buffer_used) )
4213  return false;
4214  if (connection->daemon->shutdown)
4215  return true;
4216  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4217  (connection->tls_read_ready) ) &&
4218  (urh->in_buffer_used < urh->in_buffer_size) )
4219  return true;
4220  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4221  (urh->out_buffer_used < urh->out_buffer_size) )
4222  return true;
4223  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4224  (urh->out_buffer_used > 0) )
4225  return true;
4226  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4227  (urh->in_buffer_used > 0) )
4228  return true;
4229  return false;
4230 }
4231 
4232 
4241 static enum MHD_Result
4242 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4243 {
4244  struct epoll_event events[MAX_EVENTS];
4245  int num_events;
4246  struct MHD_UpgradeResponseHandle *pos;
4247  struct MHD_UpgradeResponseHandle *prev;
4248 
4249  num_events = MAX_EVENTS;
4250  while (0 != num_events)
4251  {
4252  unsigned int i;
4253  /* update event masks */
4254  num_events = epoll_wait (daemon->epoll_upgrade_fd,
4255  events,
4256  MAX_EVENTS,
4257  0);
4258  if (-1 == num_events)
4259  {
4260  const int err = MHD_socket_get_error_ ();
4261 
4262  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4263  return MHD_YES;
4264 #ifdef HAVE_MESSAGES
4265  MHD_DLOG (daemon,
4266  _ ("Call to epoll_wait failed: %s\n"),
4267  MHD_socket_strerr_ (err));
4268 #endif
4269  return MHD_NO;
4270  }
4271  for (i = 0; i < (unsigned int) num_events; i++)
4272  {
4273  struct UpgradeEpollHandle *const ueh = events[i].data.ptr;
4274  struct MHD_UpgradeResponseHandle *const urh = ueh->urh;
4275  bool new_err_state = false;
4276 
4277  if (urh->clean_ready)
4278  continue;
4279 
4280  /* Update ueh state based on what is ready according to epoll() */
4281  if (0 != (events[i].events & EPOLLIN))
4282  ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4283  if (0 != (events[i].events & EPOLLOUT))
4284  ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4285  if (0 != (events[i].events & EPOLLHUP))
4287 
4288  if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4289  (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4290  {
4291  /* Process new error state only one time
4292  * and avoid continuously marking this connection
4293  * as 'ready'. */
4294  ueh->celi |= MHD_EPOLL_STATE_ERROR;
4295  new_err_state = true;
4296  }
4297 
4298  if (! urh->in_eready_list)
4299  {
4300  if (new_err_state ||
4301  is_urh_ready (urh))
4302  {
4303  EDLL_insert (daemon->eready_urh_head,
4304  daemon->eready_urh_tail,
4305  urh);
4306  urh->in_eready_list = true;
4307  }
4308  }
4309  }
4310  }
4311  prev = daemon->eready_urh_tail;
4312  while (NULL != (pos = prev))
4313  {
4314  prev = pos->prevE;
4315  process_urh (pos);
4316  if (! is_urh_ready (pos))
4317  {
4318  EDLL_remove (daemon->eready_urh_head,
4319  daemon->eready_urh_tail,
4320  pos);
4321  pos->in_eready_list = false;
4322  }
4323  /* Finished forwarding? */
4324  if ( (0 == pos->in_buffer_size) &&
4325  (0 == pos->out_buffer_size) &&
4326  (0 == pos->in_buffer_used) &&
4327  (0 == pos->out_buffer_used) )
4328  {
4329  MHD_connection_finish_forward_ (pos->connection);
4330  pos->clean_ready = true;
4331  /* If 'pos->was_closed' already was set to true, connection
4332  * will be moved immediately to cleanup list. Otherwise
4333  * connection will stay in suspended list until 'pos' will
4334  * be marked with 'was_closed' by application. */
4335  MHD_resume_connection (pos->connection);
4336  }
4337  }
4338 
4339  return MHD_YES;
4340 }
4341 
4342 
4343 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4344 
4345 
4349 static const char *const epoll_itc_marker = "itc_marker";
4350 
4351 
4360 static enum MHD_Result
4361 MHD_epoll (struct MHD_Daemon *daemon,
4362  int may_block)
4363 {
4364 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4365  static const char *const upgrade_marker = "upgrade_ptr";
4366 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4367  struct MHD_Connection *pos;
4368  struct MHD_Connection *prev;
4369  struct epoll_event events[MAX_EVENTS];
4370  struct epoll_event event;
4371  int timeout_ms;
4372  MHD_UNSIGNED_LONG_LONG timeout_ll;
4373  int num_events;
4374  unsigned int i;
4375  MHD_socket ls;
4376 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4377  bool run_upgraded = false;
4378 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4379 
4380  if (-1 == daemon->epoll_fd)
4381  return MHD_NO; /* we're down! */
4382  if (daemon->shutdown)
4383  return MHD_NO;
4384  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4385  (! daemon->was_quiesced) &&
4386  (daemon->connections < daemon->connection_limit) &&
4387  (! daemon->listen_socket_in_epoll) &&
4388  (! daemon->at_limit) )
4389  {
4390  event.events = EPOLLIN;
4391  event.data.ptr = daemon;
4392  if (0 != epoll_ctl (daemon->epoll_fd,
4393  EPOLL_CTL_ADD,
4394  ls,
4395  &event))
4396  {
4397 #ifdef HAVE_MESSAGES
4398  MHD_DLOG (daemon,
4399  _ ("Call to epoll_ctl failed: %s\n"),
4401 #endif
4402  return MHD_NO;
4403  }
4404  daemon->listen_socket_in_epoll = true;
4405  }
4406  if ( (daemon->was_quiesced) &&
4407  (daemon->listen_socket_in_epoll) )
4408  {
4409  if ( (0 != epoll_ctl (daemon->epoll_fd,
4410  EPOLL_CTL_DEL,
4411  ls,
4412  NULL)) &&
4413  (ENOENT != errno) ) /* ENOENT can happen due to race with
4414  #MHD_quiesce_daemon() */
4415  MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4416  daemon->listen_socket_in_epoll = false;
4417  }
4418 
4419 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4420  if ( ( (! daemon->upgrade_fd_in_epoll) &&
4421  (-1 != daemon->epoll_upgrade_fd) ) )
4422  {
4423  event.events = EPOLLIN | EPOLLOUT;
4424  event.data.ptr = (void *) upgrade_marker;
4425  if (0 != epoll_ctl (daemon->epoll_fd,
4426  EPOLL_CTL_ADD,
4427  daemon->epoll_upgrade_fd,
4428  &event))
4429  {
4430 #ifdef HAVE_MESSAGES
4431  MHD_DLOG (daemon,
4432  _ ("Call to epoll_ctl failed: %s\n"),
4434 #endif
4435  return MHD_NO;
4436  }
4437  daemon->upgrade_fd_in_epoll = true;
4438  }
4439 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4440  if ( (daemon->listen_socket_in_epoll) &&
4441  ( (daemon->connections == daemon->connection_limit) ||
4442  (daemon->at_limit) ||
4443  (daemon->was_quiesced) ) )
4444  {
4445  /* we're at the connection limit, disable listen socket
4446  for event loop for now */
4447  if (0 != epoll_ctl (daemon->epoll_fd,
4448  EPOLL_CTL_DEL,
4449  ls,
4450  NULL))
4451  MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
4452  daemon->listen_socket_in_epoll = false;
4453  }
4454 
4455  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4456  (MHD_YES == resume_suspended_connections (daemon)) )
4457  may_block = MHD_NO;
4458 
4459  if (MHD_YES == may_block)
4460  {
4461  if (MHD_YES == MHD_get_timeout (daemon,
4462  &timeout_ll))
4463  {
4464  if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4465  timeout_ms = INT_MAX;
4466  else
4467  timeout_ms = (int) timeout_ll;
4468  }
4469  else
4470  timeout_ms = -1;
4471  }
4472  else
4473  timeout_ms = 0;
4474 
4475  /* Reset. New value will be set when connections are processed. */
4476  /* Note: Used mostly for uniformity here as same situation is
4477  * signaled in epoll mode by non-empty eready DLL. */
4478  daemon->data_already_pending = false;
4479 
4480  /* drain 'epoll' event queue; need to iterate as we get at most
4481  MAX_EVENTS in one system call here; in practice this should
4482  pretty much mean only one round, but better an extra loop here
4483  than unfair behavior... */
4484  num_events = MAX_EVENTS;
4485  while (MAX_EVENTS == num_events)
4486  {
4487  /* update event masks */
4488  num_events = epoll_wait (daemon->epoll_fd,
4489  events,
4490  MAX_EVENTS,
4491  timeout_ms);
4492  if (-1 == num_events)
4493  {
4494  const int err = MHD_socket_get_error_ ();
4495  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4496  return MHD_YES;
4497 #ifdef HAVE_MESSAGES
4498  MHD_DLOG (daemon,
4499  _ ("Call to epoll_wait failed: %s\n"),
4500  MHD_socket_strerr_ (err));
4501 #endif
4502  return MHD_NO;
4503  }
4504  for (i = 0; i<(unsigned int) num_events; i++)
4505  {
4506  /* First, check for the values of `ptr` that would indicate
4507  that this event is not about a normal connection. */
4508  if (NULL == events[i].data.ptr)
4509  continue; /* shutdown signal! */
4510 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4511  if (upgrade_marker == events[i].data.ptr)
4512  {
4513  /* activity on an upgraded connection, we process
4514  those in a separate epoll() */
4515  run_upgraded = true;
4516  continue;
4517  }
4518 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4519  if (epoll_itc_marker == events[i].data.ptr)
4520  {
4521  /* It's OK to clear ITC here as all external
4522  conditions will be processed later. */
4523  MHD_itc_clear_ (daemon->itc);
4524  continue;
4525  }
4526  if (daemon == events[i].data.ptr)
4527  {
4528  /* Check for error conditions on listen socket. */
4529  /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4530  if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4531  {
4532  unsigned int series_length = 0;
4533  /* Run 'accept' until it fails or daemon at limit of connections.
4534  * Do not accept more then 10 connections at once. The rest will
4535  * be accepted on next turn (level trigger is used for listen
4536  * socket). */
4537  while ( (MHD_YES == MHD_accept_connection (daemon)) &&
4538  (series_length < 10) &&
4539  (daemon->connections < daemon->connection_limit) &&
4540  (! daemon->at_limit) )
4541  series_length++;
4542  }
4543  continue;
4544  }
4545  /* this is an event relating to a 'normal' connection,
4546  remember the event and if appropriate mark the
4547  connection as 'eready'. */
4548  pos = events[i].data.ptr;
4549  /* normal processing: update read/write data */
4550  if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4551  {
4552  pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4553  if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4554  {
4555  EDLL_insert (daemon->eready_head,
4556  daemon->eready_tail,
4557  pos);
4558  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4559  }
4560  }
4561  else
4562  {
4563  if (0 != (events[i].events & EPOLLIN))
4564  {
4565  pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4566  if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4567  (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4568  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4569  {
4570  EDLL_insert (daemon->eready_head,
4571  daemon->eready_tail,
4572  pos);
4573  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4574  }
4575  }
4576  if (0 != (events[i].events & EPOLLOUT))
4577  {
4578  pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4579  if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
4580  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4581  {
4582  EDLL_insert (daemon->eready_head,
4583  daemon->eready_tail,
4584  pos);
4585  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4586  }
4587  }
4588  }
4589  }
4590  }
4591 
4592 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4593  if (run_upgraded || (NULL != daemon->eready_urh_head))
4594  run_epoll_for_upgrade (daemon);
4595 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4596 
4597  /* process events for connections */
4598  prev = daemon->eready_tail;
4599  while (NULL != (pos = prev))
4600  {
4601  prev = pos->prevE;
4602  call_handlers (pos,
4603  0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
4604  0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
4605  0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
4607  (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED
4609  {
4610  if ( ((MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) &&
4611  (0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ||
4613  (0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ) ||
4615  {
4616  EDLL_remove (daemon->eready_head,
4617  daemon->eready_tail,
4618  pos);
4619  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4620  }
4621  }
4622  }
4623 
4624  /* Finally, handle timed-out connections; we need to do this here
4625  as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
4626  as the other event loops do. As timeouts do not get an explicit
4627  event, we need to find those connections that might have timed out
4628  here.
4629 
4630  Connections with custom timeouts must all be looked at, as we
4631  do not bother to sort that (presumably very short) list. */prev = daemon->manual_timeout_tail;
4632  while (NULL != (pos = prev))
4633  {
4634  prev = pos->prevX;
4636  }
4637  /* Connections with the default timeout are sorted by prepending
4638  them to the head of the list whenever we touch the connection;
4639  thus it suffices to iterate from the tail until the first
4640  connection is NOT timed out */
4641  prev = daemon->normal_timeout_tail;
4642  while (NULL != (pos = prev))
4643  {
4644  prev = pos->prevX;
4646  if (MHD_CONNECTION_CLOSED != pos->state)
4647  break; /* sorted by timeout, no need to visit the rest! */
4648  }
4649  return MHD_YES;
4650 }
4651 
4652 
4653 #endif
4654 
4655 
4676 enum MHD_Result
4677 MHD_run (struct MHD_Daemon *daemon)
4678 {
4679  if ( (daemon->shutdown) ||
4680  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4681  return MHD_NO;
4682  if (0 != (daemon->options & MHD_USE_POLL))
4683  {
4684  MHD_poll (daemon, MHD_NO);
4685  MHD_cleanup_connections (daemon);
4686  }
4687 #ifdef EPOLL_SUPPORT
4688  else if (0 != (daemon->options & MHD_USE_EPOLL))
4689  {
4690  MHD_epoll (daemon, MHD_NO);
4691  MHD_cleanup_connections (daemon);
4692  }
4693 #endif
4694  else
4695  {
4696  MHD_select (daemon, MHD_NO);
4697  /* MHD_select does MHD_cleanup_connections already */
4698  }
4699  return MHD_YES;
4700 }
4701 
4702 
4711 static void
4713 {
4714  struct MHD_Daemon *daemon = pos->daemon;
4715 
4716  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4717  {
4719  return; /* must let thread to do the rest */
4720  }
4721  MHD_connection_close_ (pos,
4723 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4725 #endif
4726  mhd_assert (! pos->suspended);
4727  mhd_assert (! pos->resuming);
4728  if (pos->connection_timeout == daemon->connection_timeout)
4730  daemon->normal_timeout_tail,
4731  pos);
4732  else
4734  daemon->manual_timeout_tail,
4735  pos);
4736  DLL_remove (daemon->connections_head,
4737  daemon->connections_tail,
4738  pos);
4739  DLL_insert (daemon->cleanup_head,
4740  daemon->cleanup_tail,
4741  pos);
4742 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4744 #endif
4745 }
4746 
4747 
4748 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4749 
4756 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4757 MHD_polling_thread (void *cls)
4758 {
4759  struct MHD_Daemon *daemon = cls;
4760 
4761  MHD_thread_init_ (&(daemon->pid));
4762  while (! daemon->shutdown)
4763  {
4764  if (0 != (daemon->options & MHD_USE_POLL))
4765  MHD_poll (daemon, MHD_YES);
4766 #ifdef EPOLL_SUPPORT
4767  else if (0 != (daemon->options & MHD_USE_EPOLL))
4768  MHD_epoll (daemon, MHD_YES);
4769 #endif
4770  else
4771  MHD_select (daemon, MHD_YES);
4772  MHD_cleanup_connections (daemon);
4773  }
4774 
4775  /* Resume any pending for resume connections, join
4776  * all connection's threads (if any) and finally cleanup
4777  * everything. */
4778  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
4780  close_all_connections (daemon);
4781 
4782  return (MHD_THRD_RTRN_TYPE_) 0;
4783 }
4784 
4785 
4786 #endif
4787 
4788 
4800 static size_t
4801 unescape_wrapper (void *cls,
4802  struct MHD_Connection *connection,
4803  char *val)
4804 {
4805  (void) cls; /* Mute compiler warning. */
4806 
4807  (void) connection; /* Mute compiler warning. */
4808  return MHD_http_unescape (val);
4809 }
4810 
4811 
4832 struct MHD_Daemon *
4833 MHD_start_daemon (unsigned int flags,
4834  uint16_t port,
4836  void *apc_cls,
4838  void *dh_cls,
4839  ...)
4840 {
4841  struct MHD_Daemon *daemon;
4842  va_list ap;
4843 
4844  va_start (ap,
4845  dh_cls);
4846  daemon = MHD_start_daemon_va (flags,
4847  port,
4848  apc,
4849  apc_cls,
4850  dh,
4851  dh_cls,
4852  ap);
4853  va_end (ap);
4854  return daemon;
4855 }
4856 
4857 
4877 MHD_socket
4879 {
4880 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4881  unsigned int i;
4882 #endif
4883  MHD_socket ret;
4884 
4885  ret = daemon->listen_fd;
4886  if (MHD_INVALID_SOCKET == ret)
4887  return MHD_INVALID_SOCKET;
4888  if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
4889  (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
4890  {
4891 #ifdef HAVE_MESSAGES
4892  MHD_DLOG (daemon,
4893  "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n");
4894 #endif
4895  return MHD_INVALID_SOCKET;
4896  }
4897 
4898 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4899  if (NULL != daemon->worker_pool)
4900  for (i = 0; i < daemon->worker_pool_size; i++)
4901  {
4902  daemon->worker_pool[i].was_quiesced = true;
4903 #ifdef EPOLL_SUPPORT
4904  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4905  (-1 != daemon->worker_pool[i].epoll_fd) &&
4906  (daemon->worker_pool[i].listen_socket_in_epoll) )
4907  {
4908  if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4909  EPOLL_CTL_DEL,
4910  ret,
4911  NULL))
4912  MHD_PANIC (_ ("Failed to remove listen FD from epoll set.\n"));
4913  daemon->worker_pool[i].listen_socket_in_epoll = false;
4914  }
4915  else
4916 #endif
4917  if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
4918  {
4919  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4920  MHD_PANIC (_ (
4921  "Failed to signal quiesce via inter-thread communication channel.\n"));
4922  }
4923  }
4924 #endif
4925  daemon->was_quiesced = true;
4926 #ifdef EPOLL_SUPPORT
4927  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4928  (-1 != daemon->epoll_fd) &&
4929  (daemon->listen_socket_in_epoll) )
4930  {
4931  if ( (0 != epoll_ctl (daemon->epoll_fd,
4932  EPOLL_CTL_DEL,
4933  ret,
4934  NULL)) &&
4935  (ENOENT != errno) ) /* ENOENT can happen due to race with
4936  #MHD_epoll() */
4937  MHD_PANIC ("Failed to remove listen FD from epoll set.\n");
4938  daemon->listen_socket_in_epoll = false;
4939  }
4940 #endif
4941  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
4942  (! MHD_itc_activate_ (daemon->itc, "q")) )
4943  MHD_PANIC (_ (
4944  "failed to signal quiesce via inter-thread communication channel.\n"));
4945  return ret;
4946 }
4947 
4948 
4956 typedef void
4957 (*VfprintfFunctionPointerType)(void *cls,
4958  const char *format,
4959  va_list va);
4960 
4961 
4970 static enum MHD_Result
4971 parse_options_va (struct MHD_Daemon *daemon,
4972  const struct sockaddr **servaddr,
4973  va_list ap);
4974 
4975 
4984 static enum MHD_Result
4985 parse_options (struct MHD_Daemon *daemon,
4986  const struct sockaddr **servaddr,
4987  ...)
4988 {
4989  va_list ap;
4990  enum MHD_Result ret;
4991 
4992  va_start (ap, servaddr);
4993  ret = parse_options_va (daemon,
4994  servaddr,
4995  ap);
4996  va_end (ap);
4997  return ret;
4998 }
4999 
5000 
5009 static enum MHD_Result
5010 parse_options_va (struct MHD_Daemon *daemon,
5011  const struct sockaddr **servaddr,
5012  va_list ap)
5013 {
5014  enum MHD_OPTION opt;
5015  struct MHD_OptionItem *oa;
5016  unsigned int i;
5017  unsigned int uv;
5018 #ifdef HTTPS_SUPPORT
5019  enum MHD_Result ret;
5020  const char *pstr;
5021 #if GNUTLS_VERSION_MAJOR >= 3
5022  gnutls_certificate_retrieve_function2 *pgcrf;
5023 #endif
5024 #if GNUTLS_VERSION_NUMBER >= 0x030603
5025  gnutls_certificate_retrieve_function3 *pgcrf2;
5026 #endif
5027 #endif /* HTTPS_SUPPORT */
5028 
5029  while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
5030  {
5031  switch (opt)
5032  {
5034  daemon->pool_size = va_arg (ap,
5035  size_t);
5036  break;
5038  daemon->pool_increment = va_arg (ap,
5039  size_t);
5040  break;
5042  daemon->connection_limit = va_arg (ap,
5043  unsigned int);
5044  break;
5046  uv = va_arg (ap,
5047  unsigned int);
5048  daemon->connection_timeout = (time_t) uv;
5049  /* Next comparison could be always false on some platforms and whole branch will
5050  * be optimized out on those platforms. On others it will be compiled into real
5051  * check. */
5052  if ( ( (MHD_TYPE_IS_SIGNED_ (time_t)) &&
5053  (daemon->connection_timeout < 0) ) || /* Compiler may warn on some platforms, ignore warning. */
5054  (uv != (unsigned int) daemon->connection_timeout) )
5055  {
5056 #ifdef HAVE_MESSAGES
5057  MHD_DLOG (daemon,
5058  _ ("Warning: Too large timeout value, ignored.\n"));
5059 #endif
5060  daemon->connection_timeout = 0;
5061  }
5062  break;
5064  daemon->notify_completed = va_arg (ap,
5066  daemon->notify_completed_cls = va_arg (ap,
5067  void *);
5068  break;
5070  daemon->notify_connection = va_arg (ap,
5072  daemon->notify_connection_cls = va_arg (ap,
5073  void *);
5074  break;
5076  daemon->per_ip_connection_limit = va_arg (ap,
5077  unsigned int);
5078  break;
5079  case MHD_OPTION_SOCK_ADDR:
5080  *servaddr = va_arg (ap,
5081  const struct sockaddr *);
5082  break;
5084  daemon->uri_log_callback = va_arg (ap,
5085  LogCallback);
5086  daemon->uri_log_callback_cls = va_arg (ap,
5087  void *);
5088  break;
5090  daemon->insanity_level = (enum MHD_DisableSanityCheck)
5091  va_arg (ap,
5092  unsigned int);
5093  break;
5094 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5096  daemon->worker_pool_size = va_arg (ap,
5097  unsigned int);
5098  if (0 == daemon->worker_pool_size)
5099  {
5100 #ifdef HAVE_MESSAGES
5101  MHD_DLOG (daemon,
5102  _ (
5103  "Warning: Zero size, specified for thread pool size, is ignored. "
5104  "Thread pool is not used.\n"));
5105 #endif
5106  }
5107  else if (1 == daemon->worker_pool_size)
5108  {
5109 #ifdef HAVE_MESSAGES
5110  MHD_DLOG (daemon,
5111  _ (
5112  "Warning: \"1\", specified for thread pool size, is ignored. "
5113  "Thread pool is not used.\n"));
5114 #endif
5115  daemon->worker_pool_size = 0;
5116  }
5117  /* Next comparison could be always false on some platforms and whole branch will
5118  * be optimized out on those platforms. On others it will be compiled into real
5119  * check. */
5120  else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct
5121  MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
5122  {
5123 #ifdef HAVE_MESSAGES
5124  MHD_DLOG (daemon,
5125  _ ("Specified thread pool size (%u) too big.\n"),
5126  daemon->worker_pool_size);
5127 #endif
5128  return MHD_NO;
5129  }
5130  else
5131  {
5132  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
5133  {
5134 #ifdef HAVE_MESSAGES
5135  MHD_DLOG (daemon,
5136  _ ("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5137  "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5138 #endif
5139  return MHD_NO;
5140  }
5141  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5142  {
5143 #ifdef HAVE_MESSAGES
5144  MHD_DLOG (daemon,
5145  _ ("Both MHD_OPTION_THREAD_POOL_SIZE option and "
5146  "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5147 #endif
5148  return MHD_NO;
5149  }
5150  }
5151  break;
5152 #endif
5153 #ifdef HTTPS_SUPPORT
5155  pstr = va_arg (ap,
5156  const char *);
5157  if (0 != (daemon->options & MHD_USE_TLS))
5158  daemon->https_mem_key = pstr;
5159 #ifdef HAVE_MESSAGES
5160  else
5161  MHD_DLOG (daemon,
5162  _ (
5163  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5164  opt);
5165 #endif
5166  break;
5168  pstr = va_arg (ap,
5169  const char *);
5170  if (0 != (daemon->options & MHD_USE_TLS))
5171  daemon->https_key_password = pstr;
5172 #ifdef HAVE_MESSAGES
5173  else
5174  MHD_DLOG (daemon,
5175  _ (
5176  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5177  opt);
5178 #endif
5179  break;
5181  pstr = va_arg (ap,
5182  const char *);
5183  if (0 != (daemon->options & MHD_USE_TLS))
5184  daemon->https_mem_cert = pstr;
5185 #ifdef HAVE_MESSAGES
5186  else
5187  MHD_DLOG (daemon,
5188  _ (
5189  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5190  opt);
5191 #endif
5192  break;
5194  pstr = va_arg (ap,
5195  const char *);
5196  if (0 != (daemon->options & MHD_USE_TLS))
5197  daemon->https_mem_trust = pstr;
5198 #ifdef HAVE_MESSAGES
5199  else
5200  MHD_DLOG (daemon,
5201  _ (
5202  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5203  opt);
5204 #endif
5205  break;
5207  daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5208  int);
5209  break;
5211  pstr = va_arg (ap,
5212  const char *);
5213  if (0 != (daemon->options & MHD_USE_TLS))
5214  {
5215  gnutls_datum_t dhpar;
5216  size_t pstr_len;
5217 
5218  if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5219  {
5220 #ifdef HAVE_MESSAGES
5221  MHD_DLOG (daemon,
5222  _ ("Error initializing DH parameters.\n"));
5223 #endif
5224  return MHD_NO;
5225  }
5226  dhpar.data = (unsigned char *) pstr;
5227  pstr_len = strlen (pstr);
5228  if (UINT_MAX < pstr_len)
5229  {
5230 #ifdef HAVE_MESSAGES
5231  MHD_DLOG (daemon,
5232  _ ("Diffie-Hellman parameters string too long.\n"));
5233 #endif
5234  return MHD_NO;
5235  }
5236  dhpar.size = (unsigned int) pstr_len;
5237  if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5238  &dhpar,
5239  GNUTLS_X509_FMT_PEM) < 0)
5240  {
5241 #ifdef HAVE_MESSAGES
5242  MHD_DLOG (daemon,
5243  _ ("Bad Diffie-Hellman parameters format.\n"));
5244 #endif
5245  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5246  return MHD_NO;
5247  }
5248  daemon->have_dhparams = true;
5249  }
5250 #ifdef HAVE_MESSAGES
5251  else
5252  MHD_DLOG (daemon,
5253  _ (
5254  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5255  opt);
5256 #endif
5257  break;
5259  pstr = va_arg (ap,
5260  const char *);
5261  if (0 != (daemon->options & MHD_USE_TLS))
5262  {
5263  gnutls_priority_deinit (daemon->priority_cache);
5264  ret = gnutls_priority_init (&daemon->priority_cache,
5265  pstr,
5266  NULL);
5267  if (GNUTLS_E_SUCCESS != ret)
5268  {
5269 #ifdef HAVE_MESSAGES
5270  MHD_DLOG (daemon,
5271  _ ("Setting priorities to `%s' failed: %s\n"),
5272  pstr,
5273  gnutls_strerror (ret));
5274 #endif
5275  daemon->priority_cache = NULL;
5276  return MHD_NO;
5277  }
5278  }
5279 #ifdef HAVE_MESSAGES
5280  else
5281  MHD_DLOG (daemon,
5282  _ (
5283  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5284  opt);
5285 #endif
5286  break;
5288 #if GNUTLS_VERSION_MAJOR < 3
5289 #ifdef HAVE_MESSAGES
5290  MHD_DLOG (daemon,
5291  _ (
5292  "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5293 #endif
5294  return MHD_NO;
5295 #else
5296  pgcrf = va_arg (ap,
5297  gnutls_certificate_retrieve_function2 *);
5298  if (0 != (daemon->options & MHD_USE_TLS))
5299  daemon->cert_callback = pgcrf;
5300  else
5301 #ifdef HAVE_MESSAGES
5302  MHD_DLOG (daemon,
5303  _ (
5304  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5305  opt);
5306 #endif
5307  break;
5308 #endif
5310 #if GNUTLS_VERSION_NUMBER < 0x030603
5311 #ifdef HAVE_MESSAGES
5312  MHD_DLOG (daemon,
5313  _ (
5314  "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5315 #endif
5316  return MHD_NO;
5317 #else
5318  pgcrf2 = va_arg (ap,
5319  gnutls_certificate_retrieve_function3 *);
5320  if (0 != (daemon->options & MHD_USE_TLS))
5321  daemon->cert_callback2 = pgcrf2;
5322  else
5323 #ifdef HAVE_MESSAGES
5324  MHD_DLOG (daemon,
5325  _ (
5326  "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5327  opt);
5328 #endif
5329  break;
5330 #endif
5331 #endif /* HTTPS_SUPPORT */
5332 #ifdef DAUTH_SUPPORT
5334  daemon->digest_auth_rand_size = va_arg (ap,
5335  size_t);
5336  daemon->digest_auth_random = va_arg (ap,
5337  const char *);
5338  break;
5340  daemon->nonce_nc_size = va_arg (ap,
5341  unsigned int);
5342  break;
5343 #endif
5345  if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5346  {
5347 #ifdef HAVE_MESSAGES
5348  MHD_DLOG (daemon,
5349  _ ("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5350  "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5351 #endif
5352  return MHD_NO;
5353  }
5354  else
5355  daemon->listen_fd = va_arg (ap,
5356  MHD_socket);
5357  break;
5359 #ifdef HAVE_MESSAGES
5360  daemon->custom_error_log = va_arg (ap,
5362  daemon->custom_error_log_cls = va_arg (ap,
5363  void *);
5364 #else
5365  va_arg (ap,
5367  va_arg (ap,
5368  void *);
5369 #endif
5370  break;
5371 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5373  daemon->thread_stack_size = va_arg (ap,
5374  size_t);
5375  break;
5376 #endif
5378 #ifdef TCP_FASTOPEN
5379  daemon->fastopen_queue_size = va_arg (ap,
5380  unsigned int);
5381  break;
5382 #else /* ! TCP_FASTOPEN */
5383 #ifdef HAVE_MESSAGES
5384  MHD_DLOG (daemon,
5385  _ ("TCP fastopen is not supported on this platform.\n"));
5386  return MHD_NO;
5387 #endif /* HAVE_MESSAGES */
5388 #endif /* ! TCP_FASTOPEN */
5390  daemon->listening_address_reuse = va_arg (ap,
5391  unsigned int) ? 1 : -1;
5392  break;
5394  daemon->listen_backlog_size = va_arg (ap,
5395  unsigned int);
5396  break;
5398  daemon->strict_for_client = va_arg (ap, int);
5399 #ifdef HAVE_MESSAGES
5400  if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
5401  (1 != daemon->strict_for_client) )
5402  {
5403  MHD_DLOG (daemon,
5404  _ ("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5405  "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5406  }
5407 #endif /* HAVE_MESSAGES */
5408  break;
5409  case MHD_OPTION_ARRAY:
5410  oa = va_arg (ap, struct MHD_OptionItem*);
5411  i = 0;
5412  while (MHD_OPTION_END != (opt = oa[i].option))
5413  {
5414  switch (opt)
5415  {
5416  /* all options taking 'size_t' */
5420  if (MHD_YES != parse_options (daemon,
5421  servaddr,
5422  opt,
5423  (size_t) oa[i].value,
5424  MHD_OPTION_END))
5425  return MHD_NO;
5426  break;
5427  /* all options taking 'unsigned int' */
5437  if (MHD_YES != parse_options (daemon,
5438  servaddr,
5439  opt,
5440  (unsigned int) oa[i].value,
5441  MHD_OPTION_END))
5442  return MHD_NO;
5443  break;
5444  /* all options taking 'enum' */
5445 #ifdef HTTPS_SUPPORT
5447  if (MHD_YES != parse_options (daemon,
5448  servaddr,
5449  opt,
5450  (gnutls_credentials_type_t) oa[i].value,
5451  MHD_OPTION_END))
5452  return MHD_NO;
5453  break;
5454 #endif /* HTTPS_SUPPORT */
5455  /* all options taking 'MHD_socket' */
5457  if (MHD_YES != parse_options (daemon,
5458  servaddr,
5459  opt,
5460  (MHD_socket) oa[i].value,
5461  MHD_OPTION_END))
5462  return MHD_NO;
5463  break;
5464  /* all options taking 'int' */
5466  if (MHD_YES != parse_options (daemon,
5467  servaddr,
5468  opt,
5469  (int) oa[i].value,
5470  MHD_OPTION_END))
5471  return MHD_NO;
5472  break;
5473  /* all options taking one pointer */
5474  case MHD_OPTION_SOCK_ADDR:
5481  case MHD_OPTION_ARRAY:
5484  if (MHD_YES != parse_options (daemon,
5485  servaddr,
5486  opt,
5487  oa[i].ptr_value,
5488  MHD_OPTION_END))
5489  return MHD_NO;
5490  break;
5491  /* all options taking two pointers */
5498  if (MHD_YES != parse_options (daemon,
5499  servaddr,
5500  opt,
5501  (void *) oa[i].value,
5502  oa[i].ptr_value,
5503  MHD_OPTION_END))
5504  return MHD_NO;
5505  break;
5506  /* options taking size_t-number followed by pointer */
5508  if (MHD_YES != parse_options (daemon,
5509  servaddr,
5510  opt,
5511  (size_t) oa[i].value,
5512  oa[i].ptr_value,
5513  MHD_OPTION_END))
5514  return MHD_NO;
5515  break;
5516  default:
5517  return MHD_NO;
5518  }
5519  i++;
5520  }
5521  break;
5523  daemon->unescape_callback = va_arg (ap,
5525  daemon->unescape_callback_cls = va_arg (ap,
5526  void *);
5527  break;
5528 #ifdef HTTPS_SUPPORT
5530 #if GNUTLS_VERSION_MAJOR >= 3
5531  daemon->cred_callback = va_arg (ap,
5533  daemon->cred_callback_cls = va_arg (ap,
5534  void *);
5535  break;
5536 #else
5537  MHD_DLOG (daemon,
5538  _ (
5539  "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
5540  opt);
5541  return MHD_NO;
5542 #endif
5543 #endif /* HTTPS_SUPPORT */
5544  default:
5545 #ifdef HAVE_MESSAGES
5546  if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
5547  (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
5548  (opt == MHD_OPTION_HTTPS_MEM_TRUST) ||
5550  {
5551  MHD_DLOG (daemon,
5552  _ (
5553  "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
5554  opt);
5555  }
5556  else
5557  {
5558  MHD_DLOG (daemon,
5559  _ (
5560  "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
5561  opt);
5562  }
5563 #endif
5564  return MHD_NO;
5565  }
5566  }
5567  return MHD_YES;
5568 }
5569 
5570 
5571 #ifdef EPOLL_SUPPORT
5572 static int
5573 setup_epoll_fd (struct MHD_Daemon *daemon)
5574 {
5575  int fd;
5576 
5577 #ifndef HAVE_MESSAGES
5578  (void) daemon; /* Mute compiler warning. */
5579 #endif /* ! HAVE_MESSAGES */
5580 
5581 #ifdef USE_EPOLL_CREATE1
5582  fd = epoll_create1 (EPOLL_CLOEXEC);
5583 #else /* ! USE_EPOLL_CREATE1 */
5584  fd = epoll_create (MAX_EVENTS);
5585 #endif /* ! USE_EPOLL_CREATE1 */
5586  if (MHD_INVALID_SOCKET == fd)
5587  {
5588 #ifdef HAVE_MESSAGES
5589  MHD_DLOG (daemon,
5590  _ ("Call to epoll_create1 failed: %s\n"),
5592 #endif
5593  return MHD_INVALID_SOCKET;
5594  }
5595 #if ! defined(USE_EPOLL_CREATE1)
5597  {
5598 #ifdef HAVE_MESSAGES
5599  MHD_DLOG (daemon,
5600  _ ("Failed to set noninheritable mode on epoll FD.\n"));
5601 #endif
5602  }
5603 #endif /* ! USE_EPOLL_CREATE1 */
5604  return fd;
5605 }
5606 
5607 
5617 static enum MHD_Result
5618 setup_epoll_to_listen (struct MHD_Daemon *daemon)
5619 {
5620  struct epoll_event event;
5621  MHD_socket ls;
5622 
5623  daemon->epoll_fd = setup_epoll_fd (daemon);
5624  if (-1 == daemon->epoll_fd)
5625  return MHD_NO;
5626 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5627  if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
5628  {
5629  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5630  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
5631  return MHD_NO;
5632  }
5633 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5634  if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
5635  (daemon->was_quiesced) )
5636  return MHD_YES; /* non-listening daemon */
5637  event.events = EPOLLIN;
5638  event.data.ptr = daemon;
5639  if (0 != epoll_ctl (daemon->epoll_fd,
5640  EPOLL_CTL_ADD,
5641  ls,
5642  &event))
5643  {
5644 #ifdef HAVE_MESSAGES
5645  MHD_DLOG (daemon,
5646  _ ("Call to epoll_ctl failed: %s\n"),
5648 #endif
5649  return MHD_NO;
5650  }
5651  daemon->listen_socket_in_epoll = true;
5652  if (MHD_ITC_IS_VALID_ (daemon->itc))
5653  {
5654  event.events = EPOLLIN;
5655  event.data.ptr = (void *) epoll_itc_marker;
5656  if (0 != epoll_ctl (daemon->epoll_fd,
5657  EPOLL_CTL_ADD,
5658  MHD_itc_r_fd_ (daemon->itc),
5659  &event))
5660  {
5661 #ifdef HAVE_MESSAGES
5662  MHD_DLOG (daemon,
5663  _ ("Call to epoll_ctl failed: %s\n"),
5665 #endif
5666  return MHD_NO;
5667  }
5668  }
5669  return MHD_YES;
5670 }
5671 
5672 
5673 #endif
5674 
5675 
5697 struct MHD_Daemon *
5698 MHD_start_daemon_va (unsigned int flags,
5699  uint16_t port,
5701  void *apc_cls,
5703  void *dh_cls,
5704  va_list ap)
5705 {
5706  const MHD_SCKT_OPT_BOOL_ on = 1;
5707  struct MHD_Daemon *daemon;
5709  struct sockaddr_in servaddr4;
5710 #if HAVE_INET6
5711  struct sockaddr_in6 servaddr6;
5712 #endif
5713  const struct sockaddr *servaddr = NULL;
5714  socklen_t addrlen;
5715 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5716  unsigned int i;
5717 #endif
5718  enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
5719  enum MHD_FLAG *pflags;
5720 
5722  eflags = (enum MHD_FLAG) flags;
5723  pflags = &eflags;
5724 #ifndef HAVE_INET6
5725  if (0 != (*pflags & MHD_USE_IPv6))
5726  return NULL;
5727 #endif
5728 #ifndef HAVE_POLL
5729  if (0 != (*pflags & MHD_USE_POLL))
5730  return NULL;
5731 #endif
5732 #ifndef EPOLL_SUPPORT
5733  if (0 != (*pflags & MHD_USE_EPOLL))
5734  return NULL;
5735 #endif /* ! EPOLL_SUPPORT */
5736 #ifndef HTTPS_SUPPORT
5737  if (0 != (*pflags & MHD_USE_TLS))
5738  return NULL;
5739 #endif /* ! HTTPS_SUPPORT */
5740 #ifndef TCP_FASTOPEN
5741  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5742  return NULL;
5743 #endif
5744  if (0 != (*pflags & MHD_ALLOW_UPGRADE))
5745  {
5746 #ifdef UPGRADE_SUPPORT
5747  *pflags |= MHD_ALLOW_SUSPEND_RESUME;
5748 #else /* ! UPGRADE_SUPPORT */
5749  return NULL;
5750 #endif /* ! UPGRADE_SUPPORT */
5751  }
5752  if (NULL == dh)
5753  return NULL;
5754 
5755  /* Check for invalid combinations of flags. */
5756  if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5757  ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags
5758  &
5760  ||
5761  ((0 != (*pflags & MHD_USE_POLL)) &&
5762  (0 == (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD
5764  ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL
5765  | MHD_USE_EPOLL)))) )
5766  return NULL;
5767 
5768  if (0 != (*pflags & MHD_USE_AUTO))
5769  {
5770  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5771  {
5772  /* Thread per connection with internal polling thread. */
5773 #ifdef HAVE_POLL
5774  *pflags |= MHD_USE_POLL;
5775 #else /* ! HAVE_POLL */
5776  /* use select() - do not modify flags */
5777 #endif /* ! HAVE_POLL */
5778  }
5779  else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5780  {
5781  /* Internal polling thread. */
5782 #if defined(EPOLL_SUPPORT)
5783  *pflags |= MHD_USE_EPOLL;
5784 #elif defined(HAVE_POLL)
5785  *pflags |= MHD_USE_POLL;
5786 #else /* !HAVE_POLL && !EPOLL_SUPPORT */
5787  /* use select() - do not modify flags */
5788 #endif /* !HAVE_POLL && !EPOLL_SUPPORT */
5789  }
5790  else
5791  {
5792  /* Internal threads are not used - "external" polling mode. */
5793 #if defined(EPOLL_SUPPORT)
5794  *pflags |= MHD_USE_EPOLL;
5795 #else /* ! EPOLL_SUPPORT */
5796  /* use select() - do not modify flags */
5797 #endif /* ! EPOLL_SUPPORT */
5798  }
5799  }
5800 
5801  if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
5802  return NULL;
5803 #ifdef EPOLL_SUPPORT
5804  daemon->epoll_fd = -1;
5805 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5806  daemon->epoll_upgrade_fd = -1;
5807 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5808 #endif
5809  /* try to open listen socket */
5810 #ifdef HTTPS_SUPPORT
5811  daemon->priority_cache = NULL;
5812  if (0 != (*pflags & MHD_USE_TLS))
5813  {
5814  gnutls_priority_init (&daemon->priority_cache,
5815  "@SYSTEM",
5816  NULL);
5817  }
5818 #endif /* HTTPS_SUPPORT */
5819  daemon->listen_fd = MHD_INVALID_SOCKET;
5820  daemon->listening_address_reuse = 0;
5821  daemon->options = *pflags;
5822  pflags = &daemon->options;
5823  daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 :
5824  0;
5825  daemon->port = port;
5826  daemon->apc = apc;
5827  daemon->apc_cls = apc_cls;
5828  daemon->default_handler = dh;
5829  daemon->default_handler_cls = dh_cls;
5830  daemon->connections = 0;
5832  daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
5833  daemon->pool_increment = MHD_BUF_INC_SIZE;
5835  daemon->connection_timeout = 0; /* no timeout */
5836  MHD_itc_set_invalid_ (daemon->itc);
5837 #ifdef SOMAXCONN
5838  daemon->listen_backlog_size = SOMAXCONN;
5839 #else /* !SOMAXCONN */
5840  daemon->listen_backlog_size = 511; /* should be safe value */
5841 #endif /* !SOMAXCONN */
5842 #ifdef HAVE_MESSAGES
5843  daemon->custom_error_log = &MHD_default_logger_;
5844  daemon->custom_error_log_cls = stderr;
5845 #endif
5846  if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
5847  (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
5848  {
5849 #ifdef HAVE_MESSAGES
5850  MHD_DLOG (daemon,
5851  _ (
5852  "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5853  "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5854  "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5855 #endif
5857  }
5858  if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5859  *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
5860  else
5861  {
5862 #ifdef HAVE_LISTEN_SHUTDOWN
5863  if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
5864 #endif
5865  *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
5866  }
5867 #ifdef DAUTH_SUPPORT
5868  daemon->digest_auth_rand_size = 0;
5869  daemon->digest_auth_random = NULL;
5870  daemon->nonce_nc_size = 4; /* tiny */
5871 #endif
5872 #ifdef HTTPS_SUPPORT
5873  if (0 != (*pflags & MHD_USE_TLS))
5874  {
5875  daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5876  }
5877 #endif /* HTTPS_SUPPORT */
5878 
5879 
5880  if (MHD_YES != parse_options_va (daemon,
5881  &servaddr,
5882  ap))
5883  {
5884 #ifdef HTTPS_SUPPORT
5885  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5886  (NULL != daemon->priority_cache) )
5887  gnutls_priority_deinit (daemon->priority_cache);
5888 #endif /* HTTPS_SUPPORT */
5889  free (daemon);
5890  return NULL;
5891  }
5892 
5893  if ( (NULL != daemon->notify_completed) &&
5894  (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
5895  *pflags |= MHD_USE_ITC; /* requires ITC */
5896 
5897 #ifndef NDEBUG
5898 #ifdef HAVE_MESSAGES
5899  MHD_DLOG (daemon,
5900  _ ("Using debug build of libmicrohttpd.\n") );
5901 #endif /* HAVE_MESSAGES */
5902 #endif /* ! NDEBUG */
5903 
5904  if ( (0 != (*pflags & MHD_USE_ITC))
5905 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5906  && (0 == daemon->worker_pool_size)
5907 #endif
5908  )
5909  {
5910  if (! MHD_itc_init_ (daemon->itc))
5911  {
5912 #ifdef HAVE_MESSAGES
5913  MHD_DLOG (daemon,
5914  _ ("Failed to create inter-thread communication channel: %s\n"),
5915  MHD_itc_last_strerror_ ());
5916 #endif
5917 #ifdef HTTPS_SUPPORT
5918  if (NULL != daemon->priority_cache)
5919  gnutls_priority_deinit (daemon->priority_cache);
5920 #endif /* HTTPS_SUPPORT */
5921  free (daemon);
5922  return NULL;
5923  }
5924  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5925  (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
5926  NULL)) )
5927  {
5928 #ifdef HAVE_MESSAGES
5929  MHD_DLOG (daemon,
5930  _ (
5931  "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
5932 #endif
5933  MHD_itc_destroy_chk_ (daemon->itc);
5934 #ifdef HTTPS_SUPPORT
5935  if (NULL != daemon->priority_cache)
5936  gnutls_priority_deinit (daemon->priority_cache);
5937 #endif /* HTTPS_SUPPORT */
5938  free (daemon);
5939  return NULL;
5940  }
5941  }
5942 
5943 #ifdef DAUTH_SUPPORT
5944  if (daemon->nonce_nc_size > 0)
5945  {
5946  if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc)))
5947  / sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
5948  {
5949 #ifdef HAVE_MESSAGES
5950  MHD_DLOG (daemon,
5951  _ ("Specified value for NC_SIZE too large.\n"));
5952 #endif
5953 #ifdef HTTPS_SUPPORT
5954  if (0 != (*pflags & MHD_USE_TLS))
5955  gnutls_priority_deinit (daemon->priority_cache);
5956 #endif /* HTTPS_SUPPORT */
5957  free (daemon);
5958  return NULL;
5959  }
5960  daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
5961  if (NULL == daemon->nnc)
5962  {
5963 #ifdef HAVE_MESSAGES
5964  MHD_DLOG (daemon,
5965  _ ("Failed to allocate memory for nonce-nc map: %s\n"),
5966  MHD_strerror_ (errno));
5967 #endif
5968 #ifdef HTTPS_SUPPORT
5969  if (0 != (*pflags & MHD_USE_TLS))
5970  gnutls_priority_deinit (daemon->priority_cache);
5971 #endif /* HTTPS_SUPPORT */
5972  free (daemon);
5973  return NULL;
5974  }
5975  }
5976 
5977 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5978  if (! MHD_mutex_init_ (&daemon->nnc_lock))
5979  {
5980 #ifdef HAVE_MESSAGES
5981  MHD_DLOG (daemon,
5982  _ ("MHD failed to initialize nonce-nc mutex.\n"));
5983 #endif
5984 #ifdef HTTPS_SUPPORT
5985  if (0 != (*pflags & MHD_USE_TLS))
5986  gnutls_priority_deinit (daemon->priority_cache);
5987 #endif /* HTTPS_SUPPORT */
5988  free (daemon->nnc);
5989  free (daemon);
5990  return NULL;
5991  }
5992 #endif
5993 #endif
5994 
5995  /* Thread polling currently works only with internal select thread mode */
5996 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5997  if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5998  (daemon->worker_pool_size > 0) )
5999  {
6000 #ifdef HAVE_MESSAGES
6001  MHD_DLOG (daemon,
6002  _ (
6003  "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6004 #endif
6005  goto free_and_fail;
6006  }
6007 #endif
6008  if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
6009  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6010  {
6011  /* try to open listen socket */
6012  int domain;
6013 
6014 #ifdef HAVE_INET6
6015  domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6016 #else /* ! HAVE_INET6 */
6017  if (*pflags & MHD_USE_IPv6)
6018  goto free_and_fail;
6019  domain = PF_INET;
6020 #endif /* ! HAVE_INET6 */
6021 
6022  listen_fd = MHD_socket_create_listen_ (domain);
6023  if (MHD_INVALID_SOCKET == listen_fd)
6024  {
6025 #ifdef HAVE_MESSAGES
6026  MHD_DLOG (daemon,
6027  _ ("Failed to create socket for listening: %s\n"),
6029 #endif
6030  goto free_and_fail;
6031  }
6032 
6033  /* Apply the socket options according to listening_address_reuse. */
6034  if (0 == daemon->listening_address_reuse)
6035  {
6036 #ifndef MHD_WINSOCK_SOCKETS
6037  /* No user requirement, use "traditional" default SO_REUSEADDR
6038  * on non-W32 platforms, and do not fail if it doesn't work.
6039  * Don't use it on W32, because on W32 it will allow multiple
6040  * bind to the same address:port, like SO_REUSEPORT on others. */
6041  if (0 > setsockopt (listen_fd,
6042  SOL_SOCKET,
6043  SO_REUSEADDR,
6044  (void*) &on, sizeof (on)))
6045  {
6046 #ifdef HAVE_MESSAGES
6047  MHD_DLOG (daemon,
6048  _ ("setsockopt failed: %s\n"),
6050 #endif
6051  }
6052 #endif /* ! MHD_WINSOCK_SOCKETS */
6053  }
6054  else if (daemon->listening_address_reuse > 0)
6055  {
6056  /* User requested to allow reusing listening address:port. */
6057 #ifndef MHD_WINSOCK_SOCKETS
6058  /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
6059  * it doesn't work. */
6060  if (0 > setsockopt (listen_fd,
6061  SOL_SOCKET,
6062  SO_REUSEADDR,
6063  (void*) &on, sizeof (on)))
6064  {
6065 #ifdef HAVE_MESSAGES
6066  MHD_DLOG (daemon,
6067  _ ("setsockopt failed: %s\n"),
6069 #endif
6070  }
6071 #endif /* ! MHD_WINSOCK_SOCKETS */
6072  /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
6073  * Fail if SO_REUSEPORT is not defined or setsockopt fails.
6074  */
6075  /* SO_REUSEADDR on W32 has the same semantics
6076  as SO_REUSEPORT on BSD/Linux */
6077 #if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6078  if (0 > setsockopt (listen_fd,
6079  SOL_SOCKET,
6080 #ifndef MHD_WINSOCK_SOCKETS
6081  SO_REUSEPORT,
6082 #else /* MHD_WINSOCK_SOCKETS */
6083  SO_REUSEADDR,
6084 #endif /* MHD_WINSOCK_SOCKETS */
6085  (void *) &on,
6086  sizeof (on)))
6087  {
6088 #ifdef HAVE_MESSAGES
6089  MHD_DLOG (daemon,
6090  _ ("setsockopt failed: %s\n"),
6092 #endif
6093  goto free_and_fail;
6094  }
6095 #else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6096  /* we're supposed to allow address:port re-use, but
6097  on this platform we cannot; fail hard */
6098 #ifdef HAVE_MESSAGES
6099  MHD_DLOG (daemon,
6100  _ (
6101  "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6102 #endif
6103  goto free_and_fail;
6104 #endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
6105  }
6106  else /* if (daemon->listening_address_reuse < 0) */
6107  {
6108  /* User requested to disallow reusing listening address:port.
6109  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
6110  * is used and Solaris with SO_EXCLBIND.
6111  * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
6112  * or setsockopt fails.
6113  */
6114 #if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6115  (defined(__sun) && defined(SO_EXCLBIND))
6116  if (0 > setsockopt (listen_fd,
6117  SOL_SOCKET,
6118 #ifdef SO_EXCLUSIVEADDRUSE
6119  SO_EXCLUSIVEADDRUSE,
6120 #else /* SO_EXCLBIND */
6121  SO_EXCLBIND,
6122 #endif /* SO_EXCLBIND */
6123  (void *) &on,
6124  sizeof (on)))
6125  {
6126 #ifdef HAVE_MESSAGES
6127  MHD_DLOG (daemon,
6128  _ ("setsockopt failed: %s\n"),
6130 #endif
6131  goto free_and_fail;
6132  }
6133 #elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
6134 #ifdef HAVE_MESSAGES
6135  MHD_DLOG (daemon,
6136  _ (
6137  "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6138 #endif
6139  goto free_and_fail;
6140 #endif /* MHD_WINSOCK_SOCKETS */
6141  }
6142 
6143  /* check for user supplied sockaddr */
6144 #if HAVE_INET6
6145  if (0 != (*pflags & MHD_USE_IPv6))
6146  addrlen = sizeof (struct sockaddr_in6);
6147  else
6148 #endif
6149  addrlen = sizeof (struct sockaddr_in);
6150  if (NULL == servaddr)
6151  {
6152 #if HAVE_INET6
6153  if (0 != (*pflags & MHD_USE_IPv6))
6154  {
6155 #ifdef IN6ADDR_ANY_INIT
6156  static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6157 #endif
6158  memset (&servaddr6,
6159  0,
6160  sizeof (struct sockaddr_in6));
6161  servaddr6.sin6_family = AF_INET6;
6162  servaddr6.sin6_port = htons (port);
6163 #ifdef IN6ADDR_ANY_INIT
6164  servaddr6.sin6_addr = static_in6any;
6165 #endif
6166 #if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6167  servaddr6.sin6_len = sizeof (struct sockaddr_in6);
6168 #endif
6169  servaddr = (struct sockaddr *) &servaddr6;
6170  }
6171  else
6172 #endif
6173  {
6174  memset (&servaddr4,
6175  0,
6176  sizeof (struct sockaddr_in));
6177  servaddr4.sin_family = AF_INET;
6178  servaddr4.sin_port = htons (port);
6179  if (0 != INADDR_ANY)
6180  servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6181 #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6182  servaddr4.sin_len = sizeof (struct sockaddr_in);
6183 #endif
6184  servaddr = (struct sockaddr *) &servaddr4;
6185  }
6186  }
6187  daemon->listen_fd = listen_fd;
6188 
6189  if (0 != (*pflags & MHD_USE_IPv6))
6190  {
6191 #ifdef IPPROTO_IPV6
6192 #ifdef IPV6_V6ONLY
6193  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
6194  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
6195  and may also be missing on older POSIX systems; good luck if you have any of those,
6196  your IPv6 socket may then also bind against IPv4 anyway... */
6197  const MHD_SCKT_OPT_BOOL_ v6_only =
6198  (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
6199  if (0 > setsockopt (listen_fd,
6200  IPPROTO_IPV6, IPV6_V6ONLY,
6201  (const void *) &v6_only,
6202  sizeof (v6_only)))
6203  {
6204 #ifdef HAVE_MESSAGES
6205  MHD_DLOG (daemon,
6206  _ ("setsockopt failed: %s\n"),
6208 #endif
6209  }
6210 #endif
6211 #endif
6212  }
6213  if (-1 == bind (listen_fd, servaddr, addrlen))
6214  {
6215 #ifdef HAVE_MESSAGES
6216  MHD_DLOG (daemon,
6217  _ ("Failed to bind to port %u: %s\n"),
6218  (unsigned int) port,
6220 #endif
6221  MHD_socket_close_chk_ (listen_fd);
6222  goto free_and_fail;
6223  }
6224 #ifdef TCP_FASTOPEN
6225  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
6226  {
6227  if (0 == daemon->fastopen_queue_size)
6228  daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6229  if (0 != setsockopt (listen_fd,
6230  IPPROTO_TCP,
6231  TCP_FASTOPEN,
6232  (const void*) &daemon->fastopen_queue_size,
6233  sizeof (daemon->fastopen_queue_size)))
6234  {
6235 #ifdef HAVE_MESSAGES
6236  MHD_DLOG (daemon,
6237  _ ("setsockopt failed: %s\n"),
6239 #endif
6240  }
6241  }
6242 #endif
6243  if (listen (listen_fd,
6244  daemon->listen_backlog_size) < 0)
6245  {
6246 #ifdef HAVE_MESSAGES
6247  MHD_DLOG (daemon,
6248  _ ("Failed to listen for connections: %s\n"),
6250 #endif
6251  MHD_socket_close_chk_ (listen_fd);
6252  goto free_and_fail;
6253  }
6254  }
6255  else
6256  {
6257  listen_fd = daemon->listen_fd;
6258  }
6259 
6260 #ifdef HAVE_GETSOCKNAME
6261  if ( (0 == daemon->port) &&
6262  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6263  { /* Get port number. */
6264  struct sockaddr_storage bindaddr;
6265 
6266  memset (&bindaddr,
6267  0,
6268  sizeof (struct sockaddr_storage));
6269  addrlen = sizeof (struct sockaddr_storage);
6270 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6271  bindaddr.ss_len = addrlen;
6272 #endif
6273  if (0 != getsockname (listen_fd,
6274  (struct sockaddr *) &bindaddr,
6275  &addrlen))
6276  {
6277 #ifdef HAVE_MESSAGES
6278  MHD_DLOG (daemon,
6279  _ ("Failed to get listen port number: %s\n"),
6281 #endif /* HAVE_MESSAGES */
6282  }
6283 #ifdef MHD_POSIX_SOCKETS
6284  else if (sizeof (bindaddr) < addrlen)
6285  {
6286  /* should be impossible with `struct sockaddr_storage` */
6287 #ifdef HAVE_MESSAGES
6288  MHD_DLOG (daemon,
6289  _ (
6290  "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6291 #endif /* HAVE_MESSAGES */
6292  }
6293 #ifndef __linux__
6294  else if (0 == addrlen)
6295  {
6296  /* Many non-Linux-based platforms return zero addrlen
6297  * for AF_UNIX sockets */
6298  daemon->port = 0; /* special value for UNIX domain sockets */
6299  }
6300 #endif /* __linux__ */
6301 #endif /* MHD_POSIX_SOCKETS */
6302  else
6303  {
6304  switch (bindaddr.ss_family)
6305  {
6306  case AF_INET:
6307  {
6308  struct sockaddr_in *s4 = (struct sockaddr_in *) &bindaddr;
6309 
6310  daemon->port = ntohs (s4->sin_port);
6311  break;
6312  }
6313 #ifdef HAVE_INET6
6314  case AF_INET6:
6315  {
6316  struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &bindaddr;
6317 
6318  daemon->port = ntohs (s6->sin6_port);
6319  mhd_assert (0 != (*pflags & MHD_USE_IPv6));
6320  break;
6321  }
6322 #endif /* HAVE_INET6 */
6323 #ifdef AF_UNIX
6324  case AF_UNIX:
6325  daemon->port = 0; /* special value for UNIX domain sockets */
6326  break;
6327 #endif
6328  default:
6329 #ifdef HAVE_MESSAGES
6330  MHD_DLOG (daemon,
6331  _ ("Unknown address family!\n"));
6332 #endif
6333  daemon->port = 0; /* ugh */
6334  break;
6335  }
6336  }
6337  }
6338 #endif /* HAVE_GETSOCKNAME */
6339  if ( (MHD_INVALID_SOCKET != listen_fd) &&
6340  (! MHD_socket_nonblocking_ (listen_fd)) )
6341  {
6342 #ifdef HAVE_MESSAGES
6343  MHD_DLOG (daemon,
6344  _ ("Failed to set nonblocking mode on listening socket: %s\n"),
6346 #endif
6347  if (0 != (*pflags & MHD_USE_EPOLL)
6348 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6349  || (daemon->worker_pool_size > 0)
6350 #endif
6351  )
6352  {
6353  /* Accept must be non-blocking. Multiple children may wake up
6354  * to handle a new connection, but only one will win the race.
6355  * The others must immediately return. */
6356  MHD_socket_close_chk_ (listen_fd);
6357  goto free_and_fail;
6358  }
6359  }
6360  if ( (MHD_INVALID_SOCKET != listen_fd) &&
6361  (! MHD_SCKT_FD_FITS_FDSET_ (listen_fd,
6362  NULL)) &&
6363  (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
6364  {
6365 #ifdef HAVE_MESSAGES
6366  MHD_DLOG (daemon,
6367  _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
6368  listen_fd,
6369  FD_SETSIZE);
6370 #endif
6371  MHD_socket_close_chk_ (listen_fd);
6372  goto free_and_fail;
6373  }
6374 
6375 #ifdef EPOLL_SUPPORT
6376  if ( (0 != (*pflags & MHD_USE_EPOLL))
6377 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6378  && (0 == daemon->worker_pool_size)
6379 #endif
6380  )
6381  {
6382  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6383  {
6384 #ifdef HAVE_MESSAGES
6385  MHD_DLOG (daemon,
6386  _ (
6387  "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
6388 #endif
6389  goto free_and_fail;
6390  }
6391  if (MHD_YES != setup_epoll_to_listen (daemon))
6392  goto free_and_fail;
6393  }
6394 #endif /* EPOLL_SUPPORT */
6395 
6396 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6397  if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
6398  {
6399 #ifdef HAVE_MESSAGES
6400  MHD_DLOG (daemon,
6401  _ ("MHD failed to initialize IP connection limit mutex.\n"));
6402 #endif
6403  if (MHD_INVALID_SOCKET != listen_fd)
6404  MHD_socket_close_chk_ (listen_fd);
6405  goto free_and_fail;
6406  }
6407  if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
6408  {
6409 #ifdef HAVE_MESSAGES
6410  MHD_DLOG (daemon,
6411  _ ("MHD failed to initialize IP connection limit mutex.\n"));
6412 #endif
6413 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6415 #endif
6416  if (MHD_INVALID_SOCKET != listen_fd)
6417  MHD_socket_close_chk_ (listen_fd);
6418  goto free_and_fail;
6419  }
6420 #endif
6421 
6422 #ifdef HTTPS_SUPPORT
6423  /* initialize HTTPS daemon certificate aspects & send / recv functions */
6424  if ( (0 != (*pflags & MHD_USE_TLS)) &&
6425  (0 != MHD_TLS_init (daemon)) )
6426  {
6427 #ifdef HAVE_MESSAGES
6428  MHD_DLOG (daemon,
6429  _ ("Failed to initialize TLS support.\n"));
6430 #endif
6431  if (MHD_INVALID_SOCKET != listen_fd)
6432  MHD_socket_close_chk_ (listen_fd);
6433 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6436 #endif
6437  goto free_and_fail;
6438  }
6439 #endif /* HTTPS_SUPPORT */
6440 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6441  if ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
6442  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6443  {
6444  if (0 == daemon->worker_pool_size)
6445  {
6446  if (! MHD_create_named_thread_ (&daemon->pid,
6447  (*pflags
6449  "MHD-listen" : "MHD-single",
6450  daemon->thread_stack_size,
6452  daemon) )
6453  {
6454 #ifdef HAVE_MESSAGES
6455  MHD_DLOG (daemon,
6456  _ ("Failed to create listen thread: %s\n"),
6457  MHD_strerror_ (errno));
6458 #endif
6461  if (MHD_INVALID_SOCKET != listen_fd)
6462  MHD_socket_close_chk_ (listen_fd);
6463  goto free_and_fail;
6464  }
6465  }
6466  else /* 0 < daemon->worker_pool_size */
6467  {
6468  /* Coarse-grained count of connections per thread (note error
6469  * due to integer division). Also keep track of how many
6470  * connections are leftover after an equal split. */
6471  unsigned int conns_per_thread = daemon->connection_limit
6472  / daemon->worker_pool_size;
6473  unsigned int leftover_conns = daemon->connection_limit
6474  % daemon->worker_pool_size;
6475 
6476  i = 0; /* we need this in case fcntl or malloc fails */
6477 
6478  /* Allocate memory for pooled objects */
6479  daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
6480  * daemon->worker_pool_size);
6481  if (NULL == daemon->worker_pool)
6482  goto thread_failed;
6483 
6484  /* Start the workers in the pool */
6485  for (i = 0; i < daemon->worker_pool_size; ++i)
6486  {
6487  /* Create copy of the Daemon object for each worker */
6488  struct MHD_Daemon *d = &daemon->worker_pool[i];
6489 
6490  memcpy (d, daemon, sizeof (struct MHD_Daemon));
6491  /* Adjust polling params for worker daemons; note that memcpy()
6492  has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
6493  the worker threads. */
6494  d->master = daemon;
6495  d->worker_pool_size = 0;
6496  d->worker_pool = NULL;
6497 
6498  if (0 != (*pflags & MHD_USE_ITC))
6499  {
6500  if (! MHD_itc_init_ (d->itc))
6501  {
6502 #ifdef HAVE_MESSAGES
6503  MHD_DLOG (daemon,
6504  _ (
6505  "Failed to create worker inter-thread communication channel: %s\n"),
6506  MHD_itc_last_strerror_ () );
6507 #endif
6508  goto thread_failed;
6509  }
6510  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6511  (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
6512  NULL)) )
6513  {
6514 #ifdef HAVE_MESSAGES
6515  MHD_DLOG (daemon,
6516  _ (
6517  "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
6518 #endif
6520  goto thread_failed;
6521  }
6522  }
6523  else
6524  MHD_itc_set_invalid_ (d->itc);
6525 
6526  /* Divide available connections evenly amongst the threads.
6527  * Thread indexes in [0, leftover_conns) each get one of the
6528  * leftover connections. */
6529  d->connection_limit = conns_per_thread;
6530  if (i < leftover_conns)
6531  ++d->connection_limit;
6532 #ifdef EPOLL_SUPPORT
6533  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6534  (MHD_YES != setup_epoll_to_listen (d)) )
6535  goto thread_failed;
6536 #endif
6537  /* Must init cleanup connection mutex for each worker */
6538  if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
6539  {
6540 #ifdef HAVE_MESSAGES
6541  MHD_DLOG (daemon,
6542  _ ("MHD failed to initialize cleanup connection mutex.\n"));
6543 #endif
6544  goto thread_failed;
6545  }
6546 
6547  /* Spawn the worker thread */
6548  if (! MHD_create_named_thread_ (&d->pid,
6549  "MHD-worker",
6550  daemon->thread_stack_size,
6552  d))
6553  {
6554 #ifdef HAVE_MESSAGES
6555  MHD_DLOG (daemon,
6556  _ ("Failed to create pool thread: %s\n"),
6557  MHD_strerror_ (errno));
6558 #endif
6559  /* Free memory for this worker; cleanup below handles
6560  * all previously-created workers. */
6562  goto thread_failed;
6563  }
6564  }
6565  }
6566  }
6567 #endif
6568 #ifdef HTTPS_SUPPORT
6569  /* API promises to never use the password after initialization,
6570  so we additionally NULL it here to not deref a dangling pointer. */
6571  daemon->https_key_password = NULL;
6572 #endif /* HTTPS_SUPPORT */
6573 
6574  return daemon;
6575 
6576 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6577 thread_failed:
6578  /* If no worker threads created, then shut down normally. Calling
6579  MHD_stop_daemon (as we do below) doesn't work here since it
6580  assumes a 0-sized thread pool means we had been in the default
6581  MHD_USE_INTERNAL_POLLING_THREAD mode. */
6582  if (0 == i)
6583  {
6587  if (NULL != daemon->worker_pool)
6588  free (daemon->worker_pool);
6589  goto free_and_fail;
6590  }
6591 
6592  /* Shutdown worker threads we've already created. Pretend
6593  as though we had fully initialized our daemon, but
6594  with a smaller number of threads than had been
6595  requested. */
6596  daemon->worker_pool_size = i;
6597  MHD_stop_daemon (daemon);
6598  return NULL;
6599 #endif
6600 
6601 free_and_fail:
6602  /* clean up basic memory state in 'daemon' and return NULL to
6603  indicate failure */
6604 #ifdef EPOLL_SUPPORT
6605 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6606  if (daemon->upgrade_fd_in_epoll)
6607  {
6608  if (0 != epoll_ctl (daemon->epoll_fd,
6609  EPOLL_CTL_DEL,
6610  daemon->epoll_upgrade_fd,
6611  NULL))
6612  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
6613  daemon->upgrade_fd_in_epoll = false;
6614  }
6615 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6616  if (-1 != daemon->epoll_fd)
6617  close (daemon->epoll_fd);
6618 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6619  if (-1 != daemon->epoll_upgrade_fd)
6620  close (daemon->epoll_upgrade_fd);
6621 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6622 #endif /* EPOLL_SUPPORT */
6623 #ifdef DAUTH_SUPPORT
6624  free (daemon->nnc);
6625 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6626  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6627 #endif
6628 #endif
6629 #ifdef HTTPS_SUPPORT
6630  if (0 != (*pflags & MHD_USE_TLS))
6631  {
6632  gnutls_priority_deinit (daemon->priority_cache);
6633  if (daemon->x509_cred)
6634  gnutls_certificate_free_credentials (daemon->x509_cred);
6635  if (daemon->psk_cred)
6636  gnutls_psk_free_server_credentials (daemon->psk_cred);
6637  }
6638 #endif /* HTTPS_SUPPORT */
6639  if (MHD_ITC_IS_VALID_ (daemon->itc))
6640  MHD_itc_destroy_chk_ (daemon->itc);
6641  free (daemon);
6642  return NULL;
6643 }
6644 
6645 
6654 static void
6656 {
6657  struct MHD_Connection *pos;
6658  const bool used_thr_p_c = (0 != (daemon->options
6660 #ifdef UPGRADE_SUPPORT
6661  const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
6662 #endif /* UPGRADE_SUPPORT */
6663 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6664  struct MHD_UpgradeResponseHandle *urh;
6665  struct MHD_UpgradeResponseHandle *urhn;
6666  const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
6667 
6668 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6669  mhd_assert (NULL == daemon->worker_pool);
6670 #endif
6671  mhd_assert (daemon->shutdown);
6672  /* give upgraded HTTPS connections a chance to finish */
6673  /* 'daemon->urh_head' is not used in thread-per-connection mode. */
6674  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
6675  {
6676  urhn = urh->prev;
6677  /* call generic forwarding function for passing data
6678  with chance to detect that application is done. */
6679  process_urh (urh);
6680  MHD_connection_finish_forward_ (urh->connection);
6681  urh->clean_ready = true;
6682  /* Resuming will move connection to cleanup list. */
6683  MHD_resume_connection (urh->connection);
6684  }
6685 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6686 
6687  /* Give suspended connections a chance to resume to avoid
6688  running into the check for there not being any suspended
6689  connections left in case of a tight race with a recently
6690  resumed connection. */
6691  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6692  {
6693  daemon->resuming = true; /* Force check for pending resume. */
6695  }
6696  /* first, make sure all threads are aware of shutdown; need to
6697  traverse DLLs in peace... */
6698 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6700 #endif
6701 #ifdef UPGRADE_SUPPORT
6702  if (upg_allowed)
6703  {
6704  struct MHD_Connection *susp;
6705 
6707  while (NULL != susp)
6708  {
6709  if (NULL == susp->urh) /* "Upgraded" connection? */
6710  MHD_PANIC (_ (
6711  "MHD_stop_daemon() called while we have suspended connections.\n"));
6712 #ifdef HTTPS_SUPPORT
6713  else if (used_tls &&
6714  used_thr_p_c &&
6715  (! susp->urh->clean_ready) )
6716  shutdown (susp->urh->app.socket,
6717  SHUT_RDWR); /* Wake thread by shutdown of app socket. */
6718 #endif /* HTTPS_SUPPORT */
6719  else
6720  {
6721 #ifdef HAVE_MESSAGES
6722  if (! susp->urh->was_closed)
6723  MHD_DLOG (daemon,
6724  _ (
6725  "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6726 #endif
6727  susp->urh->was_closed = true;
6728  /* If thread-per-connection is used, connection's thread
6729  * may still processing "upgrade" (exiting). */
6730  if (! used_thr_p_c)
6732  /* Do not use MHD_resume_connection() as mutex is
6733  * already locked. */
6734  susp->resuming = true;
6735  daemon->resuming = true;
6736  }
6737  susp = susp->prev;
6738  }
6739  }
6740  else /* This 'else' is combined with next 'if' */
6741 #endif /* UPGRADE_SUPPORT */
6743  MHD_PANIC (_ (
6744  "MHD_stop_daemon() called while we have suspended connections.\n"));
6745  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
6746  {
6747  shutdown (pos->socket_fd,
6748  SHUT_RDWR);
6749 #if MHD_WINSOCK_SOCKETS
6750  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6751  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
6752  (! MHD_itc_activate_ (daemon->itc, "e")) )
6753  MHD_PANIC (_ (
6754  "Failed to signal shutdown via inter-thread communication channel.\n"));
6755 #endif
6756  }
6757 
6758 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6759  /* now, collect per-connection threads */
6760  if (used_thr_p_c)
6761  {
6762  pos = daemon->connections_tail;
6763  while (NULL != pos)
6764  {
6765  if (! pos->thread_joined)
6766  {
6768  if (! MHD_join_thread_ (pos->pid.handle))
6769  MHD_PANIC (_ ("Failed to join a thread.\n"));
6771  pos->thread_joined = true;
6772  /* The thread may have concurrently modified the DLL,
6773  need to restart from the beginning */
6774  pos = daemon->connections_tail;
6775  continue;
6776  }
6777  pos = pos->prev;
6778  }
6779  }
6781 #endif
6782 
6783 #ifdef UPGRADE_SUPPORT
6784  /* Finished threads with "upgraded" connections need to be moved
6785  * to cleanup list by resume_suspended_connections(). */
6786  /* "Upgraded" connections that were not closed explicitly by
6787  * application should be moved to cleanup list too. */
6788  if (upg_allowed)
6789  {
6790  daemon->resuming = true; /* Force check for pending resume. */
6792  }
6793 #endif /* UPGRADE_SUPPORT */
6794 
6795  /* now that we're alone, move everyone to cleanup */
6796  while (NULL != (pos = daemon->connections_tail))
6797  {
6798 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6799  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6800  (! pos->thread_joined) )
6801  MHD_PANIC (_ ("Failed to join a thread.\n"));
6802 #endif
6803  close_connection (pos);
6804  }
6806 }
6807 
6808 
6815 void
6817 {
6818  MHD_socket fd;
6819 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6820  unsigned int i;
6821 #endif
6822 
6823  if (NULL == daemon)
6824  return;
6825 
6826  daemon->shutdown = true;
6827  if (daemon->was_quiesced)
6828  fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
6829  else
6830  fd = daemon->listen_fd;
6831 
6832 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6833  if (NULL != daemon->worker_pool)
6834  { /* Master daemon with worker pool. */
6837 
6838  /* Let workers shutdown in parallel. */
6839  for (i = 0; i < daemon->worker_pool_size; ++i)
6840  {
6841  daemon->worker_pool[i].shutdown = true;
6842  if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc))
6843  {
6844  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
6845  "e"))
6846  MHD_PANIC (_ (
6847  "Failed to signal shutdown via inter-thread communication channel.\n"));
6848  }
6849  else
6851  }
6852 #ifdef HAVE_LISTEN_SHUTDOWN
6853  if (MHD_INVALID_SOCKET != fd)
6854  {
6855  (void) shutdown (fd,
6856  SHUT_RDWR);
6857  }
6858 #endif /* HAVE_LISTEN_SHUTDOWN */
6859  for (i = 0; i < daemon->worker_pool_size; ++i)
6860  {
6862  }
6863  free (daemon->worker_pool);
6865 #ifdef EPOLL_SUPPORT
6866  mhd_assert (-1 == daemon->epoll_fd);
6867 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6868  mhd_assert (-1 == daemon->epoll_upgrade_fd);
6869 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6870 #endif /* EPOLL_SUPPORT */
6871  }
6872  else
6873 #endif
6874  { /* Worker daemon or single daemon. */
6875 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6877  { /* Worker daemon or single daemon with internal thread(s). */
6879  /* Separate thread(s) is used for polling sockets. */
6880  if (MHD_ITC_IS_VALID_ (daemon->itc))
6881  {
6882  if (! MHD_itc_activate_ (daemon->itc,
6883  "e"))
6884  MHD_PANIC (_ (
6885  "Failed to signal shutdown via inter-thread communication channel.\n"));
6886  }
6887  else
6888  {
6889 #ifdef HAVE_LISTEN_SHUTDOWN
6890  if (MHD_INVALID_SOCKET != fd)
6891  {
6892  if (NULL == daemon->master)
6893  (void) shutdown (fd,
6894  SHUT_RDWR);
6895  }
6896  else
6897 #endif /* HAVE_LISTEN_SHUTDOWN */
6898  mhd_assert (false); /* Should never happen */
6899  }
6900 
6901  if (! MHD_join_thread_ (daemon->pid.handle))
6902  {
6903  MHD_PANIC (_ ("Failed to join a thread.\n"));
6904  }
6905  /* close_all_connections() was called in daemon thread. */
6906  }
6907  else
6908 #endif
6909  {
6910  /* No internal threads are used for polling sockets. */
6912  }
6913  if (MHD_ITC_IS_VALID_ (daemon->itc))
6915 
6916 #ifdef EPOLL_SUPPORT
6917  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6918  (-1 != daemon->epoll_fd) )
6919  MHD_socket_close_chk_ (daemon->epoll_fd);
6920 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6921  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6922  (-1 != daemon->epoll_upgrade_fd) )
6923  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
6924 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6925 #endif /* EPOLL_SUPPORT */
6926 
6927 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6929 #endif
6930  }
6931 
6932  if (NULL == daemon->master)
6933  { /* Cleanup that should be done only one time in master/single daemon.
6934  * Do not perform this cleanup in worker daemons. */
6935 
6936  if (MHD_INVALID_SOCKET != fd)
6938 
6939  /* TLS clean up */
6940 #ifdef HTTPS_SUPPORT
6941  if (daemon->have_dhparams)
6942  {
6943  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6944  daemon->have_dhparams = false;
6945  }
6946  if (0 != (daemon->options & MHD_USE_TLS))
6947  {
6948  gnutls_priority_deinit (daemon->priority_cache);
6949  if (daemon->x509_cred)
6950  gnutls_certificate_free_credentials (daemon->x509_cred);
6951  if (daemon->psk_cred)
6952  gnutls_psk_free_server_credentials (daemon->psk_cred);
6953  }
6954 #endif /* HTTPS_SUPPORT */
6955 
6956 #ifdef DAUTH_SUPPORT
6957  free (daemon->nnc);
6958 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6959  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6960 #endif
6961 #endif
6962 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6964 #endif
6965  free (daemon);
6966  }
6967 }
6968 
6969 
6981 const union MHD_DaemonInfo *
6983  enum MHD_DaemonInfoType info_type,
6984  ...)
6985 {
6986  if (NULL == daemon)
6987  return NULL;
6988  switch (info_type)
6989  {
6991  return NULL; /* no longer supported */
6993  return NULL; /* no longer supported */
6995  return (const union MHD_DaemonInfo *) &daemon->listen_fd;
6996 #ifdef EPOLL_SUPPORT
6998  return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
6999 #endif
7001  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
7002  {
7003  /* Assume that MHD_run() in not called in other thread
7004  * at the same time. */
7005  MHD_cleanup_connections (daemon);
7006  }
7007 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7008  else if (daemon->worker_pool)
7009  {
7010  unsigned int i;
7011  /* Collect the connection information stored in the workers. */
7012  daemon->connections = 0;
7013  for (i = 0; i < daemon->worker_pool_size; i++)
7014  {
7015  /* FIXME: next line is thread-safe only if read is atomic. */
7016  daemon->connections += daemon->worker_pool[i].connections;
7017  }
7018  }
7019 #endif
7020  return (const union MHD_DaemonInfo *) &daemon->connections;
7021  case MHD_DAEMON_INFO_FLAGS:
7022  return (const union MHD_DaemonInfo *) &daemon->options;
7024  return (const union MHD_DaemonInfo *) &daemon->port;
7025  default:
7026  return NULL;
7027  }
7028 }
7029 
7030 
7047 void
7049  void *cls)
7050 {
7051  mhd_panic = cb;
7052  mhd_panic_cls = cls;
7053 }
7054 
7055 
7062 const char *
7064 {
7065 #ifdef PACKAGE_VERSION
7066  return PACKAGE_VERSION;
7067 #else /* !PACKAGE_VERSION */
7068  static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
7069  if (0 == ver[0])
7070  {
7071  int res = MHD_snprintf_ (ver,
7072  sizeof(ver),
7073  "%x.%x.%x",
7074  (((int) MHD_VERSION >> 24) & 0xFF),
7075  (((int) MHD_VERSION >> 16) & 0xFF),
7076  (((int) MHD_VERSION >> 8) & 0xFF));
7077  if ((0 >= res) || (sizeof(ver) <= res))
7078  return "0.0.0"; /* Can't return real version*/
7079  }
7080  return ver;
7081 #endif /* !PACKAGE_VERSION */
7082 }
7083 
7084 
7096 enum MHD_Result
7098 {
7099  switch (feature)
7100  {
7101  case MHD_FEATURE_MESSAGES:
7102 #ifdef HAVE_MESSAGES
7103  return MHD_YES;
7104 #else
7105  return MHD_NO;
7106 #endif
7107  case MHD_FEATURE_TLS:
7108 #ifdef HTTPS_SUPPORT
7109  return MHD_YES;
7110 #else /* ! HTTPS_SUPPORT */
7111  return MHD_NO;
7112 #endif /* ! HTTPS_SUPPORT */
7114 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7115  return MHD_YES;
7116 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7117  return MHD_NO;
7118 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
7120 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7121  return MHD_YES;
7122 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7123  return MHD_NO;
7124 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030603 */
7125  case MHD_FEATURE_IPv6:
7126 #ifdef HAVE_INET6
7127  return MHD_YES;
7128 #else
7129  return MHD_NO;
7130 #endif
7131  case MHD_FEATURE_IPv6_ONLY:
7132 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
7133  return MHD_YES;
7134 #else
7135  return MHD_NO;
7136 #endif
7137  case MHD_FEATURE_POLL:
7138 #ifdef HAVE_POLL
7139  return MHD_YES;
7140 #else
7141  return MHD_NO;
7142 #endif
7143  case MHD_FEATURE_EPOLL:
7144 #ifdef EPOLL_SUPPORT
7145  return MHD_YES;
7146 #else
7147  return MHD_NO;
7148 #endif
7150 #ifdef HAVE_LISTEN_SHUTDOWN
7151  return MHD_YES;
7152 #else
7153  return MHD_NO;
7154 #endif
7156 #ifdef _MHD_ITC_SOCKETPAIR
7157  return MHD_YES;
7158 #else
7159  return MHD_NO;
7160 #endif
7162 #ifdef TCP_FASTOPEN
7163  return MHD_YES;
7164 #else
7165  return MHD_NO;
7166 #endif
7168 #ifdef BAUTH_SUPPORT
7169  return MHD_YES;
7170 #else
7171  return MHD_NO;
7172 #endif
7174 #ifdef DAUTH_SUPPORT
7175  return MHD_YES;
7176 #else
7177  return MHD_NO;
7178 #endif
7180 #ifdef HAVE_POSTPROCESSOR
7181  return MHD_YES;
7182 #else
7183  return MHD_NO;
7184 #endif
7186 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
7187  return MHD_YES;
7188 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
7189  return MHD_NO;
7190 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
7192 #if defined(HAVE_PREAD64) || defined(_WIN32)
7193  return MHD_YES;
7194 #elif defined(HAVE_PREAD)
7195  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
7196 #elif defined(HAVE_LSEEK64)
7197  return MHD_YES;
7198 #else
7199  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
7200 #endif
7202 #if defined(MHD_USE_THREAD_NAME_)
7203  return MHD_YES;
7204 #else
7205  return MHD_NO;
7206 #endif
7207  case MHD_FEATURE_UPGRADE:
7208 #if defined(UPGRADE_SUPPORT)
7209  return MHD_YES;
7210 #else
7211  return MHD_NO;
7212 #endif
7214 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
7215  return MHD_YES;
7216 #else
7217  return MHD_NO;
7218 #endif
7220 #ifdef MHD_USE_GETSOCKNAME
7221  return MHD_YES;
7222 #else
7223  return MHD_NO;
7224 #endif
7226 #if defined(MHD_WINSOCK_SOCKETS) || defined(MHD_socket_nosignal_) || \
7227  defined (MSG_NOSIGNAL)
7228  return MHD_YES;
7229 #else
7230  return MHD_NO;
7231 #endif
7232  case MHD_FEATURE_SENDFILE:
7233 #ifdef _MHD_HAVE_SENDFILE
7234  return MHD_YES;
7235 #else
7236  return MHD_NO;
7237 #endif
7238  case MHD_FEATURE_THREADS:
7239 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7240  return MHD_YES;
7241 #else
7242  return MHD_NO;
7243 #endif
7244 
7245  }
7246  return MHD_NO;
7247 }
7248 
7249 
7250 #ifdef MHD_HTTPS_REQUIRE_GRYPT
7251 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
7252 #if defined(MHD_USE_POSIX_THREADS)
7253 GCRY_THREAD_OPTION_PTHREAD_IMPL;
7254 #elif defined(MHD_W32_MUTEX_)
7255 
7256 static int
7257 gcry_w32_mutex_init (void **ppmtx)
7258 {
7259  *ppmtx = malloc (sizeof (MHD_mutex_));
7260 
7261  if (NULL == *ppmtx)
7262  return ENOMEM;
7263  if (! MHD_mutex_init_ ((MHD_mutex_*) *ppmtx))
7264  {
7265  free (*ppmtx);
7266  *ppmtx = NULL;
7267  return EPERM;
7268  }
7269 
7270  return 0;
7271 }
7272 
7273 
7274 static int
7275 gcry_w32_mutex_destroy (void **ppmtx)
7276 {
7277  int res = (MHD_mutex_destroy_ ((MHD_mutex_*) *ppmtx)) ? 0 : EINVAL;
7278  free (*ppmtx);
7279  return res;
7280 }
7281 
7282 
7283 static int
7284 gcry_w32_mutex_lock (void **ppmtx)
7285 {
7286  return MHD_mutex_lock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7287 }
7288 
7289 
7290 static int
7291 gcry_w32_mutex_unlock (void **ppmtx)
7292 {
7293  return MHD_mutex_unlock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7294 }
7295 
7296 
7297 static struct gcry_thread_cbs gcry_threads_w32 = {
7298  (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
7299  NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
7300  gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
7301  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
7302 };
7303 
7304 #endif /* defined(MHD_W32_MUTEX_) */
7305 #endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
7306 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
7307 
7311 void
7312 MHD_init (void)
7313 {
7314 #if defined(MHD_WINSOCK_SOCKETS)
7315  WSADATA wsd;
7316 #endif /* MHD_WINSOCK_SOCKETS */
7317 
7318  if (NULL == mhd_panic)
7320 
7321 #if defined(MHD_WINSOCK_SOCKETS)
7322  if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
7323  MHD_PANIC (_ ("Failed to initialize winsock.\n"));
7324  mhd_winsock_inited_ = 1;
7325  if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
7326  MHD_PANIC (_ ("Winsock version 2.2 is not available.\n"));
7327 #endif /* MHD_WINSOCK_SOCKETS */
7328 #ifdef HTTPS_SUPPORT
7329 #ifdef MHD_HTTPS_REQUIRE_GRYPT
7330 #if GCRYPT_VERSION_NUMBER < 0x010600
7331 #if defined(MHD_USE_POSIX_THREADS)
7332  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7333  &gcry_threads_pthread))
7334  MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
7335 #elif defined(MHD_W32_MUTEX_)
7336  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7337  &gcry_threads_w32))
7338  MHD_PANIC (_ ("Failed to initialise multithreading in libgcrypt.\n"));
7339 #endif /* defined(MHD_W32_MUTEX_) */
7340  gcry_check_version (NULL);
7341 #else
7342  if (NULL == gcry_check_version ("1.6.0"))
7343  MHD_PANIC (_ (
7344  "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
7345 #endif
7346 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
7347  gnutls_global_init ();
7348 #endif /* HTTPS_SUPPORT */
7350 #ifdef HAVE_FREEBSD_SENDFILE
7351  MHD_conn_init_static_ ();
7352 #endif /* HAVE_FREEBSD_SENDFILE */
7354 }
7355 
7356 
7357 void
7358 MHD_fini (void)
7359 {
7360 #ifdef HTTPS_SUPPORT
7361  gnutls_global_deinit ();
7362 #endif /* HTTPS_SUPPORT */
7363 #if defined(MHD_WINSOCK_SOCKETS)
7364  if (mhd_winsock_inited_)
7365  WSACleanup ();
7366 #endif /* MHD_WINSOCK_SOCKETS */
7368 }
7369 
7370 
7371 #ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
7373 #endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
7374 
7375 /* end of daemon.c */
MHD_socket
int MHD_socket
Definition: microhttpd.h:195
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:4801
MHD_OptionItem::value
intptr_t value
Definition: microhttpd.h:1750
mhd_compat.h
Header for platform missing functions.
parse_options
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:4985
_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
@ MHD_USE_NO_LISTEN_SOCKET
Definition: microhttpd.h:1172
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:6982
_
#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:1600
MHD_DAEMON_INFO_MAC_KEY_SIZE
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
Definition: microhttpd.h:2061
MHD_socket_nonblocking_
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:407
MHD_OPTION_CONNECTION_LIMIT
@ MHD_OPTION_CONNECTION_LIMIT
Definition: microhttpd.h:1388
MHD_OPTION_LISTEN_BACKLOG_SIZE
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
Definition: microhttpd.h:1670
MHD_Daemon::uri_log_callback
LogCallback uri_log_callback
Definition: internal.h:1397
close_connection
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:4712
MHD_AccessHandlerCallback
enum MHD_Result(* MHD_AccessHandlerCallback)(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
Definition: microhttpd.h:2175
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:1407
MHD_Daemon::pool_size
size_t pool_size
Definition: internal.h:1447
MHD_Connection::resuming
bool resuming
Definition: internal.h:774
global_init_count
volatile int global_init_count
Definition: daemon.c:187
UnescapeCallback
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1240
MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
Definition: microhttpd.h:1846
MHD_Daemon::listen_backlog_size
unsigned int listen_backlog_size
Definition: internal.h:1754
MHD_SCKT_EINTR_
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:414
MAYBE_SOCK_NOSIGPIPE
#define MAYBE_SOCK_NOSIGPIPE
Definition: mhd_sockets.h:174
MHD_Daemon::connection_limit
unsigned int connection_limit
Definition: internal.h:1583
LogCallback
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1226
MHD_Connection::prev
struct MHD_Connection * prev
Definition: internal.h:656
MHD_Connection::sk_cork_on
bool sk_cork_on
Definition: internal.h:885
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:4833
MHD_FEATURE_LARGE_FILE
@ MHD_FEATURE_LARGE_FILE
Definition: microhttpd.h:3981
MHD_OPTION_HTTPS_MEM_DHPARAMS
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
Definition: microhttpd.h:1633
data
void * data
Definition: microhttpd.h:3038
MHD_init
void MHD_init(void)
Definition: daemon.c:7312
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
@ 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_poll
static enum MHD_Result MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:4163
MHD_Connection::tls_read_ready
bool tls_read_ready
Definition: internal.h:769
MHD_EPOLL_STATE_WRITE_READY
@ 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:1361
MHD_USE_TURBO
@ MHD_USE_TURBO
Definition: microhttpd.h:1252
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
@ MHD_OPTION_END
Definition: microhttpd.h:1373
MHD_SCKT_OPT_BOOL_
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:203
autoinit_funcs.h
MHD_connection_handle_idle
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3222
MHD_Daemon::manual_timeout_tail
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
MHD_FEATURE_MESSAGES
@ MHD_FEATURE_MESSAGES
Definition: microhttpd.h:3878
MHD_Daemon::port
uint16_t port
Definition: internal.h:1605
MHD_resume_connection
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2936
MHD_connection_finish_forward_
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
MHD_OPTION_HTTPS_KEY_PASSWORD
@ MHD_OPTION_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:1651
MHD_Daemon::connections
unsigned int connections
Definition: internal.h:1361
MHD_UNSIGNED_LONG_LONG
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:298
_MHD_EXTERN
#define _MHD_EXTERN
Definition: mhd_options.h:50
MHD_YES
@ MHD_YES
Definition: microhttpd.h:150
MHD_socket_set_nodelay_
int MHD_socket_set_nodelay_(MHD_socket sock, bool on)
Definition: mhd_sockets.c:471
resume_suspended_connections
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2973
MHD_monotonic_sec_counter
time_t MHD_monotonic_sec_counter(void)
Definition: mhd_mono_clock.c:337
MHD_Connection::sk_nonblck
bool sk_nonblck
Definition: internal.h:784
MHD_USE_IPv6
@ MHD_USE_IPv6
Definition: microhttpd.h:1104
MHD_EVENT_LOOP_INFO_BLOCK
@ 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:1491
MHD_Daemon::normal_timeout_tail
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
MHD_OPTION_DIGEST_AUTH_RANDOM
@ MHD_OPTION_DIGEST_AUTH_RANDOM
Definition: microhttpd.h:1575
MHD_FEATURE_UPGRADE
@ MHD_FEATURE_UPGRADE
Definition: microhttpd.h:3994
parse_options_va
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:5010
MHD_OPTION_PER_IP_CONNECTION_LIMIT
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
Definition: microhttpd.h:1421
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
@ MHD_OPTION_NOTIFY_COMPLETED
Definition: microhttpd.h:1409
MHD_monotonic_sec_counter_finish
void MHD_monotonic_sec_counter_finish(void)
Definition: mhd_mono_clock.c:316
MHD_OPTION_SERVER_INSANITY
@ MHD_OPTION_SERVER_INSANITY
Definition: microhttpd.h:1716
MHD_get_fdset2
_MHD_EXTERN enum MHD_Result MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: daemon.c:1129
MHD_CONNECTION_CLOSED
@ MHD_CONNECTION_CLOSED
Definition: internal.h:526
MHD_Daemon::notify_completed_cls
void * notify_completed_cls
Definition: internal.h:1377
MHD_FLAG
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:1038
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
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
Definition: microhttpd.h:2085
MHD_NO
@ MHD_NO
Definition: microhttpd.h:145
MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
Definition: microhttpd.h:1823
MHD_recv_
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
MHD_FEATURE_HTTPS_CERT_CALLBACK
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:3894
MHD_Connection::last_activity
time_t last_activity
Definition: internal.h:739
connection_https.h
Methods for managing connections.
MHD_OPTION_NONCE_NC_SIZE
@ MHD_OPTION_NONCE_NC_SIZE
Definition: microhttpd.h:1582
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:2810
MHD_fini
void MHD_fini(void)
Definition: daemon.c:7358
MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
Definition: microhttpd.h:1626
MHD_ITC_IS_INVALID_
#define MHD_ITC_IS_INVALID_(itc)
Definition: mhd_itc.h:367
MHD_EPOLL_STATE_ERROR
@ MHD_EPOLL_STATE_ERROR
Definition: internal.h:626
MHD_OPTION_LISTENING_ADDRESS_REUSE
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
Definition: microhttpd.h:1642
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
@ MHD_FEATURE_POSTPROCESSOR
Definition: microhttpd.h:3964
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:196
MHD_DisableSanityCheck
MHD_DisableSanityCheck
Definition: microhttpd.h:1725
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:2198
MHD_quiesce_daemon
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:4878
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:1743
_MHD_TIMEVAL_TV_SEC_TYPE
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
MHD_USE_INSECURE_TLS_EARLY_DATA
@ MHD_USE_INSECURE_TLS_EARLY_DATA
Definition: microhttpd.h:1323
MHD_OptionItem
Definition: microhttpd.h:1738
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_FEATURE_AUTODETECT_BIND_PORT
@ MHD_FEATURE_AUTODETECT_BIND_PORT
Definition: microhttpd.h:4013
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:1756
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:3873
MHD_Daemon::resuming
bool resuming
Definition: internal.h:1510
MHD_Connection::pool
struct MemoryPool * pool
Definition: internal.h:685
MHD_FEATURE_TCP_FASTOPEN
@ MHD_FEATURE_TCP_FASTOPEN
Definition: microhttpd.h:3941
MHD_CONNECTION_CHUNKED_BODY_READY
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:501
MHD_OPTION_HTTPS_PRIORITIES
@ MHD_OPTION_HTTPS_PRIORITIES
Definition: microhttpd.h:1490
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
@ MHD_OPTION_THREAD_POOL_SIZE
Definition: microhttpd.h:1521
MHD_FEATURE_RESPONSES_SHARED_FD
@ MHD_FEATURE_RESPONSES_SHARED_FD
Definition: microhttpd.h:4007
MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
Definition: microhttpd.h:1694
MHD_Daemon::pool_increment
size_t pool_increment
Definition: internal.h:1452
_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_add_connection
_MHD_EXTERN enum MHD_Result MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:3128
MHD_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:4957
MHD_Daemon::notify_completed
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1372
MHD_AcceptPolicyCallback
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:2130
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:1388
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
@ MHD_DAEMON_INFO_FLAGS
Definition: microhttpd.h:2093
MHD_Daemon::per_ip_connection_limit
unsigned int per_ip_connection_limit
Definition: internal.h:1595
MHD_Daemon::apc_cls
void * apc_cls
Definition: internal.h:1366
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
@ MHD_EPOLL_STATE_IN_EPOLL_SET
Definition: internal.h:616
mhd_mono_clock.h
internal monotonic clock functions implementations
MHD_Daemon::insanity_level
enum MHD_DisableSanityCheck insanity_level
Definition: internal.h:1486
MHD_NonceNc
Definition: internal.h:228
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:3166
MHD_get_version
_MHD_EXTERN const char * MHD_get_version(void)
Definition: version.c:35
MHD_EVENT_LOOP_INFO_READ
@ 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:2869
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
@ MHD_USE_AUTO
Definition: microhttpd.h:1303
MHD_Connection::read_buffer_offset
size_t read_buffer_offset
Definition: internal.h:789
MHD_OPTION_CONNECTION_MEMORY_INCREMENT
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
Definition: microhttpd.h:1601
MHD_OPTION_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:1705
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:2224
MHD_Daemon::default_handler_cls
void * default_handler_cls
Definition: internal.h:1263
MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
Definition: microhttpd.h:4020
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
@ MHD_OPTION_HTTPS_MEM_KEY
Definition: microhttpd.h:1469
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
@ MHD_FEATURE_IPv6_ONLY
Definition: microhttpd.h:3908
MHD_OPTION_LISTEN_SOCKET
@ MHD_OPTION_LISTEN_SOCKET
Definition: microhttpd.h:1498
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
@ MHD_OPTION_EXTERNAL_LOGGER
Definition: microhttpd.h:1511
MHD_Connection::addr
struct sockaddr_storage addr
Definition: internal.h:728
MHD_Daemon::connection_timeout
time_t connection_timeout
Definition: internal.h:1589
UINT_MAX
#define UINT_MAX
Definition: mhd_limits.h:45
MHD_OPTION_UNESCAPE_CALLBACK
@ MHD_OPTION_UNESCAPE_CALLBACK
Definition: microhttpd.h:1564
DLL_remove
#define DLL_remove(head, tail, element)
Definition: internal.h:1763
internal_get_fdset2
static enum MHD_Result internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: daemon.c:980
MHD_DAEMON_INFO_LISTEN_FD
@ MHD_DAEMON_INFO_LISTEN_FD
Definition: microhttpd.h:2067
MHD_suspend_connection
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2905
MHD_socket_buffering_reset_
int MHD_socket_buffering_reset_(MHD_socket sock)
Definition: mhd_sockets.c:552
MHD_Connection::state
enum MHD_CONNECTION_STATE state
Definition: internal.h:924
MHD_USE_TLS
@ MHD_USE_TLS
Definition: microhttpd.h:1060
internal_add_connection
static enum MHD_Result internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck)
Definition: daemon.c:2373
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_FEATURE_SENDFILE
@ MHD_FEATURE_SENDFILE
Definition: microhttpd.h:4027
MHD_PanicCallback
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:2116
MHD_OPTION
MHD_OPTION
MHD options.
Definition: microhttpd.h:1367
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
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
Definition: microhttpd.h:3928
MHD_itc_destroy_chk_
#define MHD_itc_destroy_chk_(itc)
Definition: mhd_itc.h:353
MHD_USE_EPOLL
@ MHD_USE_EPOLL
Definition: microhttpd.h:1181
MHD_DAEMON_INFO_KEY_SIZE
@ MHD_DAEMON_INFO_KEY_SIZE
Definition: microhttpd.h:2056
MHD_USE_ITC
@ MHD_USE_ITC
Definition: microhttpd.h:1230
MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1086
MHD_ALLOW_UPGRADE
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1290
MHD_get_fdset
_MHD_EXTERN enum MHD_Result MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
Definition: daemon.c:727
MHD_FEATURE_TLS
@ MHD_FEATURE_TLS
Definition: microhttpd.h:3887
MHD_FEATURE_IPv6
@ MHD_FEATURE_IPv6
Definition: microhttpd.h:3900
MHD_stop_daemon
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:6816
MHD_CONNECTION_NOTIFY_STARTED
@ MHD_CONNECTION_NOTIFY_STARTED
Definition: microhttpd.h:1881
MHD_Daemon::manual_timeout_head
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
internal_run_from_select
static enum MHD_Result internal_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
Definition: daemon.c:3537
MHD_OPTION_CONNECTION_MEMORY_LIMIT
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
Definition: microhttpd.h:1382
MHD_Connection::addr_len
socklen_t addr_len
Definition: internal.h:733
MHD_Daemon
Definition: internal.h:1001
MHD_DaemonInfoType
MHD_DaemonInfoType
Definition: microhttpd.h:2052
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
@ MHD_USE_DUAL_STACK
Definition: microhttpd.h:1244
MHD_run
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:4677
MHD_Daemon::unescape_callback_cls
void * unescape_callback_cls
Definition: internal.h:1412
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
@ MHD_FEATURE_BASIC_AUTH
Definition: microhttpd.h:3948
MHD_USE_PEDANTIC_CHECKS
@ MHD_USE_PEDANTIC_CHECKS
Definition: microhttpd.h:1115
MHD_Connection::event_loop_info
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:929
MHD_ALLOW_SUSPEND_RESUME
@ MHD_ALLOW_SUSPEND_RESUME
Definition: microhttpd.h:1267
MHD_EVENT_LOOP_INFO_CLEANUP
@ 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
@ MHD_OPTION_SOCK_ADDR
Definition: microhttpd.h:1429
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
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:3339
connection.h
Methods for managing connections.
MHD_Daemon::default_handler
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1258
MHD_http_unescape
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:142
MHD_EPOLL_STATE_READ_READY
@ MHD_EPOLL_STATE_READ_READY
Definition: internal.h:600
MHD_USE_POLL
@ MHD_USE_POLL
Definition: microhttpd.h:1131
close_all_connections
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:6655
MHD_accept_connection
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3189
MHD_Daemon::per_ip_connection_mutex
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1259
MHD_FEATURE_HTTPS_KEY_PASSWORD
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
Definition: microhttpd.h:3971
MHD_FEATURE_EPOLL
@ MHD_FEATURE_EPOLL
Definition: microhttpd.h:3921
MHD_Daemon::notify_connection
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1383
MHD_ip_addr_to_key
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:365
MHD_Connection::response
struct MHD_Response * response
Definition: internal.h:680
MHD_BUF_INC_SIZE
#define MHD_BUF_INC_SIZE
Definition: internal.h:120
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:3798
MHD_connection_handle_read
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2756
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
@ MHD_OPTION_HTTPS_CRED_TYPE
Definition: microhttpd.h:1484
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
@ MHD_OPTION_ARRAY
Definition: microhttpd.h:1542
XDLL_insert
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
MHD_DAEMON_INFO_EPOLL_FD
@ MHD_DAEMON_INFO_EPOLL_FD
Definition: microhttpd.h:2076
MHD_DAEMON_INFO_BIND_PORT
@ MHD_DAEMON_INFO_BIND_PORT
Definition: microhttpd.h:2101
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
@ MHD_OPTION_HTTPS_MEM_TRUST
Definition: microhttpd.h:1595
MHD_FEATURE_SOCKETPAIR
@ MHD_FEATURE_SOCKETPAIR
Definition: microhttpd.h:3934
MHD_Daemon::strict_for_client
int strict_for_client
Definition: internal.h:1610
MHD_SCKT_EINVAL_
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:464
MHD_REQUEST_TERMINATED_WITH_ERROR
@ MHD_REQUEST_TERMINATED_WITH_ERROR
Definition: microhttpd.h:1831
MHD_FEATURE_THREAD_NAMES
@ MHD_FEATURE_THREAD_NAMES
Definition: microhttpd.h:3986
MHD_run_from_select
_MHD_EXTERN enum MHD_Result MHD_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
Definition: daemon.c:3641
MHD_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:5698
MHD_CONNECTION_HEADERS_SENDING
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:480
MHD_FEATURE_HTTPS_CERT_CALLBACK2
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
Definition: microhttpd.h:4038
MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1075
MHD_socket_create_listen_
MHD_socket MHD_socket_create_listen_(int pf)
Definition: mhd_sockets.c:474
MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
Definition: microhttpd.h:1317
MHD_FEATURE_DIGEST_AUTH
@ MHD_FEATURE_DIGEST_AUTH
Definition: microhttpd.h:3956
MHD_OPTION_STRICT_FOR_CLIENT
@ MHD_OPTION_STRICT_FOR_CLIENT
Definition: microhttpd.h:1686
mhd_itc.h
Header for platform-independent inter-thread communication.
MHD_OPTION_URI_LOG_CALLBACK
@ MHD_OPTION_URI_LOG_CALLBACK
Definition: microhttpd.h:1461
MHD_Connection
Definition: internal.h:634
MHD_Daemon::connections_head
struct MHD_Connection * connections_head
Definition: internal.h:1155
MAYBE_SOCK_CLOEXEC
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:157
MHD_Result
MHD_Result
Definition: microhttpd.h:141
MHD_OPTION_THREAD_STACK_SIZE
@ MHD_OPTION_THREAD_STACK_SIZE
Definition: microhttpd.h:1588
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:1402
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
call_handlers
static enum MHD_Result call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1195
MHD_ip_limit_add
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:416
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:312
tsearch.h
MHD_OPTION_HTTPS_MEM_CERT
@ MHD_OPTION_HTTPS_MEM_CERT
Definition: microhttpd.h:1477
TIMEVAL_TV_SEC_MAX
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:140
MHD_FEATURE_POLL
@ MHD_FEATURE_POLL
Definition: microhttpd.h:3914
MHD_Connection::next
struct MHD_Connection * next
Definition: internal.h:651
MHD_TLS_CONN_INIT
@ MHD_TLS_CONN_INIT
Definition: internal.h:545
MHD_PskServerCredentialsCallback
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
Definition: microhttpd.h:1355
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
@ MHD_OPTION_CONNECTION_TIMEOUT
Definition: microhttpd.h:1395
MHD_select
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3695
MHD_Connection::socket_context
void * socket_context
Definition: internal.h:694
MHD_USE_TCP_FASTOPEN
@ MHD_USE_TCP_FASTOPEN
Definition: microhttpd.h:1283
MHD_get_timeout
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3447
MHD_EPOLL_STATE_SUSPENDED
@ MHD_EPOLL_STATE_SUSPENDED
Definition: internal.h:621
MHD_Daemon::listening_address_reuse
int listening_address_reuse
Definition: internal.h:1502
MHD_SCKT_ERR_IS_EINTR_
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:634
MHD_OPTION_HTTPS_CERT_CALLBACK
@ MHD_OPTION_HTTPS_CERT_CALLBACK
Definition: microhttpd.h:1617
MHD_init_mem_pools_
void MHD_init_mem_pools_(void)
Definition: memorypool.c:85
MHD_EPOLL_STATE_IN_EREADY_EDLL
@ 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:3760
MHD_OPTION_NOTIFY_CONNECTION
@ MHD_OPTION_NOTIFY_CONNECTION
Definition: microhttpd.h:1662
MHD_Connection::client_context
void * client_context
Definition: internal.h:698
MHD_CONNECTION_INIT
@ MHD_CONNECTION_INIT
Definition: internal.h:427
MHD_CONNECTION_NOTIFY_CLOSED
@ MHD_CONNECTION_NOTIFY_CLOSED
Definition: microhttpd.h:1887
MHD_is_feature_supported
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:7097
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
@ MHD_FEATURE_THREADS
Definition: microhttpd.h:4032
MHD_Connection::socket_fd
MHD_socket socket_fd
Definition: internal.h:752
MHD_EVENT_LOOP_INFO_WRITE
@ 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:146