GNU libmicrohttpd  0.9.59
daemon.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2017 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 #include "mhd_threads.h"
30 #include "internal.h"
31 #include "response.h"
32 #include "connection.h"
33 #include "memorypool.h"
34 #include "mhd_limits.h"
35 #include "autoinit_funcs.h"
36 #include "mhd_mono_clock.h"
37 #include "mhd_locks.h"
38 #include "mhd_sockets.h"
39 #include "mhd_itc.h"
40 #include "mhd_compat.h"
41 
42 #if HAVE_SEARCH_H
43 #include <search.h>
44 #else
45 #include "tsearch.h"
46 #endif
47 
48 #ifdef HTTPS_SUPPORT
49 #include "connection_https.h"
50 #ifdef MHD_HTTPS_REQUIRE_GRYPT
51 #include <gcrypt.h>
52 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
53 #endif /* HTTPS_SUPPORT */
54 
55 #if defined(_WIN32) && ! defined(__CYGWIN__)
56 #ifndef WIN32_LEAN_AND_MEAN
57 #define WIN32_LEAN_AND_MEAN 1
58 #endif /* !WIN32_LEAN_AND_MEAN */
59 #include <windows.h>
60 #endif
61 
65 #ifdef MHD_POSIX_SOCKETS
66 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
67 #else
68 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
69 #endif
70 
74 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
75 
80 #define DEBUG_CLOSE MHD_NO
81 
86 #define DEBUG_CONNECT MHD_NO
87 
88 
89 /* Forward declarations. */
90 
99 static void
100 close_all_connections (struct MHD_Daemon *daemon);
101 
102 #ifdef EPOLL_SUPPORT
103 
112 static int
113 MHD_epoll (struct MHD_Daemon *daemon,
114  int may_block);
115 
116 #endif /* EPOLL_SUPPORT */
117 
127 static void
128 mhd_panic_std (void *cls,
129  const char *file,
130  unsigned int line,
131  const char *reason)
132 {
133  (void)cls; /* Mute compiler warning. */
134 #ifdef HAVE_MESSAGES
135  fprintf (stderr,
136  _("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
137  file,
138  line,
139  reason);
140 #else /* ! HAVE_MESSAGES */
141  (void)file; /* Mute compiler warning. */
142  (void)line; /* Mute compiler warning. */
143  (void)reason; /* Mute compiler warning. */
144 #endif
145  abort ();
146 }
147 
148 
153 
158 
162 void
163 MHD_init(void);
164 
165 
166 #if defined(_WIN32) && ! defined(__CYGWIN__)
167 
170 static int mhd_winsock_inited_ = 0;
171 #endif
172 
173 #ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
174 
178 #define MHD_check_global_init_() (void)0
179 #else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
180 
183 volatile int global_init_count = 0;
184 #ifdef MHD_MUTEX_STATIC_DEFN_INIT_
185 
188 MHD_MUTEX_STATIC_DEFN_INIT_(global_init_mutex_);
189 #endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
190 
194 void
196 {
197 #ifdef MHD_MUTEX_STATIC_DEFN_INIT_
198  MHD_mutex_lock_chk_(&global_init_mutex_);
199 #endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
200  if (0 == global_init_count++)
201  MHD_init ();
202 #ifdef MHD_MUTEX_STATIC_DEFN_INIT_
203  MHD_mutex_unlock_chk_(&global_init_mutex_);
204 #endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
205 }
206 #endif /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
207 
215 static struct MHD_Daemon*
216 MHD_get_master (struct MHD_Daemon *daemon)
217 {
218  while (NULL != daemon->master)
219  daemon = daemon->master;
220  return daemon;
221 }
222 
223 
227 struct MHD_IPCount
228 {
232  int family;
233 
237  union
238  {
242  struct in_addr ipv4;
243 #if HAVE_INET6
244 
247  struct in6_addr ipv6;
248 #endif
249  } addr;
250 
254  unsigned int count;
255 };
256 
257 
263 static void
265 {
267 }
268 
269 
275 static void
277 {
279 }
280 
281 
291 static int
292 MHD_ip_addr_compare (const void *a1,
293  const void *a2)
294 {
295  return memcmp (a1,
296  a2,
297  offsetof (struct MHD_IPCount,
298  count));
299 }
300 
301 
310 static int
311 MHD_ip_addr_to_key (const struct sockaddr *addr,
312  socklen_t addrlen,
313  struct MHD_IPCount *key)
314 {
315  memset(key,
316  0,
317  sizeof(*key));
318 
319  /* IPv4 addresses */
320  if (sizeof (struct sockaddr_in) == addrlen)
321  {
322  const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
323 
324  key->family = AF_INET;
325  memcpy (&key->addr.ipv4,
326  &addr4->sin_addr,
327  sizeof(addr4->sin_addr));
328  return MHD_YES;
329  }
330 
331 #if HAVE_INET6
332  /* IPv6 addresses */
333  if (sizeof (struct sockaddr_in6) == addrlen)
334  {
335  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
336 
337  key->family = AF_INET6;
338  memcpy (&key->addr.ipv6,
339  &addr6->sin6_addr,
340  sizeof(addr6->sin6_addr));
341  return MHD_YES;
342  }
343 #endif
344 
345  /* Some other address */
346  return MHD_NO;
347 }
348 
349 
361 static int
362 MHD_ip_limit_add (struct MHD_Daemon *daemon,
363  const struct sockaddr *addr,
364  socklen_t addrlen)
365 {
366  struct MHD_IPCount *key;
367  void **nodep;
368  void *node;
369  int result;
370 
371  daemon = MHD_get_master (daemon);
372  /* Ignore if no connection limit assigned */
373  if (0 == daemon->per_ip_connection_limit)
374  return MHD_YES;
375 
376  if (NULL == (key = malloc (sizeof(*key))))
377  return MHD_NO;
378 
379  /* Initialize key */
380  if (MHD_NO == MHD_ip_addr_to_key (addr,
381  addrlen,
382  key))
383  {
384  /* Allow unhandled address types through */
385  free (key);
386  return MHD_YES;
387  }
388  MHD_ip_count_lock (daemon);
389 
390  /* Search for the IP address */
391  if (NULL == (nodep = tsearch (key,
392  &daemon->per_ip_connection_count,
394  {
395 #ifdef HAVE_MESSAGES
396  MHD_DLOG (daemon,
397  _("Failed to add IP connection count node\n"));
398 #endif
399  MHD_ip_count_unlock (daemon);
400  free (key);
401  return MHD_NO;
402  }
403  node = *nodep;
404  /* If we got an existing node back, free the one we created */
405  if (node != key)
406  free(key);
407  key = (struct MHD_IPCount *) node;
408  /* Test if there is room for another connection; if so,
409  * increment count */
410  result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
411  if (MHD_YES == result)
412  ++key->count;
413 
414  MHD_ip_count_unlock (daemon);
415  return result;
416 }
417 
418 
427 static void
428 MHD_ip_limit_del (struct MHD_Daemon *daemon,
429  const struct sockaddr *addr,
430  socklen_t addrlen)
431 {
432  struct MHD_IPCount search_key;
433  struct MHD_IPCount *found_key;
434  void **nodep;
435 
436  daemon = MHD_get_master (daemon);
437  /* Ignore if no connection limit assigned */
438  if (0 == daemon->per_ip_connection_limit)
439  return;
440  /* Initialize search key */
441  if (MHD_NO == MHD_ip_addr_to_key (addr,
442  addrlen,
443  &search_key))
444  return;
445 
446  MHD_ip_count_lock (daemon);
447 
448  /* Search for the IP address */
449  if (NULL == (nodep = tfind (&search_key,
450  &daemon->per_ip_connection_count,
452  {
453  /* Something's wrong if we couldn't find an IP address
454  * that was previously added */
455  MHD_PANIC (_("Failed to find previously-added IP address\n"));
456  }
457  found_key = (struct MHD_IPCount *) *nodep;
458  /* Validate existing count for IP address */
459  if (0 == found_key->count)
460  {
461  MHD_PANIC (_("Previously-added IP address had counter of zero\n"));
462  }
463  /* Remove the node entirely if count reduces to 0 */
464  if (0 == --found_key->count)
465  {
466  tdelete (found_key,
467  &daemon->per_ip_connection_count,
469  free (found_key);
470  }
471 
472  MHD_ip_count_unlock (daemon);
473 }
474 
475 
476 #ifdef HTTPS_SUPPORT
477 
483 static int
484 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
485 {
486  gnutls_datum_t key;
487  gnutls_datum_t cert;
488  int ret;
489 
490 #if GNUTLS_VERSION_MAJOR >= 3
491  if (NULL != daemon->cert_callback)
492  {
493  gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
494  daemon->cert_callback);
495  }
496 #endif
497  if (NULL != daemon->https_mem_trust)
498  {
499  cert.data = (unsigned char *) daemon->https_mem_trust;
500  cert.size = strlen (daemon->https_mem_trust);
501  if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
502  &cert,
503  GNUTLS_X509_FMT_PEM) < 0)
504  {
505 #ifdef HAVE_MESSAGES
506  MHD_DLOG(daemon,
507  "Bad trust certificate format\n");
508 #endif
509  return -1;
510  }
511  }
512 
513  if (daemon->have_dhparams)
514  {
515  gnutls_certificate_set_dh_params (daemon->x509_cred,
516  daemon->https_mem_dhparams);
517  }
518  /* certificate & key loaded from memory */
519  if ( (NULL != daemon->https_mem_cert) &&
520  (NULL != daemon->https_mem_key) )
521  {
522  key.data = (unsigned char *) daemon->https_mem_key;
523  key.size = strlen (daemon->https_mem_key);
524  cert.data = (unsigned char *) daemon->https_mem_cert;
525  cert.size = strlen (daemon->https_mem_cert);
526 
527  if (NULL != daemon->https_key_password) {
528 #if GNUTLS_VERSION_NUMBER >= 0x030111
529  ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
530  &cert,
531  &key,
532  GNUTLS_X509_FMT_PEM,
533  daemon->https_key_password,
534  0);
535 #else
536 #ifdef HAVE_MESSAGES
537  MHD_DLOG (daemon,
538  _("Failed to setup x509 certificate/key: pre 3.X.X version " \
539  "of GnuTLS does not support setting key password"));
540 #endif
541  return -1;
542 #endif
543  }
544  else
545  ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
546  &cert,
547  &key,
548  GNUTLS_X509_FMT_PEM);
549 #ifdef HAVE_MESSAGES
550  if (0 != ret)
551  MHD_DLOG (daemon,
552  "GnuTLS failed to setup x509 certificate/key: %s\n",
553  gnutls_strerror (ret));
554 #endif
555  return ret;
556  }
557 #if GNUTLS_VERSION_MAJOR >= 3
558  if (NULL != daemon->cert_callback)
559  return 0;
560 #endif
561 #ifdef HAVE_MESSAGES
562  MHD_DLOG (daemon,
563  "You need to specify a certificate and key location\n");
564 #endif
565  return -1;
566 }
567 
568 
575 static int
576 MHD_TLS_init (struct MHD_Daemon *daemon)
577 {
578  switch (daemon->cred_type)
579  {
580  case GNUTLS_CRD_CERTIFICATE:
581  if (0 !=
582  gnutls_certificate_allocate_credentials (&daemon->x509_cred))
583  return GNUTLS_E_MEMORY_ERROR;
584  return MHD_init_daemon_certificate (daemon);
585  default:
586 #ifdef HAVE_MESSAGES
587  MHD_DLOG (daemon,
588  _("Error: invalid credentials type %d specified.\n"),
589  daemon->cred_type);
590 #endif
591  return -1;
592  }
593 }
594 #endif /* HTTPS_SUPPORT */
595 
596 
597 #undef MHD_get_fdset
598 
628 int
629 MHD_get_fdset (struct MHD_Daemon *daemon,
630  fd_set *read_fd_set,
631  fd_set *write_fd_set,
632  fd_set *except_fd_set,
633  MHD_socket *max_fd)
634 {
635  return MHD_get_fdset2 (daemon,
636  read_fd_set,
637  write_fd_set,
638  except_fd_set,
639  max_fd,
641 }
642 
643 
644 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
645 
657 static bool
658 urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
659  fd_set *rs,
660  fd_set *ws,
661  fd_set *es,
662  MHD_socket *max_fd,
663  unsigned int fd_setsize)
664 {
665  const MHD_socket conn_sckt = urh->connection->socket_fd;
666  const MHD_socket mhd_sckt = urh->mhd.socket;
667  bool res = true;
668 
669  /* Do not add to 'es' only if socket is closed
670  * or not used anymore. */
671  if (MHD_INVALID_SOCKET != conn_sckt)
672  {
673  if ( (urh->in_buffer_used < urh->in_buffer_size) &&
674  (! MHD_add_to_fd_set_ (conn_sckt,
675  rs,
676  max_fd,
677  fd_setsize)) )
678  res = false;
679  if ( (0 != urh->out_buffer_used) &&
680  (! MHD_add_to_fd_set_ (conn_sckt,
681  ws,
682  max_fd,
683  fd_setsize)) )
684  res = false;
685  /* Do not monitor again for errors if error was detected before as
686  * error state is remembered. */
687  if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
688  ((0 != urh->in_buffer_size) ||
689  (0 != urh->out_buffer_size) ||
690  (0 != urh->out_buffer_used)))
691  MHD_add_to_fd_set_ (conn_sckt,
692  es,
693  max_fd,
694  fd_setsize);
695  }
696  if (MHD_INVALID_SOCKET != mhd_sckt)
697  {
698  if ( (urh->out_buffer_used < urh->out_buffer_size) &&
699  (! MHD_add_to_fd_set_ (mhd_sckt,
700  rs,
701  max_fd,
702  fd_setsize)) )
703  res = false;
704  if ( (0 != urh->in_buffer_used) &&
705  (! MHD_add_to_fd_set_ (mhd_sckt,
706  ws,
707  max_fd,
708  fd_setsize)) )
709  res = false;
710  /* Do not monitor again for errors if error was detected before as
711  * error state is remembered. */
712  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
713  ((0 != urh->out_buffer_size) ||
714  (0 != urh->in_buffer_size) ||
715  (0 != urh->in_buffer_used)))
716  MHD_add_to_fd_set_ (mhd_sckt,
717  es,
718  max_fd,
719  fd_setsize);
720  }
721 
722  return res;
723 }
724 
725 
735 static void
736 urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
737  const fd_set *rs,
738  const fd_set *ws,
739  const fd_set *es)
740 {
741  const MHD_socket conn_sckt = urh->connection->socket_fd;
742  const MHD_socket mhd_sckt = urh->mhd.socket;
743 
744  /* Reset read/write ready, preserve error state. */
747 
748  if (MHD_INVALID_SOCKET != conn_sckt)
749  {
750  if (FD_ISSET (conn_sckt, rs))
751  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
752  if (FD_ISSET (conn_sckt, ws))
753  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
754  if (FD_ISSET (conn_sckt, es))
755  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
756  }
757  if ((MHD_INVALID_SOCKET != mhd_sckt))
758  {
759  if (FD_ISSET (mhd_sckt, rs))
760  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
761  if (FD_ISSET (mhd_sckt, ws))
762  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
763  if (FD_ISSET (mhd_sckt, es))
764  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
765  }
766 }
767 
768 #ifdef HAVE_POLL
769 
778 static void
779 urh_update_pollfd(struct MHD_UpgradeResponseHandle *urh,
780  struct pollfd p[2])
781 {
782  p[0].events = 0;
783  p[1].events = 0;
784 
785  if (urh->in_buffer_used < urh->in_buffer_size)
786  p[0].events |= POLLIN;
787  if (0 != urh->out_buffer_used)
788  p[0].events |= POLLOUT;
789 
790  /* Do not monitor again for errors if error was detected before as
791  * error state is remembered. */
792  if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
793  ((0 != urh->in_buffer_size) ||
794  (0 != urh->out_buffer_size) ||
795  (0 != urh->out_buffer_used)))
796  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
797 
798  if (urh->out_buffer_used < urh->out_buffer_size)
799  p[1].events |= POLLIN;
800  if (0 != urh->in_buffer_used)
801  p[1].events |= POLLOUT;
802 
803  /* Do not monitor again for errors if error was detected before as
804  * error state is remembered. */
805  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
806  ((0 != urh->out_buffer_size) ||
807  (0 != urh->in_buffer_size) ||
808  (0 != urh->in_buffer_used)))
809  p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
810 }
811 
812 
819 static void
820 urh_to_pollfd(struct MHD_UpgradeResponseHandle *urh,
821  struct pollfd p[2])
822 {
823  p[0].fd = urh->connection->socket_fd;
824  p[1].fd = urh->mhd.socket;
825  urh_update_pollfd(urh, p);
826 }
827 
828 
834 static void
835 urh_from_pollfd(struct MHD_UpgradeResponseHandle *urh,
836  struct pollfd p[2])
837 {
838  /* Reset read/write ready, preserve error state. */
841 
842  if (0 != (p[0].revents & POLLIN))
843  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
844  if (0 != (p[0].revents & POLLOUT))
845  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
846  if (0 != (p[0].revents & POLLHUP))
848  if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
849  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
850  if (0 != (p[1].revents & POLLIN))
851  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
852  if (0 != (p[1].revents & POLLOUT))
853  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
854  if (0 != (p[1].revents & POLLHUP))
855  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
856  if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
858 }
859 #endif /* HAVE_POLL */
860 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
861 
862 
877 static int
879  fd_set *read_fd_set,
880  fd_set *write_fd_set,
881  fd_set *except_fd_set,
882  MHD_socket *max_fd,
883  unsigned int fd_setsize)
884 
885 {
886  struct MHD_Connection *pos;
887  struct MHD_Connection *posn;
888  int result = MHD_YES;
889  MHD_socket ls;
890 
891  if (daemon->shutdown)
892  return MHD_NO;
893 
894  ls = daemon->listen_fd;
895  if ( (MHD_INVALID_SOCKET != ls) &&
896  (! daemon->was_quiesced) &&
897  (! MHD_add_to_fd_set_ (ls,
898  read_fd_set,
899  max_fd,
900  fd_setsize)) )
901  result = MHD_NO;
902 
903  /* Add all sockets to 'except_fd_set' as well to watch for
904  * out-of-band data. However, ignore errors if INFO_READ
905  * or INFO_WRITE sockets will not fit 'except_fd_set'. */
906  /* Start from oldest connections. Make sense for W32 FDSETs. */
907  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
908  {
909  posn = pos->prev;
910 
911  switch (pos->event_loop_info)
912  {
914  if (! MHD_add_to_fd_set_ (pos->socket_fd,
915  read_fd_set,
916  max_fd,
917  fd_setsize))
918  result = MHD_NO;
919 #ifdef MHD_POSIX_SOCKETS
921  except_fd_set,
922  max_fd,
923  fd_setsize);
924 #endif /* MHD_POSIX_SOCKETS */
925  break;
927  if (! MHD_add_to_fd_set_ (pos->socket_fd,
928  write_fd_set,
929  max_fd,
930  fd_setsize))
931  result = MHD_NO;
932 #ifdef MHD_POSIX_SOCKETS
934  except_fd_set,
935  max_fd,
936  fd_setsize);
937 #endif /* MHD_POSIX_SOCKETS */
938  break;
940  if ( (NULL == except_fd_set) ||
942  except_fd_set,
943  max_fd,
944  fd_setsize))
945  result = MHD_NO;
946  break;
948  /* this should never happen */
949  break;
950  }
951  }
952 #ifdef MHD_WINSOCK_SOCKETS
953  /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
954  * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
955  * not be pushed out. */
956  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
957  {
958  posn = pos->prev;
960  except_fd_set,
961  max_fd,
962  fd_setsize);
963  }
964 #endif /* MHD_WINSOCK_SOCKETS */
965 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
966  {
967  struct MHD_UpgradeResponseHandle *urh;
968 
969  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
970  {
971  if (MHD_NO ==
972  urh_to_fdset (urh,
973  read_fd_set,
974  write_fd_set,
975  except_fd_set,
976  max_fd,
977  fd_setsize))
978  result = MHD_NO;
979  }
980  }
981 #endif
982 #if DEBUG_CONNECT
983 #ifdef HAVE_MESSAGES
984  if (NULL != max_fd)
985  MHD_DLOG (daemon,
986  _("Maximum socket in select set: %d\n"),
987  *max_fd);
988 #endif
989 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
990  return result;
991 }
992 
993 
1026 int
1027 MHD_get_fdset2 (struct MHD_Daemon *daemon,
1028  fd_set *read_fd_set,
1029  fd_set *write_fd_set,
1030  fd_set *except_fd_set,
1031  MHD_socket *max_fd,
1032  unsigned int fd_setsize)
1033 {
1034  fd_set es;
1035 
1036  if ( (NULL == daemon) ||
1037  (NULL == read_fd_set) ||
1038  (NULL == write_fd_set) ||
1039  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ||
1040  (0 != (daemon->options & MHD_USE_POLL)))
1041  return MHD_NO;
1042 
1043  if (NULL == except_fd_set)
1044  { /* Workaround to maintain backward compatibility. */
1045 #ifdef HAVE_MESSAGES
1046  MHD_DLOG (daemon,
1047  _("MHD_get_fdset2() called with except_fd_set "
1048  "set to NULL. Such behavior is unsupported.\n"));
1049 #endif
1050  FD_ZERO (&es);
1051  except_fd_set = &es;
1052  }
1053 
1054 #ifdef EPOLL_SUPPORT
1055  if (0 != (daemon->options & MHD_USE_EPOLL))
1056  {
1057  if (daemon->shutdown)
1058  return MHD_NO;
1059 
1060  /* we're in epoll mode, use the epoll FD as a stand-in for
1061  the entire event set */
1062 
1063  return MHD_add_to_fd_set_ (daemon->epoll_fd,
1064  read_fd_set,
1065  max_fd,
1066  fd_setsize) ? MHD_YES : MHD_NO;
1067  }
1068 #endif
1069 
1070  return internal_get_fdset2 (daemon,
1071  read_fd_set,
1072  write_fd_set,
1073  except_fd_set,
1074  max_fd,
1075  fd_setsize);
1076 }
1077 
1078 
1092 static int
1094  bool read_ready,
1095  bool write_ready,
1096  bool force_close)
1097 {
1098  int ret;
1099  bool states_info_processed = false;
1100  /* Fast track flag */
1101  bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1102 
1103 #ifdef HTTPS_SUPPORT
1104  if (con->tls_read_ready)
1105  read_ready = true;
1106 #endif /* HTTPS_SUPPORT */
1107  if (!force_close)
1108  {
1109  if ( (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) &&
1110  read_ready)
1111  {
1113  ret = MHD_connection_handle_idle (con);
1114  states_info_processed = true;
1115  }
1116  /* No need to check value of 'ret' here as closed connection
1117  * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1118  if ( (MHD_EVENT_LOOP_INFO_WRITE == con->event_loop_info) &&
1119  write_ready)
1120  {
1122  ret = MHD_connection_handle_idle (con);
1123  states_info_processed = true;
1124  }
1125  }
1126  else
1127  {
1128  MHD_connection_close_ (con,
1130  return MHD_connection_handle_idle (con);
1131  }
1132 
1133  if (!states_info_processed)
1134  { /* Connection is not read or write ready, but external conditions
1135  * may be changed and need to be processed. */
1136  ret = MHD_connection_handle_idle (con);
1137  }
1138  /* Fast track for fast connections. */
1139  /* If full request was read by single read_handler() invocation
1140  and headers were completely prepared by single MHD_connection_handle_idle()
1141  then try not to wait for next sockets polling and send response
1142  immediately.
1143  As writeability of socket was not checked and it may have
1144  some data pending in system buffers, use this optimization
1145  only for non-blocking sockets. */
1146  /* No need to check 'ret' as connection is always in
1147  * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1148  else if (on_fasttrack && con->sk_nonblck)
1149  {
1151  {
1153  /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1154  ret = MHD_connection_handle_idle (con);
1155  }
1156  /* If all headers were sent by single write_handler() and
1157  * response body is prepared by single MHD_connection_handle_idle()
1158  * call - continue. */
1159  if ((MHD_CONNECTION_NORMAL_BODY_READY == con->state) ||
1161  {
1163  ret = MHD_connection_handle_idle (con);
1164  }
1165  }
1166 
1167  /* All connection's data and states are processed for this turn.
1168  * If connection already has more data to be processed - use
1169  * zero timeout for next select()/poll(). */
1170  /* Thread-per-connection do not need global zero timeout as
1171  * connections are processed individually. */
1172  /* Note: no need to check for read buffer availability for
1173  * TLS read-ready connection in 'read info' state as connection
1174  * without space in read buffer will be market as 'info block'. */
1175  if ( (!con->daemon->data_already_pending) &&
1176  (0 == (con->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1177  {
1179  con->daemon->data_already_pending = true;
1180 #ifdef HTTPS_SUPPORT
1181  else if ( (con->tls_read_ready) &&
1183  con->daemon->data_already_pending = true;
1184 #endif /* HTTPS_SUPPORT */
1185  }
1186  return ret;
1187 }
1188 
1189 
1190 #ifdef UPGRADE_SUPPORT
1191 
1198 static void
1199 cleanup_upgraded_connection (struct MHD_Connection *connection)
1200 {
1201  struct MHD_UpgradeResponseHandle *urh = connection->urh;
1202 
1203  if (NULL == urh)
1204  return;
1205 #ifdef HTTPS_SUPPORT
1206  /* Signal remote client the end of TLS connection by
1207  * gracefully closing TLS session. */
1208  if (0 != (connection->daemon->options & MHD_USE_TLS))
1209  gnutls_bye (connection->tls_session,
1210  GNUTLS_SHUT_WR);
1211 
1212  if (MHD_INVALID_SOCKET != urh->mhd.socket)
1213  MHD_socket_close_chk_ (urh->mhd.socket);
1214 
1215  if (MHD_INVALID_SOCKET != urh->app.socket)
1216  MHD_socket_close_chk_ (urh->app.socket);
1217 #endif /* HTTPS_SUPPORT */
1218  connection->urh = NULL;
1219  free (urh);
1220 }
1221 #endif /* UPGRADE_SUPPORT */
1222 
1223 
1224 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1225 
1233 static void
1234 process_urh (struct MHD_UpgradeResponseHandle *urh)
1235 {
1236  /* Help compiler to optimize:
1237  * pointers to 'connection' and 'daemon' are not changed
1238  * during this processing, so no need to chain dereference
1239  * each time. */
1240  struct MHD_Connection * const connection = urh->connection;
1241  struct MHD_Daemon * const daemon = connection->daemon;
1242  /* Prevent data races: use same value of 'was_closed' throughout
1243  * this function. If 'was_closed' changed externally in the middle
1244  * of processing - it will be processed on next iteration. */
1245  bool was_closed;
1246  if (daemon->shutdown)
1247  {
1248  /* Daemon shutting down, application will not receive any more data. */
1249 #ifdef HAVE_MESSAGES
1250  if (! urh->was_closed)
1251  {
1252  MHD_DLOG (daemon,
1253  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1254  }
1255 #endif
1256  urh->was_closed = true;
1257  }
1258  was_closed = urh->was_closed;
1259  if (was_closed)
1260  {
1261  /* Application was closed connections: no more data
1262  * can be forwarded to application socket. */
1263  if (0 < urh->in_buffer_used)
1264  {
1265 #ifdef HAVE_MESSAGES
1266  MHD_DLOG (daemon,
1267  _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1268  " bytes of data received from remote side: application shut down socket\n"),
1269  (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used);
1270 #endif
1271 
1272  }
1273  /* If application signaled MHD about socket closure then
1274  * check for any pending data even if socket is not marked
1275  * as 'ready' (signal may arrive after poll()/select()).
1276  * Socketpair for forwarding is always in non-blocking mode
1277  * so no risk that recv() will block the thread. */
1278  if (0 != urh->out_buffer_size)
1279  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1280  /* Discard any data received form remote. */
1281  urh->in_buffer_used = 0;
1282  /* Do not try to push data to application. */
1283  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1284  /* Reading from remote client is not required anymore. */
1285  urh->in_buffer_size = 0;
1286  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1287  connection->tls_read_ready = false;
1288  }
1289 
1290  /* On some platforms (W32, possibly Darwin) failed send() (send() will always
1291  * fail after remote disconnect was detected) may discard data in system
1292  * buffers received by system but not yet read by recv().
1293  * So, before trying send() on any socket, recv() must be performed at first
1294  * otherwise last part of incoming data may be lost. */
1295 
1296  /* If disconnect or error was detected - try to read from socket
1297  * to dry data possibly pending is system buffers. */
1298  if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1299  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1300  if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1301  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1302 
1303  /*
1304  * handle reading from remote TLS client
1305  */
1306  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1307  (connection->tls_read_ready) ) &&
1308  (urh->in_buffer_used < urh->in_buffer_size) )
1309  {
1310  ssize_t res;
1311  size_t buf_size;
1312 
1313  buf_size = urh->in_buffer_size - urh->in_buffer_used;
1314  if (buf_size > SSIZE_MAX)
1315  buf_size = SSIZE_MAX;
1316 
1317  connection->tls_read_ready = false;
1318  res = gnutls_record_recv (connection->tls_session,
1319  &urh->in_buffer[urh->in_buffer_used],
1320  buf_size);
1321  if (0 >= res)
1322  {
1323  if (GNUTLS_E_INTERRUPTED != res)
1324  {
1325  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1326  if (GNUTLS_E_AGAIN != res)
1327  {
1328  /* Unrecoverable error on socket was detected or
1329  * socket was disconnected/shut down. */
1330  /* Stop trying to read from this TLS socket. */
1331  urh->in_buffer_size = 0;
1332  }
1333  }
1334  }
1335  else /* 0 < res */
1336  {
1337  urh->in_buffer_used += res;
1338  if (buf_size > (size_t)res)
1339  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1340  else if (0 < gnutls_record_check_pending (connection->tls_session))
1341  connection->tls_read_ready = true;
1342  }
1343  if (MHD_EPOLL_STATE_ERROR ==
1344  ((MHD_EPOLL_STATE_ERROR | MHD_EPOLL_STATE_READ_READY) & urh->app.celi))
1345  {
1346  /* Unrecoverable error on socket was detected and all
1347  * pending data was read from system buffers. */
1348  /* Stop trying to read from this TLS socket. */
1349  urh->in_buffer_size = 0;
1350  }
1351  }
1352 
1353  /*
1354  * handle reading from application
1355  */
1356  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1357  (urh->out_buffer_used < urh->out_buffer_size) )
1358  {
1359  ssize_t res;
1360  size_t buf_size;
1361 
1362  buf_size = urh->out_buffer_size - urh->out_buffer_used;
1363  if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1364  buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1365 
1366  res = MHD_recv_ (urh->mhd.socket,
1367  &urh->out_buffer[urh->out_buffer_used],
1368  buf_size);
1369  if (0 >= res)
1370  {
1371  const int err = MHD_socket_get_error_ ();
1372  if ((0 == res) ||
1373  ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1375  {
1376  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1377  if ((0 == res) ||
1378  (was_closed) ||
1379  (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1380  (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1381  {
1382  /* Socket disconnect/shutdown was detected;
1383  * Application signaled about closure of 'upgraded' socket;
1384  * or persistent / unrecoverable error. */
1385  /* Do not try to pull more data from application. */
1386  urh->out_buffer_size = 0;
1387  }
1388  }
1389  }
1390  else /* 0 < res */
1391  {
1392  urh->out_buffer_used += res;
1393  if (buf_size > (size_t)res)
1394  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1395  }
1396  if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1397  ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1398  (was_closed) ) )
1399  {
1400  /* Unrecoverable error on socket was detected and all
1401  * pending data was read from system buffers. */
1402  /* Do not try to pull more data from application. */
1403  urh->out_buffer_size = 0;
1404  }
1405  }
1406 
1407  /*
1408  * handle writing to remote HTTPS client
1409  */
1410  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1411  (urh->out_buffer_used > 0) )
1412  {
1413  ssize_t res;
1414  size_t data_size;
1415 
1416  data_size = urh->out_buffer_used;
1417  if (data_size > SSIZE_MAX)
1418  data_size = SSIZE_MAX;
1419 
1420  res = gnutls_record_send (connection->tls_session,
1421  urh->out_buffer,
1422  data_size);
1423  if (0 >= res)
1424  {
1425  if (GNUTLS_E_INTERRUPTED != res)
1426  {
1427  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1428  if (GNUTLS_E_INTERRUPTED != res)
1429  {
1430  /* TLS connection shut down or
1431  * persistent / unrecoverable error. */
1432 #ifdef HAVE_MESSAGES
1433  MHD_DLOG (daemon,
1434  _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1435  " bytes of data received from application: %s\n"),
1436  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1437  gnutls_strerror(res));
1438 #endif
1439  /* Discard any data unsent to remote. */
1440  urh->out_buffer_used = 0;
1441  /* Do not try to pull more data from application. */
1442  urh->out_buffer_size = 0;
1443  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1444  }
1445  }
1446  }
1447  else /* 0 < res */
1448  {
1449  const size_t next_out_buffer_used = urh->out_buffer_used - res;
1450  if (0 != next_out_buffer_used)
1451  {
1452  memmove (urh->out_buffer,
1453  &urh->out_buffer[res],
1454  next_out_buffer_used);
1455  if (data_size > (size_t)res)
1456  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1457  }
1458  urh->out_buffer_used = next_out_buffer_used;
1459  }
1460  if ( (0 == urh->out_buffer_used) &&
1461  (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1462  {
1463  /* Unrecoverable error on socket was detected and all
1464  * pending data was sent to remote. */
1465  /* Do not try to send to remote anymore. */
1466  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1467  /* Do not try to pull more data from application. */
1468  urh->out_buffer_size = 0;
1469  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1470  }
1471  }
1472 
1473  /*
1474  * handle writing to application
1475  */
1476  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1477  (urh->in_buffer_used > 0) )
1478  {
1479  ssize_t res;
1480  size_t data_size;
1481 
1482  data_size = urh->in_buffer_used;
1483  if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1484  data_size = MHD_SCKT_SEND_MAX_SIZE_;
1485 
1486  res = MHD_send_ (urh->mhd.socket,
1487  urh->in_buffer,
1488  data_size);
1489  if (0 >= res)
1490  {
1491  const int err = MHD_socket_get_error_ ();
1492  if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1494  {
1495  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1496  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1497  {
1498  /* Socketpair connection shut down or
1499  * persistent / unrecoverable error. */
1500 #ifdef HAVE_MESSAGES
1501  MHD_DLOG (daemon,
1502  _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1503  " bytes of data received from remote side: %s\n"),
1504  (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1505  MHD_socket_strerr_ (err));
1506 #endif
1507  /* Discard any data received form remote. */
1508  urh->in_buffer_used = 0;
1509  /* Reading from remote client is not required anymore. */
1510  urh->in_buffer_size = 0;
1511  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1512  connection->tls_read_ready = false;
1513  }
1514  }
1515  }
1516  else /* 0 < res */
1517  {
1518  const size_t next_in_buffer_used = urh->in_buffer_used - res;
1519  if (0 != next_in_buffer_used)
1520  {
1521  memmove (urh->in_buffer,
1522  &urh->in_buffer[res],
1523  next_in_buffer_used);
1524  if (data_size > (size_t)res)
1525  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1526  }
1527  urh->in_buffer_used = next_in_buffer_used;
1528  }
1529  if ( (0 == urh->in_buffer_used) &&
1530  (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1531  {
1532  /* Do not try to push data to application. */
1533  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1534  /* Reading from remote client is not required anymore. */
1535  urh->in_buffer_size = 0;
1536  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1537  connection->tls_read_ready = false;
1538  }
1539  }
1540 
1541  /* Check whether data is present in TLS buffers
1542  * and incoming forward buffer have some space. */
1543  if ( (connection->tls_read_ready) &&
1544  (urh->in_buffer_used < urh->in_buffer_size) &&
1545  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1546  daemon->data_already_pending = true;
1547 
1548  if ( (daemon->shutdown) &&
1549  ( (0 != urh->out_buffer_size) ||
1550  (0 != urh->out_buffer_used) ) )
1551  {
1552  /* Daemon shutting down, discard any remaining forward data. */
1553 #ifdef HAVE_MESSAGES
1554  if (0 < urh->out_buffer_used)
1555  MHD_DLOG (daemon,
1556  _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1557  " bytes of data received from application: daemon shut down\n"),
1558  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
1559 #endif
1560  /* Discard any data unsent to remote. */
1561  urh->out_buffer_used = 0;
1562  /* Do not try to sent to remote anymore. */
1563  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1564  /* Do not try to pull more data from application. */
1565  urh->out_buffer_size = 0;
1566  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1567  }
1568 }
1569 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1570 
1571 
1572 #ifdef UPGRADE_SUPPORT
1573 
1581 static void
1582 thread_main_connection_upgrade (struct MHD_Connection *con)
1583 {
1584 #ifdef HTTPS_SUPPORT
1585  struct MHD_UpgradeResponseHandle *urh = con->urh;
1586  struct MHD_Daemon *daemon = con->daemon;
1587 
1588  /* Here, we need to bi-directionally forward
1589  until the application tells us that it is done
1590  with the socket; */
1591  if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1592  (0 == (daemon->options & MHD_USE_POLL)))
1593  {
1594  while ( (0 != urh->in_buffer_size) ||
1595  (0 != urh->out_buffer_size) ||
1596  (0 != urh->in_buffer_used) ||
1597  (0 != urh->out_buffer_used) )
1598  {
1599  /* use select */
1600  fd_set rs;
1601  fd_set ws;
1602  fd_set es;
1603  MHD_socket max_fd;
1604  int num_ready;
1605  bool result;
1606 
1607  FD_ZERO (&rs);
1608  FD_ZERO (&ws);
1609  FD_ZERO (&es);
1610  max_fd = MHD_INVALID_SOCKET;
1611  result = urh_to_fdset (urh,
1612  &rs,
1613  &ws,
1614  &es,
1615  &max_fd,
1616  FD_SETSIZE);
1617  if (! result)
1618  {
1619 #ifdef HAVE_MESSAGES
1620  MHD_DLOG (con->daemon,
1621  _("Error preparing select\n"));
1622 #endif
1623  break;
1624  }
1625  /* FIXME: does this check really needed? */
1626  if (MHD_INVALID_SOCKET != max_fd)
1627  {
1628  struct timeval* tvp;
1629  struct timeval tv;
1630  if ( (con->tls_read_ready) &&
1631  (urh->in_buffer_used < urh->in_buffer_size))
1632  { /* No need to wait if incoming data is already pending in TLS buffers. */
1633  tv.tv_sec = 0;
1634  tv.tv_usec = 0;
1635  tvp = &tv;
1636  }
1637  else
1638  tvp = NULL;
1639  num_ready = MHD_SYS_select_ (max_fd + 1,
1640  &rs,
1641  &ws,
1642  &es,
1643  tvp);
1644  }
1645  else
1646  num_ready = 0;
1647  if (num_ready < 0)
1648  {
1649  const int err = MHD_socket_get_error_();
1650 
1651  if (MHD_SCKT_ERR_IS_EINTR_(err))
1652  continue;
1653 #ifdef HAVE_MESSAGES
1654  MHD_DLOG (con->daemon,
1655  _("Error during select (%d): `%s'\n"),
1656  err,
1657  MHD_socket_strerr_ (err));
1658 #endif
1659  break;
1660  }
1661  urh_from_fdset (urh,
1662  &rs,
1663  &ws,
1664  &es);
1665  process_urh (urh);
1666  }
1667  }
1668 #ifdef HAVE_POLL
1669  else if (0 != (daemon->options & MHD_USE_TLS))
1670  {
1671  /* use poll() */
1672  struct pollfd p[2];
1673  memset (p,
1674  0,
1675  sizeof (p));
1676  p[0].fd = urh->connection->socket_fd;
1677  p[1].fd = urh->mhd.socket;
1678 
1679  while ( (0 != urh->in_buffer_size) ||
1680  (0 != urh->out_buffer_size) ||
1681  (0 != urh->in_buffer_used) ||
1682  (0 != urh->out_buffer_used) )
1683  {
1684  int timeout;
1685 
1686  urh_update_pollfd(urh, p);
1687 
1688  if ( (con->tls_read_ready) &&
1689  (urh->in_buffer_used < urh->in_buffer_size))
1690  timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1691  else
1692  timeout = -1;
1693 
1694  if (MHD_sys_poll_ (p,
1695  2,
1696  timeout) < 0)
1697  {
1698  const int err = MHD_socket_get_error_ ();
1699 
1700  if (MHD_SCKT_ERR_IS_EINTR_ (err))
1701  continue;
1702 #ifdef HAVE_MESSAGES
1703  MHD_DLOG (con->daemon,
1704  _("Error during poll: `%s'\n"),
1705  MHD_socket_strerr_ (err));
1706 #endif
1707  break;
1708  }
1709  urh_from_pollfd(urh, p);
1710  process_urh (urh);
1711  }
1712  }
1713  /* end POLL */
1714 #endif
1715  /* end HTTPS */
1716 #endif /* HTTPS_SUPPORT */
1717  /* TLS forwarding was finished. Cleanup socketpair. */
1719  /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1720  * in connection thread for a little while. */
1721 }
1722 #endif /* UPGRADE_SUPPORT */
1723 
1724 
1732 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1734 {
1735  struct MHD_Connection *con = data;
1736  struct MHD_Daemon *daemon = con->daemon;
1737  int num_ready;
1738  fd_set rs;
1739  fd_set ws;
1740  fd_set es;
1741  MHD_socket maxsock;
1742  struct timeval tv;
1743  struct timeval *tvp;
1744  time_t now;
1745 #if WINDOWS
1746 #ifdef HAVE_POLL
1747  int extra_slot;
1748 #endif /* HAVE_POLL */
1749 #define EXTRA_SLOTS 1
1750 #else /* !WINDOWS */
1751 #define EXTRA_SLOTS 0
1752 #endif /* !WINDOWS */
1753 #ifdef HAVE_POLL
1754  struct pollfd p[1 + EXTRA_SLOTS];
1755 #endif
1756 #undef EXTRA_SLOTS
1757 #ifdef HAVE_POLL
1758  const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1759 #else /* ! HAVE_POLL */
1760  const bool use_poll = 0;
1761 #endif /* ! HAVE_POLL */
1762  bool was_suspended = false;
1763  MHD_thread_init_(&(con->pid));
1764 
1765  while ( (! daemon->shutdown) &&
1766  (MHD_CONNECTION_CLOSED != con->state) )
1767  {
1768  const time_t timeout = daemon->connection_timeout;
1769 #ifdef UPGRADE_SUPPORT
1770  struct MHD_UpgradeResponseHandle * const urh = con->urh;
1771 #else /* ! UPGRADE_SUPPORT */
1772  static const void * const urh = NULL;
1773 #endif /* ! UPGRADE_SUPPORT */
1774 
1775  if ( (con->suspended) &&
1776  (NULL == urh) )
1777  {
1778  /* Connection was suspended, wait for resume. */
1779  was_suspended = true;
1780  if (! use_poll)
1781  {
1782  FD_ZERO (&rs);
1783  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1784  &rs,
1785  NULL,
1786  FD_SETSIZE))
1787  {
1788  #ifdef HAVE_MESSAGES
1789  MHD_DLOG (con->daemon,
1790  _("Failed to add FD to fd_set\n"));
1791  #endif
1792  goto exit;
1793  }
1794  if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
1795  &rs,
1796  NULL,
1797  NULL,
1798  NULL))
1799  {
1800  const int err = MHD_socket_get_error_();
1801 
1802  if (MHD_SCKT_ERR_IS_EINTR_(err))
1803  continue;
1804 #ifdef HAVE_MESSAGES
1805  MHD_DLOG (con->daemon,
1806  _("Error during select (%d): `%s'\n"),
1807  err,
1808  MHD_socket_strerr_ (err));
1809 #endif
1810  break;
1811  }
1812  }
1813 #ifdef HAVE_POLL
1814  else /* use_poll */
1815  {
1816  p[0].events = POLLIN;
1817  p[0].fd = MHD_itc_r_fd_ (daemon->itc);
1818  p[0].revents = 0;
1819  if (0 > MHD_sys_poll_ (p,
1820  1,
1821  -1))
1822  {
1824  continue;
1825 #ifdef HAVE_MESSAGES
1826  MHD_DLOG (con->daemon,
1827  _("Error during poll: `%s'\n"),
1829 #endif
1830  break;
1831  }
1832  }
1833 #endif /* HAVE_POLL */
1834  MHD_itc_clear_ (daemon->itc);
1835  continue; /* Check again for resume. */
1836  } /* End of "suspended" branch. */
1837 
1838  if (was_suspended)
1839  {
1840  MHD_update_last_activity_ (con); /* Reset timeout timer. */
1841  /* Process response queued during suspend and update states. */
1843  was_suspended = false;
1844  }
1845 
1846  tvp = NULL;
1847 
1849 #ifdef HTTPS_SUPPORT
1850  || ( (con->tls_read_ready) &&
1852 #endif /* HTTPS_SUPPORT */
1853  )
1854  {
1855  /* do not block: more data may be inside of TLS buffers waiting or
1856  * application must provide response data */
1857  tv.tv_sec = 0;
1858  tv.tv_usec = 0;
1859  tvp = &tv;
1860  }
1861  if ( (NULL == tvp) &&
1862  (timeout > 0) )
1863  {
1864  now = MHD_monotonic_sec_counter();
1865  if (now - con->last_activity > timeout)
1866  tv.tv_sec = 0;
1867  else
1868  {
1869  const time_t seconds_left = timeout - (now - con->last_activity);
1870 #if !defined(_WIN32) || defined(__CYGWIN__)
1871  tv.tv_sec = seconds_left;
1872 #else /* _WIN32 && !__CYGWIN__ */
1873  if (seconds_left > TIMEVAL_TV_SEC_MAX)
1874  tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1875  else
1876  tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
1877 #endif /* _WIN32 && ! __CYGWIN__ */
1878  }
1879  tv.tv_usec = 0;
1880  tvp = &tv;
1881  }
1882  if (! use_poll)
1883  {
1884  /* use select */
1885  bool err_state = false;
1886 
1887  FD_ZERO (&rs);
1888  FD_ZERO (&ws);
1889  FD_ZERO (&es);
1890  maxsock = MHD_INVALID_SOCKET;
1891  switch (con->event_loop_info)
1892  {
1894  if (! MHD_add_to_fd_set_ (con->socket_fd,
1895  &rs,
1896  &maxsock,
1897  FD_SETSIZE))
1898  err_state = true;
1899  break;
1901  if (! MHD_add_to_fd_set_ (con->socket_fd,
1902  &ws,
1903  &maxsock,
1904  FD_SETSIZE))
1905  err_state = true;
1906  break;
1908  if (! MHD_add_to_fd_set_ (con->socket_fd,
1909  &es,
1910  &maxsock,
1911  FD_SETSIZE))
1912  err_state = true;
1913  break;
1915  /* how did we get here!? */
1916  goto exit;
1917  }
1918 #if WINDOWS
1919  if (MHD_ITC_IS_VALID_(daemon->itc) )
1920  {
1921  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1922  &rs,
1923  &maxsock,
1924  FD_SETSIZE))
1925  err_state = 1;
1926  }
1927 #endif
1928  if (err_state)
1929  {
1930 #ifdef HAVE_MESSAGES
1931  MHD_DLOG (con->daemon,
1932  _("Failed to add FD to fd_set\n"));
1933 #endif
1934  goto exit;
1935  }
1936 
1937  num_ready = MHD_SYS_select_ (maxsock + 1,
1938  &rs,
1939  &ws,
1940  NULL,
1941  tvp);
1942  if (num_ready < 0)
1943  {
1944  const int err = MHD_socket_get_error_();
1945 
1946  if (MHD_SCKT_ERR_IS_EINTR_(err))
1947  continue;
1948 #ifdef HAVE_MESSAGES
1949  MHD_DLOG (con->daemon,
1950  _("Error during select (%d): `%s'\n"),
1951  err,
1952  MHD_socket_strerr_ (err));
1953 #endif
1954  break;
1955  }
1956 #if WINDOWS
1957  /* Clear ITC before other processing so additional
1958  * signals will trigger select() again */
1959  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
1960  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
1961  &rs)) )
1962  MHD_itc_clear_ (daemon->itc);
1963 #endif
1964  if (MHD_NO ==
1965  call_handlers (con,
1966  FD_ISSET (con->socket_fd,
1967  &rs),
1968  FD_ISSET (con->socket_fd,
1969  &ws),
1970  FD_ISSET (con->socket_fd,
1971  &es)) )
1972  goto exit;
1973  }
1974 #ifdef HAVE_POLL
1975  else
1976  {
1977  /* use poll */
1978  memset (&p,
1979  0,
1980  sizeof (p));
1981  p[0].fd = con->socket_fd;
1982  switch (con->event_loop_info)
1983  {
1985  p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
1986  break;
1988  p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
1989  break;
1991  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
1992  break;
1994  /* how did we get here!? */
1995  goto exit;
1996  }
1997 #if WINDOWS
1998  extra_slot = 0;
1999  if (MHD_ITC_IS_VALID_(daemon->itc))
2000  {
2001  p[1].events |= POLLIN;
2002  p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2003  p[1].revents = 0;
2004  extra_slot = 1;
2005  }
2006 #endif
2007  if (MHD_sys_poll_ (p,
2008 #if WINDOWS
2009  1 + extra_slot,
2010 #else
2011  1,
2012 #endif
2013  (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2014  {
2016  continue;
2017 #ifdef HAVE_MESSAGES
2018  MHD_DLOG (con->daemon,
2019  _("Error during poll: `%s'\n"),
2021 #endif
2022  break;
2023  }
2024 #if WINDOWS
2025  /* Clear ITC before other processing so additional
2026  * signals will trigger poll() again */
2027  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2028  (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2029  MHD_itc_clear_ (daemon->itc);
2030 #endif
2031  if (MHD_NO ==
2032  call_handlers (con,
2033  0 != (p[0].revents & POLLIN),
2034  0 != (p[0].revents & POLLOUT),
2035  0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
2036  goto exit;
2037  }
2038 #endif
2039 #ifdef UPGRADE_SUPPORT
2040  if (MHD_CONNECTION_UPGRADE == con->state)
2041  {
2042  /* Normal HTTP processing is finished,
2043  * notify application. */
2044  if ( (NULL != daemon->notify_completed) &&
2045  (con->client_aware) )
2046  daemon->notify_completed (daemon->notify_completed_cls,
2047  con,
2048  &con->client_context,
2050  con->client_aware = false;
2051 
2052  thread_main_connection_upgrade (con);
2053  /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2054 
2055  /* "Upgraded" data will not be used in this thread from this point. */
2056  con->urh->clean_ready = true;
2057  /* If 'urh->was_closed' set to true, connection will be
2058  * moved immediately to cleanup list. Otherwise connection
2059  * will stay in suspended list until 'urh' will be marked
2060  * with 'was_closed' by application. */
2061  MHD_resume_connection(con);
2062 
2063  /* skip usual clean up */
2064  return (MHD_THRD_RTRN_TYPE_) 0;
2065  }
2066 #endif /* UPGRADE_SUPPORT */
2067  }
2068  if (MHD_CONNECTION_IN_CLEANUP != con->state)
2069  {
2070 #if DEBUG_CLOSE
2071 #ifdef HAVE_MESSAGES
2072  MHD_DLOG (con->daemon,
2073  _("Processing thread terminating. Closing connection\n"));
2074 #endif
2075 #endif
2076  if (MHD_CONNECTION_CLOSED != con->state)
2077  MHD_connection_close_ (con,
2078  (daemon->shutdown) ?
2082  }
2083 exit:
2084  if (NULL != con->response)
2085  {
2087  con->response = NULL;
2088  }
2089 
2090  if (MHD_INVALID_SOCKET != con->socket_fd)
2091  {
2092  shutdown (con->socket_fd,
2093  SHUT_WR);
2094  /* 'socket_fd' can be used in other thread to signal shutdown.
2095  * To avoid data races, do not close socket here. Daemon will
2096  * use more connections only after cleanup anyway. */
2097  }
2098  return (MHD_THRD_RTRN_TYPE_) 0;
2099 }
2100 
2101 
2109 static void
2110 MHD_cleanup_connections (struct MHD_Daemon *daemon);
2111 
2112 #if defined(HTTPS_SUPPORT)
2113 #if !defined(MHD_WINSOCK_SOCKETS) && !defined(MHD_socket_nosignal_) && \
2114  (GNUTLS_VERSION_NUMBER+0 < 0x030402) && defined(MSG_NOSIGNAL)
2115 
2120 #define MHD_TLSLIB_NEED_PUSH_FUNC 1
2121 #endif /* !MHD_WINSOCK_SOCKETS && !MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) */
2122 
2123 #ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2124 
2128 static ssize_t
2129 MHD_tls_push_func_(gnutls_transport_ptr_t trnsp,
2130  const void *data,
2131  size_t data_size)
2132 {
2133 #if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2134  if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2135  data_size = MHD_SCKT_SEND_MAX_SIZE_;
2136 #endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2137  return MHD_send_ ((MHD_socket)(intptr_t)(trnsp), data, data_size);
2138 }
2139 #endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2140 #endif /* HTTPS_SUPPORT */
2141 
2167 static int
2169  MHD_socket client_socket,
2170  const struct sockaddr *addr,
2171  socklen_t addrlen,
2172  bool external_add,
2173  bool non_blck)
2174 {
2175  struct MHD_Connection *connection;
2176  unsigned int i;
2177  int eno = 0;
2178 
2179  /* Direct add to master daemon could happen only with "external" add mode. */
2180  mhd_assert ((NULL == daemon->worker_pool) || (external_add));
2181  if ((external_add) && (NULL != daemon->worker_pool))
2182  {
2183  /* have a pool, try to find a pool with capacity; we use the
2184  socket as the initial offset into the pool for load
2185  balancing */
2186  for (i = 0; i < daemon->worker_pool_size; ++i)
2187  {
2188  struct MHD_Daemon * const worker =
2189  &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
2190  if (worker->connections < worker->connection_limit)
2191  return internal_add_connection (worker,
2192  client_socket,
2193  addr,
2194  addrlen,
2195  true,
2196  non_blck);
2197  }
2198  /* all pools are at their connection limit, must refuse */
2199  MHD_socket_close_chk_ (client_socket);
2200 #if ENFILE
2201  errno = ENFILE;
2202 #endif
2203  return MHD_NO;
2204  }
2205 
2206  if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
2207  NULL)) &&
2208  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
2209  {
2210 #ifdef HAVE_MESSAGES
2211  MHD_DLOG (daemon,
2212  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2213  (int) client_socket,
2214  (int) FD_SETSIZE);
2215 #endif
2216  MHD_socket_close_chk_ (client_socket);
2217 #if EINVAL
2218  errno = EINVAL;
2219 #endif
2220  return MHD_NO;
2221  }
2222 
2223 #ifdef MHD_socket_nosignal_
2224  if (! MHD_socket_nosignal_ (client_socket))
2225  {
2226 #ifdef HAVE_MESSAGES
2227  MHD_DLOG (daemon,
2228  _("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2230 #endif
2231 #ifndef MSG_NOSIGNAL
2232  /* Cannot use socket as it can produce SIGPIPE. */
2233 #ifdef ENOTSOCK
2234  errno = ENOTSOCK;
2235 #endif /* ENOTSOCK */
2236  return MHD_NO;
2237 #endif /* ! MSG_NOSIGNAL */
2238  }
2239 #endif /* MHD_socket_nosignal_ */
2240 
2241 
2242 #ifdef HAVE_MESSAGES
2243 #if DEBUG_CONNECT
2244  MHD_DLOG (daemon,
2245  _("Accepted connection on socket %d\n"),
2246  client_socket);
2247 #endif
2248 #endif
2249  if ( (daemon->connections == daemon->connection_limit) ||
2250  (MHD_NO == MHD_ip_limit_add (daemon,
2251  addr,
2252  addrlen)) )
2253  {
2254  /* above connection limit - reject */
2255 #ifdef HAVE_MESSAGES
2256  MHD_DLOG (daemon,
2257  _("Server reached connection limit. Closing inbound connection.\n"));
2258 #endif
2259  MHD_socket_close_chk_ (client_socket);
2260 #if ENFILE
2261  errno = ENFILE;
2262 #endif
2263  return MHD_NO;
2264  }
2265 
2266  /* apply connection acceptance policy if present */
2267  if ( (NULL != daemon->apc) &&
2268  (MHD_NO == daemon->apc (daemon->apc_cls,
2269  addr,
2270  addrlen)) )
2271  {
2272 #if DEBUG_CLOSE
2273 #ifdef HAVE_MESSAGES
2274  MHD_DLOG (daemon,
2275  _("Connection rejected by application. Closing connection.\n"));
2276 #endif
2277 #endif
2278  MHD_socket_close_chk_ (client_socket);
2279  MHD_ip_limit_del (daemon,
2280  addr,
2281  addrlen);
2282 #if EACCESS
2283  errno = EACCESS;
2284 #endif
2285  return MHD_NO;
2286  }
2287 
2288  if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2289  {
2290  eno = errno;
2291 #ifdef HAVE_MESSAGES
2292  MHD_DLOG (daemon,
2293  "Error allocating memory: %s\n",
2294  MHD_strerror_ (errno));
2295 #endif
2296  MHD_socket_close_chk_ (client_socket);
2297  MHD_ip_limit_del (daemon,
2298  addr,
2299  addrlen);
2300  errno = eno;
2301  return MHD_NO;
2302  }
2303  connection->pool = MHD_pool_create (daemon->pool_size);
2304  if (NULL == connection->pool)
2305  {
2306 #ifdef HAVE_MESSAGES
2307  MHD_DLOG (daemon,
2308  _("Error allocating memory: %s\n"),
2309  MHD_strerror_ (errno));
2310 #endif
2311  MHD_socket_close_chk_ (client_socket);
2312  MHD_ip_limit_del (daemon,
2313  addr,
2314  addrlen);
2315  free (connection);
2316 #if ENOMEM
2317  errno = ENOMEM;
2318 #endif
2319  return MHD_NO;
2320  }
2321 
2322  connection->connection_timeout = daemon->connection_timeout;
2323  if (NULL == (connection->addr = malloc (addrlen)))
2324  {
2325  eno = errno;
2326 #ifdef HAVE_MESSAGES
2327  MHD_DLOG (daemon,
2328  _("Error allocating memory: %s\n"),
2329  MHD_strerror_ (errno));
2330 #endif
2331  MHD_socket_close_chk_ (client_socket);
2332  MHD_ip_limit_del (daemon,
2333  addr,
2334  addrlen);
2335  MHD_pool_destroy (connection->pool);
2336  free (connection);
2337  errno = eno;
2338  return MHD_NO;
2339  }
2340  memcpy (connection->addr,
2341  addr,
2342  addrlen);
2343  connection->addr_len = addrlen;
2344  connection->socket_fd = client_socket;
2345  connection->sk_nonblck = non_blck;
2346  connection->daemon = daemon;
2347  connection->last_activity = MHD_monotonic_sec_counter();
2348 
2349  if (0 == (daemon->options & MHD_USE_TLS))
2350  {
2351  /* set default connection handlers */
2352  MHD_set_http_callbacks_ (connection);
2353  }
2354  else
2355  {
2356 #ifdef HTTPS_SUPPORT
2357  connection->tls_state = MHD_TLS_CONN_INIT;
2358  MHD_set_https_callbacks (connection);
2359  gnutls_init (&connection->tls_session,
2360  GNUTLS_SERVER
2361 #if (GNUTLS_VERSION_NUMBER+0 >= 0x030402)
2362  | GNUTLS_NO_SIGNAL
2363 #endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2364 #if GNUTLS_VERSION_MAJOR >= 3
2365  | GNUTLS_NONBLOCK
2366 #endif /* GNUTLS_VERSION_MAJOR >= 3*/
2367  );
2368  gnutls_priority_set (connection->tls_session,
2369  daemon->priority_cache);
2370  switch (daemon->cred_type)
2371  {
2372  /* set needed credentials for certificate authentication. */
2373  case GNUTLS_CRD_CERTIFICATE:
2374  gnutls_credentials_set (connection->tls_session,
2375  GNUTLS_CRD_CERTIFICATE,
2376  daemon->x509_cred);
2377  break;
2378  default:
2379 #ifdef HAVE_MESSAGES
2380  MHD_DLOG (connection->daemon,
2381  _("Failed to setup TLS credentials: unknown credential type %d\n"),
2382  daemon->cred_type);
2383 #endif
2384  MHD_socket_close_chk_ (client_socket);
2385  MHD_ip_limit_del (daemon,
2386  addr,
2387  addrlen);
2388  free (connection->addr);
2389  free (connection);
2390  MHD_PANIC (_("Unknown credential type"));
2391 #if EINVAL
2392  errno = EINVAL;
2393 #endif
2394  return MHD_NO;
2395  }
2396 #if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64)
2397  gnutls_transport_set_int (connection->tls_session, (int)(client_socket));
2398 #else /* GnuTLS before 3.1.9 or Win x64 */
2399  gnutls_transport_set_ptr (connection->tls_session, (gnutls_transport_ptr_t)(intptr_t)(client_socket));
2400 #endif /* GnuTLS before 3.1.9 */
2401 #ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2402  gnutls_transport_set_push_function (connection->tls_session, MHD_tls_push_func_);
2403 #endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2404  if (daemon->https_mem_trust)
2405  gnutls_certificate_server_set_request (connection->tls_session,
2406  GNUTLS_CERT_REQUEST);
2407 #else /* ! HTTPS_SUPPORT */
2408  eno = EINVAL;
2409  goto cleanup;
2410 #endif /* ! HTTPS_SUPPORT */
2411  }
2412 
2413 
2415  /* Firm check under lock. */
2416  if (daemon->connections >= daemon->connection_limit)
2417  {
2419  /* above connection limit - reject */
2420 #ifdef HAVE_MESSAGES
2421  MHD_DLOG (daemon,
2422  _("Server reached connection limit. Closing inbound connection.\n"));
2423 #endif
2424 #if ENFILE
2425  eno = ENFILE;
2426 #endif
2427  goto cleanup;
2428  }
2429  daemon->connections++;
2430  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2431  {
2433  daemon->normal_timeout_tail,
2434  connection);
2435  }
2436  DLL_insert (daemon->connections_head,
2437  daemon->connections_tail,
2438  connection);
2440 
2441  if (NULL != daemon->notify_connection)
2442  daemon->notify_connection (daemon->notify_connection_cls,
2443  connection,
2444  &connection->socket_context,
2446 
2447  /* attempt to create handler thread */
2448  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2449  {
2450  if (! MHD_create_named_thread_ (&connection->pid,
2451  "MHD-connection",
2452  daemon->thread_stack_size,
2454  connection))
2455  {
2456  eno = errno;
2457 #ifdef HAVE_MESSAGES
2458  MHD_DLOG (daemon,
2459  "Failed to create a thread: %s\n",
2460  MHD_strerror_ (eno));
2461 #endif
2462  goto cleanup;
2463  }
2464  }
2465  else
2466  connection->pid = daemon->pid;
2467 #ifdef EPOLL_SUPPORT
2468  if (0 != (daemon->options & MHD_USE_EPOLL))
2469  {
2470  if ((0 == (daemon->options & MHD_USE_TURBO)) || (external_add))
2471  { /* Do not manipulate EReady DL-list in 'external_add' mode. */
2472  struct epoll_event event;
2473 
2474  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2475  event.data.ptr = connection;
2476  if (0 != epoll_ctl (daemon->epoll_fd,
2477  EPOLL_CTL_ADD,
2478  client_socket,
2479  &event))
2480  {
2481  eno = errno;
2482 #ifdef HAVE_MESSAGES
2483  MHD_DLOG (daemon,
2484  _("Call to epoll_ctl failed: %s\n"),
2486 #endif
2487  goto cleanup;
2488  }
2489  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2490  }
2491  else
2492  {
2493  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
2495  EDLL_insert (daemon->eready_head,
2496  daemon->eready_tail,
2497  connection);
2498  }
2499  }
2500  else /* This 'else' is combined with next 'if'. */
2501 #endif
2502  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2503  (external_add) &&
2504  (MHD_ITC_IS_VALID_(daemon->itc)) &&
2505  (! MHD_itc_activate_ (daemon->itc, "n")) )
2506  {
2507 #ifdef HAVE_MESSAGES
2508  MHD_DLOG (daemon,
2509  _("Failed to signal new connection via inter-thread communication channel."));
2510 #endif
2511  }
2512  return MHD_YES;
2513  cleanup:
2514  if (NULL != daemon->notify_connection)
2515  daemon->notify_connection (daemon->notify_connection_cls,
2516  connection,
2517  &connection->socket_context,
2519 #ifdef HTTPS_SUPPORT
2520  if (NULL != connection->tls_session)
2521  gnutls_deinit (connection->tls_session);
2522 #endif /* HTTPS_SUPPORT */
2523  MHD_socket_close_chk_ (client_socket);
2524  MHD_ip_limit_del (daemon,
2525  addr,
2526  addrlen);
2528  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2529  {
2531  daemon->normal_timeout_tail,
2532  connection);
2533  }
2534  DLL_remove (daemon->connections_head,
2535  daemon->connections_tail,
2536  connection);
2538  MHD_pool_destroy (connection->pool);
2539  free (connection->addr);
2540  free (connection);
2541  if (0 != eno)
2542  errno = eno;
2543  else
2544  errno = EINVAL;
2545  return MHD_NO;
2546 }
2547 
2548 
2558 void
2560 {
2561  struct MHD_Daemon *daemon = connection->daemon;
2562 
2564  if (connection->resuming)
2565  {
2566  /* suspending again while we didn't even complete resuming yet */
2567  connection->resuming = false;
2569  return;
2570  }
2571  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2572  {
2573  if (connection->connection_timeout == daemon->connection_timeout)
2575  daemon->normal_timeout_tail,
2576  connection);
2577  else
2579  daemon->manual_timeout_tail,
2580  connection);
2581  }
2582  DLL_remove (daemon->connections_head,
2583  daemon->connections_tail,
2584  connection);
2585  mhd_assert (! connection->suspended);
2588  connection);
2589  connection->suspended = true;
2590 #ifdef EPOLL_SUPPORT
2591  if (0 != (daemon->options & MHD_USE_EPOLL))
2592  {
2593  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2594  {
2595  EDLL_remove (daemon->eready_head,
2596  daemon->eready_tail,
2597  connection);
2598  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2599  }
2600  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2601  {
2602  if (0 != epoll_ctl (daemon->epoll_fd,
2603  EPOLL_CTL_DEL,
2604  connection->socket_fd,
2605  NULL))
2606  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
2607  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2608  }
2609  connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2610  }
2611 #endif
2613 }
2614 
2615 
2647 void
2649 {
2650  struct MHD_Daemon * const daemon = connection->daemon;
2651 
2652  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2653  MHD_PANIC (_("Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2654 #ifdef UPGRADE_SUPPORT
2655  if (NULL != connection->urh)
2656  {
2657 #ifdef HAVE_MESSAGES
2658  MHD_DLOG (daemon,
2659  _("Error: connection scheduled for \"upgrade\" cannot be suspended"));
2660 #endif /* HAVE_MESSAGES */
2661  return;
2662  }
2663 #endif /* UPGRADE_SUPPORT */
2664  internal_suspend_connection_ (connection);
2665 }
2666 
2667 
2676 void
2678 {
2679  struct MHD_Daemon *daemon;
2680 
2681  daemon = connection->daemon;
2682  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2683  MHD_PANIC (_("Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2685  connection->resuming = true;
2686  daemon->resuming = true;
2688  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2689  (! MHD_itc_activate_ (daemon->itc, "r")) )
2690  {
2691 #ifdef HAVE_MESSAGES
2692  MHD_DLOG (daemon,
2693  _("Failed to signal resume via inter-thread communication channel."));
2694 #endif
2695  }
2696 }
2697 
2698 
2708 static int
2710 {
2711  struct MHD_Connection *pos;
2712  struct MHD_Connection *prev = NULL;
2713  int ret;
2714  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
2716 
2717  ret = MHD_NO;
2719 
2720  if (daemon->resuming)
2721  {
2723  /* During shutdown check for resuming is forced. */
2724  mhd_assert((NULL != prev) || (daemon->shutdown));
2725  }
2726 
2727  daemon->resuming = false;
2728 
2729  while (NULL != (pos = prev))
2730  {
2731 #ifdef UPGRADE_SUPPORT
2732  struct MHD_UpgradeResponseHandle * const urh = pos->urh;
2733 #else /* ! UPGRADE_SUPPORT */
2734  static const void * const urh = NULL;
2735 #endif /* ! UPGRADE_SUPPORT */
2736  prev = pos->prev;
2737  if ( (! pos->resuming)
2738 #ifdef UPGRADE_SUPPORT
2739  || ( (NULL != urh) &&
2740  ( (! urh->was_closed) ||
2741  (! urh->clean_ready) ) )
2742 #endif /* UPGRADE_SUPPORT */
2743  )
2744  continue;
2745  ret = MHD_YES;
2746  mhd_assert (pos->suspended);
2749  pos);
2750  pos->suspended = false;
2751  if (NULL == urh)
2752  {
2753  DLL_insert (daemon->connections_head,
2754  daemon->connections_tail,
2755  pos);
2756  if (!used_thr_p_c)
2757  {
2758  /* Reset timeout timer on resume. */
2759  if (0 != pos->connection_timeout)
2761 
2762  if (pos->connection_timeout == daemon->connection_timeout)
2764  daemon->normal_timeout_tail,
2765  pos);
2766  else
2768  daemon->manual_timeout_tail,
2769  pos);
2770  }
2771 #ifdef EPOLL_SUPPORT
2772  if (0 != (daemon->options & MHD_USE_EPOLL))
2773  {
2774  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2775  MHD_PANIC ("Resumed connection was already in EREADY set\n");
2776  /* we always mark resumed connections as ready, as we
2777  might have missed the edge poll event during suspension */
2778  EDLL_insert (daemon->eready_head,
2779  daemon->eready_tail,
2780  pos);
2781  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL | \
2782  MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
2783  pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
2784  }
2785 #endif
2786  }
2787 #ifdef UPGRADE_SUPPORT
2788  else
2789  {
2790  /* Data forwarding was finished (for TLS connections) AND
2791  * application was closed upgraded connection.
2792  * Insert connection into cleanup list. */
2793  DLL_insert (daemon->cleanup_head,
2794  daemon->cleanup_tail,
2795  pos);
2796 
2797  }
2798 #endif /* UPGRADE_SUPPORT */
2799  pos->resuming = false;
2800  }
2802  if ( (used_thr_p_c) &&
2803  (MHD_NO != ret) )
2804  { /* Wake up suspended connections. */
2805  if (! MHD_itc_activate_(daemon->itc,
2806  "w"))
2807  {
2808 #ifdef HAVE_MESSAGES
2809  MHD_DLOG (daemon,
2810  _("Failed to signal resume of connection via inter-thread communication channel."));
2811 #endif
2812  }
2813  }
2814  return ret;
2815 }
2816 
2817 
2845 int
2847  MHD_socket client_socket,
2848  const struct sockaddr *addr,
2849  socklen_t addrlen)
2850 {
2851  bool sk_nonbl;
2852  if (! MHD_socket_nonblocking_ (client_socket))
2853  {
2854 #ifdef HAVE_MESSAGES
2855  MHD_DLOG (daemon,
2856  _("Failed to set nonblocking mode on new client socket: %s\n"),
2858 #endif
2859  sk_nonbl = 0;
2860  }
2861  else
2862  sk_nonbl = !0;
2863 
2864  if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
2865  (! MHD_socket_noninheritable_ (client_socket)) )
2866  {
2867 #ifdef HAVE_MESSAGES
2868  MHD_DLOG (daemon,
2869  _("Failed to set noninheritable mode on new client socket.\n"));
2870 #endif
2871  }
2872  return internal_add_connection (daemon,
2873  client_socket,
2874  addr,
2875  addrlen,
2876  true,
2877  sk_nonbl);
2878 }
2879 
2880 
2895 static int
2897 {
2898 #if HAVE_INET6
2899  struct sockaddr_in6 addrstorage;
2900 #else
2901  struct sockaddr_in addrstorage;
2902 #endif
2903  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
2904  socklen_t addrlen;
2905  MHD_socket s;
2906  MHD_socket fd;
2907  bool sk_nonbl;
2908 
2909  addrlen = sizeof (addrstorage);
2910  memset (addr,
2911  0,
2912  sizeof (addrstorage));
2913  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
2914  (daemon->was_quiesced) )
2915  return MHD_NO;
2916 #ifdef USE_ACCEPT4
2917  s = accept4 (fd,
2918  addr,
2919  &addrlen,
2921  sk_nonbl = (MAYBE_SOCK_NONBLOCK != 0);
2922 #else /* ! USE_ACCEPT4 */
2923  s = accept (fd,
2924  addr,
2925  &addrlen);
2926  sk_nonbl = 0;
2927 #endif /* ! USE_ACCEPT4 */
2928  if ( (MHD_INVALID_SOCKET == s) ||
2929  (addrlen <= 0) )
2930  {
2931  const int err = MHD_socket_get_error_ ();
2932 
2933  /* This could be a common occurance with multiple worker threads */
2934  if (MHD_SCKT_ERR_IS_ (err,
2936  return MHD_NO; /* can happen during shutdown */
2938  return MHD_NO; /* do not print error if client just disconnected early */
2939 #ifdef HAVE_MESSAGES
2940  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
2941  MHD_DLOG (daemon,
2942  _("Error accepting connection: %s\n"),
2943  MHD_socket_strerr_(err));
2944 #endif
2945  if (MHD_INVALID_SOCKET != s)
2946  {
2948  }
2949  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
2950  {
2951  /* system/process out of resources */
2952  if (0 == daemon->connections)
2953  {
2954 #ifdef HAVE_MESSAGES
2955  /* Not setting 'at_limit' flag, as there is no way it
2956  would ever be cleared. Instead trying to produce
2957  bit fat ugly warning. */
2958  MHD_DLOG (daemon,
2959  _("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"));
2960 #endif
2961  }
2962  else
2963  {
2965  daemon->at_limit = true;
2967 #ifdef HAVE_MESSAGES
2968  MHD_DLOG (daemon,
2969  _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
2970  (unsigned int) daemon->connections);
2971 #endif
2972  }
2973  }
2974  return MHD_NO;
2975  }
2976 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
2977  if (! MHD_socket_nonblocking_ (s))
2978  {
2979 #ifdef HAVE_MESSAGES
2980  MHD_DLOG (daemon,
2981  _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
2983 #endif
2984  }
2985  else
2986  sk_nonbl = !0;
2987 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
2988 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
2989  if (! MHD_socket_noninheritable_ (s))
2990  {
2991 #ifdef HAVE_MESSAGES
2992  MHD_DLOG (daemon,
2993  _("Failed to set noninheritable mode on incoming connection socket.\n"));
2994 #endif
2995  }
2996 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
2997 #ifdef HAVE_MESSAGES
2998 #if DEBUG_CONNECT
2999  MHD_DLOG (daemon,
3000  _("Accepted connection on socket %d\n"),
3001  s);
3002 #endif
3003 #endif
3004  (void) internal_add_connection (daemon,
3005  s,
3006  addr,
3007  addrlen,
3008  false,
3009  sk_nonbl);
3010  return MHD_YES;
3011 }
3012 
3013 
3023 static void
3025 {
3026  struct MHD_Connection *pos;
3027 
3029  while (NULL != (pos = daemon->cleanup_tail))
3030  {
3033  pos);
3035 
3036  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3037  (! pos->thread_joined) &&
3038  (! MHD_join_thread_ (pos->pid.handle)) )
3039  MHD_PANIC (_("Failed to join a thread\n"));
3040 #ifdef UPGRADE_SUPPORT
3041  cleanup_upgraded_connection (pos);
3042 #endif /* UPGRADE_SUPPORT */
3043  MHD_pool_destroy (pos->pool);
3044 #ifdef HTTPS_SUPPORT
3045  if (NULL != pos->tls_session)
3046  gnutls_deinit (pos->tls_session);
3047 #endif /* HTTPS_SUPPORT */
3048 
3049  /* clean up the connection */
3050  if (NULL != daemon->notify_connection)
3052  pos,
3053  &pos->socket_context,
3056  pos->addr,
3057  pos->addr_len);
3058 #ifdef EPOLL_SUPPORT
3059  if (0 != (daemon->options & MHD_USE_EPOLL))
3060  {
3061  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3062  {
3063  EDLL_remove (daemon->eready_head,
3064  daemon->eready_tail,
3065  pos);
3066  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3067  }
3068  if ( (-1 != daemon->epoll_fd) &&
3069  (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3070  {
3071  /* epoll documentation suggests that closing a FD
3072  automatically removes it from the epoll set; however,
3073  this is not true as if we fail to do manually remove it,
3074  we are still seeing an event for this fd in epoll,
3075  causing grief (use-after-free...) --- at least on my
3076  system. */
3077  if (0 != epoll_ctl (daemon->epoll_fd,
3078  EPOLL_CTL_DEL,
3079  pos->socket_fd,
3080  NULL))
3081  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
3082  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3083  }
3084  }
3085 #endif
3086  if (NULL != pos->response)
3087  {
3089  pos->response = NULL;
3090  }
3091  if (MHD_INVALID_SOCKET != pos->socket_fd)
3093  if (NULL != pos->addr)
3094  free (pos->addr);
3095  free (pos);
3096 
3098  daemon->connections--;
3099  daemon->at_limit = false;
3100  }
3102 }
3103 
3104 
3125 int
3127  MHD_UNSIGNED_LONG_LONG *timeout)
3128 {
3129  time_t earliest_deadline;
3130  time_t now;
3131  struct MHD_Connection *pos;
3132  bool have_timeout;
3133 
3135  {
3136 #ifdef HAVE_MESSAGES
3137  MHD_DLOG (daemon,
3138  _("Illegal call to MHD_get_timeout\n"));
3139 #endif
3140  return MHD_NO;
3141  }
3142 
3144  {
3145  /* Some data already waiting to be processed. */
3146  *timeout = 0;
3147  return MHD_YES;
3148  }
3149 
3150 #ifdef EPOLL_SUPPORT
3151  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3152  ((NULL != daemon->eready_head)
3153 #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3154  || (NULL != daemon->eready_urh_head)
3155 #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3156  ) )
3157  {
3158  /* Some connection(s) already have some data pending. */
3159  *timeout = 0;
3160  return MHD_YES;
3161  }
3162 #endif /* EPOLL_SUPPORT */
3163 
3164  have_timeout = false;
3165  earliest_deadline = 0; /* avoid compiler warnings */
3166  for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3167  {
3168  if (0 != pos->connection_timeout)
3169  {
3170  if ( (! have_timeout) ||
3171  (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3172  earliest_deadline = pos->last_activity + pos->connection_timeout;
3173  have_timeout = true;
3174  }
3175  }
3176  /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3177  pos = daemon->normal_timeout_tail;
3178  if ( (NULL != pos) &&
3179  (0 != pos->connection_timeout) )
3180  {
3181  if ( (! have_timeout) ||
3182  (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3183  earliest_deadline = pos->last_activity + pos->connection_timeout;
3184  have_timeout = true;
3185  }
3186 
3187  if (! have_timeout)
3188  return MHD_NO;
3189  now = MHD_monotonic_sec_counter();
3190  if (earliest_deadline < now)
3191  *timeout = 0;
3192  else
3193  {
3194  const time_t second_left = earliest_deadline - now;
3195  if (second_left > ULLONG_MAX / 1000) /* Ignore compiler warning: 'second_left' is always positive. */
3196  *timeout = ULLONG_MAX;
3197  else
3198  *timeout = 1000LL * second_left;
3199  }
3200  return MHD_YES;
3201 }
3202 
3203 
3214 static int
3216  const fd_set *read_fd_set,
3217  const fd_set *write_fd_set,
3218  const fd_set *except_fd_set)
3219 {
3220  MHD_socket ds;
3221  struct MHD_Connection *pos;
3222  struct MHD_Connection *prev;
3223 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3224  struct MHD_UpgradeResponseHandle *urh;
3225  struct MHD_UpgradeResponseHandle *urhn;
3226 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3227  /* Reset. New value will be set when connections are processed. */
3228  /* Note: no-op for thread-per-connection as it is always false in that mode. */
3229  daemon->data_already_pending = false;
3230 
3231  /* Clear ITC to avoid spinning select */
3232  /* Do it before any other processing so new signals
3233  will trigger select again and will be processed */
3234  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3235  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3236  read_fd_set)) )
3237  MHD_itc_clear_ (daemon->itc);
3238 
3239  /* select connection thread handling type */
3240  if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3241  (! daemon->was_quiesced) &&
3242  (FD_ISSET (ds,
3243  read_fd_set)) )
3244  (void) MHD_accept_connection (daemon);
3245 
3246  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3247  {
3248  /* do not have a thread per connection, process all connections now */
3249  prev = daemon->connections_tail;
3250  while (NULL != (pos = prev))
3251  {
3252  prev = pos->prev;
3253  ds = pos->socket_fd;
3254  if (MHD_INVALID_SOCKET == ds)
3255  continue;
3256  call_handlers (pos,
3257  FD_ISSET (ds,
3258  read_fd_set),
3259  FD_ISSET (ds,
3260  write_fd_set),
3261  FD_ISSET (ds,
3262  except_fd_set));
3263  }
3264  }
3265 
3266 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3267  /* handle upgraded HTTPS connections */
3268  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3269  {
3270  urhn = urh->prev;
3271  /* update urh state based on select() output */
3272  urh_from_fdset (urh,
3273  read_fd_set,
3274  write_fd_set,
3275  except_fd_set);
3276  /* call generic forwarding function for passing data */
3277  process_urh (urh);
3278  /* Finished forwarding? */
3279  if ( (0 == urh->in_buffer_size) &&
3280  (0 == urh->out_buffer_size) &&
3281  (0 == urh->in_buffer_used) &&
3282  (0 == urh->out_buffer_used) )
3283  {
3284  MHD_connection_finish_forward_ (urh->connection);
3285  urh->clean_ready = true;
3286  /* Resuming will move connection to cleanup list. */
3287  MHD_resume_connection(urh->connection);
3288  }
3289  }
3290 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3291  MHD_cleanup_connections (daemon);
3292  return MHD_YES;
3293 }
3294 
3295 
3318 int
3320  const fd_set *read_fd_set,
3321  const fd_set *write_fd_set,
3322  const fd_set *except_fd_set)
3323 {
3324  fd_set es;
3325  if (0 != (daemon->options &
3327  return MHD_NO;
3328  if (NULL == read_fd_set || NULL == write_fd_set)
3329  return MHD_NO;
3330  if (NULL == except_fd_set)
3331  { /* Workaround to maintain backward compatibility. */
3332 #ifdef HAVE_MESSAGES
3333  MHD_DLOG (daemon,
3334  _("MHD_run_from_select() called with except_fd_set "
3335  "set to NULL. Such behavior is deprecated.\n"));
3336 #endif
3337  FD_ZERO (&es);
3338  except_fd_set = &es;
3339  }
3340  if (0 != (daemon->options & MHD_USE_EPOLL))
3341  {
3342 #ifdef EPOLL_SUPPORT
3343  int ret;
3344  ret = MHD_epoll (daemon, MHD_NO);
3345  MHD_cleanup_connections (daemon);
3346  return ret;
3347 #else /* ! EPOLL_SUPPORT */
3348  return MHD_NO;
3349 #endif /* ! EPOLL_SUPPORT */
3350  }
3351 
3352  /* Resuming external connections when using an extern mainloop */
3353  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3355 
3356  return internal_run_from_select (daemon, read_fd_set,
3357  write_fd_set, except_fd_set);
3358 }
3359 
3360 
3369 static int
3370 MHD_select (struct MHD_Daemon *daemon,
3371  int may_block)
3372 {
3373  int num_ready;
3374  fd_set rs;
3375  fd_set ws;
3376  fd_set es;
3377  MHD_socket maxsock;
3378  struct timeval timeout;
3379  struct timeval *tv;
3380  MHD_UNSIGNED_LONG_LONG ltimeout;
3381  int err_state;
3382  MHD_socket ls;
3383 
3384  timeout.tv_sec = 0;
3385  timeout.tv_usec = 0;
3386  if (daemon->shutdown)
3387  return MHD_NO;
3388  FD_ZERO (&rs);
3389  FD_ZERO (&ws);
3390  FD_ZERO (&es);
3391  maxsock = MHD_INVALID_SOCKET;
3392  err_state = MHD_NO;
3393  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3394  (MHD_YES == resume_suspended_connections (daemon)) &&
3395  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
3396  may_block = MHD_NO;
3397 
3398  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3399  {
3400  /* single-threaded, go over everything */
3401  if (MHD_NO ==
3402  internal_get_fdset2 (daemon,
3403  &rs,
3404  &ws,
3405  &es,
3406  &maxsock,
3407  FD_SETSIZE))
3408  {
3409 #ifdef HAVE_MESSAGES
3410  MHD_DLOG (daemon,
3411  _("Could not obtain daemon fdsets"));
3412 #endif
3413  err_state = MHD_YES;
3414  }
3415  }
3416  else
3417  {
3418  /* accept only, have one thread per connection */
3419  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3420  (! daemon->was_quiesced) &&
3421  (! MHD_add_to_fd_set_ (ls,
3422  &rs,
3423  &maxsock,
3424  FD_SETSIZE)) )
3425  {
3426 #ifdef HAVE_MESSAGES
3427  MHD_DLOG (daemon,
3428  _("Could not add listen socket to fdset"));
3429 #endif
3430  return MHD_NO;
3431  }
3432  }
3433  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3434  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3435  &rs,
3436  &maxsock,
3437  FD_SETSIZE)) )
3438  {
3439 #if defined(MHD_WINSOCK_SOCKETS)
3440  /* fdset limit reached, new connections
3441  cannot be handled. Remove listen socket FD
3442  from fdset and retry to add ITC FD. */
3443  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3444  (! daemon->was_quiesced) )
3445  {
3446  FD_CLR (ls,
3447  &rs);
3448  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
3449  &rs,
3450  &maxsock,
3451  FD_SETSIZE))
3452  {
3453 #endif /* MHD_WINSOCK_SOCKETS */
3454 #ifdef HAVE_MESSAGES
3455  MHD_DLOG (daemon,
3456  _("Could not add control inter-thread communication channel FD to fdset"));
3457 #endif
3458  err_state = MHD_YES;
3459 #if defined(MHD_WINSOCK_SOCKETS)
3460  }
3461  }
3462 #endif /* MHD_WINSOCK_SOCKETS */
3463  }
3464  /* Stop listening if we are at the configured connection limit */
3465  /* If we're at the connection limit, no point in really
3466  accepting new connections; however, make sure we do not miss
3467  the shutdown OR the termination of an existing connection; so
3468  only do this optimization if we have a signaling ITC in
3469  place. */
3470  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3471  (MHD_ITC_IS_VALID_(daemon->itc)) &&
3472  ( (daemon->connections == daemon->connection_limit) ||
3473  (daemon->at_limit) ) )
3474  {
3475  FD_CLR (ls,
3476  &rs);
3477  }
3478  tv = NULL;
3479  if (MHD_YES == err_state)
3480  may_block = MHD_NO;
3481  if (MHD_NO == may_block)
3482  {
3483  timeout.tv_usec = 0;
3484  timeout.tv_sec = 0;
3485  tv = &timeout;
3486  }
3487  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3488  (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
3489  {
3490  /* ltimeout is in ms */
3491  timeout.tv_usec = (ltimeout % 1000) * 1000;
3492  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
3493  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
3494  else
3495  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)(ltimeout / 1000);
3496  tv = &timeout;
3497  }
3498  num_ready = MHD_SYS_select_ (maxsock + 1,
3499  &rs,
3500  &ws,
3501  &es,
3502  tv);
3503  if (daemon->shutdown)
3504  return MHD_NO;
3505  if (num_ready < 0)
3506  {
3507  const int err = MHD_socket_get_error_ ();
3508  if (MHD_SCKT_ERR_IS_EINTR_(err))
3509  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3510 #ifdef HAVE_MESSAGES
3511  MHD_DLOG (daemon,
3512  _("select failed: %s\n"),
3513  MHD_socket_strerr_ (err));
3514 #endif
3515  return MHD_NO;
3516  }
3517  if (MHD_YES == internal_run_from_select (daemon,
3518  &rs,
3519  &ws,
3520  &es))
3521  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3522  return MHD_NO;
3523 }
3524 
3525 
3526 #ifdef HAVE_POLL
3527 
3535 static int
3536 MHD_poll_all (struct MHD_Daemon *daemon,
3537  int may_block)
3538 {
3539  unsigned int num_connections;
3540  struct MHD_Connection *pos;
3541  struct MHD_Connection *prev;
3542 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3543  struct MHD_UpgradeResponseHandle *urh;
3544  struct MHD_UpgradeResponseHandle *urhn;
3545 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3546 
3547  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3548  (MHD_YES == resume_suspended_connections (daemon)) )
3549  may_block = MHD_NO;
3550 
3551  /* count number of connections and thus determine poll set size */
3552  num_connections = 0;
3553  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3554  num_connections++;
3555 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3556  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3557  num_connections += 2;
3558 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3559  {
3560  MHD_UNSIGNED_LONG_LONG ltimeout;
3561  unsigned int i;
3562  int timeout;
3563  unsigned int poll_server;
3564  int poll_listen;
3565  int poll_itc_idx;
3566  struct pollfd *p;
3567  MHD_socket ls;
3568 
3569  p = MHD_calloc_ ((2 + num_connections), sizeof (struct pollfd));
3570  if (NULL == p)
3571  {
3572 #ifdef HAVE_MESSAGES
3573  MHD_DLOG (daemon,
3574  _("Error allocating memory: %s\n"),
3575  MHD_strerror_(errno));
3576 #endif
3577  return MHD_NO;
3578  }
3579  poll_server = 0;
3580  poll_listen = -1;
3581  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3582  (! daemon->was_quiesced) &&
3583  (daemon->connections < daemon->connection_limit) &&
3584  (! daemon->at_limit) )
3585  {
3586  /* only listen if we are not at the connection limit */
3587  p[poll_server].fd = ls;
3588  p[poll_server].events = POLLIN;
3589  p[poll_server].revents = 0;
3590  poll_listen = (int) poll_server;
3591  poll_server++;
3592  }
3593  poll_itc_idx = -1;
3594  if (MHD_ITC_IS_VALID_(daemon->itc))
3595  {
3596  p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3597  p[poll_server].events = POLLIN;
3598  p[poll_server].revents = 0;
3599  poll_itc_idx = (int) poll_server;
3600  poll_server++;
3601  }
3602  if (may_block == MHD_NO)
3603  timeout = 0;
3604  else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3605  (MHD_YES != MHD_get_timeout (daemon,
3606  &ltimeout)) )
3607  timeout = -1;
3608  else
3609  timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3610 
3611  i = 0;
3612  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
3613  {
3614  p[poll_server+i].fd = pos->socket_fd;
3615  switch (pos->event_loop_info)
3616  {
3618  p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3619  break;
3621  p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3622  break;
3624  p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3625  break;
3627  timeout = 0; /* clean up "pos" immediately */
3628  break;
3629  }
3630  i++;
3631  }
3632 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3633  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3634  {
3635  urh_to_pollfd(urh, &(p[poll_server+i]));
3636  i += 2;
3637  }
3638 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3639  if (0 == poll_server + num_connections)
3640  {
3641  free(p);
3642  return MHD_YES;
3643  }
3644  if (MHD_sys_poll_(p,
3645  poll_server + num_connections,
3646  timeout) < 0)
3647  {
3648  const int err = MHD_socket_get_error_ ();
3649  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3650  {
3651  free(p);
3652  return MHD_YES;
3653  }
3654 #ifdef HAVE_MESSAGES
3655  MHD_DLOG (daemon,
3656  _("poll failed: %s\n"),
3657  MHD_socket_strerr_ (err));
3658 #endif
3659  free(p);
3660  return MHD_NO;
3661  }
3662 
3663  /* Reset. New value will be set when connections are processed. */
3664  daemon->data_already_pending = false;
3665 
3666  /* handle ITC FD */
3667  /* do it before any other processing so
3668  new signals will be processed in next loop */
3669  if ( (-1 != poll_itc_idx) &&
3670  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3671  MHD_itc_clear_ (daemon->itc);
3672 
3673  /* handle shutdown */
3674  if (daemon->shutdown)
3675  {
3676  free(p);
3677  return MHD_NO;
3678  }
3679  i = 0;
3680  prev = daemon->connections_tail;
3681  while (NULL != (pos = prev))
3682  {
3683  prev = pos->prev;
3684  /* first, sanity checks */
3685  if (i >= num_connections)
3686  break; /* connection list changed somehow, retry later ... */
3687  if (p[poll_server+i].fd != pos->socket_fd)
3688  continue; /* fd mismatch, something else happened, retry later ... */
3689  call_handlers (pos,
3690  0 != (p[poll_server+i].revents & POLLIN),
3691  0 != (p[poll_server+i].revents & POLLOUT),
3692  0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
3693  i++;
3694  }
3695 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3696  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3697  {
3698  if (i >= num_connections)
3699  break; /* connection list changed somehow, retry later ... */
3700 
3701  /* Get next connection here as connection can be removed
3702  * from 'daemon->urh_head' list. */
3703  urhn = urh->prev;
3704  /* Check for fd mismatch. FIXME: required for safety? */
3705  if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3706  (p[poll_server+i+1].fd != urh->mhd.socket))
3707  break;
3708  urh_from_pollfd(urh, &(p[poll_server+i]));
3709  i += 2;
3710  process_urh (urh);
3711  /* Finished forwarding? */
3712  if ( (0 == urh->in_buffer_size) &&
3713  (0 == urh->out_buffer_size) &&
3714  (0 == urh->in_buffer_used) &&
3715  (0 == urh->out_buffer_used) )
3716  {
3717  /* MHD_connection_finish_forward_() will remove connection from
3718  * 'daemon->urh_head' list. */
3719  MHD_connection_finish_forward_ (urh->connection);
3720  urh->clean_ready = true;
3721  /* If 'urh->was_closed' already was set to true, connection will be
3722  * moved immediately to cleanup list. Otherwise connection
3723  * will stay in suspended list until 'urh' will be marked
3724  * with 'was_closed' by application. */
3725  MHD_resume_connection(urh->connection);
3726  }
3727  }
3728 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3729  /* handle 'listen' FD */
3730  if ( (-1 != poll_listen) &&
3731  (0 != (p[poll_listen].revents & POLLIN)) )
3732  (void) MHD_accept_connection (daemon);
3733 
3734  free(p);
3735  }
3736  return MHD_YES;
3737 }
3738 
3739 
3747 static int
3748 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3749  int may_block)
3750 {
3751  struct pollfd p[2];
3752  int timeout;
3753  unsigned int poll_count;
3754  int poll_listen;
3755  int poll_itc_idx;
3756  MHD_socket ls;
3757 
3758  memset (&p,
3759  0,
3760  sizeof (p));
3761  poll_count = 0;
3762  poll_listen = -1;
3763  poll_itc_idx = -1;
3764  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3765  (! daemon->was_quiesced) )
3766 
3767  {
3768  p[poll_count].fd = ls;
3769  p[poll_count].events = POLLIN;
3770  p[poll_count].revents = 0;
3771  poll_listen = poll_count;
3772  poll_count++;
3773  }
3774  if (MHD_ITC_IS_VALID_(daemon->itc))
3775  {
3776  p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
3777  p[poll_count].events = POLLIN;
3778  p[poll_count].revents = 0;
3779  poll_itc_idx = poll_count;
3780  poll_count++;
3781  }
3782 
3783  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3784  (void)resume_suspended_connections (daemon);
3785 
3786  if (MHD_NO == may_block)
3787  timeout = 0;
3788  else
3789  timeout = -1;
3790  if (0 == poll_count)
3791  return MHD_YES;
3792  if (MHD_sys_poll_(p,
3793  poll_count,
3794  timeout) < 0)
3795  {
3796  const int err = MHD_socket_get_error_ ();
3797 
3798  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3799  return MHD_YES;
3800 #ifdef HAVE_MESSAGES
3801  MHD_DLOG (daemon,
3802  _("poll failed: %s\n"),
3803  MHD_socket_strerr_ (err));
3804 #endif
3805  return MHD_NO;
3806  }
3807  if ( (-1 != poll_itc_idx) &&
3808  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3809  MHD_itc_clear_ (daemon->itc);
3810 
3811  /* handle shutdown */
3812  if (daemon->shutdown)
3813  return MHD_NO;
3814  if ( (-1 != poll_listen) &&
3815  (0 != (p[poll_listen].revents & POLLIN)) )
3816  (void) MHD_accept_connection (daemon);
3817  return MHD_YES;
3818 }
3819 #endif
3820 
3821 
3829 static int
3830 MHD_poll (struct MHD_Daemon *daemon,
3831  int may_block)
3832 {
3833 #ifdef HAVE_POLL
3834  if (daemon->shutdown)
3835  return MHD_NO;
3836  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3837  return MHD_poll_all (daemon,
3838  may_block);
3839  return MHD_poll_listen_socket (daemon,
3840  may_block);
3841 #else
3842  return MHD_NO;
3843 #endif
3844 }
3845 
3846 
3847 #ifdef EPOLL_SUPPORT
3848 
3857 #define MAX_EVENTS 128
3858 
3859 
3860 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3861 
3869 static bool
3870 is_urh_ready(struct MHD_UpgradeResponseHandle * const urh)
3871 {
3872  const struct MHD_Connection * const connection = urh->connection;
3873 
3874  if ( (0 == urh->in_buffer_size) &&
3875  (0 == urh->out_buffer_size) &&
3876  (0 == urh->in_buffer_used) &&
3877  (0 == urh->out_buffer_used) )
3878  return false;
3879 
3880  if (connection->daemon->shutdown)
3881  return true;
3882 
3883  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
3884  (connection->tls_read_ready) ) &&
3885  (urh->in_buffer_used < urh->in_buffer_size) )
3886  return true;
3887 
3888  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
3889  (urh->out_buffer_used < urh->out_buffer_size) )
3890  return true;
3891 
3892  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
3893  (urh->out_buffer_used > 0) )
3894  return true;
3895 
3896  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
3897  (urh->in_buffer_used > 0) )
3898  return true;
3899 
3900  return false;
3901 }
3902 
3911 static int
3912 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
3913 {
3914  struct epoll_event events[MAX_EVENTS];
3915  int num_events;
3916  struct MHD_UpgradeResponseHandle * pos;
3917  struct MHD_UpgradeResponseHandle * prev;
3918 
3919  num_events = MAX_EVENTS;
3920  while (MAX_EVENTS == num_events)
3921  {
3922  unsigned int i;
3923  /* update event masks */
3924  num_events = epoll_wait (daemon->epoll_upgrade_fd,
3925  events,
3926  MAX_EVENTS,
3927  0);
3928  if (-1 == num_events)
3929  {
3930  const int err = MHD_socket_get_error_ ();
3931  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3932  return MHD_YES;
3933 #ifdef HAVE_MESSAGES
3934  MHD_DLOG (daemon,
3935  _("Call to epoll_wait failed: %s\n"),
3936  MHD_socket_strerr_ (err));
3937 #endif
3938  return MHD_NO;
3939  }
3940  for (i = 0; i < (unsigned int) num_events; i++)
3941  {
3942  struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
3943  struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
3944  bool new_err_state = false;
3945 
3946  if (urh->clean_ready)
3947  continue;
3948 
3949  /* Update ueh state based on what is ready according to epoll() */
3950  if (0 != (events[i].events & EPOLLIN))
3951  ueh->celi |= MHD_EPOLL_STATE_READ_READY;
3952  if (0 != (events[i].events & EPOLLOUT))
3953  ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
3954  if (0 != (events[i].events & EPOLLHUP))
3956 
3957  if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
3958  (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
3959  {
3960  /* Process new error state only one time
3961  * and avoid continuously marking this connection
3962  * as 'ready'. */
3963  ueh->celi |= MHD_EPOLL_STATE_ERROR;
3964  new_err_state = true;
3965  }
3966 
3967  if (! urh->in_eready_list)
3968  {
3969  if (new_err_state ||
3970  is_urh_ready(urh))
3971  {
3972  EDLL_insert (daemon->eready_urh_head,
3973  daemon->eready_urh_tail,
3974  urh);
3975  urh->in_eready_list = true;
3976  }
3977  }
3978  }
3979  }
3980  prev = daemon->eready_urh_tail;
3981  while (NULL != (pos = prev))
3982  {
3983  prev = pos->prevE;
3984  process_urh (pos);
3985  if (! is_urh_ready(pos))
3986  {
3987  EDLL_remove (daemon->eready_urh_head,
3988  daemon->eready_urh_tail,
3989  pos);
3990  pos->in_eready_list = false;
3991  }
3992  /* Finished forwarding? */
3993  if ( (0 == pos->in_buffer_size) &&
3994  (0 == pos->out_buffer_size) &&
3995  (0 == pos->in_buffer_used) &&
3996  (0 == pos->out_buffer_used) )
3997  {
3998  MHD_connection_finish_forward_ (pos->connection);
3999  pos->clean_ready = true;
4000  /* If 'pos->was_closed' already was set to true, connection
4001  * will be moved immediately to cleanup list. Otherwise
4002  * connection will stay in suspended list until 'pos' will
4003  * be marked with 'was_closed' by application. */
4004  MHD_resume_connection(pos->connection);
4005  }
4006  }
4007 
4008  return MHD_YES;
4009 }
4010 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4011 
4015 static const char * const epoll_itc_marker = "itc_marker";
4016 
4025 static int
4026 MHD_epoll (struct MHD_Daemon *daemon,
4027  int may_block)
4028 {
4029 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4030  static const char * const upgrade_marker = "upgrade_ptr";
4031 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4032  struct MHD_Connection *pos;
4033  struct MHD_Connection *prev;
4034  struct epoll_event events[MAX_EVENTS];
4035  struct epoll_event event;
4036  int timeout_ms;
4037  MHD_UNSIGNED_LONG_LONG timeout_ll;
4038  int num_events;
4039  unsigned int i;
4040  MHD_socket ls;
4041 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4042  int run_upgraded = MHD_NO;
4043 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4044 
4045  if (-1 == daemon->epoll_fd)
4046  return MHD_NO; /* we're down! */
4047  if (daemon->shutdown)
4048  return MHD_NO;
4049  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4050  (! daemon->was_quiesced) &&
4051  (daemon->connections < daemon->connection_limit) &&
4052  (! daemon->listen_socket_in_epoll) &&
4053  (! daemon->at_limit) )
4054  {
4055  event.events = EPOLLIN;
4056  event.data.ptr = daemon;
4057  if (0 != epoll_ctl (daemon->epoll_fd,
4058  EPOLL_CTL_ADD,
4059  ls,
4060  &event))
4061  {
4062 #ifdef HAVE_MESSAGES
4063  MHD_DLOG (daemon,
4064  _("Call to epoll_ctl failed: %s\n"),
4066 #endif
4067  return MHD_NO;
4068  }
4069  daemon->listen_socket_in_epoll = true;
4070  }
4071  if ( (daemon->was_quiesced) &&
4072  (daemon->listen_socket_in_epoll) )
4073  {
4074  if (0 != epoll_ctl (daemon->epoll_fd,
4075  EPOLL_CTL_DEL,
4076  ls,
4077  NULL))
4078  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4079  daemon->listen_socket_in_epoll = false;
4080  }
4081 
4082 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4083  if ( (! daemon->upgrade_fd_in_epoll) &&
4084  (-1 != daemon->epoll_upgrade_fd) )
4085  {
4086  event.events = EPOLLIN | EPOLLOUT;
4087  event.data.ptr = (void *) upgrade_marker;
4088  if (0 != epoll_ctl (daemon->epoll_fd,
4089  EPOLL_CTL_ADD,
4090  daemon->epoll_upgrade_fd,
4091  &event))
4092  {
4093 #ifdef HAVE_MESSAGES
4094  MHD_DLOG (daemon,
4095  _("Call to epoll_ctl failed: %s\n"),
4097 #endif
4098  return MHD_NO;
4099  }
4100  daemon->upgrade_fd_in_epoll = true;
4101  }
4102 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4103  if ( (daemon->listen_socket_in_epoll) &&
4104  ( (daemon->connections == daemon->connection_limit) ||
4105  (daemon->at_limit) ||
4106  (daemon->was_quiesced) ) )
4107  {
4108  /* we're at the connection limit, disable listen socket
4109  for event loop for now */
4110  if (0 != epoll_ctl (daemon->epoll_fd,
4111  EPOLL_CTL_DEL,
4112  ls,
4113  NULL))
4114  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4115  daemon->listen_socket_in_epoll = false;
4116  }
4117 
4118  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4119  (MHD_YES == resume_suspended_connections (daemon)) )
4120  may_block = MHD_NO;
4121 
4122  if (MHD_YES == may_block)
4123  {
4124  if (MHD_YES == MHD_get_timeout (daemon,
4125  &timeout_ll))
4126  {
4127  if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4128  timeout_ms = INT_MAX;
4129  else
4130  timeout_ms = (int) timeout_ll;
4131  }
4132  else
4133  timeout_ms = -1;
4134  }
4135  else
4136  timeout_ms = 0;
4137 
4138  /* Reset. New value will be set when connections are processed. */
4139  /* Note: Used mostly for uniformity here as same situation is
4140  * signaled in epoll mode by non-empty eready DLL. */
4141  daemon->data_already_pending = false;
4142 
4143  /* drain 'epoll' event queue; need to iterate as we get at most
4144  MAX_EVENTS in one system call here; in practice this should
4145  pretty much mean only one round, but better an extra loop here
4146  than unfair behavior... */
4147  num_events = MAX_EVENTS;
4148  while (MAX_EVENTS == num_events)
4149  {
4150  /* update event masks */
4151  num_events = epoll_wait (daemon->epoll_fd,
4152  events,
4153  MAX_EVENTS,
4154  timeout_ms);
4155  if (-1 == num_events)
4156  {
4157  const int err = MHD_socket_get_error_ ();
4158  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4159  return MHD_YES;
4160 #ifdef HAVE_MESSAGES
4161  MHD_DLOG (daemon,
4162  _("Call to epoll_wait failed: %s\n"),
4163  MHD_socket_strerr_ (err));
4164 #endif
4165  return MHD_NO;
4166  }
4167  for (i=0;i<(unsigned int) num_events;i++)
4168  {
4169  /* First, check for the values of `ptr` that would indicate
4170  that this event is not about a normal connection. */
4171  if (NULL == events[i].data.ptr)
4172  continue; /* shutdown signal! */
4173 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4174  if (upgrade_marker == events[i].data.ptr)
4175  {
4176  /* activity on an upgraded connection, we process
4177  those in a separate epoll() */
4178  run_upgraded = MHD_YES;
4179  continue;
4180  }
4181 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4182  if (epoll_itc_marker == events[i].data.ptr)
4183  {
4184  /* It's OK to clear ITC here as all external
4185  conditions will be processed later. */
4186  MHD_itc_clear_ (daemon->itc);
4187  continue;
4188  }
4189  if (daemon == events[i].data.ptr)
4190  {
4191  /* Check for error conditions on listen socket. */
4192  /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4193  if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4194  {
4195  unsigned int series_length = 0;
4196  /* Run 'accept' until it fails or daemon at limit of connections.
4197  * Do not accept more then 10 connections at once. The rest will
4198  * be accepted on next turn (level trigger is used for listen
4199  * socket). */
4200  while ( (MHD_YES == MHD_accept_connection (daemon)) &&
4201  (series_length < 10) &&
4202  (daemon->connections < daemon->connection_limit) &&
4203  (! daemon->at_limit) )
4204  series_length++;
4205  }
4206  continue;
4207  }
4208  /* this is an event relating to a 'normal' connection,
4209  remember the event and if appropriate mark the
4210  connection as 'eready'. */
4211  pos = events[i].data.ptr;
4212  /* normal processing: update read/write data */
4213  if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4214  {
4215  pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4216  if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4217  {
4218  EDLL_insert (daemon->eready_head,
4219  daemon->eready_tail,
4220  pos);
4221  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4222  }
4223  }
4224  else
4225  {
4226  if (0 != (events[i].events & EPOLLIN))
4227  {
4228  pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4229  if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4230  (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4231  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4232  {
4233  EDLL_insert (daemon->eready_head,
4234  daemon->eready_tail,
4235  pos);
4236  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4237  }
4238  }
4239  if (0 != (events[i].events & EPOLLOUT))
4240  {
4241  pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4242  if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
4243  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4244  {
4245  EDLL_insert (daemon->eready_head,
4246  daemon->eready_tail,
4247  pos);
4248  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4249  }
4250  }
4251  }
4252  }
4253  }
4254 
4255 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4256  if (MHD_YES == run_upgraded)
4257  run_epoll_for_upgrade (daemon);
4258 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4259 
4260  /* process events for connections */
4261  prev = daemon->eready_tail;
4262  while (NULL != (pos = prev))
4263  {
4264  prev = pos->prevE;
4265  call_handlers (pos,
4266  0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
4267  0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
4268  0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
4271  {
4272  if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info &&
4273  0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ) ||
4275  0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ) ||
4277  {
4278  EDLL_remove (daemon->eready_head,
4279  daemon->eready_tail,
4280  pos);
4281  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4282  }
4283  }
4284  }
4285 
4286  /* Finally, handle timed-out connections; we need to do this here
4287  as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
4288  as the other event loops do. As timeouts do not get an explicit
4289  event, we need to find those connections that might have timed out
4290  here.
4291 
4292  Connections with custom timeouts must all be looked at, as we
4293  do not bother to sort that (presumably very short) list. */
4294  prev = daemon->manual_timeout_tail;
4295  while (NULL != (pos = prev))
4296  {
4297  prev = pos->prevX;
4299  }
4300  /* Connections with the default timeout are sorted by prepending
4301  them to the head of the list whenever we touch the connection;
4302  thus it suffices to iterate from the tail until the first
4303  connection is NOT timed out */
4304  prev = daemon->normal_timeout_tail;
4305  while (NULL != (pos = prev))
4306  {
4307  prev = pos->prevX;
4309  if (MHD_CONNECTION_CLOSED != pos->state)
4310  break; /* sorted by timeout, no need to visit the rest! */
4311  }
4312  return MHD_YES;
4313 }
4314 #endif
4315 
4316 
4337 int
4338 MHD_run (struct MHD_Daemon *daemon)
4339 {
4340  if ( (daemon->shutdown) ||
4341  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4342  return MHD_NO;
4343  if (0 != (daemon->options & MHD_USE_POLL))
4344  {
4345  MHD_poll (daemon, MHD_NO);
4346  MHD_cleanup_connections (daemon);
4347  }
4348 #ifdef EPOLL_SUPPORT
4349  else if (0 != (daemon->options & MHD_USE_EPOLL))
4350  {
4351  MHD_epoll (daemon, MHD_NO);
4352  MHD_cleanup_connections (daemon);
4353  }
4354 #endif
4355  else
4356  {
4357  MHD_select (daemon, MHD_NO);
4358  /* MHD_select does MHD_cleanup_connections already */
4359  }
4360  return MHD_YES;
4361 }
4362 
4363 
4372 static void
4374 {
4375  struct MHD_Daemon *daemon = pos->daemon;
4376 
4377  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4378  {
4380  return; /* must let thread to do the rest */
4381  }
4382  MHD_connection_close_ (pos,
4384 
4386 
4387  mhd_assert (! pos->suspended);
4388  mhd_assert (! pos->resuming);
4389  if (pos->connection_timeout == pos->daemon->connection_timeout)
4391  daemon->normal_timeout_tail,
4392  pos);
4393  else
4395  daemon->manual_timeout_tail,
4396  pos);
4397  DLL_remove (daemon->connections_head,
4398  daemon->connections_tail,
4399  pos);
4400  DLL_insert (daemon->cleanup_head,
4401  daemon->cleanup_tail,
4402  pos);
4403 
4405 }
4406 
4407 
4415 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4417 {
4418  struct MHD_Daemon *daemon = cls;
4419  MHD_thread_init_(&(daemon->pid));
4420 
4421  while (! daemon->shutdown)
4422  {
4423  if (0 != (daemon->options & MHD_USE_POLL))
4424  MHD_poll (daemon, MHD_YES);
4425 #ifdef EPOLL_SUPPORT
4426  else if (0 != (daemon->options & MHD_USE_EPOLL))
4427  MHD_epoll (daemon, MHD_YES);
4428 #endif
4429  else
4430  MHD_select (daemon, MHD_YES);
4431  MHD_cleanup_connections (daemon);
4432  }
4433 
4434  /* Resume any pending for resume connections, join
4435  * all connection's threads (if any) and finally cleanup
4436  * everything. */
4437  close_all_connections (daemon);
4438 
4439  return (MHD_THRD_RTRN_TYPE_)0;
4440 }
4441 
4442 
4454 static size_t
4455 unescape_wrapper (void *cls,
4456  struct MHD_Connection *connection,
4457  char *val)
4458 {
4459  (void)cls; /* Mute compiler warning. */
4460  (void)connection; /* Mute compiler warning. */
4461  return MHD_http_unescape (val);
4462 }
4463 
4464 
4485 struct MHD_Daemon *
4486 MHD_start_daemon (unsigned int flags,
4487  uint16_t port,
4489  void *apc_cls,
4491  void *dh_cls,
4492  ...)
4493 {
4494  struct MHD_Daemon *daemon;
4495  va_list ap;
4496 
4497  va_start (ap,
4498  dh_cls);
4499  daemon = MHD_start_daemon_va (flags,
4500  port,
4501  apc,
4502  apc_cls,
4503  dh,
4504  dh_cls,
4505  ap);
4506  va_end (ap);
4507  return daemon;
4508 }
4509 
4510 
4530 MHD_socket
4532 {
4533  unsigned int i;
4534  MHD_socket ret;
4535 
4536  ret = daemon->listen_fd;
4537  if (MHD_INVALID_SOCKET == ret)
4538  return MHD_INVALID_SOCKET;
4539  if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
4540  (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
4541  {
4542 #ifdef HAVE_MESSAGES
4543  MHD_DLOG (daemon,
4544  "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
4545 #endif
4546  return MHD_INVALID_SOCKET;
4547  }
4548 
4549  if (NULL != daemon->worker_pool)
4550  for (i = 0; i < daemon->worker_pool_size; i++)
4551  {
4552  daemon->worker_pool[i].was_quiesced = true;
4553 #ifdef EPOLL_SUPPORT
4554  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4555  (-1 != daemon->worker_pool[i].epoll_fd) &&
4556  (daemon->worker_pool[i].listen_socket_in_epoll) )
4557  {
4558  if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4559  EPOLL_CTL_DEL,
4560  ret,
4561  NULL))
4562  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4563  daemon->worker_pool[i].listen_socket_in_epoll = false;
4564  }
4565  else
4566 #endif
4567  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
4568  {
4569  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4570  MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
4571  }
4572  }
4573  daemon->was_quiesced = true;
4574 #ifdef EPOLL_SUPPORT
4575  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4576  (-1 != daemon->epoll_fd) &&
4577  (daemon->listen_socket_in_epoll) )
4578  {
4579  if (0 != epoll_ctl (daemon->epoll_fd,
4580  EPOLL_CTL_DEL,
4581  ret,
4582  NULL))
4583  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4584  daemon->listen_socket_in_epoll = false;
4585  }
4586 #endif
4587  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
4588  (! MHD_itc_activate_ (daemon->itc, "q")) )
4589  MHD_PANIC (_("failed to signal quiesce via inter-thread communication channel"));
4590  return ret;
4591 }
4592 
4593 
4601 typedef void
4603  const char *format,
4604  va_list va);
4605 
4606 
4615 static int
4616 parse_options_va (struct MHD_Daemon *daemon,
4617  const struct sockaddr **servaddr,
4618  va_list ap);
4619 
4620 
4629 static int
4630 parse_options (struct MHD_Daemon *daemon,
4631  const struct sockaddr **servaddr,
4632  ...)
4633 {
4634  va_list ap;
4635  int ret;
4636 
4637  va_start (ap, servaddr);
4638  ret = parse_options_va (daemon,
4639  servaddr,
4640  ap);
4641  va_end (ap);
4642  return ret;
4643 }
4644 
4645 
4654 static int
4656  const struct sockaddr **servaddr,
4657  va_list ap)
4658 {
4659  enum MHD_OPTION opt;
4660  struct MHD_OptionItem *oa;
4661  unsigned int i;
4662  unsigned int uv;
4663 #ifdef HTTPS_SUPPORT
4664  int ret;
4665  const char *pstr;
4666 #endif /* HTTPS_SUPPORT */
4667 
4668  while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
4669  {
4670  switch (opt)
4671  {
4673  daemon->pool_size = va_arg (ap,
4674  size_t);
4675  break;
4677  daemon->pool_increment= va_arg (ap,
4678  size_t);
4679  break;
4681  daemon->connection_limit = va_arg (ap,
4682  unsigned int);
4683  break;
4685  uv = va_arg (ap,
4686  unsigned int);
4687  /* Next comparison could be always false on some platforms and whole branch will
4688  * be optimized out on those platforms. On others it will be compiled into real
4689  * check. */
4690  if (TIME_T_MAX < uv) /* Compiler may warn on some platforms, ignore warning. */
4691  {
4692 #ifdef HAVE_MESSAGES
4693  MHD_DLOG (daemon,
4694  _("Warning: Too large timeout value, ignored.\n"));
4695 #endif
4696  daemon->connection_timeout = 0;
4697  }
4698  else
4699  daemon->connection_timeout = (time_t)uv;
4700  break;
4702  daemon->notify_completed = va_arg (ap,
4704  daemon->notify_completed_cls = va_arg (ap,
4705  void *);
4706  break;
4708  daemon->notify_connection = va_arg (ap,
4710  daemon->notify_connection_cls = va_arg (ap,
4711  void *);
4712  break;
4714  daemon->per_ip_connection_limit = va_arg (ap,
4715  unsigned int);
4716  break;
4717  case MHD_OPTION_SOCK_ADDR:
4718  *servaddr = va_arg (ap,
4719  const struct sockaddr *);
4720  break;
4722  daemon->uri_log_callback = va_arg (ap,
4723  LogCallback);
4724  daemon->uri_log_callback_cls = va_arg (ap,
4725  void *);
4726  break;
4728  daemon->worker_pool_size = va_arg (ap,
4729  unsigned int);
4730  if (0 == daemon->worker_pool_size)
4731  {
4732 #ifdef HAVE_MESSAGES
4733  MHD_DLOG (daemon,
4734  _("Warning: Zero size, specified for thread pool size, is ignored. "
4735  "Thread pool is not used.\n"));
4736 #endif
4737  }
4738  else if (1 == daemon->worker_pool_size)
4739  {
4740 #ifdef HAVE_MESSAGES
4741  MHD_DLOG (daemon,
4742  _("Warning: \"1\", specified for thread pool size, is ignored. "
4743  "Thread pool is not used.\n"));
4744 #endif
4745  daemon->worker_pool_size = 0;
4746  }
4747  /* Next comparison could be always false on some platforms and whole branch will
4748  * be optimized out on those platforms. On others it will be compiled into real
4749  * check. */
4750  else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
4751  {
4752 #ifdef HAVE_MESSAGES
4753  MHD_DLOG (daemon,
4754  _("Specified thread pool size (%u) too big\n"),
4755  daemon->worker_pool_size);
4756 #endif
4757  return MHD_NO;
4758  }
4759  else
4760  {
4761  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
4762  {
4763 #ifdef HAVE_MESSAGES
4764  MHD_DLOG (daemon,
4765  _("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
4766  "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
4767 #endif
4768  return MHD_NO;
4769  }
4770  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4771  {
4772 #ifdef HAVE_MESSAGES
4773  MHD_DLOG (daemon,
4774  _("Both MHD_OPTION_THREAD_POOL_SIZE option and "
4775  "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
4776 #endif
4777  return MHD_NO;
4778  }
4779  }
4780  break;
4781 #ifdef HTTPS_SUPPORT
4783  if (0 != (daemon->options & MHD_USE_TLS))
4784  daemon->https_mem_key = va_arg (ap,
4785  const char *);
4786 #ifdef HAVE_MESSAGES
4787  else
4788  MHD_DLOG (daemon,
4789  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4790  opt);
4791 #endif
4792  break;
4794  if (0 != (daemon->options & MHD_USE_TLS))
4795  daemon->https_key_password = va_arg (ap,
4796  const char *);
4797 #ifdef HAVE_MESSAGES
4798  else
4799  MHD_DLOG (daemon,
4800  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4801  opt);
4802 #endif
4803  break;
4805  if (0 != (daemon->options & MHD_USE_TLS))
4806  daemon->https_mem_cert = va_arg (ap,
4807  const char *);
4808 #ifdef HAVE_MESSAGES
4809  else
4810  MHD_DLOG (daemon,
4811  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4812  opt);
4813 #endif
4814  break;
4816  if (0 != (daemon->options & MHD_USE_TLS))
4817  daemon->https_mem_trust = va_arg (ap,
4818  const char *);
4819 #ifdef HAVE_MESSAGES
4820  else
4821  MHD_DLOG (daemon,
4822  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4823  opt);
4824 #endif
4825  break;
4827  daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4828  int);
4829  break;
4831  if (0 != (daemon->options & MHD_USE_TLS))
4832  {
4833  const char *arg = va_arg (ap,
4834  const char *);
4835  gnutls_datum_t dhpar;
4836 
4837  if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4838  {
4839 #ifdef HAVE_MESSAGES
4840  MHD_DLOG (daemon,
4841  _("Error initializing DH parameters\n"));
4842 #endif
4843  return MHD_NO;
4844  }
4845  dhpar.data = (unsigned char *) arg;
4846  dhpar.size = strlen (arg);
4847  if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4848  &dhpar,
4849  GNUTLS_X509_FMT_PEM) < 0)
4850  {
4851 #ifdef HAVE_MESSAGES
4852  MHD_DLOG (daemon,
4853  _("Bad Diffie-Hellman parameters format\n"));
4854 #endif
4855  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4856  return MHD_NO;
4857  }
4858  daemon->have_dhparams = true;
4859  }
4860  else
4861  {
4862 #ifdef HAVE_MESSAGES
4863  MHD_DLOG (daemon,
4864  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4865  opt);
4866 #endif
4867  return MHD_NO;
4868  }
4869  break;
4871  if (0 != (daemon->options & MHD_USE_TLS))
4872  {
4873  gnutls_priority_deinit (daemon->priority_cache);
4874  ret = gnutls_priority_init (&daemon->priority_cache,
4875  pstr = va_arg (ap, const char*),
4876  NULL);
4877  if (GNUTLS_E_SUCCESS != ret)
4878  {
4879 #ifdef HAVE_MESSAGES
4880  MHD_DLOG (daemon,
4881  _("Setting priorities to `%s' failed: %s\n"),
4882  pstr,
4883  gnutls_strerror (ret));
4884 #endif
4885  daemon->priority_cache = NULL;
4886  return MHD_NO;
4887  }
4888  }
4889  break;
4891 #if GNUTLS_VERSION_MAJOR < 3
4892 #ifdef HAVE_MESSAGES
4893  MHD_DLOG (daemon,
4894  _("MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
4895 #endif
4896  return MHD_NO;
4897 #else
4898  if (0 != (daemon->options & MHD_USE_TLS))
4899  daemon->cert_callback = va_arg (ap,
4900  gnutls_certificate_retrieve_function2 *);
4901  break;
4902 #endif
4903 #endif /* HTTPS_SUPPORT */
4904 #ifdef DAUTH_SUPPORT
4906  daemon->digest_auth_rand_size = va_arg (ap,
4907  size_t);
4908  daemon->digest_auth_random = va_arg (ap,
4909  const char *);
4910  break;
4912  daemon->nonce_nc_size = va_arg (ap,
4913  unsigned int);
4914  break;
4915 #endif
4917  if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
4918  {
4919 #ifdef HAVE_MESSAGES
4920  MHD_DLOG (daemon,
4921  _("MHD_OPTION_LISTEN_SOCKET specified for daemon "
4922  "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
4923 #endif
4924  return MHD_NO;
4925  }
4926  else
4927  daemon->listen_fd = va_arg (ap,
4928  MHD_socket);
4929  break;
4931 #ifdef HAVE_MESSAGES
4932  daemon->custom_error_log = va_arg (ap,
4934  daemon->custom_error_log_cls = va_arg (ap,
4935  void *);
4936 #else
4937  va_arg (ap,
4939  va_arg (ap,
4940  void *);
4941 #endif
4942  break;
4944  daemon->thread_stack_size = va_arg (ap,
4945  size_t);
4946  break;
4947 #ifdef TCP_FASTOPEN
4949  daemon->fastopen_queue_size = va_arg (ap,
4950  unsigned int);
4951  break;
4952 #endif
4954  daemon->listening_address_reuse = va_arg (ap,
4955  unsigned int) ? 1 : -1;
4956  break;
4958  daemon->listen_backlog_size = va_arg (ap,
4959  unsigned int);
4960  break;
4962  daemon->strict_for_client = va_arg (ap, int);;
4963 #ifdef HAVE_MESSAGES
4964  if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
4965  (1 != daemon->strict_for_client) )
4966  {
4967  MHD_DLOG (daemon,
4968  _("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
4969  "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
4970  }
4971 #endif /* HAVE_MESSAGES */
4972  break;
4973  case MHD_OPTION_ARRAY:
4974  oa = va_arg (ap, struct MHD_OptionItem*);
4975  i = 0;
4976  while (MHD_OPTION_END != (opt = oa[i].option))
4977  {
4978  switch (opt)
4979  {
4980  /* all options taking 'size_t' */
4984  if (MHD_YES != parse_options (daemon,
4985  servaddr,
4986  opt,
4987  (size_t) oa[i].value,
4988  MHD_OPTION_END))
4989  return MHD_NO;
4990  break;
4991  /* all options taking 'unsigned int' */
5000  if (MHD_YES != parse_options (daemon,
5001  servaddr,
5002  opt,
5003  (unsigned int) oa[i].value,
5004  MHD_OPTION_END))
5005  return MHD_NO;
5006  break;
5007  /* all options taking 'enum' */
5008 #ifdef HTTPS_SUPPORT
5010  if (MHD_YES != parse_options (daemon,
5011  servaddr,
5012  opt,
5013  (gnutls_credentials_type_t) oa[i].value,
5014  MHD_OPTION_END))
5015  return MHD_NO;
5016  break;
5017 #endif /* HTTPS_SUPPORT */
5018  /* all options taking 'MHD_socket' */
5020  if (MHD_YES != parse_options (daemon,
5021  servaddr,
5022  opt,
5023  (MHD_socket) oa[i].value,
5024  MHD_OPTION_END))
5025  return MHD_NO;
5026  break;
5027  /* all options taking 'int' */
5029  if (MHD_YES != parse_options (daemon,
5030  servaddr,
5031  opt,
5032  (int) oa[i].value,
5033  MHD_OPTION_END))
5034  return MHD_NO;
5035  break;
5036  /* all options taking one pointer */
5037  case MHD_OPTION_SOCK_ADDR:
5044  case MHD_OPTION_ARRAY:
5046  if (MHD_YES != parse_options (daemon,
5047  servaddr,
5048  opt,
5049  oa[i].ptr_value,
5050  MHD_OPTION_END))
5051  return MHD_NO;
5052  break;
5053  /* all options taking two pointers */
5059  if (MHD_YES != parse_options (daemon,
5060  servaddr,
5061  opt,
5062  (void *) oa[i].value,
5063  oa[i].ptr_value,
5064  MHD_OPTION_END))
5065  return MHD_NO;
5066  break;
5067  /* options taking size_t-number followed by pointer */
5069  if (MHD_YES != parse_options (daemon,
5070  servaddr,
5071  opt,
5072  (size_t) oa[i].value,
5073  oa[i].ptr_value,
5074  MHD_OPTION_END))
5075  return MHD_NO;
5076  break;
5077  default:
5078  return MHD_NO;
5079  }
5080  i++;
5081  }
5082  break;
5084  daemon->unescape_callback = va_arg (ap,
5086  daemon->unescape_callback_cls = va_arg (ap,
5087  void *);
5088  break;
5089  default:
5090 #ifdef HAVE_MESSAGES
5091  if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
5092  (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
5093  (opt == MHD_OPTION_HTTPS_MEM_TRUST))
5094  {
5095  MHD_DLOG (daemon,
5096  _("MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
5097  opt);
5098  }
5099  else
5100  {
5101  MHD_DLOG (daemon,
5102  _("Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
5103  opt);
5104  }
5105 #endif
5106  return MHD_NO;
5107  }
5108  }
5109  return MHD_YES;
5110 }
5111 
5112 
5113 #ifdef EPOLL_SUPPORT
5114 static int
5115 setup_epoll_fd (struct MHD_Daemon *daemon)
5116 {
5117  int fd;
5118 
5119 #ifndef HAVE_MESSAGES
5120  (void)daemon; /* Mute compiler warning. */
5121 #endif /* ! HAVE_MESSAGES */
5122 
5123 #ifdef USE_EPOLL_CREATE1
5124  fd = epoll_create1 (EPOLL_CLOEXEC);
5125 #else /* ! USE_EPOLL_CREATE1 */
5126  fd = epoll_create (MAX_EVENTS);
5127 #endif /* ! USE_EPOLL_CREATE1 */
5128  if (MHD_INVALID_SOCKET == fd)
5129  {
5130 #ifdef HAVE_MESSAGES
5131  MHD_DLOG (daemon,
5132  _("Call to epoll_create1 failed: %s\n"),
5134 #endif
5135  return MHD_INVALID_SOCKET;
5136  }
5137 #if !defined(USE_EPOLL_CREATE1)
5139  {
5140 #ifdef HAVE_MESSAGES
5141  MHD_DLOG (daemon,
5142  _("Failed to set noninheritable mode on epoll FD.\n"));
5143 #endif
5144  }
5145 #endif /* ! USE_EPOLL_CREATE1 */
5146  return fd;
5147 }
5148 
5149 
5159 static int
5160 setup_epoll_to_listen (struct MHD_Daemon *daemon)
5161 {
5162  struct epoll_event event;
5163  MHD_socket ls;
5164 
5165  daemon->epoll_fd = setup_epoll_fd (daemon);
5166  if (-1 == daemon->epoll_fd)
5167  return MHD_NO;
5168 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5169  if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
5170  {
5171  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5172  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
5173  return MHD_NO;
5174  }
5175 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5176  if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
5177  (daemon->was_quiesced) )
5178  return MHD_YES; /* non-listening daemon */
5179  event.events = EPOLLIN;
5180  event.data.ptr = daemon;
5181  if (0 != epoll_ctl (daemon->epoll_fd,
5182  EPOLL_CTL_ADD,
5183  ls,
5184  &event))
5185  {
5186 #ifdef HAVE_MESSAGES
5187  MHD_DLOG (daemon,
5188  _("Call to epoll_ctl failed: %s\n"),
5190 #endif
5191  return MHD_NO;
5192  }
5193  daemon->listen_socket_in_epoll = true;
5194  if (MHD_ITC_IS_VALID_(daemon->itc))
5195  {
5196  event.events = EPOLLIN;
5197  event.data.ptr = (void *) epoll_itc_marker;
5198  if (0 != epoll_ctl (daemon->epoll_fd,
5199  EPOLL_CTL_ADD,
5200  MHD_itc_r_fd_ (daemon->itc),
5201  &event))
5202  {
5203 #ifdef HAVE_MESSAGES
5204  MHD_DLOG (daemon,
5205  _("Call to epoll_ctl failed: %s\n"),
5207 #endif
5208  return MHD_NO;
5209  }
5210  }
5211  return MHD_YES;
5212 }
5213 #endif
5214 
5215 
5237 struct MHD_Daemon *
5238 MHD_start_daemon_va (unsigned int flags,
5239  uint16_t port,
5241  void *apc_cls,
5243  void *dh_cls,
5244  va_list ap)
5245 {
5246  const MHD_SCKT_OPT_BOOL_ on = 1;
5247  struct MHD_Daemon *daemon;
5249  struct sockaddr_in servaddr4;
5250 #if HAVE_INET6
5251  struct sockaddr_in6 servaddr6;
5252 #endif
5253  const struct sockaddr *servaddr = NULL;
5254  socklen_t addrlen;
5255  unsigned int i;
5256  enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
5257  enum MHD_FLAG *pflags;
5258 
5260  eflags = (enum MHD_FLAG) flags;
5261  pflags = &eflags;
5262 #ifndef HAVE_INET6
5263  if (0 != (*pflags & MHD_USE_IPv6))
5264  return NULL;
5265 #endif
5266 #ifndef HAVE_POLL
5267  if (0 != (*pflags & MHD_USE_POLL))
5268  return NULL;
5269 #endif
5270 #ifndef EPOLL_SUPPORT
5271  if (0 != (*pflags & MHD_USE_EPOLL))
5272  return NULL;
5273 #endif /* ! EPOLL_SUPPORT */
5274 #ifndef HTTPS_SUPPORT
5275  if (0 != (*pflags & MHD_USE_TLS))
5276  return NULL;
5277 #endif /* ! HTTPS_SUPPORT */
5278 #ifndef TCP_FASTOPEN
5279  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5280  return NULL;
5281 #endif
5282  if (0 != (*pflags & MHD_ALLOW_UPGRADE))
5283  {
5284 #ifdef UPGRADE_SUPPORT
5285  *pflags |= MHD_ALLOW_SUSPEND_RESUME;
5286 #else /* ! UPGRADE_SUPPORT */
5287  return NULL;
5288 #endif /* ! UPGRADE_SUPPORT */
5289  }
5290  if (NULL == dh)
5291  return NULL;
5292 
5293  /* Check for invalid combinations of flags. */
5294  if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5295  ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))) ||
5296  ((0 != (*pflags & MHD_USE_POLL)) &&
5298  ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)))) )
5299  return NULL;
5300 
5301  if (0 != (*pflags & MHD_USE_AUTO))
5302  {
5303  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5304  {
5305  /* Thread per connection with internal polling thread. */
5306 #ifdef HAVE_POLL
5307  *pflags |= MHD_USE_POLL;
5308 #else /* ! HAVE_POLL */
5309  /* use select() - do not modify flags */
5310 #endif /* ! HAVE_POLL */
5311  }
5312  else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5313  {
5314  /* Internal polling thread. */
5315 #if defined(EPOLL_SUPPORT)
5316  *pflags |= MHD_USE_EPOLL;
5317 #elif defined(HAVE_POLL)
5318  *pflags |= MHD_USE_POLL;
5319 #else /* !HAVE_POLL && !EPOLL_SUPPORT */
5320  /* use select() - do not modify flags */
5321 #endif /* !HAVE_POLL && !EPOLL_SUPPORT */
5322  }
5323  else
5324  {
5325  /* Internal threads are not used - "external" polling mode. */
5326 #if defined(EPOLL_SUPPORT)
5327  *pflags |= MHD_USE_EPOLL;
5328 #else /* ! EPOLL_SUPPORT */
5329  /* use select() - do not modify flags */
5330 #endif /* ! EPOLL_SUPPORT */
5331  }
5332  }
5333 
5334  if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
5335  return NULL;
5336 #ifdef EPOLL_SUPPORT
5337  daemon->epoll_fd = -1;
5338 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5339  daemon->epoll_upgrade_fd = -1;
5340 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5341 #endif
5342  /* try to open listen socket */
5343 #ifdef HTTPS_SUPPORT
5344  daemon->priority_cache = NULL;
5345  if (0 != (*pflags & MHD_USE_TLS))
5346  {
5347  gnutls_priority_init (&daemon->priority_cache,
5348  "@SYSTEM",
5349  NULL);
5350  }
5351 #endif /* HTTPS_SUPPORT */
5352  daemon->listen_fd = MHD_INVALID_SOCKET;
5353  daemon->listening_address_reuse = 0;
5354  daemon->options = *pflags;
5355  pflags = &daemon->options;
5356  daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 : 0;
5357  daemon->port = port;
5358  daemon->apc = apc;
5359  daemon->apc_cls = apc_cls;
5360  daemon->default_handler = dh;
5361  daemon->default_handler_cls = dh_cls;
5362  daemon->connections = 0;
5364  daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
5365  daemon->pool_increment = MHD_BUF_INC_SIZE;
5367  daemon->connection_timeout = 0; /* no timeout */
5368  MHD_itc_set_invalid_ (daemon->itc);
5369 #ifdef SOMAXCONN
5370  daemon->listen_backlog_size = SOMAXCONN;
5371 #else /* !SOMAXCONN */
5372  daemon->listen_backlog_size = 511; /* should be safe value */
5373 #endif /* !SOMAXCONN */
5374 #ifdef HAVE_MESSAGES
5375  daemon->custom_error_log = (MHD_LogCallback) &vfprintf;
5376  daemon->custom_error_log_cls = stderr;
5377 #endif
5378  if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
5379  (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
5380  {
5381 #ifdef HAVE_MESSAGES
5382  MHD_DLOG (daemon,
5383  _("Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5384  "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5385  "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5386 #endif
5388  }
5389  if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5390  *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
5391  else
5392  {
5393 #ifdef HAVE_LISTEN_SHUTDOWN
5394  if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
5395 #endif
5396  *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
5397  }
5398 #ifdef DAUTH_SUPPORT
5399  daemon->digest_auth_rand_size = 0;
5400  daemon->digest_auth_random = NULL;
5401  daemon->nonce_nc_size = 4; /* tiny */
5402 #endif
5403 #ifdef HTTPS_SUPPORT
5404  if (0 != (*pflags & MHD_USE_TLS))
5405  {
5406  daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5407  }
5408 #endif /* HTTPS_SUPPORT */
5409 
5410 
5411  if (MHD_YES != parse_options_va (daemon,
5412  &servaddr,
5413  ap))
5414  {
5415 #ifdef HTTPS_SUPPORT
5416  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5417  (NULL != daemon->priority_cache) )
5418  gnutls_priority_deinit (daemon->priority_cache);
5419 #endif /* HTTPS_SUPPORT */
5420  free (daemon);
5421  return NULL;
5422  }
5423 #ifndef NDEBUG
5424 #ifdef HAVE_MESSAGES
5425  MHD_DLOG (daemon, _("Using debug build of libmicrohttpd.\n") );
5426 #endif /* HAVE_MESSAGES */
5427 #endif /* ! NDEBUG */
5428  if ( (0 != (*pflags & MHD_USE_ITC)) &&
5429  (0 == daemon->worker_pool_size) )
5430  {
5431  if (! MHD_itc_init_ (daemon->itc))
5432  {
5433 #ifdef HAVE_MESSAGES
5434  MHD_DLOG (daemon,
5435  _("Failed to create inter-thread communication channel: %s\n"),
5436  MHD_itc_last_strerror_ ());
5437 #endif
5438 #ifdef HTTPS_SUPPORT
5439  if (NULL != daemon->priority_cache)
5440  gnutls_priority_deinit (daemon->priority_cache);
5441 #endif /* HTTPS_SUPPORT */
5442  free (daemon);
5443  return NULL;
5444  }
5445  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5446  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
5447  NULL)) )
5448  {
5449 #ifdef HAVE_MESSAGES
5450  MHD_DLOG (daemon,
5451  _("file descriptor for inter-thread communication channel exceeds maximum value\n"));
5452 #endif
5453  MHD_itc_destroy_chk_ (daemon->itc);
5454 #ifdef HTTPS_SUPPORT
5455  if (NULL != daemon->priority_cache)
5456  gnutls_priority_deinit (daemon->priority_cache);
5457 #endif /* HTTPS_SUPPORT */
5458  free (daemon);
5459  return NULL;
5460  }
5461  }
5462 
5463 #ifdef DAUTH_SUPPORT
5464  if (daemon->nonce_nc_size > 0)
5465  {
5466  if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc))) /
5467  sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
5468  {
5469 #ifdef HAVE_MESSAGES
5470  MHD_DLOG (daemon,
5471  _("Specified value for NC_SIZE too large\n"));
5472 #endif
5473 #ifdef HTTPS_SUPPORT
5474  if (0 != (*pflags & MHD_USE_TLS))
5475  gnutls_priority_deinit (daemon->priority_cache);
5476 #endif /* HTTPS_SUPPORT */
5477  free (daemon);
5478  return NULL;
5479  }
5480  daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
5481  if (NULL == daemon->nnc)
5482  {
5483 #ifdef HAVE_MESSAGES
5484  MHD_DLOG (daemon,
5485  _("Failed to allocate memory for nonce-nc map: %s\n"),
5486  MHD_strerror_ (errno));
5487 #endif
5488 #ifdef HTTPS_SUPPORT
5489  if (0 != (*pflags & MHD_USE_TLS))
5490  gnutls_priority_deinit (daemon->priority_cache);
5491 #endif /* HTTPS_SUPPORT */
5492  free (daemon);
5493  return NULL;
5494  }
5495  }
5496 
5497  if (! MHD_mutex_init_ (&daemon->nnc_lock))
5498  {
5499 #ifdef HAVE_MESSAGES
5500  MHD_DLOG (daemon,
5501  _("MHD failed to initialize nonce-nc mutex\n"));
5502 #endif
5503 #ifdef HTTPS_SUPPORT
5504  if (0 != (*pflags & MHD_USE_TLS))
5505  gnutls_priority_deinit (daemon->priority_cache);
5506 #endif /* HTTPS_SUPPORT */
5507  free (daemon->nnc);
5508  free (daemon);
5509  return NULL;
5510  }
5511 #endif
5512 
5513  /* Thread pooling currently works only with internal select thread model */
5514  if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5515  (daemon->worker_pool_size > 0) )
5516  {
5517 #ifdef HAVE_MESSAGES
5518  MHD_DLOG (daemon,
5519  _("MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"));
5520 #endif
5521  goto free_and_fail;
5522  }
5523 
5524  if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
5525  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5526  {
5527  /* try to open listen socket */
5528  listen_fd = MHD_socket_create_listen_(*pflags & MHD_USE_IPv6);
5529  if (MHD_INVALID_SOCKET == listen_fd)
5530  {
5531 #ifdef HAVE_MESSAGES
5532  MHD_DLOG (daemon,
5533  _("Failed to create socket for listening: %s\n"),
5535 #endif
5536  goto free_and_fail;
5537  }
5538 
5539  /* Apply the socket options according to listening_address_reuse. */
5540  if (0 == daemon->listening_address_reuse)
5541  {
5542 #ifndef MHD_WINSOCK_SOCKETS
5543  /* No user requirement, use "traditional" default SO_REUSEADDR
5544  * on non-W32 platforms, and do not fail if it doesn't work.
5545  * Don't use it on W32, because on W32 it will allow multiple
5546  * bind to the same address:port, like SO_REUSEPORT on others. */
5547  if (0 > setsockopt (listen_fd,
5548  SOL_SOCKET,
5549  SO_REUSEADDR,
5550  (void*)&on, sizeof (on)))
5551  {
5552 #ifdef HAVE_MESSAGES
5553  MHD_DLOG (daemon,
5554  _("setsockopt failed: %s\n"),
5556 #endif
5557  }
5558 #endif /* ! MHD_WINSOCK_SOCKETS */
5559  }
5560  else if (daemon->listening_address_reuse > 0)
5561  {
5562  /* User requested to allow reusing listening address:port. */
5563 #ifndef MHD_WINSOCK_SOCKETS
5564  /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
5565  * it doesn't work. */
5566  if (0 > setsockopt (listen_fd,
5567  SOL_SOCKET,
5568  SO_REUSEADDR,
5569  (void*)&on, sizeof (on)))
5570  {
5571 #ifdef HAVE_MESSAGES
5572  MHD_DLOG (daemon,
5573  _("setsockopt failed: %s\n"),
5575 #endif
5576  }
5577 #endif /* ! MHD_WINSOCK_SOCKETS */
5578  /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
5579  * Fail if SO_REUSEPORT is not defined or setsockopt fails.
5580  */
5581  /* SO_REUSEADDR on W32 has the same semantics
5582  as SO_REUSEPORT on BSD/Linux */
5583 #if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
5584  if (0 > setsockopt (listen_fd,
5585  SOL_SOCKET,
5586 #ifndef MHD_WINSOCK_SOCKETS
5587  SO_REUSEPORT,
5588 #else /* MHD_WINSOCK_SOCKETS */
5589  SO_REUSEADDR,
5590 #endif /* MHD_WINSOCK_SOCKETS */
5591  (void *) &on,
5592  sizeof (on)))
5593  {
5594 #ifdef HAVE_MESSAGES
5595  MHD_DLOG (daemon,
5596  _("setsockopt failed: %s\n"),
5598 #endif
5599  goto free_and_fail;
5600  }
5601 #else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
5602  /* we're supposed to allow address:port re-use, but
5603  on this platform we cannot; fail hard */
5604 #ifdef HAVE_MESSAGES
5605  MHD_DLOG (daemon,
5606  _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
5607 #endif
5608  goto free_and_fail;
5609 #endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
5610  }
5611  else /* if (daemon->listening_address_reuse < 0) */
5612  {
5613  /* User requested to disallow reusing listening address:port.
5614  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
5615  * is used and Solaris with SO_EXCLBIND.
5616  * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
5617  * or setsockopt fails.
5618  */
5619 #if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
5620  (defined(__sun) && defined(SO_EXCLBIND))
5621  if (0 > setsockopt (listen_fd,
5622  SOL_SOCKET,
5623 #ifdef SO_EXCLUSIVEADDRUSE
5624  SO_EXCLUSIVEADDRUSE,
5625 #else /* SO_EXCLBIND */
5626  SO_EXCLBIND,
5627 #endif /* SO_EXCLBIND */
5628  (void *) &on,
5629  sizeof (on)))
5630  {
5631 #ifdef HAVE_MESSAGES
5632  MHD_DLOG (daemon,
5633  _("setsockopt failed: %s\n"),
5635 #endif
5636  goto free_and_fail;
5637  }
5638 #elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
5639 #ifdef HAVE_MESSAGES
5640  MHD_DLOG (daemon,
5641  _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
5642 #endif
5643  goto free_and_fail;
5644 #endif /* MHD_WINSOCK_SOCKETS */
5645  }
5646 
5647  /* check for user supplied sockaddr */
5648 #if HAVE_INET6
5649  if (0 != (*pflags & MHD_USE_IPv6))
5650  addrlen = sizeof (struct sockaddr_in6);
5651  else
5652 #endif
5653  addrlen = sizeof (struct sockaddr_in);
5654  if (NULL == servaddr)
5655  {
5656 #if HAVE_INET6
5657  if (0 != (*pflags & MHD_USE_IPv6))
5658  {
5659 #ifdef IN6ADDR_ANY_INIT
5660  static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
5661 #endif
5662  memset (&servaddr6,
5663  0,
5664  sizeof (struct sockaddr_in6));
5665  servaddr6.sin6_family = AF_INET6;
5666  servaddr6.sin6_port = htons (port);
5667 #ifdef IN6ADDR_ANY_INIT
5668  servaddr6.sin6_addr = static_in6any;
5669 #endif
5670 #if HAVE_SOCKADDR_IN_SIN_LEN
5671  servaddr6.sin6_len = sizeof (struct sockaddr_in6);
5672 #endif
5673  servaddr = (struct sockaddr *) &servaddr6;
5674  }
5675  else
5676 #endif
5677  {
5678  memset (&servaddr4,
5679  0,
5680  sizeof (struct sockaddr_in));
5681  servaddr4.sin_family = AF_INET;
5682  servaddr4.sin_port = htons (port);
5683  if (0 != INADDR_ANY)
5684  servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
5685 #if HAVE_SOCKADDR_IN_SIN_LEN
5686  servaddr4.sin_len = sizeof (struct sockaddr_in);
5687 #endif
5688  servaddr = (struct sockaddr *) &servaddr4;
5689  }
5690  }
5691  daemon->listen_fd = listen_fd;
5692 
5693  if (0 != (*pflags & MHD_USE_IPv6))
5694  {
5695 #ifdef IPPROTO_IPV6
5696 #ifdef IPV6_V6ONLY
5697  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
5698  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
5699  and may also be missing on older POSIX systems; good luck if you have any of those,
5700  your IPv6 socket may then also bind against IPv4 anyway... */
5701  const MHD_SCKT_OPT_BOOL_ v6_only =
5702  (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
5703  if (0 > setsockopt (listen_fd,
5704  IPPROTO_IPV6, IPV6_V6ONLY,
5705  (const void *) &v6_only,
5706  sizeof (v6_only)))
5707  {
5708 #ifdef HAVE_MESSAGES
5709  MHD_DLOG (daemon,
5710  _("setsockopt failed: %s\n"),
5712 #endif
5713  }
5714 #endif
5715 #endif
5716  }
5717  if (-1 == bind (listen_fd, servaddr, addrlen))
5718  {
5719 #ifdef HAVE_MESSAGES
5720  MHD_DLOG (daemon,
5721  _("Failed to bind to port %u: %s\n"),
5722  (unsigned int) port,
5724 #endif
5725  MHD_socket_close_chk_ (listen_fd);
5726  goto free_and_fail;
5727  }
5728 #ifdef TCP_FASTOPEN
5729  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5730  {
5731  if (0 == daemon->fastopen_queue_size)
5732  daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
5733  if (0 != setsockopt (listen_fd,
5734  IPPROTO_TCP,
5735  TCP_FASTOPEN,
5736  &daemon->fastopen_queue_size,
5737  sizeof (daemon->fastopen_queue_size)))
5738  {
5739 #ifdef HAVE_MESSAGES
5740  MHD_DLOG (daemon,
5741  _("setsockopt failed: %s\n"),
5743 #endif
5744  }
5745  }
5746 #endif
5747  if (listen (listen_fd,
5748  daemon->listen_backlog_size) < 0)
5749  {
5750 #ifdef HAVE_MESSAGES
5751  MHD_DLOG (daemon,
5752  _("Failed to listen for connections: %s\n"),
5754 #endif
5755  MHD_socket_close_chk_ (listen_fd);
5756  goto free_and_fail;
5757  }
5758  }
5759  else
5760  {
5761  listen_fd = daemon->listen_fd;
5762  }
5763 
5764  if ( (0 == daemon->port) &&
5765  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5766  { /* Get port number. */
5767  struct sockaddr_storage servaddr;
5768 
5769  memset (&servaddr,
5770  0,
5771  sizeof (struct sockaddr_storage));
5772  addrlen = sizeof (servaddr);
5773  if (0 != getsockname (listen_fd,
5774  (struct sockaddr *) &servaddr,
5775  &addrlen))
5776  {
5777 #ifdef HAVE_MESSAGES
5778  MHD_DLOG (daemon,
5779  _("Failed to get listen port number: %s\n"),
5781 #endif /* HAVE_MESSAGES */
5782  }
5783 #ifdef MHD_POSIX_SOCKETS
5784  else if (sizeof (servaddr) < addrlen)
5785  {
5786  /* should be impossible with `struct sockaddr_storage` */
5787 #ifdef HAVE_MESSAGES
5788  MHD_DLOG (daemon,
5789  _("Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"));
5790 #endif /* HAVE_MESSAGES */
5791  }
5792 #endif /* MHD_POSIX_SOCKETS */
5793  else
5794  {
5795  switch (servaddr.ss_family)
5796  {
5797  case AF_INET:
5798  {
5799  struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
5800 
5801  daemon->port = ntohs (s4->sin_port);
5802  break;
5803  }
5804 #ifdef HAVE_INET6
5805  case AF_INET6:
5806  {
5807  struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
5808 
5809  daemon->port = ntohs(s6->sin6_port);
5810  mhd_assert (0 != (*pflags & MHD_USE_IPv6));
5811  break;
5812  }
5813 #endif /* HAVE_INET6 */
5814 #ifdef AF_UNIX
5815  case AF_UNIX:
5816  daemon->port = 0; /* special value for UNIX domain sockets */
5817  break;
5818 #endif
5819  default:
5820 #ifdef HAVE_MESSAGES
5821  MHD_DLOG (daemon,
5822  _("Unknown address family!\n"));
5823 #endif
5824  daemon->port = 0; /* ugh */
5825  break;
5826  }
5827  }
5828  }
5829 
5830  if ( (MHD_INVALID_SOCKET != listen_fd) &&
5831  (! MHD_socket_nonblocking_ (listen_fd)) )
5832  {
5833 #ifdef HAVE_MESSAGES
5834  MHD_DLOG (daemon,
5835  _("Failed to set nonblocking mode on listening socket: %s\n"),
5837 #endif
5838  if (0 != (*pflags & MHD_USE_EPOLL) ||
5839  daemon->worker_pool_size > 0)
5840  {
5841  /* Accept must be non-blocking. Multiple children may wake up
5842  * to handle a new connection, but only one will win the race.
5843  * The others must immediately return. */
5844  MHD_socket_close_chk_ (listen_fd);
5845  goto free_and_fail;
5846  }
5847  }
5848  if ( (MHD_INVALID_SOCKET != listen_fd) &&
5849  (! MHD_SCKT_FD_FITS_FDSET_(listen_fd,
5850  NULL)) &&
5851  (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
5852  {
5853 #ifdef HAVE_MESSAGES
5854  MHD_DLOG (daemon,
5855  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
5856  listen_fd,
5857  FD_SETSIZE);
5858 #endif
5859  MHD_socket_close_chk_ (listen_fd);
5860  goto free_and_fail;
5861  }
5862 
5863 #ifdef EPOLL_SUPPORT
5864  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
5865  (0 == daemon->worker_pool_size) &&
5866  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5867  {
5868  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5869  {
5870 #ifdef HAVE_MESSAGES
5871  MHD_DLOG (daemon,
5872  _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
5873 #endif
5874  goto free_and_fail;
5875  }
5876  if (MHD_YES != setup_epoll_to_listen (daemon))
5877  goto free_and_fail;
5878  }
5879 #endif /* EPOLL_SUPPORT */
5880 
5881  if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
5882  {
5883 #ifdef HAVE_MESSAGES
5884  MHD_DLOG (daemon,
5885  _("MHD failed to initialize IP connection limit mutex\n"));
5886 #endif
5887  if (MHD_INVALID_SOCKET != listen_fd)
5888  MHD_socket_close_chk_ (listen_fd);
5889  goto free_and_fail;
5890  }
5891  if (0 == daemon->worker_pool_size)
5892  { /* Initialise connection mutex only if this daemon will handle
5893  * any connections by itself. */
5894  if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
5895  {
5896 #ifdef HAVE_MESSAGES
5897  MHD_DLOG (daemon,
5898  _("MHD failed to initialize IP connection limit mutex\n"));
5899 #endif
5901  if (MHD_INVALID_SOCKET != listen_fd)
5902  MHD_socket_close_chk_ (listen_fd);
5903  goto free_and_fail;
5904  }
5905  }
5906 
5907 #ifdef HTTPS_SUPPORT
5908  /* initialize HTTPS daemon certificate aspects & send / recv functions */
5909  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5910  (0 != MHD_TLS_init (daemon)) )
5911  {
5912 #ifdef HAVE_MESSAGES
5913  MHD_DLOG (daemon,
5914  _("Failed to initialize TLS support\n"));
5915 #endif
5916  if (MHD_INVALID_SOCKET != listen_fd)
5917  MHD_socket_close_chk_ (listen_fd);
5918  if (0 == daemon->worker_pool_size)
5921  goto free_and_fail;
5922  }
5923 #endif /* HTTPS_SUPPORT */
5924  if ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5925  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5926  {
5927  if (0 == daemon->worker_pool_size)
5928  {
5929  if (! MHD_create_named_thread_ (&daemon->pid,
5930  (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
5931  "MHD-listen" : "MHD-single",
5932  daemon->thread_stack_size,
5934  daemon) )
5935  {
5936 #ifdef HAVE_MESSAGES
5937  MHD_DLOG (daemon,
5938  _("Failed to create listen thread: %s\n"),
5939  MHD_strerror_ (errno));
5940 #endif
5943  if (MHD_INVALID_SOCKET != listen_fd)
5944  MHD_socket_close_chk_ (listen_fd);
5945  goto free_and_fail;
5946  }
5947  }
5948  else /* 0 < daemon->worker_pool_size */
5949  {
5950  /* Coarse-grained count of connections per thread (note error
5951  * due to integer division). Also keep track of how many
5952  * connections are leftover after an equal split. */
5953  unsigned int conns_per_thread = daemon->connection_limit
5954  / daemon->worker_pool_size;
5955  unsigned int leftover_conns = daemon->connection_limit
5956  % daemon->worker_pool_size;
5957 
5958  i = 0; /* we need this in case fcntl or malloc fails */
5959 
5960  /* Allocate memory for pooled objects */
5961  daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
5962  * daemon->worker_pool_size);
5963  if (NULL == daemon->worker_pool)
5964  goto thread_failed;
5965 
5966  /* Start the workers in the pool */
5967  for (i = 0; i < daemon->worker_pool_size; ++i)
5968  {
5969  /* Create copy of the Daemon object for each worker */
5970  struct MHD_Daemon *d = &daemon->worker_pool[i];
5971 
5972  memcpy (d, daemon, sizeof (struct MHD_Daemon));
5973  /* Adjust pooling params for worker daemons; note that memcpy()
5974  has already copied MHD_USE_INTERNAL_POLLING_THREAD thread model into
5975  the worker threads. */
5976  d->master = daemon;
5977  d->worker_pool_size = 0;
5978  d->worker_pool = NULL;
5979 
5980  if (0 != (*pflags & MHD_USE_ITC))
5981  {
5982  if (! MHD_itc_init_ (d->itc))
5983  {
5984 #ifdef HAVE_MESSAGES
5985  MHD_DLOG (daemon,
5986  _("Failed to create worker inter-thread communication channel: %s\n"),
5987  MHD_itc_last_strerror_() );
5988 #endif
5989  goto thread_failed;
5990  }
5991  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5992  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
5993  NULL)) )
5994  {
5995 #ifdef HAVE_MESSAGES
5996  MHD_DLOG (daemon,
5997  _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
5998 #endif
6000  goto thread_failed;
6001  }
6002  }
6003  else
6004  MHD_itc_set_invalid_ (d->itc);
6005 
6006  /* Divide available connections evenly amongst the threads.
6007  * Thread indexes in [0, leftover_conns) each get one of the
6008  * leftover connections. */
6009  d->connection_limit = conns_per_thread;
6010  if (i < leftover_conns)
6011  ++d->connection_limit;
6012 #ifdef EPOLL_SUPPORT
6013  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6014  (MHD_YES != setup_epoll_to_listen (d)) )
6015  goto thread_failed;
6016 #endif
6017  /* Must init cleanup connection mutex for each worker */
6018  if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
6019  {
6020 #ifdef HAVE_MESSAGES
6021  MHD_DLOG (daemon,
6022  _("MHD failed to initialize cleanup connection mutex\n"));
6023 #endif
6024  goto thread_failed;
6025  }
6026 
6027  /* Spawn the worker thread */
6028  if (! MHD_create_named_thread_ (&d->pid,
6029  "MHD-worker",
6030  daemon->thread_stack_size,
6032  d))
6033  {
6034 #ifdef HAVE_MESSAGES
6035  MHD_DLOG (daemon,
6036  _("Failed to create pool thread: %s\n"),
6037  MHD_strerror_ (errno));
6038 #endif
6039  /* Free memory for this worker; cleanup below handles
6040  * all previously-created workers. */
6042  goto thread_failed;
6043  }
6044  }
6045  }
6046  }
6047 #ifdef HTTPS_SUPPORT
6048  /* API promises to never use the password after initialization,
6049  so we additionally NULL it here to not deref a dangling pointer. */
6050  daemon->https_key_password = NULL;
6051 #endif /* HTTPS_SUPPORT */
6052 
6053  return daemon;
6054 
6055 thread_failed:
6056  /* If no worker threads created, then shut down normally. Calling
6057  MHD_stop_daemon (as we do below) doesn't work here since it
6058  assumes a 0-sized thread pool means we had been in the default
6059  MHD_USE_INTERNAL_POLLING_THREAD mode. */
6060  if (0 == i)
6061  {
6065  if (NULL != daemon->worker_pool)
6066  free (daemon->worker_pool);
6067  goto free_and_fail;
6068  }
6069 
6070  /* Shutdown worker threads we've already created. Pretend
6071  as though we had fully initialized our daemon, but
6072  with a smaller number of threads than had been
6073  requested. */
6074  daemon->worker_pool_size = i;
6075  MHD_stop_daemon (daemon);
6076  return NULL;
6077 
6078  free_and_fail:
6079  /* clean up basic memory state in 'daemon' and return NULL to
6080  indicate failure */
6081 #ifdef EPOLL_SUPPORT
6082 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6083  if (daemon->upgrade_fd_in_epoll)
6084  {
6085  if (0 != epoll_ctl (daemon->epoll_fd,
6086  EPOLL_CTL_DEL,
6087  daemon->epoll_upgrade_fd,
6088  NULL))
6089  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
6090  daemon->upgrade_fd_in_epoll = false;
6091  }
6092 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6093  if (-1 != daemon->epoll_fd)
6094  close (daemon->epoll_fd);
6095 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6096  if (-1 != daemon->epoll_upgrade_fd)
6097  close (daemon->epoll_upgrade_fd);
6098 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6099 #endif /* EPOLL_SUPPORT */
6100 #ifdef DAUTH_SUPPORT
6101  free (daemon->nnc);
6102  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6103 #endif
6104 #ifdef HTTPS_SUPPORT
6105  if (0 != (*pflags & MHD_USE_TLS))
6106  gnutls_priority_deinit (daemon->priority_cache);
6107 #endif /* HTTPS_SUPPORT */
6108  if (MHD_ITC_IS_VALID_(daemon->itc))
6109  MHD_itc_destroy_chk_ (daemon->itc);
6110  free (daemon);
6111  return NULL;
6112 }
6113 
6114 
6123 static void
6125 {
6126  struct MHD_Connection *pos;
6127  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
6128 #ifdef UPGRADE_SUPPORT
6129  const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
6130 #endif /* UPGRADE_SUPPORT */
6131 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6132  struct MHD_UpgradeResponseHandle *urh;
6133  struct MHD_UpgradeResponseHandle *urhn;
6134  const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
6135 
6136  mhd_assert (NULL == daemon->worker_pool);
6137  mhd_assert (daemon->shutdown);
6138  /* give upgraded HTTPS connections a chance to finish */
6139  /* 'daemon->urh_head' is not used in thread-per-connection mode. */
6140  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
6141  {
6142  urhn = urh->prev;
6143  /* call generic forwarding function for passing data
6144  with chance to detect that application is done. */
6145  process_urh (urh);
6146  MHD_connection_finish_forward_ (urh->connection);
6147  urh->clean_ready = true;
6148  /* Resuming will move connection to cleanup list. */
6149  MHD_resume_connection(urh->connection);
6150  }
6151 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6152 
6153  /* Give suspended connections a chance to resume to avoid
6154  running into the check for there not being any suspended
6155  connections left in case of a tight race with a recently
6156  resumed connection. */
6157  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6158  {
6159  daemon->resuming = true; /* Force check for pending resume. */
6161  }
6162  /* first, make sure all threads are aware of shutdown; need to
6163  traverse DLLs in peace... */
6165 #ifdef UPGRADE_SUPPORT
6166  if (upg_allowed)
6167  {
6168  struct MHD_Connection * susp;
6169 
6171  while (NULL != susp)
6172  {
6173  if (NULL == susp->urh) /* "Upgraded" connection? */
6174  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6175 #ifdef HTTPS_SUPPORT
6176  else if (used_tls &&
6177  used_thr_p_c &&
6178  (! susp->urh->clean_ready) )
6179  shutdown (susp->urh->app.socket,
6180  SHUT_RDWR); /* Wake thread by shutdown of app socket. */
6181 #endif /* HTTPS_SUPPORT */
6182  else
6183  {
6184 #ifdef HAVE_MESSAGES
6185  if (! susp->urh->was_closed)
6186  MHD_DLOG (daemon,
6187  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6188 #endif
6189  susp->urh->was_closed = true;
6190  /* If thread-per-connection is used, connection's thread
6191  * may still processing "upgrade" (exiting). */
6192  if (! used_thr_p_c)
6194  /* Do not use MHD_resume_connection() as mutex is
6195  * already locked. */
6196  susp->resuming = true;
6197  daemon->resuming = true;
6198  }
6199  susp = susp->prev;
6200  }
6201  }
6202  else /* This 'else' is combined with next 'if' */
6203 #endif /* UPGRADE_SUPPORT */
6205  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6206  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
6207  {
6208  shutdown (pos->socket_fd,
6209  SHUT_RDWR);
6210 #if MHD_WINSOCK_SOCKETS
6211  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6212  (MHD_ITC_IS_VALID_(daemon->itc)) &&
6213  (! MHD_itc_activate_ (daemon->itc, "e")) )
6214  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6215 #endif
6216  }
6217 
6218  /* now, collect per-connection threads */
6219  if (used_thr_p_c)
6220  {
6221  pos = daemon->connections_tail;
6222  while (NULL != pos)
6223  {
6224  if (! pos->thread_joined)
6225  {
6227  if (! MHD_join_thread_ (pos->pid.handle))
6228  MHD_PANIC (_("Failed to join a thread\n"));
6230  pos->thread_joined = true;
6231  /* The thread may have concurrently modified the DLL,
6232  need to restart from the beginning */
6233  pos = daemon->connections_tail;
6234  continue;
6235  }
6236  pos = pos->prev;
6237  }
6238  }
6240 
6241 #ifdef UPGRADE_SUPPORT
6242  /* Finished threads with "upgraded" connections need to be moved
6243  * to cleanup list by resume_suspended_connections(). */
6244  /* "Upgraded" connections that were not closed explicitly by
6245  * application should be moved to cleanup list too. */
6246  if (upg_allowed)
6247  {
6248  daemon->resuming = true; /* Force check for pending resume. */
6250  }
6251 #endif /* UPGRADE_SUPPORT */
6252 
6253  /* now that we're alone, move everyone to cleanup */
6254  while (NULL != (pos = daemon->connections_tail))
6255  {
6256  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6257  (! pos->thread_joined) )
6258  MHD_PANIC (_("Failed to join a thread\n"));
6259  close_connection (pos);
6260  }
6262 }
6263 
6264 
6271 void
6273 {
6274  MHD_socket fd;
6275  unsigned int i;
6276 
6277  if (NULL == daemon)
6278  return;
6279 
6280  daemon->shutdown = true;
6281  if (daemon->was_quiesced)
6282  fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
6283  else
6284  fd = daemon->listen_fd;
6285 
6286  if (NULL != daemon->worker_pool)
6287  { /* Master daemon with worker pool. */
6290 
6291  /* Let workers shutdown in parallel. */
6292  for (i = 0; i < daemon->worker_pool_size; ++i)
6293  {
6294  daemon->worker_pool[i].shutdown = true;
6295  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
6296  {
6297  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
6298  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
6299  }
6300  else
6302  }
6303 #ifdef HAVE_LISTEN_SHUTDOWN
6304  if (MHD_INVALID_SOCKET != fd)
6305  {
6306  (void) shutdown (fd,
6307  SHUT_RDWR);
6308  }
6309 #endif /* HAVE_LISTEN_SHUTDOWN */
6310  for (i = 0; i < daemon->worker_pool_size; ++i)
6311  {
6313  }
6314  free (daemon->worker_pool);
6316 #ifdef EPOLL_SUPPORT
6317  mhd_assert (-1 == daemon->epoll_fd);
6318 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6319  mhd_assert (-1 == daemon->epoll_upgrade_fd);
6320 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6321 #endif /* EPOLL_SUPPORT */
6322  }
6323  else
6324  { /* Worker daemon or single daemon. */
6326  { /* Worker daemon or single daemon with internal thread(s). */
6330 
6332  {
6333  /* Separate thread(s) is used for polling sockets. */
6334  if (MHD_ITC_IS_VALID_(daemon->itc))
6335  {
6336  if (! MHD_itc_activate_ (daemon->itc, "e"))
6337  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6338  }
6339  else
6340  {
6341 #ifdef HAVE_LISTEN_SHUTDOWN
6342  if (MHD_INVALID_SOCKET != fd)
6343  {
6344  if (NULL == daemon->master)
6345  (void) shutdown (fd,
6346  SHUT_RDWR);
6347  }
6348  else
6349 #endif /* HAVE_LISTEN_SHUTDOWN */
6350  mhd_assert (false); /* Should never happen */
6351  }
6352 
6353  if (! MHD_join_thread_ (daemon->pid.handle))
6354  {
6355  MHD_PANIC (_("Failed to join a thread\n"));
6356  }
6357  /* close_all_connections() was called in daemon thread. */
6358  }
6359  }
6360  else
6361  {
6362  /* No internal threads are used for polling sockets. */
6364  }
6365  if (MHD_ITC_IS_VALID_ (daemon->itc))
6367 
6368 #ifdef EPOLL_SUPPORT
6369  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6370  (-1 != daemon->epoll_fd) )
6371  MHD_socket_close_chk_ (daemon->epoll_fd);
6372 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6373  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6374  (-1 != daemon->epoll_upgrade_fd) )
6375  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
6376 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6377 #endif /* EPOLL_SUPPORT */
6378 
6380  }
6381 
6382  if (NULL == daemon->master)
6383  { /* Cleanup that should be done only one time in master/single daemon.
6384  * Do not perform this cleanup in worker daemons. */
6385 
6386  if (MHD_INVALID_SOCKET != fd)
6388 
6389  /* TLS clean up */
6390 #ifdef HTTPS_SUPPORT
6391  if (daemon->have_dhparams)
6392  {
6393  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6394  daemon->have_dhparams = false;
6395  }
6396  if (0 != (daemon->options & MHD_USE_TLS))
6397  {
6398  gnutls_priority_deinit (daemon->priority_cache);
6399  if (daemon->x509_cred)
6400  gnutls_certificate_free_credentials (daemon->x509_cred);
6401  }
6402 #endif /* HTTPS_SUPPORT */
6403 
6404 #ifdef DAUTH_SUPPORT
6405  free (daemon->nnc);
6406  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6407 #endif
6409 
6410  free (daemon);
6411  }
6412 }
6413 
6414 
6426 const union MHD_DaemonInfo *
6428  enum MHD_DaemonInfoType info_type,
6429  ...)
6430 {
6431  if (NULL == daemon)
6432  return NULL;
6433  switch (info_type)
6434  {
6436  return NULL; /* no longer supported */
6438  return NULL; /* no longer supported */
6440  return (const union MHD_DaemonInfo *) &daemon->listen_fd;
6441 #ifdef EPOLL_SUPPORT
6443  return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
6444 #endif
6446  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6447  {
6448  /* Assume that MHD_run() in not called in other thread
6449  * at the same time. */
6450  MHD_cleanup_connections (daemon);
6451  }
6452  else if (daemon->worker_pool)
6453  {
6454  unsigned int i;
6455  /* Collect the connection information stored in the workers. */
6456  daemon->connections = 0;
6457  for (i = 0; i < daemon->worker_pool_size; i++)
6458  {
6459  /* FIXME: next line is thread-safe only if read is atomic. */
6460  daemon->connections += daemon->worker_pool[i].connections;
6461  }
6462  }
6463  return (const union MHD_DaemonInfo *) &daemon->connections;
6464  case MHD_DAEMON_INFO_FLAGS:
6465  return (const union MHD_DaemonInfo *) &daemon->options;
6467  return (const union MHD_DaemonInfo *) &daemon->port;
6468  default:
6469  return NULL;
6470  }
6471 }
6472 
6473 
6490 void
6492  void *cls)
6493 {
6494  mhd_panic = cb;
6495  mhd_panic_cls = cls;
6496 }
6497 
6498 
6505 const char *
6507 {
6508 #ifdef PACKAGE_VERSION
6509  return PACKAGE_VERSION;
6510 #else /* !PACKAGE_VERSION */
6511  static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
6512  if (0 == ver[0])
6513  {
6514  int res = MHD_snprintf_(ver,
6515  sizeof(ver),
6516  "%x.%x.%x",
6517  (((int)MHD_VERSION >> 24) & 0xFF),
6518  (((int)MHD_VERSION >> 16) & 0xFF),
6519  (((int)MHD_VERSION >> 8) & 0xFF));
6520  if (0 >= res || sizeof(ver) <= res)
6521  return "0.0.0"; /* Can't return real version*/
6522  }
6523  return ver;
6524 #endif /* !PACKAGE_VERSION */
6525 }
6526 
6527 
6539 _MHD_EXTERN int
6541 {
6542  switch(feature)
6543  {
6544  case MHD_FEATURE_MESSAGES:
6545 #ifdef HAVE_MESSAGES
6546  return MHD_YES;
6547 #else
6548  return MHD_NO;
6549 #endif
6550  case MHD_FEATURE_TLS:
6551 #ifdef HTTPS_SUPPORT
6552  return MHD_YES;
6553 #else /* ! HTTPS_SUPPORT */
6554  return MHD_NO;
6555 #endif /* ! HTTPS_SUPPORT */
6557 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
6558  return MHD_YES;
6559 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6560  return MHD_NO;
6561 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6562  case MHD_FEATURE_IPv6:
6563 #ifdef HAVE_INET6
6564  return MHD_YES;
6565 #else
6566  return MHD_NO;
6567 #endif
6568  case MHD_FEATURE_IPv6_ONLY:
6569 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
6570  return MHD_YES;
6571 #else
6572  return MHD_NO;
6573 #endif
6574  case MHD_FEATURE_POLL:
6575 #ifdef HAVE_POLL
6576  return MHD_YES;
6577 #else
6578  return MHD_NO;
6579 #endif
6580  case MHD_FEATURE_EPOLL:
6581 #ifdef EPOLL_SUPPORT
6582  return MHD_YES;
6583 #else
6584  return MHD_NO;
6585 #endif
6587 #ifdef HAVE_LISTEN_SHUTDOWN
6588  return MHD_YES;
6589 #else
6590  return MHD_NO;
6591 #endif
6593 #ifdef _MHD_ITC_SOCKETPAIR
6594  return MHD_YES;
6595 #else
6596  return MHD_NO;
6597 #endif
6599 #ifdef TCP_FASTOPEN
6600  return MHD_YES;
6601 #else
6602  return MHD_NO;
6603 #endif
6605 #ifdef BAUTH_SUPPORT
6606  return MHD_YES;
6607 #else
6608  return MHD_NO;
6609 #endif
6611 #ifdef DAUTH_SUPPORT
6612  return MHD_YES;
6613 #else
6614  return MHD_NO;
6615 #endif
6617 #ifdef HAVE_POSTPROCESSOR
6618  return MHD_YES;
6619 #else
6620  return MHD_NO;
6621 #endif
6623 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
6624  return MHD_YES;
6625 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6626  return MHD_NO;
6627 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6629 #if defined(HAVE_PREAD64) || defined(_WIN32)
6630  return MHD_YES;
6631 #elif defined(HAVE_PREAD)
6632  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6633 #elif defined(HAVE_LSEEK64)
6634  return MHD_YES;
6635 #else
6636  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6637 #endif
6639 #if defined(MHD_USE_THREAD_NAME_)
6640  return MHD_YES;
6641 #else
6642  return MHD_NO;
6643 #endif
6644  case MHD_FEATURE_UPGRADE:
6645 #if defined(UPGRADE_SUPPORT)
6646  return MHD_YES;
6647 #else
6648  return MHD_NO;
6649 #endif
6651 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
6652  return MHD_YES;
6653 #else
6654  return MHD_NO;
6655 #endif
6657 #ifdef MHD_USE_GETSOCKNAME
6658  return MHD_YES;
6659 #else
6660  return MHD_NO;
6661 #endif
6663 #if defined(MHD_WINSOCK_SOCKETS) || defined(MHD_socket_nosignal_) || defined (MSG_NOSIGNAL)
6664  return MHD_YES;
6665 #else
6666  return MHD_NO;
6667 #endif
6668  case MHD_FEATURE_SENDFILE:
6669 #ifdef _MHD_HAVE_SENDFILE
6670  return MHD_YES;
6671 #else
6672  return MHD_NO;
6673 #endif
6674 
6675  }
6676  return MHD_NO;
6677 }
6678 
6679 
6680 #ifdef MHD_HTTPS_REQUIRE_GRYPT
6681 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
6682 #if defined(MHD_USE_POSIX_THREADS)
6683 GCRY_THREAD_OPTION_PTHREAD_IMPL;
6684 #elif defined(MHD_W32_MUTEX_)
6685 
6686 static int
6687 gcry_w32_mutex_init (void **ppmtx)
6688 {
6689  *ppmtx = malloc (sizeof (MHD_mutex_));
6690 
6691  if (NULL == *ppmtx)
6692  return ENOMEM;
6693  if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
6694  {
6695  free (*ppmtx);
6696  *ppmtx = NULL;
6697  return EPERM;
6698  }
6699 
6700  return 0;
6701 }
6702 
6703 
6704 static int
6705 gcry_w32_mutex_destroy (void **ppmtx)
6706 {
6707  int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
6708  free (*ppmtx);
6709  return res;
6710 }
6711 
6712 
6713 static int
6714 gcry_w32_mutex_lock (void **ppmtx)
6715 {
6716  return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6717 }
6718 
6719 
6720 static int
6721 gcry_w32_mutex_unlock (void **ppmtx)
6722 {
6723  return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6724 }
6725 
6726 
6727 static struct gcry_thread_cbs gcry_threads_w32 = {
6728  (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
6729  NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
6730  gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
6731  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
6732 
6733 #endif /* defined(MHD_W32_MUTEX_) */
6734 #endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
6735 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
6736 
6740 void
6742 {
6743 #if defined(_WIN32) && ! defined(__CYGWIN__)
6744  WSADATA wsd;
6745 #endif /* _WIN32 && ! __CYGWIN__ */
6746 
6747  if (NULL == mhd_panic)
6749 
6750 #if defined(_WIN32) && ! defined(__CYGWIN__)
6751  if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
6752  MHD_PANIC (_("Failed to initialize winsock\n"));
6753  mhd_winsock_inited_ = 1;
6754  if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
6755  MHD_PANIC (_("Winsock version 2.2 is not available\n"));
6756 #endif
6757 #ifdef HTTPS_SUPPORT
6758 #ifdef MHD_HTTPS_REQUIRE_GRYPT
6759 #if GCRYPT_VERSION_NUMBER < 0x010600
6760 #if defined(MHD_USE_POSIX_THREADS)
6761  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6762  &gcry_threads_pthread))
6763  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
6764 #elif defined(MHD_W32_MUTEX_)
6765  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6766  &gcry_threads_w32))
6767  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
6768 #endif /* defined(MHD_W32_MUTEX_) */
6769  gcry_check_version (NULL);
6770 #else
6771  if (NULL == gcry_check_version ("1.6.0"))
6772  MHD_PANIC (_("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
6773 #endif
6774 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
6775  gnutls_global_init ();
6776 #endif /* HTTPS_SUPPORT */
6778 #ifdef HAVE_FREEBSD_SENDFILE
6779  MHD_conn_init_static_ ();
6780 #endif /* HAVE_FREEBSD_SENDFILE */
6781 }
6782 
6783 
6784 void
6786 {
6787 #ifdef HTTPS_SUPPORT
6788  gnutls_global_deinit ();
6789 #endif /* HTTPS_SUPPORT */
6790 #if defined(_WIN32) && ! defined(__CYGWIN__)
6791  if (mhd_winsock_inited_)
6792  WSACleanup();
6793 #endif
6795 }
6796 
6797 #ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
6799 #endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
6800 
6801 /* end of daemon.c */
bool thread_joined
Definition: internal.h:875
unsigned int per_ip_connection_limit
Definition: internal.h:1564
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
void * unescape_callback_cls
Definition: internal.h:1392
volatile int global_init_count
Definition: daemon.c:183
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2929
_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:5238
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:448
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:4630
_MHD_EXTERN const char * MHD_get_version(void)
Definition: daemon.c:6506
#define EXTRA_SLOTS
#define DLL_insert(head, tail, element)
Definition: internal.h:1710
bool data_already_pending
Definition: internal.h:1542
socklen_t addr_len
Definition: internal.h:826
void * socket_context
Definition: internal.h:692
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1220
enum MHD_CONNECTION_STATE state
Definition: internal.h:899
void * data
Definition: microhttpd.h:2661
#define NULL
Definition: reason_phrase.c:31
static int call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1093
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:904
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:4602
#define MHD_ITC_IS_INVALID_(itc)
Definition: mhd_itc.h:359
MHD_thread_handle_ID_ pid
Definition: internal.h:1445
time_t connection_timeout
Definition: internal.h:1558
Methods for managing connections.
_MHD_EXTERN int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3126
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:936
#define MHD_YES
Definition: microhttpd.h:134
_MHD_EXTERN int MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:2846
struct MHD_Response * response
Definition: internal.h:665
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1320
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
Definition: daemon.c:4416
Header for platform missing functions.
volatile bool was_quiesced
Definition: internal.h:1517
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:898
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:66
MHD_thread_handle_ID_ pid
Definition: internal.h:758
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:128
static int internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: daemon.c:878
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1238
int MHD_socket
Definition: microhttpd.h:181
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:264
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2648
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:4455
_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:4486
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:118
#define EDLL_insert(head, tail, element)
Definition: internal.h:1799
intptr_t value
Definition: microhttpd.h:1502
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:4655
platform-specific includes for libmicrohttpd
#define MHD_strerror_(errnum)
Definition: mhd_compat.h:44
#define MHD_itc_destroy_chk_(itc)
Definition: mhd_itc.h:345
static int internal_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
Definition: daemon.c:3215
Methods for managing response objects.
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: daemon.c:6491
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2784
void MHD_fini(void)
Definition: daemon.c:6785
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1382
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:216
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:1866
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
Definition: microhttpd.h:1158
struct MHD_Daemon * daemon
Definition: internal.h:650
int listening_address_reuse
Definition: internal.h:1472
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1450
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1328
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1363
struct MHD_Connection * cleanup_head
Definition: internal.h:1268
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:633
#define XDLL_remove(head, tail, element)
Definition: internal.h:1776
void MHD_init(void)
Definition: daemon.c:6741
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
bool client_aware
Definition: internal.h:850
#define XDLL_insert(head, tail, element)
Definition: internal.h:1755
int strict_for_client
Definition: internal.h:1579
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:398
MHD_socket MHD_socket_create_listen_(int use_ipv6)
Definition: mhd_sockets.c:471
struct MHD_Connection * cleanup_tail
Definition: internal.h:1273
Header for platform-independent inter-thread communication.
struct MHD_Connection * prev
Definition: internal.h:631
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:292
#define MHD_VERSION
Definition: microhttpd.h:129
struct MHD_Daemon * worker_pool
Definition: internal.h:1415
void * mhd_panic_cls
Definition: daemon.c:157
size_t read_buffer_size
Definition: internal.h:766
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:156
int fd
Definition: microhttpd.h:2771
void * client_context
Definition: internal.h:683
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:6272
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1335
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:311
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:857
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3370
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:74
void MHD_set_https_callbacks(struct MHD_Connection *connection)
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:208
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: mhd_sockets.c:374
unsigned int connection_limit
Definition: internal.h:1552
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
unsigned int worker_pool_size
Definition: internal.h:1440
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
enum MHD_FLAG options
Definition: internal.h:1569
_MHD_EXTERN int MHD_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
Definition: daemon.c:3319
LogCallback uri_log_callback
Definition: internal.h:1377
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2820
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:323
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1069
time_t connection_timeout
Definition: internal.h:838
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
Definition: daemon.c:1733
#define _MHD_EXTERN
Definition: mhd_options.h:51
static int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:362
Methods for managing connections.
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
uint16_t port
Definition: internal.h:1574
unsigned int connections
Definition: internal.h:1547
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1313
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:95
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:428
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:439
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:63
size_t thread_stack_size
Definition: internal.h:1435
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:162
limits values definitions
MHD_FEATURE
Definition: microhttpd.h:3333
Header for platform-independent threads abstraction.
void MHD_monotonic_sec_counter_init(void)
internal shared structures
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
UnescapeCallback unescape_callback
Definition: internal.h:1387
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2559
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:603
internal monotonic clock functions implementations
unsigned int listen_backlog_size
Definition: internal.h:1698
#define TIME_T_MAX
Definition: mhd_limits.h:132
struct MHD_Connection * connections_head
Definition: internal.h:1248
struct MHD_Daemon * master
Definition: internal.h:1410
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
size_t pool_size
Definition: internal.h:1425
struct MHD_Connection * next
Definition: internal.h:626
#define ULLONG_MAX
Definition: mhd_limits.h:58
struct MHD_itc_ itc
Definition: internal.h:1505
MHD_AcceptPolicyCallback apc
Definition: internal.h:1341
time_t last_activity
Definition: internal.h:832
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1206
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3240
static int resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2709
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:525
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck)
Definition: daemon.c:2168
int(* MHD_AccessHandlerCallback)(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
Definition: microhttpd.h:1925
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3830
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3024
bool sk_nonblck
Definition: internal.h:862
struct MemoryPool * pool
Definition: internal.h:675
static int MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:2896
_MHD_EXTERN int MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
Definition: daemon.c:629
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:276
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:156
void * ptr_value
Definition: microhttpd.h:1508
#define MHD_PANIC(msg)
Definition: internal.h:65
time_t MHD_monotonic_sec_counter(void)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Definition: microhttpd.h:1948
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:645
void MHD_check_global_init_(void)
Definition: daemon.c:195
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1352
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
struct MHD_Connection * prevX
Definition: internal.h:645
bool resuming
Definition: internal.h:1531
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:4373
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3792
#define DLL_remove(head, tail, element)
Definition: internal.h:1731
void * notify_completed_cls
Definition: internal.h:1357
MHD_socket listen_fd
Definition: internal.h:1461
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:102
#define EDLL_remove(head, tail, element)
Definition: internal.h:1818
_MHD_EXTERN int MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:4338
MHD_OPTION
MHD options.
Definition: microhttpd.h:1168
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:140
void * notify_connection_cls
Definition: internal.h:1368
void * apc_cls
Definition: internal.h:1346
bool at_limit
Definition: internal.h:1526
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
struct sockaddr * addr
Definition: internal.h:752
MHD_PanicCallback mhd_panic
Definition: daemon.c:152
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1263
MHD_DaemonInfoType
Definition: microhttpd.h:1801
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2677
bool suspended
Definition: internal.h:987
void * per_ip_connection_count
Definition: internal.h:1420
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:6540
size_t read_buffer_offset
Definition: internal.h:772
_MHD_EXTERN int MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: daemon.c:1027
void * default_handler_cls
Definition: internal.h:1243
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1510
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1456
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:4531
Header for platform-independent locks abstraction.
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:1880
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:1974
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:6427
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:136
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:6124
struct MHD_Connection * connections_tail
Definition: internal.h:1253
enum MHD_OPTION option
Definition: microhttpd.h:1495
void MHD_monotonic_sec_counter_finish(void)
#define MHD_BUF_INC_SIZE
Definition: internal.h:100
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition: internal.h:207
#define SIZE_MAX
Definition: mhd_limits.h:99
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:882
size_t pool_increment
Definition: internal.h:1430
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1258
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...