GNU libmicrohttpd  0.9.29
daemon.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2017 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
28 #include "platform.h"
29 #include "mhd_threads.h"
30 #include "internal.h"
31 #include "response.h"
32 #include "connection.h"
33 #include "memorypool.h"
34 #include "mhd_limits.h"
35 #include "autoinit_funcs.h"
36 #include "mhd_mono_clock.h"
37 #include "mhd_locks.h"
38 #include "mhd_sockets.h"
39 #include "mhd_itc.h"
40 #include "mhd_compat.h"
41 
42 #if HAVE_SEARCH_H
43 #include <search.h>
44 #else
45 #include "tsearch.h"
46 #endif
47 
48 #ifdef HTTPS_SUPPORT
49 #include "connection_https.h"
50 #include <gcrypt.h>
51 #endif /* HTTPS_SUPPORT */
52 
53 #ifdef LINUX
54 #include <sys/sendfile.h>
55 #endif
56 
57 #ifdef _WIN32
58 #ifndef WIN32_LEAN_AND_MEAN
59 #define WIN32_LEAN_AND_MEAN 1
60 #endif /* !WIN32_LEAN_AND_MEAN */
61 #include <windows.h>
62 #endif
63 
67 #ifdef MHD_POSIX_SOCKETS
68 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
69 #else
70 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
71 #endif
72 
76 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
77 
82 #define DEBUG_CLOSE MHD_NO
83 
88 #define DEBUG_CONNECT MHD_NO
89 
90 
91 /* Forward declarations. */
92 
101 static void
102 close_all_connections (struct MHD_Daemon *daemon);
103 
104 #ifdef EPOLL_SUPPORT
105 
114 static int
115 MHD_epoll (struct MHD_Daemon *daemon,
116  int may_block);
117 
118 #endif /* EPOLL_SUPPORT */
119 
129 static void
130 mhd_panic_std (void *cls,
131  const char *file,
132  unsigned int line,
133  const char *reason)
134 {
135 #ifdef HAVE_MESSAGES
136  fprintf (stderr,
137  _("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
138  file,
139  line,
140  reason);
141 #endif
142  abort ();
143 }
144 
145 
150 
155 
156 #ifdef _WIN32
157 
160 static int mhd_winsock_inited_ = 0;
161 #endif
162 
163 
171 static struct MHD_Daemon*
172 MHD_get_master (struct MHD_Daemon *daemon)
173 {
174  while (NULL != daemon->master)
175  daemon = daemon->master;
176  return daemon;
177 }
178 
179 
183 struct MHD_IPCount
184 {
188  int family;
189 
193  union
194  {
198  struct in_addr ipv4;
199 #if HAVE_INET6
200 
203  struct in6_addr ipv6;
204 #endif
205  } addr;
206 
210  unsigned int count;
211 };
212 
213 
219 static void
221 {
223 }
224 
225 
231 static void
233 {
235 }
236 
237 
247 static int
248 MHD_ip_addr_compare (const void *a1,
249  const void *a2)
250 {
251  return memcmp (a1,
252  a2,
253  offsetof (struct MHD_IPCount,
254  count));
255 }
256 
257 
266 static int
267 MHD_ip_addr_to_key (const struct sockaddr *addr,
268  socklen_t addrlen,
269  struct MHD_IPCount *key)
270 {
271  memset(key,
272  0,
273  sizeof(*key));
274 
275  /* IPv4 addresses */
276  if (sizeof (struct sockaddr_in) == addrlen)
277  {
278  const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
279 
280  key->family = AF_INET;
281  memcpy (&key->addr.ipv4,
282  &addr4->sin_addr,
283  sizeof(addr4->sin_addr));
284  return MHD_YES;
285  }
286 
287 #if HAVE_INET6
288  /* IPv6 addresses */
289  if (sizeof (struct sockaddr_in6) == addrlen)
290  {
291  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
292 
293  key->family = AF_INET6;
294  memcpy (&key->addr.ipv6,
295  &addr6->sin6_addr,
296  sizeof(addr6->sin6_addr));
297  return MHD_YES;
298  }
299 #endif
300 
301  /* Some other address */
302  return MHD_NO;
303 }
304 
305 
317 static int
318 MHD_ip_limit_add (struct MHD_Daemon *daemon,
319  const struct sockaddr *addr,
320  socklen_t addrlen)
321 {
322  struct MHD_IPCount *key;
323  void **nodep;
324  void *node;
325  int result;
326 
327  daemon = MHD_get_master (daemon);
328  /* Ignore if no connection limit assigned */
329  if (0 == daemon->per_ip_connection_limit)
330  return MHD_YES;
331 
332  if (NULL == (key = malloc (sizeof(*key))))
333  return MHD_NO;
334 
335  /* Initialize key */
336  if (MHD_NO == MHD_ip_addr_to_key (addr,
337  addrlen,
338  key))
339  {
340  /* Allow unhandled address types through */
341  free (key);
342  return MHD_YES;
343  }
344  MHD_ip_count_lock (daemon);
345 
346  /* Search for the IP address */
347  if (NULL == (nodep = tsearch (key,
348  &daemon->per_ip_connection_count,
350  {
351 #ifdef HAVE_MESSAGES
352  MHD_DLOG (daemon,
353  _("Failed to add IP connection count node\n"));
354 #endif
355  MHD_ip_count_unlock (daemon);
356  free (key);
357  return MHD_NO;
358  }
359  node = *nodep;
360  /* If we got an existing node back, free the one we created */
361  if (node != key)
362  free(key);
363  key = (struct MHD_IPCount *) node;
364  /* Test if there is room for another connection; if so,
365  * increment count */
366  result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
367  if (MHD_YES == result)
368  ++key->count;
369 
370  MHD_ip_count_unlock (daemon);
371  return result;
372 }
373 
374 
383 static void
384 MHD_ip_limit_del (struct MHD_Daemon *daemon,
385  const struct sockaddr *addr,
386  socklen_t addrlen)
387 {
388  struct MHD_IPCount search_key;
389  struct MHD_IPCount *found_key;
390  void **nodep;
391 
392  daemon = MHD_get_master (daemon);
393  /* Ignore if no connection limit assigned */
394  if (0 == daemon->per_ip_connection_limit)
395  return;
396  /* Initialize search key */
397  if (MHD_NO == MHD_ip_addr_to_key (addr,
398  addrlen,
399  &search_key))
400  return;
401 
402  MHD_ip_count_lock (daemon);
403 
404  /* Search for the IP address */
405  if (NULL == (nodep = tfind (&search_key,
406  &daemon->per_ip_connection_count,
408  {
409  /* Something's wrong if we couldn't find an IP address
410  * that was previously added */
411  MHD_PANIC (_("Failed to find previously-added IP address\n"));
412  }
413  found_key = (struct MHD_IPCount *) *nodep;
414  /* Validate existing count for IP address */
415  if (0 == found_key->count)
416  {
417  MHD_PANIC (_("Previously-added IP address had counter of zero\n"));
418  }
419  /* Remove the node entirely if count reduces to 0 */
420  if (0 == --found_key->count)
421  {
422  tdelete (found_key,
423  &daemon->per_ip_connection_count,
425  free (found_key);
426  }
427 
428  MHD_ip_count_unlock (daemon);
429 }
430 
431 
432 #ifdef HTTPS_SUPPORT
433 
441 static ssize_t
442 recv_tls_adapter (struct MHD_Connection *connection,
443  void *other,
444  size_t i)
445 {
446  ssize_t res;
447 
448  if (i > SSIZE_MAX)
449  i = SSIZE_MAX;
450 
451  res = gnutls_record_recv (connection->tls_session,
452  other,
453  i);
454  if ( (GNUTLS_E_AGAIN == res) ||
455  (GNUTLS_E_INTERRUPTED == res) )
456  {
458 #ifdef EPOLL_SUPPORT
459  if (GNUTLS_E_AGAIN == res)
460  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
461 #endif
462  return -1;
463  }
464  if (res < 0)
465  {
466  /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication
467  disrupted); set errno to something caller will interpret
468  correctly as a hard error */
470  connection->tls_read_ready = false;
471  return res;
472  }
473 
474 #ifdef EPOLL_SUPPORT
475  /* If data not available to fill whole buffer - socket is not read ready anymore. */
476  if (i > (size_t)res)
477  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
478 #endif /* EPOLL_SUPPORT */
479 
480  /* Check whether TLS buffers still have some unread data. */
481  connection->tls_read_ready = ( ((size_t)res == i) &&
482  (0 != gnutls_record_check_pending (connection->tls_session)) );
483  return res;
484 }
485 
486 
495 static ssize_t
496 send_tls_adapter (struct MHD_Connection *connection,
497  const void *other,
498  size_t i)
499 {
500  ssize_t res;
501 
502  if (i > SSIZE_MAX)
503  i = SSIZE_MAX;
504 
505  res = gnutls_record_send (connection->tls_session,
506  other,
507  i);
508  if ( (GNUTLS_E_AGAIN == res) ||
509  (GNUTLS_E_INTERRUPTED == res) )
510  {
512 #ifdef EPOLL_SUPPORT
513  if (GNUTLS_E_AGAIN == res)
514  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
515 #endif
516  return -1;
517  }
518  if (res < 0)
519  {
520  /* some other GNUTLS error, should set 'errno'; as we do not
521  really understand the error (not listed in GnuTLS
522  documentation explicitly), we set 'errno' to something that
523  will cause the connection to fail. */
525  return -1;
526  }
527 #ifdef EPOLL_SUPPORT
528  /* If NOT all available data was sent - socket is not write ready anymore. */
529  if (i > (size_t)res)
530  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
531 #endif /* EPOLL_SUPPORT */
532  return res;
533 }
534 
535 
542 static int
543 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
544 {
545  gnutls_datum_t key;
546  gnutls_datum_t cert;
547  int ret;
548 
549 #if GNUTLS_VERSION_MAJOR >= 3
550  if (NULL != daemon->cert_callback)
551  {
552  gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
553  daemon->cert_callback);
554  }
555 #endif
556  if (NULL != daemon->https_mem_trust)
557  {
558  cert.data = (unsigned char *) daemon->https_mem_trust;
559  cert.size = strlen (daemon->https_mem_trust);
560  if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
561  &cert,
562  GNUTLS_X509_FMT_PEM) < 0)
563  {
564 #ifdef HAVE_MESSAGES
565  MHD_DLOG(daemon,
566  "Bad trust certificate format\n");
567 #endif
568  return -1;
569  }
570  }
571 
572  if (daemon->have_dhparams)
573  {
574  gnutls_certificate_set_dh_params (daemon->x509_cred,
575  daemon->https_mem_dhparams);
576  }
577  /* certificate & key loaded from memory */
578  if ( (NULL != daemon->https_mem_cert) &&
579  (NULL != daemon->https_mem_key) )
580  {
581  key.data = (unsigned char *) daemon->https_mem_key;
582  key.size = strlen (daemon->https_mem_key);
583  cert.data = (unsigned char *) daemon->https_mem_cert;
584  cert.size = strlen (daemon->https_mem_cert);
585 
586  if (NULL != daemon->https_key_password) {
587 #if GNUTLS_VERSION_NUMBER >= 0x030111
588  ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
589  &cert,
590  &key,
591  GNUTLS_X509_FMT_PEM,
592  daemon->https_key_password,
593  0);
594 #else
595 #ifdef HAVE_MESSAGES
596  MHD_DLOG (daemon,
597  _("Failed to setup x509 certificate/key: pre 3.X.X version " \
598  "of GnuTLS does not support setting key password"));
599 #endif
600  return -1;
601 #endif
602  }
603  else
604  ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
605  &cert,
606  &key,
607  GNUTLS_X509_FMT_PEM);
608 #ifdef HAVE_MESSAGES
609  if (0 != ret)
610  MHD_DLOG (daemon,
611  "GnuTLS failed to setup x509 certificate/key: %s\n",
612  gnutls_strerror (ret));
613 #endif
614  return ret;
615  }
616 #if GNUTLS_VERSION_MAJOR >= 3
617  if (NULL != daemon->cert_callback)
618  return 0;
619 #endif
620 #ifdef HAVE_MESSAGES
621  MHD_DLOG (daemon,
622  "You need to specify a certificate and key location\n");
623 #endif
624  return -1;
625 }
626 
627 
634 static int
635 MHD_TLS_init (struct MHD_Daemon *daemon)
636 {
637  switch (daemon->cred_type)
638  {
639  case GNUTLS_CRD_CERTIFICATE:
640  if (0 !=
641  gnutls_certificate_allocate_credentials (&daemon->x509_cred))
642  return GNUTLS_E_MEMORY_ERROR;
643  return MHD_init_daemon_certificate (daemon);
644  default:
645 #ifdef HAVE_MESSAGES
646  MHD_DLOG (daemon,
647  _("Error: invalid credentials type %d specified.\n"),
648  daemon->cred_type);
649 #endif
650  return -1;
651  }
652 }
653 #endif /* HTTPS_SUPPORT */
654 
655 
656 #undef MHD_get_fdset
657 
677 int
678 MHD_get_fdset (struct MHD_Daemon *daemon,
679  fd_set *read_fd_set,
680  fd_set *write_fd_set,
681  fd_set *except_fd_set,
682  MHD_socket *max_fd)
683 {
684  return MHD_get_fdset2 (daemon,
685  read_fd_set,
686  write_fd_set,
687  except_fd_set,
688  max_fd,
690 }
691 
692 
693 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
694 
706 static bool
707 urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
708  fd_set *rs,
709  fd_set *ws,
710  fd_set *es,
711  MHD_socket *max_fd,
712  unsigned int fd_setsize)
713 {
714  const MHD_socket conn_sckt = urh->connection->socket_fd;
715  const MHD_socket mhd_sckt = urh->mhd.socket;
716  bool res = true;
717 
718  /* Do not add to 'es' only if socket is closed
719  * or not used anymore. */
720  if (MHD_INVALID_SOCKET != conn_sckt)
721  {
722  if ( (urh->in_buffer_used < urh->in_buffer_size) &&
723  (! MHD_add_to_fd_set_ (conn_sckt,
724  rs,
725  max_fd,
726  fd_setsize)) )
727  res = false;
728  if ( (0 != urh->out_buffer_used) &&
729  (! MHD_add_to_fd_set_ (conn_sckt,
730  ws,
731  max_fd,
732  fd_setsize)) )
733  res = false;
734  /* Do not monitor again for errors if error was detected before as
735  * error state is remembered. */
736  if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
737  ((0 != urh->in_buffer_size) ||
738  (0 != urh->out_buffer_size) ||
739  (0 != urh->out_buffer_used)))
740  MHD_add_to_fd_set_ (conn_sckt,
741  es,
742  max_fd,
743  fd_setsize);
744  }
745  if (MHD_INVALID_SOCKET != mhd_sckt)
746  {
747  if ( (urh->out_buffer_used < urh->out_buffer_size) &&
748  (! MHD_add_to_fd_set_ (mhd_sckt,
749  rs,
750  max_fd,
751  fd_setsize)) )
752  res = false;
753  if ( (0 != urh->in_buffer_used) &&
754  (! MHD_add_to_fd_set_ (mhd_sckt,
755  ws,
756  max_fd,
757  fd_setsize)) )
758  res = false;
759  /* Do not monitor again for errors if error was detected before as
760  * error state is remembered. */
761  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
762  ((0 != urh->out_buffer_size) ||
763  (0 != urh->in_buffer_size) ||
764  (0 != urh->in_buffer_used)))
765  MHD_add_to_fd_set_ (mhd_sckt,
766  es,
767  max_fd,
768  fd_setsize);
769  }
770 
771  return res;
772 }
773 
774 
784 static void
785 urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
786  const fd_set *rs,
787  const fd_set *ws,
788  const fd_set *es)
789 {
790  const MHD_socket conn_sckt = urh->connection->socket_fd;
791  const MHD_socket mhd_sckt = urh->mhd.socket;
792 
793  /* Reset read/write ready, preserve error state. */
796 
797  if (MHD_INVALID_SOCKET != conn_sckt)
798  {
799  if (FD_ISSET (conn_sckt, rs))
800  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
801  if (FD_ISSET (conn_sckt, ws))
802  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
803  if (FD_ISSET (conn_sckt, es))
804  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
805  }
806  if ((MHD_INVALID_SOCKET != mhd_sckt))
807  {
808  if (FD_ISSET (mhd_sckt, rs))
809  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
810  if (FD_ISSET (mhd_sckt, ws))
811  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
812  if (FD_ISSET (mhd_sckt, es))
813  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
814  }
815 }
816 
817 #ifdef HAVE_POLL
818 
827 static void
828 urh_update_pollfd(struct MHD_UpgradeResponseHandle *urh,
829  struct pollfd p[2])
830 {
831  p[0].events = 0;
832  p[1].events = 0;
833 
834  if (urh->in_buffer_used < urh->in_buffer_size)
835  p[0].events |= POLLIN;
836  if (0 != urh->out_buffer_used)
837  p[0].events |= POLLOUT;
838 
839  /* Do not monitor again for errors if error was detected before as
840  * error state is remembered. */
841  if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
842  ((0 != urh->in_buffer_size) ||
843  (0 != urh->out_buffer_size) ||
844  (0 != urh->out_buffer_used)))
845  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
846 
847  if (urh->out_buffer_used < urh->out_buffer_size)
848  p[1].events |= POLLIN;
849  if (0 != urh->in_buffer_used)
850  p[1].events |= POLLOUT;
851 
852  /* Do not monitor again for errors if error was detected before as
853  * error state is remembered. */
854  if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
855  ((0 != urh->out_buffer_size) ||
856  (0 != urh->in_buffer_size) ||
857  (0 != urh->in_buffer_used)))
858  p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
859 }
860 
861 
868 static void
869 urh_to_pollfd(struct MHD_UpgradeResponseHandle *urh,
870  struct pollfd p[2])
871 {
872  p[0].fd = urh->connection->socket_fd;
873  p[1].fd = urh->mhd.socket;
874  urh_update_pollfd(urh, p);
875 }
876 
877 
883 static void
884 urh_from_pollfd(struct MHD_UpgradeResponseHandle *urh,
885  struct pollfd p[2])
886 {
887  /* Reset read/write ready, preserve error state. */
890 
891  if (0 != (p[0].revents & POLLIN))
892  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
893  if (0 != (p[0].revents & POLLOUT))
894  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
895  if (0 != (p[0].revents & POLLHUP))
897  if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
898  urh->app.celi |= MHD_EPOLL_STATE_ERROR;
899  if (0 != (p[1].revents & POLLIN))
900  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
901  if (0 != (p[1].revents & POLLOUT))
902  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
903  if (0 != (p[1].revents & POLLHUP))
904  urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
905  if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
907 }
908 #endif /* HAVE_POLL */
909 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
910 
911 
926 int
928  fd_set *read_fd_set,
929  fd_set *write_fd_set,
930  fd_set *except_fd_set,
931  MHD_socket *max_fd,
932  unsigned int fd_setsize)
933 
934 {
935  struct MHD_Connection *pos;
936  struct MHD_Connection *posn;
937  int result = MHD_YES;
938  MHD_socket ls;
939 
940  if (daemon->shutdown)
941  return MHD_NO;
942 
943  ls = daemon->listen_fd;
944  if ( (MHD_INVALID_SOCKET != ls) &&
945  (! daemon->was_quiesced) &&
946  (! MHD_add_to_fd_set_ (ls,
947  read_fd_set,
948  max_fd,
949  fd_setsize)) )
950  result = MHD_NO;
951 
952  /* Add all sockets to 'except_fd_set' as well to watch for
953  * out-of-band data. However, ignore errors if INFO_READ
954  * or INFO_WRITE sockets will not fit 'except_fd_set'. */
955  /* Start from oldest connections. Make sense for W32 FDSETs. */
956  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
957  {
958  posn = pos->prev;
959 
960  switch (pos->event_loop_info)
961  {
963  if (! MHD_add_to_fd_set_ (pos->socket_fd,
964  read_fd_set,
965  max_fd,
966  fd_setsize))
967  result = MHD_NO;
968 #ifdef MHD_POSIX_SOCKETS
970  except_fd_set,
971  max_fd,
972  fd_setsize);
973 #endif /* MHD_POSIX_SOCKETS */
974  break;
976  if (! MHD_add_to_fd_set_ (pos->socket_fd,
977  write_fd_set,
978  max_fd,
979  fd_setsize))
980  result = MHD_NO;
981 #ifdef MHD_POSIX_SOCKETS
983  except_fd_set,
984  max_fd,
985  fd_setsize);
986 #endif /* MHD_POSIX_SOCKETS */
987  break;
989  if ( (NULL == except_fd_set) ||
991  except_fd_set,
992  max_fd,
993  fd_setsize))
994  result = MHD_NO;
995  break;
997  /* this should never happen */
998  break;
999  }
1000  }
1001 #ifdef MHD_WINSOCK_SOCKETS
1002  /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets
1003  * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will
1004  * not be pushed out. */
1005  for (pos = daemon->connections_tail; NULL != pos; pos = posn)
1006  {
1007  posn = pos->prev;
1009  except_fd_set,
1010  max_fd,
1011  fd_setsize);
1012  }
1013 #endif /* MHD_WINSOCK_SOCKETS */
1014 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1015  {
1016  struct MHD_UpgradeResponseHandle *urh;
1017 
1018  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
1019  {
1020  if (MHD_NO ==
1021  urh_to_fdset (urh,
1022  read_fd_set,
1023  write_fd_set,
1024  except_fd_set,
1025  max_fd,
1026  fd_setsize))
1027  result = MHD_NO;
1028  }
1029  }
1030 #endif
1031 #if DEBUG_CONNECT
1032 #ifdef HAVE_MESSAGES
1033  if (NULL != max_fd)
1034  MHD_DLOG (daemon,
1035  _("Maximum socket in select set: %d\n"),
1036  *max_fd);
1037 #endif
1038 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1039  return result;
1040 }
1041 
1042 
1067 int
1068 MHD_get_fdset2 (struct MHD_Daemon *daemon,
1069  fd_set *read_fd_set,
1070  fd_set *write_fd_set,
1071  fd_set *except_fd_set,
1072  MHD_socket *max_fd,
1073  unsigned int fd_setsize)
1074 {
1075  fd_set es;
1076 
1077  if ( (NULL == daemon) ||
1078  (NULL == read_fd_set) ||
1079  (NULL == write_fd_set) ||
1080  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ||
1081  (0 != (daemon->options & MHD_USE_POLL)))
1082  return MHD_NO;
1083 
1084  if (NULL == except_fd_set)
1085  { /* Workaround to maintain backward compatibility. */
1086 #ifdef HAVE_MESSAGES
1087  MHD_DLOG (daemon,
1088  _("MHD_get_fdset2() called with except_fd_set "
1089  "set to NULL. Such behavior is unsupported.\n"));
1090 #endif
1091  FD_ZERO (&es);
1092  except_fd_set = &es;
1093  }
1094 
1095 #ifdef EPOLL_SUPPORT
1096  if (0 != (daemon->options & MHD_USE_EPOLL))
1097  {
1098  if (daemon->shutdown)
1099  return MHD_NO;
1100 
1101  /* we're in epoll mode, use the epoll FD as a stand-in for
1102  the entire event set */
1103 
1104  return MHD_add_to_fd_set_ (daemon->epoll_fd,
1105  read_fd_set,
1106  max_fd,
1107  fd_setsize) ? MHD_YES : MHD_NO;
1108  }
1109 #endif
1110 
1111  return internal_get_fdset2 (daemon,
1112  read_fd_set,
1113  write_fd_set,
1114  except_fd_set,
1115  max_fd,
1116  fd_setsize);
1117 }
1118 
1119 
1133 static int
1135  bool read_ready,
1136  bool write_ready,
1137  bool force_close)
1138 {
1139  int ret;
1140  bool states_info_processed = false;
1141  /* Fast track flag */
1142  bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
1143 
1144 #ifdef HTTPS_SUPPORT
1145  if (con->tls_read_ready)
1146  read_ready = true;
1147 #endif /* HTTPS_SUPPORT */
1148  if (!force_close)
1149  {
1150  if ( (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) &&
1151  read_ready)
1152  {
1153  con->read_handler (con);
1154  ret = con->idle_handler (con);
1155  states_info_processed = true;
1156  }
1157  /* No need to check value of 'ret' here as closed connection
1158  * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
1159  if ( (MHD_EVENT_LOOP_INFO_WRITE == con->event_loop_info) &&
1160  write_ready)
1161  {
1162  con->write_handler (con);
1163  ret = con->idle_handler (con);
1164  states_info_processed = true;
1165  }
1166  }
1167  else
1168  {
1169  MHD_connection_close_ (con,
1171  return con->idle_handler (con);
1172  }
1173 
1174  if (!states_info_processed)
1175  { /* Connection is not read or write ready, but external conditions
1176  * may be changed and need to be processed. */
1177  ret = con->idle_handler (con);
1178  }
1179  /* Fast track for fast connections. */
1180  /* If full request was read by single read_handler() invocation
1181  and headers were completely prepared by single idle_handler()
1182  then try not to wait for next sockets polling and send response
1183  immediately.
1184  As writeability of socket was not checked and it may have
1185  some data pending in system buffers, use this optimization
1186  only for non-blocking sockets. */
1187  /* No need to check 'ret' as connection is always in
1188  * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
1189  else if (on_fasttrack && con->sk_nonblck)
1190  {
1192  {
1193  con->write_handler (con);
1194  /* Always call 'idle_handler()' after each read/write. */
1195  ret = con->idle_handler (con);
1196  }
1197  /* If all headers were sent by single write_handler() and
1198  * response body is prepared by single idle_handler()
1199  * call - continue. */
1200  if ((MHD_CONNECTION_NORMAL_BODY_READY == con->state) ||
1202  {
1203  con->write_handler (con);
1204  ret = con->idle_handler (con);
1205  }
1206  }
1207 
1208  /* All connection's data and states are processed for this turn.
1209  * If connection already has more data to be processed - use
1210  * zero timeout for next select()/poll(). */
1211  /* Thread-per-connection do not need global zero timeout as
1212  * connections are processed individually. */
1213  /* Note: no need to check for read buffer availability for
1214  * TLS read-ready connection in 'read info' state as connection
1215  * without space in read buffer will be market as 'info block'. */
1216  if ( (!con->daemon->data_already_pending) &&
1217  (0 == (con->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1218  {
1220  con->daemon->data_already_pending = true;
1221 #ifdef HTTPS_SUPPORT
1222  else if ( (con->tls_read_ready) &&
1224  con->daemon->data_already_pending = true;
1225 #endif /* HTTPS_SUPPORT */
1226  }
1227  return ret;
1228 }
1229 
1230 
1231 #ifdef UPGRADE_SUPPORT
1232 
1239 static void
1240 cleanup_upgraded_connection (struct MHD_Connection *connection)
1241 {
1242  struct MHD_UpgradeResponseHandle *urh = connection->urh;
1243 
1244  if (NULL == urh)
1245  return;
1246 #ifdef HTTPS_SUPPORT
1247  /* Signal remote client the end of TLS connection by
1248  * gracefully closing TLS session. */
1249  if (0 != (connection->daemon->options & MHD_USE_TLS))
1250  gnutls_bye (connection->tls_session,
1251  GNUTLS_SHUT_WR);
1252 
1253  if (MHD_INVALID_SOCKET != urh->mhd.socket)
1254  MHD_socket_close_chk_ (urh->mhd.socket);
1255 
1256  if (MHD_INVALID_SOCKET != urh->app.socket)
1257  MHD_socket_close_chk_ (urh->app.socket);
1258 #endif /* HTTPS_SUPPORT */
1259  connection->urh = NULL;
1260  free (urh);
1261 }
1262 #endif /* UPGRADE_SUPPORT */
1263 
1264 
1265 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1266 
1274 static void
1275 process_urh (struct MHD_UpgradeResponseHandle *urh)
1276 {
1277  /* Help compiler to optimize:
1278  * pointers to 'connection' and 'daemon' are not changed
1279  * during this processing, so no need to chain dereference
1280  * each time. */
1281  struct MHD_Connection * const connection = urh->connection;
1282  struct MHD_Daemon * const daemon = connection->daemon;
1283  /* Prevent data races: use same value of 'was_closed' throughout
1284  * this function. If 'was_closed' changed externally in the middle
1285  * of processing - it will be processed on next iteration. */
1286  bool was_closed;
1287  if (daemon->shutdown)
1288  {
1289  /* Daemon shutting down, application will not receive any more data. */
1290 #ifdef HAVE_MESSAGES
1291  if (! urh->was_closed)
1292  {
1293  MHD_DLOG (daemon,
1294  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1295  }
1296 #endif
1297  urh->was_closed = true;
1298  }
1299  was_closed = urh->was_closed;
1300  if (was_closed)
1301  {
1302  /* Application was closed connections: no more data
1303  * can be forwarded to application socket. */
1304  if (0 < urh->in_buffer_used)
1305  {
1306 #ifdef HAVE_MESSAGES
1307  MHD_DLOG (daemon,
1308  _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1309  " bytes of data received from remote side: application shut down socket\n"),
1310  (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used);
1311 #endif
1312 
1313  }
1314  /* If application signaled MHD about socket closure then
1315  * check for any pending data even if socket is not marked
1316  * as 'ready' (signal may arrive after poll()/select()).
1317  * Socketpair for forwarding is always in non-blocking mode
1318  * so no risk that recv() will block the thread. */
1319  if (0 != urh->out_buffer_size)
1320  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1321  /* Discard any data received form remote. */
1322  urh->in_buffer_used = 0;
1323  /* Do not try to push data to application. */
1324  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1325  /* Reading from remote client is not required anymore. */
1326  urh->in_buffer_size = 0;
1327  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1328  connection->tls_read_ready = false;
1329  }
1330 
1331  /* On some platforms (W32, possibly Darwin) failed send() (send() will always
1332  * fail after remote disconnect was detected) may discard data in system
1333  * buffers received by system but not yet read by recv().
1334  * So, before trying send() on any socket, recv() must be performed at first
1335  * otherwise last part of incoming data may be lost. */
1336 
1337  /* If disconnect or error was detected - try to read from socket
1338  * to dry data possibly pending is system buffers. */
1339  if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1340  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1341  if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1342  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1343 
1344  /*
1345  * handle reading from remote TLS client
1346  */
1347  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1348  (connection->tls_read_ready) ) &&
1349  (urh->in_buffer_used < urh->in_buffer_size) )
1350  {
1351  ssize_t res;
1352  size_t buf_size;
1353 
1354  buf_size = urh->in_buffer_size - urh->in_buffer_used;
1355  if (buf_size > SSIZE_MAX)
1356  buf_size = SSIZE_MAX;
1357 
1358  connection->tls_read_ready = false;
1359  res = gnutls_record_recv (connection->tls_session,
1360  &urh->in_buffer[urh->in_buffer_used],
1361  buf_size);
1362  if (0 >= res)
1363  {
1364  if (GNUTLS_E_INTERRUPTED != res)
1365  {
1366  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1367  if (GNUTLS_E_AGAIN != res)
1368  {
1369  /* Unrecoverable error on socket was detected or
1370  * socket was disconnected/shut down. */
1371  /* Stop trying to read from this TLS socket. */
1372  urh->in_buffer_size = 0;
1373  }
1374  }
1375  }
1376  else /* 0 < res */
1377  {
1378  urh->in_buffer_used += res;
1379  if (buf_size > (size_t)res)
1380  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1381  else if (0 < gnutls_record_check_pending (connection->tls_session))
1382  connection->tls_read_ready = true;
1383  }
1384  if (MHD_EPOLL_STATE_ERROR ==
1385  ((MHD_EPOLL_STATE_ERROR | MHD_EPOLL_STATE_READ_READY) & urh->app.celi))
1386  {
1387  /* Unrecoverable error on socket was detected and all
1388  * pending data was read from system buffers. */
1389  /* Stop trying to read from this TLS socket. */
1390  urh->in_buffer_size = 0;
1391  }
1392  }
1393 
1394  /*
1395  * handle reading from application
1396  */
1397  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1398  (urh->out_buffer_used < urh->out_buffer_size) )
1399  {
1400  ssize_t res;
1401  size_t buf_size;
1402 
1403  buf_size = urh->out_buffer_size - urh->out_buffer_used;
1404  if (buf_size > MHD_SCKT_SEND_MAX_SIZE_)
1405  buf_size = MHD_SCKT_SEND_MAX_SIZE_;
1406 
1407  res = MHD_recv_ (urh->mhd.socket,
1408  &urh->out_buffer[urh->out_buffer_used],
1409  buf_size);
1410  if (0 >= res)
1411  {
1412  const int err = MHD_socket_get_error_ ();
1413  if ((0 == res) ||
1414  ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1416  {
1417  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1418  if ((0 == res) ||
1419  (was_closed) ||
1420  (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1421  (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1422  {
1423  /* Socket disconnect/shutdown was detected;
1424  * Application signaled about closure of 'upgraded' socket;
1425  * or persistent / unrecoverable error. */
1426  /* Do not try to pull more data from application. */
1427  urh->out_buffer_size = 0;
1428  }
1429  }
1430  }
1431  else /* 0 < res */
1432  {
1433  urh->out_buffer_used += res;
1434  if (buf_size > (size_t)res)
1435  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1436  }
1437  if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1438  ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1439  (was_closed) ) )
1440  {
1441  /* Unrecoverable error on socket was detected and all
1442  * pending data was read from system buffers. */
1443  /* Do not try to pull more data from application. */
1444  urh->out_buffer_size = 0;
1445  }
1446  }
1447 
1448  /*
1449  * handle writing to remote HTTPS client
1450  */
1451  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1452  (urh->out_buffer_used > 0) )
1453  {
1454  ssize_t res;
1455  size_t data_size;
1456 
1457  data_size = urh->out_buffer_used;
1458  if (data_size > SSIZE_MAX)
1459  data_size = SSIZE_MAX;
1460 
1461  res = gnutls_record_send (connection->tls_session,
1462  urh->out_buffer,
1463  data_size);
1464  if (0 >= res)
1465  {
1466  if (GNUTLS_E_INTERRUPTED != res)
1467  {
1468  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1469  if (GNUTLS_E_INTERRUPTED != res)
1470  {
1471  /* TLS connection shut down or
1472  * persistent / unrecoverable error. */
1473 #ifdef HAVE_MESSAGES
1474  MHD_DLOG (daemon,
1475  _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1476  " bytes of data received from application: %s\n"),
1477  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1478  gnutls_strerror(res));
1479 #endif
1480  /* Discard any data unsent to remote. */
1481  urh->out_buffer_used = 0;
1482  /* Do not try to pull more data from application. */
1483  urh->out_buffer_size = 0;
1484  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1485  }
1486  }
1487  }
1488  else /* 0 < res */
1489  {
1490  const size_t next_out_buffer_used = urh->out_buffer_used - res;
1491  if (0 != next_out_buffer_used)
1492  {
1493  memmove (urh->out_buffer,
1494  &urh->out_buffer[res],
1495  next_out_buffer_used);
1496  if (data_size > (size_t)res)
1497  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1498  }
1499  urh->out_buffer_used = next_out_buffer_used;
1500  }
1501  if ( (0 == urh->out_buffer_used) &&
1502  (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1503  {
1504  /* Unrecoverable error on socket was detected and all
1505  * pending data was sent to remote. */
1506  /* Do not try to send to remote anymore. */
1507  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1508  /* Do not try to pull more data from application. */
1509  urh->out_buffer_size = 0;
1510  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1511  }
1512  }
1513 
1514  /*
1515  * handle writing to application
1516  */
1517  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1518  (urh->in_buffer_used > 0) )
1519  {
1520  ssize_t res;
1521  size_t data_size;
1522 
1523  data_size = urh->in_buffer_used;
1524  if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1525  data_size = MHD_SCKT_SEND_MAX_SIZE_;
1526 
1527  res = MHD_send_ (urh->mhd.socket,
1528  urh->in_buffer,
1529  data_size);
1530  if (0 >= res)
1531  {
1532  const int err = MHD_socket_get_error_ ();
1533  if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1535  {
1536  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1537  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1538  {
1539  /* Socketpair connection shut down or
1540  * persistent / unrecoverable error. */
1541 #ifdef HAVE_MESSAGES
1542  MHD_DLOG (daemon,
1543  _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1544  " bytes of data received from remote side: %s\n"),
1545  (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1546  MHD_socket_strerr_ (err));
1547 #endif
1548  /* Discard any data received form remote. */
1549  urh->in_buffer_used = 0;
1550  /* Reading from remote client is not required anymore. */
1551  urh->in_buffer_size = 0;
1552  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1553  connection->tls_read_ready = false;
1554  }
1555  }
1556  }
1557  else /* 0 < res */
1558  {
1559  const size_t next_in_buffer_used = urh->in_buffer_used - res;
1560  if (0 != next_in_buffer_used)
1561  {
1562  memmove (urh->in_buffer,
1563  &urh->in_buffer[res],
1564  next_in_buffer_used);
1565  if (data_size > (size_t)res)
1566  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1567  }
1568  urh->in_buffer_used = next_in_buffer_used;
1569  }
1570  if ( (0 == urh->in_buffer_used) &&
1571  (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1572  {
1573  /* Do not try to push data to application. */
1574  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1575  /* Reading from remote client is not required anymore. */
1576  urh->in_buffer_size = 0;
1577  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1578  connection->tls_read_ready = false;
1579  }
1580  }
1581 
1582  /* Check whether data is present in TLS buffers
1583  * and incoming forward buffer have some space. */
1584  if ( (connection->tls_read_ready) &&
1585  (urh->in_buffer_used < urh->in_buffer_size) &&
1586  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1587  daemon->data_already_pending = true;
1588 
1589  if ( (daemon->shutdown) &&
1590  ( (0 != urh->out_buffer_size) ||
1591  (0 != urh->out_buffer_used) ) )
1592  {
1593  /* Daemon shutting down, discard any remaining forward data. */
1594 #ifdef HAVE_MESSAGES
1595  if (0 < urh->out_buffer_used)
1596  MHD_DLOG (daemon,
1597  _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1598  " bytes of data received from application: daemon shut down\n"),
1599  (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
1600 #endif
1601  /* Discard any data unsent to remote. */
1602  urh->out_buffer_used = 0;
1603  /* Do not try to sent to remote anymore. */
1604  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1605  /* Do not try to pull more data from application. */
1606  urh->out_buffer_size = 0;
1607  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1608  }
1609 }
1610 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
1611 
1612 
1613 #ifdef UPGRADE_SUPPORT
1614 
1622 static void
1623 thread_main_connection_upgrade (struct MHD_Connection *con)
1624 {
1625 #ifdef HTTPS_SUPPORT
1626  struct MHD_UpgradeResponseHandle *urh = con->urh;
1627  struct MHD_Daemon *daemon = con->daemon;
1628 
1629  /* Here, we need to bi-directionally forward
1630  until the application tells us that it is done
1631  with the socket; */
1632  if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1633  (0 == (daemon->options & MHD_USE_POLL)))
1634  {
1635  while ( (0 != urh->in_buffer_size) ||
1636  (0 != urh->out_buffer_size) ||
1637  (0 != urh->in_buffer_used) ||
1638  (0 != urh->out_buffer_used) )
1639  {
1640  /* use select */
1641  fd_set rs;
1642  fd_set ws;
1643  fd_set es;
1644  MHD_socket max_fd;
1645  int num_ready;
1646  bool result;
1647 
1648  FD_ZERO (&rs);
1649  FD_ZERO (&ws);
1650  FD_ZERO (&es);
1651  max_fd = MHD_INVALID_SOCKET;
1652  result = urh_to_fdset (urh,
1653  &rs,
1654  &ws,
1655  &es,
1656  &max_fd,
1657  FD_SETSIZE);
1658  if (! result)
1659  {
1660 #ifdef HAVE_MESSAGES
1661  MHD_DLOG (con->daemon,
1662  _("Error preparing select\n"));
1663 #endif
1664  break;
1665  }
1666  /* FIXME: does this check really needed? */
1667  if (MHD_INVALID_SOCKET != max_fd)
1668  {
1669  struct timeval* tvp;
1670  struct timeval tv;
1671  if ( (con->tls_read_ready) &&
1672  (urh->in_buffer_used < urh->in_buffer_size))
1673  { /* No need to wait if incoming data is already pending in TLS buffers. */
1674  tv.tv_sec = 0;
1675  tv.tv_usec = 0;
1676  tvp = &tv;
1677  }
1678  else
1679  tvp = NULL;
1680  num_ready = MHD_SYS_select_ (max_fd + 1,
1681  &rs,
1682  &ws,
1683  &es,
1684  tvp);
1685  }
1686  else
1687  num_ready = 0;
1688  if (num_ready < 0)
1689  {
1690  const int err = MHD_socket_get_error_();
1691 
1692  if (MHD_SCKT_ERR_IS_EINTR_(err))
1693  continue;
1694 #ifdef HAVE_MESSAGES
1695  MHD_DLOG (con->daemon,
1696  _("Error during select (%d): `%s'\n"),
1697  err,
1698  MHD_socket_strerr_ (err));
1699 #endif
1700  break;
1701  }
1702  urh_from_fdset (urh,
1703  &rs,
1704  &ws,
1705  &es);
1706  process_urh (urh);
1707  }
1708  }
1709 #ifdef HAVE_POLL
1710  else if (0 != (daemon->options & MHD_USE_TLS))
1711  {
1712  /* use poll() */
1713  struct pollfd p[2];
1714  memset (p,
1715  0,
1716  sizeof (p));
1717  p[0].fd = urh->connection->socket_fd;
1718  p[1].fd = urh->mhd.socket;
1719 
1720  while ( (0 != urh->in_buffer_size) ||
1721  (0 != urh->out_buffer_size) ||
1722  (0 != urh->in_buffer_used) ||
1723  (0 != urh->out_buffer_used) )
1724  {
1725  int timeout;
1726 
1727  urh_update_pollfd(urh, p);
1728 
1729  if ( (con->tls_read_ready) &&
1730  (urh->in_buffer_used < urh->in_buffer_size))
1731  timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1732  else
1733  timeout = -1;
1734 
1735  if (MHD_sys_poll_ (p,
1736  2,
1737  timeout) < 0)
1738  {
1739  const int err = MHD_socket_get_error_ ();
1740 
1741  if (MHD_SCKT_ERR_IS_EINTR_ (err))
1742  continue;
1743 #ifdef HAVE_MESSAGES
1744  MHD_DLOG (con->daemon,
1745  _("Error during poll: `%s'\n"),
1746  MHD_socket_strerr_ (err));
1747 #endif
1748  break;
1749  }
1750  urh_from_pollfd(urh, p);
1751  process_urh (urh);
1752  }
1753  }
1754  /* end POLL */
1755 #endif
1756  /* end HTTPS */
1757 #endif /* HTTPS_SUPPORT */
1758  /* TLS forwarding was finished. Cleanup socketpair. */
1760  /* Do not set 'urh->clean_ready' yet as 'urh' will be used
1761  * in connection thread for a little while. */
1762 }
1763 #endif /* UPGRADE_SUPPORT */
1764 
1765 
1773 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1775 {
1776  struct MHD_Connection *con = data;
1777  struct MHD_Daemon *daemon = con->daemon;
1778  int num_ready;
1779  fd_set rs;
1780  fd_set ws;
1781  fd_set es;
1782  MHD_socket maxsock;
1783  struct timeval tv;
1784  struct timeval *tvp;
1785  time_t now;
1786 #if WINDOWS
1787 #ifdef HAVE_POLL
1788  int extra_slot;
1789 #endif /* HAVE_POLL */
1790 #define EXTRA_SLOTS 1
1791 #else /* !WINDOWS */
1792 #define EXTRA_SLOTS 0
1793 #endif /* !WINDOWS */
1794 #ifdef HAVE_POLL
1795  struct pollfd p[1 + EXTRA_SLOTS];
1796 #endif
1797 #undef EXTRA_SLOTS
1798 #ifdef HAVE_POLL
1799  const bool use_poll = (0 != (daemon->options & MHD_USE_POLL));
1800 #else /* ! HAVE_POLL */
1801  const bool use_poll = 0;
1802 #endif /* ! HAVE_POLL */
1803  bool was_suspended = false;
1804 
1805  while ( (! daemon->shutdown) &&
1806  (MHD_CONNECTION_CLOSED != con->state) )
1807  {
1808  const time_t timeout = daemon->connection_timeout;
1809 #ifdef UPGRADE_SUPPORT
1810  struct MHD_UpgradeResponseHandle * const urh = con->urh;
1811 #else /* ! UPGRADE_SUPPORT */
1812  static const void * const urh = NULL;
1813 #endif /* ! UPGRADE_SUPPORT */
1814 
1815  if ( (con->suspended) &&
1816  (NULL == urh) )
1817  {
1818  /* Connection was suspended, wait for resume. */
1819  was_suspended = true;
1820  if (! use_poll)
1821  {
1822  FD_ZERO (&rs);
1823  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1824  &rs,
1825  NULL,
1826  FD_SETSIZE))
1827  {
1828  #ifdef HAVE_MESSAGES
1829  MHD_DLOG (con->daemon,
1830  _("Failed to add FD to fd_set\n"));
1831  #endif
1832  goto exit;
1833  }
1834  if (0 > MHD_SYS_select_ (MHD_itc_r_fd_ (daemon->itc) + 1,
1835  &rs,
1836  NULL,
1837  NULL,
1838  NULL))
1839  {
1840  const int err = MHD_socket_get_error_();
1841 
1842  if (MHD_SCKT_ERR_IS_EINTR_(err))
1843  continue;
1844 #ifdef HAVE_MESSAGES
1845  MHD_DLOG (con->daemon,
1846  _("Error during select (%d): `%s'\n"),
1847  err,
1848  MHD_socket_strerr_ (err));
1849 #endif
1850  break;
1851  }
1852  }
1853 #ifdef HAVE_POLL
1854  else /* use_poll */
1855  {
1856  p[0].events = POLLIN;
1857  p[0].fd = MHD_itc_r_fd_ (daemon->itc);
1858  p[0].revents = 0;
1859  if (0 > MHD_sys_poll_ (p,
1860  1,
1861  -1))
1862  {
1864  continue;
1865 #ifdef HAVE_MESSAGES
1866  MHD_DLOG (con->daemon,
1867  _("Error during poll: `%s'\n"),
1869 #endif
1870  break;
1871  }
1872  }
1873 #endif /* HAVE_POLL */
1874  MHD_itc_clear_ (daemon->itc);
1875  continue; /* Check again for resume. */
1876  } /* End of "suspended" branch. */
1877 
1878  if (was_suspended)
1879  {
1880  MHD_update_last_activity_ (con); /* Reset timeout timer. */
1881  was_suspended = false;
1882  }
1883 
1884  tvp = NULL;
1885 
1887 #ifdef HTTPS_SUPPORT
1888  || ( (con->tls_read_ready) &&
1890 #endif /* HTTPS_SUPPORT */
1891  )
1892  {
1893  /* do not block: more data may be inside of TLS buffers waiting or
1894  * application must provide response data */
1895  tv.tv_sec = 0;
1896  tv.tv_usec = 0;
1897  tvp = &tv;
1898  }
1899  if ( (NULL == tvp) &&
1900  (timeout > 0) )
1901  {
1902  now = MHD_monotonic_sec_counter();
1903  if (now - con->last_activity > timeout)
1904  tv.tv_sec = 0;
1905  else
1906  {
1907  const time_t seconds_left = timeout - (now - con->last_activity);
1908 #ifndef _WIN32
1909  tv.tv_sec = seconds_left;
1910 #else /* _WIN32 */
1911  if (seconds_left > TIMEVAL_TV_SEC_MAX)
1912  tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1913  else
1914  tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
1915 #endif /* _WIN32 */
1916  }
1917  tv.tv_usec = 0;
1918  tvp = &tv;
1919  }
1920  if (! use_poll)
1921  {
1922  /* use select */
1923  bool err_state = false;
1924 
1925  FD_ZERO (&rs);
1926  FD_ZERO (&ws);
1927  FD_ZERO (&es);
1928  maxsock = MHD_INVALID_SOCKET;
1929  switch (con->event_loop_info)
1930  {
1932  if (! MHD_add_to_fd_set_ (con->socket_fd,
1933  &rs,
1934  &maxsock,
1935  FD_SETSIZE))
1936  err_state = true;
1937  break;
1939  if (! MHD_add_to_fd_set_ (con->socket_fd,
1940  &ws,
1941  &maxsock,
1942  FD_SETSIZE))
1943  err_state = true;
1944  break;
1946  if (! MHD_add_to_fd_set_ (con->socket_fd,
1947  &es,
1948  &maxsock,
1949  FD_SETSIZE))
1950  err_state = true;
1951  break;
1953  /* how did we get here!? */
1954  goto exit;
1955  }
1956 #if WINDOWS
1957  if (MHD_ITC_IS_VALID_(daemon->itc) )
1958  {
1959  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1960  &rs,
1961  &maxsock,
1962  FD_SETSIZE))
1963  err_state = 1;
1964  }
1965 #endif
1966  if (err_state)
1967  {
1968 #ifdef HAVE_MESSAGES
1969  MHD_DLOG (con->daemon,
1970  _("Failed to add FD to fd_set\n"));
1971 #endif
1972  goto exit;
1973  }
1974 
1975  num_ready = MHD_SYS_select_ (maxsock + 1,
1976  &rs,
1977  &ws,
1978  NULL,
1979  tvp);
1980  if (num_ready < 0)
1981  {
1982  const int err = MHD_socket_get_error_();
1983 
1984  if (MHD_SCKT_ERR_IS_EINTR_(err))
1985  continue;
1986 #ifdef HAVE_MESSAGES
1987  MHD_DLOG (con->daemon,
1988  _("Error during select (%d): `%s'\n"),
1989  err,
1990  MHD_socket_strerr_ (err));
1991 #endif
1992  break;
1993  }
1994 #if WINDOWS
1995  /* Clear ITC before other processing so additional
1996  * signals will trigger select() again */
1997  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
1998  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
1999  &rs)) )
2000  MHD_itc_clear_ (daemon->itc);
2001 #endif
2002  if (MHD_NO ==
2003  call_handlers (con,
2004  FD_ISSET (con->socket_fd,
2005  &rs),
2006  FD_ISSET (con->socket_fd,
2007  &ws),
2008  FD_ISSET (con->socket_fd,
2009  &es)) )
2010  goto exit;
2011  }
2012 #ifdef HAVE_POLL
2013  else
2014  {
2015  /* use poll */
2016  memset (&p,
2017  0,
2018  sizeof (p));
2019  p[0].fd = con->socket_fd;
2020  switch (con->event_loop_info)
2021  {
2023  p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2024  break;
2026  p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2027  break;
2029  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2030  break;
2032  /* how did we get here!? */
2033  goto exit;
2034  }
2035 #if WINDOWS
2036  extra_slot = 0;
2037  if (MHD_ITC_IS_VALID_(daemon->itc))
2038  {
2039  p[1].events |= POLLIN;
2040  p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2041  p[1].revents = 0;
2042  extra_slot = 1;
2043  }
2044 #endif
2045  if (MHD_sys_poll_ (p,
2046 #if WINDOWS
2047  1 + extra_slot,
2048 #else
2049  1,
2050 #endif
2051  (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2052  {
2054  continue;
2055 #ifdef HAVE_MESSAGES
2056  MHD_DLOG (con->daemon,
2057  _("Error during poll: `%s'\n"),
2059 #endif
2060  break;
2061  }
2062 #if WINDOWS
2063  /* Clear ITC before other processing so additional
2064  * signals will trigger poll() again */
2065  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2066  (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2067  MHD_itc_clear_ (daemon->itc);
2068 #endif
2069  if (MHD_NO ==
2070  call_handlers (con,
2071  0 != (p[0].revents & POLLIN),
2072  0 != (p[0].revents & POLLOUT),
2073  0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
2074  goto exit;
2075  }
2076 #endif
2077 #ifdef UPGRADE_SUPPORT
2078  if (MHD_CONNECTION_UPGRADE == con->state)
2079  {
2080  /* Normal HTTP processing is finished,
2081  * notify application. */
2082  if ( (NULL != daemon->notify_completed) &&
2083  (con->client_aware) )
2084  daemon->notify_completed (daemon->notify_completed_cls,
2085  con,
2086  &con->client_context,
2088  con->client_aware = false;
2089 
2090  thread_main_connection_upgrade (con);
2091  /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2092 
2093  /* "Upgraded" data will not be used in this thread from this point. */
2094  con->urh->clean_ready = true;
2095  /* If 'urh->was_closed' set to true, connection will be
2096  * moved immediately to cleanup list. Otherwise connection
2097  * will stay in suspended list until 'urh' will be marked
2098  * with 'was_closed' by application. */
2099  MHD_resume_connection(con);
2100 
2101  /* skip usual clean up */
2102  return (MHD_THRD_RTRN_TYPE_) 0;
2103  }
2104 #endif /* UPGRADE_SUPPORT */
2105  }
2106  if (MHD_CONNECTION_IN_CLEANUP != con->state)
2107  {
2108 #if DEBUG_CLOSE
2109 #ifdef HAVE_MESSAGES
2110  MHD_DLOG (con->daemon,
2111  _("Processing thread terminating. Closing connection\n"));
2112 #endif
2113 #endif
2114  if (MHD_CONNECTION_CLOSED != con->state)
2115  MHD_connection_close_ (con,
2116  (daemon->shutdown) ?
2119  con->idle_handler (con);
2120  }
2121 exit:
2122  if (NULL != con->response)
2123  {
2125  con->response = NULL;
2126  }
2127 
2128  if (MHD_INVALID_SOCKET != con->socket_fd)
2129  {
2130  shutdown (con->socket_fd,
2131  SHUT_WR);
2132  /* 'socket_fd' can be used in other thread to signal shutdown.
2133  * To avoid data races, do not close socket here. Daemon will
2134  * use more connections only after cleanup anyway. */
2135  }
2136  return (MHD_THRD_RTRN_TYPE_) 0;
2137 }
2138 
2139 
2148 static ssize_t
2150  void *other,
2151  size_t i)
2152 {
2153  ssize_t ret;
2154 
2155  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
2156  (MHD_CONNECTION_CLOSED == connection->state) )
2157  {
2159  return -1;
2160  }
2161  if (i > MHD_SCKT_SEND_MAX_SIZE_)
2162  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
2163 
2164  ret = MHD_recv_ (connection->socket_fd,
2165  other,
2166  i);
2167 #ifdef EPOLL_SUPPORT
2168  if (0 > ret)
2169  {
2170  /* Got EAGAIN --- no longer read-ready */
2172  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
2173  }
2174  else if (i > (size_t)ret)
2175  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
2176 #endif
2177  return ret;
2178 }
2179 
2180 
2189 static ssize_t
2191  const void *other,
2192  size_t i)
2193 {
2194  ssize_t ret;
2195  int err;
2196 
2197  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
2198  (MHD_CONNECTION_CLOSED == connection->state) )
2199  {
2201  return -1;
2202  }
2203  if (i > MHD_SCKT_SEND_MAX_SIZE_)
2204  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
2205 
2206  if (0 != (connection->daemon->options & MHD_USE_TLS))
2207  return MHD_send_ (connection->socket_fd,
2208  other,
2209  i);
2210 #if LINUX
2211  if ( (connection->write_buffer_append_offset ==
2212  connection->write_buffer_send_offset) &&
2213  (NULL != connection->response) &&
2214  (MHD_resp_sender_sendfile == connection->resp_sender) )
2215  {
2216  /* can use sendfile */
2217  int file_fd = connection->response->fd;
2218  uint64_t left;
2219  uint64_t offsetu64;
2220 #ifndef HAVE_SENDFILE64
2221  off_t offset;
2222 #else /* HAVE_SENDFILE64 */
2223  off64_t offset;
2224 #endif /* HAVE_SENDFILE64 */
2225  offsetu64 = connection->response_write_position + connection->response->fd_off;
2226  left = connection->response->total_size - connection->response_write_position;
2227  ret = 0;
2228 #ifndef HAVE_SENDFILE64
2229  if ((uint64_t)OFF_T_MAX < offsetu64)
2231  else
2232  {
2233  offset = (off_t) offsetu64;
2234  ret = sendfile (connection->socket_fd,
2235  file_fd,
2236  &offset,
2237  left);
2238  }
2239 #else /* HAVE_SENDFILE64 */
2240  if ((uint64_t)OFF64_T_MAX < offsetu64)
2242  else
2243  {
2244  offset = (off64_t) offsetu64;
2245  ret = sendfile64 (connection->socket_fd,
2246  file_fd,
2247  &offset,
2248  left);
2249  }
2250 #endif /* HAVE_SENDFILE64 */
2251  if (0 < ret)
2252  {
2253  /* write successful */
2254 #ifdef EPOLL_SUPPORT
2255  if (left > (uint64_t)ret)
2256  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2257 #endif /* EPOLL_SUPPORT */
2258  return ret;
2259  }
2260  err = MHD_socket_get_error_();
2261 #ifdef EPOLL_SUPPORT
2262  if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) )
2263  {
2264  /* EAGAIN --- no longer write-ready */
2265  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2266  }
2267 #endif
2268  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2270  return 0;
2271  if (MHD_SCKT_ERR_IS_(err,
2272  MHD_SCKT_EBADF_))
2273  return -1;
2274  /* sendfile() failed with EINVAL if mmap()-like operations are not
2275  supported for FD or other 'unusual' errors occurred, so we should try
2276  to fall back to 'SEND'; see also this thread for info on
2277  odd libc/Linux behavior with sendfile:
2278  http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
2279  connection->resp_sender = MHD_resp_sender_std;
2280  }
2281 #endif
2282  ret = MHD_send_ (connection->socket_fd,
2283  other,
2284  i);
2285  err = MHD_socket_get_error_();
2286 #ifdef EPOLL_SUPPORT
2287  if (0 > ret)
2288  {
2289  /* EAGAIN --- no longer write-ready */
2290  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
2291  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2292  }
2293  else if (i > (size_t)ret)
2294  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2295 #endif
2296  /* Handle broken kernel / libc, returning -1 but not setting errno;
2297  kill connection as that should be safe; reported on mailinglist here:
2298  http://lists.gnu.org/archive/html/libmicrohttpd/2014-10/msg00023.html */
2299  if ( (0 > ret) &&
2300  (0 == err) )
2302  return ret;
2303 }
2304 
2305 
2313 static void
2314 MHD_cleanup_connections (struct MHD_Daemon *daemon);
2315 
2316 
2347 static int
2349  MHD_socket client_socket,
2350  const struct sockaddr *addr,
2351  socklen_t addrlen,
2352  int external_add,
2353  bool non_blck)
2354 {
2355  struct MHD_Connection *connection;
2356  unsigned int i;
2357  int eno;
2358  struct MHD_Daemon *worker;
2359 
2360  if (NULL != daemon->worker_pool)
2361  {
2362  /* have a pool, try to find a pool with capacity; we use the
2363  socket as the initial offset into the pool for load
2364  balancing */
2365  for (i=0;i<daemon->worker_pool_size;i++)
2366  {
2367  worker = &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
2368  if (worker->connections < worker->connection_limit)
2369  return internal_add_connection (worker,
2370  client_socket,
2371  addr,
2372  addrlen,
2373  external_add,
2374  non_blck);
2375  }
2376  /* all pools are at their connection limit, must refuse */
2377  MHD_socket_close_chk_ (client_socket);
2378 #if ENFILE
2379  errno = ENFILE;
2380 #endif
2381  return MHD_NO;
2382  }
2383 
2384  if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
2385  NULL)) &&
2386  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
2387  {
2388 #ifdef HAVE_MESSAGES
2389  MHD_DLOG (daemon,
2390  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2391  (int) client_socket,
2392  (int) FD_SETSIZE);
2393 #endif
2394  MHD_socket_close_chk_ (client_socket);
2395 #if EINVAL
2396  errno = EINVAL;
2397 #endif
2398  return MHD_NO;
2399  }
2400 
2401 #ifdef MHD_socket_nosignal_
2402  if (! MHD_socket_nosignal_ (client_socket))
2403  {
2404 #ifdef HAVE_MESSAGES
2405  MHD_DLOG (daemon,
2406  _("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2408 #endif
2409 #ifndef MSG_NOSIGNAL
2410  /* Cannot use socket as it can produce SIGPIPE. */
2411 #ifdef ENOTSOCK
2412  errno = ENOTSOCK;
2413 #endif /* ENOTSOCK */
2414  return MHD_NO;
2415 #endif /* ! MSG_NOSIGNAL */
2416  }
2417 #endif /* MHD_socket_nosignal_ */
2418 
2419 
2420 #ifdef HAVE_MESSAGES
2421 #if DEBUG_CONNECT
2422  MHD_DLOG (daemon,
2423  _("Accepted connection on socket %d\n"),
2424  client_socket);
2425 #endif
2426 #endif
2427  if ( (daemon->connections == daemon->connection_limit) ||
2428  (MHD_NO == MHD_ip_limit_add (daemon,
2429  addr,
2430  addrlen)) )
2431  {
2432  /* above connection limit - reject */
2433 #ifdef HAVE_MESSAGES
2434  MHD_DLOG (daemon,
2435  _("Server reached connection limit. Closing inbound connection.\n"));
2436 #endif
2437  MHD_socket_close_chk_ (client_socket);
2438 #if ENFILE
2439  errno = ENFILE;
2440 #endif
2441  return MHD_NO;
2442  }
2443 
2444  /* apply connection acceptance policy if present */
2445  if ( (NULL != daemon->apc) &&
2446  (MHD_NO == daemon->apc (daemon->apc_cls,
2447  addr,
2448  addrlen)) )
2449  {
2450 #if DEBUG_CLOSE
2451 #ifdef HAVE_MESSAGES
2452  MHD_DLOG (daemon,
2453  _("Connection rejected by application. Closing connection.\n"));
2454 #endif
2455 #endif
2456  MHD_socket_close_chk_ (client_socket);
2457  MHD_ip_limit_del (daemon,
2458  addr,
2459  addrlen);
2460 #if EACCESS
2461  errno = EACCESS;
2462 #endif
2463  return MHD_NO;
2464  }
2465 
2466  if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2467  {
2468  eno = errno;
2469 #ifdef HAVE_MESSAGES
2470  MHD_DLOG (daemon,
2471  "Error allocating memory: %s\n",
2472  MHD_strerror_ (errno));
2473 #endif
2474  MHD_socket_close_chk_ (client_socket);
2475  MHD_ip_limit_del (daemon,
2476  addr,
2477  addrlen);
2478  errno = eno;
2479  return MHD_NO;
2480  }
2481  connection->pool = MHD_pool_create (daemon->pool_size);
2482  if (NULL == connection->pool)
2483  {
2484 #ifdef HAVE_MESSAGES
2485  MHD_DLOG (daemon,
2486  _("Error allocating memory: %s\n"),
2487  MHD_strerror_ (errno));
2488 #endif
2489  MHD_socket_close_chk_ (client_socket);
2490  MHD_ip_limit_del (daemon,
2491  addr,
2492  addrlen);
2493  free (connection);
2494 #if ENOMEM
2495  errno = ENOMEM;
2496 #endif
2497  return MHD_NO;
2498  }
2499 
2500  connection->connection_timeout = daemon->connection_timeout;
2501  if (NULL == (connection->addr = malloc (addrlen)))
2502  {
2503  eno = errno;
2504 #ifdef HAVE_MESSAGES
2505  MHD_DLOG (daemon,
2506  _("Error allocating memory: %s\n"),
2507  MHD_strerror_ (errno));
2508 #endif
2509  MHD_socket_close_chk_ (client_socket);
2510  MHD_ip_limit_del (daemon,
2511  addr,
2512  addrlen);
2513  MHD_pool_destroy (connection->pool);
2514  free (connection);
2515  errno = eno;
2516  return MHD_NO;
2517  }
2518  memcpy (connection->addr,
2519  addr,
2520  addrlen);
2521  connection->addr_len = addrlen;
2522  connection->socket_fd = client_socket;
2523  connection->sk_nonblck = non_blck;
2524  connection->daemon = daemon;
2525  connection->last_activity = MHD_monotonic_sec_counter();
2526 
2527  if (0 == (daemon->options & MHD_USE_TLS))
2528  {
2529  /* set default connection handlers */
2530  MHD_set_http_callbacks_ (connection);
2531  connection->recv_cls = &recv_param_adapter;
2532  connection->send_cls = &send_param_adapter;
2533  }
2534  else
2535  {
2536 #ifdef HTTPS_SUPPORT
2537  connection->recv_cls = &recv_tls_adapter;
2538  connection->send_cls = &send_tls_adapter;
2539  connection->state = MHD_TLS_CONNECTION_INIT;
2540  MHD_set_https_callbacks (connection);
2541  gnutls_init (&connection->tls_session,
2542  GNUTLS_SERVER);
2543  gnutls_priority_set (connection->tls_session,
2544  daemon->priority_cache);
2545  switch (daemon->cred_type)
2546  {
2547  /* set needed credentials for certificate authentication. */
2548  case GNUTLS_CRD_CERTIFICATE:
2549  gnutls_credentials_set (connection->tls_session,
2550  GNUTLS_CRD_CERTIFICATE,
2551  daemon->x509_cred);
2552  break;
2553  default:
2554 #ifdef HAVE_MESSAGES
2555  MHD_DLOG (connection->daemon,
2556  _("Failed to setup TLS credentials: unknown credential type %d\n"),
2557  daemon->cred_type);
2558 #endif
2559  MHD_socket_close_chk_ (client_socket);
2560  MHD_ip_limit_del (daemon,
2561  addr,
2562  addrlen);
2563  free (connection->addr);
2564  free (connection);
2565  MHD_PANIC (_("Unknown credential type"));
2566 #if EINVAL
2567  errno = EINVAL;
2568 #endif
2569  return MHD_NO;
2570  }
2571  gnutls_transport_set_ptr (connection->tls_session,
2572  (gnutls_transport_ptr_t) connection);
2573  gnutls_transport_set_pull_function (connection->tls_session,
2574  (gnutls_pull_func) &recv_param_adapter);
2575  gnutls_transport_set_push_function (connection->tls_session,
2576  (gnutls_push_func) &send_param_adapter);
2577 
2578  if (daemon->https_mem_trust)
2579  gnutls_certificate_server_set_request (connection->tls_session,
2580  GNUTLS_CERT_REQUEST);
2581 #else /* ! HTTPS_SUPPORT */
2582  eno = EINVAL;
2583  goto cleanup;
2584 #endif /* ! HTTPS_SUPPORT */
2585  }
2586 
2587 
2589  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2590  {
2592  daemon->normal_timeout_tail,
2593  connection);
2594  }
2595  DLL_insert (daemon->connections_head,
2596  daemon->connections_tail,
2597  connection);
2599 
2600  if (NULL != daemon->notify_connection)
2601  daemon->notify_connection (daemon->notify_connection_cls,
2602  connection,
2603  &connection->socket_context,
2605 
2606  /* attempt to create handler thread */
2607  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2608  {
2609  if (! MHD_create_named_thread_ (&connection->pid,
2610  "MHD-connection",
2611  daemon->thread_stack_size,
2613  connection))
2614  {
2615  eno = errno;
2616 #ifdef HAVE_MESSAGES
2617  MHD_DLOG (daemon,
2618  "Failed to create a thread: %s\n",
2619  MHD_strerror_ (eno));
2620 #endif
2621  goto cleanup;
2622  }
2623  }
2624  else
2625  if ( (MHD_YES == external_add) &&
2626  (MHD_ITC_IS_VALID_(daemon->itc)) &&
2627  (! MHD_itc_activate_ (daemon->itc, "n")) )
2628  {
2629 #ifdef HAVE_MESSAGES
2630  MHD_DLOG (daemon,
2631  _("Failed to signal new connection via inter-thread communication channel."));
2632 #endif
2633  }
2634 #ifdef EPOLL_SUPPORT
2635  if (0 != (daemon->options & MHD_USE_EPOLL))
2636  {
2637  if (0 == (daemon->options & MHD_USE_TURBO))
2638  {
2639  struct epoll_event event;
2640 
2641  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2642  event.data.ptr = connection;
2643  if (0 != epoll_ctl (daemon->epoll_fd,
2644  EPOLL_CTL_ADD,
2645  client_socket,
2646  &event))
2647  {
2648  eno = errno;
2649 #ifdef HAVE_MESSAGES
2650  MHD_DLOG (daemon,
2651  _("Call to epoll_ctl failed: %s\n"),
2653 #endif
2654  goto cleanup;
2655  }
2656  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2657  }
2658  else
2659  {
2660  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
2662  EDLL_insert (daemon->eready_head,
2663  daemon->eready_tail,
2664  connection);
2665  }
2666  }
2667 #endif
2668  daemon->connections++;
2669  return MHD_YES;
2670  cleanup:
2671  if (NULL != daemon->notify_connection)
2672  daemon->notify_connection (daemon->notify_connection_cls,
2673  connection,
2674  &connection->socket_context,
2676  MHD_socket_close_chk_ (client_socket);
2677  MHD_ip_limit_del (daemon,
2678  addr,
2679  addrlen);
2681  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2682  {
2684  daemon->normal_timeout_tail,
2685  connection);
2686  }
2687  DLL_remove (daemon->connections_head,
2688  daemon->connections_tail,
2689  connection);
2691  MHD_pool_destroy (connection->pool);
2692  free (connection->addr);
2693  free (connection);
2694  errno = eno;
2695  return MHD_NO;
2696 }
2697 
2698 
2730 void
2732 {
2733  struct MHD_Daemon *daemon = connection->daemon;
2734 
2735  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2736  MHD_PANIC (_("Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2738  if (connection->resuming)
2739  {
2740  /* suspending again while we didn't even complete resuming yet */
2741  connection->resuming = false;
2743  return;
2744  }
2745  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2746  {
2747  if (connection->connection_timeout == daemon->connection_timeout)
2749  daemon->normal_timeout_tail,
2750  connection);
2751  else
2753  daemon->manual_timeout_tail,
2754  connection);
2755  }
2756  DLL_remove (daemon->connections_head,
2757  daemon->connections_tail,
2758  connection);
2759  EXTRA_CHECK (! connection->suspended);
2762  connection);
2763  connection->suspended = true;
2764 #ifdef EPOLL_SUPPORT
2765  if (0 != (daemon->options & MHD_USE_EPOLL))
2766  {
2767  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2768  {
2769  EDLL_remove (daemon->eready_head,
2770  daemon->eready_tail,
2771  connection);
2772  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2773  }
2774  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2775  {
2776  if (0 != epoll_ctl (daemon->epoll_fd,
2777  EPOLL_CTL_DEL,
2778  connection->socket_fd,
2779  NULL))
2780  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
2781  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2782  }
2783  connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2784  }
2785 #endif
2787 }
2788 
2789 
2798 void
2800 {
2801  struct MHD_Daemon *daemon;
2802 
2803  daemon = connection->daemon;
2804  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2805  MHD_PANIC (_("Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2807  connection->resuming = true;
2808  daemon->resuming = true;
2810  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2811  (! MHD_itc_activate_ (daemon->itc, "r")) )
2812  {
2813 #ifdef HAVE_MESSAGES
2814  MHD_DLOG (daemon,
2815  _("Failed to signal resume via inter-thread communication channel."));
2816 #endif
2817  }
2818 }
2819 
2820 
2830 static int
2832 {
2833  struct MHD_Connection *pos;
2834  struct MHD_Connection *prev = NULL;
2835  int ret;
2836 
2837  ret = MHD_NO;
2839 
2840  if (daemon->resuming)
2841  prev = daemon->suspended_connections_tail;
2842 
2843  EXTRA_CHECK(NULL != next);
2844  daemon->resuming = false;
2845 
2846  while (NULL != (pos = prev))
2847  {
2848 #ifdef UPGRADE_SUPPORT
2849  struct MHD_UpgradeResponseHandle * const urh = pos->urh;
2850 #else /* ! UPGRADE_SUPPORT */
2851  static const void * const urh = NULL;
2852 #endif /* ! UPGRADE_SUPPORT */
2853  prev = pos->prev;
2854  if ( (! pos->resuming)
2855 #ifdef UPGRADE_SUPPORT
2856  || ( (NULL != urh) &&
2857  ( (! urh->was_closed) ||
2858  (! urh->clean_ready) ) )
2859 #endif /* UPGRADE_SUPPORT */
2860  )
2861  continue;
2862  ret = MHD_YES;
2863  EXTRA_CHECK (pos->suspended);
2866  pos);
2867  pos->suspended = false;
2868  if (NULL == urh)
2869  {
2870  DLL_insert (daemon->connections_head,
2871  daemon->connections_tail,
2872  pos);
2873  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2874  {
2875  /* Reset timeout timer on resume. */
2876  if (0 != pos->connection_timeout)
2878 
2879  if (pos->connection_timeout == daemon->connection_timeout)
2881  daemon->normal_timeout_tail,
2882  pos);
2883  else
2885  daemon->manual_timeout_tail,
2886  pos);
2887  }
2888 #ifdef EPOLL_SUPPORT
2889  if (0 != (daemon->options & MHD_USE_EPOLL))
2890  {
2891  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2892  MHD_PANIC ("Resumed connection was already in EREADY set\n");
2893  /* we always mark resumed connections as ready, as we
2894  might have missed the edge poll event during suspension */
2895  EDLL_insert (daemon->eready_head,
2896  daemon->eready_tail,
2897  pos);
2898  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2899  pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
2900  }
2901 #endif
2902  }
2903 #ifdef UPGRADE_SUPPORT
2904  else
2905  {
2906  /* Data forwarding was finished (for TLS connections) AND
2907  * application was closed upgraded connection.
2908  * Insert connection into cleanup list. */
2909  DLL_insert (daemon->cleanup_head,
2910  daemon->cleanup_tail,
2911  pos);
2912 
2913  }
2914 #endif /* UPGRADE_SUPPORT */
2915  pos->resuming = false;
2916  }
2918  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2919  (MHD_NO != ret) )
2920  { /* Wake up suspended connections. */
2921  if (! MHD_itc_activate_(daemon->itc,
2922  "w"))
2923  {
2924 #ifdef HAVE_MESSAGES
2925  MHD_DLOG (daemon,
2926  _("Failed to signal resume of connection via inter-thread communication channel."));
2927 #endif
2928  }
2929  }
2930  return ret;
2931 }
2932 
2933 
2963 int
2965  MHD_socket client_socket,
2966  const struct sockaddr *addr,
2967  socklen_t addrlen)
2968 {
2969  bool sk_nonbl;
2970  if (! MHD_socket_nonblocking_ (client_socket))
2971  {
2972 #ifdef HAVE_MESSAGES
2973  MHD_DLOG (daemon,
2974  _("Failed to set nonblocking mode on new client socket: %s\n"),
2976 #endif
2977  sk_nonbl = 0;
2978  }
2979  else
2980  sk_nonbl = !0;
2981 
2982  if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
2983  (! MHD_socket_noninheritable_ (client_socket)) )
2984  {
2985 #ifdef HAVE_MESSAGES
2986  MHD_DLOG (daemon,
2987  _("Failed to set noninheritable mode on new client socket.\n"));
2988 #endif
2989  }
2990  return internal_add_connection (daemon,
2991  client_socket,
2992  addr,
2993  addrlen,
2994  MHD_YES,
2995  sk_nonbl);
2996 }
2997 
2998 
3013 static int
3015 {
3016 #if HAVE_INET6
3017  struct sockaddr_in6 addrstorage;
3018 #else
3019  struct sockaddr_in addrstorage;
3020 #endif
3021  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3022  socklen_t addrlen;
3023  MHD_socket s;
3024  MHD_socket fd;
3025  bool sk_nonbl;
3026 
3027  addrlen = sizeof (addrstorage);
3028  memset (addr,
3029  0,
3030  sizeof (addrstorage));
3031  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3032  (daemon->was_quiesced) )
3033  return MHD_NO;
3034 #ifdef USE_ACCEPT4
3035  s = accept4 (fd,
3036  addr,
3037  &addrlen,
3039  sk_nonbl = (MAYBE_SOCK_NONBLOCK != 0);
3040 #else /* ! USE_ACCEPT4 */
3041  s = accept (fd,
3042  addr,
3043  &addrlen);
3044  sk_nonbl = 0;
3045 #endif /* ! USE_ACCEPT4 */
3046  if ( (MHD_INVALID_SOCKET == s) ||
3047  (addrlen <= 0) )
3048  {
3049  const int err = MHD_socket_get_error_ ();
3050 
3051  /* This could be a common occurance with multiple worker threads */
3052  if (MHD_SCKT_ERR_IS_ (err,
3054  return MHD_NO; /* can happen during shutdown */
3056  return MHD_NO; /* do not print error if client just disconnected early */
3057 #ifdef HAVE_MESSAGES
3058  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3059  MHD_DLOG (daemon,
3060  _("Error accepting connection: %s\n"),
3061  MHD_socket_strerr_(err));
3062 #endif
3063  if (MHD_INVALID_SOCKET != s)
3064  {
3066  }
3067  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
3068  {
3069  /* system/process out of resources */
3070  if (0 == daemon->connections)
3071  {
3072 #ifdef HAVE_MESSAGES
3073  /* Not setting 'at_limit' flag, as there is no way it
3074  would ever be cleared. Instead trying to produce
3075  bit fat ugly warning. */
3076  MHD_DLOG (daemon,
3077  _("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"));
3078 #endif
3079  }
3080  else
3081  {
3082  daemon->at_limit = true;
3083 #ifdef HAVE_MESSAGES
3084  MHD_DLOG (daemon,
3085  _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3086  (unsigned int) daemon->connections);
3087 #endif
3088  }
3089  }
3090  return MHD_NO;
3091  }
3092 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
3093  if (! MHD_socket_nonblocking_ (s))
3094  {
3095 #ifdef HAVE_MESSAGES
3096  MHD_DLOG (daemon,
3097  _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
3099 #endif
3100  }
3101  else
3102  sk_nonbl = !0;
3103 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
3104 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
3105  if (! MHD_socket_noninheritable_ (s))
3106  {
3107 #ifdef HAVE_MESSAGES
3108  MHD_DLOG (daemon,
3109  _("Failed to set noninheritable mode on incoming connection socket.\n"));
3110 #endif
3111  }
3112 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
3113 #ifdef HAVE_MESSAGES
3114 #if DEBUG_CONNECT
3115  MHD_DLOG (daemon,
3116  _("Accepted connection on socket %d\n"),
3117  s);
3118 #endif
3119 #endif
3120  (void) internal_add_connection (daemon,
3121  s,
3122  addr,
3123  addrlen,
3124  MHD_NO,
3125  sk_nonbl);
3126  return MHD_YES;
3127 }
3128 
3129 
3139 static void
3141 {
3142  struct MHD_Connection *pos;
3143 
3145  while (NULL != (pos = daemon->cleanup_tail))
3146  {
3147  DLL_remove (daemon->cleanup_head,
3148  daemon->cleanup_tail,
3149  pos);
3151 
3152  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3153  (! pos->thread_joined) &&
3154  (! MHD_join_thread_ (pos->pid)) )
3155  MHD_PANIC (_("Failed to join a thread\n"));
3156 #ifdef UPGRADE_SUPPORT
3157  cleanup_upgraded_connection (pos);
3158 #endif /* UPGRADE_SUPPORT */
3159  MHD_pool_destroy (pos->pool);
3160 #ifdef HTTPS_SUPPORT
3161  if (NULL != pos->tls_session)
3162  gnutls_deinit (pos->tls_session);
3163 #endif /* HTTPS_SUPPORT */
3164  daemon->connections--;
3165  daemon->at_limit = false;
3166 
3167  /* clean up the connection */
3168  if (NULL != daemon->notify_connection)
3169  daemon->notify_connection (daemon->notify_connection_cls,
3170  pos,
3171  &pos->socket_context,
3173  MHD_ip_limit_del (daemon,
3174  pos->addr,
3175  pos->addr_len);
3176 #ifdef EPOLL_SUPPORT
3177  if (0 != (daemon->options & MHD_USE_EPOLL))
3178  {
3179  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3180  {
3181  EDLL_remove (daemon->eready_head,
3182  daemon->eready_tail,
3183  pos);
3184  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3185  }
3186  if ( (-1 != daemon->epoll_fd) &&
3187  (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3188  {
3189  /* epoll documentation suggests that closing a FD
3190  automatically removes it from the epoll set; however,
3191  this is not true as if we fail to do manually remove it,
3192  we are still seeing an event for this fd in epoll,
3193  causing grief (use-after-free...) --- at least on my
3194  system. */
3195  if (0 != epoll_ctl (daemon->epoll_fd,
3196  EPOLL_CTL_DEL,
3197  pos->socket_fd,
3198  NULL))
3199  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
3200  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3201  }
3202  }
3203 #endif
3204  if (NULL != pos->response)
3205  {
3207  pos->response = NULL;
3208  }
3209  if (MHD_INVALID_SOCKET != pos->socket_fd)
3211  if (NULL != pos->addr)
3212  free (pos->addr);
3213  free (pos);
3214 
3216  }
3218 }
3219 
3220 
3237 int
3238 MHD_get_timeout (struct MHD_Daemon *daemon,
3239  MHD_UNSIGNED_LONG_LONG *timeout)
3240 {
3241  time_t earliest_deadline;
3242  time_t now;
3243  struct MHD_Connection *pos;
3244  bool have_timeout;
3245 
3246  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3247  {
3248 #ifdef HAVE_MESSAGES
3249  MHD_DLOG (daemon,
3250  _("Illegal call to MHD_get_timeout\n"));
3251 #endif
3252  return MHD_NO;
3253  }
3254 
3255  if (daemon->data_already_pending)
3256  {
3257  /* Some data already waiting to be processed. */
3258  *timeout = 0;
3259  return MHD_YES;
3260  }
3261 
3262 #ifdef EPOLL_SUPPORT
3263  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3264  ((NULL != daemon->eready_head)
3265 #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3266  || (NULL != daemon->eready_urh_head)
3267 #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3268  ) )
3269  {
3270  /* Some connection(s) already have some data pending. */
3271  *timeout = 0;
3272  return MHD_YES;
3273  }
3274 #endif /* EPOLL_SUPPORT */
3275 
3276  have_timeout = false;
3277  earliest_deadline = 0; /* avoid compiler warnings */
3278  for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3279  {
3280  if (0 != pos->connection_timeout)
3281  {
3282  if ( (! have_timeout) ||
3283  (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3284  earliest_deadline = pos->last_activity + pos->connection_timeout;
3285  have_timeout = true;
3286  }
3287  }
3288  /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3289  pos = daemon->normal_timeout_tail;
3290  if ( (NULL != pos) &&
3291  (0 != pos->connection_timeout) )
3292  {
3293  if ( (! have_timeout) ||
3294  (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3295  earliest_deadline = pos->last_activity + pos->connection_timeout;
3296  have_timeout = true;
3297  }
3298 
3299  if (! have_timeout)
3300  return MHD_NO;
3301  now = MHD_monotonic_sec_counter();
3302  if (earliest_deadline < now)
3303  *timeout = 0;
3304  else
3305  {
3306  const time_t second_left = earliest_deadline - now;
3307  if (second_left > ULLONG_MAX / 1000) /* Ignore compiler warning: 'second_left' is always positive. */
3308  *timeout = ULLONG_MAX;
3309  else
3310  *timeout = 1000LL * second_left;
3311  }
3312  return MHD_YES;
3313 }
3314 
3315 
3326 static int
3328  const fd_set *read_fd_set,
3329  const fd_set *write_fd_set,
3330  const fd_set *except_fd_set)
3331 {
3332  MHD_socket ds;
3333  struct MHD_Connection *pos;
3334  struct MHD_Connection *prev;
3335 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3336  struct MHD_UpgradeResponseHandle *urh;
3337  struct MHD_UpgradeResponseHandle *urhn;
3338 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3339  /* Reset. New value will be set when connections are processed. */
3340  /* Note: no-op for thread-per-connection as it is always false in that mode. */
3341  daemon->data_already_pending = false;
3342 
3343  /* Clear ITC to avoid spinning select */
3344  /* Do it before any other processing so new signals
3345  will trigger select again and will be processed */
3346  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3347  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3348  read_fd_set)) )
3349  MHD_itc_clear_ (daemon->itc);
3350 
3351 #ifdef EPOLL_SUPPORT
3352  if (0 != (daemon->options & MHD_USE_EPOLL))
3353  {
3354  /* we're in epoll mode, the epoll FD stands for
3355  the entire event set! */
3356  if (! MHD_SCKT_FD_FITS_FDSET_(daemon->epoll_fd,
3357  NULL))
3358  return MHD_NO; /* poll fd too big, fail hard */
3359  if (FD_ISSET (daemon->epoll_fd,
3360  read_fd_set))
3361  return MHD_run (daemon);
3362  return MHD_YES;
3363  }
3364 #endif
3365 
3366  /* select connection thread handling type */
3367  if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3368  (! daemon->was_quiesced) &&
3369  (FD_ISSET (ds,
3370  read_fd_set)) )
3371  (void) MHD_accept_connection (daemon);
3372 
3373  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3374  {
3375  /* do not have a thread per connection, process all connections now */
3376  prev = daemon->connections_tail;
3377  while (NULL != (pos = prev))
3378  {
3379  prev = pos->prev;
3380  ds = pos->socket_fd;
3381  if (MHD_INVALID_SOCKET == ds)
3382  continue;
3383  call_handlers (pos,
3384  FD_ISSET (ds,
3385  read_fd_set),
3386  FD_ISSET (ds,
3387  write_fd_set),
3388  FD_ISSET (ds,
3389  except_fd_set));
3390  }
3391  }
3392 
3393 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3394  /* handle upgraded HTTPS connections */
3395  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3396  {
3397  urhn = urh->prev;
3398  /* update urh state based on select() output */
3399  urh_from_fdset (urh,
3400  read_fd_set,
3401  write_fd_set,
3402  except_fd_set);
3403  /* call generic forwarding function for passing data */
3404  process_urh (urh);
3405  /* Finished forwarding? */
3406  if ( (0 == urh->in_buffer_size) &&
3407  (0 == urh->out_buffer_size) &&
3408  (0 == urh->in_buffer_used) &&
3409  (0 == urh->out_buffer_used) )
3410  {
3411  MHD_connection_finish_forward_ (urh->connection);
3412  urh->clean_ready = true;
3413  /* Resuming will move connection to cleanup list. */
3414  MHD_resume_connection(urh->connection);
3415  }
3416  }
3417 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3418  MHD_cleanup_connections (daemon);
3419  return MHD_YES;
3420 }
3421 
3422 
3445 int
3447  const fd_set *read_fd_set,
3448  const fd_set *write_fd_set,
3449  const fd_set *except_fd_set)
3450 {
3451  fd_set es;
3452  if (0 != (daemon->options &
3454  return MHD_NO;
3455  if (NULL == read_fd_set || NULL == write_fd_set)
3456  return MHD_NO;
3457  if (NULL == except_fd_set)
3458  { /* Workaround to maintain backward compatibility. */
3459 #ifdef HAVE_MESSAGES
3460  MHD_DLOG (daemon,
3461  _("MHD_run_from_select() called with except_fd_set "
3462  "set to NULL. Such behavior is deprecated.\n"));
3463 #endif
3464  FD_ZERO (&es);
3465  except_fd_set = &es;
3466  }
3467  if (0 != (daemon->options & MHD_USE_EPOLL))
3468  {
3469 #ifdef EPOLL_SUPPORT
3470  int ret;
3471  ret = MHD_epoll (daemon, MHD_NO);
3472  MHD_cleanup_connections (daemon);
3473  return ret;
3474 #else /* ! EPOLL_SUPPORT */
3475  return MHD_NO;
3476 #endif /* ! EPOLL_SUPPORT */
3477  }
3478 
3479  /* Resuming external connections when using an extern mainloop */
3481 
3482  return internal_run_from_select (daemon, read_fd_set,
3483  write_fd_set, except_fd_set);
3484 }
3485 
3486 
3495 static int
3496 MHD_select (struct MHD_Daemon *daemon,
3497  int may_block)
3498 {
3499  int num_ready;
3500  fd_set rs;
3501  fd_set ws;
3502  fd_set es;
3503  MHD_socket maxsock;
3504  struct timeval timeout;
3505  struct timeval *tv;
3506  MHD_UNSIGNED_LONG_LONG ltimeout;
3507  int err_state;
3508  MHD_socket ls;
3509 
3510  timeout.tv_sec = 0;
3511  timeout.tv_usec = 0;
3512  if (daemon->shutdown)
3513  return MHD_NO;
3514  FD_ZERO (&rs);
3515  FD_ZERO (&ws);
3516  FD_ZERO (&es);
3517  maxsock = MHD_INVALID_SOCKET;
3518  err_state = MHD_NO;
3519  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3520  {
3521  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3522  (MHD_YES == resume_suspended_connections (daemon)) )
3523  may_block = MHD_NO;
3524 
3525  /* single-threaded, go over everything */
3526  if (MHD_NO ==
3527  internal_get_fdset2 (daemon,
3528  &rs,
3529  &ws,
3530  &es,
3531  &maxsock,
3532  FD_SETSIZE))
3533  {
3534 #ifdef HAVE_MESSAGES
3535  MHD_DLOG (daemon,
3536  _("Could not obtain daemon fdsets"));
3537 #endif
3538  err_state = MHD_YES;
3539  }
3540  }
3541  else
3542  {
3543  /* accept only, have one thread per connection */
3544  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3545  (! daemon->was_quiesced) &&
3546  (! MHD_add_to_fd_set_ (ls,
3547  &rs,
3548  &maxsock,
3549  FD_SETSIZE)) )
3550  {
3551 #ifdef HAVE_MESSAGES
3552  MHD_DLOG (daemon,
3553  _("Could not add listen socket to fdset"));
3554 #endif
3555  return MHD_NO;
3556  }
3557  }
3558  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3559  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3560  &rs,
3561  &maxsock,
3562  FD_SETSIZE)) )
3563  {
3564 #if defined(MHD_WINSOCK_SOCKETS)
3565  /* fdset limit reached, new connections
3566  cannot be handled. Remove listen socket FD
3567  from fdset and retry to add ITC FD. */
3568  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3569  (! daemon->was_quiesced) )
3570  {
3571  FD_CLR (ls,
3572  &rs);
3573  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
3574  &rs,
3575  &maxsock,
3576  FD_SETSIZE))
3577  {
3578 #endif /* MHD_WINSOCK_SOCKETS */
3579 #ifdef HAVE_MESSAGES
3580  MHD_DLOG (daemon,
3581  _("Could not add control inter-thread communication channel FD to fdset"));
3582 #endif
3583  err_state = MHD_YES;
3584 #if defined(MHD_WINSOCK_SOCKETS)
3585  }
3586  }
3587 #endif /* MHD_WINSOCK_SOCKETS */
3588  }
3589  /* Stop listening if we are at the configured connection limit */
3590  /* If we're at the connection limit, no point in really
3591  accepting new connections; however, make sure we do not miss
3592  the shutdown OR the termination of an existing connection; so
3593  only do this optimization if we have a signaling ITC in
3594  place. */
3595  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3596  (MHD_ITC_IS_VALID_(daemon->itc)) &&
3597  ( (daemon->connections == daemon->connection_limit) ||
3598  (daemon->at_limit) ) )
3599  {
3600  FD_CLR (ls,
3601  &rs);
3602  }
3603  tv = NULL;
3604  if (MHD_YES == err_state)
3605  may_block = MHD_NO;
3606  if (MHD_NO == may_block)
3607  {
3608  timeout.tv_usec = 0;
3609  timeout.tv_sec = 0;
3610  tv = &timeout;
3611  }
3612  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3613  (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
3614  {
3615  /* ltimeout is in ms */
3616  timeout.tv_usec = (ltimeout % 1000) * 1000;
3617  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
3618  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
3619  else
3620  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)(ltimeout / 1000);
3621  tv = &timeout;
3622  }
3623  num_ready = MHD_SYS_select_ (maxsock + 1,
3624  &rs,
3625  &ws,
3626  &es,
3627  tv);
3628  if (daemon->shutdown)
3629  return MHD_NO;
3630  if (num_ready < 0)
3631  {
3632  const int err = MHD_socket_get_error_ ();
3633  if (MHD_SCKT_ERR_IS_EINTR_(err))
3634  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3635 #ifdef HAVE_MESSAGES
3636  MHD_DLOG (daemon,
3637  _("select failed: %s\n"),
3638  MHD_socket_strerr_ (err));
3639 #endif
3640  return MHD_NO;
3641  }
3642  if (MHD_YES == internal_run_from_select (daemon,
3643  &rs,
3644  &ws,
3645  &es))
3646  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3647  return MHD_NO;
3648 }
3649 
3650 
3651 #ifdef HAVE_POLL
3652 
3660 static int
3661 MHD_poll_all (struct MHD_Daemon *daemon,
3662  int may_block)
3663 {
3664  unsigned int num_connections;
3665  struct MHD_Connection *pos;
3666  struct MHD_Connection *prev;
3667 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3668  struct MHD_UpgradeResponseHandle *urh;
3669  struct MHD_UpgradeResponseHandle *urhn;
3670 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3671 
3672  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3673  (MHD_YES == resume_suspended_connections (daemon)) )
3674  may_block = MHD_NO;
3675 
3676  /* count number of connections and thus determine poll set size */
3677  num_connections = 0;
3678  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3679  num_connections++;
3680 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3681  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3682  num_connections += 2;
3683 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3684  {
3685  MHD_UNSIGNED_LONG_LONG ltimeout;
3686  unsigned int i;
3687  int timeout;
3688  unsigned int poll_server;
3689  int poll_listen;
3690  int poll_itc_idx;
3691  struct pollfd *p;
3692  MHD_socket ls;
3693 
3694  p = MHD_calloc_ ((2 + num_connections), sizeof (struct pollfd));
3695  if (NULL == p)
3696  {
3697 #ifdef HAVE_MESSAGES
3698  MHD_DLOG (daemon,
3699  _("Error allocating memory: %s\n"),
3700  MHD_strerror_(errno));
3701 #endif
3702  return MHD_NO;
3703  }
3704  poll_server = 0;
3705  poll_listen = -1;
3706  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3707  (! daemon->was_quiesced) &&
3708  (daemon->connections < daemon->connection_limit) &&
3709  (! daemon->at_limit) )
3710  {
3711  /* only listen if we are not at the connection limit */
3712  p[poll_server].fd = ls;
3713  p[poll_server].events = POLLIN;
3714  p[poll_server].revents = 0;
3715  poll_listen = (int) poll_server;
3716  poll_server++;
3717  }
3718  poll_itc_idx = -1;
3719  if (MHD_ITC_IS_VALID_(daemon->itc))
3720  {
3721  p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3722  p[poll_server].events = POLLIN;
3723  p[poll_server].revents = 0;
3724  poll_itc_idx = (int) poll_server;
3725  poll_server++;
3726  }
3727  if (may_block == MHD_NO)
3728  timeout = 0;
3729  else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3730  (MHD_YES != MHD_get_timeout (daemon,
3731  &ltimeout)) )
3732  timeout = -1;
3733  else
3734  timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3735 
3736  i = 0;
3737  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
3738  {
3739  p[poll_server+i].fd = pos->socket_fd;
3740  switch (pos->event_loop_info)
3741  {
3743  p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3744  break;
3746  p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3747  break;
3749  p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3750  break;
3752  timeout = 0; /* clean up "pos" immediately */
3753  break;
3754  }
3755  i++;
3756  }
3757 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3758  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3759  {
3760  urh_to_pollfd(urh, &(p[poll_server+i]));
3761  i += 2;
3762  }
3763 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3764  if (0 == poll_server + num_connections)
3765  {
3766  free(p);
3767  return MHD_YES;
3768  }
3769  if (MHD_sys_poll_(p,
3770  poll_server + num_connections,
3771  timeout) < 0)
3772  {
3773  const int err = MHD_socket_get_error_ ();
3774  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3775  {
3776  free(p);
3777  return MHD_YES;
3778  }
3779 #ifdef HAVE_MESSAGES
3780  MHD_DLOG (daemon,
3781  _("poll failed: %s\n"),
3782  MHD_socket_strerr_ (err));
3783 #endif
3784  free(p);
3785  return MHD_NO;
3786  }
3787 
3788  /* Reset. New value will be set when connections are processed. */
3789  daemon->data_already_pending = false;
3790 
3791  /* handle ITC FD */
3792  /* do it before any other processing so
3793  new signals will be processed in next loop */
3794  if ( (-1 != poll_itc_idx) &&
3795  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3796  MHD_itc_clear_ (daemon->itc);
3797 
3798  /* handle shutdown */
3799  if (daemon->shutdown)
3800  {
3801  free(p);
3802  return MHD_NO;
3803  }
3804  i = 0;
3805  prev = daemon->connections_tail;
3806  while (NULL != (pos = prev))
3807  {
3808  prev = pos->prev;
3809  /* first, sanity checks */
3810  if (i >= num_connections)
3811  break; /* connection list changed somehow, retry later ... */
3812  if (p[poll_server+i].fd != pos->socket_fd)
3813  continue; /* fd mismatch, something else happened, retry later ... */
3814  call_handlers (pos,
3815  0 != (p[poll_server+i].revents & POLLIN),
3816  0 != (p[poll_server+i].revents & POLLOUT),
3817  0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
3818  i++;
3819  }
3820 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3821  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3822  {
3823  if (i >= num_connections)
3824  break; /* connection list changed somehow, retry later ... */
3825 
3826  /* Get next connection here as connection can be removed
3827  * from 'daemon->urh_head' list. */
3828  urhn = urh->prev;
3829  /* Check for fd mismatch. FIXME: required for safety? */
3830  if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3831  (p[poll_server+i+1].fd != urh->mhd.socket))
3832  break;
3833  urh_from_pollfd(urh, &(p[poll_server+i]));
3834  i += 2;
3835  process_urh (urh);
3836  /* Finished forwarding? */
3837  if ( (0 == urh->in_buffer_size) &&
3838  (0 == urh->out_buffer_size) &&
3839  (0 == urh->in_buffer_used) &&
3840  (0 == urh->out_buffer_used) )
3841  {
3842  /* MHD_connection_finish_forward_() will remove connection from
3843  * 'daemon->urh_head' list. */
3844  MHD_connection_finish_forward_ (urh->connection);
3845  urh->clean_ready = true;
3846  /* If 'urh->was_closed' already was set to true, connection will be
3847  * moved immediately to cleanup list. Otherwise connection
3848  * will stay in suspended list until 'urh' will be marked
3849  * with 'was_closed' by application. */
3850  MHD_resume_connection(urh->connection);
3851  }
3852  }
3853 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3854  /* handle 'listen' FD */
3855  if ( (-1 != poll_listen) &&
3856  (0 != (p[poll_listen].revents & POLLIN)) )
3857  (void) MHD_accept_connection (daemon);
3858 
3859  free(p);
3860  }
3861  return MHD_YES;
3862 }
3863 
3864 
3872 static int
3873 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3874  int may_block)
3875 {
3876  struct pollfd p[2];
3877  int timeout;
3878  unsigned int poll_count;
3879  int poll_listen;
3880  int poll_itc_idx;
3881  MHD_socket ls;
3882 
3883  memset (&p,
3884  0,
3885  sizeof (p));
3886  poll_count = 0;
3887  poll_listen = -1;
3888  poll_itc_idx = -1;
3889  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3890  (! daemon->was_quiesced) )
3891 
3892  {
3893  p[poll_count].fd = ls;
3894  p[poll_count].events = POLLIN;
3895  p[poll_count].revents = 0;
3896  poll_listen = poll_count;
3897  poll_count++;
3898  }
3899  if (MHD_ITC_IS_VALID_(daemon->itc))
3900  {
3901  p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
3902  p[poll_count].events = POLLIN;
3903  p[poll_count].revents = 0;
3904  poll_itc_idx = poll_count;
3905  poll_count++;
3906  }
3907  if (MHD_NO == may_block)
3908  timeout = 0;
3909  else
3910  timeout = -1;
3911  if (0 == poll_count)
3912  return MHD_YES;
3913  if (MHD_sys_poll_(p,
3914  poll_count,
3915  timeout) < 0)
3916  {
3917  const int err = MHD_socket_get_error_ ();
3918 
3919  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3920  return MHD_YES;
3921 #ifdef HAVE_MESSAGES
3922  MHD_DLOG (daemon,
3923  _("poll failed: %s\n"),
3924  MHD_socket_strerr_ (err));
3925 #endif
3926  return MHD_NO;
3927  }
3928  if ( (-1 != poll_itc_idx) &&
3929  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3930  MHD_itc_clear_ (daemon->itc);
3931 
3932  /* handle shutdown */
3933  if (daemon->shutdown)
3934  return MHD_NO;
3935  if ( (-1 != poll_listen) &&
3936  (0 != (p[poll_listen].revents & POLLIN)) )
3937  (void) MHD_accept_connection (daemon);
3938  return MHD_YES;
3939 }
3940 #endif
3941 
3942 
3950 static int
3951 MHD_poll (struct MHD_Daemon *daemon,
3952  int may_block)
3953 {
3954 #ifdef HAVE_POLL
3955  if (daemon->shutdown)
3956  return MHD_NO;
3957  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3958  return MHD_poll_all (daemon,
3959  may_block);
3960  return MHD_poll_listen_socket (daemon,
3961  may_block);
3962 #else
3963  return MHD_NO;
3964 #endif
3965 }
3966 
3967 
3968 #ifdef EPOLL_SUPPORT
3969 
3978 #define MAX_EVENTS 128
3979 
3980 
3981 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3982 
3990 static bool
3991 is_urh_ready(struct MHD_UpgradeResponseHandle * const urh)
3992 {
3993  const struct MHD_Connection * const connection = urh->connection;
3994 
3995  if ( (0 == urh->in_buffer_size) &&
3996  (0 == urh->out_buffer_size) &&
3997  (0 == urh->in_buffer_used) &&
3998  (0 == urh->out_buffer_used) )
3999  return false;
4000 
4001  if (connection->daemon->shutdown)
4002  return true;
4003 
4004  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4005  (connection->tls_read_ready) ) &&
4006  (urh->in_buffer_used < urh->in_buffer_size) )
4007  return true;
4008 
4009  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4010  (urh->out_buffer_used < urh->out_buffer_size) )
4011  return true;
4012 
4013  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4014  (urh->out_buffer_used > 0) )
4015  return true;
4016 
4017  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4018  (urh->in_buffer_used > 0) )
4019  return true;
4020 
4021  return false;
4022 }
4023 
4032 static int
4033 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4034 {
4035  struct epoll_event events[MAX_EVENTS];
4036  int num_events;
4037  struct MHD_UpgradeResponseHandle * pos;
4038  struct MHD_UpgradeResponseHandle * prev;
4039 
4040  num_events = MAX_EVENTS;
4041  while (MAX_EVENTS == num_events)
4042  {
4043  unsigned int i;
4044  /* update event masks */
4045  num_events = epoll_wait (daemon->epoll_upgrade_fd,
4046  events,
4047  MAX_EVENTS,
4048  0);
4049  if (-1 == num_events)
4050  {
4051  const int err = MHD_socket_get_error_ ();
4052  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4053  return MHD_YES;
4054 #ifdef HAVE_MESSAGES
4055  MHD_DLOG (daemon,
4056  _("Call to epoll_wait failed: %s\n"),
4057  MHD_socket_strerr_ (err));
4058 #endif
4059  return MHD_NO;
4060  }
4061  for (i = 0; i < (unsigned int) num_events; i++)
4062  {
4063  struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
4064  struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
4065  bool new_err_state = false;
4066 
4067  if (urh->clean_ready)
4068  continue;
4069 
4070  /* Update ueh state based on what is ready according to epoll() */
4071  if (0 != (events[i].events & EPOLLIN))
4072  ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4073  if (0 != (events[i].events & EPOLLOUT))
4074  ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4075  if (0 != (events[i].events & EPOLLHUP))
4077 
4078  if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4079  (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4080  {
4081  /* Process new error state only one time
4082  * and avoid continuously marking this connection
4083  * as 'ready'. */
4084  ueh->celi |= MHD_EPOLL_STATE_ERROR;
4085  new_err_state = true;
4086  }
4087 
4088  if (! urh->in_eready_list)
4089  {
4090  if (new_err_state ||
4091  is_urh_ready(urh))
4092  {
4093  EDLL_insert (daemon->eready_urh_head,
4094  daemon->eready_urh_tail,
4095  urh);
4096  urh->in_eready_list = true;
4097  }
4098  }
4099  }
4100  }
4101  prev = daemon->eready_urh_tail;
4102  while (NULL != (pos = prev))
4103  {
4104  prev = pos->prevE;
4105  process_urh (pos);
4106  if (! is_urh_ready(pos))
4107  {
4108  EDLL_remove (daemon->eready_urh_head,
4109  daemon->eready_urh_tail,
4110  pos);
4111  pos->in_eready_list = false;
4112  }
4113  /* Finished forwarding? */
4114  if ( (0 == pos->in_buffer_size) &&
4115  (0 == pos->out_buffer_size) &&
4116  (0 == pos->in_buffer_used) &&
4117  (0 == pos->out_buffer_used) )
4118  {
4119  MHD_connection_finish_forward_ (pos->connection);
4120  pos->clean_ready = true;
4121  /* If 'pos->was_closed' already was set to true, connection
4122  * will be moved immediately to cleanup list. Otherwise
4123  * connection will stay in suspended list until 'pos' will
4124  * be marked with 'was_closed' by application. */
4125  MHD_resume_connection(pos->connection);
4126  }
4127  }
4128 
4129  return MHD_YES;
4130 }
4131 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4132 
4136 static const char * const epoll_itc_marker = "itc_marker";
4137 
4146 static int
4147 MHD_epoll (struct MHD_Daemon *daemon,
4148  int may_block)
4149 {
4150 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4151  static const char * const upgrade_marker = "upgrade_ptr";
4152 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4153  struct MHD_Connection *pos;
4154  struct MHD_Connection *prev;
4155  struct epoll_event events[MAX_EVENTS];
4156  struct epoll_event event;
4157  int timeout_ms;
4158  MHD_UNSIGNED_LONG_LONG timeout_ll;
4159  int num_events;
4160  unsigned int i;
4161  MHD_socket ls;
4162 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4163  int run_upgraded = MHD_NO;
4164 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4165 
4166  if (-1 == daemon->epoll_fd)
4167  return MHD_NO; /* we're down! */
4168  if (daemon->shutdown)
4169  return MHD_NO;
4170  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4171  (! daemon->was_quiesced) &&
4172  (daemon->connections < daemon->connection_limit) &&
4173  (! daemon->listen_socket_in_epoll) &&
4174  (! daemon->at_limit) )
4175  {
4176  event.events = EPOLLIN;
4177  event.data.ptr = daemon;
4178  if (0 != epoll_ctl (daemon->epoll_fd,
4179  EPOLL_CTL_ADD,
4180  ls,
4181  &event))
4182  {
4183 #ifdef HAVE_MESSAGES
4184  MHD_DLOG (daemon,
4185  _("Call to epoll_ctl failed: %s\n"),
4187 #endif
4188  return MHD_NO;
4189  }
4190  daemon->listen_socket_in_epoll = true;
4191  }
4192  if ( (daemon->was_quiesced) &&
4193  (daemon->listen_socket_in_epoll) )
4194  {
4195  if (0 != epoll_ctl (daemon->epoll_fd,
4196  EPOLL_CTL_DEL,
4197  ls,
4198  NULL))
4199  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4200  daemon->listen_socket_in_epoll = false;
4201  }
4202 
4203 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4204  if ( (! daemon->upgrade_fd_in_epoll) &&
4205  (-1 != daemon->epoll_upgrade_fd) )
4206  {
4207  event.events = EPOLLIN | EPOLLOUT;
4208  event.data.ptr = (void *) upgrade_marker;
4209  if (0 != epoll_ctl (daemon->epoll_fd,
4210  EPOLL_CTL_ADD,
4211  daemon->epoll_upgrade_fd,
4212  &event))
4213  {
4214 #ifdef HAVE_MESSAGES
4215  MHD_DLOG (daemon,
4216  _("Call to epoll_ctl failed: %s\n"),
4218 #endif
4219  return MHD_NO;
4220  }
4221  daemon->upgrade_fd_in_epoll = true;
4222  }
4223 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4224  if ( (daemon->listen_socket_in_epoll) &&
4225  ( (daemon->connections == daemon->connection_limit) ||
4226  (daemon->at_limit) ||
4227  (daemon->was_quiesced) ) )
4228  {
4229  /* we're at the connection limit, disable listen socket
4230  for event loop for now */
4231  if (0 != epoll_ctl (daemon->epoll_fd,
4232  EPOLL_CTL_DEL,
4233  ls,
4234  NULL))
4235  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4236  daemon->listen_socket_in_epoll = false;
4237  }
4238  if (MHD_YES == may_block)
4239  {
4240  if (MHD_YES == MHD_get_timeout (daemon,
4241  &timeout_ll))
4242  {
4243  if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4244  timeout_ms = INT_MAX;
4245  else
4246  timeout_ms = (int) timeout_ll;
4247  }
4248  else
4249  timeout_ms = -1;
4250  }
4251  else
4252  timeout_ms = 0;
4253 
4254  /* Reset. New value will be set when connections are processed. */
4255  /* Note: Used mostly for uniformity here as same situation is
4256  * signaled in epoll mode by non-empty eready DLL. */
4257  daemon->data_already_pending = false;
4258 
4259  /* drain 'epoll' event queue; need to iterate as we get at most
4260  MAX_EVENTS in one system call here; in practice this should
4261  pretty much mean only one round, but better an extra loop here
4262  than unfair behavior... */
4263  num_events = MAX_EVENTS;
4264  while (MAX_EVENTS == num_events)
4265  {
4266  /* update event masks */
4267  num_events = epoll_wait (daemon->epoll_fd,
4268  events,
4269  MAX_EVENTS,
4270  timeout_ms);
4271  if (-1 == num_events)
4272  {
4273  const int err = MHD_socket_get_error_ ();
4274  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4275  return MHD_YES;
4276 #ifdef HAVE_MESSAGES
4277  MHD_DLOG (daemon,
4278  _("Call to epoll_wait failed: %s\n"),
4279  MHD_socket_strerr_ (err));
4280 #endif
4281  return MHD_NO;
4282  }
4283  for (i=0;i<(unsigned int) num_events;i++)
4284  {
4285  /* First, check for the values of `ptr` that would indicate
4286  that this event is not about a normal connection. */
4287  if (NULL == events[i].data.ptr)
4288  continue; /* shutdown signal! */
4289 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4290  if (upgrade_marker == events[i].data.ptr)
4291  {
4292  /* activity on an upgraded connection, we process
4293  those in a separate epoll() */
4294  run_upgraded = MHD_YES;
4295  continue;
4296  }
4297 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4298  if (epoll_itc_marker == events[i].data.ptr)
4299  {
4300  /* It's OK to clear ITC here as all external
4301  conditions will be processed later. */
4302  MHD_itc_clear_ (daemon->itc);
4303  continue;
4304  }
4305  if (daemon == events[i].data.ptr)
4306  {
4307  /* Check for error conditions on listen socket. */
4308  /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4309  if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4310  {
4311  unsigned int series_length = 0;
4312  /* Run 'accept' until it fails or daemon at limit of connections.
4313  * Do not accept more then 10 connections at once. The rest will
4314  * be accepted on next turn (level trigger is used for listen
4315  * socket). */
4316  while ( (MHD_YES == MHD_accept_connection (daemon)) &&
4317  (series_length < 10) &&
4318  (daemon->connections < daemon->connection_limit) &&
4319  (! daemon->at_limit) )
4320  series_length++;
4321  }
4322  continue;
4323  }
4324  /* this is an event relating to a 'normal' connection,
4325  remember the event and if appropriate mark the
4326  connection as 'eready'. */
4327  pos = events[i].data.ptr;
4328  /* normal processing: update read/write data */
4329  if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4330  {
4331  pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4332  if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4333  {
4334  EDLL_insert (daemon->eready_head,
4335  daemon->eready_tail,
4336  pos);
4337  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4338  }
4339  }
4340  else
4341  {
4342  if (0 != (events[i].events & EPOLLIN))
4343  {
4344  pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4345  if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4346  (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4347  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4348  {
4349  EDLL_insert (daemon->eready_head,
4350  daemon->eready_tail,
4351  pos);
4352  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4353  }
4354  }
4355  if (0 != (events[i].events & EPOLLOUT))
4356  {
4357  pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4358  if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
4359  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4360  {
4361  EDLL_insert (daemon->eready_head,
4362  daemon->eready_tail,
4363  pos);
4364  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4365  }
4366  }
4367  }
4368  }
4369  }
4370 
4371 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4372  if (MHD_YES == run_upgraded)
4373  run_epoll_for_upgrade (daemon);
4374 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4375 
4376  /* we handle resumes here because we may have ready connections
4377  that will not be placed into the epoll list immediately. */
4378  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
4379  (void) resume_suspended_connections (daemon);
4380 
4381  /* process events for connections */
4382  prev = daemon->eready_tail;
4383  while (NULL != (pos = prev))
4384  {
4385  prev = pos->prevE;
4386  call_handlers (pos,
4387  0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
4388  0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
4389  0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
4392  {
4393  if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info &&
4394  0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ) ||
4396  0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ) ||
4398  {
4399  EDLL_remove (daemon->eready_head,
4400  daemon->eready_tail,
4401  pos);
4402  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4403  }
4404  }
4405  }
4406 
4407  /* Finally, handle timed-out connections; we need to do this here
4408  as the epoll mechanism won't call the 'idle_handler' on everything,
4409  as the other event loops do. As timeouts do not get an explicit
4410  event, we need to find those connections that might have timed out
4411  here.
4412 
4413  Connections with custom timeouts must all be looked at, as we
4414  do not bother to sort that (presumably very short) list. */
4415  prev = daemon->manual_timeout_tail;
4416  while (NULL != (pos = prev))
4417  {
4418  prev = pos->prevX;
4419  pos->idle_handler (pos);
4420  }
4421  /* Connections with the default timeout are sorted by prepending
4422  them to the head of the list whenever we touch the connection;
4423  thus it suffices to iterate from the tail until the first
4424  connection is NOT timed out */
4425  prev = daemon->normal_timeout_tail;
4426  while (NULL != (pos = prev))
4427  {
4428  prev = pos->prevX;
4429  pos->idle_handler (pos);
4430  if (MHD_CONNECTION_CLOSED != pos->state)
4431  break; /* sorted by timeout, no need to visit the rest! */
4432  }
4433  return MHD_YES;
4434 }
4435 #endif
4436 
4437 
4457 int
4458 MHD_run (struct MHD_Daemon *daemon)
4459 {
4460  if ( (daemon->shutdown) ||
4461  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4462  return MHD_NO;
4463  if (0 != (daemon->options & MHD_USE_POLL))
4464  {
4465  MHD_poll (daemon, MHD_NO);
4466  MHD_cleanup_connections (daemon);
4467  }
4468 #ifdef EPOLL_SUPPORT
4469  else if (0 != (daemon->options & MHD_USE_EPOLL))
4470  {
4471  MHD_epoll (daemon, MHD_NO);
4472  MHD_cleanup_connections (daemon);
4473  }
4474 #endif
4475  else
4476  {
4477  MHD_select (daemon, MHD_NO);
4478  /* MHD_select does MHD_cleanup_connections already */
4479  }
4480  return MHD_YES;
4481 }
4482 
4483 
4492 static void
4494 {
4495  struct MHD_Daemon *daemon = pos->daemon;
4496 
4497  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4498  {
4500  return; /* must let thread to do the rest */
4501  }
4502  MHD_connection_close_ (pos,
4504 
4506 
4507  if (pos->connection_timeout == pos->daemon->connection_timeout)
4509  daemon->normal_timeout_tail,
4510  pos);
4511  else
4513  daemon->manual_timeout_tail,
4514  pos);
4515  DLL_remove (daemon->connections_head,
4516  daemon->connections_tail,
4517  pos);
4518  DLL_insert (daemon->cleanup_head,
4519  daemon->cleanup_tail,
4520  pos);
4521 
4523 }
4524 
4525 
4533 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4535 {
4536  struct MHD_Daemon *daemon = cls;
4537 
4538  while (! daemon->shutdown)
4539  {
4540  if (0 != (daemon->options & MHD_USE_POLL))
4541  MHD_poll (daemon, MHD_YES);
4542 #ifdef EPOLL_SUPPORT
4543  else if (0 != (daemon->options & MHD_USE_EPOLL))
4544  MHD_epoll (daemon, MHD_YES);
4545 #endif
4546  else
4547  MHD_select (daemon, MHD_YES);
4548  MHD_cleanup_connections (daemon);
4549  }
4550 
4551  /* Resume any pending for resume connections, join
4552  * all connection's threads (if any) and finally cleanup
4553  * everything. */
4554  close_all_connections (daemon);
4555 
4556  return (MHD_THRD_RTRN_TYPE_)0;
4557 }
4558 
4559 
4571 static size_t
4572 unescape_wrapper (void *cls,
4573  struct MHD_Connection *connection,
4574  char *val)
4575 {
4576  return MHD_http_unescape (val);
4577 }
4578 
4579 
4596 struct MHD_Daemon *
4597 MHD_start_daemon (unsigned int flags,
4598  uint16_t port,
4600  void *apc_cls,
4602  void *dh_cls,
4603  ...)
4604 {
4605  struct MHD_Daemon *daemon;
4606  va_list ap;
4607 
4608  va_start (ap,
4609  dh_cls);
4610  daemon = MHD_start_daemon_va (flags,
4611  port,
4612  apc,
4613  apc_cls,
4614  dh,
4615  dh_cls,
4616  ap);
4617  va_end (ap);
4618  return daemon;
4619 }
4620 
4621 
4641 MHD_socket
4643 {
4644  unsigned int i;
4645  MHD_socket ret;
4646 
4647  ret = daemon->listen_fd;
4648  if (MHD_INVALID_SOCKET == ret)
4649  return MHD_INVALID_SOCKET;
4650  if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
4651  (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
4652  {
4653 #ifdef HAVE_MESSAGES
4654  MHD_DLOG (daemon,
4655  "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
4656 #endif
4657  return MHD_INVALID_SOCKET;
4658  }
4659 
4660  if (NULL != daemon->worker_pool)
4661  for (i = 0; i < daemon->worker_pool_size; i++)
4662  {
4663  daemon->worker_pool[i].was_quiesced = true;
4664 #ifdef EPOLL_SUPPORT
4665  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4666  (-1 != daemon->worker_pool[i].epoll_fd) &&
4667  (daemon->worker_pool[i].listen_socket_in_epoll) )
4668  {
4669  if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4670  EPOLL_CTL_DEL,
4671  ret,
4672  NULL))
4673  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4674  daemon->worker_pool[i].listen_socket_in_epoll = false;
4675  }
4676  else
4677 #endif
4678  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
4679  {
4680  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4681  MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
4682  }
4683  }
4684  daemon->was_quiesced = true;
4685 #ifdef EPOLL_SUPPORT
4686  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4687  (-1 != daemon->epoll_fd) &&
4688  (daemon->listen_socket_in_epoll) )
4689  {
4690  if (0 != epoll_ctl (daemon->epoll_fd,
4691  EPOLL_CTL_DEL,
4692  ret,
4693  NULL))
4694  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4695  daemon->listen_socket_in_epoll = false;
4696  }
4697 #endif
4698  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
4699  (! MHD_itc_activate_ (daemon->itc, "q")) )
4700  MHD_PANIC (_("failed to signal quiesce via inter-thread communication channel"));
4701  return ret;
4702 }
4703 
4704 
4712 typedef void
4714  const char *format,
4715  va_list va);
4716 
4717 
4726 static int
4727 parse_options_va (struct MHD_Daemon *daemon,
4728  const struct sockaddr **servaddr,
4729  va_list ap);
4730 
4731 
4740 static int
4741 parse_options (struct MHD_Daemon *daemon,
4742  const struct sockaddr **servaddr,
4743  ...)
4744 {
4745  va_list ap;
4746  int ret;
4747 
4748  va_start (ap, servaddr);
4749  ret = parse_options_va (daemon,
4750  servaddr,
4751  ap);
4752  va_end (ap);
4753  return ret;
4754 }
4755 
4756 
4765 static int
4767  const struct sockaddr **servaddr,
4768  va_list ap)
4769 {
4770  enum MHD_OPTION opt;
4771  struct MHD_OptionItem *oa;
4772  unsigned int i;
4773  unsigned int uv;
4774 #ifdef HTTPS_SUPPORT
4775  int ret;
4776  const char *pstr;
4777 #endif /* HTTPS_SUPPORT */
4778 
4779  while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
4780  {
4781  switch (opt)
4782  {
4784  daemon->pool_size = va_arg (ap,
4785  size_t);
4786  break;
4788  daemon->pool_increment= va_arg (ap,
4789  size_t);
4790  break;
4792  daemon->connection_limit = va_arg (ap,
4793  unsigned int);
4794  break;
4796  uv = va_arg (ap,
4797  unsigned int);
4798  if (TIME_T_MAX < uv)
4799  {
4800 #ifdef HAVE_MESSAGES
4801  MHD_DLOG (daemon,
4802  _("Warning: Too large timeout value, ignored.\n"));
4803 #endif
4804  daemon->connection_timeout = 0;
4805  }
4806  else
4807  daemon->connection_timeout = (time_t)uv;
4808  break;
4810  daemon->notify_completed = va_arg (ap,
4812  daemon->notify_completed_cls = va_arg (ap,
4813  void *);
4814  break;
4816  daemon->notify_connection = va_arg (ap,
4818  daemon->notify_connection_cls = va_arg (ap,
4819  void *);
4820  break;
4822  daemon->per_ip_connection_limit = va_arg (ap,
4823  unsigned int);
4824  break;
4825  case MHD_OPTION_SOCK_ADDR:
4826  *servaddr = va_arg (ap,
4827  const struct sockaddr *);
4828  break;
4830  daemon->uri_log_callback = va_arg (ap,
4831  LogCallback);
4832  daemon->uri_log_callback_cls = va_arg (ap,
4833  void *);
4834  break;
4836  daemon->worker_pool_size = va_arg (ap,
4837  unsigned int);
4838  if (0 == daemon->worker_pool_size)
4839  {
4840 #ifdef HAVE_MESSAGES
4841  MHD_DLOG (daemon,
4842  _("Warning: Zero size, specified for thread pool size, is ignored. "
4843  "Thread pool is not used.\n"));
4844 #endif
4845  }
4846  else if (1 == daemon->worker_pool_size)
4847  {
4848 #ifdef HAVE_MESSAGES
4849  MHD_DLOG (daemon,
4850  _("Warning: \"1\", specified for thread pool size, is ignored. "
4851  "Thread pool is not used.\n"));
4852 #endif
4853  daemon->worker_pool_size = 0;
4854  }
4855  else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct MHD_Daemon)))
4856  {
4857 #ifdef HAVE_MESSAGES
4858  MHD_DLOG (daemon,
4859  _("Specified thread pool size (%u) too big\n"),
4860  daemon->worker_pool_size);
4861 #endif
4862  return MHD_NO;
4863  }
4864  else
4865  {
4866  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
4867  {
4868 #ifdef HAVE_MESSAGES
4869  MHD_DLOG (daemon,
4870  _("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
4871  "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
4872 #endif
4873  return MHD_NO;
4874  }
4875  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4876  {
4877 #ifdef HAVE_MESSAGES
4878  MHD_DLOG (daemon,
4879  _("Both MHD_OPTION_THREAD_POOL_SIZE option and "
4880  "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
4881 #endif
4882  return MHD_NO;
4883  }
4884  }
4885  break;
4886 #ifdef HTTPS_SUPPORT
4888  if (0 != (daemon->options & MHD_USE_TLS))
4889  daemon->https_mem_key = va_arg (ap,
4890  const char *);
4891 #ifdef HAVE_MESSAGES
4892  else
4893  MHD_DLOG (daemon,
4894  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4895  opt);
4896 #endif
4897  break;
4899  if (0 != (daemon->options & MHD_USE_TLS))
4900  daemon->https_key_password = va_arg (ap,
4901  const char *);
4902 #ifdef HAVE_MESSAGES
4903  else
4904  MHD_DLOG (daemon,
4905  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4906  opt);
4907 #endif
4908  break;
4910  if (0 != (daemon->options & MHD_USE_TLS))
4911  daemon->https_mem_cert = va_arg (ap,
4912  const char *);
4913 #ifdef HAVE_MESSAGES
4914  else
4915  MHD_DLOG (daemon,
4916  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4917  opt);
4918 #endif
4919  break;
4921  if (0 != (daemon->options & MHD_USE_TLS))
4922  daemon->https_mem_trust = va_arg (ap,
4923  const char *);
4924 #ifdef HAVE_MESSAGES
4925  else
4926  MHD_DLOG (daemon,
4927  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4928  opt);
4929 #endif
4930  break;
4932  daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4933  int);
4934  break;
4936  if (0 != (daemon->options & MHD_USE_TLS))
4937  {
4938  const char *arg = va_arg (ap,
4939  const char *);
4940  gnutls_datum_t dhpar;
4941 
4942  if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4943  {
4944 #ifdef HAVE_MESSAGES
4945  MHD_DLOG (daemon,
4946  _("Error initializing DH parameters\n"));
4947 #endif
4948  return MHD_NO;
4949  }
4950  dhpar.data = (unsigned char *) arg;
4951  dhpar.size = strlen (arg);
4952  if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4953  &dhpar,
4954  GNUTLS_X509_FMT_PEM) < 0)
4955  {
4956 #ifdef HAVE_MESSAGES
4957  MHD_DLOG (daemon,
4958  _("Bad Diffie-Hellman parameters format\n"));
4959 #endif
4960  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4961  return MHD_NO;
4962  }
4963  daemon->have_dhparams = true;
4964  }
4965  else
4966  {
4967 #ifdef HAVE_MESSAGES
4968  MHD_DLOG (daemon,
4969  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4970  opt);
4971 #endif
4972  return MHD_NO;
4973  }
4974  break;
4976  if (0 != (daemon->options & MHD_USE_TLS))
4977  {
4978  gnutls_priority_deinit (daemon->priority_cache);
4979  ret = gnutls_priority_init (&daemon->priority_cache,
4980  pstr = va_arg (ap, const char*),
4981  NULL);
4982  if (GNUTLS_E_SUCCESS != ret)
4983  {
4984 #ifdef HAVE_MESSAGES
4985  MHD_DLOG (daemon,
4986  _("Setting priorities to `%s' failed: %s\n"),
4987  pstr,
4988  gnutls_strerror (ret));
4989 #endif
4990  daemon->priority_cache = NULL;
4991  return MHD_NO;
4992  }
4993  }
4994  break;
4996 #if GNUTLS_VERSION_MAJOR < 3
4997 #ifdef HAVE_MESSAGES
4998  MHD_DLOG (daemon,
4999  _("MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
5000 #endif
5001  return MHD_NO;
5002 #else
5003  if (0 != (daemon->options & MHD_USE_TLS))
5004  daemon->cert_callback = va_arg (ap,
5005  gnutls_certificate_retrieve_function2 *);
5006  break;
5007 #endif
5008 #endif /* HTTPS_SUPPORT */
5009 #ifdef DAUTH_SUPPORT
5011  daemon->digest_auth_rand_size = va_arg (ap,
5012  size_t);
5013  daemon->digest_auth_random = va_arg (ap,
5014  const char *);
5015  break;
5017  daemon->nonce_nc_size = va_arg (ap,
5018  unsigned int);
5019  break;
5020 #endif
5022  if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5023  {
5024 #ifdef HAVE_MESSAGES
5025  MHD_DLOG (daemon,
5026  _("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5027  "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5028 #endif
5029  return MHD_NO;
5030  }
5031  else
5032  daemon->listen_fd = va_arg (ap,
5033  MHD_socket);
5034  break;
5036 #ifdef HAVE_MESSAGES
5037  daemon->custom_error_log = va_arg (ap,
5039  daemon->custom_error_log_cls = va_arg (ap,
5040  void *);
5041 #else
5042  va_arg (ap,
5044  va_arg (ap,
5045  void *);
5046 #endif
5047  break;
5049  daemon->thread_stack_size = va_arg (ap,
5050  size_t);
5051  break;
5052 #ifdef TCP_FASTOPEN
5054  daemon->fastopen_queue_size = va_arg (ap,
5055  unsigned int);
5056  break;
5057 #endif
5059  daemon->listening_address_reuse = va_arg (ap,
5060  unsigned int) ? 1 : -1;
5061  break;
5063  daemon->listen_backlog_size = va_arg (ap,
5064  unsigned int);
5065  break;
5067  daemon->strict_for_client = va_arg (ap, int);;
5068 #ifdef HAVE_MESSAGES
5069  if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
5070  (1 != daemon->strict_for_client) )
5071  {
5072  MHD_DLOG (daemon,
5073  _("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5074  "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5075  }
5076 #endif /* HAVE_MESSAGES */
5077  break;
5078  case MHD_OPTION_ARRAY:
5079  oa = va_arg (ap, struct MHD_OptionItem*);
5080  i = 0;
5081  while (MHD_OPTION_END != (opt = oa[i].option))
5082  {
5083  switch (opt)
5084  {
5085  /* all options taking 'size_t' */
5089  if (MHD_YES != parse_options (daemon,
5090  servaddr,
5091  opt,
5092  (size_t) oa[i].value,
5093  MHD_OPTION_END))
5094  return MHD_NO;
5095  break;
5096  /* all options taking 'unsigned int' */
5105  if (MHD_YES != parse_options (daemon,
5106  servaddr,
5107  opt,
5108  (unsigned int) oa[i].value,
5109  MHD_OPTION_END))
5110  return MHD_NO;
5111  break;
5112  /* all options taking 'enum' */
5113 #ifdef HTTPS_SUPPORT
5115  if (MHD_YES != parse_options (daemon,
5116  servaddr,
5117  opt,
5118  (gnutls_credentials_type_t) oa[i].value,
5119  MHD_OPTION_END))
5120  return MHD_NO;
5121  break;
5122 #endif /* HTTPS_SUPPORT */
5123  /* all options taking 'MHD_socket' */
5125  if (MHD_YES != parse_options (daemon,
5126  servaddr,
5127  opt,
5128  (MHD_socket) oa[i].value,
5129  MHD_OPTION_END))
5130  return MHD_NO;
5131  break;
5132  /* all options taking 'int' */
5134  if (MHD_YES != parse_options (daemon,
5135  servaddr,
5136  opt,
5137  (int) oa[i].value,
5138  MHD_OPTION_END))
5139  return MHD_NO;
5140  break;
5141  /* all options taking one pointer */
5142  case MHD_OPTION_SOCK_ADDR:
5149  case MHD_OPTION_ARRAY:
5151  if (MHD_YES != parse_options (daemon,
5152  servaddr,
5153  opt,
5154  oa[i].ptr_value,
5155  MHD_OPTION_END))
5156  return MHD_NO;
5157  break;
5158  /* all options taking two pointers */
5164  if (MHD_YES != parse_options (daemon,
5165  servaddr,
5166  opt,
5167  (void *) oa[i].value,
5168  oa[i].ptr_value,
5169  MHD_OPTION_END))
5170  return MHD_NO;
5171  break;
5172  /* options taking size_t-number followed by pointer */
5174  if (MHD_YES != parse_options (daemon,
5175  servaddr,
5176  opt,
5177  (size_t) oa[i].value,
5178  oa[i].ptr_value,
5179  MHD_OPTION_END))
5180  return MHD_NO;
5181  break;
5182  default:
5183  return MHD_NO;
5184  }
5185  i++;
5186  }
5187  break;
5189  daemon->unescape_callback = va_arg (ap,
5191  daemon->unescape_callback_cls = va_arg (ap,
5192  void *);
5193  break;
5194  default:
5195 #ifdef HAVE_MESSAGES
5196  if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
5197  (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
5198  (opt == MHD_OPTION_HTTPS_MEM_TRUST))
5199  {
5200  MHD_DLOG (daemon,
5201  _("MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
5202  opt);
5203  }
5204  else
5205  {
5206  MHD_DLOG (daemon,
5207  _("Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
5208  opt);
5209  }
5210 #endif
5211  return MHD_NO;
5212  }
5213  }
5214  return MHD_YES;
5215 }
5216 
5217 
5218 #ifdef EPOLL_SUPPORT
5219 static int
5220 setup_epoll_fd (struct MHD_Daemon *daemon)
5221 {
5222  int fd;
5223 
5224 #ifdef USE_EPOLL_CREATE1
5225  fd = epoll_create1 (EPOLL_CLOEXEC);
5226 #else /* ! USE_EPOLL_CREATE1 */
5227  fd = epoll_create (MAX_EVENTS);
5228 #endif /* ! USE_EPOLL_CREATE1 */
5229  if (MHD_INVALID_SOCKET == fd)
5230  {
5231 #ifdef HAVE_MESSAGES
5232  MHD_DLOG (daemon,
5233  _("Call to epoll_create1 failed: %s\n"),
5235 #endif
5236  return MHD_INVALID_SOCKET;
5237  }
5238 #if !defined(USE_EPOLL_CREATE1)
5239  if (! MHD_socket_noninheritable_ (fd))
5240  {
5241 #ifdef HAVE_MESSAGES
5242  MHD_DLOG (daemon,
5243  _("Failed to set noninheritable mode on epoll FD.\n"));
5244 #endif
5245  }
5246 #endif /* ! USE_EPOLL_CREATE1 */
5247  return fd;
5248 }
5249 
5250 
5260 static int
5261 setup_epoll_to_listen (struct MHD_Daemon *daemon)
5262 {
5263  struct epoll_event event;
5264  MHD_socket ls;
5265 
5266  daemon->epoll_fd = setup_epoll_fd (daemon);
5267  if (-1 == daemon->epoll_fd)
5268  return MHD_NO;
5269 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5270  if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
5271  {
5272  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5273  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
5274  return MHD_NO;
5275  }
5276 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5277  if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
5278  (daemon->was_quiesced) )
5279  return MHD_YES; /* non-listening daemon */
5280  event.events = EPOLLIN;
5281  event.data.ptr = daemon;
5282  if (0 != epoll_ctl (daemon->epoll_fd,
5283  EPOLL_CTL_ADD,
5284  ls,
5285  &event))
5286  {
5287 #ifdef HAVE_MESSAGES
5288  MHD_DLOG (daemon,
5289  _("Call to epoll_ctl failed: %s\n"),
5291 #endif
5292  return MHD_NO;
5293  }
5294  daemon->listen_socket_in_epoll = true;
5295  if (MHD_ITC_IS_VALID_(daemon->itc))
5296  {
5297  event.events = EPOLLIN;
5298  event.data.ptr = (void *) epoll_itc_marker;
5299  if (0 != epoll_ctl (daemon->epoll_fd,
5300  EPOLL_CTL_ADD,
5301  MHD_itc_r_fd_ (daemon->itc),
5302  &event))
5303  {
5304 #ifdef HAVE_MESSAGES
5305  MHD_DLOG (daemon,
5306  _("Call to epoll_ctl failed: %s\n"),
5308 #endif
5309  return MHD_NO;
5310  }
5311  }
5312  return MHD_YES;
5313 }
5314 #endif
5315 
5316 
5334 struct MHD_Daemon *
5335 MHD_start_daemon_va (unsigned int flags,
5336  uint16_t port,
5338  void *apc_cls,
5340  void *dh_cls,
5341  va_list ap)
5342 {
5343  const MHD_SCKT_OPT_BOOL_ on = 1;
5344  struct MHD_Daemon *daemon;
5346  struct sockaddr_in servaddr4;
5347 #if HAVE_INET6
5348  struct sockaddr_in6 servaddr6;
5349 #endif
5350  const struct sockaddr *servaddr = NULL;
5351  socklen_t addrlen;
5352  unsigned int i;
5353  enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
5354  enum MHD_FLAG *pflags;
5355 
5356  eflags = (enum MHD_FLAG) flags;
5357  pflags = &eflags;
5358 #ifndef HAVE_INET6
5359  if (0 != (*pflags & MHD_USE_IPv6))
5360  return NULL;
5361 #endif
5362 #ifndef HAVE_POLL
5363  if (0 != (*pflags & MHD_USE_POLL))
5364  return NULL;
5365 #endif
5366 #ifndef EPOLL_SUPPORT
5367  if (0 != (*pflags & MHD_USE_EPOLL))
5368  return NULL;
5369 #endif /* ! EPOLL_SUPPORT */
5370 #ifndef HTTPS_SUPPORT
5371  if (0 != (*pflags & MHD_USE_TLS))
5372  return NULL;
5373 #endif /* ! HTTPS_SUPPORT */
5374 #ifndef TCP_FASTOPEN
5375  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5376  return NULL;
5377 #endif
5378  if (0 != (*pflags & MHD_ALLOW_UPGRADE))
5379  {
5380 #ifdef UPGRADE_SUPPORT
5381  *pflags |= MHD_ALLOW_SUSPEND_RESUME;
5382 #else /* ! UPGRADE_SUPPORT */
5383  return NULL;
5384 #endif /* ! UPGRADE_SUPPORT */
5385  }
5386  if (NULL == dh)
5387  return NULL;
5388 
5389  /* Check for invalid combinations of flags. */
5390  if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5391  ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))) ||
5392  ((0 != (*pflags & MHD_USE_POLL)) &&
5394  ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)))) )
5395  return NULL;
5396 
5397  if (0 != (*pflags & MHD_USE_AUTO))
5398  {
5399  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5400  {
5401  /* Thread per connection with internal polling thread. */
5402 #ifdef HAVE_POLL
5403  *pflags |= MHD_USE_POLL;
5404 #else /* ! HAVE_POLL */
5405  /* use select() - do not modify flags */
5406 #endif /* ! HAVE_POLL */
5407  }
5408  else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5409  {
5410  /* Internal polling thread. */
5411 #if defined(EPOLL_SUPPORT)
5412  *pflags |= MHD_USE_EPOLL;
5413 #elif defined(HAVE_POLL)
5414  *pflags |= MHD_USE_POLL;
5415 #else /* !HAVE_POLL && !EPOLL_SUPPORT */
5416  /* use select() - do not modify flags */
5417 #endif /* !HAVE_POLL && !EPOLL_SUPPORT */
5418  }
5419  else
5420  {
5421  /* Internal threads are not used - "external" polling mode. */
5422 #if defined(EPOLL_SUPPORT)
5423  *pflags |= MHD_USE_EPOLL;
5424 #else /* ! EPOLL_SUPPORT */
5425  /* use select() - do not modify flags */
5426 #endif /* ! EPOLL_SUPPORT */
5427  }
5428  }
5429 
5430  if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
5431  return NULL;
5432 #ifdef EPOLL_SUPPORT
5433  daemon->epoll_fd = -1;
5434 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5435  daemon->epoll_upgrade_fd = -1;
5436 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5437 #endif
5438  /* try to open listen socket */
5439 #ifdef HTTPS_SUPPORT
5440  daemon->priority_cache = NULL;
5441  if (0 != (*pflags & MHD_USE_TLS))
5442  {
5443  gnutls_priority_init (&daemon->priority_cache,
5444  "@SYSTEM",
5445  NULL);
5446  }
5447 #endif /* HTTPS_SUPPORT */
5448  daemon->listen_fd = MHD_INVALID_SOCKET;
5449  daemon->listening_address_reuse = 0;
5450  daemon->options = *pflags;
5451  pflags = &daemon->options;
5452  daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 : 0;
5453  daemon->port = port;
5454  daemon->apc = apc;
5455  daemon->apc_cls = apc_cls;
5456  daemon->default_handler = dh;
5457  daemon->default_handler_cls = dh_cls;
5458  daemon->connections = 0;
5460  daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
5461  daemon->pool_increment = MHD_BUF_INC_SIZE;
5463  daemon->connection_timeout = 0; /* no timeout */
5464  MHD_itc_set_invalid_ (daemon->itc);
5465 #ifdef SOMAXCONN
5466  daemon->listen_backlog_size = SOMAXCONN;
5467 #else /* !SOMAXCONN */
5468  daemon->listen_backlog_size = 511; /* should be safe value */
5469 #endif /* !SOMAXCONN */
5470 #ifdef HAVE_MESSAGES
5471  daemon->custom_error_log = (MHD_LogCallback) &vfprintf;
5472  daemon->custom_error_log_cls = stderr;
5473 #endif
5474  if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
5475  (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
5476  {
5477 #ifdef HAVE_MESSAGES
5478  MHD_DLOG (daemon,
5479  _("Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5480  "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5481  "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5482 #endif
5484  }
5485  if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5486  *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
5487  else
5488  {
5489 #ifdef HAVE_LISTEN_SHUTDOWN
5490  if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
5491 #endif
5492  *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
5493  }
5494 #ifdef DAUTH_SUPPORT
5495  daemon->digest_auth_rand_size = 0;
5496  daemon->digest_auth_random = NULL;
5497  daemon->nonce_nc_size = 4; /* tiny */
5498 #endif
5499 #ifdef HTTPS_SUPPORT
5500  if (0 != (*pflags & MHD_USE_TLS))
5501  {
5502  daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5503  }
5504 #endif /* HTTPS_SUPPORT */
5505 
5506 
5507  if (MHD_YES != parse_options_va (daemon,
5508  &servaddr,
5509  ap))
5510  {
5511 #ifdef HTTPS_SUPPORT
5512  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5513  (NULL != daemon->priority_cache) )
5514  gnutls_priority_deinit (daemon->priority_cache);
5515 #endif /* HTTPS_SUPPORT */
5516  free (daemon);
5517  return NULL;
5518  }
5519  if ( (0 != (*pflags & MHD_USE_ITC)) &&
5520  (0 == daemon->worker_pool_size) )
5521  {
5522  if (! MHD_itc_init_ (daemon->itc))
5523  {
5524 #ifdef HAVE_MESSAGES
5525  MHD_DLOG (daemon,
5526  _("Failed to create inter-thread communication channel: %s\n"),
5527  MHD_itc_last_strerror_ ());
5528 #endif
5529 #ifdef HTTPS_SUPPORT
5530  if (NULL != daemon->priority_cache)
5531  gnutls_priority_deinit (daemon->priority_cache);
5532 #endif /* HTTPS_SUPPORT */
5533  free (daemon);
5534  return NULL;
5535  }
5536  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5537  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
5538  NULL)) )
5539  {
5540 #ifdef HAVE_MESSAGES
5541  MHD_DLOG (daemon,
5542  _("file descriptor for inter-thread communication channel exceeds maximum value\n"));
5543 #endif
5544  MHD_itc_destroy_chk_ (daemon->itc);
5545 #ifdef HTTPS_SUPPORT
5546  if (NULL != daemon->priority_cache)
5547  gnutls_priority_deinit (daemon->priority_cache);
5548 #endif /* HTTPS_SUPPORT */
5549  free (daemon);
5550  return NULL;
5551  }
5552  }
5553 
5554 #ifdef DAUTH_SUPPORT
5555  if (daemon->nonce_nc_size > 0)
5556  {
5557  if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc))) /
5558  sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
5559  {
5560 #ifdef HAVE_MESSAGES
5561  MHD_DLOG (daemon,
5562  _("Specified value for NC_SIZE too large\n"));
5563 #endif
5564 #ifdef HTTPS_SUPPORT
5565  if (0 != (*pflags & MHD_USE_TLS))
5566  gnutls_priority_deinit (daemon->priority_cache);
5567 #endif /* HTTPS_SUPPORT */
5568  free (daemon);
5569  return NULL;
5570  }
5571  daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
5572  if (NULL == daemon->nnc)
5573  {
5574 #ifdef HAVE_MESSAGES
5575  MHD_DLOG (daemon,
5576  _("Failed to allocate memory for nonce-nc map: %s\n"),
5577  MHD_strerror_ (errno));
5578 #endif
5579 #ifdef HTTPS_SUPPORT
5580  if (0 != (*pflags & MHD_USE_TLS))
5581  gnutls_priority_deinit (daemon->priority_cache);
5582 #endif /* HTTPS_SUPPORT */
5583  free (daemon);
5584  return NULL;
5585  }
5586  }
5587 
5588  if (! MHD_mutex_init_ (&daemon->nnc_lock))
5589  {
5590 #ifdef HAVE_MESSAGES
5591  MHD_DLOG (daemon,
5592  _("MHD failed to initialize nonce-nc mutex\n"));
5593 #endif
5594 #ifdef HTTPS_SUPPORT
5595  if (0 != (*pflags & MHD_USE_TLS))
5596  gnutls_priority_deinit (daemon->priority_cache);
5597 #endif /* HTTPS_SUPPORT */
5598  free (daemon->nnc);
5599  free (daemon);
5600  return NULL;
5601  }
5602 #endif
5603 
5604  /* Thread pooling currently works only with internal select thread model */
5605  if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5606  (daemon->worker_pool_size > 0) )
5607  {
5608 #ifdef HAVE_MESSAGES
5609  MHD_DLOG (daemon,
5610  _("MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"));
5611 #endif
5612  goto free_and_fail;
5613  }
5614 
5615 #ifdef __SYMBIAN32__
5616  if (0 != (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION)))
5617  {
5618 #ifdef HAVE_MESSAGES
5619  MHD_DLOG (daemon,
5620  _("Threaded operations are not supported on Symbian.\n"));
5621 #endif
5622  goto free_and_fail;
5623  }
5624 #endif
5625  if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
5626  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5627  {
5628  /* try to open listen socket */
5629  listen_fd = MHD_socket_create_listen_(*pflags & MHD_USE_IPv6);
5630  if (MHD_INVALID_SOCKET == listen_fd)
5631  {
5632 #ifdef HAVE_MESSAGES
5633  MHD_DLOG (daemon,
5634  _("Failed to create socket for listening: %s\n"),
5636 #endif
5637  goto free_and_fail;
5638  }
5639 
5640  /* Apply the socket options according to listening_address_reuse. */
5641  if (0 == daemon->listening_address_reuse)
5642  {
5643 #ifndef _WIN32
5644  /* No user requirement, use "traditional" default SO_REUSEADDR
5645  * on non-W32 platforms, and do not fail if it doesn't work.
5646  * Don't use it on W32, because on W32 it will allow multiple
5647  * bind to the same address:port, like SO_REUSEPORT on others. */
5648  if (0 > setsockopt (listen_fd,
5649  SOL_SOCKET,
5650  SO_REUSEADDR,
5651  (void*)&on, sizeof (on)))
5652  {
5653 #ifdef HAVE_MESSAGES
5654  MHD_DLOG (daemon,
5655  _("setsockopt failed: %s\n"),
5657 #endif
5658  }
5659 #endif /* ! _WIN32 */
5660  }
5661  else if (daemon->listening_address_reuse > 0)
5662  {
5663  /* User requested to allow reusing listening address:port. */
5664 #ifndef _WIN32
5665  /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
5666  * it doesn't work. */
5667  if (0 > setsockopt (listen_fd,
5668  SOL_SOCKET,
5669  SO_REUSEADDR,
5670  (void*)&on, sizeof (on)))
5671  {
5672 #ifdef HAVE_MESSAGES
5673  MHD_DLOG (daemon,
5674  _("setsockopt failed: %s\n"),
5676 #endif
5677  }
5678 #endif /* ! _WIN32 */
5679  /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
5680  * Fail if SO_REUSEPORT is not defined or setsockopt fails.
5681  */
5682  /* SO_REUSEADDR on W32 has the same semantics
5683  as SO_REUSEPORT on BSD/Linux */
5684 #if defined(_WIN32) || defined(SO_REUSEPORT)
5685  if (0 > setsockopt (listen_fd,
5686  SOL_SOCKET,
5687 #ifndef _WIN32
5688  SO_REUSEPORT,
5689 #else /* _WIN32 */
5690  SO_REUSEADDR,
5691 #endif /* _WIN32 */
5692  (void *) &on,
5693  sizeof (on)))
5694  {
5695 #ifdef HAVE_MESSAGES
5696  MHD_DLOG (daemon,
5697  _("setsockopt failed: %s\n"),
5699 #endif
5700  goto free_and_fail;
5701  }
5702 #else /* !_WIN32 && !SO_REUSEPORT */
5703  /* we're supposed to allow address:port re-use, but
5704  on this platform we cannot; fail hard */
5705 #ifdef HAVE_MESSAGES
5706  MHD_DLOG (daemon,
5707  _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
5708 #endif
5709  goto free_and_fail;
5710 #endif /* !_WIN32 && !SO_REUSEPORT */
5711  }
5712  else /* if (daemon->listening_address_reuse < 0) */
5713  {
5714  /* User requested to disallow reusing listening address:port.
5715  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
5716  * is used and Solaris with SO_EXCLBIND.
5717  * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
5718  * or setsockopt fails.
5719  */
5720 #if (defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)) || \
5721  (defined(__sun) && defined(SO_EXCLBIND))
5722  if (0 > setsockopt (listen_fd,
5723  SOL_SOCKET,
5724 #ifdef SO_EXCLUSIVEADDRUSE
5725  SO_EXCLUSIVEADDRUSE,
5726 #else /* SO_EXCLBIND */
5727  SO_EXCLBIND,
5728 #endif /* SO_EXCLBIND */
5729  (void *) &on,
5730  sizeof (on)))
5731  {
5732 #ifdef HAVE_MESSAGES
5733  MHD_DLOG (daemon,
5734  _("setsockopt failed: %s\n"),
5736 #endif
5737  goto free_and_fail;
5738  }
5739 #elif defined(_WIN32) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
5740 #ifdef HAVE_MESSAGES
5741  MHD_DLOG (daemon,
5742  _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
5743 #endif
5744  goto free_and_fail;
5745 #endif /* _WIN32 */
5746  }
5747 
5748  /* check for user supplied sockaddr */
5749 #if HAVE_INET6
5750  if (0 != (*pflags & MHD_USE_IPv6))
5751  addrlen = sizeof (struct sockaddr_in6);
5752  else
5753 #endif
5754  addrlen = sizeof (struct sockaddr_in);
5755  if (NULL == servaddr)
5756  {
5757 #if HAVE_INET6
5758  if (0 != (*pflags & MHD_USE_IPv6))
5759  {
5760  memset (&servaddr6,
5761  0,
5762  sizeof (struct sockaddr_in6));
5763  servaddr6.sin6_family = AF_INET6;
5764  servaddr6.sin6_port = htons (port);
5765 #if HAVE_SOCKADDR_IN_SIN_LEN
5766  servaddr6.sin6_len = sizeof (struct sockaddr_in6);
5767 #endif
5768  servaddr = (struct sockaddr *) &servaddr6;
5769  }
5770  else
5771 #endif
5772  {
5773  memset (&servaddr4,
5774  0,
5775  sizeof (struct sockaddr_in));
5776  servaddr4.sin_family = AF_INET;
5777  servaddr4.sin_port = htons (port);
5778 #if HAVE_SOCKADDR_IN_SIN_LEN
5779  servaddr4.sin_len = sizeof (struct sockaddr_in);
5780 #endif
5781  servaddr = (struct sockaddr *) &servaddr4;
5782  }
5783  }
5784  daemon->listen_fd = listen_fd;
5785 
5786  if (0 != (*pflags & MHD_USE_IPv6))
5787  {
5788 #ifdef IPPROTO_IPV6
5789 #ifdef IPV6_V6ONLY
5790  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
5791  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
5792  and may also be missing on older POSIX systems; good luck if you have any of those,
5793  your IPv6 socket may then also bind against IPv4 anyway... */
5794  const MHD_SCKT_OPT_BOOL_ v6_only =
5795  (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
5796  if (0 > setsockopt (listen_fd,
5797  IPPROTO_IPV6, IPV6_V6ONLY,
5798  (const void *) &v6_only,
5799  sizeof (v6_only)))
5800  {
5801 #ifdef HAVE_MESSAGES
5802  MHD_DLOG (daemon,
5803  _("setsockopt failed: %s\n"),
5805 #endif
5806  }
5807 #endif
5808 #endif
5809  }
5810  if (-1 == bind (listen_fd, servaddr, addrlen))
5811  {
5812 #ifdef HAVE_MESSAGES
5813  MHD_DLOG (daemon,
5814  _("Failed to bind to port %u: %s\n"),
5815  (unsigned int) port,
5817 #endif
5818  MHD_socket_close_chk_ (listen_fd);
5819  goto free_and_fail;
5820  }
5821 #ifdef TCP_FASTOPEN
5822  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5823  {
5824  if (0 == daemon->fastopen_queue_size)
5825  daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
5826  if (0 != setsockopt (listen_fd,
5827  IPPROTO_TCP,
5828  TCP_FASTOPEN,
5829  &daemon->fastopen_queue_size,
5830  sizeof (daemon->fastopen_queue_size)))
5831  {
5832 #ifdef HAVE_MESSAGES
5833  MHD_DLOG (daemon,
5834  _("setsockopt failed: %s\n"),
5836 #endif
5837  }
5838  }
5839 #endif
5840  if (listen (listen_fd,
5841  daemon->listen_backlog_size) < 0)
5842  {
5843 #ifdef HAVE_MESSAGES
5844  MHD_DLOG (daemon,
5845  _("Failed to listen for connections: %s\n"),
5847 #endif
5848  MHD_socket_close_chk_ (listen_fd);
5849  goto free_and_fail;
5850  }
5851  }
5852  else
5853  {
5854  listen_fd = daemon->listen_fd;
5855  }
5856 
5857  if ( (MHD_INVALID_SOCKET != listen_fd) &&
5858  (! MHD_socket_nonblocking_ (listen_fd)) )
5859  {
5860 #ifdef HAVE_MESSAGES
5861  MHD_DLOG (daemon,
5862  _("Failed to set nonblocking mode on listening socket: %s\n"),
5864 #endif
5865  if (0 != (*pflags & MHD_USE_EPOLL) ||
5866  daemon->worker_pool_size > 0)
5867  {
5868  /* Accept must be non-blocking. Multiple children may wake up
5869  * to handle a new connection, but only one will win the race.
5870  * The others must immediately return. */
5871  MHD_socket_close_chk_ (listen_fd);
5872  goto free_and_fail;
5873  }
5874  }
5875  if ( (MHD_INVALID_SOCKET != listen_fd) &&
5876  (! MHD_SCKT_FD_FITS_FDSET_(listen_fd,
5877  NULL)) &&
5878  (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
5879  {
5880 #ifdef HAVE_MESSAGES
5881  MHD_DLOG (daemon,
5882  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
5883  listen_fd,
5884  FD_SETSIZE);
5885 #endif
5886  MHD_socket_close_chk_ (listen_fd);
5887  goto free_and_fail;
5888  }
5889 
5890 #ifdef EPOLL_SUPPORT
5891  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
5892  (0 == daemon->worker_pool_size) &&
5893  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5894  {
5895  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5896  {
5897 #ifdef HAVE_MESSAGES
5898  MHD_DLOG (daemon,
5899  _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
5900 #endif
5901  goto free_and_fail;
5902  }
5903  if (MHD_YES != setup_epoll_to_listen (daemon))
5904  goto free_and_fail;
5905  }
5906 #endif /* EPOLL_SUPPORT */
5907 
5908  if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
5909  {
5910 #ifdef HAVE_MESSAGES
5911  MHD_DLOG (daemon,
5912  _("MHD failed to initialize IP connection limit mutex\n"));
5913 #endif
5914  if (MHD_INVALID_SOCKET != listen_fd)
5915  MHD_socket_close_chk_ (listen_fd);
5916  goto free_and_fail;
5917  }
5918  if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
5919  {
5920 #ifdef HAVE_MESSAGES
5921  MHD_DLOG (daemon,
5922  _("MHD failed to initialize IP connection limit mutex\n"));
5923 #endif
5925  if (MHD_INVALID_SOCKET != listen_fd)
5926  MHD_socket_close_chk_ (listen_fd);
5927  goto free_and_fail;
5928  }
5929 
5930 #ifdef HTTPS_SUPPORT
5931  /* initialize HTTPS daemon certificate aspects & send / recv functions */
5932  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5933  (0 != MHD_TLS_init (daemon)) )
5934  {
5935 #ifdef HAVE_MESSAGES
5936  MHD_DLOG (daemon,
5937  _("Failed to initialize TLS support\n"));
5938 #endif
5939  if (MHD_INVALID_SOCKET != listen_fd)
5940  MHD_socket_close_chk_ (listen_fd);
5943  goto free_and_fail;
5944  }
5945 #endif /* HTTPS_SUPPORT */
5946  if ( ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5947  (0 == daemon->worker_pool_size) ) &&
5948  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
5949  (! MHD_create_named_thread_ (&daemon->pid,
5950  (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
5951  "MHD-listen" : "MHD-single",
5952  daemon->thread_stack_size,
5954  daemon) ) )
5955  {
5956 #ifdef HAVE_MESSAGES
5957  MHD_DLOG (daemon,
5958  _("Failed to create listen thread: %s\n"),
5959  MHD_strerror_ (errno));
5960 #endif
5963  if (MHD_INVALID_SOCKET != listen_fd)
5964  MHD_socket_close_chk_ (listen_fd);
5965  goto free_and_fail;
5966  }
5967  if ( (daemon->worker_pool_size > 0) &&
5968  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5969  {
5970  /* Coarse-grained count of connections per thread (note error
5971  * due to integer division). Also keep track of how many
5972  * connections are leftover after an equal split. */
5973  unsigned int conns_per_thread = daemon->connection_limit
5974  / daemon->worker_pool_size;
5975  unsigned int leftover_conns = daemon->connection_limit
5976  % daemon->worker_pool_size;
5977 
5978  i = 0; /* we need this in case fcntl or malloc fails */
5979 
5980  /* Allocate memory for pooled objects */
5981  daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
5982  * daemon->worker_pool_size);
5983  if (NULL == daemon->worker_pool)
5984  goto thread_failed;
5985 
5986  /* Start the workers in the pool */
5987  for (i = 0; i < daemon->worker_pool_size; ++i)
5988  {
5989  /* Create copy of the Daemon object for each worker */
5990  struct MHD_Daemon *d = &daemon->worker_pool[i];
5991 
5992  memcpy (d, daemon, sizeof (struct MHD_Daemon));
5993  /* Adjust pooling params for worker daemons; note that memcpy()
5994  has already copied MHD_USE_INTERNAL_POLLING_THREAD thread model into
5995  the worker threads. */
5996  d->master = daemon;
5997  d->worker_pool_size = 0;
5998  d->worker_pool = NULL;
5999 
6000  if (0 != (*pflags & MHD_USE_ITC))
6001  {
6002  if (! MHD_itc_init_ (d->itc))
6003  {
6004 #ifdef HAVE_MESSAGES
6005  MHD_DLOG (daemon,
6006  _("Failed to create worker inter-thread communication channel: %s\n"),
6007  MHD_itc_last_strerror_() );
6008 #endif
6009  goto thread_failed;
6010  }
6011  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6012  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
6013  NULL)) )
6014  {
6015 #ifdef HAVE_MESSAGES
6016  MHD_DLOG (daemon,
6017  _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
6018 #endif
6020  goto thread_failed;
6021  }
6022  }
6023  else
6024  MHD_itc_set_invalid_ (d->itc);
6025 
6026  /* Divide available connections evenly amongst the threads.
6027  * Thread indexes in [0, leftover_conns) each get one of the
6028  * leftover connections. */
6029  d->connection_limit = conns_per_thread;
6030  if (i < leftover_conns)
6031  ++d->connection_limit;
6032 #ifdef EPOLL_SUPPORT
6033  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6034  (MHD_YES != setup_epoll_to_listen (d)) )
6035  goto thread_failed;
6036 #endif
6037  /* Must init cleanup connection mutex for each worker */
6038  if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
6039  {
6040 #ifdef HAVE_MESSAGES
6041  MHD_DLOG (daemon,
6042  _("MHD failed to initialize cleanup connection mutex\n"));
6043 #endif
6044  goto thread_failed;
6045  }
6046 
6047  /* Spawn the worker thread */
6048  if (! MHD_create_named_thread_ (&d->pid,
6049  "MHD-worker",
6050  daemon->thread_stack_size,
6052  d))
6053  {
6054 #ifdef HAVE_MESSAGES
6055  MHD_DLOG (daemon,
6056  _("Failed to create pool thread: %s\n"),
6057  MHD_strerror_ (errno));
6058 #endif
6059  /* Free memory for this worker; cleanup below handles
6060  * all previously-created workers. */
6062  goto thread_failed;
6063  }
6064  }
6065  }
6066 #ifdef HTTPS_SUPPORT
6067  /* API promises to never use the password after initialization,
6068  so we additionally NULL it here to not deref a dangling pointer. */
6069  daemon->https_key_password = NULL;
6070 #endif /* HTTPS_SUPPORT */
6071 
6072  return daemon;
6073 
6074 thread_failed:
6075  /* If no worker threads created, then shut down normally. Calling
6076  MHD_stop_daemon (as we do below) doesn't work here since it
6077  assumes a 0-sized thread pool means we had been in the default
6078  MHD_USE_INTERNAL_POLLING_THREAD mode. */
6079  if (0 == i)
6080  {
6081  if (MHD_INVALID_SOCKET != listen_fd)
6082  MHD_socket_close_chk_ (listen_fd);
6085  if (NULL != daemon->worker_pool)
6086  free (daemon->worker_pool);
6087  goto free_and_fail;
6088  }
6089 
6090  /* Shutdown worker threads we've already created. Pretend
6091  as though we had fully initialized our daemon, but
6092  with a smaller number of threads than had been
6093  requested. */
6094  daemon->worker_pool_size = i;
6095  MHD_stop_daemon (daemon);
6096  return NULL;
6097 
6098  free_and_fail:
6099  /* clean up basic memory state in 'daemon' and return NULL to
6100  indicate failure */
6101 #ifdef EPOLL_SUPPORT
6102 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6103  if (daemon->upgrade_fd_in_epoll)
6104  {
6105  if (0 != epoll_ctl (daemon->epoll_fd,
6106  EPOLL_CTL_DEL,
6107  daemon->epoll_upgrade_fd,
6108  NULL))
6109  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
6110  daemon->upgrade_fd_in_epoll = false;
6111  }
6112 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6113  if (-1 != daemon->epoll_fd)
6114  close (daemon->epoll_fd);
6115 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6116  if (-1 != daemon->epoll_upgrade_fd)
6117  close (daemon->epoll_upgrade_fd);
6118 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6119 #endif /* EPOLL_SUPPORT */
6120 #ifdef DAUTH_SUPPORT
6121  free (daemon->nnc);
6122  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6123 #endif
6124 #ifdef HTTPS_SUPPORT
6125  if (0 != (*pflags & MHD_USE_TLS))
6126  gnutls_priority_deinit (daemon->priority_cache);
6127 #endif /* HTTPS_SUPPORT */
6128  if (MHD_ITC_IS_VALID_(daemon->itc))
6129  MHD_itc_destroy_chk_ (daemon->itc);
6130  free (daemon);
6131  return NULL;
6132 }
6133 
6134 
6143 static void
6145 {
6146  struct MHD_Connection *pos;
6147  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
6148 #ifdef UPGRADE_SUPPORT
6149  const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
6150 #endif /* UPGRADE_SUPPORT */
6151 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6152  struct MHD_UpgradeResponseHandle *urh;
6153  struct MHD_UpgradeResponseHandle *urhn;
6154  const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
6155 
6156  /* give upgraded HTTPS connections a chance to finish */
6157  /* 'daemon->urh_head' is not used in thread-per-connection mode. */
6158  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
6159  {
6160  urhn = urh->prev;
6161  /* call generic forwarding function for passing data
6162  with chance to detect that application is done. */
6163  process_urh (urh);
6164  MHD_connection_finish_forward_ (urh->connection);
6165  urh->clean_ready = true;
6166  /* Resuming will move connection to cleanup list. */
6167  MHD_resume_connection(urh->connection);
6168  }
6169 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6170 
6171  /* Give suspended connections a chance to resume to avoid
6172  running into the check for there not being any suspended
6173  connections left in case of a tight race with a recently
6174  resumed connection. */
6175  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6176  {
6177  daemon->resuming = true; /* Force check for pending resume. */
6179  }
6180  /* first, make sure all threads are aware of shutdown; need to
6181  traverse DLLs in peace... */
6183 #ifdef UPGRADE_SUPPORT
6184  if (upg_allowed)
6185  {
6186  struct MHD_Connection * susp;
6187 
6188  susp = daemon->suspended_connections_tail;
6189  while (NULL != susp)
6190  {
6191  if (NULL == susp->urh) /* "Upgraded" connection? */
6192  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6193 #ifdef HTTPS_SUPPORT
6194  else if (used_tls &&
6195  used_thr_p_c &&
6196  (! susp->urh->clean_ready) )
6197  shutdown (susp->urh->app.socket,
6198  SHUT_RDWR); /* Wake thread by shutdown of app socket. */
6199 #endif /* HTTPS_SUPPORT */
6200  else
6201  {
6202 #ifdef HAVE_MESSAGES
6203  if (! susp->urh->was_closed)
6204  MHD_DLOG (daemon,
6205  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6206 #endif
6207  susp->urh->was_closed = true;
6208  /* If thread-per-connection is used, connection's thread
6209  * may still processing "upgrade" (exiting). */
6210  if (! used_thr_p_c)
6212  /* Do not use MHD_resume_connection() as mutex is
6213  * already locked. */
6214  susp->resuming = true;
6215  daemon->resuming = true;
6216  }
6217  susp = susp->prev;
6218  }
6219  }
6220  else /* This 'else' is combined with next 'if' */
6221 #endif /* UPGRADE_SUPPORT */
6222  if (NULL != daemon->suspended_connections_head)
6223  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6224  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
6225  {
6226  shutdown (pos->socket_fd,
6227  SHUT_RDWR);
6228 #if MHD_WINSOCK_SOCKETS
6229  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6230  (MHD_ITC_IS_VALID_(daemon->itc)) &&
6231  (! MHD_itc_activate_ (daemon->itc, "e")) )
6232  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6233 #endif
6234  }
6235 
6236  /* now, collect per-connection threads */
6237  if (used_thr_p_c)
6238  {
6239  pos = daemon->connections_tail;
6240  while (NULL != pos)
6241  {
6242  if (! pos->thread_joined)
6243  {
6245  if (! MHD_join_thread_ (pos->pid))
6246  MHD_PANIC (_("Failed to join a thread\n"));
6248  pos->thread_joined = true;
6249  /* The thread may have concurrently modified the DLL,
6250  need to restart from the beginning */
6251  pos = daemon->connections_tail;
6252  continue;
6253  }
6254  pos = pos->prev;
6255  }
6256  }
6258 
6259 #ifdef UPGRADE_SUPPORT
6260  /* Finished threads with "upgraded" connections need to be moved
6261  * to cleanup list by resume_suspended_connections(). */
6262  /* "Upgraded" connections that were not closed explicitly by
6263  * application should be moved to cleanup list too. */
6264  if (upg_allowed)
6265  {
6266  daemon->resuming = true; /* Force check for pending resume. */
6268  }
6269 #endif /* UPGRADE_SUPPORT */
6270 
6271  /* now that we're alone, move everyone to cleanup */
6272  while (NULL != (pos = daemon->connections_tail))
6273  {
6274  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6275  (! pos->thread_joined) )
6276  MHD_PANIC (_("Failed to join a thread\n"));
6277  close_connection (pos);
6278  }
6279  MHD_cleanup_connections (daemon);
6280 }
6281 
6282 
6289 void
6290 MHD_stop_daemon (struct MHD_Daemon *daemon)
6291 {
6292  MHD_socket fd;
6293  unsigned int i;
6294 
6295  if (NULL == daemon)
6296  return;
6297 
6298  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6300 
6301  daemon->shutdown = true;
6302  fd = daemon->listen_fd;
6303 
6304  if (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6305  {
6306  /* Separate thread(s) is used for select()/poll()/etc. */
6307  if (NULL != daemon->worker_pool)
6308  {
6309  /* Pool of workers is used. */
6310  /* Initiate shutdown process in wokers. */
6311  for (i = 0; i < daemon->worker_pool_size; ++i)
6312  {
6313  daemon->worker_pool[i].shutdown = true;
6314  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
6315  {
6316  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
6317  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
6318  }
6319 #ifdef HAVE_LISTEN_SHUTDOWN
6320  else if (MHD_INVALID_SOCKET != fd)
6321  {
6322  /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
6323  /* No problem if shutdown will be called several times for the same socket. */
6324  (void) shutdown (fd,
6325  SHUT_RDWR);
6326  }
6327 #endif
6328  }
6329  /* Start harvesting. */
6330  for (i = 0; i < daemon->worker_pool_size; ++i)
6331  {
6332  if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
6333  MHD_PANIC (_("Failed to join a thread\n"));
6334 #ifdef EPOLL_SUPPORT
6335  if (-1 != daemon->worker_pool[i].epoll_fd)
6336  MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
6337 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6338  if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
6339  MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
6340 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6341 #endif
6342  if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc) )
6343  MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
6345  }
6346  free (daemon->worker_pool);
6347  }
6348  else
6349  {
6350  /* Single internal thread is used for select()/poll()/etc. */
6351  if (MHD_ITC_IS_VALID_(daemon->itc))
6352  {
6353  if (! MHD_itc_activate_ (daemon->itc, "e"))
6354  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6355  }
6356 #ifdef HAVE_LISTEN_SHUTDOWN
6357  else
6358  {
6359  /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
6360  if ( (MHD_INVALID_SOCKET != fd) &&
6361  (! daemon->was_quiesced) )
6362  (void) shutdown (fd,
6363  SHUT_RDWR);
6364  }
6365 #endif
6366  if (! MHD_join_thread_ (daemon->pid))
6367  {
6368  MHD_PANIC (_("Failed to join a thread\n"));
6369  }
6370  }
6371  }
6372  else
6373  {
6374  /* Internal threads are not used for select()/poll()/etc. */
6375  close_all_connections (daemon);
6376  }
6377 
6378  if ( (MHD_INVALID_SOCKET != fd) &&
6379  (! daemon->was_quiesced) )
6380  MHD_socket_close_chk_ (fd);
6381 
6382  if (MHD_ITC_IS_VALID_ (daemon->itc))
6383  MHD_itc_destroy_chk_ (daemon->itc);
6384 
6385 #ifdef EPOLL_SUPPORT
6386  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6387  (-1 != daemon->epoll_fd) )
6388  MHD_socket_close_chk_ (daemon->epoll_fd);
6389 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6390  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6391  (-1 != daemon->epoll_upgrade_fd) )
6392  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
6393 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6394 #endif
6395 
6396  /* TLS clean up */
6397 #ifdef HTTPS_SUPPORT
6398  if (daemon->have_dhparams)
6399  {
6400  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6401  daemon->have_dhparams = false;
6402  }
6403  if (0 != (daemon->options & MHD_USE_TLS))
6404  {
6405  gnutls_priority_deinit (daemon->priority_cache);
6406  if (daemon->x509_cred)
6407  gnutls_certificate_free_credentials (daemon->x509_cred);
6408  }
6409 #endif /* HTTPS_SUPPORT */
6410 
6411 #ifdef DAUTH_SUPPORT
6412  free (daemon->nnc);
6413  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6414 #endif
6417 
6418  free (daemon);
6419 }
6420 
6421 
6433 const union MHD_DaemonInfo *
6435  enum MHD_DaemonInfoType info_type,
6436  ...)
6437 {
6438  if (NULL == daemon)
6439  return NULL;
6440  switch (info_type)
6441  {
6443  return NULL; /* no longer supported */
6445  return NULL; /* no longer supported */
6447  return (const union MHD_DaemonInfo *) &daemon->listen_fd;
6448 #ifdef EPOLL_SUPPORT
6450  return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
6451 #endif
6453  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6454  {
6455  /* Assume that MHD_run() in not called in other thread
6456  * at the same time. */
6457  MHD_cleanup_connections (daemon);
6458  }
6459  else if (daemon->worker_pool)
6460  {
6461  unsigned int i;
6462  /* Collect the connection information stored in the workers. */
6463  daemon->connections = 0;
6464  for (i = 0; i < daemon->worker_pool_size; i++)
6465  {
6466  /* FIXME: next line is thread-safe only if read is atomic. */
6467  daemon->connections += daemon->worker_pool[i].connections;
6468  }
6469  }
6470  return (const union MHD_DaemonInfo *) &daemon->connections;
6471  case MHD_DAEMON_INFO_FLAGS:
6472  return (const union MHD_DaemonInfo *) &daemon->options;
6473  default:
6474  return NULL;
6475  };
6476 }
6477 
6478 
6495 void
6497  void *cls)
6498 {
6499  mhd_panic = cb;
6500  mhd_panic_cls = cls;
6501 }
6502 
6503 
6510 const char *
6512 {
6513 #ifdef PACKAGE_VERSION
6514  return PACKAGE_VERSION;
6515 #else /* !PACKAGE_VERSION */
6516  static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
6517  if (0 == ver[0])
6518  {
6519  int res = MHD_snprintf_(ver,
6520  sizeof(ver),
6521  "%x.%x.%x",
6522  (((int)MHD_VERSION >> 24) & 0xFF),
6523  (((int)MHD_VERSION >> 16) & 0xFF),
6524  (((int)MHD_VERSION >> 8) & 0xFF));
6525  if (0 >= res || sizeof(ver) <= res)
6526  return "0.0.0"; /* Can't return real version*/
6527  }
6528  return ver;
6529 #endif /* !PACKAGE_VERSION */
6530 }
6531 
6532 
6544 _MHD_EXTERN int
6545 MHD_is_feature_supported(enum MHD_FEATURE feature)
6546 {
6547  switch(feature)
6548  {
6549  case MHD_FEATURE_MESSAGES:
6550 #ifdef HAVE_MESSAGES
6551  return MHD_YES;
6552 #else
6553  return MHD_NO;
6554 #endif
6555  case MHD_FEATURE_TLS:
6556 #ifdef HTTPS_SUPPORT
6557  return MHD_YES;
6558 #else /* ! HTTPS_SUPPORT */
6559  return MHD_NO;
6560 #endif /* ! HTTPS_SUPPORT */
6561  case MHD_FEATURE_HTTPS_CERT_CALLBACK:
6562 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
6563  return MHD_YES;
6564 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6565  return MHD_NO;
6566 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6567  case MHD_FEATURE_IPv6:
6568 #ifdef HAVE_INET6
6569  return MHD_YES;
6570 #else
6571  return MHD_NO;
6572 #endif
6573  case MHD_FEATURE_IPv6_ONLY:
6574 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
6575  return MHD_YES;
6576 #else
6577  return MHD_NO;
6578 #endif
6579  case MHD_FEATURE_POLL:
6580 #ifdef HAVE_POLL
6581  return MHD_YES;
6582 #else
6583  return MHD_NO;
6584 #endif
6585  case MHD_FEATURE_EPOLL:
6586 #ifdef EPOLL_SUPPORT
6587  return MHD_YES;
6588 #else
6589  return MHD_NO;
6590 #endif
6591  case MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET:
6592 #ifdef HAVE_LISTEN_SHUTDOWN
6593  return MHD_YES;
6594 #else
6595  return MHD_NO;
6596 #endif
6597  case MHD_FEATURE_SOCKETPAIR:
6598 #ifdef _MHD_ITC_SOCKETPAIR
6599  return MHD_YES;
6600 #else
6601  return MHD_NO;
6602 #endif
6603  case MHD_FEATURE_TCP_FASTOPEN:
6604 #ifdef TCP_FASTOPEN
6605  return MHD_YES;
6606 #else
6607  return MHD_NO;
6608 #endif
6609  case MHD_FEATURE_BASIC_AUTH:
6610 #ifdef BAUTH_SUPPORT
6611  return MHD_YES;
6612 #else
6613  return MHD_NO;
6614 #endif
6615  case MHD_FEATURE_DIGEST_AUTH:
6616 #ifdef DAUTH_SUPPORT
6617  return MHD_YES;
6618 #else
6619  return MHD_NO;
6620 #endif
6621  case MHD_FEATURE_POSTPROCESSOR:
6622 #ifdef HAVE_POSTPROCESSOR
6623  return MHD_YES;
6624 #else
6625  return MHD_NO;
6626 #endif
6627  case MHD_FEATURE_HTTPS_KEY_PASSWORD:
6628 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
6629  return MHD_YES;
6630 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6631  return MHD_NO;
6632 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6633  case MHD_FEATURE_LARGE_FILE:
6634 #if defined(HAVE_PREAD64) || defined(_WIN32)
6635  return MHD_YES;
6636 #elif defined(HAVE_PREAD)
6637  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6638 #elif defined(HAVE_LSEEK64)
6639  return MHD_YES;
6640 #else
6641  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6642 #endif
6643  case MHD_FEATURE_THREAD_NAMES:
6644 #if defined(MHD_USE_THREAD_NAME_)
6645  return MHD_YES;
6646 #else
6647  return MHD_NO;
6648 #endif
6649  case MHD_FEATURE_UPGRADE:
6650 #if defined(UPGRADE_SUPPORT)
6651  return MHD_YES;
6652 #else
6653  return MHD_NO;
6654 #endif
6655  case MHD_FEATURE_RESPONSES_SHARED_FD:
6656 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
6657  return MHD_YES;
6658 #else
6659  return MHD_NO;
6660 #endif
6661  }
6662  return MHD_NO;
6663 }
6664 
6665 
6666 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
6667 #if defined(MHD_USE_POSIX_THREADS)
6668 GCRY_THREAD_OPTION_PTHREAD_IMPL;
6669 #elif defined(MHD_W32_MUTEX_)
6670 
6671 static int
6672 gcry_w32_mutex_init (void **ppmtx)
6673 {
6674  *ppmtx = malloc (sizeof (MHD_mutex_));
6675 
6676  if (NULL == *ppmtx)
6677  return ENOMEM;
6678  if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
6679  {
6680  free (*ppmtx);
6681  *ppmtx = NULL;
6682  return EPERM;
6683  }
6684 
6685  return 0;
6686 }
6687 
6688 
6689 static int
6690 gcry_w32_mutex_destroy (void **ppmtx)
6691 {
6692  int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
6693  free (*ppmtx);
6694  return res;
6695 }
6696 
6697 
6698 static int
6699 gcry_w32_mutex_lock (void **ppmtx)
6700 {
6701  return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6702 }
6703 
6704 
6705 static int
6706 gcry_w32_mutex_unlock (void **ppmtx)
6707 {
6708  return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6709 }
6710 
6711 
6712 static struct gcry_thread_cbs gcry_threads_w32 = {
6713  (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
6714  NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
6715  gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
6716  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
6717 
6718 #endif /* defined(MHD_W32_MUTEX_) */
6719 #endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
6720 
6721 
6725 void
6727 {
6728 #ifdef _WIN32
6729  WSADATA wsd;
6730 #endif /* _WIN32 */
6732  mhd_panic_cls = NULL;
6733 
6734 #ifdef _WIN32
6735  if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
6736  MHD_PANIC (_("Failed to initialize winsock\n"));
6737  mhd_winsock_inited_ = 1;
6738  if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
6739  MHD_PANIC (_("Winsock version 2.2 is not available\n"));
6740 #endif
6741 #ifdef HTTPS_SUPPORT
6742 #if GCRYPT_VERSION_NUMBER < 0x010600
6743 #if defined(MHD_USE_POSIX_THREADS)
6744  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6745  &gcry_threads_pthread))
6746  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
6747 #elif defined(MHD_W32_MUTEX_)
6748  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6749  &gcry_threads_w32))
6750  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
6751 #endif /* defined(MHD_W32_MUTEX_) */
6752  gcry_check_version (NULL);
6753 #else
6754  if (NULL == gcry_check_version ("1.6.0"))
6755  MHD_PANIC (_("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
6756 #endif
6757  gnutls_global_init ();
6758 #endif /* HTTPS_SUPPORT */
6760 }
6761 
6762 
6763 void
6765 {
6766 #ifdef HTTPS_SUPPORT
6767  gnutls_global_deinit ();
6768 #endif /* HTTPS_SUPPORT */
6769 #ifdef _WIN32
6770  if (mhd_winsock_inited_)
6771  WSACleanup();
6772 #endif
6774 }
6775 
6777 
6778 /* end of daemon.c */
bool thread_joined
Definition: internal.h:835
unsigned int per_ip_connection_limit
Definition: internal.h:1537
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
void * unescape_callback_cls
Definition: internal.h:1365
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
uint64_t total_size
Definition: internal.h:340
_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:5335
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:448
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add, bool non_blck)
Definition: daemon.c:2348
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:4741
uint64_t fd_off
Definition: internal.h:351
#define DLL_insert(head, tail, element)
Definition: internal.h:1690
bool data_already_pending
Definition: internal.h:1515
socklen_t addr_len
Definition: internal.h:786
void * socket_context
Definition: internal.h:659
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1193
enum MHD_CONNECTION_STATE state
Definition: internal.h:859
uint64_t response_write_position
Definition: internal.h:767
#define NULL
Definition: reason_phrase.c:31
static int call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
Definition: daemon.c:1134
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_select_thread(void *cls)
Definition: daemon.c:4534
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:142
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:864
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:4713
time_t connection_timeout
Definition: internal.h:1531
Methods for managing connections.
int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3238
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:541
#define MHD_YES
Definition: microhttpd.h:134
#define MHD_socket_set_error_(err)
Definition: mhd_sockets.h:574
_MHD_EXTERN int MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:2964
struct MHD_Response * response
Definition: internal.h:632
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:438
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1293
Header for platform missing functions.
volatile bool was_quiesced
Definition: internal.h:1490
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:503
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:927
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:68
#define EXTRA_CHECK(a)
Definition: internal.h:1678
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:130
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1211
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: daemon.c:2190
int MHD_socket
Definition: microhttpd.h:181
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:220
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2731
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:4572
_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:4597
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:109
#define EDLL_insert(head, tail, element)
Definition: internal.h:1779
intptr_t value
Definition: microhttpd.h:1509
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:4766
platform-specific includes for libmicrohttpd
#define MHD_strerror_(errnum)
Definition: mhd_compat.h:44
#define MHD_itc_destroy_chk_(itc)
Definition: mhd_itc.h:345
static int internal_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
Definition: daemon.c:3327
Methods for managing response objects.
void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: daemon.c:6496
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2424
void MHD_fini(void)
Definition: daemon.c:6764
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1355
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:172
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:1859
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
Definition: microhttpd.h:1158
#define OFF_T_MAX
Definition: mhd_limits.h:88
struct MHD_Daemon * daemon
Definition: internal.h:617
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:911
int listening_address_reuse
Definition: internal.h:1445
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1423
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1301
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1336
struct MHD_Connection * cleanup_head
Definition: internal.h:1241
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:633
#define XDLL_remove(head, tail, element)
Definition: internal.h:1756
void MHD_init(void)
Definition: daemon.c:6726
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
bool client_aware
Definition: internal.h:810
#define XDLL_insert(head, tail, element)
Definition: internal.h:1735
int strict_for_client
Definition: internal.h:1552
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:398
MHD_socket MHD_socket_create_listen_(int use_ipv6)
Definition: mhd_sockets.c:471
struct MHD_Connection * cleanup_tail
Definition: internal.h:1246
Header for platform-independent inter-thread communication.
struct MHD_Connection * prev
Definition: internal.h:598
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:248
#define MHD_VERSION
Definition: microhttpd.h:129
size_t write_buffer_send_offset
Definition: internal.h:742
struct MHD_Daemon * worker_pool
Definition: internal.h:1388
void * mhd_panic_cls
Definition: daemon.c:154
size_t read_buffer_size
Definition: internal.h:726
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:156
void * client_context
Definition: internal.h:650
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:6290
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1308
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
Definition: daemon.c:267
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:817
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3496
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:76
void MHD_set_https_callbacks(struct MHD_Connection *connection)
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:132
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: mhd_sockets.c:374
MHD_thread_handle_ pid
Definition: internal.h:718
unsigned int connection_limit
Definition: internal.h:1525
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
unsigned int worker_pool_size
Definition: internal.h:1413
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
enum MHD_FLAG options
Definition: internal.h:1542
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:3446
LogCallback uri_log_callback
Definition: internal.h:1350
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:323
void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1020
time_t connection_timeout
Definition: internal.h:798
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
Definition: daemon.c:1774
#define _MHD_EXTERN
Definition: mhd_options.h:51
static int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:318
Methods for managing connections.
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
uint16_t port
Definition: internal.h:1547
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:899
unsigned int connections
Definition: internal.h:1520
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1286
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:95
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:384
_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini)
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:439
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:63
ReceiveCallback recv_cls
Definition: internal.h:916
size_t thread_stack_size
Definition: internal.h:1408
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:162
limits values definitions
Header for platform-independent threads abstraction.
void MHD_monotonic_sec_counter_init(void)
#define MHD_SCKT_ENOTCONN_
Definition: mhd_sockets.h:413
internal shared structures
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
UnescapeCallback unescape_callback
Definition: internal.h:1360
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:603
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:905
unsigned int listen_backlog_size
Definition: internal.h:1671
#define MHD_fd_close_chk_(fd)
Definition: internal.h:76
#define TIME_T_MAX
Definition: mhd_limits.h:98
struct MHD_Connection * connections_head
Definition: internal.h:1221
struct MHD_Daemon * master
Definition: internal.h:1383
size_t pool_size
Definition: internal.h:1398
struct MHD_Connection * next
Definition: internal.h:593
#define ULLONG_MAX
Definition: mhd_limits.h:52
struct MHD_itc_ itc
Definition: internal.h:1478
MHD_AcceptPolicyCallback apc
Definition: internal.h:1314
time_t last_activity
Definition: internal.h:792
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1179
static int resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2831
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:525
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:1918
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3951
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3140
bool sk_nonblck
Definition: internal.h:822
struct MemoryPool * pool
Definition: internal.h:642
const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:6434
static int MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3014
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:678
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:232
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:120
void * ptr_value
Definition: microhttpd.h:1515
#define MHD_PANIC(msg)
Definition: internal.h:63
time_t MHD_monotonic_sec_counter(void)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Definition: microhttpd.h:1941
size_t write_buffer_append_offset
Definition: internal.h:748
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:645
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1325
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
struct MHD_Connection * prevX
Definition: internal.h:612
bool resuming
Definition: internal.h:1504
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:4493
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3353
MHD_thread_handle_ pid
Definition: internal.h:1418
#define DLL_remove(head, tail, element)
Definition: internal.h:1711
void * notify_completed_cls
Definition: internal.h:1330
MHD_socket listen_fd
Definition: internal.h:1434
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:87
TransmitCallback send_cls
Definition: internal.h:921
#define EDLL_remove(head, tail, element)
Definition: internal.h:1798
int MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:4458
MHD_OPTION
MHD options.
Definition: microhttpd.h:1168
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:103
void * notify_connection_cls
Definition: internal.h:1341
void * apc_cls
Definition: internal.h:1319
bool at_limit
Definition: internal.h:1499
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
struct sockaddr * addr
Definition: internal.h:712
MHD_PanicCallback mhd_panic
Definition: daemon.c:149
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1236
MHD_DaemonInfoType
Definition: microhttpd.h:1804
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2799
bool suspended
Definition: internal.h:965
const char * MHD_get_version(void)
Definition: daemon.c:6511
void * per_ip_connection_count
Definition: internal.h:1393
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:6545
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
size_t read_buffer_offset
Definition: internal.h:732
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:1068
void * default_handler_cls
Definition: internal.h:1216
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1483
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: daemon.c:2149
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1429
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:4642
Header for platform-independent locks abstraction.
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:1873
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:1966
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:6144
struct MHD_Connection * connections_tail
Definition: internal.h:1226
enum MHD_OPTION option
Definition: microhttpd.h:1502
#define MHD_socket_set_error_to_ENOMEM()
Definition: mhd_sockets.h:671
void MHD_monotonic_sec_counter_finish(void)
#define MHD_BUF_INC_SIZE
Definition: internal.h:98
#define MHD_TEST_ALLOW_SUSPEND_RESUME
Definition: internal.h:202
#define SIZE_MAX
Definition: mhd_limits.h:83
size_t MHD_http_unescape(char *val)
Definition: internal.c:138
MHD_FLAG
Flags for the struct MHD_Daemon.
Definition: microhttpd.h:882
size_t pool_increment
Definition: internal.h:1403
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1231
#define _MHD_SYS_DEFAULT_FD_SETSIZE
Definition: mhd_sockets.h:126
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...