GNU libmicrohttpd  0.9.62
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
daemon.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
28 #include "platform.h"
29 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
30 #include "mhd_threads.h"
31 #endif
32 #include "internal.h"
33 #include "response.h"
34 #include "connection.h"
35 #include "memorypool.h"
36 #include "mhd_limits.h"
37 #include "autoinit_funcs.h"
38 #include "mhd_mono_clock.h"
39 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
40 #include "mhd_locks.h"
41 #endif
42 #include "mhd_sockets.h"
43 #include "mhd_itc.h"
44 #include "mhd_compat.h"
45 
46 #if HAVE_SEARCH_H
47 #include <search.h>
48 #else
49 #include "tsearch.h"
50 #endif
51 
52 #ifdef HTTPS_SUPPORT
53 #include "connection_https.h"
54 #ifdef MHD_HTTPS_REQUIRE_GRYPT
55 #include <gcrypt.h>
56 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
57 #endif /* HTTPS_SUPPORT */
58 
59 #if defined(_WIN32) && ! defined(__CYGWIN__)
60 #ifndef WIN32_LEAN_AND_MEAN
61 #define WIN32_LEAN_AND_MEAN 1
62 #endif /* !WIN32_LEAN_AND_MEAN */
63 #include <windows.h>
64 #endif
65 
69 #ifdef MHD_POSIX_SOCKETS
70 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
71 #else
72 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
73 #endif
74 
78 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
79 
84 #define DEBUG_CLOSE MHD_NO
85 
90 #define DEBUG_CONNECT MHD_NO
91 
92 
93 /* Forward declarations. */
94 
103 static void
105 
106 #ifdef EPOLL_SUPPORT
107 
116 static int
117 MHD_epoll (struct MHD_Daemon *daemon,
118  int may_block);
119 
120 #endif /* EPOLL_SUPPORT */
121 
131 static void
132 mhd_panic_std (void *cls,
133  const char *file,
134  unsigned int line,
135  const char *reason)
136 {
137  (void)cls; /* Mute compiler warning. */
138 #ifdef HAVE_MESSAGES
139  fprintf (stderr,
140  _("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
141  file,
142  line,
143  reason);
144 #else /* ! HAVE_MESSAGES */
145  (void)file; /* Mute compiler warning. */
146  (void)line; /* Mute compiler warning. */
147  (void)reason; /* Mute compiler warning. */
148 #endif
149  abort ();
150 }
151 
152 
157 
162 
166 void
167 MHD_init(void);
168 
169 
170 #if defined(_WIN32) && ! defined(__CYGWIN__)
171 
174 static int mhd_winsock_inited_ = 0;
175 #endif
176 
177 #ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
178 
182 #define MHD_check_global_init_() (void)0
183 #else /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
184 
187 volatile int global_init_count = 0;
188 
189 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
190 #ifdef MHD_MUTEX_STATIC_DEFN_INIT_
191 
194 MHD_MUTEX_STATIC_DEFN_INIT_(global_init_mutex_);
195 #endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
196 #endif
197 
198 
203 void
205 {
206 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
207 #ifdef MHD_MUTEX_STATIC_DEFN_INIT_
208  MHD_mutex_lock_chk_(&global_init_mutex_);
209 #endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
210 #endif
211  if (0 == global_init_count++)
212  MHD_init ();
213 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
214 #ifdef MHD_MUTEX_STATIC_DEFN_INIT_
215  MHD_mutex_unlock_chk_(&global_init_mutex_);
216 #endif /* MHD_MUTEX_STATIC_DEFN_INIT_ */
217 #endif
218 }
219 #endif /* ! _AUTOINIT_FUNCS_ARE_SUPPORTED */
220 
228 static struct MHD_Daemon*
230 {
231  while (NULL != daemon->master)
232  daemon = daemon->master;
233  return daemon;
234 }
235 
236 
240 struct MHD_IPCount
241 {
245  int family;
246 
250  union
251  {
255  struct in_addr ipv4;
256 #if HAVE_INET6
257 
260  struct in6_addr ipv6;
261 #endif
262  } addr;
263 
267  unsigned int count;
268 };
269 
270 
276 static void
278 {
279 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
281 #else
282  (void) daemon;
283 #endif
284 }
285 
286 
292 static void
294 {
295 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
297 #else
298  (void) daemon;
299 #endif
300 }
301 
302 
312 static int
313 MHD_ip_addr_compare (const void *a1,
314  const void *a2)
315 {
316  return memcmp (a1,
317  a2,
318  offsetof (struct MHD_IPCount,
319  count));
320 }
321 
322 
331 static int
332 MHD_ip_addr_to_key (const struct sockaddr *addr,
333  socklen_t addrlen,
334  struct MHD_IPCount *key)
335 {
336  memset(key,
337  0,
338  sizeof(*key));
339 
340  /* IPv4 addresses */
341  if (sizeof (struct sockaddr_in) == addrlen)
342  {
343  const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
344 
345  key->family = AF_INET;
346  memcpy (&key->addr.ipv4,
347  &addr4->sin_addr,
348  sizeof(addr4->sin_addr));
349  return MHD_YES;
350  }
351 
352 #if HAVE_INET6
353  /* IPv6 addresses */
354  if (sizeof (struct sockaddr_in6) == addrlen)
355  {
356  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
357 
358  key->family = AF_INET6;
359  memcpy (&key->addr.ipv6,
360  &addr6->sin6_addr,
361  sizeof(addr6->sin6_addr));
362  return MHD_YES;
363  }
364 #endif
365 
366  /* Some other address */
367  return MHD_NO;
368 }
369 
370 
382 static int
384  const struct sockaddr *addr,
385  socklen_t addrlen)
386 {
387  struct MHD_IPCount *key;
388  void **nodep;
389  void *node;
390  int result;
391 
392  daemon = MHD_get_master (daemon);
393  /* Ignore if no connection limit assigned */
394  if (0 == daemon->per_ip_connection_limit)
395  return MHD_YES;
396 
397  if (NULL == (key = malloc (sizeof(*key))))
398  return MHD_NO;
399 
400  /* Initialize key */
401  if (MHD_NO == MHD_ip_addr_to_key (addr,
402  addrlen,
403  key))
404  {
405  /* Allow unhandled address types through */
406  free (key);
407  return MHD_YES;
408  }
409  MHD_ip_count_lock (daemon);
410 
411  /* Search for the IP address */
412  if (NULL == (nodep = tsearch (key,
413  &daemon->per_ip_connection_count,
415  {
416 #ifdef HAVE_MESSAGES
417  MHD_DLOG (daemon,
418  _("Failed to add IP connection count node\n"));
419 #endif
420  MHD_ip_count_unlock (daemon);
421  free (key);
422  return MHD_NO;
423  }
424  node = *nodep;
425  /* If we got an existing node back, free the one we created */
426  if (node != key)
427  free(key);
428  key = (struct MHD_IPCount *) node;
429  /* Test if there is room for another connection; if so,
430  * increment count */
431  result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
432  if (MHD_YES == result)
433  ++key->count;
434 
435  MHD_ip_count_unlock (daemon);
436  return result;
437 }
438 
439 
448 static void
450  const struct sockaddr *addr,
451  socklen_t addrlen)
452 {
453  struct MHD_IPCount search_key;
454  struct MHD_IPCount *found_key;
455  void **nodep;
456 
457  daemon = MHD_get_master (daemon);
458  /* Ignore if no connection limit assigned */
459  if (0 == daemon->per_ip_connection_limit)
460  return;
461  /* Initialize search key */
462  if (MHD_NO == MHD_ip_addr_to_key (addr,
463  addrlen,
464  &search_key))
465  return;
466 
467  MHD_ip_count_lock (daemon);
468 
469  /* Search for the IP address */
470  if (NULL == (nodep = tfind (&search_key,
471  &daemon->per_ip_connection_count,
473  {
474  /* Something's wrong if we couldn't find an IP address
475  * that was previously added */
476  MHD_PANIC (_("Failed to find previously-added IP address\n"));
477  }
478  found_key = (struct MHD_IPCount *) *nodep;
479  /* Validate existing count for IP address */
480  if (0 == found_key->count)
481  {
482  MHD_PANIC (_("Previously-added IP address had counter of zero\n"));
483  }
484  /* Remove the node entirely if count reduces to 0 */
485  if (0 == --found_key->count)
486  {
487  tdelete (found_key,
488  &daemon->per_ip_connection_count,
490  free (found_key);
491  }
492 
493  MHD_ip_count_unlock (daemon);
494 }
495 
496 
497 #ifdef HTTPS_SUPPORT
498 
504 static int
505 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
506 {
507  gnutls_datum_t key;
508  gnutls_datum_t cert;
509  int ret;
510 
511 #if GNUTLS_VERSION_MAJOR >= 3
512  if (NULL != daemon->cert_callback)
513  {
514  gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
515  daemon->cert_callback);
516  }
517 #endif
518  if (NULL != daemon->https_mem_trust)
519  {
520  cert.data = (unsigned char *) daemon->https_mem_trust;
521  cert.size = strlen (daemon->https_mem_trust);
522  if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
523  &cert,
524  GNUTLS_X509_FMT_PEM) < 0)
525  {
526 #ifdef HAVE_MESSAGES
527  MHD_DLOG(daemon,
528  "Bad trust certificate format\n");
529 #endif
530  return -1;
531  }
532  }
533 
534  if (daemon->have_dhparams)
535  {
536  gnutls_certificate_set_dh_params (daemon->x509_cred,
537  daemon->https_mem_dhparams);
538  }
539  /* certificate & key loaded from memory */
540  if ( (NULL != daemon->https_mem_cert) &&
541  (NULL != daemon->https_mem_key) )
542  {
543  key.data = (unsigned char *) daemon->https_mem_key;
544  key.size = strlen (daemon->https_mem_key);
545  cert.data = (unsigned char *) daemon->https_mem_cert;
546  cert.size = strlen (daemon->https_mem_cert);
547 
548  if (NULL != daemon->https_key_password) {
549 #if GNUTLS_VERSION_NUMBER >= 0x030111
550  ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
551  &cert,
552  &key,
553  GNUTLS_X509_FMT_PEM,
554  daemon->https_key_password,
555  0);
556 #else
557 #ifdef HAVE_MESSAGES
558  MHD_DLOG (daemon,
559  _("Failed to setup x509 certificate/key: pre 3.X.X version " \
560  "of GnuTLS does not support setting key password"));
561 #endif
562  return -1;
563 #endif
564  }
565  else
566  ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
567  &cert,
568  &key,
569  GNUTLS_X509_FMT_PEM);
570 #ifdef HAVE_MESSAGES
571  if (0 != ret)
572  MHD_DLOG (daemon,
573  "GnuTLS failed to setup x509 certificate/key: %s\n",
574  gnutls_strerror (ret));
575 #endif
576  return ret;
577  }
578 #if GNUTLS_VERSION_MAJOR >= 3
579  if (NULL != daemon->cert_callback)
580  return 0;
581 #endif
582 #ifdef HAVE_MESSAGES
583  MHD_DLOG (daemon,
584  "You need to specify a certificate and key location\n");
585 #endif
586  return -1;
587 }
588 
595 static int
596 MHD_TLS_init (struct MHD_Daemon *daemon)
597 {
598  switch (daemon->cred_type)
599  {
600  case GNUTLS_CRD_CERTIFICATE:
601  if (0 !=
602  gnutls_certificate_allocate_credentials (&daemon->x509_cred))
603  return GNUTLS_E_MEMORY_ERROR;
604  return MHD_init_daemon_certificate (daemon);
605  case GNUTLS_CRD_PSK:
606  if (0 !=
607  gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
608  return GNUTLS_E_MEMORY_ERROR;
609  return 0;
610  default:
611 #ifdef HAVE_MESSAGES
612  MHD_DLOG (daemon,
613  _("Error: invalid credentials type %d specified.\n"),
614  daemon->cred_type);
615 #endif
616  return -1;
617  }
618 }
619 #endif /* HTTPS_SUPPORT */
620 
621 
622 #undef MHD_get_fdset
623 
653 int
654 MHD_get_fdset (struct MHD_Daemon *daemon,
655  fd_set *read_fd_set,
656  fd_set *write_fd_set,
657  fd_set *except_fd_set,
658  MHD_socket *max_fd)
659 {
660  return MHD_get_fdset2 (daemon,
661  read_fd_set,
662  write_fd_set,
663  except_fd_set,
664  max_fd,
666 }
667 
668 
669 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
670 
682 static bool
683 urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
684  fd_set *rs,
685  fd_set *ws,
686  fd_set *es,
687  MHD_socket *max_fd,
688  unsigned int fd_setsize)
689 {
690  const MHD_socket conn_sckt = urh->connection->socket_fd;
691  const MHD_socket mhd_sckt = urh->mhd.socket;
692  bool res = true;
693 
694  /* Do not add to 'es' only if socket is closed
695  * or not used anymore. */
696  if (MHD_INVALID_SOCKET != conn_sckt)
697  {
698  if ( (urh->in_buffer_used < urh->in_buffer_size) &&
699  (! MHD_add_to_fd_set_ (conn_sckt,
700  rs,
701  max_fd,
702  fd_setsize)) )
703  res = false;
704  if ( (0 != urh->out_buffer_used) &&
705  (! MHD_add_to_fd_set_ (conn_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->app.celi & MHD_EPOLL_STATE_ERROR)) &&
713  ((0 != urh->in_buffer_size) ||
714  (0 != urh->out_buffer_size) ||
715  (0 != urh->out_buffer_used)))
716  MHD_add_to_fd_set_ (conn_sckt,
717  es,
718  max_fd,
719  fd_setsize);
720  }
721  if (MHD_INVALID_SOCKET != mhd_sckt)
722  {
723  if ( (urh->out_buffer_used < urh->out_buffer_size) &&
724  (! MHD_add_to_fd_set_ (mhd_sckt,
725  rs,
726  max_fd,
727  fd_setsize)) )
728  res = false;
729  if ( (0 != urh->in_buffer_used) &&
730  (! MHD_add_to_fd_set_ (mhd_sckt,
731  ws,
732  max_fd,
733  fd_setsize)) )
734  res = false;
735  /* Do not monitor again for errors if error was detected before as
736  * error state is remembered. */
737  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
738  ((0 != urh->out_buffer_size) ||
739  (0 != urh->in_buffer_size) ||
740  (0 != urh->in_buffer_used)))
741  MHD_add_to_fd_set_ (mhd_sckt,
742  es,
743  max_fd,
744  fd_setsize);
745  }
746 
747  return res;
748 }
749 
750 
760 static void
761 urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
762  const fd_set *rs,
763  const fd_set *ws,
764  const fd_set *es)
765 {
766  const MHD_socket conn_sckt = urh->connection->socket_fd;
767  const MHD_socket mhd_sckt = urh->mhd.socket;
768 
769  /* Reset read/write ready, preserve error state. */
772 
773  if (MHD_INVALID_SOCKET != conn_sckt)
774  {
775  if (FD_ISSET (conn_sckt, rs))
776  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
777  if (FD_ISSET (conn_sckt, ws))
778  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
779  if (FD_ISSET (conn_sckt, es))
780  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
781  }
782  if ((MHD_INVALID_SOCKET != mhd_sckt))
783  {
784  if (FD_ISSET (mhd_sckt, rs))
785  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
786  if (FD_ISSET (mhd_sckt, ws))
787  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
788  if (FD_ISSET (mhd_sckt, es))
789  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
790  }
791 }
792 
793 #ifdef HAVE_POLL
794 
803 static void
804 urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
805  struct pollfd p[2])
806 {
807  p[0].events = 0;
808  p[1].events = 0;
809 
810  if (urh->in_buffer_used < urh->in_buffer_size)
811  p[0].events |= POLLIN;
812  if (0 != urh->out_buffer_used)
813  p[0].events |= POLLOUT;
814 
815  /* Do not monitor again for errors if error was detected before as
816  * error state is remembered. */
817  if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
818  ((0 != urh->in_buffer_size) ||
819  (0 != urh->out_buffer_size) ||
820  (0 != urh->out_buffer_used)))
821  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
822 
823  if (urh->out_buffer_used < urh->out_buffer_size)
824  p[1].events |= POLLIN;
825  if (0 != urh->in_buffer_used)
826  p[1].events |= POLLOUT;
827 
828  /* Do not monitor again for errors if error was detected before as
829  * error state is remembered. */
830  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
831  ((0 != urh->out_buffer_size) ||
832  (0 != urh->in_buffer_size) ||
833  (0 != urh->in_buffer_used)))
834  p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
835 }
836 
837 
844 static void
845 urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
846  struct pollfd p[2])
847 {
848  p[0].fd = urh->connection->socket_fd;
849  p[1].fd = urh->mhd.socket;
850  urh_update_pollfd (urh,
851  p);
852 }
853 
854 
860 static void
861 urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
862  struct pollfd p[2])
863 {
864  /* Reset read/write ready, preserve error state. */
867 
868  if (0 != (p[0].revents & POLLIN))
869  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
870  if (0 != (p[0].revents & POLLOUT))
871  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
872  if (0 != (p[0].revents & POLLHUP))
874  if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
875  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
876  if (0 != (p[1].revents & POLLIN))
877  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
878  if (0 != (p[1].revents & POLLOUT))
879  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
880  if (0 != (p[1].revents & POLLHUP))
881  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
882  if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
884 }
885 #endif /* HAVE_POLL */
886 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
887 
888 
903 static int
905  fd_set *read_fd_set,
906  fd_set *write_fd_set,
907  fd_set *except_fd_set,
908  MHD_socket *max_fd,
909  unsigned int fd_setsize)
910 
911 {
912  struct MHD_Connection *pos;
913  struct MHD_Connection *posn;
914  int result = MHD_YES;
915  MHD_socket ls;
916 
917  if (daemon->shutdown)
918  return MHD_NO;
919 
920  ls = daemon->listen_fd;
921  if ( (MHD_INVALID_SOCKET != ls) &&
922  (! daemon->was_quiesced) &&
923  (! MHD_add_to_fd_set_ (ls,
924  read_fd_set,
925  max_fd,
926  fd_setsize)) )
927  result = MHD_NO;
928 
929  /* Add all sockets to 'except_fd_set' as well to watch for
930  * out-of-band data. However, ignore errors if INFO_READ
931  * or INFO_WRITE sockets will not fit 'except_fd_set'. */
932  /* Start from oldest connections. Make sense for W32 FDSETs. */
933  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
934  {
935  posn = pos->prev;
936 
937  switch (pos->event_loop_info)
938  {
940  if (! MHD_add_to_fd_set_ (pos->socket_fd,
941  read_fd_set,
942  max_fd,
943  fd_setsize))
944  result = MHD_NO;
945 #ifdef MHD_POSIX_SOCKETS
947  except_fd_set,
948  max_fd,
949  fd_setsize);
950 #endif /* MHD_POSIX_SOCKETS */
951  break;
953  if (! MHD_add_to_fd_set_ (pos->socket_fd,
954  write_fd_set,
955  max_fd,
956  fd_setsize))
957  result = MHD_NO;
958 #ifdef MHD_POSIX_SOCKETS
960  except_fd_set,
961  max_fd,
962  fd_setsize);
963 #endif /* MHD_POSIX_SOCKETS */
964  break;
966  if ( (NULL == except_fd_set) ||
968  except_fd_set,
969  max_fd,
970  fd_setsize))
971  result = MHD_NO;
972  break;
974  /* this should never happen */
975  break;
976  }
977  }
978 #ifdef MHD_WINSOCK_SOCKETS
979  /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
980  * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
981  * not be pushed out. */
982  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
983  {
984  posn = pos->prev;
986  except_fd_set,
987  max_fd,
988  fd_setsize);
989  }
990 #endif /* MHD_WINSOCK_SOCKETS */
991 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
992  {
993  struct MHD_UpgradeResponseHandle *urh;
994 
995  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
996  {
997  if (MHD_NO ==
998  urh_to_fdset (urh,
999  read_fd_set,
1000  write_fd_set,
1001  except_fd_set,
1002  max_fd,
1003  fd_setsize))
1004  result = MHD_NO;
1005  }
1006  }
1007 #endif
1008 #if DEBUG_CONNECT
1009 #ifdef HAVE_MESSAGES
1010  if (NULL != max_fd)
1011  MHD_DLOG (daemon,
1012  _("Maximum socket in select set: %d\n"),
1013  *max_fd);
1014 #endif
1015 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1016  return result;
1017 }
1018 
1019 
1052 int
1053 MHD_get_fdset2 (struct MHD_Daemon *daemon,
1054  fd_set *read_fd_set,
1055  fd_set *write_fd_set,
1056  fd_set *except_fd_set,
1057  MHD_socket *max_fd,
1058  unsigned int fd_setsize)
1059 {
1060  fd_set es;
1061 
1062  if ( (NULL == daemon) ||
1063  (NULL == read_fd_set) ||
1064  (NULL == write_fd_set) ||
1065  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ||
1066  (0 != (daemon->options & MHD_USE_POLL)))
1067  return MHD_NO;
1068 
1069  if (NULL == except_fd_set)
1070  { /* Workaround to maintain backward compatibility. */
1071 #ifdef HAVE_MESSAGES
1072  MHD_DLOG (daemon,
1073  _("MHD_get_fdset2() called with except_fd_set "
1074  "set to NULL. Such behavior is unsupported.\n"));
1075 #endif
1076  FD_ZERO (&es);
1077  except_fd_set = &es;
1078  }
1079 
1080 #ifdef EPOLL_SUPPORT
1081  if (0 != (daemon->options & MHD_USE_EPOLL))
1082  {
1083  if (daemon->shutdown)
1084  return MHD_NO;
1085 
1086  /* we're in epoll mode, use the epoll FD as a stand-in for
1087  the entire event set */
1088 
1089  return MHD_add_to_fd_set_ (daemon->epoll_fd,
1090  read_fd_set,
1091  max_fd,
1092  fd_setsize) ? MHD_YES : MHD_NO;
1093  }
1094 #endif
1095 
1096  return internal_get_fdset2 (daemon,
1097  read_fd_set,
1098  write_fd_set,
1099  except_fd_set,
1100  max_fd,
1101  fd_setsize);
1102 }
1103 
1104 
1118 static int
1120  bool read_ready,
1121  bool write_ready,
1122  bool force_close)
1123 {
1124  int ret;
1125  bool states_info_processed = false;
1126  /* Fast track flag */
1127  bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1128 
1129 #ifdef HTTPS_SUPPORT
1130  if (con->tls_read_ready)
1131  read_ready = true;
1132 #endif /* HTTPS_SUPPORT */
1133  if (!force_close)
1134  {
1135  if ( (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) &&
1136  read_ready)
1137  {
1139  ret = MHD_connection_handle_idle (con);
1140  states_info_processed = true;
1141  }
1142  /* No need to check value of 'ret' here as closed connection
1143  * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1144  if ( (MHD_EVENT_LOOP_INFO_WRITE == con->event_loop_info) &&
1145  write_ready)
1146  {
1148  ret = MHD_connection_handle_idle (con);
1149  states_info_processed = true;
1150  }
1151  }
1152  else
1153  {
1154  MHD_connection_close_ (con,
1156  return MHD_connection_handle_idle (con);
1157  }
1158 
1159  if (!states_info_processed)
1160  { /* Connection is not read or write ready, but external conditions
1161  * may be changed and need to be processed. */
1162  ret = MHD_connection_handle_idle (con);
1163  }
1164  /* Fast track for fast connections. */
1165  /* If full request was read by single read_handler() invocation
1166  and headers were completely prepared by single MHD_connection_handle_idle()
1167  then try not to wait for next sockets polling and send response
1168  immediately.
1169  As writeability of socket was not checked and it may have
1170  some data pending in system buffers, use this optimization
1171  only for non-blocking sockets. */
1172  /* No need to check 'ret' as connection is always in
1173  * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1174  else if (on_fasttrack && con->sk_nonblck)
1175  {
1177  {
1179  /* Always call 'MHD_connection_handle_idle()' after each read/write. */
1180  ret = MHD_connection_handle_idle (con);
1181  }
1182  /* If all headers were sent by single write_handler() and
1183  * response body is prepared by single MHD_connection_handle_idle()
1184  * call - continue. */
1185  if ((MHD_CONNECTION_NORMAL_BODY_READY == con->state) ||
1187  {
1189  ret = MHD_connection_handle_idle (con);
1190  }
1191  }
1192 
1193  /* All connection's data and states are processed for this turn.
1194  * If connection already has more data to be processed - use
1195  * zero timeout for next select()/poll(). */
1196  /* Thread-per-connection do not need global zero timeout as
1197  * connections are processed individually. */
1198  /* Note: no need to check for read buffer availability for
1199  * TLS read-ready connection in 'read info' state as connection
1200  * without space in read buffer will be market as 'info block'. */
1201  if ( (! con->daemon->data_already_pending) &&
1202  (0 == (con->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1203  {
1205  con->daemon->data_already_pending = true;
1206 #ifdef HTTPS_SUPPORT
1207  else if ( (con->tls_read_ready) &&
1209  con->daemon->data_already_pending = true;
1210 #endif /* HTTPS_SUPPORT */
1211  }
1212  return ret;
1213 }
1214 
1215 
1216 #ifdef UPGRADE_SUPPORT
1217 
1224 static void
1225 cleanup_upgraded_connection (struct MHD_Connection *connection)
1226 {
1227  struct MHD_UpgradeResponseHandle *urh = connection->urh;
1228 
1229  if (NULL == urh)
1230  return;
1231 #ifdef HTTPS_SUPPORT
1232  /* Signal remote client the end of TLS connection by
1233  * gracefully closing TLS session. */
1234  if (0 != (connection->daemon->options & MHD_USE_TLS))
1235  gnutls_bye (connection->tls_session,
1236  GNUTLS_SHUT_WR);
1237 
1238  if (MHD_INVALID_SOCKET != urh->mhd.socket)
1239  MHD_socket_close_chk_ (urh->mhd.socket);
1240 
1241  if (MHD_INVALID_SOCKET != urh->app.socket)
1242  MHD_socket_close_chk_ (urh->app.socket);
1243 #endif /* HTTPS_SUPPORT */
1244  connection->urh = NULL;
1245  free (urh);
1246 }
1247 #endif /* UPGRADE_SUPPORT */
1248 
1249 
1250 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1251 
1259 static void
1260 process_urh (struct MHD_UpgradeResponseHandle *urh)
1261 {
1262  /* Help compiler to optimize:
1263  * pointers to 'connection' and 'daemon' are not changed
1264  * during this processing, so no need to chain dereference
1265  * each time. */
1266  struct MHD_Connection * const connection = urh->connection;
1267  struct MHD_Daemon * const daemon = connection->daemon;
1268  /* Prevent data races: use same value of 'was_closed' throughout
1269  * this function. If 'was_closed' changed externally in the middle
1270  * of processing - it will be processed on next iteration. */
1271  bool was_closed;
1272  if (daemon->shutdown)
1273  {
1274  /* Daemon shutting down, application will not receive any more data. */
1275 #ifdef HAVE_MESSAGES
1276  if (! urh->was_closed)
1277  {
1278  MHD_DLOG (daemon,
1279  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1280  }
1281 #endif
1282  urh->was_closed = true;
1283  }
1284  was_closed = urh->was_closed;
1285  if (was_closed)
1286  {
1287  /* Application was closed connections: no more data
1288  * can be forwarded to application socket. */
1289  if (0 < urh->in_buffer_used)
1290  {
1291 #ifdef HAVE_MESSAGES
1292  MHD_DLOG (daemon,
1293  _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1294  " bytes of data received from remote side: application shut down socket\n"),
1295  (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used);
1296 #endif
1297 
1298  }
1299  /* If application signaled MHD about socket closure then
1300  * check for any pending data even if socket is not marked
1301  * as 'ready' (signal may arrive after poll()/select()).
1302  * Socketpair for forwarding is always in non-blocking mode
1303  * so no risk that recv() will block the thread. */
1304  if (0 != urh->out_buffer_size)
1305  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1306  /* Discard any data received form remote. */
1307  urh->in_buffer_used = 0;
1308  /* Do not try to push data to application. */
1309  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1310  /* Reading from remote client is not required anymore. */
1311  urh->in_buffer_size = 0;
1312  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1313  connection->tls_read_ready = false;
1314  }
1315 
1316  /* On some platforms (W32, possibly Darwin) failed send() (send() will always
1317  * fail after remote disconnect was detected) may discard data in system
1318  * buffers received by system but not yet read by recv().
1319  * So, before trying send() on any socket, recv() must be performed at first
1320  * otherwise last part of incoming data may be lost. */
1321 
1322  /* If disconnect or error was detected - try to read from socket
1323  * to dry data possibly pending is system buffers. */
1324  if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1325  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1326  if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1327  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1328 
1329  /*
1330  * handle reading from remote TLS client
1331  */
1332  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1333  (connection->tls_read_ready) ) &&
1334  (urh->in_buffer_used < urh->in_buffer_size) )
1335  {
1336  ssize_t res;
1337  size_t buf_size;
1338 
1339  buf_size = urh->in_buffer_size - urh->in_buffer_used;
1340  if (buf_size > SSIZE_MAX)
1341  buf_size = SSIZE_MAX;
1342 
1343  connection->tls_read_ready = false;
1344  res = gnutls_record_recv (connection->tls_session,
1345  &urh->in_buffer[urh->in_buffer_used],
1346  buf_size);
1347  if (0 >= res)
1348  {
1349  if (GNUTLS_E_INTERRUPTED != res)
1350  {
1351  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1352  if (GNUTLS_E_AGAIN != res)
1353  {
1354  /* Unrecoverable error on socket was detected or
1355  * socket was disconnected/shut down. */
1356  /* Stop trying to read from this TLS socket. */
1357  urh->in_buffer_size = 0;
1358  }
1359  }
1360  }
1361  else /* 0 < res */
1362  {
1363  urh->in_buffer_used += res;
1364  if (buf_size > (size_t)res)
1365  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1366  else if (0 < gnutls_record_check_pending (connection->tls_session))
1367  connection->tls_read_ready = true;
1368  }
1369  if (MHD_EPOLL_STATE_ERROR ==
1370  ((MHD_EPOLL_STATE_ERROR | MHD_EPOLL_STATE_READ_READY) & urh->app.celi))
1371  {
1372  /* Unrecoverable error on socket was detected and all
1373  * pending data was read from system buffers. */
1374  /* Stop trying to read from this TLS socket. */
1375  urh->in_buffer_size = 0;
1376  }
1377  }
1378 
1379  /*
1380  * handle reading from application
1381  */
1382  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1383  (urh->out_buffer_used < urh->out_buffer_size) )
1384  {
1385  ssize_t res;
1386  size_t buf_size;
1387 
1388  buf_size = urh->out_buffer_size - urh->out_buffer_used;
1389  if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1390  buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1391 
1392  res = MHD_recv_ (urh->mhd.socket,
1393  &urh->out_buffer[urh->out_buffer_used],
1394  buf_size);
1395  if (0 >= res)
1396  {
1397  const int err = MHD_socket_get_error_ ();
1398  if ((0 == res) ||
1399  ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1401  {
1402  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1403  if ((0 == res) ||
1404  (was_closed) ||
1405  (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1406  (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1407  {
1408  /* Socket disconnect/shutdown was detected;
1409  * Application signaled about closure of 'upgraded' socket;
1410  * or persistent / unrecoverable error. */
1411  /* Do not try to pull more data from application. */
1412  urh->out_buffer_size = 0;
1413  }
1414  }
1415  }
1416  else /* 0 < res */
1417  {
1418  urh->out_buffer_used += res;
1419  if (buf_size > (size_t)res)
1420  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1421  }
1422  if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1423  ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1424  (was_closed) ) )
1425  {
1426  /* Unrecoverable error on socket was detected and all
1427  * pending data was read from system buffers. */
1428  /* Do not try to pull more data from application. */
1429  urh->out_buffer_size = 0;
1430  }
1431  }
1432 
1433  /*
1434  * handle writing to remote HTTPS client
1435  */
1436  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1437  (urh->out_buffer_used > 0) )
1438  {
1439  ssize_t res;
1440  size_t data_size;
1441 
1442  data_size = urh->out_buffer_used;
1443  if (data_size > SSIZE_MAX)
1444  data_size = SSIZE_MAX;
1445 
1446  res = gnutls_record_send (connection->tls_session,
1447  urh->out_buffer,
1448  data_size);
1449  if (0 >= res)
1450  {
1451  if (GNUTLS_E_INTERRUPTED != res)
1452  {
1453  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1454  if (GNUTLS_E_INTERRUPTED != res)
1455  {
1456  /* TLS connection shut down or
1457  * persistent / unrecoverable error. */
1458 #ifdef HAVE_MESSAGES
1459  MHD_DLOG (daemon,
1460  _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1461  " bytes of data received from application: %s\n"),
1462  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1463  gnutls_strerror(res));
1464 #endif
1465  /* Discard any data unsent to remote. */
1466  urh->out_buffer_used = 0;
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  else /* 0 < res */
1474  {
1475  const size_t next_out_buffer_used = urh->out_buffer_used - res;
1476  if (0 != next_out_buffer_used)
1477  {
1478  memmove (urh->out_buffer,
1479  &urh->out_buffer[res],
1480  next_out_buffer_used);
1481  if (data_size > (size_t)res)
1482  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1483  }
1484  urh->out_buffer_used = next_out_buffer_used;
1485  }
1486  if ( (0 == urh->out_buffer_used) &&
1487  (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1488  {
1489  /* Unrecoverable error on socket was detected and all
1490  * pending data was sent to remote. */
1491  /* Do not try to send to remote anymore. */
1492  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1493  /* Do not try to pull more data from application. */
1494  urh->out_buffer_size = 0;
1495  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1496  }
1497  }
1498 
1499  /*
1500  * handle writing to application
1501  */
1502  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1503  (urh->in_buffer_used > 0) )
1504  {
1505  ssize_t res;
1506  size_t data_size;
1507 
1508  data_size = urh->in_buffer_used;
1509  if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1510  data_size = MHD_SCKT_SEND_MAX_SIZE_;
1511 
1512  res = MHD_send_ (urh->mhd.socket,
1513  urh->in_buffer,
1514  data_size);
1515  if (0 >= res)
1516  {
1517  const int err = MHD_socket_get_error_ ();
1518  if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1520  {
1521  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1522  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1523  {
1524  /* Socketpair connection shut down or
1525  * persistent / unrecoverable error. */
1526 #ifdef HAVE_MESSAGES
1527  MHD_DLOG (daemon,
1528  _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1529  " bytes of data received from remote side: %s\n"),
1530  (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1531  MHD_socket_strerr_ (err));
1532 #endif
1533  /* Discard any data received form remote. */
1534  urh->in_buffer_used = 0;
1535  /* Reading from remote client is not required anymore. */
1536  urh->in_buffer_size = 0;
1537  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1538  connection->tls_read_ready = false;
1539  }
1540  }
1541  }
1542  else /* 0 < res */
1543  {
1544  const size_t next_in_buffer_used = urh->in_buffer_used - res;
1545  if (0 != next_in_buffer_used)
1546  {
1547  memmove (urh->in_buffer,
1548  &urh->in_buffer[res],
1549  next_in_buffer_used);
1550  if (data_size > (size_t)res)
1551  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1552  }
1553  urh->in_buffer_used = next_in_buffer_used;
1554  }
1555  if ( (0 == urh->in_buffer_used) &&
1556  (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1557  {
1558  /* Do not try to push data to application. */
1559  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1560  /* Reading from remote client is not required anymore. */
1561  urh->in_buffer_size = 0;
1562  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1563  connection->tls_read_ready = false;
1564  }
1565  }
1566 
1567  /* Check whether data is present in TLS buffers
1568  * and incoming forward buffer have some space. */
1569  if ( (connection->tls_read_ready) &&
1570  (urh->in_buffer_used < urh->in_buffer_size) &&
1571  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1572  daemon->data_already_pending = true;
1573 
1574  if ( (daemon->shutdown) &&
1575  ( (0 != urh->out_buffer_size) ||
1576  (0 != urh->out_buffer_used) ) )
1577  {
1578  /* Daemon shutting down, discard any remaining forward data. */
1579 #ifdef HAVE_MESSAGES
1580  if (0 < urh->out_buffer_used)
1581  MHD_DLOG (daemon,
1582  _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1583  " bytes of data received from application: daemon shut down\n"),
1584  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
1585 #endif
1586  /* Discard any data unsent to remote. */
1587  urh->out_buffer_used = 0;
1588  /* Do not try to sent to remote anymore. */
1589  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1590  /* Do not try to pull more data from application. */
1591  urh->out_buffer_size = 0;
1592  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1593  }
1594 }
1595 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1596 
1597 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1598 #ifdef UPGRADE_SUPPORT
1599 
1607 static void
1608 thread_main_connection_upgrade (struct MHD_Connection *con)
1609 {
1610 #ifdef HTTPS_SUPPORT
1611  struct MHD_UpgradeResponseHandle *urh = con->urh;
1612  struct MHD_Daemon *daemon = con->daemon;
1613 
1614  /* Here, we need to bi-directionally forward
1615  until the application tells us that it is done
1616  with the socket; */
1617  if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1618  (0 == (daemon->options & MHD_USE_POLL)))
1619  {
1620  while ( (0 != urh->in_buffer_size) ||
1621  (0 != urh->out_buffer_size) ||
1622  (0 != urh->in_buffer_used) ||
1623  (0 != urh->out_buffer_used) )
1624  {
1625  /* use select */
1626  fd_set rs;
1627  fd_set ws;
1628  fd_set es;
1629  MHD_socket max_fd;
1630  int num_ready;
1631  bool result;
1632 
1633  FD_ZERO (&rs);
1634  FD_ZERO (&ws);
1635  FD_ZERO (&es);
1636  max_fd = MHD_INVALID_SOCKET;
1637  result = urh_to_fdset (urh,
1638  &rs,
1639  &ws,
1640  &es,
1641  &max_fd,
1642  FD_SETSIZE);
1643  if (! result)
1644  {
1645 #ifdef HAVE_MESSAGES
1646  MHD_DLOG (con->daemon,
1647  _("Error preparing select\n"));
1648 #endif
1649  break;
1650  }
1651  /* FIXME: does this check really needed? */
1652  if (MHD_INVALID_SOCKET != max_fd)
1653  {
1654  struct timeval* tvp;
1655  struct timeval tv;
1656  if ( (con->tls_read_ready) &&
1657  (urh->in_buffer_used < urh->in_buffer_size))
1658  { /* No need to wait if incoming data is already pending in TLS buffers. */
1659  tv.tv_sec = 0;
1660  tv.tv_usec = 0;
1661  tvp = &tv;
1662  }
1663  else
1664  tvp = NULL;
1665  num_ready = MHD_SYS_select_ (max_fd + 1,
1666  &rs,
1667  &ws,
1668  &es,
1669  tvp);
1670  }
1671  else
1672  num_ready = 0;
1673  if (num_ready < 0)
1674  {
1675  const int err = MHD_socket_get_error_();
1676 
1677  if (MHD_SCKT_ERR_IS_EINTR_(err))
1678  continue;
1679 #ifdef HAVE_MESSAGES
1680  MHD_DLOG (con->daemon,
1681  _("Error during select (%d): `%s'\n"),
1682  err,
1683  MHD_socket_strerr_ (err));
1684 #endif
1685  break;
1686  }
1687  urh_from_fdset (urh,
1688  &rs,
1689  &ws,
1690  &es);
1691  process_urh (urh);
1692  }
1693  }
1694 #ifdef HAVE_POLL
1695  else if (0 != (daemon->options & MHD_USE_TLS))
1696  {
1697  /* use poll() */
1698  struct pollfd p[2];
1699  memset (p,
1700  0,
1701  sizeof (p));
1702  p[0].fd = urh->connection->socket_fd;
1703  p[1].fd = urh->mhd.socket;
1704 
1705  while ( (0 != urh->in_buffer_size) ||
1706  (0 != urh->out_buffer_size) ||
1707  (0 != urh->in_buffer_used) ||
1708  (0 != urh->out_buffer_used) )
1709  {
1710  int timeout;
1711 
1712  urh_update_pollfd(urh, p);
1713 
1714  if ( (con->tls_read_ready) &&
1715  (urh->in_buffer_used < urh->in_buffer_size))
1716  timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1717  else
1718  timeout = -1;
1719 
1720  if (MHD_sys_poll_ (p,
1721  2,
1722  timeout) < 0)
1723  {
1724  const int err = MHD_socket_get_error_ ();
1725 
1726  if (MHD_SCKT_ERR_IS_EINTR_ (err))
1727  continue;
1728 #ifdef HAVE_MESSAGES
1729  MHD_DLOG (con->daemon,
1730  _("Error during poll: `%s'\n"),
1731  MHD_socket_strerr_ (err));
1732 #endif
1733  break;
1734  }
1735  urh_from_pollfd (urh,
1736  p);
1737  process_urh (urh);
1738  }
1739  }
1740  /* end POLL */
1741 #endif
1742  /* end HTTPS */
1743 #endif /* HTTPS_SUPPORT */
1744  /* TLS forwarding was finished. Cleanup socketpair. */
1746  /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1747  * in connection thread for a little while. */
1748 }
1749 #endif /* UPGRADE_SUPPORT */
1750 
1751 
1759 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1761 {
1762  struct MHD_Connection *con = data;
1763  struct MHD_Daemon *daemon = con->daemon;
1764  int num_ready;
1765  fd_set rs;
1766  fd_set ws;
1767  fd_set es;
1768  MHD_socket maxsock;
1769  struct timeval tv;
1770  struct timeval *tvp;
1771  time_t now;
1772 #if WINDOWS
1773 #ifdef HAVE_POLL
1774  int extra_slot;
1775 #endif /* HAVE_POLL */
1776 #define EXTRA_SLOTS 1
1777 #else /* !WINDOWS */
1778 #define EXTRA_SLOTS 0
1779 #endif /* !WINDOWS */
1780 #ifdef HAVE_POLL
1781  struct pollfd p[1 + EXTRA_SLOTS];
1782 #endif
1783 #undef EXTRA_SLOTS
1784 #ifdef HAVE_POLL
1785  const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1786 #else /* ! HAVE_POLL */
1787  const bool use_poll = 0;
1788 #endif /* ! HAVE_POLL */
1789  bool was_suspended = false;
1790  MHD_thread_init_(&(con->pid));
1791 
1792  while ( (! daemon->shutdown) &&
1793  (MHD_CONNECTION_CLOSED != con->state) )
1794  {
1795  const time_t timeout = daemon->connection_timeout;
1796 #ifdef UPGRADE_SUPPORT
1797  struct MHD_UpgradeResponseHandle * const urh = con->urh;
1798 #else /* ! UPGRADE_SUPPORT */
1799  static const void * const urh = NULL;
1800 #endif /* ! UPGRADE_SUPPORT */
1801 
1802  if ( (con->suspended) &&
1803  (NULL == urh) )
1804  {
1805  /* Connection was suspended, wait for resume. */
1806  was_suspended = true;
1807  if (! use_poll)
1808  {
1809  FD_ZERO (&rs);
1810  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1811  &rs,
1812  NULL,
1813  FD_SETSIZE))
1814  {
1815  #ifdef HAVE_MESSAGES
1816  MHD_DLOG (con->daemon,
1817  _("Failed to add FD to fd_set\n"));
1818  #endif
1819  goto exit;
1820  }
1821  if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
1822  &rs,
1823  NULL,
1824  NULL,
1825  NULL))
1826  {
1827  const int err = MHD_socket_get_error_();
1828 
1829  if (MHD_SCKT_ERR_IS_EINTR_(err))
1830  continue;
1831 #ifdef HAVE_MESSAGES
1832  MHD_DLOG (con->daemon,
1833  _("Error during select (%d): `%s'\n"),
1834  err,
1835  MHD_socket_strerr_ (err));
1836 #endif
1837  break;
1838  }
1839  }
1840 #ifdef HAVE_POLL
1841  else /* use_poll */
1842  {
1843  p[0].events = POLLIN;
1844  p[0].fd = MHD_itc_r_fd_ (daemon->itc);
1845  p[0].revents = 0;
1846  if (0 > MHD_sys_poll_ (p,
1847  1,
1848  -1))
1849  {
1851  continue;
1852 #ifdef HAVE_MESSAGES
1853  MHD_DLOG (con->daemon,
1854  _("Error during poll: `%s'\n"),
1856 #endif
1857  break;
1858  }
1859  }
1860 #endif /* HAVE_POLL */
1861  MHD_itc_clear_ (daemon->itc);
1862  continue; /* Check again for resume. */
1863  } /* End of "suspended" branch. */
1864 
1865  if (was_suspended)
1866  {
1867  MHD_update_last_activity_ (con); /* Reset timeout timer. */
1868  /* Process response queued during suspend and update states. */
1870  was_suspended = false;
1871  }
1872 
1873  tvp = NULL;
1874 
1876 #ifdef HTTPS_SUPPORT
1877  || ( (con->tls_read_ready) &&
1879 #endif /* HTTPS_SUPPORT */
1880  )
1881  {
1882  /* do not block: more data may be inside of TLS buffers waiting or
1883  * application must provide response data */
1884  tv.tv_sec = 0;
1885  tv.tv_usec = 0;
1886  tvp = &tv;
1887  }
1888  if ( (NULL == tvp) &&
1889  (timeout > 0) )
1890  {
1891  now = MHD_monotonic_sec_counter();
1892  if (now - con->last_activity > timeout)
1893  tv.tv_sec = 0;
1894  else
1895  {
1896  const time_t seconds_left = timeout - (now - con->last_activity);
1897 #if !defined(_WIN32) || defined(__CYGWIN__)
1898  tv.tv_sec = seconds_left;
1899 #else /* _WIN32 && !__CYGWIN__ */
1900  if (seconds_left > TIMEVAL_TV_SEC_MAX)
1901  tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1902  else
1903  tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
1904 #endif /* _WIN32 && ! __CYGWIN__ */
1905  }
1906  tv.tv_usec = 0;
1907  tvp = &tv;
1908  }
1909  if (! use_poll)
1910  {
1911  /* use select */
1912  bool err_state = false;
1913 
1914  FD_ZERO (&rs);
1915  FD_ZERO (&ws);
1916  FD_ZERO (&es);
1917  maxsock = MHD_INVALID_SOCKET;
1918  switch (con->event_loop_info)
1919  {
1921  if (! MHD_add_to_fd_set_ (con->socket_fd,
1922  &rs,
1923  &maxsock,
1924  FD_SETSIZE))
1925  err_state = true;
1926  break;
1928  if (! MHD_add_to_fd_set_ (con->socket_fd,
1929  &ws,
1930  &maxsock,
1931  FD_SETSIZE))
1932  err_state = true;
1933  break;
1935  if (! MHD_add_to_fd_set_ (con->socket_fd,
1936  &es,
1937  &maxsock,
1938  FD_SETSIZE))
1939  err_state = true;
1940  break;
1942  /* how did we get here!? */
1943  goto exit;
1944  }
1945 #if WINDOWS
1946  if (MHD_ITC_IS_VALID_(daemon->itc) )
1947  {
1948  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1949  &rs,
1950  &maxsock,
1951  FD_SETSIZE))
1952  err_state = 1;
1953  }
1954 #endif
1955  if (err_state)
1956  {
1957 #ifdef HAVE_MESSAGES
1958  MHD_DLOG (con->daemon,
1959  _("Failed to add FD to fd_set\n"));
1960 #endif
1961  goto exit;
1962  }
1963 
1964  num_ready = MHD_SYS_select_ (maxsock + 1,
1965  &rs,
1966  &ws,
1967  &es,
1968  tvp);
1969  if (num_ready < 0)
1970  {
1971  const int err = MHD_socket_get_error_();
1972 
1973  if (MHD_SCKT_ERR_IS_EINTR_(err))
1974  continue;
1975 #ifdef HAVE_MESSAGES
1976  MHD_DLOG (con->daemon,
1977  _("Error during select (%d): `%s'\n"),
1978  err,
1979  MHD_socket_strerr_ (err));
1980 #endif
1981  break;
1982  }
1983 #if WINDOWS
1984  /* Clear ITC before other processing so additional
1985  * signals will trigger select() again */
1986  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
1987  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
1988  &rs)) )
1989  MHD_itc_clear_ (daemon->itc);
1990 #endif
1991  if (MHD_NO ==
1992  call_handlers (con,
1993  FD_ISSET (con->socket_fd,
1994  &rs),
1995  FD_ISSET (con->socket_fd,
1996  &ws),
1997  FD_ISSET (con->socket_fd,
1998  &es)) )
1999  goto exit;
2000  }
2001 #ifdef HAVE_POLL
2002  else
2003  {
2004  /* use poll */
2005  memset (&p,
2006  0,
2007  sizeof (p));
2008  p[0].fd = con->socket_fd;
2009  switch (con->event_loop_info)
2010  {
2012  p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2013  break;
2015  p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2016  break;
2018  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2019  break;
2021  /* how did we get here!? */
2022  goto exit;
2023  }
2024 #if WINDOWS
2025  extra_slot = 0;
2026  if (MHD_ITC_IS_VALID_(daemon->itc))
2027  {
2028  p[1].events |= POLLIN;
2029  p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2030  p[1].revents = 0;
2031  extra_slot = 1;
2032  }
2033 #endif
2034  if (MHD_sys_poll_ (p,
2035 #if WINDOWS
2036  1 + extra_slot,
2037 #else
2038  1,
2039 #endif
2040  (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2041  {
2043  continue;
2044 #ifdef HAVE_MESSAGES
2045  MHD_DLOG (con->daemon,
2046  _("Error during poll: `%s'\n"),
2048 #endif
2049  break;
2050  }
2051 #if WINDOWS
2052  /* Clear ITC before other processing so additional
2053  * signals will trigger poll() again */
2054  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2055  (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2056  MHD_itc_clear_ (daemon->itc);
2057 #endif
2058  if (MHD_NO ==
2059  call_handlers (con,
2060  0 != (p[0].revents & POLLIN),
2061  0 != (p[0].revents & POLLOUT),
2062  0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
2063  goto exit;
2064  }
2065 #endif
2066 #ifdef UPGRADE_SUPPORT
2067  if (MHD_CONNECTION_UPGRADE == con->state)
2068  {
2069  /* Normal HTTP processing is finished,
2070  * notify application. */
2071  if ( (NULL != daemon->notify_completed) &&
2072  (con->client_aware) )
2073  daemon->notify_completed (daemon->notify_completed_cls,
2074  con,
2075  &con->client_context,
2077  con->client_aware = false;
2078 
2079  thread_main_connection_upgrade (con);
2080  /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2081 
2082  /* "Upgraded" data will not be used in this thread from this point. */
2083  con->urh->clean_ready = true;
2084  /* If 'urh->was_closed' set to true, connection will be
2085  * moved immediately to cleanup list. Otherwise connection
2086  * will stay in suspended list until 'urh' will be marked
2087  * with 'was_closed' by application. */
2088  MHD_resume_connection(con);
2089 
2090  /* skip usual clean up */
2091  return (MHD_THRD_RTRN_TYPE_) 0;
2092  }
2093 #endif /* UPGRADE_SUPPORT */
2094  }
2095 #if DEBUG_CLOSE
2096 #ifdef HAVE_MESSAGES
2097  MHD_DLOG (con->daemon,
2098  _("Processing thread terminating. Closing connection\n"));
2099 #endif
2100 #endif
2101  if (MHD_CONNECTION_CLOSED != con->state)
2102  MHD_connection_close_ (con,
2103  (daemon->shutdown) ?
2107 exit:
2108  if (NULL != con->response)
2109  {
2111  con->response = NULL;
2112  }
2113 
2114  if (MHD_INVALID_SOCKET != con->socket_fd)
2115  {
2116  shutdown (con->socket_fd,
2117  SHUT_WR);
2118  /* 'socket_fd' can be used in other thread to signal shutdown.
2119  * To avoid data races, do not close socket here. Daemon will
2120  * use more connections only after cleanup anyway. */
2121  }
2122  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2123  (! MHD_itc_activate_ (daemon->itc, "t")) )
2124  {
2125 #ifdef HAVE_MESSAGES
2126  MHD_DLOG (daemon,
2127  _("Failed to signal thread termination via inter-thread communication channel."));
2128 #endif
2129  }
2130  return (MHD_THRD_RTRN_TYPE_) 0;
2131 }
2132 #endif
2133 
2134 
2142 static void
2143 MHD_cleanup_connections (struct MHD_Daemon *daemon);
2144 
2145 #if defined(HTTPS_SUPPORT)
2146 #if !defined(MHD_WINSOCK_SOCKETS) && !defined(MHD_socket_nosignal_) && \
2147  (GNUTLS_VERSION_NUMBER+0 < 0x030402) && defined(MSG_NOSIGNAL)
2148 
2153 #define MHD_TLSLIB_NEED_PUSH_FUNC 1
2154 #endif /* !MHD_WINSOCK_SOCKETS && !MHD_socket_nosignal_ && (GNUTLS_VERSION_NUMBER+0 < 0x030402) */
2155 
2156 #ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2157 
2161 static ssize_t
2162 MHD_tls_push_func_(gnutls_transport_ptr_t trnsp,
2163  const void *data,
2164  size_t data_size)
2165 {
2166 #if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2167  if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
2168  data_size = MHD_SCKT_SEND_MAX_SIZE_;
2169 #endif /* (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX) */
2170  return MHD_send_ ((MHD_socket)(intptr_t)(trnsp), data, data_size);
2171 }
2172 #endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
2173 
2174 
2183 static int
2184 psk_gnutls_adapter (gnutls_session_t session,
2185  const char *username,
2186  gnutls_datum_t *key)
2187 {
2188  struct MHD_Connection *connection;
2189  struct MHD_Daemon *daemon;
2190  void *app_psk;
2191  size_t app_psk_size;
2192 
2193  connection = gnutls_session_get_ptr (session);
2194  if (NULL == connection)
2195  {
2196 #ifdef HAVE_MESSAGES
2197  /* Cannot use our logger, we don't even have "daemon" */
2198  MHD_PANIC (_("Internal server error. This should be impossible.\n"));
2199 #endif
2200  return -1;
2201  }
2202  daemon = connection->daemon;
2203 #if GNUTLS_VERSION_MAJOR >= 3
2204  if (NULL == daemon->cred_callback)
2205  {
2206 #ifdef HAVE_MESSAGES
2207  MHD_DLOG (daemon,
2208  _("PSK not supported by this server.\n"));
2209 #endif
2210  return -1;
2211  }
2212  if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2213  connection,
2214  username,
2215  &app_psk,
2216  &app_psk_size))
2217  return -1;
2218  if (NULL == (key->data = gnutls_malloc (app_psk_size)))
2219  {
2220 #ifdef HAVE_MESSAGES
2221  MHD_DLOG (daemon,
2222  _("PSK authentication failed: gnutls_malloc failed to allocate memory\n"));
2223 #endif
2224  free (app_psk);
2225  return -1;
2226  }
2227  key->size = app_psk_size;
2228  memcpy (key->data,
2229  app_psk,
2230  app_psk_size);
2231  free (app_psk);
2232  return 0;
2233 #else
2234 #ifdef HAVE_MESSAGES
2235  MHD_DLOG (daemon,
2236  _("PSK not supported by this server.\n"));
2237 #endif
2238  return -1;
2239 #endif
2240 }
2241 #endif /* HTTPS_SUPPORT */
2242 
2243 
2269 static int
2271  MHD_socket client_socket,
2272  const struct sockaddr *addr,
2273  socklen_t addrlen,
2274  bool external_add,
2275  bool non_blck)
2276 {
2277  struct MHD_Connection *connection;
2278 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2279  unsigned int i;
2280 #endif
2281  int eno = 0;
2282 
2283  /* Direct add to master daemon could happen only with "external" add mode. */
2284 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2285  mhd_assert ((NULL == daemon->worker_pool) || (external_add));
2286  if ((external_add) && (NULL != daemon->worker_pool))
2287  {
2288  /* have a pool, try to find a pool with capacity; we use the
2289  socket as the initial offset into the pool for load
2290  balancing */
2291  for (i = 0; i < daemon->worker_pool_size; ++i)
2292  {
2293  struct MHD_Daemon * const worker =
2294  &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
2295  if (worker->connections < worker->connection_limit)
2296  return internal_add_connection (worker,
2297  client_socket,
2298  addr,
2299  addrlen,
2300  true,
2301  non_blck);
2302  }
2303  /* all pools are at their connection limit, must refuse */
2304  MHD_socket_close_chk_ (client_socket);
2305 #if ENFILE
2306  errno = ENFILE;
2307 #endif
2308  return MHD_NO;
2309  }
2310 #endif
2311 
2312  if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
2313  NULL)) &&
2314  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
2315  {
2316 #ifdef HAVE_MESSAGES
2317  MHD_DLOG (daemon,
2318  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2319  (int) client_socket,
2320  (int) FD_SETSIZE);
2321 #endif
2322  MHD_socket_close_chk_ (client_socket);
2323 #if EINVAL
2324  errno = EINVAL;
2325 #endif
2326  return MHD_NO;
2327  }
2328 
2329 #ifdef MHD_socket_nosignal_
2330  if (! MHD_socket_nosignal_ (client_socket))
2331  {
2332 #ifdef HAVE_MESSAGES
2333  MHD_DLOG (daemon,
2334  _("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2336 #endif
2337 #ifndef MSG_NOSIGNAL
2338  /* Cannot use socket as it can produce SIGPIPE. */
2339 #ifdef ENOTSOCK
2340  errno = ENOTSOCK;
2341 #endif /* ENOTSOCK */
2342  return MHD_NO;
2343 #endif /* ! MSG_NOSIGNAL */
2344  }
2345 #endif /* MHD_socket_nosignal_ */
2346 
2347 
2348 #ifdef HAVE_MESSAGES
2349 #if DEBUG_CONNECT
2350  MHD_DLOG (daemon,
2351  _("Accepted connection on socket %d\n"),
2352  client_socket);
2353 #endif
2354 #endif
2355  if ( (daemon->connections == daemon->connection_limit) ||
2356  (MHD_NO == MHD_ip_limit_add (daemon,
2357  addr,
2358  addrlen)) )
2359  {
2360  /* above connection limit - reject */
2361 #ifdef HAVE_MESSAGES
2362  MHD_DLOG (daemon,
2363  _("Server reached connection limit. Closing inbound connection.\n"));
2364 #endif
2365  MHD_socket_close_chk_ (client_socket);
2366 #if ENFILE
2367  errno = ENFILE;
2368 #endif
2369  return MHD_NO;
2370  }
2371 
2372  /* apply connection acceptance policy if present */
2373  if ( (NULL != daemon->apc) &&
2374  (MHD_NO == daemon->apc (daemon->apc_cls,
2375  addr,
2376  addrlen)) )
2377  {
2378 #if DEBUG_CLOSE
2379 #ifdef HAVE_MESSAGES
2380  MHD_DLOG (daemon,
2381  _("Connection rejected by application. Closing connection.\n"));
2382 #endif
2383 #endif
2384  MHD_socket_close_chk_ (client_socket);
2385  MHD_ip_limit_del (daemon,
2386  addr,
2387  addrlen);
2388 #if EACCESS
2389  errno = EACCESS;
2390 #endif
2391  return MHD_NO;
2392  }
2393 
2394  if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2395  {
2396  eno = errno;
2397 #ifdef HAVE_MESSAGES
2398  MHD_DLOG (daemon,
2399  "Error allocating memory: %s\n",
2400  MHD_strerror_ (errno));
2401 #endif
2402  MHD_socket_close_chk_ (client_socket);
2403  MHD_ip_limit_del (daemon,
2404  addr,
2405  addrlen);
2406  errno = eno;
2407  return MHD_NO;
2408  }
2409  connection->pool = MHD_pool_create (daemon->pool_size);
2410  if (NULL == connection->pool)
2411  {
2412 #ifdef HAVE_MESSAGES
2413  MHD_DLOG (daemon,
2414  _("Error allocating memory: %s\n"),
2415  MHD_strerror_ (errno));
2416 #endif
2417  MHD_socket_close_chk_ (client_socket);
2418  MHD_ip_limit_del (daemon,
2419  addr,
2420  addrlen);
2421  free (connection);
2422 #if ENOMEM
2423  errno = ENOMEM;
2424 #endif
2425  return MHD_NO;
2426  }
2427 
2428  connection->connection_timeout = daemon->connection_timeout;
2429  if (NULL == (connection->addr = malloc (addrlen)))
2430  {
2431  eno = errno;
2432 #ifdef HAVE_MESSAGES
2433  MHD_DLOG (daemon,
2434  _("Error allocating memory: %s\n"),
2435  MHD_strerror_ (errno));
2436 #endif
2437  MHD_socket_close_chk_ (client_socket);
2438  MHD_ip_limit_del (daemon,
2439  addr,
2440  addrlen);
2441  MHD_pool_destroy (connection->pool);
2442  free (connection);
2443  errno = eno;
2444  return MHD_NO;
2445  }
2446  memcpy (connection->addr,
2447  addr,
2448  addrlen);
2449  connection->addr_len = addrlen;
2450  connection->socket_fd = client_socket;
2451  connection->sk_nonblck = non_blck;
2452  connection->daemon = daemon;
2453  connection->last_activity = MHD_monotonic_sec_counter();
2454 
2455  if (0 == (daemon->options & MHD_USE_TLS))
2456  {
2457  /* set default connection handlers */
2458  MHD_set_http_callbacks_ (connection);
2459  }
2460  else
2461  {
2462 #ifdef HTTPS_SUPPORT
2463  connection->tls_state = MHD_TLS_CONN_INIT;
2464  MHD_set_https_callbacks (connection);
2465  gnutls_init (&connection->tls_session,
2466  GNUTLS_SERVER
2467 #if (GNUTLS_VERSION_NUMBER+0 >= 0x030402)
2468  | GNUTLS_NO_SIGNAL
2469 #endif /* GNUTLS_VERSION_NUMBER >= 0x030402 */
2470 #if GNUTLS_VERSION_MAJOR >= 3
2471  | GNUTLS_NONBLOCK
2472 #endif /* GNUTLS_VERSION_MAJOR >= 3*/
2473  );
2474  gnutls_priority_set (connection->tls_session,
2475  daemon->priority_cache);
2476  gnutls_session_set_ptr (connection->tls_session,
2477  connection);
2478  switch (daemon->cred_type)
2479  {
2480  /* set needed credentials for certificate authentication. */
2481  case GNUTLS_CRD_CERTIFICATE:
2482  gnutls_credentials_set (connection->tls_session,
2483  GNUTLS_CRD_CERTIFICATE,
2484  daemon->x509_cred);
2485  break;
2486  case GNUTLS_CRD_PSK:
2487  gnutls_credentials_set (connection->tls_session,
2488  GNUTLS_CRD_PSK,
2489  daemon->psk_cred);
2490  gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2491  &psk_gnutls_adapter);
2492  break;
2493  default:
2494 #ifdef HAVE_MESSAGES
2495  MHD_DLOG (connection->daemon,
2496  _("Failed to setup TLS credentials: unknown credential type %d\n"),
2497  daemon->cred_type);
2498 #endif
2499  MHD_socket_close_chk_ (client_socket);
2500  MHD_ip_limit_del (daemon,
2501  addr,
2502  addrlen);
2503  free (connection->addr);
2504  free (connection);
2505  MHD_PANIC (_("Unknown credential type"));
2506 #if EINVAL
2507  errno = EINVAL;
2508 #endif
2509  return MHD_NO;
2510  }
2511 #if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64)
2512  gnutls_transport_set_int (connection->tls_session,
2513  (int)(client_socket));
2514 #else /* GnuTLS before 3.1.9 or Win x64 */
2515  gnutls_transport_set_ptr (connection->tls_session,
2516  (gnutls_transport_ptr_t)(intptr_t)(client_socket));
2517 #endif /* GnuTLS before 3.1.9 */
2518 #ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2519  gnutls_transport_set_push_function (connection->tls_session,
2520  MHD_tls_push_func_);
2521 #endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2522  if (daemon->https_mem_trust)
2523  gnutls_certificate_server_set_request (connection->tls_session,
2524  GNUTLS_CERT_REQUEST);
2525 #else /* ! HTTPS_SUPPORT */
2526  eno = EINVAL;
2527  goto cleanup;
2528 #endif /* ! HTTPS_SUPPORT */
2529  }
2530 
2531 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2533 #endif
2534  /* Firm check under lock. */
2535  if (daemon->connections >= daemon->connection_limit)
2536  {
2537 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2539 #endif
2540  /* above connection limit - reject */
2541 #ifdef HAVE_MESSAGES
2542  MHD_DLOG (daemon,
2543  _("Server reached connection limit. Closing inbound connection.\n"));
2544 #endif
2545 #if ENFILE
2546  eno = ENFILE;
2547 #endif
2548  goto cleanup;
2549  }
2550  daemon->connections++;
2551  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2552  {
2554  daemon->normal_timeout_tail,
2555  connection);
2556  }
2557  DLL_insert (daemon->connections_head,
2558  daemon->connections_tail,
2559  connection);
2560 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2562 #endif
2563  if (NULL != daemon->notify_connection)
2564  daemon->notify_connection (daemon->notify_connection_cls,
2565  connection,
2566  &connection->socket_context,
2568 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2569  /* attempt to create handler thread */
2570  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2571  {
2572  if (! MHD_create_named_thread_ (&connection->pid,
2573  "MHD-connection",
2574  daemon->thread_stack_size,
2576  connection))
2577  {
2578  eno = errno;
2579 #ifdef HAVE_MESSAGES
2580  MHD_DLOG (daemon,
2581  "Failed to create a thread: %s\n",
2582  MHD_strerror_ (eno));
2583 #endif
2584  goto cleanup;
2585  }
2586  }
2587  else
2588  connection->pid = daemon->pid;
2589 #endif
2590 #ifdef EPOLL_SUPPORT
2591  if (0 != (daemon->options & MHD_USE_EPOLL))
2592  {
2593  if ((0 == (daemon->options & MHD_USE_TURBO)) || (external_add))
2594  { /* Do not manipulate EReady DL-list in 'external_add' mode. */
2595  struct epoll_event event;
2596 
2597  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2598  event.data.ptr = connection;
2599  if (0 != epoll_ctl (daemon->epoll_fd,
2600  EPOLL_CTL_ADD,
2601  client_socket,
2602  &event))
2603  {
2604  eno = errno;
2605 #ifdef HAVE_MESSAGES
2606  MHD_DLOG (daemon,
2607  _("Call to epoll_ctl failed: %s\n"),
2609 #endif
2610  goto cleanup;
2611  }
2612  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2613  }
2614  else
2615  {
2616  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
2618  EDLL_insert (daemon->eready_head,
2619  daemon->eready_tail,
2620  connection);
2621  }
2622  }
2623  else /* This 'else' is combined with next 'if'. */
2624 #endif
2625  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2626  (external_add) &&
2627  (MHD_ITC_IS_VALID_(daemon->itc)) &&
2628  (! MHD_itc_activate_ (daemon->itc, "n")) )
2629  {
2630 #ifdef HAVE_MESSAGES
2631  MHD_DLOG (daemon,
2632  _("Failed to signal new connection via inter-thread communication channel."));
2633 #endif
2634  }
2635  return MHD_YES;
2636  cleanup:
2637  if (NULL != daemon->notify_connection)
2638  daemon->notify_connection (daemon->notify_connection_cls,
2639  connection,
2640  &connection->socket_context,
2642 #ifdef HTTPS_SUPPORT
2643  if (NULL != connection->tls_session)
2644  gnutls_deinit (connection->tls_session);
2645 #endif /* HTTPS_SUPPORT */
2646  MHD_socket_close_chk_ (client_socket);
2647  MHD_ip_limit_del (daemon,
2648  addr,
2649  addrlen);
2650 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2652 #endif
2653  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2654  {
2656  daemon->normal_timeout_tail,
2657  connection);
2658  }
2659  DLL_remove (daemon->connections_head,
2660  daemon->connections_tail,
2661  connection);
2662 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2664 #endif
2665  MHD_pool_destroy (connection->pool);
2666  free (connection->addr);
2667  free (connection);
2668  if (0 != eno)
2669  errno = eno;
2670  else
2671  errno = EINVAL;
2672  return MHD_NO;
2673 }
2674 
2675 
2685 void
2687 {
2688  struct MHD_Daemon *daemon = connection->daemon;
2689 
2690 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2692 #endif
2693  if (connection->resuming)
2694  {
2695  /* suspending again while we didn't even complete resuming yet */
2696  connection->resuming = false;
2697 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2699 #endif
2700  return;
2701  }
2702  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2703  {
2704  if (connection->connection_timeout == daemon->connection_timeout)
2706  daemon->normal_timeout_tail,
2707  connection);
2708  else
2710  daemon->manual_timeout_tail,
2711  connection);
2712  }
2713  DLL_remove (daemon->connections_head,
2714  daemon->connections_tail,
2715  connection);
2716  mhd_assert (! connection->suspended);
2719  connection);
2720  connection->suspended = true;
2721 #ifdef EPOLL_SUPPORT
2722  if (0 != (daemon->options & MHD_USE_EPOLL))
2723  {
2724  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2725  {
2726  EDLL_remove (daemon->eready_head,
2727  daemon->eready_tail,
2728  connection);
2729  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2730  }
2731  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2732  {
2733  if (0 != epoll_ctl (daemon->epoll_fd,
2734  EPOLL_CTL_DEL,
2735  connection->socket_fd,
2736  NULL))
2737  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
2738  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2739  }
2740  connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2741  }
2742 #endif
2743 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2745 #endif
2746 }
2747 
2748 
2780 void
2782 {
2783  struct MHD_Daemon * const daemon = connection->daemon;
2784 
2785  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2786  MHD_PANIC (_("Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2787 #ifdef UPGRADE_SUPPORT
2788  if (NULL != connection->urh)
2789  {
2790 #ifdef HAVE_MESSAGES
2791  MHD_DLOG (daemon,
2792  _("Error: connection scheduled for \"upgrade\" cannot be suspended"));
2793 #endif /* HAVE_MESSAGES */
2794  return;
2795  }
2796 #endif /* UPGRADE_SUPPORT */
2797  internal_suspend_connection_ (connection);
2798 }
2799 
2800 
2809 void
2811 {
2812  struct MHD_Daemon *daemon = connection->daemon;
2813 
2814  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2815  MHD_PANIC (_("Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2816 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2818 #endif
2819  connection->resuming = true;
2820  daemon->resuming = true;
2821 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2823 #endif
2824  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2825  (! MHD_itc_activate_ (daemon->itc, "r")) )
2826  {
2827 #ifdef HAVE_MESSAGES
2828  MHD_DLOG (daemon,
2829  _("Failed to signal resume via inter-thread communication channel."));
2830 #endif
2831  }
2832 }
2833 
2834 
2844 static int
2846 {
2847  struct MHD_Connection *pos;
2848  struct MHD_Connection *prev = NULL;
2849  int ret;
2850  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
2851 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2852  mhd_assert (NULL == daemon->worker_pool);
2853 #endif
2854  ret = MHD_NO;
2855 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2857 #endif
2858  if (daemon->resuming)
2859  {
2860  prev = daemon->suspended_connections_tail;
2861  /* During shutdown check for resuming is forced. */
2862  mhd_assert((NULL != prev) || (daemon->shutdown));
2863  }
2864 
2865  daemon->resuming = false;
2866 
2867  while (NULL != (pos = prev))
2868  {
2869 #ifdef UPGRADE_SUPPORT
2870  struct MHD_UpgradeResponseHandle * const urh = pos->urh;
2871 #else /* ! UPGRADE_SUPPORT */
2872  static const void * const urh = NULL;
2873 #endif /* ! UPGRADE_SUPPORT */
2874  prev = pos->prev;
2875  if ( (! pos->resuming)
2876 #ifdef UPGRADE_SUPPORT
2877  || ( (NULL != urh) &&
2878  ( (! urh->was_closed) ||
2879  (! urh->clean_ready) ) )
2880 #endif /* UPGRADE_SUPPORT */
2881  )
2882  continue;
2883  ret = MHD_YES;
2884  mhd_assert (pos->suspended);
2887  pos);
2888  pos->suspended = false;
2889  if (NULL == urh)
2890  {
2891  DLL_insert (daemon->connections_head,
2892  daemon->connections_tail,
2893  pos);
2894  if (! used_thr_p_c)
2895  {
2896  /* Reset timeout timer on resume. */
2897  if (0 != pos->connection_timeout)
2899 
2900  if (pos->connection_timeout == daemon->connection_timeout)
2902  daemon->normal_timeout_tail,
2903  pos);
2904  else
2906  daemon->manual_timeout_tail,
2907  pos);
2908  }
2909 #ifdef EPOLL_SUPPORT
2910  if (0 != (daemon->options & MHD_USE_EPOLL))
2911  {
2912  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2913  MHD_PANIC ("Resumed connection was already in EREADY set\n");
2914  /* we always mark resumed connections as ready, as we
2915  might have missed the edge poll event during suspension */
2916  EDLL_insert (daemon->eready_head,
2917  daemon->eready_tail,
2918  pos);
2919  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL | \
2921  pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
2922  }
2923 #endif
2924  }
2925 #ifdef UPGRADE_SUPPORT
2926  else
2927  {
2928  /* Data forwarding was finished (for TLS connections) AND
2929  * application was closed upgraded connection.
2930  * Insert connection into cleanup list. */
2931 
2932  if ( (NULL != daemon->notify_completed) &&
2933  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2934  (pos->client_aware) )
2935  {
2936  daemon->notify_completed (daemon->notify_completed_cls,
2937  pos,
2938  &pos->client_context,
2940  pos->client_aware = false;
2941  }
2942  DLL_insert (daemon->cleanup_head,
2943  daemon->cleanup_tail,
2944  pos);
2945 
2946  }
2947 #endif /* UPGRADE_SUPPORT */
2948  pos->resuming = false;
2949  }
2950 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2952 #endif
2953  if ( (used_thr_p_c) &&
2954  (MHD_NO != ret) )
2955  { /* Wake up suspended connections. */
2956  if (! MHD_itc_activate_(daemon->itc,
2957  "w"))
2958  {
2959 #ifdef HAVE_MESSAGES
2960  MHD_DLOG (daemon,
2961  _("Failed to signal resume of connection via inter-thread communication channel."));
2962 #endif
2963  }
2964  }
2965  return ret;
2966 }
2967 
2968 
2996 int
2998  MHD_socket client_socket,
2999  const struct sockaddr *addr,
3000  socklen_t addrlen)
3001 {
3002  bool sk_nonbl;
3003  if (! MHD_socket_nonblocking_ (client_socket))
3004  {
3005 #ifdef HAVE_MESSAGES
3006  MHD_DLOG (daemon,
3007  _("Failed to set nonblocking mode on new client socket: %s\n"),
3009 #endif
3010  sk_nonbl = 0;
3011  }
3012  else
3013  sk_nonbl = !0;
3014 
3015  if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3016  (! MHD_socket_noninheritable_ (client_socket)) )
3017  {
3018 #ifdef HAVE_MESSAGES
3019  MHD_DLOG (daemon,
3020  _("Failed to set noninheritable mode on new client socket.\n"));
3021 #endif
3022  }
3023  return internal_add_connection (daemon,
3024  client_socket,
3025  addr,
3026  addrlen,
3027  true,
3028  sk_nonbl);
3029 }
3030 
3031 
3046 static int
3048 {
3049 #if HAVE_INET6
3050  struct sockaddr_in6 addrstorage;
3051 #else
3052  struct sockaddr_in addrstorage;
3053 #endif
3054  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3055  socklen_t addrlen;
3056  MHD_socket s;
3057  MHD_socket fd;
3058  bool sk_nonbl;
3059 
3060  addrlen = sizeof (addrstorage);
3061  memset (addr,
3062  0,
3063  sizeof (addrstorage));
3064  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3065  (daemon->was_quiesced) )
3066  return MHD_NO;
3067 #ifdef USE_ACCEPT4
3068  s = accept4 (fd,
3069  addr,
3070  &addrlen,
3072  sk_nonbl = (MAYBE_SOCK_NONBLOCK != 0);
3073 #else /* ! USE_ACCEPT4 */
3074  s = accept (fd,
3075  addr,
3076  &addrlen);
3077  sk_nonbl = 0;
3078 #endif /* ! USE_ACCEPT4 */
3079  if ( (MHD_INVALID_SOCKET == s) ||
3080  (addrlen <= 0) )
3081  {
3082  const int err = MHD_socket_get_error_ ();
3083 
3084  /* This could be a common occurance with multiple worker threads */
3085  if (MHD_SCKT_ERR_IS_ (err,
3087  return MHD_NO; /* can happen during shutdown */
3089  return MHD_NO; /* do not print error if client just disconnected early */
3090 #ifdef HAVE_MESSAGES
3091  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3092  MHD_DLOG (daemon,
3093  _("Error accepting connection: %s\n"),
3094  MHD_socket_strerr_(err));
3095 #endif
3096  if (MHD_INVALID_SOCKET != s)
3097  {
3099  }
3100  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
3101  {
3102  /* system/process out of resources */
3103  if (0 == daemon->connections)
3104  {
3105 #ifdef HAVE_MESSAGES
3106  /* Not setting 'at_limit' flag, as there is no way it
3107  would ever be cleared. Instead trying to produce
3108  bit fat ugly warning. */
3109  MHD_DLOG (daemon,
3110  _("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"));
3111 #endif
3112  }
3113  else
3114  {
3115 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3117 #endif
3118  daemon->at_limit = true;
3119 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3121 #endif
3122 #ifdef HAVE_MESSAGES
3123  MHD_DLOG (daemon,
3124  _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3125  (unsigned int) daemon->connections);
3126 #endif
3127  }
3128  }
3129  return MHD_NO;
3130  }
3131 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
3132  if (! MHD_socket_nonblocking_ (s))
3133  {
3134 #ifdef HAVE_MESSAGES
3135  MHD_DLOG (daemon,
3136  _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
3138 #endif
3139  }
3140  else
3141  sk_nonbl = !0;
3142 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
3143 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
3144  if (! MHD_socket_noninheritable_ (s))
3145  {
3146 #ifdef HAVE_MESSAGES
3147  MHD_DLOG (daemon,
3148  _("Failed to set noninheritable mode on incoming connection socket.\n"));
3149 #endif
3150  }
3151 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
3152 #ifdef HAVE_MESSAGES
3153 #if DEBUG_CONNECT
3154  MHD_DLOG (daemon,
3155  _("Accepted connection on socket %d\n"),
3156  s);
3157 #endif
3158 #endif
3159  (void) internal_add_connection (daemon,
3160  s,
3161  addr,
3162  addrlen,
3163  false,
3164  sk_nonbl);
3165  return MHD_YES;
3166 }
3167 
3168 
3178 static void
3180 {
3181  struct MHD_Connection *pos;
3182 
3183 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3185 #endif
3186  while (NULL != (pos = daemon->cleanup_tail))
3187  {
3188  DLL_remove (daemon->cleanup_head,
3189  daemon->cleanup_tail,
3190  pos);
3191 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3193  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3194  (! pos->thread_joined) &&
3195  (! MHD_join_thread_ (pos->pid.handle)) )
3196  MHD_PANIC (_("Failed to join a thread\n"));
3197 #endif
3198 #ifdef UPGRADE_SUPPORT
3199  cleanup_upgraded_connection (pos);
3200 #endif /* UPGRADE_SUPPORT */
3201  MHD_pool_destroy (pos->pool);
3202 #ifdef HTTPS_SUPPORT
3203  if (NULL != pos->tls_session)
3204  gnutls_deinit (pos->tls_session);
3205 #endif /* HTTPS_SUPPORT */
3206 
3207  /* clean up the connection */
3208  if (NULL != daemon->notify_connection)
3209  daemon->notify_connection (daemon->notify_connection_cls,
3210  pos,
3211  &pos->socket_context,
3213  MHD_ip_limit_del (daemon,
3214  pos->addr,
3215  pos->addr_len);
3216 #ifdef EPOLL_SUPPORT
3217  if (0 != (daemon->options & MHD_USE_EPOLL))
3218  {
3219  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3220  {
3221  EDLL_remove (daemon->eready_head,
3222  daemon->eready_tail,
3223  pos);
3224  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3225  }
3226  if ( (-1 != daemon->epoll_fd) &&
3227  (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3228  {
3229  /* epoll documentation suggests that closing a FD
3230  automatically removes it from the epoll set; however,
3231  this is not true as if we fail to do manually remove it,
3232  we are still seeing an event for this fd in epoll,
3233  causing grief (use-after-free...) --- at least on my
3234  system. */
3235  if (0 != epoll_ctl (daemon->epoll_fd,
3236  EPOLL_CTL_DEL,
3237  pos->socket_fd,
3238  NULL))
3239  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
3240  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3241  }
3242  }
3243 #endif
3244  if (NULL != pos->response)
3245  {
3247  pos->response = NULL;
3248  }
3249  if (MHD_INVALID_SOCKET != pos->socket_fd)
3251  if (NULL != pos->addr)
3252  free (pos->addr);
3253  free (pos);
3254 
3255 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3257 #endif
3258  daemon->connections--;
3259  daemon->at_limit = false;
3260  }
3261 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3263 #endif
3264 }
3265 
3266 
3287 int
3288 MHD_get_timeout (struct MHD_Daemon *daemon,
3289  MHD_UNSIGNED_LONG_LONG *timeout)
3290 {
3291  time_t earliest_deadline;
3292  time_t now;
3293  struct MHD_Connection *pos;
3294  bool have_timeout;
3295 
3296  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3297  {
3298 #ifdef HAVE_MESSAGES
3299  MHD_DLOG (daemon,
3300  _("Illegal call to MHD_get_timeout\n"));
3301 #endif
3302  return MHD_NO;
3303  }
3304 
3305  if (daemon->data_already_pending)
3306  {
3307  /* Some data already waiting to be processed. */
3308  *timeout = 0;
3309  return MHD_YES;
3310  }
3311 
3312 #ifdef EPOLL_SUPPORT
3313  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3314  ((NULL != daemon->eready_head)
3315 #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3316  || (NULL != daemon->eready_urh_head)
3317 #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3318  ) )
3319  {
3320  /* Some connection(s) already have some data pending. */
3321  *timeout = 0;
3322  return MHD_YES;
3323  }
3324 #endif /* EPOLL_SUPPORT */
3325 
3326  have_timeout = false;
3327  earliest_deadline = 0; /* avoid compiler warnings */
3328  for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3329  {
3330  if (0 != pos->connection_timeout)
3331  {
3332  if ( (! have_timeout) ||
3333  (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3334  earliest_deadline = pos->last_activity + pos->connection_timeout;
3335  have_timeout = true;
3336  }
3337  }
3338  /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3339  pos = daemon->normal_timeout_tail;
3340  if ( (NULL != pos) &&
3341  (0 != pos->connection_timeout) )
3342  {
3343  if ( (! have_timeout) ||
3344  (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3345  earliest_deadline = pos->last_activity + pos->connection_timeout;
3346  have_timeout = true;
3347  }
3348 
3349  if (! have_timeout)
3350  return MHD_NO;
3351  now = MHD_monotonic_sec_counter();
3352  if (earliest_deadline < now)
3353  *timeout = 0;
3354  else
3355  {
3356  const time_t second_left = earliest_deadline - now;
3357 
3358  if (((unsigned long long)second_left) > ULLONG_MAX / 1000)
3359  *timeout = ULLONG_MAX;
3360  else
3361  *timeout = 1000LLU * (unsigned long long) second_left;
3362  }
3363  return MHD_YES;
3364 }
3365 
3366 
3377 static int
3379  const fd_set *read_fd_set,
3380  const fd_set *write_fd_set,
3381  const fd_set *except_fd_set)
3382 {
3383  MHD_socket ds;
3384  struct MHD_Connection *pos;
3385  struct MHD_Connection *prev;
3386 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3387  struct MHD_UpgradeResponseHandle *urh;
3388  struct MHD_UpgradeResponseHandle *urhn;
3389 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3390  /* Reset. New value will be set when connections are processed. */
3391  /* Note: no-op for thread-per-connection as it is always false in that mode. */
3392  daemon->data_already_pending = false;
3393 
3394  /* Clear ITC to avoid spinning select */
3395  /* Do it before any other processing so new signals
3396  will trigger select again and will be processed */
3397  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3398  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3399  read_fd_set)) )
3400  MHD_itc_clear_ (daemon->itc);
3401 
3402  /* select connection thread handling type */
3403  if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3404  (! daemon->was_quiesced) &&
3405  (FD_ISSET (ds,
3406  read_fd_set)) )
3407  (void) MHD_accept_connection (daemon);
3408 
3409  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3410  {
3411  /* do not have a thread per connection, process all connections now */
3412  prev = daemon->connections_tail;
3413  while (NULL != (pos = prev))
3414  {
3415  prev = pos->prev;
3416  ds = pos->socket_fd;
3417  if (MHD_INVALID_SOCKET == ds)
3418  continue;
3419  call_handlers (pos,
3420  FD_ISSET (ds,
3421  read_fd_set),
3422  FD_ISSET (ds,
3423  write_fd_set),
3424  FD_ISSET (ds,
3425  except_fd_set));
3426  }
3427  }
3428 
3429 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3430  /* handle upgraded HTTPS connections */
3431  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3432  {
3433  urhn = urh->prev;
3434  /* update urh state based on select() output */
3435  urh_from_fdset (urh,
3436  read_fd_set,
3437  write_fd_set,
3438  except_fd_set);
3439  /* call generic forwarding function for passing data */
3440  process_urh (urh);
3441  /* Finished forwarding? */
3442  if ( (0 == urh->in_buffer_size) &&
3443  (0 == urh->out_buffer_size) &&
3444  (0 == urh->in_buffer_used) &&
3445  (0 == urh->out_buffer_used) )
3446  {
3447  MHD_connection_finish_forward_ (urh->connection);
3448  urh->clean_ready = true;
3449  /* Resuming will move connection to cleanup list. */
3450  MHD_resume_connection(urh->connection);
3451  }
3452  }
3453 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3454  MHD_cleanup_connections (daemon);
3455  return MHD_YES;
3456 }
3457 
3458 
3481 int
3483  const fd_set *read_fd_set,
3484  const fd_set *write_fd_set,
3485  const fd_set *except_fd_set)
3486 {
3487  fd_set es;
3488  if (0 != (daemon->options &
3490  return MHD_NO;
3491  if (NULL == read_fd_set || NULL == write_fd_set)
3492  return MHD_NO;
3493  if (NULL == except_fd_set)
3494  { /* Workaround to maintain backward compatibility. */
3495 #ifdef HAVE_MESSAGES
3496  MHD_DLOG (daemon,
3497  _("MHD_run_from_select() called with except_fd_set "
3498  "set to NULL. Such behavior is deprecated.\n"));
3499 #endif
3500  FD_ZERO (&es);
3501  except_fd_set = &es;
3502  }
3503  if (0 != (daemon->options & MHD_USE_EPOLL))
3504  {
3505 #ifdef EPOLL_SUPPORT
3506  int ret = MHD_epoll (daemon,
3507  MHD_NO);
3508 
3509  MHD_cleanup_connections (daemon);
3510  return ret;
3511 #else /* ! EPOLL_SUPPORT */
3512  return MHD_NO;
3513 #endif /* ! EPOLL_SUPPORT */
3514  }
3515 
3516  /* Resuming external connections when using an extern mainloop */
3517  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3519 
3520  return internal_run_from_select (daemon,
3521  read_fd_set,
3522  write_fd_set,
3523  except_fd_set);
3524 }
3525 
3526 
3535 static int
3536 MHD_select (struct MHD_Daemon *daemon,
3537  int may_block)
3538 {
3539  int num_ready;
3540  fd_set rs;
3541  fd_set ws;
3542  fd_set es;
3543  MHD_socket maxsock;
3544  struct timeval timeout;
3545  struct timeval *tv;
3546  MHD_UNSIGNED_LONG_LONG ltimeout;
3547  int err_state;
3548  MHD_socket ls;
3549 
3550  timeout.tv_sec = 0;
3551  timeout.tv_usec = 0;
3552  if (daemon->shutdown)
3553  return MHD_NO;
3554  FD_ZERO (&rs);
3555  FD_ZERO (&ws);
3556  FD_ZERO (&es);
3557  maxsock = MHD_INVALID_SOCKET;
3558  err_state = MHD_NO;
3559  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3560  (MHD_YES == resume_suspended_connections (daemon)) &&
3561  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
3562  may_block = MHD_NO;
3563 
3564  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3565  {
3566  /* single-threaded, go over everything */
3567  if (MHD_NO ==
3568  internal_get_fdset2 (daemon,
3569  &rs,
3570  &ws,
3571  &es,
3572  &maxsock,
3573  FD_SETSIZE))
3574  {
3575 #ifdef HAVE_MESSAGES
3576  MHD_DLOG (daemon,
3577  _("Could not obtain daemon fdsets"));
3578 #endif
3579  err_state = MHD_YES;
3580  }
3581  }
3582  else
3583  {
3584  /* accept only, have one thread per connection */
3585  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3586  (! daemon->was_quiesced) &&
3587  (! MHD_add_to_fd_set_ (ls,
3588  &rs,
3589  &maxsock,
3590  FD_SETSIZE)) )
3591  {
3592 #ifdef HAVE_MESSAGES
3593  MHD_DLOG (daemon,
3594  _("Could not add listen socket to fdset"));
3595 #endif
3596  return MHD_NO;
3597  }
3598  }
3599  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3600  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3601  &rs,
3602  &maxsock,
3603  FD_SETSIZE)) )
3604  {
3605 #if defined(MHD_WINSOCK_SOCKETS)
3606  /* fdset limit reached, new connections
3607  cannot be handled. Remove listen socket FD
3608  from fdset and retry to add ITC FD. */
3609  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3610  (! daemon->was_quiesced) )
3611  {
3612  FD_CLR (ls,
3613  &rs);
3614  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
3615  &rs,
3616  &maxsock,
3617  FD_SETSIZE))
3618  {
3619 #endif /* MHD_WINSOCK_SOCKETS */
3620 #ifdef HAVE_MESSAGES
3621  MHD_DLOG (daemon,
3622  _("Could not add control inter-thread communication channel FD to fdset"));
3623 #endif
3624  err_state = MHD_YES;
3625 #if defined(MHD_WINSOCK_SOCKETS)
3626  }
3627  }
3628 #endif /* MHD_WINSOCK_SOCKETS */
3629  }
3630  /* Stop listening if we are at the configured connection limit */
3631  /* If we're at the connection limit, no point in really
3632  accepting new connections; however, make sure we do not miss
3633  the shutdown OR the termination of an existing connection; so
3634  only do this optimization if we have a signaling ITC in
3635  place. */
3636  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3637  (MHD_ITC_IS_VALID_(daemon->itc)) &&
3638  ( (daemon->connections == daemon->connection_limit) ||
3639  (daemon->at_limit) ) )
3640  {
3641  FD_CLR (ls,
3642  &rs);
3643  }
3644  tv = NULL;
3645  if (MHD_YES == err_state)
3646  may_block = MHD_NO;
3647  if (MHD_NO == may_block)
3648  {
3649  timeout.tv_usec = 0;
3650  timeout.tv_sec = 0;
3651  tv = &timeout;
3652  }
3653  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3654  (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
3655  {
3656  /* ltimeout is in ms */
3657  timeout.tv_usec = (ltimeout % 1000) * 1000;
3658  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
3659  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
3660  else
3661  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)(ltimeout / 1000);
3662  tv = &timeout;
3663  }
3664  num_ready = MHD_SYS_select_ (maxsock + 1,
3665  &rs,
3666  &ws,
3667  &es,
3668  tv);
3669  if (daemon->shutdown)
3670  return MHD_NO;
3671  if (num_ready < 0)
3672  {
3673  const int err = MHD_socket_get_error_ ();
3674  if (MHD_SCKT_ERR_IS_EINTR_(err))
3675  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3676 #ifdef HAVE_MESSAGES
3677  MHD_DLOG (daemon,
3678  _("select failed: %s\n"),
3679  MHD_socket_strerr_ (err));
3680 #endif
3681  return MHD_NO;
3682  }
3683  if (MHD_YES == internal_run_from_select (daemon,
3684  &rs,
3685  &ws,
3686  &es))
3687  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3688  return MHD_NO;
3689 }
3690 
3691 
3692 #ifdef HAVE_POLL
3693 
3701 static int
3702 MHD_poll_all (struct MHD_Daemon *daemon,
3703  int may_block)
3704 {
3705  unsigned int num_connections;
3706  struct MHD_Connection *pos;
3707  struct MHD_Connection *prev;
3708 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3709  struct MHD_UpgradeResponseHandle *urh;
3710  struct MHD_UpgradeResponseHandle *urhn;
3711 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3712 
3713  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3714  (MHD_YES == resume_suspended_connections (daemon)) )
3715  may_block = MHD_NO;
3716 
3717  /* count number of connections and thus determine poll set size */
3718  num_connections = 0;
3719  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3720  num_connections++;
3721 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3722  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3723  num_connections += 2;
3724 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3725  {
3726  MHD_UNSIGNED_LONG_LONG ltimeout;
3727  unsigned int i;
3728  int timeout;
3729  unsigned int poll_server;
3730  int poll_listen;
3731  int poll_itc_idx;
3732  struct pollfd *p;
3733  MHD_socket ls;
3734 
3735  p = MHD_calloc_ ((2 + num_connections),
3736  sizeof (struct pollfd));
3737  if (NULL == p)
3738  {
3739 #ifdef HAVE_MESSAGES
3740  MHD_DLOG (daemon,
3741  _("Error allocating memory: %s\n"),
3742  MHD_strerror_(errno));
3743 #endif
3744  return MHD_NO;
3745  }
3746  poll_server = 0;
3747  poll_listen = -1;
3748  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3749  (! daemon->was_quiesced) &&
3750  (daemon->connections < daemon->connection_limit) &&
3751  (! daemon->at_limit) )
3752  {
3753  /* only listen if we are not at the connection limit */
3754  p[poll_server].fd = ls;
3755  p[poll_server].events = POLLIN;
3756  p[poll_server].revents = 0;
3757  poll_listen = (int) poll_server;
3758  poll_server++;
3759  }
3760  poll_itc_idx = -1;
3761  if (MHD_ITC_IS_VALID_(daemon->itc))
3762  {
3763  p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3764  p[poll_server].events = POLLIN;
3765  p[poll_server].revents = 0;
3766  poll_itc_idx = (int) poll_server;
3767  poll_server++;
3768  }
3769  if (may_block == MHD_NO)
3770  timeout = 0;
3771  else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3772  (MHD_YES != MHD_get_timeout (daemon,
3773  &ltimeout)) )
3774  timeout = -1;
3775  else
3776  timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3777 
3778  i = 0;
3779  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
3780  {
3781  p[poll_server+i].fd = pos->socket_fd;
3782  switch (pos->event_loop_info)
3783  {
3785  p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3786  break;
3788  p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3789  break;
3791  p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3792  break;
3794  timeout = 0; /* clean up "pos" immediately */
3795  break;
3796  }
3797  i++;
3798  }
3799 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3800  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3801  {
3802  urh_to_pollfd(urh, &(p[poll_server+i]));
3803  i += 2;
3804  }
3805 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3806  if (0 == poll_server + num_connections)
3807  {
3808  free(p);
3809  return MHD_YES;
3810  }
3811  if (MHD_sys_poll_(p,
3812  poll_server + num_connections,
3813  timeout) < 0)
3814  {
3815  const int err = MHD_socket_get_error_ ();
3816  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3817  {
3818  free(p);
3819  return MHD_YES;
3820  }
3821 #ifdef HAVE_MESSAGES
3822  MHD_DLOG (daemon,
3823  _("poll failed: %s\n"),
3824  MHD_socket_strerr_ (err));
3825 #endif
3826  free(p);
3827  return MHD_NO;
3828  }
3829 
3830  /* Reset. New value will be set when connections are processed. */
3831  daemon->data_already_pending = false;
3832 
3833  /* handle ITC FD */
3834  /* do it before any other processing so
3835  new signals will be processed in next loop */
3836  if ( (-1 != poll_itc_idx) &&
3837  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3838  MHD_itc_clear_ (daemon->itc);
3839 
3840  /* handle shutdown */
3841  if (daemon->shutdown)
3842  {
3843  free(p);
3844  return MHD_NO;
3845  }
3846  i = 0;
3847  prev = daemon->connections_tail;
3848  while (NULL != (pos = prev))
3849  {
3850  prev = pos->prev;
3851  /* first, sanity checks */
3852  if (i >= num_connections)
3853  break; /* connection list changed somehow, retry later ... */
3854  if (p[poll_server+i].fd != pos->socket_fd)
3855  continue; /* fd mismatch, something else happened, retry later ... */
3856  call_handlers (pos,
3857  0 != (p[poll_server+i].revents & POLLIN),
3858  0 != (p[poll_server+i].revents & POLLOUT),
3859  0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
3860  i++;
3861  }
3862 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3863  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3864  {
3865  if (i >= num_connections)
3866  break; /* connection list changed somehow, retry later ... */
3867 
3868  /* Get next connection here as connection can be removed
3869  * from 'daemon->urh_head' list. */
3870  urhn = urh->prev;
3871  /* Check for fd mismatch. FIXME: required for safety? */
3872  if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3873  (p[poll_server+i+1].fd != urh->mhd.socket))
3874  break;
3875  urh_from_pollfd (urh,
3876  &p[poll_server+i]);
3877  i += 2;
3878  process_urh (urh);
3879  /* Finished forwarding? */
3880  if ( (0 == urh->in_buffer_size) &&
3881  (0 == urh->out_buffer_size) &&
3882  (0 == urh->in_buffer_used) &&
3883  (0 == urh->out_buffer_used) )
3884  {
3885  /* MHD_connection_finish_forward_() will remove connection from
3886  * 'daemon->urh_head' list. */
3887  MHD_connection_finish_forward_ (urh->connection);
3888  urh->clean_ready = true;
3889  /* If 'urh->was_closed' already was set to true, connection will be
3890  * moved immediately to cleanup list. Otherwise connection
3891  * will stay in suspended list until 'urh' will be marked
3892  * with 'was_closed' by application. */
3893  MHD_resume_connection(urh->connection);
3894  }
3895  }
3896 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3897  /* handle 'listen' FD */
3898  if ( (-1 != poll_listen) &&
3899  (0 != (p[poll_listen].revents & POLLIN)) )
3900  (void) MHD_accept_connection (daemon);
3901 
3902  free(p);
3903  }
3904  return MHD_YES;
3905 }
3906 
3907 
3915 static int
3916 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3917  int may_block)
3918 {
3919  struct pollfd p[2];
3920  int timeout;
3921  unsigned int poll_count;
3922  int poll_listen;
3923  int poll_itc_idx;
3924  MHD_socket ls;
3925 
3926  memset (&p,
3927  0,
3928  sizeof (p));
3929  poll_count = 0;
3930  poll_listen = -1;
3931  poll_itc_idx = -1;
3932  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3933  (! daemon->was_quiesced) )
3934 
3935  {
3936  p[poll_count].fd = ls;
3937  p[poll_count].events = POLLIN;
3938  p[poll_count].revents = 0;
3939  poll_listen = poll_count;
3940  poll_count++;
3941  }
3942  if (MHD_ITC_IS_VALID_(daemon->itc))
3943  {
3944  p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
3945  p[poll_count].events = POLLIN;
3946  p[poll_count].revents = 0;
3947  poll_itc_idx = poll_count;
3948  poll_count++;
3949  }
3950 
3951  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3952  (void) resume_suspended_connections (daemon);
3953 
3954  if (MHD_NO == may_block)
3955  timeout = 0;
3956  else
3957  timeout = -1;
3958  if (0 == poll_count)
3959  return MHD_YES;
3960  if (MHD_sys_poll_(p,
3961  poll_count,
3962  timeout) < 0)
3963  {
3964  const int err = MHD_socket_get_error_ ();
3965 
3966  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3967  return MHD_YES;
3968 #ifdef HAVE_MESSAGES
3969  MHD_DLOG (daemon,
3970  _("poll failed: %s\n"),
3971  MHD_socket_strerr_ (err));
3972 #endif
3973  return MHD_NO;
3974  }
3975  if ( (-1 != poll_itc_idx) &&
3976  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3977  MHD_itc_clear_ (daemon->itc);
3978 
3979  /* handle shutdown */
3980  if (daemon->shutdown)
3981  return MHD_NO;
3982  if ( (-1 != poll_listen) &&
3983  (0 != (p[poll_listen].revents & POLLIN)) )
3984  (void) MHD_accept_connection (daemon);
3985  return MHD_YES;
3986 }
3987 #endif
3988 
3989 
3997 static int
3998 MHD_poll (struct MHD_Daemon *daemon,
3999  int may_block)
4000 {
4001 #ifdef HAVE_POLL
4002  if (daemon->shutdown)
4003  return MHD_NO;
4004  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4005  return MHD_poll_all (daemon,
4006  may_block);
4007  return MHD_poll_listen_socket (daemon,
4008  may_block);
4009 #else
4010  (void) daemon;
4011  (void) may_block;
4012  return MHD_NO;
4013 #endif
4014 }
4015 
4016 
4017 #ifdef EPOLL_SUPPORT
4018 
4027 #define MAX_EVENTS 128
4028 
4029 
4030 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4031 
4039 static bool
4040 is_urh_ready(struct MHD_UpgradeResponseHandle * const urh)
4041 {
4042  const struct MHD_Connection * const connection = urh->connection;
4043 
4044  if ( (0 == urh->in_buffer_size) &&
4045  (0 == urh->out_buffer_size) &&
4046  (0 == urh->in_buffer_used) &&
4047  (0 == urh->out_buffer_used) )
4048  return false;
4049  if (connection->daemon->shutdown)
4050  return true;
4051  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4052  (connection->tls_read_ready) ) &&
4053  (urh->in_buffer_used < urh->in_buffer_size) )
4054  return true;
4055  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4056  (urh->out_buffer_used < urh->out_buffer_size) )
4057  return true;
4058  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4059  (urh->out_buffer_used > 0) )
4060  return true;
4061  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4062  (urh->in_buffer_used > 0) )
4063  return true;
4064  return false;
4065 }
4066 
4067 
4076 static int
4077 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4078 {
4079  struct epoll_event events[MAX_EVENTS];
4080  int num_events;
4081  struct MHD_UpgradeResponseHandle * pos;
4082  struct MHD_UpgradeResponseHandle * prev;
4083 
4084  num_events = MAX_EVENTS;
4085  while (MAX_EVENTS == num_events)
4086  {
4087  unsigned int i;
4088  /* update event masks */
4089  num_events = epoll_wait (daemon->epoll_upgrade_fd,
4090  events,
4091  MAX_EVENTS,
4092  0);
4093  if (-1 == num_events)
4094  {
4095  const int err = MHD_socket_get_error_ ();
4096  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4097  return MHD_YES;
4098 #ifdef HAVE_MESSAGES
4099  MHD_DLOG (daemon,
4100  _("Call to epoll_wait failed: %s\n"),
4101  MHD_socket_strerr_ (err));
4102 #endif
4103  return MHD_NO;
4104  }
4105  for (i = 0; i < (unsigned int) num_events; i++)
4106  {
4107  struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
4108  struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
4109  bool new_err_state = false;
4110 
4111  if (urh->clean_ready)
4112  continue;
4113 
4114  /* Update ueh state based on what is ready according to epoll() */
4115  if (0 != (events[i].events & EPOLLIN))
4116  ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4117  if (0 != (events[i].events & EPOLLOUT))
4118  ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4119  if (0 != (events[i].events & EPOLLHUP))
4121 
4122  if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4123  (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4124  {
4125  /* Process new error state only one time
4126  * and avoid continuously marking this connection
4127  * as 'ready'. */
4128  ueh->celi |= MHD_EPOLL_STATE_ERROR;
4129  new_err_state = true;
4130  }
4131 
4132  if (! urh->in_eready_list)
4133  {
4134  if (new_err_state ||
4135  is_urh_ready(urh))
4136  {
4137  EDLL_insert (daemon->eready_urh_head,
4138  daemon->eready_urh_tail,
4139  urh);
4140  urh->in_eready_list = true;
4141  }
4142  }
4143  }
4144  }
4145  prev = daemon->eready_urh_tail;
4146  while (NULL != (pos = prev))
4147  {
4148  prev = pos->prevE;
4149  process_urh (pos);
4150  if (! is_urh_ready(pos))
4151  {
4152  EDLL_remove (daemon->eready_urh_head,
4153  daemon->eready_urh_tail,
4154  pos);
4155  pos->in_eready_list = false;
4156  }
4157  /* Finished forwarding? */
4158  if ( (0 == pos->in_buffer_size) &&
4159  (0 == pos->out_buffer_size) &&
4160  (0 == pos->in_buffer_used) &&
4161  (0 == pos->out_buffer_used) )
4162  {
4163  MHD_connection_finish_forward_ (pos->connection);
4164  pos->clean_ready = true;
4165  /* If 'pos->was_closed' already was set to true, connection
4166  * will be moved immediately to cleanup list. Otherwise
4167  * connection will stay in suspended list until 'pos' will
4168  * be marked with 'was_closed' by application. */
4169  MHD_resume_connection(pos->connection);
4170  }
4171  }
4172 
4173  return MHD_YES;
4174 }
4175 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4176 
4177 
4181 static const char * const epoll_itc_marker = "itc_marker";
4182 
4183 
4192 static int
4193 MHD_epoll (struct MHD_Daemon *daemon,
4194  int may_block)
4195 {
4196 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4197  static const char * const upgrade_marker = "upgrade_ptr";
4198 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4199  struct MHD_Connection *pos;
4200  struct MHD_Connection *prev;
4201  struct epoll_event events[MAX_EVENTS];
4202  struct epoll_event event;
4203  int timeout_ms;
4204  MHD_UNSIGNED_LONG_LONG timeout_ll;
4205  int num_events;
4206  unsigned int i;
4207  MHD_socket ls;
4208 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4209  int run_upgraded = MHD_NO;
4210 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4211 
4212  if (-1 == daemon->epoll_fd)
4213  return MHD_NO; /* we're down! */
4214  if (daemon->shutdown)
4215  return MHD_NO;
4216  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4217  (! daemon->was_quiesced) &&
4218  (daemon->connections < daemon->connection_limit) &&
4219  (! daemon->listen_socket_in_epoll) &&
4220  (! daemon->at_limit) )
4221  {
4222  event.events = EPOLLIN;
4223  event.data.ptr = daemon;
4224  if (0 != epoll_ctl (daemon->epoll_fd,
4225  EPOLL_CTL_ADD,
4226  ls,
4227  &event))
4228  {
4229 #ifdef HAVE_MESSAGES
4230  MHD_DLOG (daemon,
4231  _("Call to epoll_ctl failed: %s\n"),
4233 #endif
4234  return MHD_NO;
4235  }
4236  daemon->listen_socket_in_epoll = true;
4237  }
4238  if ( (daemon->was_quiesced) &&
4239  (daemon->listen_socket_in_epoll) )
4240  {
4241  if ( (0 != epoll_ctl (daemon->epoll_fd,
4242  EPOLL_CTL_DEL,
4243  ls,
4244  NULL)) &&
4245  (ENOENT != errno) ) /* ENOENT can happen due to race with
4246  #MHD_quiesce_daemon() */
4247  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4248  daemon->listen_socket_in_epoll = false;
4249  }
4250 
4251 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4252  if ( (! daemon->upgrade_fd_in_epoll) &&
4253  (-1 != daemon->epoll_upgrade_fd) )
4254  {
4255  event.events = EPOLLIN | EPOLLOUT;
4256  event.data.ptr = (void *) upgrade_marker;
4257  if (0 != epoll_ctl (daemon->epoll_fd,
4258  EPOLL_CTL_ADD,
4259  daemon->epoll_upgrade_fd,
4260  &event))
4261  {
4262 #ifdef HAVE_MESSAGES
4263  MHD_DLOG (daemon,
4264  _("Call to epoll_ctl failed: %s\n"),
4266 #endif
4267  return MHD_NO;
4268  }
4269  daemon->upgrade_fd_in_epoll = true;
4270  }
4271 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4272  if ( (daemon->listen_socket_in_epoll) &&
4273  ( (daemon->connections == daemon->connection_limit) ||
4274  (daemon->at_limit) ||
4275  (daemon->was_quiesced) ) )
4276  {
4277  /* we're at the connection limit, disable listen socket
4278  for event loop for now */
4279  if (0 != epoll_ctl (daemon->epoll_fd,
4280  EPOLL_CTL_DEL,
4281  ls,
4282  NULL))
4283  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4284  daemon->listen_socket_in_epoll = false;
4285  }
4286 
4287  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4288  (MHD_YES == resume_suspended_connections (daemon)) )
4289  may_block = MHD_NO;
4290 
4291  if (MHD_YES == may_block)
4292  {
4293  if (MHD_YES == MHD_get_timeout (daemon,
4294  &timeout_ll))
4295  {
4296  if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4297  timeout_ms = INT_MAX;
4298  else
4299  timeout_ms = (int) timeout_ll;
4300  }
4301  else
4302  timeout_ms = -1;
4303  }
4304  else
4305  timeout_ms = 0;
4306 
4307  /* Reset. New value will be set when connections are processed. */
4308  /* Note: Used mostly for uniformity here as same situation is
4309  * signaled in epoll mode by non-empty eready DLL. */
4310  daemon->data_already_pending = false;
4311 
4312  /* drain 'epoll' event queue; need to iterate as we get at most
4313  MAX_EVENTS in one system call here; in practice this should
4314  pretty much mean only one round, but better an extra loop here
4315  than unfair behavior... */
4316  num_events = MAX_EVENTS;
4317  while (MAX_EVENTS == num_events)
4318  {
4319  /* update event masks */
4320  num_events = epoll_wait (daemon->epoll_fd,
4321  events,
4322  MAX_EVENTS,
4323  timeout_ms);
4324  if (-1 == num_events)
4325  {
4326  const int err = MHD_socket_get_error_ ();
4327  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4328  return MHD_YES;
4329 #ifdef HAVE_MESSAGES
4330  MHD_DLOG (daemon,
4331  _("Call to epoll_wait failed: %s\n"),
4332  MHD_socket_strerr_ (err));
4333 #endif
4334  return MHD_NO;
4335  }
4336  for (i=0;i<(unsigned int) num_events;i++)
4337  {
4338  /* First, check for the values of `ptr` that would indicate
4339  that this event is not about a normal connection. */
4340  if (NULL == events[i].data.ptr)
4341  continue; /* shutdown signal! */
4342 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4343  if (upgrade_marker == events[i].data.ptr)
4344  {
4345  /* activity on an upgraded connection, we process
4346  those in a separate epoll() */
4347  run_upgraded = MHD_YES;
4348  continue;
4349  }
4350 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4351  if (epoll_itc_marker == events[i].data.ptr)
4352  {
4353  /* It's OK to clear ITC here as all external
4354  conditions will be processed later. */
4355  MHD_itc_clear_ (daemon->itc);
4356  continue;
4357  }
4358  if (daemon == events[i].data.ptr)
4359  {
4360  /* Check for error conditions on listen socket. */
4361  /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4362  if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4363  {
4364  unsigned int series_length = 0;
4365  /* Run 'accept' until it fails or daemon at limit of connections.
4366  * Do not accept more then 10 connections at once. The rest will
4367  * be accepted on next turn (level trigger is used for listen
4368  * socket). */
4369  while ( (MHD_YES == MHD_accept_connection (daemon)) &&
4370  (series_length < 10) &&
4371  (daemon->connections < daemon->connection_limit) &&
4372  (! daemon->at_limit) )
4373  series_length++;
4374  }
4375  continue;
4376  }
4377  /* this is an event relating to a 'normal' connection,
4378  remember the event and if appropriate mark the
4379  connection as 'eready'. */
4380  pos = events[i].data.ptr;
4381  /* normal processing: update read/write data */
4382  if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4383  {
4384  pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4385  if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4386  {
4387  EDLL_insert (daemon->eready_head,
4388  daemon->eready_tail,
4389  pos);
4390  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4391  }
4392  }
4393  else
4394  {
4395  if (0 != (events[i].events & EPOLLIN))
4396  {
4397  pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4398  if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4399  (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4400  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4401  {
4402  EDLL_insert (daemon->eready_head,
4403  daemon->eready_tail,
4404  pos);
4405  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4406  }
4407  }
4408  if (0 != (events[i].events & EPOLLOUT))
4409  {
4410  pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4411  if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
4412  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4413  {
4414  EDLL_insert (daemon->eready_head,
4415  daemon->eready_tail,
4416  pos);
4417  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4418  }
4419  }
4420  }
4421  }
4422  }
4423 
4424 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4425  if (MHD_YES == run_upgraded)
4426  run_epoll_for_upgrade (daemon);
4427 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4428 
4429  /* process events for connections */
4430  prev = daemon->eready_tail;
4431  while (NULL != (pos = prev))
4432  {
4433  prev = pos->prevE;
4434  call_handlers (pos,
4435  0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
4436  0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
4437  0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
4440  {
4441  if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info &&
4442  0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ) ||
4444  0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ) ||
4446  {
4447  EDLL_remove (daemon->eready_head,
4448  daemon->eready_tail,
4449  pos);
4450  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4451  }
4452  }
4453  }
4454 
4455  /* Finally, handle timed-out connections; we need to do this here
4456  as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
4457  as the other event loops do. As timeouts do not get an explicit
4458  event, we need to find those connections that might have timed out
4459  here.
4460 
4461  Connections with custom timeouts must all be looked at, as we
4462  do not bother to sort that (presumably very short) list. */
4463  prev = daemon->manual_timeout_tail;
4464  while (NULL != (pos = prev))
4465  {
4466  prev = pos->prevX;
4468  }
4469  /* Connections with the default timeout are sorted by prepending
4470  them to the head of the list whenever we touch the connection;
4471  thus it suffices to iterate from the tail until the first
4472  connection is NOT timed out */
4473  prev = daemon->normal_timeout_tail;
4474  while (NULL != (pos = prev))
4475  {
4476  prev = pos->prevX;
4478  if (MHD_CONNECTION_CLOSED != pos->state)
4479  break; /* sorted by timeout, no need to visit the rest! */
4480  }
4481  return MHD_YES;
4482 }
4483 #endif
4484 
4485 
4506 int
4507 MHD_run (struct MHD_Daemon *daemon)
4508 {
4509  if ( (daemon->shutdown) ||
4510  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4511  return MHD_NO;
4512  if (0 != (daemon->options & MHD_USE_POLL))
4513  {
4514  MHD_poll (daemon, MHD_NO);
4515  MHD_cleanup_connections (daemon);
4516  }
4517 #ifdef EPOLL_SUPPORT
4518  else if (0 != (daemon->options & MHD_USE_EPOLL))
4519  {
4520  MHD_epoll (daemon, MHD_NO);
4521  MHD_cleanup_connections (daemon);
4522  }
4523 #endif
4524  else
4525  {
4526  MHD_select (daemon, MHD_NO);
4527  /* MHD_select does MHD_cleanup_connections already */
4528  }
4529  return MHD_YES;
4530 }
4531 
4532 
4541 static void
4543 {
4544  struct MHD_Daemon *daemon = pos->daemon;
4545 
4546  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4547  {
4549  return; /* must let thread to do the rest */
4550  }
4551  MHD_connection_close_ (pos,
4553 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4555 #endif
4556  mhd_assert (! pos->suspended);
4557  mhd_assert (! pos->resuming);
4558  if (pos->connection_timeout == daemon->connection_timeout)
4560  daemon->normal_timeout_tail,
4561  pos);
4562  else
4564  daemon->manual_timeout_tail,
4565  pos);
4566  DLL_remove (daemon->connections_head,
4567  daemon->connections_tail,
4568  pos);
4569  DLL_insert (daemon->cleanup_head,
4570  daemon->cleanup_tail,
4571  pos);
4572 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4574 #endif
4575 }
4576 
4577 
4578 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4579 
4586 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4587 MHD_polling_thread (void *cls)
4588 {
4589  struct MHD_Daemon *daemon = cls;
4590 
4591  MHD_thread_init_(&(daemon->pid));
4592  while (! daemon->shutdown)
4593  {
4594  if (0 != (daemon->options & MHD_USE_POLL))
4595  MHD_poll (daemon, MHD_YES);
4596 #ifdef EPOLL_SUPPORT
4597  else if (0 != (daemon->options & MHD_USE_EPOLL))
4598  MHD_epoll (daemon, MHD_YES);
4599 #endif
4600  else
4601  MHD_select (daemon, MHD_YES);
4602  MHD_cleanup_connections (daemon);
4603  }
4604 
4605  /* Resume any pending for resume connections, join
4606  * all connection's threads (if any) and finally cleanup
4607  * everything. */
4608  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
4610  close_all_connections (daemon);
4611 
4612  return (MHD_THRD_RTRN_TYPE_)0;
4613 }
4614 #endif
4615 
4616 
4628 static size_t
4629 unescape_wrapper (void *cls,
4630  struct MHD_Connection *connection,
4631  char *val)
4632 {
4633  (void) cls; /* Mute compiler warning. */
4634 
4635  (void) connection; /* Mute compiler warning. */
4636  return MHD_http_unescape (val);
4637 }
4638 
4639 
4660 struct MHD_Daemon *
4661 MHD_start_daemon (unsigned int flags,
4662  uint16_t port,
4664  void *apc_cls,
4666  void *dh_cls,
4667  ...)
4668 {
4669  struct MHD_Daemon *daemon;
4670  va_list ap;
4671 
4672  va_start (ap,
4673  dh_cls);
4674  daemon = MHD_start_daemon_va (flags,
4675  port,
4676  apc,
4677  apc_cls,
4678  dh,
4679  dh_cls,
4680  ap);
4681  va_end (ap);
4682  return daemon;
4683 }
4684 
4685 
4705 MHD_socket
4707 {
4708 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4709  unsigned int i;
4710 #endif
4711  MHD_socket ret;
4712 
4713  ret = daemon->listen_fd;
4714  if (MHD_INVALID_SOCKET == ret)
4715  return MHD_INVALID_SOCKET;
4716  if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
4717  (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
4718  {
4719 #ifdef HAVE_MESSAGES
4720  MHD_DLOG (daemon,
4721  "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
4722 #endif
4723  return MHD_INVALID_SOCKET;
4724  }
4725 
4726 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4727  if (NULL != daemon->worker_pool)
4728  for (i = 0; i < daemon->worker_pool_size; i++)
4729  {
4730  daemon->worker_pool[i].was_quiesced = true;
4731 #ifdef EPOLL_SUPPORT
4732  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4733  (-1 != daemon->worker_pool[i].epoll_fd) &&
4734  (daemon->worker_pool[i].listen_socket_in_epoll) )
4735  {
4736  if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4737  EPOLL_CTL_DEL,
4738  ret,
4739  NULL))
4740  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4741  daemon->worker_pool[i].listen_socket_in_epoll = false;
4742  }
4743  else
4744 #endif
4745  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
4746  {
4747  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4748  MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
4749  }
4750  }
4751 #endif
4752  daemon->was_quiesced = true;
4753 #ifdef EPOLL_SUPPORT
4754  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4755  (-1 != daemon->epoll_fd) &&
4756  (daemon->listen_socket_in_epoll) )
4757  {
4758  if ( (0 != epoll_ctl (daemon->epoll_fd,
4759  EPOLL_CTL_DEL,
4760  ret,
4761  NULL)) &&
4762  (ENOENT != errno) ) /* ENOENT can happen due to race with
4763  #MHD_epoll() */
4764  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4765  daemon->listen_socket_in_epoll = false;
4766  }
4767 #endif
4768  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
4769  (! MHD_itc_activate_ (daemon->itc, "q")) )
4770  MHD_PANIC (_("failed to signal quiesce via inter-thread communication channel"));
4771  return ret;
4772 }
4773 
4774 
4782 typedef void
4784  const char *format,
4785  va_list va);
4786 
4787 
4796 static int
4797 parse_options_va (struct MHD_Daemon *daemon,
4798  const struct sockaddr **servaddr,
4799  va_list ap);
4800 
4801 
4810 static int
4811 parse_options (struct MHD_Daemon *daemon,
4812  const struct sockaddr **servaddr,
4813  ...)
4814 {
4815  va_list ap;
4816  int ret;
4817 
4818  va_start (ap, servaddr);
4819  ret = parse_options_va (daemon,
4820  servaddr,
4821  ap);
4822  va_end (ap);
4823  return ret;
4824 }
4825 
4826 
4835 static int
4837  const struct sockaddr **servaddr,
4838  va_list ap)
4839 {
4840  enum MHD_OPTION opt;
4841  struct MHD_OptionItem *oa;
4842  unsigned int i;
4843  unsigned int uv;
4844 #ifdef HTTPS_SUPPORT
4845  int ret;
4846  const char *pstr;
4847 #if GNUTLS_VERSION_MAJOR >= 3
4848  gnutls_certificate_retrieve_function2 *pgcrf;
4849 #endif
4850 #endif /* HTTPS_SUPPORT */
4851 
4852  while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
4853  {
4854  switch (opt)
4855  {
4857  daemon->pool_size = va_arg (ap,
4858  size_t);
4859  break;
4861  daemon->pool_increment= va_arg (ap,
4862  size_t);
4863  break;
4865  daemon->connection_limit = va_arg (ap,
4866  unsigned int);
4867  break;
4869  uv = va_arg (ap,
4870  unsigned int);
4871  /* Next comparison could be always false on some platforms and whole branch will
4872  * be optimized out on those platforms. On others it will be compiled into real
4873  * check. */
4874  if (TIME_T_MAX < uv) /* Compiler may warn on some platforms, ignore warning. */
4875  {
4876 #ifdef HAVE_MESSAGES
4877  MHD_DLOG (daemon,
4878  _("Warning: Too large timeout value, ignored.\n"));
4879 #endif
4880  daemon->connection_timeout = 0;
4881  }
4882  else
4883  daemon->connection_timeout = (time_t)uv;
4884  break;
4886  daemon->notify_completed = va_arg (ap,
4888  daemon->notify_completed_cls = va_arg (ap,
4889  void *);
4890  break;
4892  daemon->notify_connection = va_arg (ap,
4894  daemon->notify_connection_cls = va_arg (ap,
4895  void *);
4896  break;
4898  daemon->per_ip_connection_limit = va_arg (ap,
4899  unsigned int);
4900  break;
4901  case MHD_OPTION_SOCK_ADDR:
4902  *servaddr = va_arg (ap,
4903  const struct sockaddr *);
4904  break;
4906  daemon->uri_log_callback = va_arg (ap,
4907  LogCallback);
4908  daemon->uri_log_callback_cls = va_arg (ap,
4909  void *);
4910  break;
4911 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4913  daemon->worker_pool_size = va_arg (ap,
4914  unsigned int);
4915  if (0 == daemon->worker_pool_size)
4916  {
4917 #ifdef HAVE_MESSAGES
4918  MHD_DLOG (daemon,
4919  _("Warning: Zero size, specified for thread pool size, is ignored. "
4920  "Thread pool is not used.\n"));
4921 #endif
4922  }
4923  else if (1 == daemon->worker_pool_size)
4924  {
4925 #ifdef HAVE_MESSAGES
4926  MHD_DLOG (daemon,
4927  _("Warning: \"1\", specified for thread pool size, is ignored. "
4928  "Thread pool is not used.\n"));
4929 #endif
4930  daemon->worker_pool_size = 0;
4931  }
4932  /* Next comparison could be always false on some platforms and whole branch will
4933  * be optimized out on those platforms. On others it will be compiled into real
4934  * check. */
4935  else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct MHD_Daemon))) /* Compiler may warn on some platforms, ignore warning. */
4936  {
4937 #ifdef HAVE_MESSAGES
4938  MHD_DLOG (daemon,
4939  _("Specified thread pool size (%u) too big\n"),
4940  daemon->worker_pool_size);
4941 #endif
4942  return MHD_NO;
4943  }
4944  else
4945  {
4946  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
4947  {
4948 #ifdef HAVE_MESSAGES
4949  MHD_DLOG (daemon,
4950  _("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
4951  "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
4952 #endif
4953  return MHD_NO;
4954  }
4955  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4956  {
4957 #ifdef HAVE_MESSAGES
4958  MHD_DLOG (daemon,
4959  _("Both MHD_OPTION_THREAD_POOL_SIZE option and "
4960  "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
4961 #endif
4962  return MHD_NO;
4963  }
4964  }
4965  break;
4966 #endif
4967 #ifdef HTTPS_SUPPORT
4969  pstr = va_arg (ap,
4970  const char *);
4971  if (0 != (daemon->options & MHD_USE_TLS))
4972  daemon->https_mem_key = pstr;
4973 #ifdef HAVE_MESSAGES
4974  else
4975  MHD_DLOG (daemon,
4976  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4977  opt);
4978 #endif
4979  break;
4981  pstr = va_arg (ap,
4982  const char *);
4983  if (0 != (daemon->options & MHD_USE_TLS))
4984  daemon->https_key_password = pstr;
4985 #ifdef HAVE_MESSAGES
4986  else
4987  MHD_DLOG (daemon,
4988  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4989  opt);
4990 #endif
4991  break;
4993  pstr = va_arg (ap,
4994  const char *);
4995  if (0 != (daemon->options & MHD_USE_TLS))
4996  daemon->https_mem_cert = pstr;
4997 #ifdef HAVE_MESSAGES
4998  else
4999  MHD_DLOG (daemon,
5000  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
5001  opt);
5002 #endif
5003  break;
5005  pstr = va_arg (ap,
5006  const char *);
5007  if (0 != (daemon->options & MHD_USE_TLS))
5008  daemon->https_mem_trust = pstr;
5009 #ifdef HAVE_MESSAGES
5010  else
5011  MHD_DLOG (daemon,
5012  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
5013  opt);
5014 #endif
5015  break;
5017  daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5018  int);
5019  break;
5021  pstr = va_arg (ap,
5022  const char *);
5023  if (0 != (daemon->options & MHD_USE_TLS))
5024  {
5025  gnutls_datum_t dhpar;
5026 
5027  if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5028  {
5029 #ifdef HAVE_MESSAGES
5030  MHD_DLOG (daemon,
5031  _("Error initializing DH parameters\n"));
5032 #endif
5033  return MHD_NO;
5034  }
5035  dhpar.data = (unsigned char *) pstr;
5036  dhpar.size = strlen (pstr);
5037  if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5038  &dhpar,
5039  GNUTLS_X509_FMT_PEM) < 0)
5040  {
5041 #ifdef HAVE_MESSAGES
5042  MHD_DLOG (daemon,
5043  _("Bad Diffie-Hellman parameters format\n"));
5044 #endif
5045  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5046  return MHD_NO;
5047  }
5048  daemon->have_dhparams = true;
5049  }
5050 #ifdef HAVE_MESSAGES
5051  else
5052  MHD_DLOG (daemon,
5053  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
5054  opt);
5055 #endif
5056  break;
5058  pstr = va_arg (ap,
5059  const char *);
5060  if (0 != (daemon->options & MHD_USE_TLS))
5061  {
5062  gnutls_priority_deinit (daemon->priority_cache);
5063  ret = gnutls_priority_init (&daemon->priority_cache,
5064  pstr,
5065  NULL);
5066  if (GNUTLS_E_SUCCESS != ret)
5067  {
5068 #ifdef HAVE_MESSAGES
5069  MHD_DLOG (daemon,
5070  _("Setting priorities to `%s' failed: %s\n"),
5071  pstr,
5072  gnutls_strerror (ret));
5073 #endif
5074  daemon->priority_cache = NULL;
5075  return MHD_NO;
5076  }
5077  }
5078 #ifdef HAVE_MESSAGES
5079  else
5080  MHD_DLOG (daemon,
5081  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
5082  opt);
5083 #endif
5084  break;
5086 #if GNUTLS_VERSION_MAJOR < 3
5087 #ifdef HAVE_MESSAGES
5088  MHD_DLOG (daemon,
5089  _("MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
5090 #endif
5091  return MHD_NO;
5092 #else
5093  pgcrf = va_arg (ap,
5094  gnutls_certificate_retrieve_function2 *);
5095  if (0 != (daemon->options & MHD_USE_TLS))
5096  daemon->cert_callback = pgcrf;
5097  else
5098 #ifdef HAVE_MESSAGES
5099  MHD_DLOG (daemon,
5100  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
5101  opt);
5102 #endif
5103  break;
5104 #endif
5105 #endif /* HTTPS_SUPPORT */
5106 #ifdef DAUTH_SUPPORT
5108  daemon->digest_auth_rand_size = va_arg (ap,
5109  size_t);
5110  daemon->digest_auth_random = va_arg (ap,
5111  const char *);
5112  break;
5114  daemon->nonce_nc_size = va_arg (ap,
5115  unsigned int);
5116  break;
5117 #endif
5119  if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5120  {
5121 #ifdef HAVE_MESSAGES
5122  MHD_DLOG (daemon,
5123  _("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5124  "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5125 #endif
5126  return MHD_NO;
5127  }
5128  else
5129  daemon->listen_fd = va_arg (ap,
5130  MHD_socket);
5131  break;
5133 #ifdef HAVE_MESSAGES
5134  daemon->custom_error_log = va_arg (ap,
5136  daemon->custom_error_log_cls = va_arg (ap,
5137  void *);
5138 #else
5139  va_arg (ap,
5141  va_arg (ap,
5142  void *);
5143 #endif
5144  break;
5145 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5147  daemon->thread_stack_size = va_arg (ap,
5148  size_t);
5149  break;
5150 #endif
5151 #ifdef TCP_FASTOPEN
5153  daemon->fastopen_queue_size = va_arg (ap,
5154  unsigned int);
5155  break;
5156 #endif
5158  daemon->listening_address_reuse = va_arg (ap,
5159  unsigned int) ? 1 : -1;
5160  break;
5162  daemon->listen_backlog_size = va_arg (ap,
5163  unsigned int);
5164  break;
5166  daemon->strict_for_client = va_arg (ap, int);;
5167 #ifdef HAVE_MESSAGES
5168  if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
5169  (1 != daemon->strict_for_client) )
5170  {
5171  MHD_DLOG (daemon,
5172  _("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5173  "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5174  }
5175 #endif /* HAVE_MESSAGES */
5176  break;
5177  case MHD_OPTION_ARRAY:
5178  oa = va_arg (ap, struct MHD_OptionItem*);
5179  i = 0;
5180  while (MHD_OPTION_END != (opt = oa[i].option))
5181  {
5182  switch (opt)
5183  {
5184  /* all options taking 'size_t' */
5188  if (MHD_YES != parse_options (daemon,
5189  servaddr,
5190  opt,
5191  (size_t) oa[i].value,
5192  MHD_OPTION_END))
5193  return MHD_NO;
5194  break;
5195  /* all options taking 'unsigned int' */
5204  if (MHD_YES != parse_options (daemon,
5205  servaddr,
5206  opt,
5207  (unsigned int) oa[i].value,
5208  MHD_OPTION_END))
5209  return MHD_NO;
5210  break;
5211  /* all options taking 'enum' */
5212 #ifdef HTTPS_SUPPORT
5214  if (MHD_YES != parse_options (daemon,
5215  servaddr,
5216  opt,
5217  (gnutls_credentials_type_t) oa[i].value,
5218  MHD_OPTION_END))
5219  return MHD_NO;
5220  break;
5221 #endif /* HTTPS_SUPPORT */
5222  /* all options taking 'MHD_socket' */
5224  if (MHD_YES != parse_options (daemon,
5225  servaddr,
5226  opt,
5227  (MHD_socket) oa[i].value,
5228  MHD_OPTION_END))
5229  return MHD_NO;
5230  break;
5231  /* all options taking 'int' */
5233  if (MHD_YES != parse_options (daemon,
5234  servaddr,
5235  opt,
5236  (int) oa[i].value,
5237  MHD_OPTION_END))
5238  return MHD_NO;
5239  break;
5240  /* all options taking one pointer */
5241  case MHD_OPTION_SOCK_ADDR:
5248  case MHD_OPTION_ARRAY:
5250  if (MHD_YES != parse_options (daemon,
5251  servaddr,
5252  opt,
5253  oa[i].ptr_value,
5254  MHD_OPTION_END))
5255  return MHD_NO;
5256  break;
5257  /* all options taking two pointers */
5264  if (MHD_YES != parse_options (daemon,
5265  servaddr,
5266  opt,
5267  (void *) oa[i].value,
5268  oa[i].ptr_value,
5269  MHD_OPTION_END))
5270  return MHD_NO;
5271  break;
5272  /* options taking size_t-number followed by pointer */
5274  if (MHD_YES != parse_options (daemon,
5275  servaddr,
5276  opt,
5277  (size_t) oa[i].value,
5278  oa[i].ptr_value,
5279  MHD_OPTION_END))
5280  return MHD_NO;
5281  break;
5282  default:
5283  return MHD_NO;
5284  }
5285  i++;
5286  }
5287  break;
5289  daemon->unescape_callback = va_arg (ap,
5291  daemon->unescape_callback_cls = va_arg (ap,
5292  void *);
5293  break;
5294 #ifdef HTTPS_SUPPORT
5296 #if GNUTLS_VERSION_MAJOR >= 3
5297  daemon->cred_callback = va_arg (ap,
5299  daemon->cred_callback_cls = va_arg (ap,
5300  void *);
5301  break;
5302 #else
5303  MHD_DLOG (daemon,
5304  _("MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3\n"),
5305  opt);
5306  return MHD_NO;
5307 #endif
5308 #endif /* HTTPS_SUPPORT */
5309  default:
5310 #ifdef HAVE_MESSAGES
5311  if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
5312  (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
5313  (opt == MHD_OPTION_HTTPS_MEM_TRUST) ||
5315  {
5316  MHD_DLOG (daemon,
5317  _("MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
5318  opt);
5319  }
5320  else
5321  {
5322  MHD_DLOG (daemon,
5323  _("Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
5324  opt);
5325  }
5326 #endif
5327  return MHD_NO;
5328  }
5329  }
5330  return MHD_YES;
5331 }
5332 
5333 
5334 #ifdef EPOLL_SUPPORT
5335 static int
5336 setup_epoll_fd (struct MHD_Daemon *daemon)
5337 {
5338  int fd;
5339 
5340 #ifndef HAVE_MESSAGES
5341  (void)daemon; /* Mute compiler warning. */
5342 #endif /* ! HAVE_MESSAGES */
5343 
5344 #ifdef USE_EPOLL_CREATE1
5345  fd = epoll_create1 (EPOLL_CLOEXEC);
5346 #else /* ! USE_EPOLL_CREATE1 */
5347  fd = epoll_create (MAX_EVENTS);
5348 #endif /* ! USE_EPOLL_CREATE1 */
5349  if (MHD_INVALID_SOCKET == fd)
5350  {
5351 #ifdef HAVE_MESSAGES
5352  MHD_DLOG (daemon,
5353  _("Call to epoll_create1 failed: %s\n"),
5355 #endif
5356  return MHD_INVALID_SOCKET;
5357  }
5358 #if !defined(USE_EPOLL_CREATE1)
5359  if (! MHD_socket_noninheritable_ (fd))
5360  {
5361 #ifdef HAVE_MESSAGES
5362  MHD_DLOG (daemon,
5363  _("Failed to set noninheritable mode on epoll FD.\n"));
5364 #endif
5365  }
5366 #endif /* ! USE_EPOLL_CREATE1 */
5367  return fd;
5368 }
5369 
5370 
5380 static int
5381 setup_epoll_to_listen (struct MHD_Daemon *daemon)
5382 {
5383  struct epoll_event event;
5384  MHD_socket ls;
5385 
5386  daemon->epoll_fd = setup_epoll_fd (daemon);
5387  if (-1 == daemon->epoll_fd)
5388  return MHD_NO;
5389 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5390  if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
5391  {
5392  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5393  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
5394  return MHD_NO;
5395  }
5396 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5397  if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
5398  (daemon->was_quiesced) )
5399  return MHD_YES; /* non-listening daemon */
5400  event.events = EPOLLIN;
5401  event.data.ptr = daemon;
5402  if (0 != epoll_ctl (daemon->epoll_fd,
5403  EPOLL_CTL_ADD,
5404  ls,
5405  &event))
5406  {
5407 #ifdef HAVE_MESSAGES
5408  MHD_DLOG (daemon,
5409  _("Call to epoll_ctl failed: %s\n"),
5411 #endif
5412  return MHD_NO;
5413  }
5414  daemon->listen_socket_in_epoll = true;
5415  if (MHD_ITC_IS_VALID_(daemon->itc))
5416  {
5417  event.events = EPOLLIN;
5418  event.data.ptr = (void *) epoll_itc_marker;
5419  if (0 != epoll_ctl (daemon->epoll_fd,
5420  EPOLL_CTL_ADD,
5421  MHD_itc_r_fd_ (daemon->itc),
5422  &event))
5423  {
5424 #ifdef HAVE_MESSAGES
5425  MHD_DLOG (daemon,
5426  _("Call to epoll_ctl failed: %s\n"),
5428 #endif
5429  return MHD_NO;
5430  }
5431  }
5432  return MHD_YES;
5433 }
5434 #endif
5435 
5436 
5458 struct MHD_Daemon *
5459 MHD_start_daemon_va (unsigned int flags,
5460  uint16_t port,
5462  void *apc_cls,
5464  void *dh_cls,
5465  va_list ap)
5466 {
5467  const MHD_SCKT_OPT_BOOL_ on = 1;
5468  struct MHD_Daemon *daemon;
5470  struct sockaddr_in servaddr4;
5471 #if HAVE_INET6
5472  struct sockaddr_in6 servaddr6;
5473 #endif
5474  const struct sockaddr *servaddr = NULL;
5475  socklen_t addrlen;
5476 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5477  unsigned int i;
5478 #endif
5479  enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
5480  enum MHD_FLAG *pflags;
5481 
5483  eflags = (enum MHD_FLAG) flags;
5484  pflags = &eflags;
5485 #ifndef HAVE_INET6
5486  if (0 != (*pflags & MHD_USE_IPv6))
5487  return NULL;
5488 #endif
5489 #ifndef HAVE_POLL
5490  if (0 != (*pflags & MHD_USE_POLL))
5491  return NULL;
5492 #endif
5493 #ifndef EPOLL_SUPPORT
5494  if (0 != (*pflags & MHD_USE_EPOLL))
5495  return NULL;
5496 #endif /* ! EPOLL_SUPPORT */
5497 #ifndef HTTPS_SUPPORT
5498  if (0 != (*pflags & MHD_USE_TLS))
5499  return NULL;
5500 #endif /* ! HTTPS_SUPPORT */
5501 #ifndef TCP_FASTOPEN
5502  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5503  return NULL;
5504 #endif
5505  if (0 != (*pflags & MHD_ALLOW_UPGRADE))
5506  {
5507 #ifdef UPGRADE_SUPPORT
5508  *pflags |= MHD_ALLOW_SUSPEND_RESUME;
5509 #else /* ! UPGRADE_SUPPORT */
5510  return NULL;
5511 #endif /* ! UPGRADE_SUPPORT */
5512  }
5513  if (NULL == dh)
5514  return NULL;
5515 
5516  /* Check for invalid combinations of flags. */
5517  if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5518  ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))) ||
5519  ((0 != (*pflags & MHD_USE_POLL)) &&
5521  ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)))) )
5522  return NULL;
5523 
5524  if (0 != (*pflags & MHD_USE_AUTO))
5525  {
5526  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5527  {
5528  /* Thread per connection with internal polling thread. */
5529 #ifdef HAVE_POLL
5530  *pflags |= MHD_USE_POLL;
5531 #else /* ! HAVE_POLL */
5532  /* use select() - do not modify flags */
5533 #endif /* ! HAVE_POLL */
5534  }
5535  else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5536  {
5537  /* Internal polling thread. */
5538 #if defined(EPOLL_SUPPORT)
5539  *pflags |= MHD_USE_EPOLL;
5540 #elif defined(HAVE_POLL)
5541  *pflags |= MHD_USE_POLL;
5542 #else /* !HAVE_POLL && !EPOLL_SUPPORT */
5543  /* use select() - do not modify flags */
5544 #endif /* !HAVE_POLL && !EPOLL_SUPPORT */
5545  }
5546  else
5547  {
5548  /* Internal threads are not used - "external" polling mode. */
5549 #if defined(EPOLL_SUPPORT)
5550  *pflags |= MHD_USE_EPOLL;
5551 #else /* ! EPOLL_SUPPORT */
5552  /* use select() - do not modify flags */
5553 #endif /* ! EPOLL_SUPPORT */
5554  }
5555  }
5556 
5557  if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
5558  return NULL;
5559 #ifdef EPOLL_SUPPORT
5560  daemon->epoll_fd = -1;
5561 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5562  daemon->epoll_upgrade_fd = -1;
5563 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5564 #endif
5565  /* try to open listen socket */
5566 #ifdef HTTPS_SUPPORT
5567  daemon->priority_cache = NULL;
5568  if (0 != (*pflags & MHD_USE_TLS))
5569  {
5570  gnutls_priority_init (&daemon->priority_cache,
5571  "NORMAL",
5572  NULL);
5573  }
5574 #endif /* HTTPS_SUPPORT */
5575  daemon->listen_fd = MHD_INVALID_SOCKET;
5576  daemon->listening_address_reuse = 0;
5577  daemon->options = *pflags;
5578  pflags = &daemon->options;
5579  daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 : 0;
5580  daemon->port = port;
5581  daemon->apc = apc;
5582  daemon->apc_cls = apc_cls;
5583  daemon->default_handler = dh;
5584  daemon->default_handler_cls = dh_cls;
5585  daemon->connections = 0;
5587  daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
5588  daemon->pool_increment = MHD_BUF_INC_SIZE;
5590  daemon->connection_timeout = 0; /* no timeout */
5591  MHD_itc_set_invalid_ (daemon->itc);
5592 #ifdef SOMAXCONN
5593  daemon->listen_backlog_size = SOMAXCONN;
5594 #else /* !SOMAXCONN */
5595  daemon->listen_backlog_size = 511; /* should be safe value */
5596 #endif /* !SOMAXCONN */
5597 #ifdef HAVE_MESSAGES
5598  daemon->custom_error_log = (MHD_LogCallback) &vfprintf;
5599  daemon->custom_error_log_cls = stderr;
5600 #endif
5601  if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
5602  (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
5603  {
5604 #ifdef HAVE_MESSAGES
5605  MHD_DLOG (daemon,
5606  _("Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5607  "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5608  "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5609 #endif
5611  }
5612  if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5613  *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
5614  else
5615  {
5616 #ifdef HAVE_LISTEN_SHUTDOWN
5617  if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
5618 #endif
5619  *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
5620  }
5621 #ifdef DAUTH_SUPPORT
5622  daemon->digest_auth_rand_size = 0;
5623  daemon->digest_auth_random = NULL;
5624  daemon->nonce_nc_size = 4; /* tiny */
5625 #endif
5626 #ifdef HTTPS_SUPPORT
5627  if (0 != (*pflags & MHD_USE_TLS))
5628  {
5629  daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5630  }
5631 #endif /* HTTPS_SUPPORT */
5632 
5633 
5634  if (MHD_YES != parse_options_va (daemon,
5635  &servaddr,
5636  ap))
5637  {
5638 #ifdef HTTPS_SUPPORT
5639  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5640  (NULL != daemon->priority_cache) )
5641  gnutls_priority_deinit (daemon->priority_cache);
5642 #endif /* HTTPS_SUPPORT */
5643  free (daemon);
5644  return NULL;
5645  }
5646 
5647  if ( (NULL != daemon->notify_completed) &&
5648  (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
5649  *pflags |= MHD_USE_ITC; /* requires ITC */
5650 
5651 #ifndef NDEBUG
5652 #ifdef HAVE_MESSAGES
5653  MHD_DLOG (daemon,
5654  _("Using debug build of libmicrohttpd.\n") );
5655 #endif /* HAVE_MESSAGES */
5656 #endif /* ! NDEBUG */
5657 
5658  if ( (0 != (*pflags & MHD_USE_ITC))
5659 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5660  && (0 == daemon->worker_pool_size)
5661 #endif
5662  )
5663  {
5664  if (! MHD_itc_init_ (daemon->itc))
5665  {
5666 #ifdef HAVE_MESSAGES
5667  MHD_DLOG (daemon,
5668  _("Failed to create inter-thread communication channel: %s\n"),
5669  MHD_itc_last_strerror_ ());
5670 #endif
5671 #ifdef HTTPS_SUPPORT
5672  if (NULL != daemon->priority_cache)
5673  gnutls_priority_deinit (daemon->priority_cache);
5674 #endif /* HTTPS_SUPPORT */
5675  free (daemon);
5676  return NULL;
5677  }
5678  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5679  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
5680  NULL)) )
5681  {
5682 #ifdef HAVE_MESSAGES
5683  MHD_DLOG (daemon,
5684  _("file descriptor for inter-thread communication channel exceeds maximum value\n"));
5685 #endif
5686  MHD_itc_destroy_chk_ (daemon->itc);
5687 #ifdef HTTPS_SUPPORT
5688  if (NULL != daemon->priority_cache)
5689  gnutls_priority_deinit (daemon->priority_cache);
5690 #endif /* HTTPS_SUPPORT */
5691  free (daemon);
5692  return NULL;
5693  }
5694  }
5695 
5696 #ifdef DAUTH_SUPPORT
5697  if (daemon->nonce_nc_size > 0)
5698  {
5699  if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc))) /
5700  sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
5701  {
5702 #ifdef HAVE_MESSAGES
5703  MHD_DLOG (daemon,
5704  _("Specified value for NC_SIZE too large\n"));
5705 #endif
5706 #ifdef HTTPS_SUPPORT
5707  if (0 != (*pflags & MHD_USE_TLS))
5708  gnutls_priority_deinit (daemon->priority_cache);
5709 #endif /* HTTPS_SUPPORT */
5710  free (daemon);
5711  return NULL;
5712  }
5713  daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
5714  if (NULL == daemon->nnc)
5715  {
5716 #ifdef HAVE_MESSAGES
5717  MHD_DLOG (daemon,
5718  _("Failed to allocate memory for nonce-nc map: %s\n"),
5719  MHD_strerror_ (errno));
5720 #endif
5721 #ifdef HTTPS_SUPPORT
5722  if (0 != (*pflags & MHD_USE_TLS))
5723  gnutls_priority_deinit (daemon->priority_cache);
5724 #endif /* HTTPS_SUPPORT */
5725  free (daemon);
5726  return NULL;
5727  }
5728  }
5729 
5730 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5731  if (! MHD_mutex_init_ (&daemon->nnc_lock))
5732  {
5733 #ifdef HAVE_MESSAGES
5734  MHD_DLOG (daemon,
5735  _("MHD failed to initialize nonce-nc mutex\n"));
5736 #endif
5737 #ifdef HTTPS_SUPPORT
5738  if (0 != (*pflags & MHD_USE_TLS))
5739  gnutls_priority_deinit (daemon->priority_cache);
5740 #endif /* HTTPS_SUPPORT */
5741  free (daemon->nnc);
5742  free (daemon);
5743  return NULL;
5744  }
5745 #endif
5746 #endif
5747 
5748  /* Thread pooling currently works only with internal select thread mode */
5749 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5750  if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5751  (daemon->worker_pool_size > 0) )
5752  {
5753 #ifdef HAVE_MESSAGES
5754  MHD_DLOG (daemon,
5755  _("MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"));
5756 #endif
5757  goto free_and_fail;
5758  }
5759 #endif
5760  if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
5761  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5762  {
5763  /* try to open listen socket */
5764  int domain;
5765 
5766 #ifdef HAVE_INET6
5767  domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
5768 #else /* ! HAVE_INET6 */
5769  if (*pflags & MHD_USE_IPv6)
5770  goto free_and_fail;
5771  domain = PF_INET;
5772 #endif /* ! HAVE_INET6 */
5773 
5774  listen_fd = MHD_socket_create_listen_(domain);
5775  if (MHD_INVALID_SOCKET == listen_fd)
5776  {
5777 #ifdef HAVE_MESSAGES
5778  MHD_DLOG (daemon,
5779  _("Failed to create socket for listening: %s\n"),
5781 #endif
5782  goto free_and_fail;
5783  }
5784 
5785  /* Apply the socket options according to listening_address_reuse. */
5786  if (0 == daemon->listening_address_reuse)
5787  {
5788 #ifndef MHD_WINSOCK_SOCKETS
5789  /* No user requirement, use "traditional" default SO_REUSEADDR
5790  * on non-W32 platforms, and do not fail if it doesn't work.
5791  * Don't use it on W32, because on W32 it will allow multiple
5792  * bind to the same address:port, like SO_REUSEPORT on others. */
5793  if (0 > setsockopt (listen_fd,
5794  SOL_SOCKET,
5795  SO_REUSEADDR,
5796  (void*)&on, sizeof (on)))
5797  {
5798 #ifdef HAVE_MESSAGES
5799  MHD_DLOG (daemon,
5800  _("setsockopt failed: %s\n"),
5802 #endif
5803  }
5804 #endif /* ! MHD_WINSOCK_SOCKETS */
5805  }
5806  else if (daemon->listening_address_reuse > 0)
5807  {
5808  /* User requested to allow reusing listening address:port. */
5809 #ifndef MHD_WINSOCK_SOCKETS
5810  /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
5811  * it doesn't work. */
5812  if (0 > setsockopt (listen_fd,
5813  SOL_SOCKET,
5814  SO_REUSEADDR,
5815  (void*)&on, sizeof (on)))
5816  {
5817 #ifdef HAVE_MESSAGES
5818  MHD_DLOG (daemon,
5819  _("setsockopt failed: %s\n"),
5821 #endif
5822  }
5823 #endif /* ! MHD_WINSOCK_SOCKETS */
5824  /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
5825  * Fail if SO_REUSEPORT is not defined or setsockopt fails.
5826  */
5827  /* SO_REUSEADDR on W32 has the same semantics
5828  as SO_REUSEPORT on BSD/Linux */
5829 #if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
5830  if (0 > setsockopt (listen_fd,
5831  SOL_SOCKET,
5832 #ifndef MHD_WINSOCK_SOCKETS
5833  SO_REUSEPORT,
5834 #else /* MHD_WINSOCK_SOCKETS */
5835  SO_REUSEADDR,
5836 #endif /* MHD_WINSOCK_SOCKETS */
5837  (void *) &on,
5838  sizeof (on)))
5839  {
5840 #ifdef HAVE_MESSAGES
5841  MHD_DLOG (daemon,
5842  _("setsockopt failed: %s\n"),
5844 #endif
5845  goto free_and_fail;
5846  }
5847 #else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
5848  /* we're supposed to allow address:port re-use, but
5849  on this platform we cannot; fail hard */
5850 #ifdef HAVE_MESSAGES
5851  MHD_DLOG (daemon,
5852  _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
5853 #endif
5854  goto free_and_fail;
5855 #endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
5856  }
5857  else /* if (daemon->listening_address_reuse < 0) */
5858  {
5859  /* User requested to disallow reusing listening address:port.
5860  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
5861  * is used and Solaris with SO_EXCLBIND.
5862  * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
5863  * or setsockopt fails.
5864  */
5865 #if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
5866  (defined(__sun) && defined(SO_EXCLBIND))
5867  if (0 > setsockopt (listen_fd,
5868  SOL_SOCKET,
5869 #ifdef SO_EXCLUSIVEADDRUSE
5870  SO_EXCLUSIVEADDRUSE,
5871 #else /* SO_EXCLBIND */
5872  SO_EXCLBIND,
5873 #endif /* SO_EXCLBIND */
5874  (void *) &on,
5875  sizeof (on)))
5876  {
5877 #ifdef HAVE_MESSAGES
5878  MHD_DLOG (daemon,
5879  _("setsockopt failed: %s\n"),
5881 #endif
5882  goto free_and_fail;
5883  }
5884 #elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
5885 #ifdef HAVE_MESSAGES
5886  MHD_DLOG (daemon,
5887  _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
5888 #endif
5889  goto free_and_fail;
5890 #endif /* MHD_WINSOCK_SOCKETS */
5891  }
5892 
5893  /* check for user supplied sockaddr */
5894 #if HAVE_INET6
5895  if (0 != (*pflags & MHD_USE_IPv6))
5896  addrlen = sizeof (struct sockaddr_in6);
5897  else
5898 #endif
5899  addrlen = sizeof (struct sockaddr_in);
5900  if (NULL == servaddr)
5901  {
5902 #if HAVE_INET6
5903  if (0 != (*pflags & MHD_USE_IPv6))
5904  {
5905 #ifdef IN6ADDR_ANY_INIT
5906  static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
5907 #endif
5908  memset (&servaddr6,
5909  0,
5910  sizeof (struct sockaddr_in6));
5911  servaddr6.sin6_family = AF_INET6;
5912  servaddr6.sin6_port = htons (port);
5913 #ifdef IN6ADDR_ANY_INIT
5914  servaddr6.sin6_addr = static_in6any;
5915 #endif
5916 #if HAVE_SOCKADDR_IN_SIN_LEN
5917  servaddr6.sin6_len = sizeof (struct sockaddr_in6);
5918 #endif
5919  servaddr = (struct sockaddr *) &servaddr6;
5920  }
5921  else
5922 #endif
5923  {
5924  memset (&servaddr4,
5925  0,
5926  sizeof (struct sockaddr_in));
5927  servaddr4.sin_family = AF_INET;
5928  servaddr4.sin_port = htons (port);
5929  if (0 != INADDR_ANY)
5930  servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
5931 #if HAVE_SOCKADDR_IN_SIN_LEN
5932  servaddr4.sin_len = sizeof (struct sockaddr_in);
5933 #endif
5934  servaddr = (struct sockaddr *) &servaddr4;
5935  }
5936  }
5937  daemon->listen_fd = listen_fd;
5938 
5939  if (0 != (*pflags & MHD_USE_IPv6))
5940  {
5941 #ifdef IPPROTO_IPV6
5942 #ifdef IPV6_V6ONLY
5943  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
5944  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
5945  and may also be missing on older POSIX systems; good luck if you have any of those,
5946  your IPv6 socket may then also bind against IPv4 anyway... */
5947  const MHD_SCKT_OPT_BOOL_ v6_only =
5948  (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
5949  if (0 > setsockopt (listen_fd,
5950  IPPROTO_IPV6, IPV6_V6ONLY,
5951  (const void *) &v6_only,
5952  sizeof (v6_only)))
5953  {
5954 #ifdef HAVE_MESSAGES
5955  MHD_DLOG (daemon,
5956  _("setsockopt failed: %s\n"),
5958 #endif
5959  }
5960 #endif
5961 #endif
5962  }
5963  if (-1 == bind (listen_fd, servaddr, addrlen))
5964  {
5965 #ifdef HAVE_MESSAGES
5966  MHD_DLOG (daemon,
5967  _("Failed to bind to port %u: %s\n"),
5968  (unsigned int) port,
5970 #endif
5971  MHD_socket_close_chk_ (listen_fd);
5972  goto free_and_fail;
5973  }
5974 #ifdef TCP_FASTOPEN
5975  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5976  {
5977  if (0 == daemon->fastopen_queue_size)
5978  daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
5979  if (0 != setsockopt (listen_fd,
5980  IPPROTO_TCP,
5981  TCP_FASTOPEN,
5982  (const void*)&daemon->fastopen_queue_size,
5983  sizeof (daemon->fastopen_queue_size)))
5984  {
5985 #ifdef HAVE_MESSAGES
5986  MHD_DLOG (daemon,
5987  _("setsockopt failed: %s\n"),
5989 #endif
5990  }
5991  }
5992 #endif
5993  if (listen (listen_fd,
5994  daemon->listen_backlog_size) < 0)
5995  {
5996 #ifdef HAVE_MESSAGES
5997  MHD_DLOG (daemon,
5998  _("Failed to listen for connections: %s\n"),
6000 #endif
6001  MHD_socket_close_chk_ (listen_fd);
6002  goto free_and_fail;
6003  }
6004  }
6005  else
6006  {
6007  listen_fd = daemon->listen_fd;
6008  }
6009 
6010  if ( (0 == daemon->port) &&
6011  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6012  { /* Get port number. */
6013  struct sockaddr_storage servaddr;
6014 
6015  memset (&servaddr,
6016  0,
6017  sizeof (struct sockaddr_storage));
6018  addrlen = sizeof (servaddr);
6019  if (0 != getsockname (listen_fd,
6020  (struct sockaddr *) &servaddr,
6021  &addrlen))
6022  {
6023 #ifdef HAVE_MESSAGES
6024  MHD_DLOG (daemon,
6025  _("Failed to get listen port number: %s\n"),
6027 #endif /* HAVE_MESSAGES */
6028  }
6029 #ifdef MHD_POSIX_SOCKETS
6030  else if (sizeof (servaddr) < addrlen)
6031  {
6032  /* should be impossible with `struct sockaddr_storage` */
6033 #ifdef HAVE_MESSAGES
6034  MHD_DLOG (daemon,
6035  _("Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"));
6036 #endif /* HAVE_MESSAGES */
6037  }
6038 #endif /* MHD_POSIX_SOCKETS */
6039  else
6040  {
6041  switch (servaddr.ss_family)
6042  {
6043  case AF_INET:
6044  {
6045  struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
6046 
6047  daemon->port = ntohs (s4->sin_port);
6048  break;
6049  }
6050 #ifdef HAVE_INET6
6051  case AF_INET6:
6052  {
6053  struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
6054 
6055  daemon->port = ntohs(s6->sin6_port);
6056  mhd_assert (0 != (*pflags & MHD_USE_IPv6));
6057  break;
6058  }
6059 #endif /* HAVE_INET6 */
6060 #ifdef AF_UNIX
6061  case AF_UNIX:
6062  daemon->port = 0; /* special value for UNIX domain sockets */
6063  break;
6064 #endif
6065  default:
6066 #ifdef HAVE_MESSAGES
6067  MHD_DLOG (daemon,
6068  _("Unknown address family!\n"));
6069 #endif
6070  daemon->port = 0; /* ugh */
6071  break;
6072  }
6073  }
6074  }
6075 
6076  if ( (MHD_INVALID_SOCKET != listen_fd) &&
6077  (! MHD_socket_nonblocking_ (listen_fd)) )
6078  {
6079 #ifdef HAVE_MESSAGES
6080  MHD_DLOG (daemon,
6081  _("Failed to set nonblocking mode on listening socket: %s\n"),
6083 #endif
6084  if (0 != (*pflags & MHD_USE_EPOLL)
6085 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6086  || (daemon->worker_pool_size > 0)
6087 #endif
6088  )
6089  {
6090  /* Accept must be non-blocking. Multiple children may wake up
6091  * to handle a new connection, but only one will win the race.
6092  * The others must immediately return. */
6093  MHD_socket_close_chk_ (listen_fd);
6094  goto free_and_fail;
6095  }
6096  }
6097  if ( (MHD_INVALID_SOCKET != listen_fd) &&
6098  (! MHD_SCKT_FD_FITS_FDSET_(listen_fd,
6099  NULL)) &&
6100  (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
6101  {
6102 #ifdef HAVE_MESSAGES
6103  MHD_DLOG (daemon,
6104  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
6105  listen_fd,
6106  FD_SETSIZE);
6107 #endif
6108  MHD_socket_close_chk_ (listen_fd);
6109  goto free_and_fail;
6110  }
6111 
6112 #ifdef EPOLL_SUPPORT
6113  if ( (0 != (*pflags & MHD_USE_EPOLL))
6114 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6115  && (0 == daemon->worker_pool_size)
6116 #endif
6117  )
6118  {
6119  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
6120  {
6121 #ifdef HAVE_MESSAGES
6122  MHD_DLOG (daemon,
6123  _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
6124 #endif
6125  goto free_and_fail;
6126  }
6127  if (MHD_YES != setup_epoll_to_listen (daemon))
6128  goto free_and_fail;
6129  }
6130 #endif /* EPOLL_SUPPORT */
6131 
6132 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6133  if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
6134  {
6135 #ifdef HAVE_MESSAGES
6136  MHD_DLOG (daemon,
6137  _("MHD failed to initialize IP connection limit mutex\n"));
6138 #endif
6139  if (MHD_INVALID_SOCKET != listen_fd)
6140  MHD_socket_close_chk_ (listen_fd);
6141  goto free_and_fail;
6142  }
6143  if (0 == daemon->worker_pool_size)
6144  { /* Initialise connection mutex only if this daemon will handle
6145  * any connections by itself. */
6146  if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
6147  {
6148 #ifdef HAVE_MESSAGES
6149  MHD_DLOG (daemon,
6150  _("MHD failed to initialize IP connection limit mutex\n"));
6151 #endif
6152 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6154 #endif
6155  if (MHD_INVALID_SOCKET != listen_fd)
6156  MHD_socket_close_chk_ (listen_fd);
6157  goto free_and_fail;
6158  }
6159  }
6160 #endif
6161 
6162 #ifdef HTTPS_SUPPORT
6163  /* initialize HTTPS daemon certificate aspects & send / recv functions */
6164  if ( (0 != (*pflags & MHD_USE_TLS)) &&
6165  (0 != MHD_TLS_init (daemon)) )
6166  {
6167 #ifdef HAVE_MESSAGES
6168  MHD_DLOG (daemon,
6169  _("Failed to initialize TLS support\n"));
6170 #endif
6171  if (MHD_INVALID_SOCKET != listen_fd)
6172  MHD_socket_close_chk_ (listen_fd);
6173 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6174  if (0 == daemon->worker_pool_size)
6177 #endif
6178  goto free_and_fail;
6179  }
6180 #endif /* HTTPS_SUPPORT */
6181 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6182  if ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
6183  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6184  {
6185  if (0 == daemon->worker_pool_size)
6186  {
6187  if (! MHD_create_named_thread_ (&daemon->pid,
6188  (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
6189  "MHD-listen" : "MHD-single",
6190  daemon->thread_stack_size,
6192  daemon) )
6193  {
6194 #ifdef HAVE_MESSAGES
6195  MHD_DLOG (daemon,
6196  _("Failed to create listen thread: %s\n"),
6197  MHD_strerror_ (errno));
6198 #endif
6201  if (MHD_INVALID_SOCKET != listen_fd)
6202  MHD_socket_close_chk_ (listen_fd);
6203  goto free_and_fail;
6204  }
6205  }
6206  else /* 0 < daemon->worker_pool_size */
6207  {
6208  /* Coarse-grained count of connections per thread (note error
6209  * due to integer division). Also keep track of how many
6210  * connections are leftover after an equal split. */
6211  unsigned int conns_per_thread = daemon->connection_limit
6212  / daemon->worker_pool_size;
6213  unsigned int leftover_conns = daemon->connection_limit
6214  % daemon->worker_pool_size;
6215 
6216  i = 0; /* we need this in case fcntl or malloc fails */
6217 
6218  /* Allocate memory for pooled objects */
6219  daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
6220  * daemon->worker_pool_size);
6221  if (NULL == daemon->worker_pool)
6222  goto thread_failed;
6223 
6224  /* Start the workers in the pool */
6225  for (i = 0; i < daemon->worker_pool_size; ++i)
6226  {
6227  /* Create copy of the Daemon object for each worker */
6228  struct MHD_Daemon *d = &daemon->worker_pool[i];
6229 
6230  memcpy (d, daemon, sizeof (struct MHD_Daemon));
6231  /* Adjust pooling params for worker daemons; note that memcpy()
6232  has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
6233  the worker threads. */
6234  d->master = daemon;
6235  d->worker_pool_size = 0;
6236  d->worker_pool = NULL;
6237 
6238  if (0 != (*pflags & MHD_USE_ITC))
6239  {
6240  if (! MHD_itc_init_ (d->itc))
6241  {
6242 #ifdef HAVE_MESSAGES
6243  MHD_DLOG (daemon,
6244  _("Failed to create worker inter-thread communication channel: %s\n"),
6245  MHD_itc_last_strerror_() );
6246 #endif
6247  goto thread_failed;
6248  }
6249  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6250  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
6251  NULL)) )
6252  {
6253 #ifdef HAVE_MESSAGES
6254  MHD_DLOG (daemon,
6255  _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
6256 #endif
6258  goto thread_failed;
6259  }
6260  }
6261  else
6262  MHD_itc_set_invalid_ (d->itc);
6263 
6264  /* Divide available connections evenly amongst the threads.
6265  * Thread indexes in [0, leftover_conns) each get one of the
6266  * leftover connections. */
6267  d->connection_limit = conns_per_thread;
6268  if (i < leftover_conns)
6269  ++d->connection_limit;
6270 #ifdef EPOLL_SUPPORT
6271  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6272  (MHD_YES != setup_epoll_to_listen (d)) )
6273  goto thread_failed;
6274 #endif
6275  /* Must init cleanup connection mutex for each worker */
6276  if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
6277  {
6278 #ifdef HAVE_MESSAGES
6279  MHD_DLOG (daemon,
6280  _("MHD failed to initialize cleanup connection mutex\n"));
6281 #endif
6282  goto thread_failed;
6283  }
6284 
6285  /* Spawn the worker thread */
6286  if (! MHD_create_named_thread_ (&d->pid,
6287  "MHD-worker",
6288  daemon->thread_stack_size,
6290  d))
6291  {
6292 #ifdef HAVE_MESSAGES
6293  MHD_DLOG (daemon,
6294  _("Failed to create pool thread: %s\n"),
6295  MHD_strerror_ (errno));
6296 #endif
6297  /* Free memory for this worker; cleanup below handles
6298  * all previously-created workers. */
6300  goto thread_failed;
6301  }
6302  }
6303  }
6304  }
6305 #endif
6306 #ifdef HTTPS_SUPPORT
6307  /* API promises to never use the password after initialization,
6308  so we additionally NULL it here to not deref a dangling pointer. */
6309  daemon->https_key_password = NULL;
6310 #endif /* HTTPS_SUPPORT */
6311 
6312  return daemon;
6313 
6314 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6315 thread_failed:
6316  /* If no worker threads created, then shut down normally. Calling
6317  MHD_stop_daemon (as we do below) doesn't work here since it
6318  assumes a 0-sized thread pool means we had been in the default
6319  MHD_USE_INTERNAL_POLLING_THREAD mode. */
6320  if (0 == i)
6321  {
6322  if (MHD_INVALID_SOCKET != listen_fd)
6323  MHD_socket_close_chk_ (listen_fd);
6325  if (NULL != daemon->worker_pool)
6326  free (daemon->worker_pool);
6327  goto free_and_fail;
6328  }
6329 
6330  /* Shutdown worker threads we've already created. Pretend
6331  as though we had fully initialized our daemon, but
6332  with a smaller number of threads than had been
6333  requested. */
6334  daemon->worker_pool_size = i;
6335  MHD_stop_daemon (daemon);
6336  return NULL;
6337 #endif
6338 
6339  free_and_fail:
6340  /* clean up basic memory state in 'daemon' and return NULL to
6341  indicate failure */
6342 #ifdef EPOLL_SUPPORT
6343 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6344  if (daemon->upgrade_fd_in_epoll)
6345  {
6346  if (0 != epoll_ctl (daemon->epoll_fd,
6347  EPOLL_CTL_DEL,
6348  daemon->epoll_upgrade_fd,
6349  NULL))
6350  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
6351  daemon->upgrade_fd_in_epoll = false;
6352  }
6353 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6354  if (-1 != daemon->epoll_fd)
6355  close (daemon->epoll_fd);
6356 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6357  if (-1 != daemon->epoll_upgrade_fd)
6358  close (daemon->epoll_upgrade_fd);
6359 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6360 #endif /* EPOLL_SUPPORT */
6361 #ifdef DAUTH_SUPPORT
6362  free (daemon->nnc);
6363 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6364  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6365 #endif
6366 #endif
6367 #ifdef HTTPS_SUPPORT
6368  if (0 != (*pflags & MHD_USE_TLS))
6369  gnutls_priority_deinit (daemon->priority_cache);
6370 #endif /* HTTPS_SUPPORT */
6371  if (MHD_ITC_IS_VALID_(daemon->itc))
6372  MHD_itc_destroy_chk_ (daemon->itc);
6373  free (daemon);
6374  return NULL;
6375 }
6376 
6377 
6386 static void
6388 {
6389  struct MHD_Connection *pos;
6390  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
6391 #ifdef UPGRADE_SUPPORT
6392  const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
6393 #endif /* UPGRADE_SUPPORT */
6394 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6395  struct MHD_UpgradeResponseHandle *urh;
6396  struct MHD_UpgradeResponseHandle *urhn;
6397  const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
6398 
6399 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6400  mhd_assert (NULL == daemon->worker_pool);
6401 #endif
6402  mhd_assert (daemon->shutdown);
6403  /* give upgraded HTTPS connections a chance to finish */
6404  /* 'daemon->urh_head' is not used in thread-per-connection mode. */
6405  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
6406  {
6407  urhn = urh->prev;
6408  /* call generic forwarding function for passing data
6409  with chance to detect that application is done. */
6410  process_urh (urh);
6411  MHD_connection_finish_forward_ (urh->connection);
6412  urh->clean_ready = true;
6413  /* Resuming will move connection to cleanup list. */
6414  MHD_resume_connection(urh->connection);
6415  }
6416 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6417 
6418  /* Give suspended connections a chance to resume to avoid
6419  running into the check for there not being any suspended
6420  connections left in case of a tight race with a recently
6421  resumed connection. */
6422  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6423  {
6424  daemon->resuming = true; /* Force check for pending resume. */
6426  }
6427  /* first, make sure all threads are aware of shutdown; need to
6428  traverse DLLs in peace... */
6429 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6431 #endif
6432 #ifdef UPGRADE_SUPPORT
6433  if (upg_allowed)
6434  {
6435  struct MHD_Connection * susp;
6436 
6437  susp = daemon->suspended_connections_tail;
6438  while (NULL != susp)
6439  {
6440  if (NULL == susp->urh) /* "Upgraded" connection? */
6441  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6442 #ifdef HTTPS_SUPPORT
6443  else if (used_tls &&
6444  used_thr_p_c &&
6445  (! susp->urh->clean_ready) )
6446  shutdown (susp->urh->app.socket,
6447  SHUT_RDWR); /* Wake thread by shutdown of app socket. */
6448 #endif /* HTTPS_SUPPORT */
6449  else
6450  {
6451 #ifdef HAVE_MESSAGES
6452  if (! susp->urh->was_closed)
6453  MHD_DLOG (daemon,
6454  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6455 #endif
6456  susp->urh->was_closed = true;
6457  /* If thread-per-connection is used, connection's thread
6458  * may still processing "upgrade" (exiting). */
6459  if (! used_thr_p_c)
6461  /* Do not use MHD_resume_connection() as mutex is
6462  * already locked. */
6463  susp->resuming = true;
6464  daemon->resuming = true;
6465  }
6466  susp = susp->prev;
6467  }
6468  }
6469  else /* This 'else' is combined with next 'if' */
6470 #endif /* UPGRADE_SUPPORT */
6471  if (NULL != daemon->suspended_connections_head)
6472  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6473  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
6474  {
6475  shutdown (pos->socket_fd,
6476  SHUT_RDWR);
6477 #if MHD_WINSOCK_SOCKETS
6478  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6479  (MHD_ITC_IS_VALID_(daemon->itc)) &&
6480  (! MHD_itc_activate_ (daemon->itc, "e")) )
6481  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6482 #endif
6483  }
6484 
6485 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6486  /* now, collect per-connection threads */
6487  if (used_thr_p_c)
6488  {
6489  pos = daemon->connections_tail;
6490  while (NULL != pos)
6491  {
6492  if (! pos->thread_joined)
6493  {
6495  if (! MHD_join_thread_ (pos->pid.handle))
6496  MHD_PANIC (_("Failed to join a thread\n"));
6498  pos->thread_joined = true;
6499  /* The thread may have concurrently modified the DLL,
6500  need to restart from the beginning */
6501  pos = daemon->connections_tail;
6502  continue;
6503  }
6504  pos = pos->prev;
6505  }
6506  }
6508 #endif
6509 
6510 #ifdef UPGRADE_SUPPORT
6511  /* Finished threads with "upgraded" connections need to be moved
6512  * to cleanup list by resume_suspended_connections(). */
6513  /* "Upgraded" connections that were not closed explicitly by
6514  * application should be moved to cleanup list too. */
6515  if (upg_allowed)
6516  {
6517  daemon->resuming = true; /* Force check for pending resume. */
6519  }
6520 #endif /* UPGRADE_SUPPORT */
6521 
6522  /* now that we're alone, move everyone to cleanup */
6523  while (NULL != (pos = daemon->connections_tail))
6524  {
6525 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6526  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6527  (! pos->thread_joined) )
6528  MHD_PANIC (_("Failed to join a thread\n"));
6529 #endif
6530  close_connection (pos);
6531  }
6532  MHD_cleanup_connections (daemon);
6533 }
6534 
6535 
6542 void
6543 MHD_stop_daemon (struct MHD_Daemon *daemon)
6544 {
6545  MHD_socket fd;
6546 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6547  unsigned int i;
6548 #endif
6549 
6550  if (NULL == daemon)
6551  return;
6552 
6553  daemon->shutdown = true;
6554  if (daemon->was_quiesced)
6555  fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */
6556  else
6557  fd = daemon->listen_fd;
6558 
6559 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6560  if (NULL != daemon->worker_pool)
6561  { /* Master daemon with worker pool. */
6562  mhd_assert (1 < daemon->worker_pool_size);
6564 
6565  /* Let workers shutdown in parallel. */
6566  for (i = 0; i < daemon->worker_pool_size; ++i)
6567  {
6568  daemon->worker_pool[i].shutdown = true;
6569  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
6570  {
6571  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc,
6572  "e"))
6573  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
6574  }
6575  else
6577  }
6578 #ifdef HAVE_LISTEN_SHUTDOWN
6579  if (MHD_INVALID_SOCKET != fd)
6580  {
6581  (void) shutdown (fd,
6582  SHUT_RDWR);
6583  }
6584 #endif /* HAVE_LISTEN_SHUTDOWN */
6585  for (i = 0; i < daemon->worker_pool_size; ++i)
6586  {
6587  MHD_stop_daemon (&daemon->worker_pool[i]);
6588  }
6589  free (daemon->worker_pool);
6590  mhd_assert (MHD_ITC_IS_INVALID_(daemon->itc));
6591 #ifdef EPOLL_SUPPORT
6592  mhd_assert (-1 == daemon->epoll_fd);
6593 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6594  mhd_assert (-1 == daemon->epoll_upgrade_fd);
6595 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6596 #endif /* EPOLL_SUPPORT */
6597  }
6598  else
6599 #endif
6600  { /* Worker daemon or single daemon. */
6601 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6602  if (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6603  { /* Worker daemon or single daemon with internal thread(s). */
6604  mhd_assert (0 == daemon->worker_pool_size);
6605  /* Separate thread(s) is used for polling sockets. */
6606  if (MHD_ITC_IS_VALID_ (daemon->itc))
6607  {
6608  if (! MHD_itc_activate_ (daemon->itc,
6609  "e"))
6610  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6611  }
6612  else
6613  {
6614 #ifdef HAVE_LISTEN_SHUTDOWN
6615  if (MHD_INVALID_SOCKET != fd)
6616  {
6617  if (NULL == daemon->master)
6618  (void) shutdown (fd,
6619  SHUT_RDWR);
6620  }
6621  else
6622 #endif /* HAVE_LISTEN_SHUTDOWN */
6623  mhd_assert (false); /* Should never happen */
6624  }
6625 
6626  if (! MHD_join_thread_ (daemon->pid.handle))
6627  {
6628  MHD_PANIC (_("Failed to join a thread\n"));
6629  }
6630  /* close_all_connections() was called in daemon thread. */
6631  }
6632  else
6633 #endif
6634  {
6635  /* No internal threads are used for polling sockets. */
6636  close_all_connections (daemon);
6637  }
6638  if (MHD_ITC_IS_VALID_ (daemon->itc))
6639  MHD_itc_destroy_chk_ (daemon->itc);
6640 
6641 #ifdef EPOLL_SUPPORT
6642  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6643  (-1 != daemon->epoll_fd) )
6644  MHD_socket_close_chk_ (daemon->epoll_fd);
6645 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6646  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6647  (-1 != daemon->epoll_upgrade_fd) )
6648  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
6649 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6650 #endif /* EPOLL_SUPPORT */
6651 
6652 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6654 #endif
6655  }
6656 
6657  if (NULL == daemon->master)
6658  { /* Cleanup that should be done only one time in master/single daemon.
6659  * Do not perform this cleanup in worker daemons. */
6660 
6661  if (MHD_INVALID_SOCKET != fd)
6662  MHD_socket_close_chk_ (fd);
6663 
6664  /* TLS clean up */
6665 #ifdef HTTPS_SUPPORT
6666  if (daemon->have_dhparams)
6667  {
6668  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6669  daemon->have_dhparams = false;
6670  }
6671  if (0 != (daemon->options & MHD_USE_TLS))
6672  {
6673  gnutls_priority_deinit (daemon->priority_cache);
6674  if (daemon->x509_cred)
6675  gnutls_certificate_free_credentials (daemon->x509_cred);
6676  if (daemon->psk_cred)
6677  gnutls_psk_free_server_credentials (daemon->psk_cred);
6678  }
6679 #endif /* HTTPS_SUPPORT */
6680 
6681 #ifdef DAUTH_SUPPORT
6682  free (daemon->nnc);
6683 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6684  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6685 #endif
6686 #endif
6687 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6689 #endif
6690  free (daemon);
6691  }
6692 }
6693 
6694 
6706 const union MHD_DaemonInfo *
6708  enum MHD_DaemonInfoType info_type,
6709  ...)
6710 {
6711  if (NULL == daemon)
6712  return NULL;
6713  switch (info_type)
6714  {
6716  return NULL; /* no longer supported */
6718  return NULL; /* no longer supported */
6720  return (const union MHD_DaemonInfo *) &daemon->listen_fd;
6721 #ifdef EPOLL_SUPPORT
6723  return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
6724 #endif
6726  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6727  {
6728  /* Assume that MHD_run() in not called in other thread
6729  * at the same time. */
6730  MHD_cleanup_connections (daemon);
6731  }
6732 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6733  else if (daemon->worker_pool)
6734  {
6735  unsigned int i;
6736  /* Collect the connection information stored in the workers. */
6737  daemon->connections = 0;
6738  for (i = 0; i < daemon->worker_pool_size; i++)
6739  {
6740  /* FIXME: next line is thread-safe only if read is atomic. */
6741  daemon->connections += daemon->worker_pool[i].connections;
6742  }
6743  }
6744 #endif
6745  return (const union MHD_DaemonInfo *) &daemon->connections;
6746  case MHD_DAEMON_INFO_FLAGS:
6747  return (const union MHD_DaemonInfo *) &daemon->options;
6749  return (const union MHD_DaemonInfo *) &daemon->port;
6750  default:
6751  return NULL;
6752  }
6753 }
6754 
6755 
6772 void
6774  void *cls)
6775 {
6776  mhd_panic = cb;
6777  mhd_panic_cls = cls;
6778 }
6779 
6780 
6787 const char *
6788 MHD_get_version (void)
6789 {
6790 #ifdef PACKAGE_VERSION
6791  return PACKAGE_VERSION;
6792 #else /* !PACKAGE_VERSION */
6793  static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
6794  if (0 == ver[0])
6795  {
6796  int res = MHD_snprintf_(ver,
6797  sizeof(ver),
6798  "%x.%x.%x",
6799  (((int)MHD_VERSION >> 24) & 0xFF),
6800  (((int)MHD_VERSION >> 16) & 0xFF),
6801  (((int)MHD_VERSION >> 8) & 0xFF));
6802  if (0 >= res || sizeof(ver) <= res)
6803  return "0.0.0"; /* Can't return real version*/
6804  }
6805  return ver;
6806 #endif /* !PACKAGE_VERSION */
6807 }
6808 
6809 
6821 _MHD_EXTERN int
6823 {
6824  switch(feature)
6825  {
6826  case MHD_FEATURE_MESSAGES:
6827 #ifdef HAVE_MESSAGES
6828  return MHD_YES;
6829 #else
6830  return MHD_NO;
6831 #endif
6832  case MHD_FEATURE_TLS:
6833 #ifdef HTTPS_SUPPORT
6834  return MHD_YES;
6835 #else /* ! HTTPS_SUPPORT */
6836  return MHD_NO;
6837 #endif /* ! HTTPS_SUPPORT */
6839 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
6840  return MHD_YES;
6841 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6842  return MHD_NO;
6843 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6844  case MHD_FEATURE_IPv6:
6845 #ifdef HAVE_INET6
6846  return MHD_YES;
6847 #else
6848  return MHD_NO;
6849 #endif
6850  case MHD_FEATURE_IPv6_ONLY:
6851 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
6852  return MHD_YES;
6853 #else
6854  return MHD_NO;
6855 #endif
6856  case MHD_FEATURE_POLL:
6857 #ifdef HAVE_POLL
6858  return MHD_YES;
6859 #else
6860  return MHD_NO;
6861 #endif
6862  case MHD_FEATURE_EPOLL:
6863 #ifdef EPOLL_SUPPORT
6864  return MHD_YES;
6865 #else
6866  return MHD_NO;
6867 #endif
6869 #ifdef HAVE_LISTEN_SHUTDOWN
6870  return MHD_YES;
6871 #else
6872  return MHD_NO;
6873 #endif
6875 #ifdef _MHD_ITC_SOCKETPAIR
6876  return MHD_YES;
6877 #else
6878  return MHD_NO;
6879 #endif
6881 #ifdef TCP_FASTOPEN
6882  return MHD_YES;
6883 #else
6884  return MHD_NO;
6885 #endif
6887 #ifdef BAUTH_SUPPORT
6888  return MHD_YES;
6889 #else
6890  return MHD_NO;
6891 #endif
6893 #ifdef DAUTH_SUPPORT
6894  return MHD_YES;
6895 #else
6896  return MHD_NO;
6897 #endif
6899 #ifdef HAVE_POSTPROCESSOR
6900  return MHD_YES;
6901 #else
6902  return MHD_NO;
6903 #endif
6905 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
6906  return MHD_YES;
6907 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6908  return MHD_NO;
6909 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6911 #if defined(HAVE_PREAD64) || defined(_WIN32)
6912  return MHD_YES;
6913 #elif defined(HAVE_PREAD)
6914  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6915 #elif defined(HAVE_LSEEK64)
6916  return MHD_YES;
6917 #else
6918  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6919 #endif
6921 #if defined(MHD_USE_THREAD_NAME_)
6922  return MHD_YES;
6923 #else
6924  return MHD_NO;
6925 #endif
6926  case MHD_FEATURE_UPGRADE:
6927 #if defined(UPGRADE_SUPPORT)
6928  return MHD_YES;
6929 #else
6930  return MHD_NO;
6931 #endif
6933 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
6934  return MHD_YES;
6935 #else
6936  return MHD_NO;
6937 #endif
6939 #ifdef MHD_USE_GETSOCKNAME
6940  return MHD_YES;
6941 #else
6942  return MHD_NO;
6943 #endif
6945 #if defined(MHD_WINSOCK_SOCKETS) || defined(MHD_socket_nosignal_) || defined (MSG_NOSIGNAL)
6946  return MHD_YES;
6947 #else
6948  return MHD_NO;
6949 #endif
6950  case MHD_FEATURE_SENDFILE:
6951 #ifdef _MHD_HAVE_SENDFILE
6952  return MHD_YES;
6953 #else
6954  return MHD_NO;
6955 #endif
6956  case MHD_FEATURE_THREADS:
6957 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6958  return MHD_YES;
6959 #else
6960  return MHD_NO;
6961 #endif
6962 
6963  }
6964  return MHD_NO;
6965 }
6966 
6967 
6968 #ifdef MHD_HTTPS_REQUIRE_GRYPT
6969 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
6970 #if defined(MHD_USE_POSIX_THREADS)
6971 GCRY_THREAD_OPTION_PTHREAD_IMPL;
6972 #elif defined(MHD_W32_MUTEX_)
6973 
6974 static int
6975 gcry_w32_mutex_init (void **ppmtx)
6976 {
6977  *ppmtx = malloc (sizeof (MHD_mutex_));
6978 
6979  if (NULL == *ppmtx)
6980  return ENOMEM;
6981  if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
6982  {
6983  free (*ppmtx);
6984  *ppmtx = NULL;
6985  return EPERM;
6986  }
6987 
6988  return 0;
6989 }
6990 
6991 
6992 static int
6993 gcry_w32_mutex_destroy (void **ppmtx)
6994 {
6995  int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
6996  free (*ppmtx);
6997  return res;
6998 }
6999 
7000 
7001 static int
7002 gcry_w32_mutex_lock (void **ppmtx)
7003 {
7004  return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
7005 }
7006 
7007 
7008 static int
7009 gcry_w32_mutex_unlock (void **ppmtx)
7010 {
7011  return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
7012 }
7013 
7014 
7015 static struct gcry_thread_cbs gcry_threads_w32 = {
7016  (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
7017  NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
7018  gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
7019  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
7020 
7021 #endif /* defined(MHD_W32_MUTEX_) */
7022 #endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
7023 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
7024 
7028 void
7029 MHD_init(void)
7030 {
7031 #if defined(_WIN32) && ! defined(__CYGWIN__)
7032  WSADATA wsd;
7033 #endif /* _WIN32 && ! __CYGWIN__ */
7034 
7035  if (NULL == mhd_panic)
7037 
7038 #if defined(_WIN32) && ! defined(__CYGWIN__)
7039  if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
7040  MHD_PANIC (_("Failed to initialize winsock\n"));
7041  mhd_winsock_inited_ = 1;
7042  if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
7043  MHD_PANIC (_("Winsock version 2.2 is not available\n"));
7044 #endif
7045 #ifdef HTTPS_SUPPORT
7046 #ifdef MHD_HTTPS_REQUIRE_GRYPT
7047 #if GCRYPT_VERSION_NUMBER < 0x010600
7048 #if defined(MHD_USE_POSIX_THREADS)
7049  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7050  &gcry_threads_pthread))
7051  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
7052 #elif defined(MHD_W32_MUTEX_)
7053  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7054  &gcry_threads_w32))
7055  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
7056 #endif /* defined(MHD_W32_MUTEX_) */
7057  gcry_check_version (NULL);
7058 #else
7059  if (NULL == gcry_check_version ("1.6.0"))
7060  MHD_PANIC (_("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
7061 #endif
7062 #endif /* MHD_HTTPS_REQUIRE_GRYPT */
7063  gnutls_global_init ();
7064 #endif /* HTTPS_SUPPORT */
7066 #ifdef HAVE_FREEBSD_SENDFILE
7067  MHD_conn_init_static_ ();
7068 #endif /* HAVE_FREEBSD_SENDFILE */
7069 }
7070 
7071 
7072 void
7074 {
7075 #ifdef HTTPS_SUPPORT
7076  gnutls_global_deinit ();
7077 #endif /* HTTPS_SUPPORT */
7078 #if defined(_WIN32) && ! defined(__CYGWIN__)
7079  if (mhd_winsock_inited_)
7080  WSACleanup();
7081 #endif
7083 }
7084 
7085 #ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
7087 #endif /* _AUTOINIT_FUNCS_ARE_SUPPORTED */
7088 
7089 /* end of daemon.c */
bool thread_joined
Definition: internal.h:776
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
unsigned int per_ip_connection_limit
Definition: internal.h:1572
void * unescape_callback_cls
Definition: internal.h:1395
int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_PANIC(msg)
Definition: internal.h:68
void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:3008
_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:5459
Header for platform missing functions.
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:4811
_MHD_EXTERN const char * MHD_get_version(void)
Definition: version.c:35
bool data_already_pending
Definition: internal.h:1497
DLL_remove(daemon->suspended_connections_head, daemon->suspended_connections_tail, pos)
_MHD_EXTERN union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:6707
void MHD_update_last_activity_(struct MHD_Connection *connection)
if(daemon->resuming)
socklen_t addr_len
Definition: internal.h:730
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:323
struct sockaddr_storage addr
Definition: internal.h:725
struct MHD_Connection * cleanup_head
Definition: internal.h:1174
enum MHD_CONNECTION_STATE state
Definition: internal.h:902
void * data
Definition: microhttpd.h:2709
static int call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1119
void * mhd_panic_cls
Definition: panic.c:36
MHD_mutex_lock_chk_ & daemon
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:907
#define MHD_ITC_IS_INVALID_(itc)
Definition: mhd_itc.h:359
struct MHD_Connection * prevX
Definition: internal.h:667
MHD_thread_handle_ID_ pid
Definition: internal.h:1246
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
time_t connection_timeout
Definition: internal.h:1566
Methods for managing connections.
MHD_PanicCallback mhd_panic
Definition: panic.c:31
_MHD_EXTERN int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3288
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
internal monotonic clock functions implementations
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:118
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:525
MHD_socket MHD_socket_create_listen_(int pf)
Definition: mhd_sockets.c:471
#define EDLL_insert(head, tail, element)
Definition: internal.h:1829
void MHD_check_global_init_(void)
Definition: init.c:135
#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:2997
#define SIZE_MAX
Definition: mhd_limits.h:99
struct MHD_Response * response
Definition: internal.h:664
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Definition: microhttpd.h:1985
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1209
struct MHD_Connection * prev
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1140
#define EXTRA_SLOTS
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:70
MHD_thread_handle_ID_ pid
Definition: internal.h:720
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:95
#define TIME_T_MAX
Definition: mhd_limits.h:132
time_t MHD_monotonic_sec_counter(void)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: mhd_sockets.c:374
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:132
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:2011
bool ret
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1241
int MHD_socket
Definition: microhttpd.h:181
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:277
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:4629
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
void MHD_fini(void)
Definition: init.c:115
_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:4661
intptr_t value
Definition: microhttpd.h:1539
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:603
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:4836
platform-specific includes for libmicrohttpd
const bool used_thr_p_c
Methods for managing response objects.
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: panic.c:56
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1385
struct MHD_Daemon * daemon
Definition: internal.h:672
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:229
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition: internal.h:209
int listening_address_reuse
Definition: internal.h:1479
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1256
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1366
Header for platform-independent inter-thread communication.
struct MHD_Connection * next
Definition: internal.h:648
bool client_aware
Definition: internal.h:851
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
int strict_for_client
Definition: internal.h:1587
void * socket_context
Definition: internal.h:691
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:313
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
Definition: microhttpd.h:1182
#define MHD_VERSION
Definition: microhttpd.h:129
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
bool was_quiesced
Definition: internal.h:1502
struct MHD_Connection * connections_tail
Definition: internal.h:1157
struct MHD_Daemon * worker_pool
Definition: internal.h:1070
size_t read_buffer_size
Definition: internal.h:767
int fd
Definition: microhttpd.h:2837
void * client_context
Definition: internal.h:682
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:6543
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:332
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:102
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:749
internal shared structures
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3536
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:78
void MHD_set_https_callbacks(struct MHD_Connection *connection)
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
unsigned int connection_limit
Definition: internal.h:1560
unsigned int worker_pool_size
Definition: internal.h:1363
enum MHD_FLAG options
Definition: internal.h:1577
struct MHD_Connection * connections_head
Definition: internal.h:1152
_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:3482
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
LogCallback uri_log_callback
Definition: internal.h:1380
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2899
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1127
_MHD_EXTERN void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2781
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
time_t connection_timeout
Definition: internal.h:742
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:1917
volatile unsigned int global_init_count
Definition: init.c:33
#define _MHD_EXTERN
Definition: mhd_options.h:51
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
Methods for managing connections.
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1223
struct MHD_Daemon * master
Definition: internal.h:1065
#define EDLL_remove(head, tail, element)
Definition: internal.h:1847
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1147
uint16_t port
Definition: internal.h:1582
#define NULL
Definition: reason_phrase.c:30
unsigned int connections
Definition: internal.h:1358
#define ULLONG_MAX
Definition: mhd_limits.h:58
struct MHD_Connection * prev
Definition: internal.h:653
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:140
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:448
#define MHD_strerror_(errnum)
Definition: mhd_compat.h:44
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:63
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
MHD_FEATURE
Definition: microhttpd.h:3530
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:904
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1125
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
UnescapeCallback unescape_callback
Definition: internal.h:1390
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2686
unsigned int listen_backlog_size
Definition: internal.h:1723
#define XDLL_remove(head, tail, element)
Definition: internal.h:1806
void MHD_monotonic_sec_counter_finish(void)
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
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:3378
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1169
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:208
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
size_t pool_size
Definition: internal.h:1430
bool tls_read_ready
Definition: internal.h:766
struct MHD_itc_ itc
Definition: internal.h:1407
MHD_AcceptPolicyCallback apc
Definition: internal.h:1344
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:736
struct MHD_Connection * cleanup_tail
Definition: internal.h:1179
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3324
static int resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2845
#define MHD_itc_destroy_chk_(itc)
Definition: mhd_itc.h:345
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:2270
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3998
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3179
bool sk_nonblck
Definition: internal.h:781
void MHD_monotonic_sec_counter_init(void)
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
static int MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3047
_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:654
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:293
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:156
void * ptr_value
Definition: microhttpd.h:1545
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1132
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1355
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:645
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
#define MHD_BUF_INC_SIZE
Definition: internal.h:117
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
bool resuming
Definition: internal.h:1507
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:4542
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3887
void * notify_completed_cls
Definition: internal.h:1360
MHD_socket listen_fd
Definition: internal.h:1468
struct MemoryPool * pool
Definition: internal.h:682
_MHD_EXTERN int MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:4507
MHD_OPTION
MHD options.
Definition: microhttpd.h:1193
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
void * notify_connection_cls
Definition: internal.h:1371
void * apc_cls
Definition: internal.h:1349
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:4783
bool at_limit
Definition: internal.h:1480
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
Definition: daemon_start.c:613
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
MHD_DaemonInfoType
Definition: microhttpd.h:1838
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
bool suspended
Definition: internal.h:761
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:6822
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1163
void * per_ip_connection_count
Definition: internal.h:1184
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:1962
size_t read_buffer_offset
Definition: internal.h:773
_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:1053
void MHD_init(void)
Definition: init.c:86
void * default_handler_cls
Definition: internal.h:1246
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1523
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1262
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:4706
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:138
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:633
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:6387
limits values definitions
enum MHD_OPTION option
Definition: microhttpd.h:1532
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:439
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:162
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:888
size_t pool_increment
Definition: internal.h:1435
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
Definition: microhttpd.h:1164
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2810
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:1903
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:156
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:398