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 static 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  /* Process response queued during suspend and update states. */
1883  was_suspended = false;
1884  }
1885 
1886  tvp = NULL;
1887 
1889 #ifdef HTTPS_SUPPORT
1890  || ( (con->tls_read_ready) &&
1892 #endif /* HTTPS_SUPPORT */
1893  )
1894  {
1895  /* do not block: more data may be inside of TLS buffers waiting or
1896  * application must provide response data */
1897  tv.tv_sec = 0;
1898  tv.tv_usec = 0;
1899  tvp = &tv;
1900  }
1901  if ( (NULL == tvp) &&
1902  (timeout > 0) )
1903  {
1904  now = MHD_monotonic_sec_counter();
1905  if (now - con->last_activity > timeout)
1906  tv.tv_sec = 0;
1907  else
1908  {
1909  const time_t seconds_left = timeout - (now - con->last_activity);
1910 #ifndef _WIN32
1911  tv.tv_sec = seconds_left;
1912 #else /* _WIN32 */
1913  if (seconds_left > TIMEVAL_TV_SEC_MAX)
1914  tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1915  else
1916  tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
1917 #endif /* _WIN32 */
1918  }
1919  tv.tv_usec = 0;
1920  tvp = &tv;
1921  }
1922  if (! use_poll)
1923  {
1924  /* use select */
1925  bool err_state = false;
1926 
1927  FD_ZERO (&rs);
1928  FD_ZERO (&ws);
1929  FD_ZERO (&es);
1930  maxsock = MHD_INVALID_SOCKET;
1931  switch (con->event_loop_info)
1932  {
1934  if (! MHD_add_to_fd_set_ (con->socket_fd,
1935  &rs,
1936  &maxsock,
1937  FD_SETSIZE))
1938  err_state = true;
1939  break;
1941  if (! MHD_add_to_fd_set_ (con->socket_fd,
1942  &ws,
1943  &maxsock,
1944  FD_SETSIZE))
1945  err_state = true;
1946  break;
1948  if (! MHD_add_to_fd_set_ (con->socket_fd,
1949  &es,
1950  &maxsock,
1951  FD_SETSIZE))
1952  err_state = true;
1953  break;
1955  /* how did we get here!? */
1956  goto exit;
1957  }
1958 #if WINDOWS
1959  if (MHD_ITC_IS_VALID_(daemon->itc) )
1960  {
1961  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1962  &rs,
1963  &maxsock,
1964  FD_SETSIZE))
1965  err_state = 1;
1966  }
1967 #endif
1968  if (err_state)
1969  {
1970 #ifdef HAVE_MESSAGES
1971  MHD_DLOG (con->daemon,
1972  _("Failed to add FD to fd_set\n"));
1973 #endif
1974  goto exit;
1975  }
1976 
1977  num_ready = MHD_SYS_select_ (maxsock + 1,
1978  &rs,
1979  &ws,
1980  NULL,
1981  tvp);
1982  if (num_ready < 0)
1983  {
1984  const int err = MHD_socket_get_error_();
1985 
1986  if (MHD_SCKT_ERR_IS_EINTR_(err))
1987  continue;
1988 #ifdef HAVE_MESSAGES
1989  MHD_DLOG (con->daemon,
1990  _("Error during select (%d): `%s'\n"),
1991  err,
1992  MHD_socket_strerr_ (err));
1993 #endif
1994  break;
1995  }
1996 #if WINDOWS
1997  /* Clear ITC before other processing so additional
1998  * signals will trigger select() again */
1999  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2000  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2001  &rs)) )
2002  MHD_itc_clear_ (daemon->itc);
2003 #endif
2004  if (MHD_NO ==
2005  call_handlers (con,
2006  FD_ISSET (con->socket_fd,
2007  &rs),
2008  FD_ISSET (con->socket_fd,
2009  &ws),
2010  FD_ISSET (con->socket_fd,
2011  &es)) )
2012  goto exit;
2013  }
2014 #ifdef HAVE_POLL
2015  else
2016  {
2017  /* use poll */
2018  memset (&p,
2019  0,
2020  sizeof (p));
2021  p[0].fd = con->socket_fd;
2022  switch (con->event_loop_info)
2023  {
2025  p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2026  break;
2028  p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2029  break;
2031  p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2032  break;
2034  /* how did we get here!? */
2035  goto exit;
2036  }
2037 #if WINDOWS
2038  extra_slot = 0;
2039  if (MHD_ITC_IS_VALID_(daemon->itc))
2040  {
2041  p[1].events |= POLLIN;
2042  p[1].fd = MHD_itc_r_fd_ (daemon->itc);
2043  p[1].revents = 0;
2044  extra_slot = 1;
2045  }
2046 #endif
2047  if (MHD_sys_poll_ (p,
2048 #if WINDOWS
2049  1 + extra_slot,
2050 #else
2051  1,
2052 #endif
2053  (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2054  {
2056  continue;
2057 #ifdef HAVE_MESSAGES
2058  MHD_DLOG (con->daemon,
2059  _("Error during poll: `%s'\n"),
2061 #endif
2062  break;
2063  }
2064 #if WINDOWS
2065  /* Clear ITC before other processing so additional
2066  * signals will trigger poll() again */
2067  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2068  (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2069  MHD_itc_clear_ (daemon->itc);
2070 #endif
2071  if (MHD_NO ==
2072  call_handlers (con,
2073  0 != (p[0].revents & POLLIN),
2074  0 != (p[0].revents & POLLOUT),
2075  0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
2076  goto exit;
2077  }
2078 #endif
2079 #ifdef UPGRADE_SUPPORT
2080  if (MHD_CONNECTION_UPGRADE == con->state)
2081  {
2082  /* Normal HTTP processing is finished,
2083  * notify application. */
2084  if ( (NULL != daemon->notify_completed) &&
2085  (con->client_aware) )
2086  daemon->notify_completed (daemon->notify_completed_cls,
2087  con,
2088  &con->client_context,
2090  con->client_aware = false;
2091 
2092  thread_main_connection_upgrade (con);
2093  /* MHD_connection_finish_forward_() was called by thread_main_connection_upgrade(). */
2094 
2095  /* "Upgraded" data will not be used in this thread from this point. */
2096  con->urh->clean_ready = true;
2097  /* If 'urh->was_closed' set to true, connection will be
2098  * moved immediately to cleanup list. Otherwise connection
2099  * will stay in suspended list until 'urh' will be marked
2100  * with 'was_closed' by application. */
2101  MHD_resume_connection(con);
2102 
2103  /* skip usual clean up */
2104  return (MHD_THRD_RTRN_TYPE_) 0;
2105  }
2106 #endif /* UPGRADE_SUPPORT */
2107  }
2108  if (MHD_CONNECTION_IN_CLEANUP != con->state)
2109  {
2110 #if DEBUG_CLOSE
2111 #ifdef HAVE_MESSAGES
2112  MHD_DLOG (con->daemon,
2113  _("Processing thread terminating. Closing connection\n"));
2114 #endif
2115 #endif
2116  if (MHD_CONNECTION_CLOSED != con->state)
2117  MHD_connection_close_ (con,
2118  (daemon->shutdown) ?
2121  con->idle_handler (con);
2122  }
2123 exit:
2124  if (NULL != con->response)
2125  {
2127  con->response = NULL;
2128  }
2129 
2130  if (MHD_INVALID_SOCKET != con->socket_fd)
2131  {
2132  shutdown (con->socket_fd,
2133  SHUT_WR);
2134  /* 'socket_fd' can be used in other thread to signal shutdown.
2135  * To avoid data races, do not close socket here. Daemon will
2136  * use more connections only after cleanup anyway. */
2137  }
2138  return (MHD_THRD_RTRN_TYPE_) 0;
2139 }
2140 
2141 
2150 static ssize_t
2152  void *other,
2153  size_t i)
2154 {
2155  ssize_t ret;
2156 
2157  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
2158  (MHD_CONNECTION_CLOSED == connection->state) )
2159  {
2161  return -1;
2162  }
2163  if (i > MHD_SCKT_SEND_MAX_SIZE_)
2164  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
2165 
2166  ret = MHD_recv_ (connection->socket_fd,
2167  other,
2168  i);
2169 #ifdef EPOLL_SUPPORT
2170  if (0 > ret)
2171  {
2172  /* Got EAGAIN --- no longer read-ready */
2174  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
2175  }
2176  else if (i > (size_t)ret)
2177  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
2178 #endif
2179  return ret;
2180 }
2181 
2182 
2191 static ssize_t
2193  const void *other,
2194  size_t i)
2195 {
2196  ssize_t ret;
2197  int err;
2198 
2199  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
2200  (MHD_CONNECTION_CLOSED == connection->state) )
2201  {
2203  return -1;
2204  }
2205  if (i > MHD_SCKT_SEND_MAX_SIZE_)
2206  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
2207 
2208  if (0 != (connection->daemon->options & MHD_USE_TLS))
2209  return MHD_send_ (connection->socket_fd,
2210  other,
2211  i);
2212 #if LINUX
2213  if ( (connection->write_buffer_append_offset ==
2214  connection->write_buffer_send_offset) &&
2215  (NULL != connection->response) &&
2216  (MHD_resp_sender_sendfile == connection->resp_sender) )
2217  {
2218  /* can use sendfile */
2219  int file_fd = connection->response->fd;
2220  uint64_t left;
2221  uint64_t offsetu64;
2222 #ifndef HAVE_SENDFILE64
2223  off_t offset;
2224 #else /* HAVE_SENDFILE64 */
2225  off64_t offset;
2226 #endif /* HAVE_SENDFILE64 */
2227  offsetu64 = connection->response_write_position + connection->response->fd_off;
2228  left = connection->response->total_size - connection->response_write_position;
2229  ret = 0;
2230 #ifndef HAVE_SENDFILE64
2231  if ((uint64_t)OFF_T_MAX < offsetu64)
2233  else
2234  {
2235  offset = (off_t) offsetu64;
2236  ret = sendfile (connection->socket_fd,
2237  file_fd,
2238  &offset,
2239  left);
2240  }
2241 #else /* HAVE_SENDFILE64 */
2242  if ((uint64_t)OFF64_T_MAX < offsetu64)
2244  else
2245  {
2246  offset = (off64_t) offsetu64;
2247  ret = sendfile64 (connection->socket_fd,
2248  file_fd,
2249  &offset,
2250  left);
2251  }
2252 #endif /* HAVE_SENDFILE64 */
2253  if (0 < ret)
2254  {
2255  /* write successful */
2256 #ifdef EPOLL_SUPPORT
2257  if (left > (uint64_t)ret)
2258  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2259 #endif /* EPOLL_SUPPORT */
2260  return ret;
2261  }
2262  err = MHD_socket_get_error_();
2263 #ifdef EPOLL_SUPPORT
2264  if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) )
2265  {
2266  /* EAGAIN --- no longer write-ready */
2267  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2268  }
2269 #endif
2270  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2272  return 0;
2273  if (MHD_SCKT_ERR_IS_(err,
2274  MHD_SCKT_EBADF_))
2275  return -1;
2276  /* sendfile() failed with EINVAL if mmap()-like operations are not
2277  supported for FD or other 'unusual' errors occurred, so we should try
2278  to fall back to 'SEND'; see also this thread for info on
2279  odd libc/Linux behavior with sendfile:
2280  http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
2281  connection->resp_sender = MHD_resp_sender_std;
2282  }
2283 #endif
2284  ret = MHD_send_ (connection->socket_fd,
2285  other,
2286  i);
2287  err = MHD_socket_get_error_();
2288 #ifdef EPOLL_SUPPORT
2289  if (0 > ret)
2290  {
2291  /* EAGAIN --- no longer write-ready */
2292  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
2293  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2294  }
2295  else if (i > (size_t)ret)
2296  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
2297 #endif
2298  /* Handle broken kernel / libc, returning -1 but not setting errno;
2299  kill connection as that should be safe; reported on mailinglist here:
2300  http://lists.gnu.org/archive/html/libmicrohttpd/2014-10/msg00023.html */
2301  if ( (0 > ret) &&
2302  (0 == err) )
2304  return ret;
2305 }
2306 
2307 
2315 static void
2316 MHD_cleanup_connections (struct MHD_Daemon *daemon);
2317 
2318 
2349 static int
2351  MHD_socket client_socket,
2352  const struct sockaddr *addr,
2353  socklen_t addrlen,
2354  int external_add,
2355  bool non_blck)
2356 {
2357  struct MHD_Connection *connection;
2358  unsigned int i;
2359  int eno;
2360  struct MHD_Daemon *worker;
2361 
2362  if (NULL != daemon->worker_pool)
2363  {
2364  /* have a pool, try to find a pool with capacity; we use the
2365  socket as the initial offset into the pool for load
2366  balancing */
2367  for (i=0;i<daemon->worker_pool_size;i++)
2368  {
2369  worker = &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
2370  if (worker->connections < worker->connection_limit)
2371  return internal_add_connection (worker,
2372  client_socket,
2373  addr,
2374  addrlen,
2375  external_add,
2376  non_blck);
2377  }
2378  /* all pools are at their connection limit, must refuse */
2379  MHD_socket_close_chk_ (client_socket);
2380 #if ENFILE
2381  errno = ENFILE;
2382 #endif
2383  return MHD_NO;
2384  }
2385 
2386  if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
2387  NULL)) &&
2388  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
2389  {
2390 #ifdef HAVE_MESSAGES
2391  MHD_DLOG (daemon,
2392  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2393  (int) client_socket,
2394  (int) FD_SETSIZE);
2395 #endif
2396  MHD_socket_close_chk_ (client_socket);
2397 #if EINVAL
2398  errno = EINVAL;
2399 #endif
2400  return MHD_NO;
2401  }
2402 
2403 #ifdef MHD_socket_nosignal_
2404  if (! MHD_socket_nosignal_ (client_socket))
2405  {
2406 #ifdef HAVE_MESSAGES
2407  MHD_DLOG (daemon,
2408  _("Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2410 #endif
2411 #ifndef MSG_NOSIGNAL
2412  /* Cannot use socket as it can produce SIGPIPE. */
2413 #ifdef ENOTSOCK
2414  errno = ENOTSOCK;
2415 #endif /* ENOTSOCK */
2416  return MHD_NO;
2417 #endif /* ! MSG_NOSIGNAL */
2418  }
2419 #endif /* MHD_socket_nosignal_ */
2420 
2421 
2422 #ifdef HAVE_MESSAGES
2423 #if DEBUG_CONNECT
2424  MHD_DLOG (daemon,
2425  _("Accepted connection on socket %d\n"),
2426  client_socket);
2427 #endif
2428 #endif
2429  if ( (daemon->connections == daemon->connection_limit) ||
2430  (MHD_NO == MHD_ip_limit_add (daemon,
2431  addr,
2432  addrlen)) )
2433  {
2434  /* above connection limit - reject */
2435 #ifdef HAVE_MESSAGES
2436  MHD_DLOG (daemon,
2437  _("Server reached connection limit. Closing inbound connection.\n"));
2438 #endif
2439  MHD_socket_close_chk_ (client_socket);
2440 #if ENFILE
2441  errno = ENFILE;
2442 #endif
2443  return MHD_NO;
2444  }
2445 
2446  /* apply connection acceptance policy if present */
2447  if ( (NULL != daemon->apc) &&
2448  (MHD_NO == daemon->apc (daemon->apc_cls,
2449  addr,
2450  addrlen)) )
2451  {
2452 #if DEBUG_CLOSE
2453 #ifdef HAVE_MESSAGES
2454  MHD_DLOG (daemon,
2455  _("Connection rejected by application. Closing connection.\n"));
2456 #endif
2457 #endif
2458  MHD_socket_close_chk_ (client_socket);
2459  MHD_ip_limit_del (daemon,
2460  addr,
2461  addrlen);
2462 #if EACCESS
2463  errno = EACCESS;
2464 #endif
2465  return MHD_NO;
2466  }
2467 
2468  if (NULL == (connection = MHD_calloc_ (1, sizeof (struct MHD_Connection))))
2469  {
2470  eno = errno;
2471 #ifdef HAVE_MESSAGES
2472  MHD_DLOG (daemon,
2473  "Error allocating memory: %s\n",
2474  MHD_strerror_ (errno));
2475 #endif
2476  MHD_socket_close_chk_ (client_socket);
2477  MHD_ip_limit_del (daemon,
2478  addr,
2479  addrlen);
2480  errno = eno;
2481  return MHD_NO;
2482  }
2483  connection->pool = MHD_pool_create (daemon->pool_size);
2484  if (NULL == connection->pool)
2485  {
2486 #ifdef HAVE_MESSAGES
2487  MHD_DLOG (daemon,
2488  _("Error allocating memory: %s\n"),
2489  MHD_strerror_ (errno));
2490 #endif
2491  MHD_socket_close_chk_ (client_socket);
2492  MHD_ip_limit_del (daemon,
2493  addr,
2494  addrlen);
2495  free (connection);
2496 #if ENOMEM
2497  errno = ENOMEM;
2498 #endif
2499  return MHD_NO;
2500  }
2501 
2502  connection->connection_timeout = daemon->connection_timeout;
2503  if (NULL == (connection->addr = malloc (addrlen)))
2504  {
2505  eno = errno;
2506 #ifdef HAVE_MESSAGES
2507  MHD_DLOG (daemon,
2508  _("Error allocating memory: %s\n"),
2509  MHD_strerror_ (errno));
2510 #endif
2511  MHD_socket_close_chk_ (client_socket);
2512  MHD_ip_limit_del (daemon,
2513  addr,
2514  addrlen);
2515  MHD_pool_destroy (connection->pool);
2516  free (connection);
2517  errno = eno;
2518  return MHD_NO;
2519  }
2520  memcpy (connection->addr,
2521  addr,
2522  addrlen);
2523  connection->addr_len = addrlen;
2524  connection->socket_fd = client_socket;
2525  connection->sk_nonblck = non_blck;
2526  connection->daemon = daemon;
2527  connection->last_activity = MHD_monotonic_sec_counter();
2528 
2529  if (0 == (daemon->options & MHD_USE_TLS))
2530  {
2531  /* set default connection handlers */
2532  MHD_set_http_callbacks_ (connection);
2533  connection->recv_cls = &recv_param_adapter;
2534  connection->send_cls = &send_param_adapter;
2535  }
2536  else
2537  {
2538 #ifdef HTTPS_SUPPORT
2539  connection->recv_cls = &recv_tls_adapter;
2540  connection->send_cls = &send_tls_adapter;
2541  connection->state = MHD_TLS_CONNECTION_INIT;
2542  MHD_set_https_callbacks (connection);
2543  gnutls_init (&connection->tls_session,
2544  GNUTLS_SERVER);
2545  gnutls_priority_set (connection->tls_session,
2546  daemon->priority_cache);
2547  switch (daemon->cred_type)
2548  {
2549  /* set needed credentials for certificate authentication. */
2550  case GNUTLS_CRD_CERTIFICATE:
2551  gnutls_credentials_set (connection->tls_session,
2552  GNUTLS_CRD_CERTIFICATE,
2553  daemon->x509_cred);
2554  break;
2555  default:
2556 #ifdef HAVE_MESSAGES
2557  MHD_DLOG (connection->daemon,
2558  _("Failed to setup TLS credentials: unknown credential type %d\n"),
2559  daemon->cred_type);
2560 #endif
2561  MHD_socket_close_chk_ (client_socket);
2562  MHD_ip_limit_del (daemon,
2563  addr,
2564  addrlen);
2565  free (connection->addr);
2566  free (connection);
2567  MHD_PANIC (_("Unknown credential type"));
2568 #if EINVAL
2569  errno = EINVAL;
2570 #endif
2571  return MHD_NO;
2572  }
2573  gnutls_transport_set_ptr (connection->tls_session,
2574  (gnutls_transport_ptr_t) connection);
2575  gnutls_transport_set_pull_function (connection->tls_session,
2576  (gnutls_pull_func) &recv_param_adapter);
2577  gnutls_transport_set_push_function (connection->tls_session,
2578  (gnutls_push_func) &send_param_adapter);
2579 
2580  if (daemon->https_mem_trust)
2581  gnutls_certificate_server_set_request (connection->tls_session,
2582  GNUTLS_CERT_REQUEST);
2583 #else /* ! HTTPS_SUPPORT */
2584  eno = EINVAL;
2585  goto cleanup;
2586 #endif /* ! HTTPS_SUPPORT */
2587  }
2588 
2589 
2591  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2592  {
2594  daemon->normal_timeout_tail,
2595  connection);
2596  }
2597  DLL_insert (daemon->connections_head,
2598  daemon->connections_tail,
2599  connection);
2601 
2602  if (NULL != daemon->notify_connection)
2603  daemon->notify_connection (daemon->notify_connection_cls,
2604  connection,
2605  &connection->socket_context,
2607 
2608  /* attempt to create handler thread */
2609  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2610  {
2611  if (! MHD_create_named_thread_ (&connection->pid,
2612  "MHD-connection",
2613  daemon->thread_stack_size,
2615  connection))
2616  {
2617  eno = errno;
2618 #ifdef HAVE_MESSAGES
2619  MHD_DLOG (daemon,
2620  "Failed to create a thread: %s\n",
2621  MHD_strerror_ (eno));
2622 #endif
2623  goto cleanup;
2624  }
2625  }
2626  else
2627  if ( (MHD_YES == external_add) &&
2628  (MHD_ITC_IS_VALID_(daemon->itc)) &&
2629  (! MHD_itc_activate_ (daemon->itc, "n")) )
2630  {
2631 #ifdef HAVE_MESSAGES
2632  MHD_DLOG (daemon,
2633  _("Failed to signal new connection via inter-thread communication channel."));
2634 #endif
2635  }
2636 #ifdef EPOLL_SUPPORT
2637  if (0 != (daemon->options & MHD_USE_EPOLL))
2638  {
2639  if (0 == (daemon->options & MHD_USE_TURBO))
2640  {
2641  struct epoll_event event;
2642 
2643  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2644  event.data.ptr = connection;
2645  if (0 != epoll_ctl (daemon->epoll_fd,
2646  EPOLL_CTL_ADD,
2647  client_socket,
2648  &event))
2649  {
2650  eno = errno;
2651 #ifdef HAVE_MESSAGES
2652  MHD_DLOG (daemon,
2653  _("Call to epoll_ctl failed: %s\n"),
2655 #endif
2656  goto cleanup;
2657  }
2658  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2659  }
2660  else
2661  {
2662  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
2664  EDLL_insert (daemon->eready_head,
2665  daemon->eready_tail,
2666  connection);
2667  }
2668  }
2669 #endif
2670  daemon->connections++;
2671  return MHD_YES;
2672  cleanup:
2673  if (NULL != daemon->notify_connection)
2674  daemon->notify_connection (daemon->notify_connection_cls,
2675  connection,
2676  &connection->socket_context,
2678  MHD_socket_close_chk_ (client_socket);
2679  MHD_ip_limit_del (daemon,
2680  addr,
2681  addrlen);
2683  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2684  {
2686  daemon->normal_timeout_tail,
2687  connection);
2688  }
2689  DLL_remove (daemon->connections_head,
2690  daemon->connections_tail,
2691  connection);
2693  MHD_pool_destroy (connection->pool);
2694  free (connection->addr);
2695  free (connection);
2696  errno = eno;
2697  return MHD_NO;
2698 }
2699 
2700 
2710 void
2712 {
2713  struct MHD_Daemon *daemon = connection->daemon;
2714 
2716  if (connection->resuming)
2717  {
2718  /* suspending again while we didn't even complete resuming yet */
2719  connection->resuming = false;
2721  return;
2722  }
2723  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2724  {
2725  if (connection->connection_timeout == daemon->connection_timeout)
2727  daemon->normal_timeout_tail,
2728  connection);
2729  else
2731  daemon->manual_timeout_tail,
2732  connection);
2733  }
2734  DLL_remove (daemon->connections_head,
2735  daemon->connections_tail,
2736  connection);
2737  EXTRA_CHECK (! connection->suspended);
2740  connection);
2741  connection->suspended = true;
2742 #ifdef EPOLL_SUPPORT
2743  if (0 != (daemon->options & MHD_USE_EPOLL))
2744  {
2745  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2746  {
2747  EDLL_remove (daemon->eready_head,
2748  daemon->eready_tail,
2749  connection);
2750  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2751  }
2752  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2753  {
2754  if (0 != epoll_ctl (daemon->epoll_fd,
2755  EPOLL_CTL_DEL,
2756  connection->socket_fd,
2757  NULL))
2758  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
2759  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2760  }
2761  connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2762  }
2763 #endif
2765 }
2766 
2767 
2799 void
2801 {
2802  struct MHD_Daemon * const daemon = connection->daemon;
2803 
2804  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2805  MHD_PANIC (_("Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2806 #ifdef UPGRADE_SUPPORT
2807  if (NULL != connection->urh)
2808  {
2809 #ifdef HAVE_MESSAGES
2810  MHD_DLOG (daemon,
2811  _("Error: connection scheduled for \"upgrade\" cannot be suspended"));
2812 #endif /* HAVE_MESSAGES */
2813  return;
2814  }
2815 #endif /* UPGRADE_SUPPORT */
2816  internal_suspend_connection_ (connection);
2817 }
2818 
2819 
2828 void
2830 {
2831  struct MHD_Daemon *daemon;
2832 
2833  daemon = connection->daemon;
2834  if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
2835  MHD_PANIC (_("Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2837  connection->resuming = true;
2838  daemon->resuming = true;
2840  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2841  (! MHD_itc_activate_ (daemon->itc, "r")) )
2842  {
2843 #ifdef HAVE_MESSAGES
2844  MHD_DLOG (daemon,
2845  _("Failed to signal resume via inter-thread communication channel."));
2846 #endif
2847  }
2848 }
2849 
2850 
2860 static int
2862 {
2863  struct MHD_Connection *pos;
2864  struct MHD_Connection *prev = NULL;
2865  int ret;
2866  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
2867 
2868  ret = MHD_NO;
2870 
2871  if (daemon->resuming)
2872  prev = daemon->suspended_connections_tail;
2873 
2874  EXTRA_CHECK(NULL != next);
2875  daemon->resuming = false;
2876 
2877  while (NULL != (pos = prev))
2878  {
2879 #ifdef UPGRADE_SUPPORT
2880  struct MHD_UpgradeResponseHandle * const urh = pos->urh;
2881 #else /* ! UPGRADE_SUPPORT */
2882  static const void * const urh = NULL;
2883 #endif /* ! UPGRADE_SUPPORT */
2884  prev = pos->prev;
2885  if ( (! pos->resuming)
2886 #ifdef UPGRADE_SUPPORT
2887  || ( (NULL != urh) &&
2888  ( (! urh->was_closed) ||
2889  (! urh->clean_ready) ) )
2890 #endif /* UPGRADE_SUPPORT */
2891  )
2892  continue;
2893  ret = MHD_YES;
2894  EXTRA_CHECK (pos->suspended);
2897  pos);
2898  pos->suspended = false;
2899  if (NULL == urh)
2900  {
2901  DLL_insert (daemon->connections_head,
2902  daemon->connections_tail,
2903  pos);
2904  if (!used_thr_p_c)
2905  {
2906  /* Reset timeout timer on resume. */
2907  if (0 != pos->connection_timeout)
2909 
2910  if (pos->connection_timeout == daemon->connection_timeout)
2912  daemon->normal_timeout_tail,
2913  pos);
2914  else
2916  daemon->manual_timeout_tail,
2917  pos);
2918  }
2919 #ifdef EPOLL_SUPPORT
2920  if (0 != (daemon->options & MHD_USE_EPOLL))
2921  {
2922  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2923  MHD_PANIC ("Resumed connection was already in EREADY set\n");
2924  /* we always mark resumed connections as ready, as we
2925  might have missed the edge poll event during suspension */
2926  EDLL_insert (daemon->eready_head,
2927  daemon->eready_tail,
2928  pos);
2929  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL | \
2930  MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
2931  pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
2932  }
2933 #endif
2934  }
2935 #ifdef UPGRADE_SUPPORT
2936  else
2937  {
2938  /* Data forwarding was finished (for TLS connections) AND
2939  * application was closed upgraded connection.
2940  * Insert connection into cleanup list. */
2941  DLL_insert (daemon->cleanup_head,
2942  daemon->cleanup_tail,
2943  pos);
2944 
2945  }
2946 #endif /* UPGRADE_SUPPORT */
2947  pos->resuming = false;
2948  }
2950  if ( (used_thr_p_c) &&
2951  (MHD_NO != ret) )
2952  { /* Wake up suspended connections. */
2953  if (! MHD_itc_activate_(daemon->itc,
2954  "w"))
2955  {
2956 #ifdef HAVE_MESSAGES
2957  MHD_DLOG (daemon,
2958  _("Failed to signal resume of connection via inter-thread communication channel."));
2959 #endif
2960  }
2961  }
2962  return ret;
2963 }
2964 
2965 
2995 int
2997  MHD_socket client_socket,
2998  const struct sockaddr *addr,
2999  socklen_t addrlen)
3000 {
3001  bool sk_nonbl;
3002  if (! MHD_socket_nonblocking_ (client_socket))
3003  {
3004 #ifdef HAVE_MESSAGES
3005  MHD_DLOG (daemon,
3006  _("Failed to set nonblocking mode on new client socket: %s\n"),
3008 #endif
3009  sk_nonbl = 0;
3010  }
3011  else
3012  sk_nonbl = !0;
3013 
3014  if ( (0 != (daemon->options & MHD_USE_TURBO)) &&
3015  (! MHD_socket_noninheritable_ (client_socket)) )
3016  {
3017 #ifdef HAVE_MESSAGES
3018  MHD_DLOG (daemon,
3019  _("Failed to set noninheritable mode on new client socket.\n"));
3020 #endif
3021  }
3022  return internal_add_connection (daemon,
3023  client_socket,
3024  addr,
3025  addrlen,
3026  MHD_YES,
3027  sk_nonbl);
3028 }
3029 
3030 
3045 static int
3047 {
3048 #if HAVE_INET6
3049  struct sockaddr_in6 addrstorage;
3050 #else
3051  struct sockaddr_in addrstorage;
3052 #endif
3053  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
3054  socklen_t addrlen;
3055  MHD_socket s;
3056  MHD_socket fd;
3057  bool sk_nonbl;
3058 
3059  addrlen = sizeof (addrstorage);
3060  memset (addr,
3061  0,
3062  sizeof (addrstorage));
3063  if ( (MHD_INVALID_SOCKET == (fd = daemon->listen_fd)) ||
3064  (daemon->was_quiesced) )
3065  return MHD_NO;
3066 #ifdef USE_ACCEPT4
3067  s = accept4 (fd,
3068  addr,
3069  &addrlen,
3071  sk_nonbl = (MAYBE_SOCK_NONBLOCK != 0);
3072 #else /* ! USE_ACCEPT4 */
3073  s = accept (fd,
3074  addr,
3075  &addrlen);
3076  sk_nonbl = 0;
3077 #endif /* ! USE_ACCEPT4 */
3078  if ( (MHD_INVALID_SOCKET == s) ||
3079  (addrlen <= 0) )
3080  {
3081  const int err = MHD_socket_get_error_ ();
3082 
3083  /* This could be a common occurance with multiple worker threads */
3084  if (MHD_SCKT_ERR_IS_ (err,
3086  return MHD_NO; /* can happen during shutdown */
3088  return MHD_NO; /* do not print error if client just disconnected early */
3089 #ifdef HAVE_MESSAGES
3090  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
3091  MHD_DLOG (daemon,
3092  _("Error accepting connection: %s\n"),
3093  MHD_socket_strerr_(err));
3094 #endif
3095  if (MHD_INVALID_SOCKET != s)
3096  {
3098  }
3099  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
3100  {
3101  /* system/process out of resources */
3102  if (0 == daemon->connections)
3103  {
3104 #ifdef HAVE_MESSAGES
3105  /* Not setting 'at_limit' flag, as there is no way it
3106  would ever be cleared. Instead trying to produce
3107  bit fat ugly warning. */
3108  MHD_DLOG (daemon,
3109  _("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"));
3110 #endif
3111  }
3112  else
3113  {
3114  daemon->at_limit = true;
3115 #ifdef HAVE_MESSAGES
3116  MHD_DLOG (daemon,
3117  _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3118  (unsigned int) daemon->connections);
3119 #endif
3120  }
3121  }
3122  return MHD_NO;
3123  }
3124 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
3125  if (! MHD_socket_nonblocking_ (s))
3126  {
3127 #ifdef HAVE_MESSAGES
3128  MHD_DLOG (daemon,
3129  _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
3131 #endif
3132  }
3133  else
3134  sk_nonbl = !0;
3135 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
3136 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
3137  if (! MHD_socket_noninheritable_ (s))
3138  {
3139 #ifdef HAVE_MESSAGES
3140  MHD_DLOG (daemon,
3141  _("Failed to set noninheritable mode on incoming connection socket.\n"));
3142 #endif
3143  }
3144 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
3145 #ifdef HAVE_MESSAGES
3146 #if DEBUG_CONNECT
3147  MHD_DLOG (daemon,
3148  _("Accepted connection on socket %d\n"),
3149  s);
3150 #endif
3151 #endif
3152  (void) internal_add_connection (daemon,
3153  s,
3154  addr,
3155  addrlen,
3156  MHD_NO,
3157  sk_nonbl);
3158  return MHD_YES;
3159 }
3160 
3161 
3171 static void
3173 {
3174  struct MHD_Connection *pos;
3175 
3177  while (NULL != (pos = daemon->cleanup_tail))
3178  {
3179  DLL_remove (daemon->cleanup_head,
3180  daemon->cleanup_tail,
3181  pos);
3183 
3184  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3185  (! pos->thread_joined) &&
3186  (! MHD_join_thread_ (pos->pid)) )
3187  MHD_PANIC (_("Failed to join a thread\n"));
3188 #ifdef UPGRADE_SUPPORT
3189  cleanup_upgraded_connection (pos);
3190 #endif /* UPGRADE_SUPPORT */
3191  MHD_pool_destroy (pos->pool);
3192 #ifdef HTTPS_SUPPORT
3193  if (NULL != pos->tls_session)
3194  gnutls_deinit (pos->tls_session);
3195 #endif /* HTTPS_SUPPORT */
3196  daemon->connections--;
3197  daemon->at_limit = false;
3198 
3199  /* clean up the connection */
3200  if (NULL != daemon->notify_connection)
3201  daemon->notify_connection (daemon->notify_connection_cls,
3202  pos,
3203  &pos->socket_context,
3205  MHD_ip_limit_del (daemon,
3206  pos->addr,
3207  pos->addr_len);
3208 #ifdef EPOLL_SUPPORT
3209  if (0 != (daemon->options & MHD_USE_EPOLL))
3210  {
3211  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
3212  {
3213  EDLL_remove (daemon->eready_head,
3214  daemon->eready_tail,
3215  pos);
3216  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3217  }
3218  if ( (-1 != daemon->epoll_fd) &&
3219  (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
3220  {
3221  /* epoll documentation suggests that closing a FD
3222  automatically removes it from the epoll set; however,
3223  this is not true as if we fail to do manually remove it,
3224  we are still seeing an event for this fd in epoll,
3225  causing grief (use-after-free...) --- at least on my
3226  system. */
3227  if (0 != epoll_ctl (daemon->epoll_fd,
3228  EPOLL_CTL_DEL,
3229  pos->socket_fd,
3230  NULL))
3231  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
3232  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3233  }
3234  }
3235 #endif
3236  if (NULL != pos->response)
3237  {
3239  pos->response = NULL;
3240  }
3241  if (MHD_INVALID_SOCKET != pos->socket_fd)
3243  if (NULL != pos->addr)
3244  free (pos->addr);
3245  free (pos);
3246 
3248  }
3250 }
3251 
3252 
3269 int
3270 MHD_get_timeout (struct MHD_Daemon *daemon,
3271  MHD_UNSIGNED_LONG_LONG *timeout)
3272 {
3273  time_t earliest_deadline;
3274  time_t now;
3275  struct MHD_Connection *pos;
3276  bool have_timeout;
3277 
3278  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3279  {
3280 #ifdef HAVE_MESSAGES
3281  MHD_DLOG (daemon,
3282  _("Illegal call to MHD_get_timeout\n"));
3283 #endif
3284  return MHD_NO;
3285  }
3286 
3287  if (daemon->data_already_pending)
3288  {
3289  /* Some data already waiting to be processed. */
3290  *timeout = 0;
3291  return MHD_YES;
3292  }
3293 
3294 #ifdef EPOLL_SUPPORT
3295  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3296  ((NULL != daemon->eready_head)
3297 #if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3298  || (NULL != daemon->eready_urh_head)
3299 #endif /* UPGRADE_SUPPORT && HTTPS_SUPPORT */
3300  ) )
3301  {
3302  /* Some connection(s) already have some data pending. */
3303  *timeout = 0;
3304  return MHD_YES;
3305  }
3306 #endif /* EPOLL_SUPPORT */
3307 
3308  have_timeout = false;
3309  earliest_deadline = 0; /* avoid compiler warnings */
3310  for (pos = daemon->manual_timeout_tail; NULL != pos; pos = pos->prevX)
3311  {
3312  if (0 != pos->connection_timeout)
3313  {
3314  if ( (! have_timeout) ||
3315  (earliest_deadline - pos->last_activity > pos->connection_timeout) )
3316  earliest_deadline = pos->last_activity + pos->connection_timeout;
3317  have_timeout = true;
3318  }
3319  }
3320  /* normal timeouts are sorted, so we only need to look at the 'tail' (oldest) */
3321  pos = daemon->normal_timeout_tail;
3322  if ( (NULL != pos) &&
3323  (0 != pos->connection_timeout) )
3324  {
3325  if ( (! have_timeout) ||
3326  (earliest_deadline - pos->connection_timeout > pos->last_activity) )
3327  earliest_deadline = pos->last_activity + pos->connection_timeout;
3328  have_timeout = true;
3329  }
3330 
3331  if (! have_timeout)
3332  return MHD_NO;
3333  now = MHD_monotonic_sec_counter();
3334  if (earliest_deadline < now)
3335  *timeout = 0;
3336  else
3337  {
3338  const time_t second_left = earliest_deadline - now;
3339  if (second_left > ULLONG_MAX / 1000) /* Ignore compiler warning: 'second_left' is always positive. */
3340  *timeout = ULLONG_MAX;
3341  else
3342  *timeout = 1000LL * second_left;
3343  }
3344  return MHD_YES;
3345 }
3346 
3347 
3358 static int
3360  const fd_set *read_fd_set,
3361  const fd_set *write_fd_set,
3362  const fd_set *except_fd_set)
3363 {
3364  MHD_socket ds;
3365  struct MHD_Connection *pos;
3366  struct MHD_Connection *prev;
3367 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3368  struct MHD_UpgradeResponseHandle *urh;
3369  struct MHD_UpgradeResponseHandle *urhn;
3370 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3371  /* Reset. New value will be set when connections are processed. */
3372  /* Note: no-op for thread-per-connection as it is always false in that mode. */
3373  daemon->data_already_pending = false;
3374 
3375  /* Clear ITC to avoid spinning select */
3376  /* Do it before any other processing so new signals
3377  will trigger select again and will be processed */
3378  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3379  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
3380  read_fd_set)) )
3381  MHD_itc_clear_ (daemon->itc);
3382 
3383  /* select connection thread handling type */
3384  if ( (MHD_INVALID_SOCKET != (ds = daemon->listen_fd)) &&
3385  (! daemon->was_quiesced) &&
3386  (FD_ISSET (ds,
3387  read_fd_set)) )
3388  (void) MHD_accept_connection (daemon);
3389 
3390  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3391  {
3392  /* do not have a thread per connection, process all connections now */
3393  prev = daemon->connections_tail;
3394  while (NULL != (pos = prev))
3395  {
3396  prev = pos->prev;
3397  ds = pos->socket_fd;
3398  if (MHD_INVALID_SOCKET == ds)
3399  continue;
3400  call_handlers (pos,
3401  FD_ISSET (ds,
3402  read_fd_set),
3403  FD_ISSET (ds,
3404  write_fd_set),
3405  FD_ISSET (ds,
3406  except_fd_set));
3407  }
3408  }
3409 
3410 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3411  /* handle upgraded HTTPS connections */
3412  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3413  {
3414  urhn = urh->prev;
3415  /* update urh state based on select() output */
3416  urh_from_fdset (urh,
3417  read_fd_set,
3418  write_fd_set,
3419  except_fd_set);
3420  /* call generic forwarding function for passing data */
3421  process_urh (urh);
3422  /* Finished forwarding? */
3423  if ( (0 == urh->in_buffer_size) &&
3424  (0 == urh->out_buffer_size) &&
3425  (0 == urh->in_buffer_used) &&
3426  (0 == urh->out_buffer_used) )
3427  {
3428  MHD_connection_finish_forward_ (urh->connection);
3429  urh->clean_ready = true;
3430  /* Resuming will move connection to cleanup list. */
3431  MHD_resume_connection(urh->connection);
3432  }
3433  }
3434 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3435  MHD_cleanup_connections (daemon);
3436  return MHD_YES;
3437 }
3438 
3439 
3462 int
3464  const fd_set *read_fd_set,
3465  const fd_set *write_fd_set,
3466  const fd_set *except_fd_set)
3467 {
3468  fd_set es;
3469  if (0 != (daemon->options &
3471  return MHD_NO;
3472  if (NULL == read_fd_set || NULL == write_fd_set)
3473  return MHD_NO;
3474  if (NULL == except_fd_set)
3475  { /* Workaround to maintain backward compatibility. */
3476 #ifdef HAVE_MESSAGES
3477  MHD_DLOG (daemon,
3478  _("MHD_run_from_select() called with except_fd_set "
3479  "set to NULL. Such behavior is deprecated.\n"));
3480 #endif
3481  FD_ZERO (&es);
3482  except_fd_set = &es;
3483  }
3484  if (0 != (daemon->options & MHD_USE_EPOLL))
3485  {
3486 #ifdef EPOLL_SUPPORT
3487  int ret;
3488  ret = MHD_epoll (daemon, MHD_NO);
3489  MHD_cleanup_connections (daemon);
3490  return ret;
3491 #else /* ! EPOLL_SUPPORT */
3492  return MHD_NO;
3493 #endif /* ! EPOLL_SUPPORT */
3494  }
3495 
3496  /* Resuming external connections when using an extern mainloop */
3497  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3499 
3500  return internal_run_from_select (daemon, read_fd_set,
3501  write_fd_set, except_fd_set);
3502 }
3503 
3504 
3513 static int
3514 MHD_select (struct MHD_Daemon *daemon,
3515  int may_block)
3516 {
3517  int num_ready;
3518  fd_set rs;
3519  fd_set ws;
3520  fd_set es;
3521  MHD_socket maxsock;
3522  struct timeval timeout;
3523  struct timeval *tv;
3524  MHD_UNSIGNED_LONG_LONG ltimeout;
3525  int err_state;
3526  MHD_socket ls;
3527 
3528  timeout.tv_sec = 0;
3529  timeout.tv_usec = 0;
3530  if (daemon->shutdown)
3531  return MHD_NO;
3532  FD_ZERO (&rs);
3533  FD_ZERO (&ws);
3534  FD_ZERO (&es);
3535  maxsock = MHD_INVALID_SOCKET;
3536  err_state = MHD_NO;
3537  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3538  (MHD_YES == resume_suspended_connections (daemon)) &&
3539  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
3540  may_block = MHD_NO;
3541 
3542  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3543  {
3544  /* single-threaded, go over everything */
3545  if (MHD_NO ==
3546  internal_get_fdset2 (daemon,
3547  &rs,
3548  &ws,
3549  &es,
3550  &maxsock,
3551  FD_SETSIZE))
3552  {
3553 #ifdef HAVE_MESSAGES
3554  MHD_DLOG (daemon,
3555  _("Could not obtain daemon fdsets"));
3556 #endif
3557  err_state = MHD_YES;
3558  }
3559  }
3560  else
3561  {
3562  /* accept only, have one thread per connection */
3563  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3564  (! daemon->was_quiesced) &&
3565  (! MHD_add_to_fd_set_ (ls,
3566  &rs,
3567  &maxsock,
3568  FD_SETSIZE)) )
3569  {
3570 #ifdef HAVE_MESSAGES
3571  MHD_DLOG (daemon,
3572  _("Could not add listen socket to fdset"));
3573 #endif
3574  return MHD_NO;
3575  }
3576  }
3577  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3578  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
3579  &rs,
3580  &maxsock,
3581  FD_SETSIZE)) )
3582  {
3583 #if defined(MHD_WINSOCK_SOCKETS)
3584  /* fdset limit reached, new connections
3585  cannot be handled. Remove listen socket FD
3586  from fdset and retry to add ITC FD. */
3587  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3588  (! daemon->was_quiesced) )
3589  {
3590  FD_CLR (ls,
3591  &rs);
3592  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
3593  &rs,
3594  &maxsock,
3595  FD_SETSIZE))
3596  {
3597 #endif /* MHD_WINSOCK_SOCKETS */
3598 #ifdef HAVE_MESSAGES
3599  MHD_DLOG (daemon,
3600  _("Could not add control inter-thread communication channel FD to fdset"));
3601 #endif
3602  err_state = MHD_YES;
3603 #if defined(MHD_WINSOCK_SOCKETS)
3604  }
3605  }
3606 #endif /* MHD_WINSOCK_SOCKETS */
3607  }
3608  /* Stop listening if we are at the configured connection limit */
3609  /* If we're at the connection limit, no point in really
3610  accepting new connections; however, make sure we do not miss
3611  the shutdown OR the termination of an existing connection; so
3612  only do this optimization if we have a signaling ITC in
3613  place. */
3614  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3615  (MHD_ITC_IS_VALID_(daemon->itc)) &&
3616  ( (daemon->connections == daemon->connection_limit) ||
3617  (daemon->at_limit) ) )
3618  {
3619  FD_CLR (ls,
3620  &rs);
3621  }
3622  tv = NULL;
3623  if (MHD_YES == err_state)
3624  may_block = MHD_NO;
3625  if (MHD_NO == may_block)
3626  {
3627  timeout.tv_usec = 0;
3628  timeout.tv_sec = 0;
3629  tv = &timeout;
3630  }
3631  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3632  (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
3633  {
3634  /* ltimeout is in ms */
3635  timeout.tv_usec = (ltimeout % 1000) * 1000;
3636  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
3637  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
3638  else
3639  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)(ltimeout / 1000);
3640  tv = &timeout;
3641  }
3642  num_ready = MHD_SYS_select_ (maxsock + 1,
3643  &rs,
3644  &ws,
3645  &es,
3646  tv);
3647  if (daemon->shutdown)
3648  return MHD_NO;
3649  if (num_ready < 0)
3650  {
3651  const int err = MHD_socket_get_error_ ();
3652  if (MHD_SCKT_ERR_IS_EINTR_(err))
3653  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3654 #ifdef HAVE_MESSAGES
3655  MHD_DLOG (daemon,
3656  _("select failed: %s\n"),
3657  MHD_socket_strerr_ (err));
3658 #endif
3659  return MHD_NO;
3660  }
3661  if (MHD_YES == internal_run_from_select (daemon,
3662  &rs,
3663  &ws,
3664  &es))
3665  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
3666  return MHD_NO;
3667 }
3668 
3669 
3670 #ifdef HAVE_POLL
3671 
3679 static int
3680 MHD_poll_all (struct MHD_Daemon *daemon,
3681  int may_block)
3682 {
3683  unsigned int num_connections;
3684  struct MHD_Connection *pos;
3685  struct MHD_Connection *prev;
3686 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3687  struct MHD_UpgradeResponseHandle *urh;
3688  struct MHD_UpgradeResponseHandle *urhn;
3689 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3690 
3691  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
3692  (MHD_YES == resume_suspended_connections (daemon)) )
3693  may_block = MHD_NO;
3694 
3695  /* count number of connections and thus determine poll set size */
3696  num_connections = 0;
3697  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3698  num_connections++;
3699 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3700  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3701  num_connections += 2;
3702 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3703  {
3704  MHD_UNSIGNED_LONG_LONG ltimeout;
3705  unsigned int i;
3706  int timeout;
3707  unsigned int poll_server;
3708  int poll_listen;
3709  int poll_itc_idx;
3710  struct pollfd *p;
3711  MHD_socket ls;
3712 
3713  p = MHD_calloc_ ((2 + num_connections), sizeof (struct pollfd));
3714  if (NULL == p)
3715  {
3716 #ifdef HAVE_MESSAGES
3717  MHD_DLOG (daemon,
3718  _("Error allocating memory: %s\n"),
3719  MHD_strerror_(errno));
3720 #endif
3721  return MHD_NO;
3722  }
3723  poll_server = 0;
3724  poll_listen = -1;
3725  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3726  (! daemon->was_quiesced) &&
3727  (daemon->connections < daemon->connection_limit) &&
3728  (! daemon->at_limit) )
3729  {
3730  /* only listen if we are not at the connection limit */
3731  p[poll_server].fd = ls;
3732  p[poll_server].events = POLLIN;
3733  p[poll_server].revents = 0;
3734  poll_listen = (int) poll_server;
3735  poll_server++;
3736  }
3737  poll_itc_idx = -1;
3738  if (MHD_ITC_IS_VALID_(daemon->itc))
3739  {
3740  p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3741  p[poll_server].events = POLLIN;
3742  p[poll_server].revents = 0;
3743  poll_itc_idx = (int) poll_server;
3744  poll_server++;
3745  }
3746  if (may_block == MHD_NO)
3747  timeout = 0;
3748  else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3749  (MHD_YES != MHD_get_timeout (daemon,
3750  &ltimeout)) )
3751  timeout = -1;
3752  else
3753  timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3754 
3755  i = 0;
3756  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
3757  {
3758  p[poll_server+i].fd = pos->socket_fd;
3759  switch (pos->event_loop_info)
3760  {
3762  p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3763  break;
3765  p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3766  break;
3768  p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3769  break;
3771  timeout = 0; /* clean up "pos" immediately */
3772  break;
3773  }
3774  i++;
3775  }
3776 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3777  for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3778  {
3779  urh_to_pollfd(urh, &(p[poll_server+i]));
3780  i += 2;
3781  }
3782 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3783  if (0 == poll_server + num_connections)
3784  {
3785  free(p);
3786  return MHD_YES;
3787  }
3788  if (MHD_sys_poll_(p,
3789  poll_server + num_connections,
3790  timeout) < 0)
3791  {
3792  const int err = MHD_socket_get_error_ ();
3793  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3794  {
3795  free(p);
3796  return MHD_YES;
3797  }
3798 #ifdef HAVE_MESSAGES
3799  MHD_DLOG (daemon,
3800  _("poll failed: %s\n"),
3801  MHD_socket_strerr_ (err));
3802 #endif
3803  free(p);
3804  return MHD_NO;
3805  }
3806 
3807  /* Reset. New value will be set when connections are processed. */
3808  daemon->data_already_pending = false;
3809 
3810  /* handle ITC FD */
3811  /* do it before any other processing so
3812  new signals will be processed in next loop */
3813  if ( (-1 != poll_itc_idx) &&
3814  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3815  MHD_itc_clear_ (daemon->itc);
3816 
3817  /* handle shutdown */
3818  if (daemon->shutdown)
3819  {
3820  free(p);
3821  return MHD_NO;
3822  }
3823  i = 0;
3824  prev = daemon->connections_tail;
3825  while (NULL != (pos = prev))
3826  {
3827  prev = pos->prev;
3828  /* first, sanity checks */
3829  if (i >= num_connections)
3830  break; /* connection list changed somehow, retry later ... */
3831  if (p[poll_server+i].fd != pos->socket_fd)
3832  continue; /* fd mismatch, something else happened, retry later ... */
3833  call_handlers (pos,
3834  0 != (p[poll_server+i].revents & POLLIN),
3835  0 != (p[poll_server+i].revents & POLLOUT),
3836  0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
3837  i++;
3838  }
3839 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3840  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
3841  {
3842  if (i >= num_connections)
3843  break; /* connection list changed somehow, retry later ... */
3844 
3845  /* Get next connection here as connection can be removed
3846  * from 'daemon->urh_head' list. */
3847  urhn = urh->prev;
3848  /* Check for fd mismatch. FIXME: required for safety? */
3849  if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3850  (p[poll_server+i+1].fd != urh->mhd.socket))
3851  break;
3852  urh_from_pollfd(urh, &(p[poll_server+i]));
3853  i += 2;
3854  process_urh (urh);
3855  /* Finished forwarding? */
3856  if ( (0 == urh->in_buffer_size) &&
3857  (0 == urh->out_buffer_size) &&
3858  (0 == urh->in_buffer_used) &&
3859  (0 == urh->out_buffer_used) )
3860  {
3861  /* MHD_connection_finish_forward_() will remove connection from
3862  * 'daemon->urh_head' list. */
3863  MHD_connection_finish_forward_ (urh->connection);
3864  urh->clean_ready = true;
3865  /* If 'urh->was_closed' already was set to true, connection will be
3866  * moved immediately to cleanup list. Otherwise connection
3867  * will stay in suspended list until 'urh' will be marked
3868  * with 'was_closed' by application. */
3869  MHD_resume_connection(urh->connection);
3870  }
3871  }
3872 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3873  /* handle 'listen' FD */
3874  if ( (-1 != poll_listen) &&
3875  (0 != (p[poll_listen].revents & POLLIN)) )
3876  (void) MHD_accept_connection (daemon);
3877 
3878  free(p);
3879  }
3880  return MHD_YES;
3881 }
3882 
3883 
3891 static int
3892 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3893  int may_block)
3894 {
3895  struct pollfd p[2];
3896  int timeout;
3897  unsigned int poll_count;
3898  int poll_listen;
3899  int poll_itc_idx;
3900  MHD_socket ls;
3901 
3902  memset (&p,
3903  0,
3904  sizeof (p));
3905  poll_count = 0;
3906  poll_listen = -1;
3907  poll_itc_idx = -1;
3908  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
3909  (! daemon->was_quiesced) )
3910 
3911  {
3912  p[poll_count].fd = ls;
3913  p[poll_count].events = POLLIN;
3914  p[poll_count].revents = 0;
3915  poll_listen = poll_count;
3916  poll_count++;
3917  }
3918  if (MHD_ITC_IS_VALID_(daemon->itc))
3919  {
3920  p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
3921  p[poll_count].events = POLLIN;
3922  p[poll_count].revents = 0;
3923  poll_itc_idx = poll_count;
3924  poll_count++;
3925  }
3926 
3927  if (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
3928  (void)resume_suspended_connections (daemon);
3929 
3930  if (MHD_NO == may_block)
3931  timeout = 0;
3932  else
3933  timeout = -1;
3934  if (0 == poll_count)
3935  return MHD_YES;
3936  if (MHD_sys_poll_(p,
3937  poll_count,
3938  timeout) < 0)
3939  {
3940  const int err = MHD_socket_get_error_ ();
3941 
3942  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3943  return MHD_YES;
3944 #ifdef HAVE_MESSAGES
3945  MHD_DLOG (daemon,
3946  _("poll failed: %s\n"),
3947  MHD_socket_strerr_ (err));
3948 #endif
3949  return MHD_NO;
3950  }
3951  if ( (-1 != poll_itc_idx) &&
3952  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3953  MHD_itc_clear_ (daemon->itc);
3954 
3955  /* handle shutdown */
3956  if (daemon->shutdown)
3957  return MHD_NO;
3958  if ( (-1 != poll_listen) &&
3959  (0 != (p[poll_listen].revents & POLLIN)) )
3960  (void) MHD_accept_connection (daemon);
3961  return MHD_YES;
3962 }
3963 #endif
3964 
3965 
3973 static int
3974 MHD_poll (struct MHD_Daemon *daemon,
3975  int may_block)
3976 {
3977 #ifdef HAVE_POLL
3978  if (daemon->shutdown)
3979  return MHD_NO;
3980  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3981  return MHD_poll_all (daemon,
3982  may_block);
3983  return MHD_poll_listen_socket (daemon,
3984  may_block);
3985 #else
3986  return MHD_NO;
3987 #endif
3988 }
3989 
3990 
3991 #ifdef EPOLL_SUPPORT
3992 
4001 #define MAX_EVENTS 128
4002 
4003 
4004 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4005 
4013 static bool
4014 is_urh_ready(struct MHD_UpgradeResponseHandle * const urh)
4015 {
4016  const struct MHD_Connection * const connection = urh->connection;
4017 
4018  if ( (0 == urh->in_buffer_size) &&
4019  (0 == urh->out_buffer_size) &&
4020  (0 == urh->in_buffer_used) &&
4021  (0 == urh->out_buffer_used) )
4022  return false;
4023 
4024  if (connection->daemon->shutdown)
4025  return true;
4026 
4027  if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
4028  (connection->tls_read_ready) ) &&
4029  (urh->in_buffer_used < urh->in_buffer_size) )
4030  return true;
4031 
4032  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
4033  (urh->out_buffer_used < urh->out_buffer_size) )
4034  return true;
4035 
4036  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
4037  (urh->out_buffer_used > 0) )
4038  return true;
4039 
4040  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
4041  (urh->in_buffer_used > 0) )
4042  return true;
4043 
4044  return false;
4045 }
4046 
4055 static int
4056 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4057 {
4058  struct epoll_event events[MAX_EVENTS];
4059  int num_events;
4060  struct MHD_UpgradeResponseHandle * pos;
4061  struct MHD_UpgradeResponseHandle * prev;
4062 
4063  num_events = MAX_EVENTS;
4064  while (MAX_EVENTS == num_events)
4065  {
4066  unsigned int i;
4067  /* update event masks */
4068  num_events = epoll_wait (daemon->epoll_upgrade_fd,
4069  events,
4070  MAX_EVENTS,
4071  0);
4072  if (-1 == num_events)
4073  {
4074  const int err = MHD_socket_get_error_ ();
4075  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4076  return MHD_YES;
4077 #ifdef HAVE_MESSAGES
4078  MHD_DLOG (daemon,
4079  _("Call to epoll_wait failed: %s\n"),
4080  MHD_socket_strerr_ (err));
4081 #endif
4082  return MHD_NO;
4083  }
4084  for (i = 0; i < (unsigned int) num_events; i++)
4085  {
4086  struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
4087  struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
4088  bool new_err_state = false;
4089 
4090  if (urh->clean_ready)
4091  continue;
4092 
4093  /* Update ueh state based on what is ready according to epoll() */
4094  if (0 != (events[i].events & EPOLLIN))
4095  ueh->celi |= MHD_EPOLL_STATE_READ_READY;
4096  if (0 != (events[i].events & EPOLLOUT))
4097  ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
4098  if (0 != (events[i].events & EPOLLHUP))
4100 
4101  if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4102  (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4103  {
4104  /* Process new error state only one time
4105  * and avoid continuously marking this connection
4106  * as 'ready'. */
4107  ueh->celi |= MHD_EPOLL_STATE_ERROR;
4108  new_err_state = true;
4109  }
4110 
4111  if (! urh->in_eready_list)
4112  {
4113  if (new_err_state ||
4114  is_urh_ready(urh))
4115  {
4116  EDLL_insert (daemon->eready_urh_head,
4117  daemon->eready_urh_tail,
4118  urh);
4119  urh->in_eready_list = true;
4120  }
4121  }
4122  }
4123  }
4124  prev = daemon->eready_urh_tail;
4125  while (NULL != (pos = prev))
4126  {
4127  prev = pos->prevE;
4128  process_urh (pos);
4129  if (! is_urh_ready(pos))
4130  {
4131  EDLL_remove (daemon->eready_urh_head,
4132  daemon->eready_urh_tail,
4133  pos);
4134  pos->in_eready_list = false;
4135  }
4136  /* Finished forwarding? */
4137  if ( (0 == pos->in_buffer_size) &&
4138  (0 == pos->out_buffer_size) &&
4139  (0 == pos->in_buffer_used) &&
4140  (0 == pos->out_buffer_used) )
4141  {
4142  MHD_connection_finish_forward_ (pos->connection);
4143  pos->clean_ready = true;
4144  /* If 'pos->was_closed' already was set to true, connection
4145  * will be moved immediately to cleanup list. Otherwise
4146  * connection will stay in suspended list until 'pos' will
4147  * be marked with 'was_closed' by application. */
4148  MHD_resume_connection(pos->connection);
4149  }
4150  }
4151 
4152  return MHD_YES;
4153 }
4154 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4155 
4159 static const char * const epoll_itc_marker = "itc_marker";
4160 
4169 static int
4170 MHD_epoll (struct MHD_Daemon *daemon,
4171  int may_block)
4172 {
4173 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4174  static const char * const upgrade_marker = "upgrade_ptr";
4175 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4176  struct MHD_Connection *pos;
4177  struct MHD_Connection *prev;
4178  struct epoll_event events[MAX_EVENTS];
4179  struct epoll_event event;
4180  int timeout_ms;
4181  MHD_UNSIGNED_LONG_LONG timeout_ll;
4182  int num_events;
4183  unsigned int i;
4184  MHD_socket ls;
4185 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4186  int run_upgraded = MHD_NO;
4187 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4188 
4189  if (-1 == daemon->epoll_fd)
4190  return MHD_NO; /* we're down! */
4191  if (daemon->shutdown)
4192  return MHD_NO;
4193  if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) &&
4194  (! daemon->was_quiesced) &&
4195  (daemon->connections < daemon->connection_limit) &&
4196  (! daemon->listen_socket_in_epoll) &&
4197  (! daemon->at_limit) )
4198  {
4199  event.events = EPOLLIN;
4200  event.data.ptr = daemon;
4201  if (0 != epoll_ctl (daemon->epoll_fd,
4202  EPOLL_CTL_ADD,
4203  ls,
4204  &event))
4205  {
4206 #ifdef HAVE_MESSAGES
4207  MHD_DLOG (daemon,
4208  _("Call to epoll_ctl failed: %s\n"),
4210 #endif
4211  return MHD_NO;
4212  }
4213  daemon->listen_socket_in_epoll = true;
4214  }
4215  if ( (daemon->was_quiesced) &&
4216  (daemon->listen_socket_in_epoll) )
4217  {
4218  if (0 != epoll_ctl (daemon->epoll_fd,
4219  EPOLL_CTL_DEL,
4220  ls,
4221  NULL))
4222  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4223  daemon->listen_socket_in_epoll = false;
4224  }
4225 
4226 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4227  if ( (! daemon->upgrade_fd_in_epoll) &&
4228  (-1 != daemon->epoll_upgrade_fd) )
4229  {
4230  event.events = EPOLLIN | EPOLLOUT;
4231  event.data.ptr = (void *) upgrade_marker;
4232  if (0 != epoll_ctl (daemon->epoll_fd,
4233  EPOLL_CTL_ADD,
4234  daemon->epoll_upgrade_fd,
4235  &event))
4236  {
4237 #ifdef HAVE_MESSAGES
4238  MHD_DLOG (daemon,
4239  _("Call to epoll_ctl failed: %s\n"),
4241 #endif
4242  return MHD_NO;
4243  }
4244  daemon->upgrade_fd_in_epoll = true;
4245  }
4246 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4247  if ( (daemon->listen_socket_in_epoll) &&
4248  ( (daemon->connections == daemon->connection_limit) ||
4249  (daemon->at_limit) ||
4250  (daemon->was_quiesced) ) )
4251  {
4252  /* we're at the connection limit, disable listen socket
4253  for event loop for now */
4254  if (0 != epoll_ctl (daemon->epoll_fd,
4255  EPOLL_CTL_DEL,
4256  ls,
4257  NULL))
4258  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4259  daemon->listen_socket_in_epoll = false;
4260  }
4261 
4262  if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
4263  (MHD_YES == resume_suspended_connections (daemon)) )
4264  may_block = MHD_NO;
4265 
4266  if (MHD_YES == may_block)
4267  {
4268  if (MHD_YES == MHD_get_timeout (daemon,
4269  &timeout_ll))
4270  {
4271  if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4272  timeout_ms = INT_MAX;
4273  else
4274  timeout_ms = (int) timeout_ll;
4275  }
4276  else
4277  timeout_ms = -1;
4278  }
4279  else
4280  timeout_ms = 0;
4281 
4282  /* Reset. New value will be set when connections are processed. */
4283  /* Note: Used mostly for uniformity here as same situation is
4284  * signaled in epoll mode by non-empty eready DLL. */
4285  daemon->data_already_pending = false;
4286 
4287  /* drain 'epoll' event queue; need to iterate as we get at most
4288  MAX_EVENTS in one system call here; in practice this should
4289  pretty much mean only one round, but better an extra loop here
4290  than unfair behavior... */
4291  num_events = MAX_EVENTS;
4292  while (MAX_EVENTS == num_events)
4293  {
4294  /* update event masks */
4295  num_events = epoll_wait (daemon->epoll_fd,
4296  events,
4297  MAX_EVENTS,
4298  timeout_ms);
4299  if (-1 == num_events)
4300  {
4301  const int err = MHD_socket_get_error_ ();
4302  if (MHD_SCKT_ERR_IS_EINTR_ (err))
4303  return MHD_YES;
4304 #ifdef HAVE_MESSAGES
4305  MHD_DLOG (daemon,
4306  _("Call to epoll_wait failed: %s\n"),
4307  MHD_socket_strerr_ (err));
4308 #endif
4309  return MHD_NO;
4310  }
4311  for (i=0;i<(unsigned int) num_events;i++)
4312  {
4313  /* First, check for the values of `ptr` that would indicate
4314  that this event is not about a normal connection. */
4315  if (NULL == events[i].data.ptr)
4316  continue; /* shutdown signal! */
4317 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4318  if (upgrade_marker == events[i].data.ptr)
4319  {
4320  /* activity on an upgraded connection, we process
4321  those in a separate epoll() */
4322  run_upgraded = MHD_YES;
4323  continue;
4324  }
4325 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4326  if (epoll_itc_marker == events[i].data.ptr)
4327  {
4328  /* It's OK to clear ITC here as all external
4329  conditions will be processed later. */
4330  MHD_itc_clear_ (daemon->itc);
4331  continue;
4332  }
4333  if (daemon == events[i].data.ptr)
4334  {
4335  /* Check for error conditions on listen socket. */
4336  /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4337  if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4338  {
4339  unsigned int series_length = 0;
4340  /* Run 'accept' until it fails or daemon at limit of connections.
4341  * Do not accept more then 10 connections at once. The rest will
4342  * be accepted on next turn (level trigger is used for listen
4343  * socket). */
4344  while ( (MHD_YES == MHD_accept_connection (daemon)) &&
4345  (series_length < 10) &&
4346  (daemon->connections < daemon->connection_limit) &&
4347  (! daemon->at_limit) )
4348  series_length++;
4349  }
4350  continue;
4351  }
4352  /* this is an event relating to a 'normal' connection,
4353  remember the event and if appropriate mark the
4354  connection as 'eready'. */
4355  pos = events[i].data.ptr;
4356  /* normal processing: update read/write data */
4357  if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4358  {
4359  pos->epoll_state |= MHD_EPOLL_STATE_ERROR;
4360  if (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
4361  {
4362  EDLL_insert (daemon->eready_head,
4363  daemon->eready_tail,
4364  pos);
4365  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4366  }
4367  }
4368  else
4369  {
4370  if (0 != (events[i].events & EPOLLIN))
4371  {
4372  pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
4373  if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
4374  (pos->read_buffer_size > pos->read_buffer_offset) ) &&
4375  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4376  {
4377  EDLL_insert (daemon->eready_head,
4378  daemon->eready_tail,
4379  pos);
4380  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4381  }
4382  }
4383  if (0 != (events[i].events & EPOLLOUT))
4384  {
4385  pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
4386  if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
4387  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
4388  {
4389  EDLL_insert (daemon->eready_head,
4390  daemon->eready_tail,
4391  pos);
4392  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
4393  }
4394  }
4395  }
4396  }
4397  }
4398 
4399 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4400  if (MHD_YES == run_upgraded)
4401  run_epoll_for_upgrade (daemon);
4402 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4403 
4404  /* process events for connections */
4405  prev = daemon->eready_tail;
4406  while (NULL != (pos = prev))
4407  {
4408  prev = pos->prevE;
4409  call_handlers (pos,
4410  0 != (pos->epoll_state & MHD_EPOLL_STATE_READ_READY),
4411  0 != (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY),
4412  0 != (pos->epoll_state & MHD_EPOLL_STATE_ERROR));
4415  {
4416  if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info &&
4417  0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ) ||
4419  0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ) ||
4421  {
4422  EDLL_remove (daemon->eready_head,
4423  daemon->eready_tail,
4424  pos);
4425  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4426  }
4427  }
4428  }
4429 
4430  /* Finally, handle timed-out connections; we need to do this here
4431  as the epoll mechanism won't call the 'idle_handler' on everything,
4432  as the other event loops do. As timeouts do not get an explicit
4433  event, we need to find those connections that might have timed out
4434  here.
4435 
4436  Connections with custom timeouts must all be looked at, as we
4437  do not bother to sort that (presumably very short) list. */
4438  prev = daemon->manual_timeout_tail;
4439  while (NULL != (pos = prev))
4440  {
4441  prev = pos->prevX;
4442  pos->idle_handler (pos);
4443  }
4444  /* Connections with the default timeout are sorted by prepending
4445  them to the head of the list whenever we touch the connection;
4446  thus it suffices to iterate from the tail until the first
4447  connection is NOT timed out */
4448  prev = daemon->normal_timeout_tail;
4449  while (NULL != (pos = prev))
4450  {
4451  prev = pos->prevX;
4452  pos->idle_handler (pos);
4453  if (MHD_CONNECTION_CLOSED != pos->state)
4454  break; /* sorted by timeout, no need to visit the rest! */
4455  }
4456  return MHD_YES;
4457 }
4458 #endif
4459 
4460 
4480 int
4481 MHD_run (struct MHD_Daemon *daemon)
4482 {
4483  if ( (daemon->shutdown) ||
4484  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4485  return MHD_NO;
4486  if (0 != (daemon->options & MHD_USE_POLL))
4487  {
4488  MHD_poll (daemon, MHD_NO);
4489  MHD_cleanup_connections (daemon);
4490  }
4491 #ifdef EPOLL_SUPPORT
4492  else if (0 != (daemon->options & MHD_USE_EPOLL))
4493  {
4494  MHD_epoll (daemon, MHD_NO);
4495  MHD_cleanup_connections (daemon);
4496  }
4497 #endif
4498  else
4499  {
4500  MHD_select (daemon, MHD_NO);
4501  /* MHD_select does MHD_cleanup_connections already */
4502  }
4503  return MHD_YES;
4504 }
4505 
4506 
4515 static void
4517 {
4518  struct MHD_Daemon *daemon = pos->daemon;
4519 
4520  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4521  {
4523  return; /* must let thread to do the rest */
4524  }
4525  MHD_connection_close_ (pos,
4527 
4529 
4530  EXTRA_CHECK (! pos->suspended);
4531  EXTRA_CHECK (! pos->resuming);
4532  if (pos->connection_timeout == pos->daemon->connection_timeout)
4534  daemon->normal_timeout_tail,
4535  pos);
4536  else
4538  daemon->manual_timeout_tail,
4539  pos);
4540  DLL_remove (daemon->connections_head,
4541  daemon->connections_tail,
4542  pos);
4543  DLL_insert (daemon->cleanup_head,
4544  daemon->cleanup_tail,
4545  pos);
4546 
4548 }
4549 
4550 
4558 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4560 {
4561  struct MHD_Daemon *daemon = cls;
4562 
4563  while (! daemon->shutdown)
4564  {
4565  if (0 != (daemon->options & MHD_USE_POLL))
4566  MHD_poll (daemon, MHD_YES);
4567 #ifdef EPOLL_SUPPORT
4568  else if (0 != (daemon->options & MHD_USE_EPOLL))
4569  MHD_epoll (daemon, MHD_YES);
4570 #endif
4571  else
4572  MHD_select (daemon, MHD_YES);
4573  MHD_cleanup_connections (daemon);
4574  }
4575 
4576  /* Resume any pending for resume connections, join
4577  * all connection's threads (if any) and finally cleanup
4578  * everything. */
4579  close_all_connections (daemon);
4580 
4581  return (MHD_THRD_RTRN_TYPE_)0;
4582 }
4583 
4584 
4596 static size_t
4597 unescape_wrapper (void *cls,
4598  struct MHD_Connection *connection,
4599  char *val)
4600 {
4601  return MHD_http_unescape (val);
4602 }
4603 
4604 
4621 struct MHD_Daemon *
4622 MHD_start_daemon (unsigned int flags,
4623  uint16_t port,
4625  void *apc_cls,
4627  void *dh_cls,
4628  ...)
4629 {
4630  struct MHD_Daemon *daemon;
4631  va_list ap;
4632 
4633  va_start (ap,
4634  dh_cls);
4635  daemon = MHD_start_daemon_va (flags,
4636  port,
4637  apc,
4638  apc_cls,
4639  dh,
4640  dh_cls,
4641  ap);
4642  va_end (ap);
4643  return daemon;
4644 }
4645 
4646 
4666 MHD_socket
4668 {
4669  unsigned int i;
4670  MHD_socket ret;
4671 
4672  ret = daemon->listen_fd;
4673  if (MHD_INVALID_SOCKET == ret)
4674  return MHD_INVALID_SOCKET;
4675  if ( (0 == (daemon->options & (MHD_USE_ITC))) &&
4676  (0 != (daemon->options & (MHD_USE_INTERNAL_POLLING_THREAD))) )
4677  {
4678 #ifdef HAVE_MESSAGES
4679  MHD_DLOG (daemon,
4680  "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
4681 #endif
4682  return MHD_INVALID_SOCKET;
4683  }
4684 
4685  if (NULL != daemon->worker_pool)
4686  for (i = 0; i < daemon->worker_pool_size; i++)
4687  {
4688  daemon->worker_pool[i].was_quiesced = true;
4689 #ifdef EPOLL_SUPPORT
4690  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4691  (-1 != daemon->worker_pool[i].epoll_fd) &&
4692  (daemon->worker_pool[i].listen_socket_in_epoll) )
4693  {
4694  if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4695  EPOLL_CTL_DEL,
4696  ret,
4697  NULL))
4698  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4699  daemon->worker_pool[i].listen_socket_in_epoll = false;
4700  }
4701  else
4702 #endif
4703  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
4704  {
4705  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4706  MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
4707  }
4708  }
4709  daemon->was_quiesced = true;
4710 #ifdef EPOLL_SUPPORT
4711  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4712  (-1 != daemon->epoll_fd) &&
4713  (daemon->listen_socket_in_epoll) )
4714  {
4715  if (0 != epoll_ctl (daemon->epoll_fd,
4716  EPOLL_CTL_DEL,
4717  ret,
4718  NULL))
4719  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4720  daemon->listen_socket_in_epoll = false;
4721  }
4722 #endif
4723  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
4724  (! MHD_itc_activate_ (daemon->itc, "q")) )
4725  MHD_PANIC (_("failed to signal quiesce via inter-thread communication channel"));
4726  return ret;
4727 }
4728 
4729 
4737 typedef void
4739  const char *format,
4740  va_list va);
4741 
4742 
4751 static int
4752 parse_options_va (struct MHD_Daemon *daemon,
4753  const struct sockaddr **servaddr,
4754  va_list ap);
4755 
4756 
4765 static int
4766 parse_options (struct MHD_Daemon *daemon,
4767  const struct sockaddr **servaddr,
4768  ...)
4769 {
4770  va_list ap;
4771  int ret;
4772 
4773  va_start (ap, servaddr);
4774  ret = parse_options_va (daemon,
4775  servaddr,
4776  ap);
4777  va_end (ap);
4778  return ret;
4779 }
4780 
4781 
4790 static int
4792  const struct sockaddr **servaddr,
4793  va_list ap)
4794 {
4795  enum MHD_OPTION opt;
4796  struct MHD_OptionItem *oa;
4797  unsigned int i;
4798  unsigned int uv;
4799 #ifdef HTTPS_SUPPORT
4800  int ret;
4801  const char *pstr;
4802 #endif /* HTTPS_SUPPORT */
4803 
4804  while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
4805  {
4806  switch (opt)
4807  {
4809  daemon->pool_size = va_arg (ap,
4810  size_t);
4811  break;
4813  daemon->pool_increment= va_arg (ap,
4814  size_t);
4815  break;
4817  daemon->connection_limit = va_arg (ap,
4818  unsigned int);
4819  break;
4821  uv = va_arg (ap,
4822  unsigned int);
4823  if (TIME_T_MAX < uv)
4824  {
4825 #ifdef HAVE_MESSAGES
4826  MHD_DLOG (daemon,
4827  _("Warning: Too large timeout value, ignored.\n"));
4828 #endif
4829  daemon->connection_timeout = 0;
4830  }
4831  else
4832  daemon->connection_timeout = (time_t)uv;
4833  break;
4835  daemon->notify_completed = va_arg (ap,
4837  daemon->notify_completed_cls = va_arg (ap,
4838  void *);
4839  break;
4841  daemon->notify_connection = va_arg (ap,
4843  daemon->notify_connection_cls = va_arg (ap,
4844  void *);
4845  break;
4847  daemon->per_ip_connection_limit = va_arg (ap,
4848  unsigned int);
4849  break;
4850  case MHD_OPTION_SOCK_ADDR:
4851  *servaddr = va_arg (ap,
4852  const struct sockaddr *);
4853  break;
4855  daemon->uri_log_callback = va_arg (ap,
4856  LogCallback);
4857  daemon->uri_log_callback_cls = va_arg (ap,
4858  void *);
4859  break;
4861  daemon->worker_pool_size = va_arg (ap,
4862  unsigned int);
4863  if (0 == daemon->worker_pool_size)
4864  {
4865 #ifdef HAVE_MESSAGES
4866  MHD_DLOG (daemon,
4867  _("Warning: Zero size, specified for thread pool size, is ignored. "
4868  "Thread pool is not used.\n"));
4869 #endif
4870  }
4871  else if (1 == daemon->worker_pool_size)
4872  {
4873 #ifdef HAVE_MESSAGES
4874  MHD_DLOG (daemon,
4875  _("Warning: \"1\", specified for thread pool size, is ignored. "
4876  "Thread pool is not used.\n"));
4877 #endif
4878  daemon->worker_pool_size = 0;
4879  }
4880  else if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct MHD_Daemon)))
4881  {
4882 #ifdef HAVE_MESSAGES
4883  MHD_DLOG (daemon,
4884  _("Specified thread pool size (%u) too big\n"),
4885  daemon->worker_pool_size);
4886 #endif
4887  return MHD_NO;
4888  }
4889  else
4890  {
4891  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
4892  {
4893 #ifdef HAVE_MESSAGES
4894  MHD_DLOG (daemon,
4895  _("MHD_OPTION_THREAD_POOL_SIZE option is specified but "
4896  "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
4897 #endif
4898  return MHD_NO;
4899  }
4900  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
4901  {
4902 #ifdef HAVE_MESSAGES
4903  MHD_DLOG (daemon,
4904  _("Both MHD_OPTION_THREAD_POOL_SIZE option and "
4905  "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
4906 #endif
4907  return MHD_NO;
4908  }
4909  }
4910  break;
4911 #ifdef HTTPS_SUPPORT
4913  if (0 != (daemon->options & MHD_USE_TLS))
4914  daemon->https_mem_key = va_arg (ap,
4915  const char *);
4916 #ifdef HAVE_MESSAGES
4917  else
4918  MHD_DLOG (daemon,
4919  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4920  opt);
4921 #endif
4922  break;
4924  if (0 != (daemon->options & MHD_USE_TLS))
4925  daemon->https_key_password = va_arg (ap,
4926  const char *);
4927 #ifdef HAVE_MESSAGES
4928  else
4929  MHD_DLOG (daemon,
4930  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4931  opt);
4932 #endif
4933  break;
4935  if (0 != (daemon->options & MHD_USE_TLS))
4936  daemon->https_mem_cert = va_arg (ap,
4937  const char *);
4938 #ifdef HAVE_MESSAGES
4939  else
4940  MHD_DLOG (daemon,
4941  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4942  opt);
4943 #endif
4944  break;
4946  if (0 != (daemon->options & MHD_USE_TLS))
4947  daemon->https_mem_trust = va_arg (ap,
4948  const char *);
4949 #ifdef HAVE_MESSAGES
4950  else
4951  MHD_DLOG (daemon,
4952  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4953  opt);
4954 #endif
4955  break;
4957  daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4958  int);
4959  break;
4961  if (0 != (daemon->options & MHD_USE_TLS))
4962  {
4963  const char *arg = va_arg (ap,
4964  const char *);
4965  gnutls_datum_t dhpar;
4966 
4967  if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4968  {
4969 #ifdef HAVE_MESSAGES
4970  MHD_DLOG (daemon,
4971  _("Error initializing DH parameters\n"));
4972 #endif
4973  return MHD_NO;
4974  }
4975  dhpar.data = (unsigned char *) arg;
4976  dhpar.size = strlen (arg);
4977  if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4978  &dhpar,
4979  GNUTLS_X509_FMT_PEM) < 0)
4980  {
4981 #ifdef HAVE_MESSAGES
4982  MHD_DLOG (daemon,
4983  _("Bad Diffie-Hellman parameters format\n"));
4984 #endif
4985  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4986  return MHD_NO;
4987  }
4988  daemon->have_dhparams = true;
4989  }
4990  else
4991  {
4992 #ifdef HAVE_MESSAGES
4993  MHD_DLOG (daemon,
4994  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4995  opt);
4996 #endif
4997  return MHD_NO;
4998  }
4999  break;
5001  if (0 != (daemon->options & MHD_USE_TLS))
5002  {
5003  gnutls_priority_deinit (daemon->priority_cache);
5004  ret = gnutls_priority_init (&daemon->priority_cache,
5005  pstr = va_arg (ap, const char*),
5006  NULL);
5007  if (GNUTLS_E_SUCCESS != ret)
5008  {
5009 #ifdef HAVE_MESSAGES
5010  MHD_DLOG (daemon,
5011  _("Setting priorities to `%s' failed: %s\n"),
5012  pstr,
5013  gnutls_strerror (ret));
5014 #endif
5015  daemon->priority_cache = NULL;
5016  return MHD_NO;
5017  }
5018  }
5019  break;
5021 #if GNUTLS_VERSION_MAJOR < 3
5022 #ifdef HAVE_MESSAGES
5023  MHD_DLOG (daemon,
5024  _("MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
5025 #endif
5026  return MHD_NO;
5027 #else
5028  if (0 != (daemon->options & MHD_USE_TLS))
5029  daemon->cert_callback = va_arg (ap,
5030  gnutls_certificate_retrieve_function2 *);
5031  break;
5032 #endif
5033 #endif /* HTTPS_SUPPORT */
5034 #ifdef DAUTH_SUPPORT
5036  daemon->digest_auth_rand_size = va_arg (ap,
5037  size_t);
5038  daemon->digest_auth_random = va_arg (ap,
5039  const char *);
5040  break;
5042  daemon->nonce_nc_size = va_arg (ap,
5043  unsigned int);
5044  break;
5045 #endif
5047  if (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET))
5048  {
5049 #ifdef HAVE_MESSAGES
5050  MHD_DLOG (daemon,
5051  _("MHD_OPTION_LISTEN_SOCKET specified for daemon "
5052  "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5053 #endif
5054  return MHD_NO;
5055  }
5056  else
5057  daemon->listen_fd = va_arg (ap,
5058  MHD_socket);
5059  break;
5061 #ifdef HAVE_MESSAGES
5062  daemon->custom_error_log = va_arg (ap,
5064  daemon->custom_error_log_cls = va_arg (ap,
5065  void *);
5066 #else
5067  va_arg (ap,
5069  va_arg (ap,
5070  void *);
5071 #endif
5072  break;
5074  daemon->thread_stack_size = va_arg (ap,
5075  size_t);
5076  break;
5077 #ifdef TCP_FASTOPEN
5079  daemon->fastopen_queue_size = va_arg (ap,
5080  unsigned int);
5081  break;
5082 #endif
5084  daemon->listening_address_reuse = va_arg (ap,
5085  unsigned int) ? 1 : -1;
5086  break;
5088  daemon->listen_backlog_size = va_arg (ap,
5089  unsigned int);
5090  break;
5092  daemon->strict_for_client = va_arg (ap, int);;
5093 #ifdef HAVE_MESSAGES
5094  if ( (0 != (daemon->options & MHD_USE_PEDANTIC_CHECKS)) &&
5095  (1 != daemon->strict_for_client) )
5096  {
5097  MHD_DLOG (daemon,
5098  _("Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5099  "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5100  }
5101 #endif /* HAVE_MESSAGES */
5102  break;
5103  case MHD_OPTION_ARRAY:
5104  oa = va_arg (ap, struct MHD_OptionItem*);
5105  i = 0;
5106  while (MHD_OPTION_END != (opt = oa[i].option))
5107  {
5108  switch (opt)
5109  {
5110  /* all options taking 'size_t' */
5114  if (MHD_YES != parse_options (daemon,
5115  servaddr,
5116  opt,
5117  (size_t) oa[i].value,
5118  MHD_OPTION_END))
5119  return MHD_NO;
5120  break;
5121  /* all options taking 'unsigned int' */
5130  if (MHD_YES != parse_options (daemon,
5131  servaddr,
5132  opt,
5133  (unsigned int) oa[i].value,
5134  MHD_OPTION_END))
5135  return MHD_NO;
5136  break;
5137  /* all options taking 'enum' */
5138 #ifdef HTTPS_SUPPORT
5140  if (MHD_YES != parse_options (daemon,
5141  servaddr,
5142  opt,
5143  (gnutls_credentials_type_t) oa[i].value,
5144  MHD_OPTION_END))
5145  return MHD_NO;
5146  break;
5147 #endif /* HTTPS_SUPPORT */
5148  /* all options taking 'MHD_socket' */
5150  if (MHD_YES != parse_options (daemon,
5151  servaddr,
5152  opt,
5153  (MHD_socket) oa[i].value,
5154  MHD_OPTION_END))
5155  return MHD_NO;
5156  break;
5157  /* all options taking 'int' */
5159  if (MHD_YES != parse_options (daemon,
5160  servaddr,
5161  opt,
5162  (int) oa[i].value,
5163  MHD_OPTION_END))
5164  return MHD_NO;
5165  break;
5166  /* all options taking one pointer */
5167  case MHD_OPTION_SOCK_ADDR:
5174  case MHD_OPTION_ARRAY:
5176  if (MHD_YES != parse_options (daemon,
5177  servaddr,
5178  opt,
5179  oa[i].ptr_value,
5180  MHD_OPTION_END))
5181  return MHD_NO;
5182  break;
5183  /* all options taking two pointers */
5189  if (MHD_YES != parse_options (daemon,
5190  servaddr,
5191  opt,
5192  (void *) oa[i].value,
5193  oa[i].ptr_value,
5194  MHD_OPTION_END))
5195  return MHD_NO;
5196  break;
5197  /* options taking size_t-number followed by pointer */
5199  if (MHD_YES != parse_options (daemon,
5200  servaddr,
5201  opt,
5202  (size_t) oa[i].value,
5203  oa[i].ptr_value,
5204  MHD_OPTION_END))
5205  return MHD_NO;
5206  break;
5207  default:
5208  return MHD_NO;
5209  }
5210  i++;
5211  }
5212  break;
5214  daemon->unescape_callback = va_arg (ap,
5216  daemon->unescape_callback_cls = va_arg (ap,
5217  void *);
5218  break;
5219  default:
5220 #ifdef HAVE_MESSAGES
5221  if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
5222  (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
5223  (opt == MHD_OPTION_HTTPS_MEM_TRUST))
5224  {
5225  MHD_DLOG (daemon,
5226  _("MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
5227  opt);
5228  }
5229  else
5230  {
5231  MHD_DLOG (daemon,
5232  _("Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
5233  opt);
5234  }
5235 #endif
5236  return MHD_NO;
5237  }
5238  }
5239  return MHD_YES;
5240 }
5241 
5242 
5243 #ifdef EPOLL_SUPPORT
5244 static int
5245 setup_epoll_fd (struct MHD_Daemon *daemon)
5246 {
5247  int fd;
5248 
5249 #ifdef USE_EPOLL_CREATE1
5250  fd = epoll_create1 (EPOLL_CLOEXEC);
5251 #else /* ! USE_EPOLL_CREATE1 */
5252  fd = epoll_create (MAX_EVENTS);
5253 #endif /* ! USE_EPOLL_CREATE1 */
5254  if (MHD_INVALID_SOCKET == fd)
5255  {
5256 #ifdef HAVE_MESSAGES
5257  MHD_DLOG (daemon,
5258  _("Call to epoll_create1 failed: %s\n"),
5260 #endif
5261  return MHD_INVALID_SOCKET;
5262  }
5263 #if !defined(USE_EPOLL_CREATE1)
5264  if (! MHD_socket_noninheritable_ (fd))
5265  {
5266 #ifdef HAVE_MESSAGES
5267  MHD_DLOG (daemon,
5268  _("Failed to set noninheritable mode on epoll FD.\n"));
5269 #endif
5270  }
5271 #endif /* ! USE_EPOLL_CREATE1 */
5272  return fd;
5273 }
5274 
5275 
5285 static int
5286 setup_epoll_to_listen (struct MHD_Daemon *daemon)
5287 {
5288  struct epoll_event event;
5289  MHD_socket ls;
5290 
5291  daemon->epoll_fd = setup_epoll_fd (daemon);
5292  if (-1 == daemon->epoll_fd)
5293  return MHD_NO;
5294 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5295  if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
5296  {
5297  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5298  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
5299  return MHD_NO;
5300  }
5301 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5302  if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
5303  (daemon->was_quiesced) )
5304  return MHD_YES; /* non-listening daemon */
5305  event.events = EPOLLIN;
5306  event.data.ptr = daemon;
5307  if (0 != epoll_ctl (daemon->epoll_fd,
5308  EPOLL_CTL_ADD,
5309  ls,
5310  &event))
5311  {
5312 #ifdef HAVE_MESSAGES
5313  MHD_DLOG (daemon,
5314  _("Call to epoll_ctl failed: %s\n"),
5316 #endif
5317  return MHD_NO;
5318  }
5319  daemon->listen_socket_in_epoll = true;
5320  if (MHD_ITC_IS_VALID_(daemon->itc))
5321  {
5322  event.events = EPOLLIN;
5323  event.data.ptr = (void *) epoll_itc_marker;
5324  if (0 != epoll_ctl (daemon->epoll_fd,
5325  EPOLL_CTL_ADD,
5326  MHD_itc_r_fd_ (daemon->itc),
5327  &event))
5328  {
5329 #ifdef HAVE_MESSAGES
5330  MHD_DLOG (daemon,
5331  _("Call to epoll_ctl failed: %s\n"),
5333 #endif
5334  return MHD_NO;
5335  }
5336  }
5337  return MHD_YES;
5338 }
5339 #endif
5340 
5341 
5359 struct MHD_Daemon *
5360 MHD_start_daemon_va (unsigned int flags,
5361  uint16_t port,
5363  void *apc_cls,
5365  void *dh_cls,
5366  va_list ap)
5367 {
5368  const MHD_SCKT_OPT_BOOL_ on = 1;
5369  struct MHD_Daemon *daemon;
5371  struct sockaddr_in servaddr4;
5372 #if HAVE_INET6
5373  struct sockaddr_in6 servaddr6;
5374 #endif
5375  const struct sockaddr *servaddr = NULL;
5376  socklen_t addrlen;
5377  unsigned int i;
5378  enum MHD_FLAG eflags; /* same type as in MHD_Daemon */
5379  enum MHD_FLAG *pflags;
5380 
5381  eflags = (enum MHD_FLAG) flags;
5382  pflags = &eflags;
5383 #ifndef HAVE_INET6
5384  if (0 != (*pflags & MHD_USE_IPv6))
5385  return NULL;
5386 #endif
5387 #ifndef HAVE_POLL
5388  if (0 != (*pflags & MHD_USE_POLL))
5389  return NULL;
5390 #endif
5391 #ifndef EPOLL_SUPPORT
5392  if (0 != (*pflags & MHD_USE_EPOLL))
5393  return NULL;
5394 #endif /* ! EPOLL_SUPPORT */
5395 #ifndef HTTPS_SUPPORT
5396  if (0 != (*pflags & MHD_USE_TLS))
5397  return NULL;
5398 #endif /* ! HTTPS_SUPPORT */
5399 #ifndef TCP_FASTOPEN
5400  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5401  return NULL;
5402 #endif
5403  if (0 != (*pflags & MHD_ALLOW_UPGRADE))
5404  {
5405 #ifdef UPGRADE_SUPPORT
5406  *pflags |= MHD_ALLOW_SUSPEND_RESUME;
5407 #else /* ! UPGRADE_SUPPORT */
5408  return NULL;
5409 #endif /* ! UPGRADE_SUPPORT */
5410  }
5411  if (NULL == dh)
5412  return NULL;
5413 
5414  /* Check for invalid combinations of flags. */
5415  if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5416  ((0 != (*pflags & MHD_USE_EPOLL)) && (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))) ||
5417  ((0 != (*pflags & MHD_USE_POLL)) &&
5419  ((0 != (*pflags & MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)))) )
5420  return NULL;
5421 
5422  if (0 != (*pflags & MHD_USE_AUTO))
5423  {
5424  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5425  {
5426  /* Thread per connection with internal polling thread. */
5427 #ifdef HAVE_POLL
5428  *pflags |= MHD_USE_POLL;
5429 #else /* ! HAVE_POLL */
5430  /* use select() - do not modify flags */
5431 #endif /* ! HAVE_POLL */
5432  }
5433  else if (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5434  {
5435  /* Internal polling thread. */
5436 #if defined(EPOLL_SUPPORT)
5437  *pflags |= MHD_USE_EPOLL;
5438 #elif defined(HAVE_POLL)
5439  *pflags |= MHD_USE_POLL;
5440 #else /* !HAVE_POLL && !EPOLL_SUPPORT */
5441  /* use select() - do not modify flags */
5442 #endif /* !HAVE_POLL && !EPOLL_SUPPORT */
5443  }
5444  else
5445  {
5446  /* Internal threads are not used - "external" polling mode. */
5447 #if defined(EPOLL_SUPPORT)
5448  *pflags |= MHD_USE_EPOLL;
5449 #else /* ! EPOLL_SUPPORT */
5450  /* use select() - do not modify flags */
5451 #endif /* ! EPOLL_SUPPORT */
5452  }
5453  }
5454 
5455  if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon))))
5456  return NULL;
5457 #ifdef EPOLL_SUPPORT
5458  daemon->epoll_fd = -1;
5459 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5460  daemon->epoll_upgrade_fd = -1;
5461 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
5462 #endif
5463  /* try to open listen socket */
5464 #ifdef HTTPS_SUPPORT
5465  daemon->priority_cache = NULL;
5466  if (0 != (*pflags & MHD_USE_TLS))
5467  {
5468  gnutls_priority_init (&daemon->priority_cache,
5469  "@SYSTEM",
5470  NULL);
5471  }
5472 #endif /* HTTPS_SUPPORT */
5473  daemon->listen_fd = MHD_INVALID_SOCKET;
5474  daemon->listening_address_reuse = 0;
5475  daemon->options = *pflags;
5476  pflags = &daemon->options;
5477  daemon->strict_for_client = (0 != (*pflags & MHD_USE_PEDANTIC_CHECKS)) ? 1 : 0;
5478  daemon->port = port;
5479  daemon->apc = apc;
5480  daemon->apc_cls = apc_cls;
5481  daemon->default_handler = dh;
5482  daemon->default_handler_cls = dh_cls;
5483  daemon->connections = 0;
5485  daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
5486  daemon->pool_increment = MHD_BUF_INC_SIZE;
5488  daemon->connection_timeout = 0; /* no timeout */
5489  MHD_itc_set_invalid_ (daemon->itc);
5490 #ifdef SOMAXCONN
5491  daemon->listen_backlog_size = SOMAXCONN;
5492 #else /* !SOMAXCONN */
5493  daemon->listen_backlog_size = 511; /* should be safe value */
5494 #endif /* !SOMAXCONN */
5495 #ifdef HAVE_MESSAGES
5496  daemon->custom_error_log = (MHD_LogCallback) &vfprintf;
5497  daemon->custom_error_log_cls = stderr;
5498 #endif
5499  if ( (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION)) &&
5500  (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) )
5501  {
5502 #ifdef HAVE_MESSAGES
5503  MHD_DLOG (daemon,
5504  _("Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5505  "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5506  "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5507 #endif
5509  }
5510  if (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD))
5511  *pflags &= ~MHD_USE_ITC; /* useless if we are using 'external' select */
5512  else
5513  {
5514 #ifdef HAVE_LISTEN_SHUTDOWN
5515  if (0 != (*pflags & MHD_USE_NO_LISTEN_SOCKET))
5516 #endif
5517  *pflags |= MHD_USE_ITC; /* yes, must use ITC to signal thread */
5518  }
5519 #ifdef DAUTH_SUPPORT
5520  daemon->digest_auth_rand_size = 0;
5521  daemon->digest_auth_random = NULL;
5522  daemon->nonce_nc_size = 4; /* tiny */
5523 #endif
5524 #ifdef HTTPS_SUPPORT
5525  if (0 != (*pflags & MHD_USE_TLS))
5526  {
5527  daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5528  }
5529 #endif /* HTTPS_SUPPORT */
5530 
5531 
5532  if (MHD_YES != parse_options_va (daemon,
5533  &servaddr,
5534  ap))
5535  {
5536 #ifdef HTTPS_SUPPORT
5537  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5538  (NULL != daemon->priority_cache) )
5539  gnutls_priority_deinit (daemon->priority_cache);
5540 #endif /* HTTPS_SUPPORT */
5541  free (daemon);
5542  return NULL;
5543  }
5544  if ( (0 != (*pflags & MHD_USE_ITC)) &&
5545  (0 == daemon->worker_pool_size) )
5546  {
5547  if (! MHD_itc_init_ (daemon->itc))
5548  {
5549 #ifdef HAVE_MESSAGES
5550  MHD_DLOG (daemon,
5551  _("Failed to create inter-thread communication channel: %s\n"),
5552  MHD_itc_last_strerror_ ());
5553 #endif
5554 #ifdef HTTPS_SUPPORT
5555  if (NULL != daemon->priority_cache)
5556  gnutls_priority_deinit (daemon->priority_cache);
5557 #endif /* HTTPS_SUPPORT */
5558  free (daemon);
5559  return NULL;
5560  }
5561  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5562  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
5563  NULL)) )
5564  {
5565 #ifdef HAVE_MESSAGES
5566  MHD_DLOG (daemon,
5567  _("file descriptor for inter-thread communication channel exceeds maximum value\n"));
5568 #endif
5569  MHD_itc_destroy_chk_ (daemon->itc);
5570 #ifdef HTTPS_SUPPORT
5571  if (NULL != daemon->priority_cache)
5572  gnutls_priority_deinit (daemon->priority_cache);
5573 #endif /* HTTPS_SUPPORT */
5574  free (daemon);
5575  return NULL;
5576  }
5577  }
5578 
5579 #ifdef DAUTH_SUPPORT
5580  if (daemon->nonce_nc_size > 0)
5581  {
5582  if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc))) /
5583  sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
5584  {
5585 #ifdef HAVE_MESSAGES
5586  MHD_DLOG (daemon,
5587  _("Specified value for NC_SIZE too large\n"));
5588 #endif
5589 #ifdef HTTPS_SUPPORT
5590  if (0 != (*pflags & MHD_USE_TLS))
5591  gnutls_priority_deinit (daemon->priority_cache);
5592 #endif /* HTTPS_SUPPORT */
5593  free (daemon);
5594  return NULL;
5595  }
5596  daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
5597  if (NULL == daemon->nnc)
5598  {
5599 #ifdef HAVE_MESSAGES
5600  MHD_DLOG (daemon,
5601  _("Failed to allocate memory for nonce-nc map: %s\n"),
5602  MHD_strerror_ (errno));
5603 #endif
5604 #ifdef HTTPS_SUPPORT
5605  if (0 != (*pflags & MHD_USE_TLS))
5606  gnutls_priority_deinit (daemon->priority_cache);
5607 #endif /* HTTPS_SUPPORT */
5608  free (daemon);
5609  return NULL;
5610  }
5611  }
5612 
5613  if (! MHD_mutex_init_ (&daemon->nnc_lock))
5614  {
5615 #ifdef HAVE_MESSAGES
5616  MHD_DLOG (daemon,
5617  _("MHD failed to initialize nonce-nc mutex\n"));
5618 #endif
5619 #ifdef HTTPS_SUPPORT
5620  if (0 != (*pflags & MHD_USE_TLS))
5621  gnutls_priority_deinit (daemon->priority_cache);
5622 #endif /* HTTPS_SUPPORT */
5623  free (daemon->nnc);
5624  free (daemon);
5625  return NULL;
5626  }
5627 #endif
5628 
5629  /* Thread pooling currently works only with internal select thread model */
5630  if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5631  (daemon->worker_pool_size > 0) )
5632  {
5633 #ifdef HAVE_MESSAGES
5634  MHD_DLOG (daemon,
5635  _("MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"));
5636 #endif
5637  goto free_and_fail;
5638  }
5639 
5640 #ifdef __SYMBIAN32__
5641  if (0 != (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION)))
5642  {
5643 #ifdef HAVE_MESSAGES
5644  MHD_DLOG (daemon,
5645  _("Threaded operations are not supported on Symbian.\n"));
5646 #endif
5647  goto free_and_fail;
5648  }
5649 #endif
5650  if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
5651  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5652  {
5653  /* try to open listen socket */
5654  listen_fd = MHD_socket_create_listen_(*pflags & MHD_USE_IPv6);
5655  if (MHD_INVALID_SOCKET == listen_fd)
5656  {
5657 #ifdef HAVE_MESSAGES
5658  MHD_DLOG (daemon,
5659  _("Failed to create socket for listening: %s\n"),
5661 #endif
5662  goto free_and_fail;
5663  }
5664 
5665  /* Apply the socket options according to listening_address_reuse. */
5666  if (0 == daemon->listening_address_reuse)
5667  {
5668 #ifndef _WIN32
5669  /* No user requirement, use "traditional" default SO_REUSEADDR
5670  * on non-W32 platforms, and do not fail if it doesn't work.
5671  * Don't use it on W32, because on W32 it will allow multiple
5672  * bind to the same address:port, like SO_REUSEPORT on others. */
5673  if (0 > setsockopt (listen_fd,
5674  SOL_SOCKET,
5675  SO_REUSEADDR,
5676  (void*)&on, sizeof (on)))
5677  {
5678 #ifdef HAVE_MESSAGES
5679  MHD_DLOG (daemon,
5680  _("setsockopt failed: %s\n"),
5682 #endif
5683  }
5684 #endif /* ! _WIN32 */
5685  }
5686  else if (daemon->listening_address_reuse > 0)
5687  {
5688  /* User requested to allow reusing listening address:port. */
5689 #ifndef _WIN32
5690  /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
5691  * it doesn't work. */
5692  if (0 > setsockopt (listen_fd,
5693  SOL_SOCKET,
5694  SO_REUSEADDR,
5695  (void*)&on, sizeof (on)))
5696  {
5697 #ifdef HAVE_MESSAGES
5698  MHD_DLOG (daemon,
5699  _("setsockopt failed: %s\n"),
5701 #endif
5702  }
5703 #endif /* ! _WIN32 */
5704  /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
5705  * Fail if SO_REUSEPORT is not defined or setsockopt fails.
5706  */
5707  /* SO_REUSEADDR on W32 has the same semantics
5708  as SO_REUSEPORT on BSD/Linux */
5709 #if defined(_WIN32) || defined(SO_REUSEPORT)
5710  if (0 > setsockopt (listen_fd,
5711  SOL_SOCKET,
5712 #ifndef _WIN32
5713  SO_REUSEPORT,
5714 #else /* _WIN32 */
5715  SO_REUSEADDR,
5716 #endif /* _WIN32 */
5717  (void *) &on,
5718  sizeof (on)))
5719  {
5720 #ifdef HAVE_MESSAGES
5721  MHD_DLOG (daemon,
5722  _("setsockopt failed: %s\n"),
5724 #endif
5725  goto free_and_fail;
5726  }
5727 #else /* !_WIN32 && !SO_REUSEPORT */
5728  /* we're supposed to allow address:port re-use, but
5729  on this platform we cannot; fail hard */
5730 #ifdef HAVE_MESSAGES
5731  MHD_DLOG (daemon,
5732  _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
5733 #endif
5734  goto free_and_fail;
5735 #endif /* !_WIN32 && !SO_REUSEPORT */
5736  }
5737  else /* if (daemon->listening_address_reuse < 0) */
5738  {
5739  /* User requested to disallow reusing listening address:port.
5740  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
5741  * is used and Solaris with SO_EXCLBIND.
5742  * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
5743  * or setsockopt fails.
5744  */
5745 #if (defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)) || \
5746  (defined(__sun) && defined(SO_EXCLBIND))
5747  if (0 > setsockopt (listen_fd,
5748  SOL_SOCKET,
5749 #ifdef SO_EXCLUSIVEADDRUSE
5750  SO_EXCLUSIVEADDRUSE,
5751 #else /* SO_EXCLBIND */
5752  SO_EXCLBIND,
5753 #endif /* SO_EXCLBIND */
5754  (void *) &on,
5755  sizeof (on)))
5756  {
5757 #ifdef HAVE_MESSAGES
5758  MHD_DLOG (daemon,
5759  _("setsockopt failed: %s\n"),
5761 #endif
5762  goto free_and_fail;
5763  }
5764 #elif defined(_WIN32) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
5765 #ifdef HAVE_MESSAGES
5766  MHD_DLOG (daemon,
5767  _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
5768 #endif
5769  goto free_and_fail;
5770 #endif /* _WIN32 */
5771  }
5772 
5773  /* check for user supplied sockaddr */
5774 #if HAVE_INET6
5775  if (0 != (*pflags & MHD_USE_IPv6))
5776  addrlen = sizeof (struct sockaddr_in6);
5777  else
5778 #endif
5779  addrlen = sizeof (struct sockaddr_in);
5780  if (NULL == servaddr)
5781  {
5782 #if HAVE_INET6
5783  if (0 != (*pflags & MHD_USE_IPv6))
5784  {
5785  memset (&servaddr6,
5786  0,
5787  sizeof (struct sockaddr_in6));
5788  servaddr6.sin6_family = AF_INET6;
5789  servaddr6.sin6_port = htons (port);
5790 #if HAVE_SOCKADDR_IN_SIN_LEN
5791  servaddr6.sin6_len = sizeof (struct sockaddr_in6);
5792 #endif
5793  servaddr = (struct sockaddr *) &servaddr6;
5794  }
5795  else
5796 #endif
5797  {
5798  memset (&servaddr4,
5799  0,
5800  sizeof (struct sockaddr_in));
5801  servaddr4.sin_family = AF_INET;
5802  servaddr4.sin_port = htons (port);
5803 #if HAVE_SOCKADDR_IN_SIN_LEN
5804  servaddr4.sin_len = sizeof (struct sockaddr_in);
5805 #endif
5806  servaddr = (struct sockaddr *) &servaddr4;
5807  }
5808  }
5809  daemon->listen_fd = listen_fd;
5810 
5811  if (0 != (*pflags & MHD_USE_IPv6))
5812  {
5813 #ifdef IPPROTO_IPV6
5814 #ifdef IPV6_V6ONLY
5815  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
5816  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
5817  and may also be missing on older POSIX systems; good luck if you have any of those,
5818  your IPv6 socket may then also bind against IPv4 anyway... */
5819  const MHD_SCKT_OPT_BOOL_ v6_only =
5820  (MHD_USE_DUAL_STACK != (*pflags & MHD_USE_DUAL_STACK));
5821  if (0 > setsockopt (listen_fd,
5822  IPPROTO_IPV6, IPV6_V6ONLY,
5823  (const void *) &v6_only,
5824  sizeof (v6_only)))
5825  {
5826 #ifdef HAVE_MESSAGES
5827  MHD_DLOG (daemon,
5828  _("setsockopt failed: %s\n"),
5830 #endif
5831  }
5832 #endif
5833 #endif
5834  }
5835  if (-1 == bind (listen_fd, servaddr, addrlen))
5836  {
5837 #ifdef HAVE_MESSAGES
5838  MHD_DLOG (daemon,
5839  _("Failed to bind to port %u: %s\n"),
5840  (unsigned int) port,
5842 #endif
5843  MHD_socket_close_chk_ (listen_fd);
5844  goto free_and_fail;
5845  }
5846 #ifdef TCP_FASTOPEN
5847  if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5848  {
5849  if (0 == daemon->fastopen_queue_size)
5850  daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
5851  if (0 != setsockopt (listen_fd,
5852  IPPROTO_TCP,
5853  TCP_FASTOPEN,
5854  &daemon->fastopen_queue_size,
5855  sizeof (daemon->fastopen_queue_size)))
5856  {
5857 #ifdef HAVE_MESSAGES
5858  MHD_DLOG (daemon,
5859  _("setsockopt failed: %s\n"),
5861 #endif
5862  }
5863  }
5864 #endif
5865  if (listen (listen_fd,
5866  daemon->listen_backlog_size) < 0)
5867  {
5868 #ifdef HAVE_MESSAGES
5869  MHD_DLOG (daemon,
5870  _("Failed to listen for connections: %s\n"),
5872 #endif
5873  MHD_socket_close_chk_ (listen_fd);
5874  goto free_and_fail;
5875  }
5876  }
5877  else
5878  {
5879  listen_fd = daemon->listen_fd;
5880  }
5881 
5882  if ( (MHD_INVALID_SOCKET != listen_fd) &&
5883  (! MHD_socket_nonblocking_ (listen_fd)) )
5884  {
5885 #ifdef HAVE_MESSAGES
5886  MHD_DLOG (daemon,
5887  _("Failed to set nonblocking mode on listening socket: %s\n"),
5889 #endif
5890  if (0 != (*pflags & MHD_USE_EPOLL) ||
5891  daemon->worker_pool_size > 0)
5892  {
5893  /* Accept must be non-blocking. Multiple children may wake up
5894  * to handle a new connection, but only one will win the race.
5895  * The others must immediately return. */
5896  MHD_socket_close_chk_ (listen_fd);
5897  goto free_and_fail;
5898  }
5899  }
5900  if ( (MHD_INVALID_SOCKET != listen_fd) &&
5901  (! MHD_SCKT_FD_FITS_FDSET_(listen_fd,
5902  NULL)) &&
5903  (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
5904  {
5905 #ifdef HAVE_MESSAGES
5906  MHD_DLOG (daemon,
5907  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
5908  listen_fd,
5909  FD_SETSIZE);
5910 #endif
5911  MHD_socket_close_chk_ (listen_fd);
5912  goto free_and_fail;
5913  }
5914 
5915 #ifdef EPOLL_SUPPORT
5916  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
5917  (0 == daemon->worker_pool_size) &&
5918  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5919  {
5920  if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5921  {
5922 #ifdef HAVE_MESSAGES
5923  MHD_DLOG (daemon,
5924  _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
5925 #endif
5926  goto free_and_fail;
5927  }
5928  if (MHD_YES != setup_epoll_to_listen (daemon))
5929  goto free_and_fail;
5930  }
5931 #endif /* EPOLL_SUPPORT */
5932 
5933  if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
5934  {
5935 #ifdef HAVE_MESSAGES
5936  MHD_DLOG (daemon,
5937  _("MHD failed to initialize IP connection limit mutex\n"));
5938 #endif
5939  if (MHD_INVALID_SOCKET != listen_fd)
5940  MHD_socket_close_chk_ (listen_fd);
5941  goto free_and_fail;
5942  }
5943  if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
5944  {
5945 #ifdef HAVE_MESSAGES
5946  MHD_DLOG (daemon,
5947  _("MHD failed to initialize IP connection limit mutex\n"));
5948 #endif
5950  if (MHD_INVALID_SOCKET != listen_fd)
5951  MHD_socket_close_chk_ (listen_fd);
5952  goto free_and_fail;
5953  }
5954 
5955 #ifdef HTTPS_SUPPORT
5956  /* initialize HTTPS daemon certificate aspects & send / recv functions */
5957  if ( (0 != (*pflags & MHD_USE_TLS)) &&
5958  (0 != MHD_TLS_init (daemon)) )
5959  {
5960 #ifdef HAVE_MESSAGES
5961  MHD_DLOG (daemon,
5962  _("Failed to initialize TLS support\n"));
5963 #endif
5964  if (MHD_INVALID_SOCKET != listen_fd)
5965  MHD_socket_close_chk_ (listen_fd);
5968  goto free_and_fail;
5969  }
5970 #endif /* HTTPS_SUPPORT */
5971  if ( ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5972  (0 == daemon->worker_pool_size) ) &&
5973  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
5974  (! MHD_create_named_thread_ (&daemon->pid,
5975  (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
5976  "MHD-listen" : "MHD-single",
5977  daemon->thread_stack_size,
5979  daemon) ) )
5980  {
5981 #ifdef HAVE_MESSAGES
5982  MHD_DLOG (daemon,
5983  _("Failed to create listen thread: %s\n"),
5984  MHD_strerror_ (errno));
5985 #endif
5988  if (MHD_INVALID_SOCKET != listen_fd)
5989  MHD_socket_close_chk_ (listen_fd);
5990  goto free_and_fail;
5991  }
5992  if ( (daemon->worker_pool_size > 0) &&
5993  (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5994  {
5995  /* Coarse-grained count of connections per thread (note error
5996  * due to integer division). Also keep track of how many
5997  * connections are leftover after an equal split. */
5998  unsigned int conns_per_thread = daemon->connection_limit
5999  / daemon->worker_pool_size;
6000  unsigned int leftover_conns = daemon->connection_limit
6001  % daemon->worker_pool_size;
6002 
6003  i = 0; /* we need this in case fcntl or malloc fails */
6004 
6005  /* Allocate memory for pooled objects */
6006  daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
6007  * daemon->worker_pool_size);
6008  if (NULL == daemon->worker_pool)
6009  goto thread_failed;
6010 
6011  /* Start the workers in the pool */
6012  for (i = 0; i < daemon->worker_pool_size; ++i)
6013  {
6014  /* Create copy of the Daemon object for each worker */
6015  struct MHD_Daemon *d = &daemon->worker_pool[i];
6016 
6017  memcpy (d, daemon, sizeof (struct MHD_Daemon));
6018  /* Adjust pooling params for worker daemons; note that memcpy()
6019  has already copied MHD_USE_INTERNAL_POLLING_THREAD thread model into
6020  the worker threads. */
6021  d->master = daemon;
6022  d->worker_pool_size = 0;
6023  d->worker_pool = NULL;
6024 
6025  if (0 != (*pflags & MHD_USE_ITC))
6026  {
6027  if (! MHD_itc_init_ (d->itc))
6028  {
6029 #ifdef HAVE_MESSAGES
6030  MHD_DLOG (daemon,
6031  _("Failed to create worker inter-thread communication channel: %s\n"),
6032  MHD_itc_last_strerror_() );
6033 #endif
6034  goto thread_failed;
6035  }
6036  if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6037  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
6038  NULL)) )
6039  {
6040 #ifdef HAVE_MESSAGES
6041  MHD_DLOG (daemon,
6042  _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
6043 #endif
6045  goto thread_failed;
6046  }
6047  }
6048  else
6049  MHD_itc_set_invalid_ (d->itc);
6050 
6051  /* Divide available connections evenly amongst the threads.
6052  * Thread indexes in [0, leftover_conns) each get one of the
6053  * leftover connections. */
6054  d->connection_limit = conns_per_thread;
6055  if (i < leftover_conns)
6056  ++d->connection_limit;
6057 #ifdef EPOLL_SUPPORT
6058  if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6059  (MHD_YES != setup_epoll_to_listen (d)) )
6060  goto thread_failed;
6061 #endif
6062  /* Must init cleanup connection mutex for each worker */
6063  if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
6064  {
6065 #ifdef HAVE_MESSAGES
6066  MHD_DLOG (daemon,
6067  _("MHD failed to initialize cleanup connection mutex\n"));
6068 #endif
6069  goto thread_failed;
6070  }
6071 
6072  /* Spawn the worker thread */
6073  if (! MHD_create_named_thread_ (&d->pid,
6074  "MHD-worker",
6075  daemon->thread_stack_size,
6077  d))
6078  {
6079 #ifdef HAVE_MESSAGES
6080  MHD_DLOG (daemon,
6081  _("Failed to create pool thread: %s\n"),
6082  MHD_strerror_ (errno));
6083 #endif
6084  /* Free memory for this worker; cleanup below handles
6085  * all previously-created workers. */
6087  goto thread_failed;
6088  }
6089  }
6090  }
6091 #ifdef HTTPS_SUPPORT
6092  /* API promises to never use the password after initialization,
6093  so we additionally NULL it here to not deref a dangling pointer. */
6094  daemon->https_key_password = NULL;
6095 #endif /* HTTPS_SUPPORT */
6096 
6097  return daemon;
6098 
6099 thread_failed:
6100  /* If no worker threads created, then shut down normally. Calling
6101  MHD_stop_daemon (as we do below) doesn't work here since it
6102  assumes a 0-sized thread pool means we had been in the default
6103  MHD_USE_INTERNAL_POLLING_THREAD mode. */
6104  if (0 == i)
6105  {
6106  if (MHD_INVALID_SOCKET != listen_fd)
6107  MHD_socket_close_chk_ (listen_fd);
6110  if (NULL != daemon->worker_pool)
6111  free (daemon->worker_pool);
6112  goto free_and_fail;
6113  }
6114 
6115  /* Shutdown worker threads we've already created. Pretend
6116  as though we had fully initialized our daemon, but
6117  with a smaller number of threads than had been
6118  requested. */
6119  daemon->worker_pool_size = i;
6120  MHD_stop_daemon (daemon);
6121  return NULL;
6122 
6123  free_and_fail:
6124  /* clean up basic memory state in 'daemon' and return NULL to
6125  indicate failure */
6126 #ifdef EPOLL_SUPPORT
6127 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6128  if (daemon->upgrade_fd_in_epoll)
6129  {
6130  if (0 != epoll_ctl (daemon->epoll_fd,
6131  EPOLL_CTL_DEL,
6132  daemon->epoll_upgrade_fd,
6133  NULL))
6134  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
6135  daemon->upgrade_fd_in_epoll = false;
6136  }
6137 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6138  if (-1 != daemon->epoll_fd)
6139  close (daemon->epoll_fd);
6140 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6141  if (-1 != daemon->epoll_upgrade_fd)
6142  close (daemon->epoll_upgrade_fd);
6143 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6144 #endif /* EPOLL_SUPPORT */
6145 #ifdef DAUTH_SUPPORT
6146  free (daemon->nnc);
6147  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6148 #endif
6149 #ifdef HTTPS_SUPPORT
6150  if (0 != (*pflags & MHD_USE_TLS))
6151  gnutls_priority_deinit (daemon->priority_cache);
6152 #endif /* HTTPS_SUPPORT */
6153  if (MHD_ITC_IS_VALID_(daemon->itc))
6154  MHD_itc_destroy_chk_ (daemon->itc);
6155  free (daemon);
6156  return NULL;
6157 }
6158 
6159 
6168 static void
6170 {
6171  struct MHD_Connection *pos;
6172  const bool used_thr_p_c = (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION));
6173 #ifdef UPGRADE_SUPPORT
6174  const bool upg_allowed = (0 != (daemon->options & MHD_ALLOW_UPGRADE));
6175 #endif /* UPGRADE_SUPPORT */
6176 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6177  struct MHD_UpgradeResponseHandle *urh;
6178  struct MHD_UpgradeResponseHandle *urhn;
6179  const bool used_tls = (0 != (daemon->options & MHD_USE_TLS));
6180 
6181  /* give upgraded HTTPS connections a chance to finish */
6182  /* 'daemon->urh_head' is not used in thread-per-connection mode. */
6183  for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
6184  {
6185  urhn = urh->prev;
6186  /* call generic forwarding function for passing data
6187  with chance to detect that application is done. */
6188  process_urh (urh);
6189  MHD_connection_finish_forward_ (urh->connection);
6190  urh->clean_ready = true;
6191  /* Resuming will move connection to cleanup list. */
6192  MHD_resume_connection(urh->connection);
6193  }
6194 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6195 
6196  /* Give suspended connections a chance to resume to avoid
6197  running into the check for there not being any suspended
6198  connections left in case of a tight race with a recently
6199  resumed connection. */
6200  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6201  {
6202  daemon->resuming = true; /* Force check for pending resume. */
6204  }
6205  /* first, make sure all threads are aware of shutdown; need to
6206  traverse DLLs in peace... */
6208 #ifdef UPGRADE_SUPPORT
6209  if (upg_allowed)
6210  {
6211  struct MHD_Connection * susp;
6212 
6213  susp = daemon->suspended_connections_tail;
6214  while (NULL != susp)
6215  {
6216  if (NULL == susp->urh) /* "Upgraded" connection? */
6217  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6218 #ifdef HTTPS_SUPPORT
6219  else if (used_tls &&
6220  used_thr_p_c &&
6221  (! susp->urh->clean_ready) )
6222  shutdown (susp->urh->app.socket,
6223  SHUT_RDWR); /* Wake thread by shutdown of app socket. */
6224 #endif /* HTTPS_SUPPORT */
6225  else
6226  {
6227 #ifdef HAVE_MESSAGES
6228  if (! susp->urh->was_closed)
6229  MHD_DLOG (daemon,
6230  _("Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6231 #endif
6232  susp->urh->was_closed = true;
6233  /* If thread-per-connection is used, connection's thread
6234  * may still processing "upgrade" (exiting). */
6235  if (! used_thr_p_c)
6237  /* Do not use MHD_resume_connection() as mutex is
6238  * already locked. */
6239  susp->resuming = true;
6240  daemon->resuming = true;
6241  }
6242  susp = susp->prev;
6243  }
6244  }
6245  else /* This 'else' is combined with next 'if' */
6246 #endif /* UPGRADE_SUPPORT */
6247  if (NULL != daemon->suspended_connections_head)
6248  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
6249  for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
6250  {
6251  shutdown (pos->socket_fd,
6252  SHUT_RDWR);
6253 #if MHD_WINSOCK_SOCKETS
6254  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6255  (MHD_ITC_IS_VALID_(daemon->itc)) &&
6256  (! MHD_itc_activate_ (daemon->itc, "e")) )
6257  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6258 #endif
6259  }
6260 
6261  /* now, collect per-connection threads */
6262  if (used_thr_p_c)
6263  {
6264  pos = daemon->connections_tail;
6265  while (NULL != pos)
6266  {
6267  if (! pos->thread_joined)
6268  {
6270  if (! MHD_join_thread_ (pos->pid))
6271  MHD_PANIC (_("Failed to join a thread\n"));
6273  pos->thread_joined = true;
6274  /* The thread may have concurrently modified the DLL,
6275  need to restart from the beginning */
6276  pos = daemon->connections_tail;
6277  continue;
6278  }
6279  pos = pos->prev;
6280  }
6281  }
6283 
6284 #ifdef UPGRADE_SUPPORT
6285  /* Finished threads with "upgraded" connections need to be moved
6286  * to cleanup list by resume_suspended_connections(). */
6287  /* "Upgraded" connections that were not closed explicitly by
6288  * application should be moved to cleanup list too. */
6289  if (upg_allowed)
6290  {
6291  daemon->resuming = true; /* Force check for pending resume. */
6293  }
6294 #endif /* UPGRADE_SUPPORT */
6295 
6296  /* now that we're alone, move everyone to cleanup */
6297  while (NULL != (pos = daemon->connections_tail))
6298  {
6299  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
6300  (! pos->thread_joined) )
6301  MHD_PANIC (_("Failed to join a thread\n"));
6302  close_connection (pos);
6303  }
6304  MHD_cleanup_connections (daemon);
6305 }
6306 
6307 
6314 void
6315 MHD_stop_daemon (struct MHD_Daemon *daemon)
6316 {
6317  MHD_socket fd;
6318  unsigned int i;
6319 
6320  if (NULL == daemon)
6321  return;
6322 
6323  if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options))
6325 
6326  daemon->shutdown = true;
6327  fd = daemon->listen_fd;
6328 
6329  if (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6330  {
6331  /* Separate thread(s) is used for select()/poll()/etc. */
6332  if (NULL != daemon->worker_pool)
6333  {
6334  /* Pool of workers is used. */
6335  /* Initiate shutdown process in wokers. */
6336  for (i = 0; i < daemon->worker_pool_size; ++i)
6337  {
6338  daemon->worker_pool[i].shutdown = true;
6339  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
6340  {
6341  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
6342  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
6343  }
6344 #ifdef HAVE_LISTEN_SHUTDOWN
6345  else if (MHD_INVALID_SOCKET != fd)
6346  {
6347  /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
6348  /* No problem if shutdown will be called several times for the same socket. */
6349  (void) shutdown (fd,
6350  SHUT_RDWR);
6351  }
6352 #endif
6353  }
6354  /* Start harvesting. */
6355  for (i = 0; i < daemon->worker_pool_size; ++i)
6356  {
6357  if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
6358  MHD_PANIC (_("Failed to join a thread\n"));
6359 #ifdef EPOLL_SUPPORT
6360  if (-1 != daemon->worker_pool[i].epoll_fd)
6361  MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
6362 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6363  if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
6364  MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
6365 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6366 #endif
6367  if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc) )
6368  MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
6370  }
6371  free (daemon->worker_pool);
6372  }
6373  else
6374  {
6375  /* Single internal thread is used for select()/poll()/etc. */
6376  if (MHD_ITC_IS_VALID_(daemon->itc))
6377  {
6378  if (! MHD_itc_activate_ (daemon->itc, "e"))
6379  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
6380  }
6381 #ifdef HAVE_LISTEN_SHUTDOWN
6382  else
6383  {
6384  /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
6385  if ( (MHD_INVALID_SOCKET != fd) &&
6386  (! daemon->was_quiesced) )
6387  (void) shutdown (fd,
6388  SHUT_RDWR);
6389  }
6390 #endif
6391  if (! MHD_join_thread_ (daemon->pid))
6392  {
6393  MHD_PANIC (_("Failed to join a thread\n"));
6394  }
6395  }
6396  }
6397  else
6398  {
6399  /* Internal threads are not used for select()/poll()/etc. */
6400  close_all_connections (daemon);
6401  }
6402 
6403  if ( (MHD_INVALID_SOCKET != fd) &&
6404  (! daemon->was_quiesced) )
6405  MHD_socket_close_chk_ (fd);
6406 
6407  if (MHD_ITC_IS_VALID_ (daemon->itc))
6408  MHD_itc_destroy_chk_ (daemon->itc);
6409 
6410 #ifdef EPOLL_SUPPORT
6411  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6412  (-1 != daemon->epoll_fd) )
6413  MHD_socket_close_chk_ (daemon->epoll_fd);
6414 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6415  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
6416  (-1 != daemon->epoll_upgrade_fd) )
6417  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
6418 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
6419 #endif
6420 
6421  /* TLS clean up */
6422 #ifdef HTTPS_SUPPORT
6423  if (daemon->have_dhparams)
6424  {
6425  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6426  daemon->have_dhparams = false;
6427  }
6428  if (0 != (daemon->options & MHD_USE_TLS))
6429  {
6430  gnutls_priority_deinit (daemon->priority_cache);
6431  if (daemon->x509_cred)
6432  gnutls_certificate_free_credentials (daemon->x509_cred);
6433  }
6434 #endif /* HTTPS_SUPPORT */
6435 
6436 #ifdef DAUTH_SUPPORT
6437  free (daemon->nnc);
6438  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
6439 #endif
6442 
6443  free (daemon);
6444 }
6445 
6446 
6458 const union MHD_DaemonInfo *
6460  enum MHD_DaemonInfoType info_type,
6461  ...)
6462 {
6463  if (NULL == daemon)
6464  return NULL;
6465  switch (info_type)
6466  {
6468  return NULL; /* no longer supported */
6470  return NULL; /* no longer supported */
6472  return (const union MHD_DaemonInfo *) &daemon->listen_fd;
6473 #ifdef EPOLL_SUPPORT
6475  return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
6476 #endif
6478  if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD))
6479  {
6480  /* Assume that MHD_run() in not called in other thread
6481  * at the same time. */
6482  MHD_cleanup_connections (daemon);
6483  }
6484  else if (daemon->worker_pool)
6485  {
6486  unsigned int i;
6487  /* Collect the connection information stored in the workers. */
6488  daemon->connections = 0;
6489  for (i = 0; i < daemon->worker_pool_size; i++)
6490  {
6491  /* FIXME: next line is thread-safe only if read is atomic. */
6492  daemon->connections += daemon->worker_pool[i].connections;
6493  }
6494  }
6495  return (const union MHD_DaemonInfo *) &daemon->connections;
6496  case MHD_DAEMON_INFO_FLAGS:
6497  return (const union MHD_DaemonInfo *) &daemon->options;
6498  default:
6499  return NULL;
6500  };
6501 }
6502 
6503 
6520 void
6522  void *cls)
6523 {
6524  mhd_panic = cb;
6525  mhd_panic_cls = cls;
6526 }
6527 
6528 
6535 const char *
6537 {
6538 #ifdef PACKAGE_VERSION
6539  return PACKAGE_VERSION;
6540 #else /* !PACKAGE_VERSION */
6541  static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
6542  if (0 == ver[0])
6543  {
6544  int res = MHD_snprintf_(ver,
6545  sizeof(ver),
6546  "%x.%x.%x",
6547  (((int)MHD_VERSION >> 24) & 0xFF),
6548  (((int)MHD_VERSION >> 16) & 0xFF),
6549  (((int)MHD_VERSION >> 8) & 0xFF));
6550  if (0 >= res || sizeof(ver) <= res)
6551  return "0.0.0"; /* Can't return real version*/
6552  }
6553  return ver;
6554 #endif /* !PACKAGE_VERSION */
6555 }
6556 
6557 
6569 _MHD_EXTERN int
6570 MHD_is_feature_supported(enum MHD_FEATURE feature)
6571 {
6572  switch(feature)
6573  {
6574  case MHD_FEATURE_MESSAGES:
6575 #ifdef HAVE_MESSAGES
6576  return MHD_YES;
6577 #else
6578  return MHD_NO;
6579 #endif
6580  case MHD_FEATURE_TLS:
6581 #ifdef HTTPS_SUPPORT
6582  return MHD_YES;
6583 #else /* ! HTTPS_SUPPORT */
6584  return MHD_NO;
6585 #endif /* ! HTTPS_SUPPORT */
6586  case MHD_FEATURE_HTTPS_CERT_CALLBACK:
6587 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
6588  return MHD_YES;
6589 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6590  return MHD_NO;
6591 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_MAJOR < 3 */
6592  case MHD_FEATURE_IPv6:
6593 #ifdef HAVE_INET6
6594  return MHD_YES;
6595 #else
6596  return MHD_NO;
6597 #endif
6598  case MHD_FEATURE_IPv6_ONLY:
6599 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
6600  return MHD_YES;
6601 #else
6602  return MHD_NO;
6603 #endif
6604  case MHD_FEATURE_POLL:
6605 #ifdef HAVE_POLL
6606  return MHD_YES;
6607 #else
6608  return MHD_NO;
6609 #endif
6610  case MHD_FEATURE_EPOLL:
6611 #ifdef EPOLL_SUPPORT
6612  return MHD_YES;
6613 #else
6614  return MHD_NO;
6615 #endif
6616  case MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET:
6617 #ifdef HAVE_LISTEN_SHUTDOWN
6618  return MHD_YES;
6619 #else
6620  return MHD_NO;
6621 #endif
6622  case MHD_FEATURE_SOCKETPAIR:
6623 #ifdef _MHD_ITC_SOCKETPAIR
6624  return MHD_YES;
6625 #else
6626  return MHD_NO;
6627 #endif
6628  case MHD_FEATURE_TCP_FASTOPEN:
6629 #ifdef TCP_FASTOPEN
6630  return MHD_YES;
6631 #else
6632  return MHD_NO;
6633 #endif
6634  case MHD_FEATURE_BASIC_AUTH:
6635 #ifdef BAUTH_SUPPORT
6636  return MHD_YES;
6637 #else
6638  return MHD_NO;
6639 #endif
6640  case MHD_FEATURE_DIGEST_AUTH:
6641 #ifdef DAUTH_SUPPORT
6642  return MHD_YES;
6643 #else
6644  return MHD_NO;
6645 #endif
6646  case MHD_FEATURE_POSTPROCESSOR:
6647 #ifdef HAVE_POSTPROCESSOR
6648  return MHD_YES;
6649 #else
6650  return MHD_NO;
6651 #endif
6652  case MHD_FEATURE_HTTPS_KEY_PASSWORD:
6653 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
6654  return MHD_YES;
6655 #else /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6656  return MHD_NO;
6657 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
6658  case MHD_FEATURE_LARGE_FILE:
6659 #if defined(HAVE_PREAD64) || defined(_WIN32)
6660  return MHD_YES;
6661 #elif defined(HAVE_PREAD)
6662  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6663 #elif defined(HAVE_LSEEK64)
6664  return MHD_YES;
6665 #else
6666  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
6667 #endif
6668  case MHD_FEATURE_THREAD_NAMES:
6669 #if defined(MHD_USE_THREAD_NAME_)
6670  return MHD_YES;
6671 #else
6672  return MHD_NO;
6673 #endif
6674  case MHD_FEATURE_UPGRADE:
6675 #if defined(UPGRADE_SUPPORT)
6676  return MHD_YES;
6677 #else
6678  return MHD_NO;
6679 #endif
6680  case MHD_FEATURE_RESPONSES_SHARED_FD:
6681 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
6682  return MHD_YES;
6683 #else
6684  return MHD_NO;
6685 #endif
6686  }
6687  return MHD_NO;
6688 }
6689 
6690 
6691 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
6692 #if defined(MHD_USE_POSIX_THREADS)
6693 GCRY_THREAD_OPTION_PTHREAD_IMPL;
6694 #elif defined(MHD_W32_MUTEX_)
6695 
6696 static int
6697 gcry_w32_mutex_init (void **ppmtx)
6698 {
6699  *ppmtx = malloc (sizeof (MHD_mutex_));
6700 
6701  if (NULL == *ppmtx)
6702  return ENOMEM;
6703  if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
6704  {
6705  free (*ppmtx);
6706  *ppmtx = NULL;
6707  return EPERM;
6708  }
6709 
6710  return 0;
6711 }
6712 
6713 
6714 static int
6715 gcry_w32_mutex_destroy (void **ppmtx)
6716 {
6717  int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
6718  free (*ppmtx);
6719  return res;
6720 }
6721 
6722 
6723 static int
6724 gcry_w32_mutex_lock (void **ppmtx)
6725 {
6726  return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6727 }
6728 
6729 
6730 static int
6731 gcry_w32_mutex_unlock (void **ppmtx)
6732 {
6733  return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6734 }
6735 
6736 
6737 static struct gcry_thread_cbs gcry_threads_w32 = {
6738  (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
6739  NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
6740  gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
6741  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
6742 
6743 #endif /* defined(MHD_W32_MUTEX_) */
6744 #endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
6745 
6746 
6750 void
6752 {
6753 #ifdef _WIN32
6754  WSADATA wsd;
6755 #endif /* _WIN32 */
6757  mhd_panic_cls = NULL;
6758 
6759 #ifdef _WIN32
6760  if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
6761  MHD_PANIC (_("Failed to initialize winsock\n"));
6762  mhd_winsock_inited_ = 1;
6763  if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
6764  MHD_PANIC (_("Winsock version 2.2 is not available\n"));
6765 #endif
6766 #ifdef HTTPS_SUPPORT
6767 #if GCRYPT_VERSION_NUMBER < 0x010600
6768 #if defined(MHD_USE_POSIX_THREADS)
6769  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6770  &gcry_threads_pthread))
6771  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
6772 #elif defined(MHD_W32_MUTEX_)
6773  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6774  &gcry_threads_w32))
6775  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
6776 #endif /* defined(MHD_W32_MUTEX_) */
6777  gcry_check_version (NULL);
6778 #else
6779  if (NULL == gcry_check_version ("1.6.0"))
6780  MHD_PANIC (_("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
6781 #endif
6782  gnutls_global_init ();
6783 #endif /* HTTPS_SUPPORT */
6785 }
6786 
6787 
6788 void
6790 {
6791 #ifdef HTTPS_SUPPORT
6792  gnutls_global_deinit ();
6793 #endif /* HTTPS_SUPPORT */
6794 #ifdef _WIN32
6795  if (mhd_winsock_inited_)
6796  WSACleanup();
6797 #endif
6799 }
6800 
6802 
6803 /* end of daemon.c */
bool thread_joined
Definition: internal.h:866
unsigned int per_ip_connection_limit
Definition: internal.h:1573
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
void * unescape_callback_cls
Definition: internal.h:1401
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
uint64_t total_size
Definition: internal.h:343
_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:5360
#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:2350
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:4766
uint64_t fd_off
Definition: internal.h:354
#define DLL_insert(head, tail, element)
Definition: internal.h:1726
bool data_already_pending
Definition: internal.h:1551
socklen_t addr_len
Definition: internal.h:817
void * socket_context
Definition: internal.h:683
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1229
enum MHD_CONNECTION_STATE state
Definition: internal.h:890
uint64_t response_write_position
Definition: internal.h:798
#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:4559
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:895
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:4738
time_t connection_timeout
Definition: internal.h:1567
Methods for managing connections.
int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:3270
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:592
#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:2996
struct MHD_Response * response
Definition: internal.h:656
#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:1329
Header for platform missing functions.
volatile bool was_quiesced
Definition: internal.h:1526
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:554
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:68
#define EXTRA_CHECK(a)
Definition: internal.h:1714
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:130
static int internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: daemon.c:927
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1247
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: daemon.c:2192
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:2800
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:4597
_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:4622
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:109
#define EDLL_insert(head, tail, element)
Definition: internal.h:1815
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:4791
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:3359
Methods for managing response objects.
void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: daemon.c:6521
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2522
void MHD_fini(void)
Definition: daemon.c:6789
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1391
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:1863
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:641
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:942
int listening_address_reuse
Definition: internal.h:1481
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1459
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1337
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1372
struct MHD_Connection * cleanup_head
Definition: internal.h:1277
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:633
#define XDLL_remove(head, tail, element)
Definition: internal.h:1792
void MHD_init(void)
Definition: daemon.c:6751
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
bool client_aware
Definition: internal.h:841
#define XDLL_insert(head, tail, element)
Definition: internal.h:1771
int strict_for_client
Definition: internal.h:1588
#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:1282
Header for platform-independent inter-thread communication.
struct MHD_Connection * prev
Definition: internal.h:622
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:773
struct MHD_Daemon * worker_pool
Definition: internal.h:1424
void * mhd_panic_cls
Definition: daemon.c:154
size_t read_buffer_size
Definition: internal.h:757
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:156
void * client_context
Definition: internal.h:674
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:6315
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1344
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:848
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3514
#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:749
unsigned int connection_limit
Definition: internal.h:1561
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
unsigned int worker_pool_size
Definition: internal.h:1449
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
enum MHD_FLAG options
Definition: internal.h:1578
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:3463
LogCallback uri_log_callback
Definition: internal.h:1386
#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:1056
time_t connection_timeout
Definition: internal.h:829
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:1583
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:930
unsigned int connections
Definition: internal.h:1556
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1322
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:947
size_t thread_stack_size
Definition: internal.h:1444
#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:1396
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2711
#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:936
unsigned int listen_backlog_size
Definition: internal.h:1707
#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:1257
struct MHD_Daemon * master
Definition: internal.h:1419
size_t pool_size
Definition: internal.h:1434
struct MHD_Connection * next
Definition: internal.h:617
#define ULLONG_MAX
Definition: mhd_limits.h:52
struct MHD_itc_ itc
Definition: internal.h:1514
MHD_AcceptPolicyCallback apc
Definition: internal.h:1350
time_t last_activity
Definition: internal.h:823
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1215
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2895
static int resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2861
#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:1922
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3974
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:3172
bool sk_nonblck
Definition: internal.h:853
struct MemoryPool * pool
Definition: internal.h:666
const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:6459
static int MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:3046
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:1945
size_t write_buffer_append_offset
Definition: internal.h:779
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:645
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1361
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
struct MHD_Connection * prevX
Definition: internal.h:636
bool resuming
Definition: internal.h:1540
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:4516
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3439
MHD_thread_handle_ pid
Definition: internal.h:1454
#define DLL_remove(head, tail, element)
Definition: internal.h:1747
void * notify_completed_cls
Definition: internal.h:1366
MHD_socket listen_fd
Definition: internal.h:1470
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:87
TransmitCallback send_cls
Definition: internal.h:952
#define EDLL_remove(head, tail, element)
Definition: internal.h:1834
int MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:4481
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:1377
void * apc_cls
Definition: internal.h:1355
bool at_limit
Definition: internal.h:1535
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
struct sockaddr * addr
Definition: internal.h:743
MHD_PanicCallback mhd_panic
Definition: daemon.c:149
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1272
MHD_DaemonInfoType
Definition: microhttpd.h:1808
#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:2829
bool suspended
Definition: internal.h:996
const char * MHD_get_version(void)
Definition: daemon.c:6536
void * per_ip_connection_count
Definition: internal.h:1429
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:6570
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
size_t read_buffer_offset
Definition: internal.h:763
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:1252
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1519
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: daemon.c:2151
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1465
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:4667
Header for platform-independent locks abstraction.
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:1877
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:1970
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:6169
struct MHD_Connection * connections_tail
Definition: internal.h:1262
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:205
#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:1439
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1267
#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...