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