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-2016 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 
27 #include "platform.h"
28 #include "mhd_threads.h"
29 #include "internal.h"
30 #include "response.h"
31 #include "connection.h"
32 #include "memorypool.h"
33 #include "mhd_limits.h"
34 #include "autoinit_funcs.h"
35 #include "mhd_mono_clock.h"
36 #include "mhd_locks.h"
37 #include "mhd_sockets.h"
38 #include "mhd_itc.h"
39 #include "mhd_compat.h"
40 
41 #if HAVE_SEARCH_H
42 #include <search.h>
43 #else
44 #include "tsearch.h"
45 #endif
46 
47 #if HTTPS_SUPPORT
48 #include "connection_https.h"
49 #include <gcrypt.h>
50 #endif
51 
52 #ifdef LINUX
53 #include <sys/sendfile.h>
54 #endif
55 
56 #ifdef _WIN32
57 #ifndef WIN32_LEAN_AND_MEAN
58 #define WIN32_LEAN_AND_MEAN 1
59 #endif /* !WIN32_LEAN_AND_MEAN */
60 #include <windows.h>
61 #endif
62 
66 #ifdef MHD_POSIX_SOCKETS
67 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
68 #else
69 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
70 #endif
71 
75 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
76 
81 #define DEBUG_CLOSE MHD_NO
82 
87 #define DEBUG_CONNECT MHD_NO
88 
89 
99 static void
100 mhd_panic_std (void *cls,
101  const char *file,
102  unsigned int line,
103  const char *reason)
104 {
105 #ifdef HAVE_MESSAGES
106  fprintf (stderr,
107  _("Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
108  file,
109  line,
110  reason);
111 #endif
112  abort ();
113 }
114 
115 
120 
125 
126 #ifdef _WIN32
127 
130 static int mhd_winsock_inited_ = 0;
131 #endif
132 
133 
141 static struct MHD_Daemon*
142 MHD_get_master (struct MHD_Daemon *daemon)
143 {
144  while (NULL != daemon->master)
145  daemon = daemon->master;
146  return daemon;
147 }
148 
149 
153 struct MHD_IPCount
154 {
158  int family;
159 
163  union
164  {
168  struct in_addr ipv4;
169 #if HAVE_INET6
170 
173  struct in6_addr ipv6;
174 #endif
175  } addr;
176 
180  unsigned int count;
181 };
182 
183 
189 static void
191 {
193 }
194 
195 
201 static void
203 {
205 }
206 
207 
217 static int
218 MHD_ip_addr_compare (const void *a1,
219  const void *a2)
220 {
221  return memcmp (a1,
222  a2,
223  offsetof (struct MHD_IPCount,
224  count));
225 }
226 
227 
236 static int
237 MHD_ip_addr_to_key (const struct sockaddr *addr,
238  socklen_t addrlen,
239  struct MHD_IPCount *key)
240 {
241  memset(key,
242  0,
243  sizeof(*key));
244 
245  /* IPv4 addresses */
246  if (sizeof (struct sockaddr_in) == addrlen)
247  {
248  const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
249 
250  key->family = AF_INET;
251  memcpy (&key->addr.ipv4,
252  &addr4->sin_addr,
253  sizeof(addr4->sin_addr));
254  return MHD_YES;
255  }
256 
257 #if HAVE_INET6
258  /* IPv6 addresses */
259  if (sizeof (struct sockaddr_in6) == addrlen)
260  {
261  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
262 
263  key->family = AF_INET6;
264  memcpy (&key->addr.ipv6,
265  &addr6->sin6_addr,
266  sizeof(addr6->sin6_addr));
267  return MHD_YES;
268  }
269 #endif
270 
271  /* Some other address */
272  return MHD_NO;
273 }
274 
275 
287 static int
288 MHD_ip_limit_add (struct MHD_Daemon *daemon,
289  const struct sockaddr *addr,
290  socklen_t addrlen)
291 {
292  struct MHD_IPCount *key;
293  void **nodep;
294  void *node;
295  int result;
296 
297  daemon = MHD_get_master (daemon);
298  /* Ignore if no connection limit assigned */
299  if (0 == daemon->per_ip_connection_limit)
300  return MHD_YES;
301 
302  if (NULL == (key = malloc (sizeof(*key))))
303  return MHD_NO;
304 
305  /* Initialize key */
306  if (MHD_NO == MHD_ip_addr_to_key (addr,
307  addrlen,
308  key))
309  {
310  /* Allow unhandled address types through */
311  free (key);
312  return MHD_YES;
313  }
314  MHD_ip_count_lock (daemon);
315 
316  /* Search for the IP address */
317  if (NULL == (nodep = tsearch (key,
318  &daemon->per_ip_connection_count,
320  {
321 #ifdef HAVE_MESSAGES
322  MHD_DLOG (daemon,
323  _("Failed to add IP connection count node\n"));
324 #endif
325  MHD_ip_count_unlock (daemon);
326  free (key);
327  return MHD_NO;
328  }
329  node = *nodep;
330  /* If we got an existing node back, free the one we created */
331  if (node != key)
332  free(key);
333  key = (struct MHD_IPCount *) node;
334  /* Test if there is room for another connection; if so,
335  * increment count */
336  result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
337  if (MHD_YES == result)
338  ++key->count;
339 
340  MHD_ip_count_unlock (daemon);
341  return result;
342 }
343 
344 
353 static void
354 MHD_ip_limit_del (struct MHD_Daemon *daemon,
355  const struct sockaddr *addr,
356  socklen_t addrlen)
357 {
358  struct MHD_IPCount search_key;
359  struct MHD_IPCount *found_key;
360  void **nodep;
361 
362  daemon = MHD_get_master (daemon);
363  /* Ignore if no connection limit assigned */
364  if (0 == daemon->per_ip_connection_limit)
365  return;
366  /* Initialize search key */
367  if (MHD_NO == MHD_ip_addr_to_key (addr,
368  addrlen,
369  &search_key))
370  return;
371 
372  MHD_ip_count_lock (daemon);
373 
374  /* Search for the IP address */
375  if (NULL == (nodep = tfind (&search_key,
376  &daemon->per_ip_connection_count,
378  {
379  /* Something's wrong if we couldn't find an IP address
380  * that was previously added */
381  MHD_PANIC (_("Failed to find previously-added IP address\n"));
382  }
383  found_key = (struct MHD_IPCount *) *nodep;
384  /* Validate existing count for IP address */
385  if (0 == found_key->count)
386  {
387  MHD_PANIC (_("Previously-added IP address had counter of zero\n"));
388  }
389  /* Remove the node entirely if count reduces to 0 */
390  if (0 == --found_key->count)
391  {
392  tdelete (found_key,
393  &daemon->per_ip_connection_count,
395  free (found_key);
396  }
397 
398  MHD_ip_count_unlock (daemon);
399 }
400 
401 
402 #if HTTPS_SUPPORT
403 
411 static ssize_t
412 recv_tls_adapter (struct MHD_Connection *connection,
413  void *other,
414  size_t i)
415 {
416  ssize_t res;
417 
418  if (MHD_YES == connection->tls_read_ready)
419  {
420  connection->daemon->num_tls_read_ready--;
421  connection->tls_read_ready = MHD_NO;
422  }
423  res = gnutls_record_recv (connection->tls_session,
424  other,
425  i);
426  if ( (GNUTLS_E_AGAIN == res) ||
427  (GNUTLS_E_INTERRUPTED == res) )
428  {
430 #ifdef EPOLL_SUPPORT
431  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
432 #endif
433  return -1;
434  }
435  if (res < 0)
436  {
437  /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication
438  disrupted); set errno to something caller will interpret
439  correctly as a hard error */
441  return res;
442  }
443  if ((size_t)res == i)
444  {
445  connection->tls_read_ready = MHD_YES;
446  connection->daemon->num_tls_read_ready++;
447  }
448  return res;
449 }
450 
451 
460 static ssize_t
461 send_tls_adapter (struct MHD_Connection *connection,
462  const void *other,
463  size_t i)
464 {
465  int res;
466 
467  res = gnutls_record_send (connection->tls_session,
468  other,
469  i);
470  if ( (GNUTLS_E_AGAIN == res) ||
471  (GNUTLS_E_INTERRUPTED == res) )
472  {
474 #ifdef EPOLL_SUPPORT
475  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
476 #endif
477  return -1;
478  }
479  if (res < 0)
480  {
481  /* some other GNUTLS error, should set 'errno'; as we do not
482  really understand the error (not listed in GnuTLS
483  documentation explicitly), we set 'errno' to something that
484  will cause the connection to fail. */
486  return -1;
487  }
488  return res;
489 }
490 
491 
498 static int
499 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
500 {
501  gnutls_datum_t key;
502  gnutls_datum_t cert;
503  int ret;
504 
505 #if GNUTLS_VERSION_MAJOR >= 3
506  if (NULL != daemon->cert_callback)
507  {
508  gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
509  daemon->cert_callback);
510  }
511 #endif
512  if (NULL != daemon->https_mem_trust)
513  {
514  cert.data = (unsigned char *) daemon->https_mem_trust;
515  cert.size = strlen (daemon->https_mem_trust);
516  if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
517  &cert,
518  GNUTLS_X509_FMT_PEM) < 0)
519  {
520 #ifdef HAVE_MESSAGES
521  MHD_DLOG(daemon,
522  "Bad trust certificate format\n");
523 #endif
524  return -1;
525  }
526  }
527 
528  if (MHD_YES == daemon->have_dhparams)
529  {
530  gnutls_certificate_set_dh_params (daemon->x509_cred,
531  daemon->https_mem_dhparams);
532  }
533  /* certificate & key loaded from memory */
534  if ( (NULL != daemon->https_mem_cert) &&
535  (NULL != daemon->https_mem_key) )
536  {
537  key.data = (unsigned char *) daemon->https_mem_key;
538  key.size = strlen (daemon->https_mem_key);
539  cert.data = (unsigned char *) daemon->https_mem_cert;
540  cert.size = strlen (daemon->https_mem_cert);
541 
542  if (NULL != daemon->https_key_password) {
543 #if GNUTLS_VERSION_NUMBER >= 0x030111
544  ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
545  &cert,
546  &key,
547  GNUTLS_X509_FMT_PEM,
548  daemon->https_key_password,
549  0);
550 #else
551 #ifdef HAVE_MESSAGES
552  MHD_DLOG (daemon,
553  _("Failed to setup x509 certificate/key: pre 3.X.X version " \
554  "of GnuTLS does not support setting key password"));
555 #endif
556  return -1;
557 #endif
558  }
559  else
560  ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
561  &cert,
562  &key,
563  GNUTLS_X509_FMT_PEM);
564 #ifdef HAVE_MESSAGES
565  if (0 != ret)
566  MHD_DLOG (daemon,
567  "GnuTLS failed to setup x509 certificate/key: %s\n",
568  gnutls_strerror (ret));
569 #endif
570  return ret;
571  }
572 #if GNUTLS_VERSION_MAJOR >= 3
573  if (NULL != daemon->cert_callback)
574  return 0;
575 #endif
576 #ifdef HAVE_MESSAGES
577  MHD_DLOG (daemon,
578  "You need to specify a certificate and key location\n");
579 #endif
580  return -1;
581 }
582 
583 
590 static int
591 MHD_TLS_init (struct MHD_Daemon *daemon)
592 {
593  switch (daemon->cred_type)
594  {
595  case GNUTLS_CRD_CERTIFICATE:
596  if (0 !=
597  gnutls_certificate_allocate_credentials (&daemon->x509_cred))
598  return GNUTLS_E_MEMORY_ERROR;
599  return MHD_init_daemon_certificate (daemon);
600  default:
601 #ifdef HAVE_MESSAGES
602  MHD_DLOG (daemon,
603  _("Error: invalid credentials type %d specified.\n"),
604  daemon->cred_type);
605 #endif
606  return -1;
607  }
608 }
609 #endif
610 
611 
612 #undef MHD_get_fdset
613 
633 int
634 MHD_get_fdset (struct MHD_Daemon *daemon,
635  fd_set *read_fd_set,
636  fd_set *write_fd_set,
637  fd_set *except_fd_set,
638  MHD_socket *max_fd)
639 {
640  return MHD_get_fdset2 (daemon,
641  read_fd_set,
642  write_fd_set,
643  except_fd_set,
644  max_fd,
646 }
647 
648 
649 #if HTTPS_SUPPORT
650 
661 static int
662 urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
663  fd_set *rs,
664  fd_set *ws,
665  MHD_socket *max_fd,
666  unsigned int fd_setsize)
667 {
668  if ( (urh->out_buffer_off < urh->out_buffer_size) &&
669  (MHD_INVALID_SOCKET != urh->mhd.socket) &&
670  (! MHD_add_to_fd_set_ (urh->mhd.socket,
671  rs,
672  max_fd,
673  fd_setsize)) )
674  return MHD_NO;
675  if ( (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
676  (MHD_INVALID_SOCKET != urh->mhd.socket) &&
677  (! MHD_add_to_fd_set_ (urh->mhd.socket,
678  ws,
679  max_fd,
680  fd_setsize)) )
681  return MHD_NO;
682  if ( (urh->in_buffer_off < urh->in_buffer_size) &&
685  rs,
686  max_fd,
687  fd_setsize)) )
688  return MHD_NO;
689  if ( (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
692  ws,
693  max_fd,
694  fd_setsize)) )
695  return MHD_NO;
696  return MHD_YES;
697 }
698 
699 
707 static void
708 urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
709  const fd_set *rs,
710  const fd_set *ws)
711 {
712  const MHD_socket mhd_sckt = urh->mhd.socket;
713  const MHD_socket conn_sckt = urh->connection->socket_fd;
714 
715  if ((MHD_INVALID_SOCKET != conn_sckt) &&
716  FD_ISSET (conn_sckt, rs))
717  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
718  if ((MHD_INVALID_SOCKET != conn_sckt) &&
719  FD_ISSET (conn_sckt, ws))
720  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
721  if ((MHD_INVALID_SOCKET != mhd_sckt) &&
722  FD_ISSET (mhd_sckt, rs))
723  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
724  if ((MHD_INVALID_SOCKET != mhd_sckt) &&
725  FD_ISSET (mhd_sckt, ws))
726  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
727 }
728 #endif
729 
730 
752 int
753 MHD_get_fdset2 (struct MHD_Daemon *daemon,
754  fd_set *read_fd_set,
755  fd_set *write_fd_set,
756  fd_set *except_fd_set,
757  MHD_socket *max_fd,
758  unsigned int fd_setsize)
759 {
760  struct MHD_Connection *pos;
761  struct MHD_Connection *posn;
762  int result = MHD_YES;
763 
764  if ( (NULL == daemon) ||
765  (NULL == read_fd_set) ||
766  (NULL == write_fd_set) ||
767  (MHD_YES == daemon->shutdown) ||
768  (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
769  (0 != (daemon->options & MHD_USE_POLL)))
770  return MHD_NO;
771 #ifdef EPOLL_SUPPORT
772  if (0 != (daemon->options & MHD_USE_EPOLL))
773  {
774  /* we're in epoll mode, use the epoll FD as a stand-in for
775  the entire event set */
776 
777  return MHD_add_to_fd_set_ (daemon->epoll_fd,
778  read_fd_set,
779  max_fd,
780  fd_setsize) ? MHD_YES : MHD_NO;
781  }
782 #endif
783  if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
784  (! MHD_add_to_fd_set_ (daemon->socket_fd,
785  read_fd_set,
786  max_fd,
787  fd_setsize)) )
788  result = MHD_NO;
789 
790  for (pos = daemon->connections_head; NULL != pos; pos = posn)
791  {
792  posn = pos->next;
793 
794  switch (pos->event_loop_info)
795  {
797  if (! MHD_add_to_fd_set_ (pos->socket_fd,
798  read_fd_set,
799  max_fd,
800  fd_setsize))
801  result = MHD_NO;
802  break;
804  if (! MHD_add_to_fd_set_ (pos->socket_fd,
805  write_fd_set,
806  max_fd,
807  fd_setsize))
808  result = MHD_NO;
809  if ( (pos->read_buffer_size > pos->read_buffer_offset) &&
811  read_fd_set,
812  max_fd,
813  fd_setsize))
814  result = MHD_NO;
815  break;
817  if ( (pos->read_buffer_size > pos->read_buffer_offset) &&
819  read_fd_set,
820  max_fd,
821  fd_setsize))
822  result = MHD_NO;
823  break;
825  /* this should never happen */
826  break;
827  }
828  }
829 #if HTTPS_SUPPORT
830  {
831  struct MHD_UpgradeResponseHandle *urh;
832 
833  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
834  {
835  if (MHD_NO ==
836  urh_to_fdset (urh,
837  read_fd_set,
838  write_fd_set,
839  max_fd,
840  fd_setsize))
841  result = MHD_NO;
842  }
843  }
844 #endif
845 #if DEBUG_CONNECT
846 #ifdef HAVE_MESSAGES
847  if (NULL != max_fd)
848  MHD_DLOG (daemon,
849  _("Maximum socket in select set: %d\n"),
850  *max_fd);
851 #endif
852 #endif
853  return result;
854 }
855 
856 
870 static int
872  int read_ready,
873  int write_ready,
874  int force_close)
875 {
876  struct MHD_Daemon *daemon = con->daemon;
877  int had_response_before_idle;
878  int ret;
879 
880 #if HTTPS_SUPPORT
881  if (MHD_YES == con->tls_read_ready)
882  read_ready = MHD_YES;
883 #endif
884  if (read_ready)
885  con->read_handler (con);
886  if (write_ready)
887  con->write_handler (con);
888  had_response_before_idle = (NULL != con->response);
889  if (force_close)
892  ret = con->idle_handler (con);
893  /* If we're in TURBO mode, and got a response object,
894  try opportunistically to just call write immediately. */
895  if ( (! force_close) &&
896  (MHD_YES == ret) &&
897  (0 != (daemon->options & MHD_USE_EPOLL_TURBO)) &&
898  (NULL != con->response) &&
899  (MHD_NO == had_response_before_idle) )
900  {
901  /* first 'write' gets the header, then 'idle'
902  readies the body, then 2nd 'write' may send
903  the body. */
904  con->write_handler (con);
905  if (MHD_YES == (ret = con->idle_handler (con)))
906  con->write_handler (con);
907  }
908  return ret;
909 }
910 
911 
919 void
921 {
922  struct MHD_Daemon *daemon = connection->daemon;
923  struct MHD_UpgradeResponseHandle *urh = connection->urh;
924 
925 #if HTTPS_SUPPORT
926  if (0 != (daemon->options & MHD_USE_TLS))
927  {
928  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
929  DLL_remove (daemon->urh_head,
930  daemon->urh_tail,
931  urh);
932 #if EPOLL_SUPPORT
933  if (0 != (daemon->options & MHD_USE_EPOLL))
934  {
935  /* epoll documentation suggests that closing a FD
936  automatically removes it from the epoll set; however,
937  this is not true as if we fail to do manually remove it,
938  we are still seeing an event for this fd in epoll,
939  causing grief (use-after-free...) --- at least on my
940  system. */
941  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
942  EPOLL_CTL_DEL,
943  connection->socket_fd,
944  NULL))
945  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
946  }
947 #endif /* EPOLL_SUPPORT */
948  if (MHD_INVALID_SOCKET != urh->mhd.socket)
949  {
950  /* epoll documentation suggests that closing a FD
951  automatically removes it from the epoll set; however,
952  this is not true as if we fail to do manually remove it,
953  we are still seeing an event for this fd in epoll,
954  causing grief (use-after-free...) --- at least on my
955  system. */
956 #if EPOLL_SUPPORT
957  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
958  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
959  EPOLL_CTL_DEL,
960  urh->mhd.socket,
961  NULL)) )
962  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
963 #endif /* EPOLL_SUPPORT */
964  MHD_socket_close_chk_ (urh->mhd.socket);
965  }
966  if (MHD_INVALID_SOCKET != urh->app.socket)
967  MHD_socket_close_chk_ (urh->app.socket);
968  }
969 #endif /* HTTPS_SUPPORT */
970  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
971  {
972  /* resuming the connection will indirectly close it */
973  MHD_resume_connection (connection);
974 #if HTTPS_SUPPORT
975  if (0 != (daemon->options & MHD_USE_TLS))
976  {
977  gnutls_bye (connection->tls_session,
978  GNUTLS_SHUT_RDWR);
979  }
980 #endif
981  }
982  else
983  {
984  /* the thread would no longer close it */
985  MHD_connection_close_ (connection,
987  }
988 
989  connection->urh = NULL;
990  if (NULL != urh)
991  free (urh);
992 }
993 
994 
995 #if HTTPS_SUPPORT
996 
1002 static void
1003 process_urh (struct MHD_UpgradeResponseHandle *urh)
1004 {
1005  int fin_read;
1006 
1007  /* handle reading from TLS client and writing to application */
1008  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
1009  (urh->in_buffer_off < urh->in_buffer_size) )
1010  {
1011  ssize_t res;
1012 
1013  res = gnutls_record_recv (urh->connection->tls_session,
1014  &urh->in_buffer[urh->in_buffer_off],
1015  urh->in_buffer_size - urh->in_buffer_off);
1016  if ( (GNUTLS_E_AGAIN == res) ||
1017  (GNUTLS_E_INTERRUPTED == res) )
1018  {
1019  urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1020  }
1021  else if (res > 0)
1022  {
1023  urh->in_buffer_off += res;
1024  }
1025  if (0 == res)
1026  {
1027  /* connection was shut down, signal by shrinking buffer,
1028  which will eventually ensure this FD is no longer listed. */
1029  urh->in_buffer_size = urh->in_buffer_off;
1030  }
1031  }
1032  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1033  (urh->in_buffer_off > 0) )
1034  {
1035  ssize_t res;
1036 
1037  res = MHD_send_ (urh->mhd.socket,
1038  urh->in_buffer,
1039  urh->in_buffer_off);
1040  if (-1 == res)
1041  {
1042  int err = MHD_socket_get_error_ ();
1043 
1044  if ( (MHD_SCKT_ERR_IS_EINTR_ (err)) ||
1045  (MHD_SCKT_ERR_IS_EAGAIN_ (err)) )
1046  urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1047  else
1048  {
1049  /* persistent / unrecoverable error, treat as
1050  if connection was shut down */
1051  urh->in_buffer_size = 0;
1052  urh->in_buffer_off = 0;
1053  }
1054  }
1055  else
1056  {
1057  if (urh->in_buffer_off != res)
1058  {
1059  memmove (urh->in_buffer,
1060  &urh->in_buffer[res],
1061  urh->in_buffer_off - res);
1062  urh->in_buffer_off -= res;
1063  }
1064  else
1065  {
1066  urh->in_buffer_off = 0;
1067  }
1068  }
1069  }
1070 
1071  /* handle reading from application and writing to HTTPS client */
1072  if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1073  (urh->out_buffer_off < urh->out_buffer_size) )
1074  {
1075  ssize_t res;
1076 
1077  res = MHD_recv_ (urh->mhd.socket,
1078  &urh->out_buffer[urh->out_buffer_off],
1079  urh->out_buffer_size - urh->out_buffer_off);
1080  if (-1 == res)
1081  {
1082  /* FIXME: differenciate by errno? */
1083  urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1084  }
1085  else
1086  {
1087  urh->out_buffer_off += res;
1088  }
1089  if (0 == res)
1090  {
1091  /* connection was shut down, signal by shrinking buffer,
1092  which will eventually ensure this FD is no longer listed. */
1093  urh->out_buffer_size = urh->out_buffer_off;
1094  }
1095  fin_read = (0 == res);
1096  }
1097  else
1098  fin_read = 0;
1099  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1100  (urh->out_buffer_off > 0) )
1101  {
1102  ssize_t res;
1103 
1104  res = gnutls_record_send (urh->connection->tls_session,
1105  urh->out_buffer,
1106  urh->out_buffer_off);
1107  if ( (GNUTLS_E_AGAIN == res) ||
1108  (GNUTLS_E_INTERRUPTED == res) )
1109  {
1110  urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1111  }
1112  else if (res > 0)
1113  {
1114  if (urh->out_buffer_off != res)
1115  {
1116  memmove (urh->out_buffer,
1117  &urh->out_buffer[res],
1118  urh->out_buffer_off - res);
1119  urh->out_buffer_off -= res;
1120  }
1121  else
1122  {
1123  urh->out_buffer_off = 0;
1124  }
1125  }
1126  else
1127  {
1128  /* persistent / unrecoverable error, treat as
1129  if connection was shut down */
1130  urh->out_buffer_size = 0;
1131  urh->out_buffer_off = 0;
1132  }
1133  }
1134  /* cleanup connection if it was closed and all data was sent */
1135  if ( (MHD_YES == urh->was_closed) &&
1136  (0 == urh->out_buffer_off) &&
1137  (MHD_YES == fin_read) )
1138  {
1140  }
1141 }
1142 #endif
1143 
1144 
1151 static void
1153 {
1154  struct MHD_UpgradeResponseHandle *urh = con->urh;
1155 #if HTTPS_SUPPORT
1156  struct MHD_Daemon *daemon = con->daemon;
1157 
1158  /* Here, we need to bi-directionally forward
1159  until the application tells us that it is done
1160  with the socket; */
1161  if ( (0 != (daemon->options & MHD_USE_TLS)) &&
1162  (0 == (daemon->options & MHD_USE_POLL)))
1163  {
1164  while (MHD_CONNECTION_UPGRADE == con->state)
1165  {
1166  /* use select */
1167  fd_set rs;
1168  fd_set ws;
1169  MHD_socket max_fd;
1170  int num_ready;
1171  int result;
1172 
1173  FD_ZERO (&rs);
1174  FD_ZERO (&ws);
1175  max_fd = MHD_INVALID_SOCKET;
1176  result = urh_to_fdset (urh,
1177  &rs,
1178  &ws,
1179  &max_fd,
1180  FD_SETSIZE);
1181  if (MHD_NO == result)
1182  {
1183 #ifdef HAVE_MESSAGES
1184  MHD_DLOG (con->daemon,
1185  _("Error preparing select\n"));
1186 #endif
1187  break;
1188  }
1189  if (MHD_INVALID_SOCKET != max_fd)
1190  num_ready = MHD_SYS_select_ (max_fd + 1,
1191  &rs,
1192  &ws,
1193  NULL,
1194  NULL);
1195  else
1196  num_ready = 0;
1197  if (num_ready < 0)
1198  {
1199  const int err = MHD_socket_get_error_();
1200 
1201  if (MHD_SCKT_ERR_IS_EINTR_(err))
1202  continue;
1203 #ifdef HAVE_MESSAGES
1204  MHD_DLOG (con->daemon,
1205  _("Error during select (%d): `%s'\n"),
1206  err,
1207  MHD_socket_strerr_ (err));
1208 #endif
1209  break;
1210  }
1211  urh_from_fdset (urh,
1212  &rs,
1213  &ws);
1214  process_urh (urh);
1215  if ( (0 == urh->out_buffer_size) &&
1216  (0 == urh->in_buffer_size) )
1217  break; /* connections died, we have no more purpose here */
1218  }
1219  }
1220 #ifdef HAVE_POLL
1221  else if (0 != (daemon->options & MHD_USE_TLS))
1222  {
1223  /* use poll() */
1224  const unsigned int timeout = UINT_MAX;
1225 
1226  while (MHD_CONNECTION_UPGRADE == con->state)
1227  {
1228  struct pollfd p[2];
1229 
1230  memset (p,
1231  0,
1232  sizeof (struct pollfd) * 2);
1233  p[0].fd = urh->connection->socket_fd;
1234  p[1].fd = urh->mhd.socket;
1235  if (urh->in_buffer_off < urh->in_buffer_size)
1236  p[0].events |= POLLIN;
1237  if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
1238  p[0].events |= POLLOUT;
1239  if (urh->out_buffer_off < urh->out_buffer_size)
1240  p[1].events |= POLLIN;
1241  if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
1242  p[1].events |= POLLOUT;
1243 
1244  if ( (0 != (p[0].events | p[1].events)) &&
1245  (MHD_sys_poll_ (p,
1246  2,
1247  timeout) < 0) )
1248  {
1249  const int err = MHD_socket_get_error_ ();
1250 
1251  if (MHD_SCKT_ERR_IS_EINTR_ (err))
1252  continue;
1253 #ifdef HAVE_MESSAGES
1254  MHD_DLOG (con->daemon,
1255  _("Error during poll: `%s'\n"),
1256  MHD_socket_strerr_ (err));
1257 #endif
1258  break;
1259  }
1260  if (0 != (p[0].revents & POLLIN))
1261  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1262  if (0 != (p[0].revents & POLLOUT))
1263  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
1264  if (0 != (p[1].revents & POLLIN))
1265  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1266  if (0 != (p[1].revents & POLLOUT))
1267  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
1268  process_urh (urh);
1269  if ( (0 == urh->out_buffer_size) &&
1270  (0 == urh->in_buffer_size) )
1271  break; /* connections died, we have no more purpose here */
1272  }
1273  }
1274  /* end POLL */
1275 #endif
1276  /* end HTTPS */
1277 #endif
1278 }
1279 
1280 
1288 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1290 {
1291  struct MHD_Connection *con = data;
1292  struct MHD_Daemon *daemon = con->daemon;
1293  int num_ready;
1294  fd_set rs;
1295  fd_set ws;
1296  MHD_socket maxsock;
1297  struct timeval tv;
1298  struct timeval *tvp;
1299  time_t now;
1300 #if WINDOWS
1301 #ifdef HAVE_POLL
1302  int extra_slot;
1303 #endif /* HAVE_POLL */
1304 #define EXTRA_SLOTS 1
1305 #else /* !WINDOWS */
1306 #define EXTRA_SLOTS 0
1307 #endif /* !WINDOWS */
1308 #ifdef HAVE_POLL
1309  struct pollfd p[1 + EXTRA_SLOTS];
1310 #endif
1311 #undef EXTRA_SLOTS
1312 
1313  while ( (MHD_YES != daemon->shutdown) &&
1314  (MHD_CONNECTION_CLOSED != con->state) )
1315  {
1316  const unsigned int timeout = daemon->connection_timeout;
1317 
1318  tvp = NULL;
1319 #if HTTPS_SUPPORT
1320  if (MHD_YES == con->tls_read_ready)
1321  {
1322  /* do not block (more data may be inside of TLS buffers waiting for us) */
1323  tv.tv_sec = 0;
1324  tv.tv_usec = 0;
1325  tvp = &tv;
1326  }
1327 #endif
1328  if ( (NULL == tvp) &&
1329  (timeout > 0) )
1330  {
1331  now = MHD_monotonic_sec_counter();
1332  if (now - con->last_activity > timeout)
1333  tv.tv_sec = 0;
1334  else
1335  {
1336  const time_t seconds_left = timeout - (now - con->last_activity);
1337 #ifndef _WIN32
1338  tv.tv_sec = seconds_left;
1339 #else /* _WIN32 */
1340  if (seconds_left > TIMEVAL_TV_SEC_MAX)
1341  tv.tv_sec = TIMEVAL_TV_SEC_MAX;
1342  else
1343  tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
1344 #endif /* _WIN32 */
1345  }
1346  tv.tv_usec = 0;
1347  tvp = &tv;
1348  }
1349  if (0 == (daemon->options & MHD_USE_POLL))
1350  {
1351  /* use select */
1352  int err_state = 0;
1353 
1354  FD_ZERO (&rs);
1355  FD_ZERO (&ws);
1356  maxsock = MHD_INVALID_SOCKET;
1357  switch (con->event_loop_info)
1358  {
1360  if (! MHD_add_to_fd_set_ (con->socket_fd,
1361  &rs,
1362  &maxsock,
1363  FD_SETSIZE))
1364  err_state = 1;
1365  break;
1367  if (! MHD_add_to_fd_set_ (con->socket_fd,
1368  &ws,
1369  &maxsock,
1370  FD_SETSIZE))
1371  err_state = 1;
1372  if ( (con->read_buffer_size > con->read_buffer_offset) &&
1373  (! MHD_add_to_fd_set_ (con->socket_fd,
1374  &rs,
1375  &maxsock,
1376  FD_SETSIZE)) )
1377  err_state = 1;
1378  break;
1380  if ( (con->read_buffer_size > con->read_buffer_offset) &&
1381  (! MHD_add_to_fd_set_ (con->socket_fd,
1382  &rs,
1383  &maxsock,
1384  FD_SETSIZE)) )
1385  err_state = 1;
1386  tv.tv_sec = 0;
1387  tv.tv_usec = 0;
1388  tvp = &tv;
1389  break;
1391  /* how did we get here!? */
1392  goto exit;
1393  }
1394 #if WINDOWS
1395  if (MHD_ITC_IS_VALID_(daemon->itc) )
1396  {
1397  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
1398  &rs,
1399  &maxsock,
1400  FD_SETSIZE))
1401  err_state = 1;
1402  }
1403 #endif
1404  if (0 != err_state)
1405  {
1406 #ifdef HAVE_MESSAGES
1407  MHD_DLOG (con->daemon,
1408  _("Failed to add FD to fd_set\n"));
1409 #endif
1410  goto exit;
1411  }
1412 
1413  num_ready = MHD_SYS_select_ (maxsock + 1,
1414  &rs,
1415  &ws,
1416  NULL,
1417  tvp);
1418  if (num_ready < 0)
1419  {
1420  const int err = MHD_socket_get_error_();
1421 
1422  if (MHD_SCKT_ERR_IS_EINTR_(err))
1423  continue;
1424 #ifdef HAVE_MESSAGES
1425  MHD_DLOG (con->daemon,
1426  _("Error during select (%d): `%s'\n"),
1427  err,
1428  MHD_socket_strerr_ (err));
1429 #endif
1430  break;
1431  }
1432 #if WINDOWS
1433  /* Clear ITC before other processing so additional
1434  * signals will trigger select() again */
1435  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
1436  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
1437  &rs)) )
1438  MHD_itc_clear_ (daemon->itc);
1439 #endif
1440  if (MHD_NO ==
1441  call_handlers (con,
1442  FD_ISSET (con->socket_fd,
1443  &rs),
1444  FD_ISSET (con->socket_fd,
1445  &ws),
1446  MHD_NO))
1447  goto exit;
1448  }
1449 #ifdef HAVE_POLL
1450  else
1451  {
1452  /* use poll */
1453  memset (&p,
1454  0,
1455  sizeof (p));
1456  p[0].fd = con->socket_fd;
1457  switch (con->event_loop_info)
1458  {
1460  p[0].events |= POLLIN;
1461  break;
1463  p[0].events |= POLLOUT;
1464  if (con->read_buffer_size > con->read_buffer_offset)
1465  p[0].events |= POLLIN;
1466  break;
1468  if (con->read_buffer_size > con->read_buffer_offset)
1469  p[0].events |= POLLIN;
1470  tv.tv_sec = 0;
1471  tv.tv_usec = 0;
1472  tvp = &tv;
1473  break;
1475  /* how did we get here!? */
1476  goto exit;
1477  }
1478 #if WINDOWS
1479  extra_slot = 0;
1480  if (MHD_ITC_IS_VALID_(daemon->itc))
1481  {
1482  p[1].events |= POLLIN;
1483  p[1].fd = MHD_itc_r_fd_ (daemon->itc);
1484  p[1].revents = 0;
1485  extra_slot = 1;
1486  }
1487 #endif
1488  if (MHD_sys_poll_ (p,
1489 #if WINDOWS
1490  1 + extra_slot,
1491 #else
1492  1,
1493 #endif
1494  (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
1495  {
1497  continue;
1498 #ifdef HAVE_MESSAGES
1499  MHD_DLOG (con->daemon,
1500  _("Error during poll: `%s'\n"),
1502 #endif
1503  break;
1504  }
1505 #if WINDOWS
1506  /* Clear ITC before other processing so additional
1507  * signals will trigger poll() again */
1508  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
1509  (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
1510  MHD_itc_clear_ (daemon->itc);
1511 #endif
1512  if (MHD_NO ==
1513  call_handlers (con,
1514  0 != (p[0].revents & POLLIN),
1515  0 != (p[0].revents & POLLOUT),
1516  0 != (p[0].revents & (POLLERR | POLLHUP))))
1517  goto exit;
1518  }
1519 #endif
1520  if (MHD_CONNECTION_UPGRADE == con->state)
1521  {
1523 #if HTTPS_SUPPORT
1524  if (0 != (daemon->options & MHD_USE_TLS) )
1525  break;
1526 #endif
1527 
1528  /* skip usual clean up EXCEPT for the completion
1529  notification (which must be done in this thread)! */
1530  if ( (NULL != daemon->notify_completed) &&
1531  (MHD_YES == con->client_aware) )
1532  daemon->notify_completed (daemon->notify_completed_cls,
1533  con,
1534  &con->client_context,
1536  con->client_aware = MHD_NO;
1537 
1538  return (MHD_THRD_RTRN_TYPE_) 0;
1539  }
1540  }
1541  if (MHD_CONNECTION_IN_CLEANUP != con->state)
1542  {
1543 #if DEBUG_CLOSE
1544 #ifdef HAVE_MESSAGES
1545  MHD_DLOG (con->daemon,
1546  _("Processing thread terminating. Closing connection\n"));
1547 #endif
1548 #endif
1549  if (MHD_CONNECTION_CLOSED != con->state)
1550  MHD_connection_close_ (con,
1552  con->idle_handler (con);
1553  }
1554 exit:
1555  if (NULL != con->response)
1556  {
1558  con->response = NULL;
1559  }
1560 
1561  if (MHD_INVALID_SOCKET != con->socket_fd)
1562  {
1563  shutdown (con->socket_fd,
1564  SHUT_WR);
1567  }
1568  return (MHD_THRD_RTRN_TYPE_) 0;
1569 }
1570 
1571 
1580 static ssize_t
1582  void *other,
1583  size_t i)
1584 {
1585  ssize_t ret;
1586 
1587  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
1588  (MHD_CONNECTION_CLOSED == connection->state) )
1589  {
1591  return -1;
1592  }
1593 #ifdef MHD_POSIX_SOCKETS
1594  if (i > SSIZE_MAX)
1595  i = SSIZE_MAX; /* return value limit */
1596 #else /* MHD_WINSOCK_SOCKETS */
1597  if (i > INT_MAX)
1598  i = INT_MAX; /* return value limit */
1599 #endif /* MHD_WINSOCK_SOCKETS */
1600 
1601  ret = MHD_recv_ (connection->socket_fd,
1602  other,
1603  i);
1604 #ifdef EPOLL_SUPPORT
1605  if ( (0 > ret) &&
1607  {
1608  /* Got EAGAIN --- no longer read-ready */
1609  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
1610  }
1611 #endif
1612  return ret;
1613 }
1614 
1615 
1624 static ssize_t
1626  const void *other,
1627  size_t i)
1628 {
1629  ssize_t ret;
1630  int err;
1631 #if LINUX
1632  MHD_socket fd;
1633 #endif
1634 
1635  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
1636  (MHD_CONNECTION_CLOSED == connection->state) )
1637  {
1639  return -1;
1640  }
1641  if (i > MHD_SCKT_SEND_MAX_SIZE_)
1642  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
1643 
1644  if (0 != (connection->daemon->options & MHD_USE_TLS))
1645  return MHD_send_ (connection->socket_fd,
1646  other,
1647  i);
1648 #if LINUX
1649  if ( (connection->write_buffer_append_offset ==
1650  connection->write_buffer_send_offset) &&
1651  (NULL != connection->response) &&
1652  (-1 != (fd = connection->response->fd)) )
1653  {
1654  /* can use sendfile */
1655  uint64_t left;
1656  uint64_t offsetu64;
1657 #ifndef HAVE_SENDFILE64
1658  off_t offset;
1659 #else /* HAVE_SENDFILE64 */
1660  off64_t offset;
1661 #endif /* HAVE_SENDFILE64 */
1662  offsetu64 = connection->response_write_position + connection->response->fd_off;
1663  left = connection->response->total_size - connection->response_write_position;
1664  ret = 0;
1666 #ifndef HAVE_SENDFILE64
1667  offset = (off_t) offsetu64;
1668  if ( (offsetu64 <= (uint64_t) OFF_T_MAX) &&
1669  (0 < (ret = sendfile (connection->socket_fd,
1670  fd,
1671  &offset,
1672  left))) )
1673 #else /* HAVE_SENDFILE64 */
1674  offset = (off64_t) offsetu64;
1675  if ( (offsetu64 <= (uint64_t) OFF64_T_MAX) &&
1676  (0 < (ret = sendfile64 (connection->socket_fd,
1677  fd,
1678  &offset,
1679  left))) )
1680 #endif /* HAVE_SENDFILE64 */
1681  {
1682  /* write successful */
1683  return ret;
1684  }
1685  err = MHD_socket_get_error_();
1686 #ifdef EPOLL_SUPPORT
1687  if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) )
1688  {
1689  /* EAGAIN --- no longer write-ready */
1690  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
1691  }
1692 #endif
1693  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
1695  return 0;
1696  if (MHD_SCKT_ERR_IS_(err,
1697  MHD_SCKT_EBADF_))
1698  return -1;
1699  /* sendfile() failed with EINVAL if mmap()-like operations are not
1700  supported for FD or other 'unusual' errors occurred, so we should try
1701  to fall back to 'SEND'; see also this thread for info on
1702  odd libc/Linux behavior with sendfile:
1703  http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
1704  }
1705 #endif
1706  ret = MHD_send_ (connection->socket_fd,
1707  other,
1708  i);
1709  err = MHD_socket_get_error_();
1710 #ifdef EPOLL_SUPPORT
1711  if ( (0 > ret) &&
1712  (MHD_SCKT_ERR_IS_EAGAIN_(err)) )
1713  {
1714  /* EAGAIN --- no longer write-ready */
1715  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
1716  }
1717 #endif
1718  /* Handle broken kernel / libc, returning -1 but not setting errno;
1719  kill connection as that should be safe; reported on mailinglist here:
1720  http://lists.gnu.org/archive/html/libmicrohttpd/2014-10/msg00023.html */
1721  if ( (0 > ret) &&
1722  (0 == err) )
1724  return ret;
1725 }
1726 
1727 
1735 static void
1736 MHD_cleanup_connections (struct MHD_Daemon *daemon);
1737 
1738 
1765 static int
1767  MHD_socket client_socket,
1768  const struct sockaddr *addr,
1769  socklen_t addrlen,
1770  int external_add)
1771 {
1772  struct MHD_Connection *connection;
1773  unsigned int i;
1774  int eno;
1775  struct MHD_Daemon *worker;
1776 #if OSX
1777  static int on = 1;
1778 #endif
1779 
1780  if (NULL != daemon->worker_pool)
1781  {
1782  /* have a pool, try to find a pool with capacity; we use the
1783  socket as the initial offset into the pool for load
1784  balancing */
1785  for (i=0;i<daemon->worker_pool_size;i++)
1786  {
1787  worker = &daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size];
1788  if (worker->connections < worker->connection_limit)
1789  return internal_add_connection (worker,
1790  client_socket,
1791  addr,
1792  addrlen,
1793  external_add);
1794  }
1795  /* all pools are at their connection limit, must refuse */
1796  MHD_socket_close_chk_ (client_socket);
1797 #if ENFILE
1798  errno = ENFILE;
1799 #endif
1800  return MHD_NO;
1801  }
1802 
1803  if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket,
1804  NULL)) &&
1805  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
1806  {
1807 #ifdef HAVE_MESSAGES
1808  MHD_DLOG (daemon,
1809  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
1810  (int) client_socket,
1811  (int) FD_SETSIZE);
1812 #endif
1813  MHD_socket_close_chk_ (client_socket);
1814 #if EINVAL
1815  errno = EINVAL;
1816 #endif
1817  return MHD_NO;
1818  }
1819 
1820 
1821 #ifdef HAVE_MESSAGES
1822 #if DEBUG_CONNECT
1823  MHD_DLOG (daemon,
1824  _("Accepted connection on socket %d\n"),
1825  client_socket);
1826 #endif
1827 #endif
1828  if ( (daemon->connections == daemon->connection_limit) ||
1829  (MHD_NO == MHD_ip_limit_add (daemon,
1830  addr,
1831  addrlen)) )
1832  {
1833  /* above connection limit - reject */
1834 #ifdef HAVE_MESSAGES
1835  MHD_DLOG (daemon,
1836  _("Server reached connection limit. Closing inbound connection.\n"));
1837 #endif
1838  MHD_socket_close_chk_ (client_socket);
1839 #if ENFILE
1840  errno = ENFILE;
1841 #endif
1842  return MHD_NO;
1843  }
1844 
1845  /* apply connection acceptance policy if present */
1846  if ( (NULL != daemon->apc) &&
1847  (MHD_NO == daemon->apc (daemon->apc_cls,
1848  addr,
1849  addrlen)) )
1850  {
1851 #if DEBUG_CLOSE
1852 #ifdef HAVE_MESSAGES
1853  MHD_DLOG (daemon,
1854  _("Connection rejected by application. Closing connection.\n"));
1855 #endif
1856 #endif
1857  MHD_socket_close_chk_ (client_socket);
1858  MHD_ip_limit_del (daemon,
1859  addr,
1860  addrlen);
1861 #if EACCESS
1862  errno = EACCESS;
1863 #endif
1864  return MHD_NO;
1865  }
1866 
1867 #if OSX
1868 #ifdef SOL_SOCKET
1869 #ifdef SO_NOSIGPIPE
1870  setsockopt (client_socket,
1871  SOL_SOCKET,
1872  SO_NOSIGPIPE,
1873  &on,
1874  sizeof (on));
1875 #endif
1876 #endif
1877 #endif
1878 
1879  if (NULL == (connection = malloc (sizeof (struct MHD_Connection))))
1880  {
1881  eno = errno;
1882 #ifdef HAVE_MESSAGES
1883  MHD_DLOG (daemon,
1884  "Error allocating memory: %s\n",
1885  MHD_strerror_ (errno));
1886 #endif
1887  MHD_socket_close_chk_ (client_socket);
1888  MHD_ip_limit_del (daemon,
1889  addr,
1890  addrlen);
1891  errno = eno;
1892  return MHD_NO;
1893  }
1894  memset (connection,
1895  0,
1896  sizeof (struct MHD_Connection));
1897  connection->pool = MHD_pool_create (daemon->pool_size);
1898  if (NULL == connection->pool)
1899  {
1900 #ifdef HAVE_MESSAGES
1901  MHD_DLOG (daemon,
1902  _("Error allocating memory: %s\n"),
1903  MHD_strerror_ (errno));
1904 #endif
1905  MHD_socket_close_chk_ (client_socket);
1906  MHD_ip_limit_del (daemon,
1907  addr,
1908  addrlen);
1909  free (connection);
1910 #if ENOMEM
1911  errno = ENOMEM;
1912 #endif
1913  return MHD_NO;
1914  }
1915 
1916  connection->connection_timeout = daemon->connection_timeout;
1917  if (NULL == (connection->addr = malloc (addrlen)))
1918  {
1919  eno = errno;
1920 #ifdef HAVE_MESSAGES
1921  MHD_DLOG (daemon,
1922  _("Error allocating memory: %s\n"),
1923  MHD_strerror_ (errno));
1924 #endif
1925  MHD_socket_close_chk_ (client_socket);
1926  MHD_ip_limit_del (daemon,
1927  addr,
1928  addrlen);
1929  MHD_pool_destroy (connection->pool);
1930  free (connection);
1931  errno = eno;
1932  return MHD_NO;
1933  }
1934  memcpy (connection->addr,
1935  addr,
1936  addrlen);
1937  connection->addr_len = addrlen;
1938  connection->socket_fd = client_socket;
1939  connection->daemon = daemon;
1940  connection->last_activity = MHD_monotonic_sec_counter();
1941 
1942  /* set default connection handlers */
1943  MHD_set_http_callbacks_ (connection);
1944  connection->recv_cls = &recv_param_adapter;
1945  connection->send_cls = &send_param_adapter;
1946 
1947  if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
1948  {
1949  /* in turbo mode, we assume that non-blocking was already set
1950  by 'accept4' or whoever calls 'MHD_add_connection' */
1951  if (! MHD_socket_nonblocking_ (connection->socket_fd))
1952  {
1953 #ifdef HAVE_MESSAGES
1954  MHD_DLOG (connection->daemon,
1955  _("Failed to set nonblocking mode on connection socket: %s\n"),
1957 #endif
1958  }
1959  }
1960 
1961 #if HTTPS_SUPPORT
1962  if (0 != (daemon->options & MHD_USE_TLS))
1963  {
1964  connection->recv_cls = &recv_tls_adapter;
1965  connection->send_cls = &send_tls_adapter;
1966  connection->state = MHD_TLS_CONNECTION_INIT;
1967  MHD_set_https_callbacks (connection);
1968  gnutls_init (&connection->tls_session,
1969  GNUTLS_SERVER);
1970  gnutls_priority_set (connection->tls_session,
1971  daemon->priority_cache);
1972  switch (daemon->cred_type)
1973  {
1974  /* set needed credentials for certificate authentication. */
1975  case GNUTLS_CRD_CERTIFICATE:
1976  gnutls_credentials_set (connection->tls_session,
1977  GNUTLS_CRD_CERTIFICATE,
1978  daemon->x509_cred);
1979  break;
1980  default:
1981 #ifdef HAVE_MESSAGES
1982  MHD_DLOG (connection->daemon,
1983  _("Failed to setup TLS credentials: unknown credential type %d\n"),
1984  daemon->cred_type);
1985 #endif
1986  MHD_socket_close_chk_ (client_socket);
1987  MHD_ip_limit_del (daemon,
1988  addr,
1989  addrlen);
1990  free (connection->addr);
1991  free (connection);
1992  MHD_PANIC (_("Unknown credential type"));
1993 #if EINVAL
1994  errno = EINVAL;
1995 #endif
1996  return MHD_NO;
1997  }
1998  gnutls_transport_set_ptr (connection->tls_session,
1999  (gnutls_transport_ptr_t) connection);
2000  gnutls_transport_set_pull_function (connection->tls_session,
2001  (gnutls_pull_func) &recv_param_adapter);
2002  gnutls_transport_set_push_function (connection->tls_session,
2003  (gnutls_push_func) &send_param_adapter);
2004 
2005  if (daemon->https_mem_trust)
2006  gnutls_certificate_server_set_request (connection->tls_session,
2007  GNUTLS_CERT_REQUEST);
2008  }
2009 #endif
2010 
2011  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2012  {
2014  }
2015  else
2016  {
2018  daemon->normal_timeout_tail,
2019  connection);
2020  }
2021  DLL_insert (daemon->connections_head,
2022  daemon->connections_tail,
2023  connection);
2024  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2026 
2027  if (NULL != daemon->notify_connection)
2028  daemon->notify_connection (daemon->notify_connection_cls,
2029  connection,
2030  &connection->socket_context,
2032 
2033  /* attempt to create handler thread */
2034  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2035  {
2036  if (! MHD_create_named_thread_ (&connection->pid,
2037  "MHD-connection",
2038  daemon->thread_stack_size,
2040  connection))
2041  {
2042  eno = errno;
2043 #ifdef HAVE_MESSAGES
2044  MHD_DLOG (daemon,
2045  "Failed to create a thread: %s\n",
2046  MHD_strerror_ (eno));
2047 #endif
2048  goto cleanup;
2049  }
2050  }
2051  else
2052  if ( (MHD_YES == external_add) &&
2053  (MHD_ITC_IS_VALID_(daemon->itc)) &&
2054  (! MHD_itc_activate_ (daemon->itc, "n")) )
2055  {
2056 #ifdef HAVE_MESSAGES
2057  MHD_DLOG (daemon,
2058  _("Failed to signal new connection via inter-thread communication channel."));
2059 #endif
2060  }
2061 #ifdef EPOLL_SUPPORT
2062  if (0 != (daemon->options & MHD_USE_EPOLL))
2063  {
2064  if (0 == (daemon->options & MHD_USE_EPOLL_TURBO))
2065  {
2066  struct epoll_event event;
2067 
2068  event.events = EPOLLIN | EPOLLOUT | EPOLLET;
2069  event.data.ptr = connection;
2070  if (0 != epoll_ctl (daemon->epoll_fd,
2071  EPOLL_CTL_ADD,
2072  client_socket,
2073  &event))
2074  {
2075  eno = errno;
2076 #ifdef HAVE_MESSAGES
2077  MHD_DLOG (daemon,
2078  _("Call to epoll_ctl failed: %s\n"),
2080 #endif
2081  goto cleanup;
2082  }
2083  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2084  }
2085  else
2086  {
2087  connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
2089  EDLL_insert (daemon->eready_head,
2090  daemon->eready_tail,
2091  connection);
2092  }
2093  }
2094 #endif
2095  daemon->connections++;
2096  return MHD_YES;
2097  cleanup:
2098  if (NULL != daemon->notify_connection)
2099  daemon->notify_connection (daemon->notify_connection_cls,
2100  connection,
2101  &connection->socket_context,
2103  MHD_socket_close_chk_ (client_socket);
2104  MHD_ip_limit_del (daemon,
2105  addr,
2106  addrlen);
2107  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2108  {
2110  }
2111  else
2112  {
2114  daemon->normal_timeout_tail,
2115  connection);
2116  }
2117  DLL_remove (daemon->connections_head,
2118  daemon->connections_tail,
2119  connection);
2120  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2122  MHD_pool_destroy (connection->pool);
2123  free (connection->addr);
2124  free (connection);
2125  errno = eno;
2126  return MHD_NO;
2127 }
2128 
2129 
2157 void
2159 {
2160  struct MHD_Daemon *daemon;
2161 
2162  daemon = connection->daemon;
2164  MHD_PANIC (_("Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n"));
2165  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2166  {
2168  }
2169  else
2170  {
2171  if (connection->connection_timeout == daemon->connection_timeout)
2173  daemon->normal_timeout_tail,
2174  connection);
2175  else
2177  daemon->manual_timeout_tail,
2178  connection);
2179  }
2180  DLL_remove (daemon->connections_head,
2181  daemon->connections_tail,
2182  connection);
2185  connection);
2186 #ifdef EPOLL_SUPPORT
2187  if (0 != (daemon->options & MHD_USE_EPOLL))
2188  {
2189  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2190  {
2191  EDLL_remove (daemon->eready_head,
2192  daemon->eready_tail,
2193  connection);
2194  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2195  }
2196  if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
2197  {
2198  if (0 != epoll_ctl (daemon->epoll_fd,
2199  EPOLL_CTL_DEL,
2200  connection->socket_fd,
2201  NULL))
2202  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
2203  connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2204  }
2205  connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
2206  }
2207 #endif
2208  connection->suspended = MHD_YES;
2209  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2211 }
2212 
2213 
2222 void
2224 {
2225  struct MHD_Daemon *daemon;
2226 
2227  daemon = connection->daemon;
2229  MHD_PANIC (_("Cannot resume connections without enabling MHD_USE_SUSPEND_RESUME!\n"));
2230  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2232  connection->resuming = MHD_YES;
2233  daemon->resuming = MHD_YES;
2234  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2235  (! MHD_itc_activate_ (daemon->itc, "r")) )
2236  {
2237 #ifdef HAVE_MESSAGES
2238  MHD_DLOG (daemon,
2239  _("Failed to signal resume via inter-thread communication channel."));
2240 #endif
2241  }
2242  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2244 }
2245 
2246 
2254 static int
2256 {
2257  struct MHD_Connection *pos;
2258  struct MHD_Connection *next = NULL;
2259  int ret;
2260 
2261  ret = MHD_NO;
2262  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2264  if (MHD_NO != daemon->resuming)
2265  next = daemon->suspended_connections_head;
2266 
2267  /* Clear the flag *only* if connections will be resumed otherwise
2268  it may accidentally clear flag that was set at the same time in
2269  other thread (just after 'if (MHD_NO != daemon->resuming)' in
2270  this thread).
2271  Clear flag *before* resuming connections otherwise new connection can
2272  be set to "resuming" in other thread, but missed resuming in this
2273  function at this time so clearing flag at end will clear it without
2274  actually resuming of new connection. */
2275  if (NULL != next)
2276  daemon->resuming = MHD_NO;
2277  while (NULL != (pos = next))
2278  {
2279  next = pos->next;
2280  if (MHD_NO == pos->resuming)
2281  continue;
2282  ret = MHD_YES;
2285  pos);
2286  DLL_insert (daemon->connections_head,
2287  daemon->connections_tail,
2288  pos);
2289  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2290  {
2291  if (pos->connection_timeout == daemon->connection_timeout)
2293  daemon->normal_timeout_tail,
2294  pos);
2295  else
2297  daemon->manual_timeout_tail,
2298  pos);
2299  }
2300 #ifdef EPOLL_SUPPORT
2301  if (0 != (daemon->options & MHD_USE_EPOLL))
2302  {
2303  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2304  MHD_PANIC ("Resumed connection was already in EREADY set\n");
2305  /* we always mark resumed connections as ready, as we
2306  might have missed the edge poll event during suspension */
2307  EDLL_insert (daemon->eready_head,
2308  daemon->eready_tail,
2309  pos);
2310  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2311  pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
2312  }
2313 #endif
2314  pos->suspended = MHD_NO;
2315  pos->resuming = MHD_NO;
2316  }
2317  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2319  return ret;
2320 }
2321 
2322 
2352 int
2354  MHD_socket client_socket,
2355  const struct sockaddr *addr,
2356  socklen_t addrlen)
2357 {
2358  /* internal_add_connection() assume that non-blocking is
2359  already set in MHD_USE_EPOLL_TURBO mode */
2360  if (0 != (daemon->options & MHD_USE_EPOLL_TURBO))
2361  {
2362  if (! MHD_socket_nonblocking_ (client_socket))
2363  {
2364 #ifdef HAVE_MESSAGES
2365  MHD_DLOG (daemon,
2366  _("Failed to set nonblocking mode on new client socket: %s\n"),
2368 #endif
2369  }
2370  if (! MHD_socket_noninheritable_ (client_socket))
2371  {
2372 #ifdef HAVE_MESSAGES
2373  MHD_DLOG (daemon,
2374  _("Failed to set noninheritable mode on new client socket.\n"));
2375 #endif
2376  }
2377  }
2378  return internal_add_connection (daemon,
2379  client_socket,
2380  addr,
2381  addrlen,
2382  MHD_YES);
2383 }
2384 
2385 
2398 static int
2400 {
2401 #if HAVE_INET6
2402  struct sockaddr_in6 addrstorage;
2403 #else
2404  struct sockaddr_in addrstorage;
2405 #endif
2406  struct sockaddr *addr = (struct sockaddr *) &addrstorage;
2407  socklen_t addrlen;
2408  MHD_socket s;
2409  MHD_socket fd;
2410 
2411  addrlen = sizeof (addrstorage);
2412  memset (addr,
2413  0,
2414  sizeof (addrstorage));
2415  if (MHD_INVALID_SOCKET == (fd = daemon->socket_fd))
2416  return MHD_NO;
2417 #ifdef USE_ACCEPT4
2418  s = accept4 (fd,
2419  addr,
2420  &addrlen,
2422 #else /* ! USE_ACCEPT4 */
2423  s = accept (fd,
2424  addr,
2425  &addrlen);
2426 #endif /* ! USE_ACCEPT4 */
2427  if ( (MHD_INVALID_SOCKET == s) ||
2428  (addrlen <= 0) )
2429  {
2430  const int err = MHD_socket_get_error_ ();
2431 
2432  /* This could be a common occurance with multiple worker threads */
2433  if ( (MHD_SCKT_ERR_IS_ (err,
2434  MHD_SCKT_EINVAL_)) &&
2435  (MHD_INVALID_SOCKET == daemon->socket_fd) )
2436  return MHD_NO; /* can happen during shutdown */
2438  return MHD_NO; /* do not print error if client just disconnected early */
2439 #ifdef HAVE_MESSAGES
2440  if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) )
2441  MHD_DLOG (daemon,
2442  _("Error accepting connection: %s\n"),
2443  MHD_socket_strerr_(err));
2444 #endif
2445  if (MHD_INVALID_SOCKET != s)
2446  {
2448  }
2449  if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) )
2450  {
2451  /* system/process out of resources */
2452  if (0 == daemon->connections)
2453  {
2454 #ifdef HAVE_MESSAGES
2455  /* Not setting 'at_limit' flag, as there is no way it
2456  would ever be cleared. Instead trying to produce
2457  bit fat ugly warning. */
2458  MHD_DLOG (daemon,
2459  _("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"));
2460 #endif
2461  }
2462  else
2463  {
2464  daemon->at_limit = MHD_YES;
2465 #ifdef HAVE_MESSAGES
2466  MHD_DLOG (daemon,
2467  _("Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
2468  (unsigned int) daemon->connections);
2469 #endif
2470  }
2471  }
2472  return MHD_NO;
2473  }
2474 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK)
2475  if (! MHD_socket_nonblocking_ (s))
2476  {
2477 #ifdef HAVE_MESSAGES
2478  MHD_DLOG (daemon,
2479  _("Failed to set nonblocking mode on incoming connection socket: %s\n"),
2481 #endif
2482  }
2483 #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */
2484 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC)
2485  if (! MHD_socket_noninheritable_ (s))
2486  {
2487 #ifdef HAVE_MESSAGES
2488  MHD_DLOG (daemon,
2489  _("Failed to set noninheritable mode on incoming connection socket.\n"));
2490 #endif
2491  }
2492 #endif /* !USE_ACCEPT4 || !SOCK_CLOEXEC */
2493 #ifdef HAVE_MESSAGES
2494 #if DEBUG_CONNECT
2495  MHD_DLOG (daemon,
2496  _("Accepted connection on socket %d\n"),
2497  s);
2498 #endif
2499 #endif
2500  (void) internal_add_connection (daemon,
2501  s,
2502  addr,
2503  addrlen,
2504  MHD_NO);
2505  return MHD_YES;
2506 }
2507 
2508 
2516 static void
2518 {
2519  struct MHD_Connection *pos;
2520 
2521  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2523  while (NULL != (pos = daemon->cleanup_head))
2524  {
2525  DLL_remove (daemon->cleanup_head,
2526  daemon->cleanup_tail,
2527  pos);
2528 
2529  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2531 
2532  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2533  (MHD_NO == pos->thread_joined) &&
2534  (! MHD_join_thread_ (pos->pid)) )
2535  MHD_PANIC (_("Failed to join a thread\n"));
2536  MHD_pool_destroy (pos->pool);
2537 #if HTTPS_SUPPORT
2538  if (NULL != pos->tls_session)
2539  gnutls_deinit (pos->tls_session);
2540 #endif
2541  daemon->connections--;
2542  daemon->at_limit = MHD_NO;
2543 
2544  /* clean up the connection */
2545  if (NULL != daemon->notify_connection)
2546  daemon->notify_connection (daemon->notify_connection_cls,
2547  pos,
2548  &pos->socket_context,
2550  MHD_ip_limit_del (daemon,
2551  pos->addr,
2552  pos->addr_len);
2553 #ifdef EPOLL_SUPPORT
2554  if (0 != (daemon->options & MHD_USE_EPOLL))
2555  {
2556  if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2557  {
2558  EDLL_remove (daemon->eready_head,
2559  daemon->eready_tail,
2560  pos);
2561  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2562  }
2563  if ( (-1 != daemon->epoll_fd) &&
2564  (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
2565  {
2566  /* epoll documentation suggests that closing a FD
2567  automatically removes it from the epoll set; however,
2568  this is not true as if we fail to do manually remove it,
2569  we are still seeing an event for this fd in epoll,
2570  causing grief (use-after-free...) --- at least on my
2571  system. */
2572  if (0 != epoll_ctl (daemon->epoll_fd,
2573  EPOLL_CTL_DEL,
2574  pos->socket_fd,
2575  NULL))
2576  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
2577  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2578  }
2579  }
2580 #endif
2581  if (NULL != pos->response)
2582  {
2584  pos->response = NULL;
2585  }
2586  if (MHD_INVALID_SOCKET != pos->socket_fd)
2588  if (NULL != pos->addr)
2589  free (pos->addr);
2590  free (pos);
2591 
2592  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2594  }
2595  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2597 }
2598 
2599 
2614 int
2615 MHD_get_timeout (struct MHD_Daemon *daemon,
2616  MHD_UNSIGNED_LONG_LONG *timeout)
2617 {
2618  time_t earliest_deadline;
2619  time_t now;
2620  struct MHD_Connection *pos;
2621  int have_timeout;
2622 
2623  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2624  {
2625 #ifdef HAVE_MESSAGES
2626  MHD_DLOG (daemon,
2627  _("Illegal call to MHD_get_timeout\n"));
2628 #endif
2629  return MHD_NO;
2630  }
2631 
2632 #if HTTPS_SUPPORT
2633  if (0 != daemon->num_tls_read_ready)
2634  {
2635  /* if there is any TLS connection with data ready for
2636  reading, we must not block in the event loop */
2637  *timeout = 0;
2638  return MHD_YES;
2639  }
2640 #endif
2641 
2642  have_timeout = MHD_NO;
2643  earliest_deadline = 0; /* avoid compiler warnings */
2644  for (pos = daemon->manual_timeout_head; NULL != pos; pos = pos->nextX)
2645  {
2646  if (0 != pos->connection_timeout)
2647  {
2648  if ( (! have_timeout) ||
2649  (earliest_deadline > pos->last_activity + pos->connection_timeout) )
2650  earliest_deadline = pos->last_activity + pos->connection_timeout;
2651 #if HTTPS_SUPPORT
2652  if ( (0 != (daemon->options & MHD_USE_TLS)) &&
2653  (0 != gnutls_record_check_pending (pos->tls_session)) )
2654  earliest_deadline = 0;
2655 #endif
2656  have_timeout = MHD_YES;
2657  }
2658  }
2659  /* normal timeouts are sorted, so we only need to look at the 'head' */
2660  pos = daemon->normal_timeout_head;
2661  if ( (NULL != pos) &&
2662  (0 != pos->connection_timeout) )
2663  {
2664  if ( (! have_timeout) ||
2665  (earliest_deadline > pos->last_activity + pos->connection_timeout) )
2666  earliest_deadline = pos->last_activity + pos->connection_timeout;
2667 #if HTTPS_SUPPORT
2668  if ( (0 != (daemon->options & MHD_USE_TLS)) &&
2669  (0 != gnutls_record_check_pending (pos->tls_session)) )
2670  earliest_deadline = 0;
2671 #endif
2672  have_timeout = MHD_YES;
2673  }
2674 
2675  if (MHD_NO == have_timeout)
2676  return MHD_NO;
2677  now = MHD_monotonic_sec_counter();
2678  if (earliest_deadline < now)
2679  *timeout = 0;
2680  else
2681  {
2682  const time_t second_left = earliest_deadline - now;
2683  if (second_left > ULLONG_MAX / 1000)
2684  *timeout = ULLONG_MAX;
2685  else
2686  *timeout = 1000 * second_left;
2687  }
2688  return MHD_YES;
2689 }
2690 
2691 
2711 int
2713  const fd_set *read_fd_set,
2714  const fd_set *write_fd_set,
2715  const fd_set *except_fd_set)
2716 {
2717  MHD_socket ds;
2718  struct MHD_Connection *pos;
2719  struct MHD_Connection *next;
2720 #if HTTPS_SUPPORT
2721  struct MHD_UpgradeResponseHandle *urh;
2722  struct MHD_UpgradeResponseHandle *urhn;
2723 #endif
2724  unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY |
2726 
2727  /* Clear ITC to avoid spinning select */
2728  /* Do it before any other processing so new signals
2729  will trigger select again and will be processed */
2730  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2731  (FD_ISSET (MHD_itc_r_fd_ (daemon->itc),
2732  read_fd_set)) )
2733  MHD_itc_clear_ (daemon->itc);
2734 
2735  /* Resuming external connections when using an extern mainloop */
2736  if (MHD_USE_SUSPEND_RESUME == (daemon->options & mask))
2738 
2739 #ifdef EPOLL_SUPPORT
2740  if (0 != (daemon->options & MHD_USE_EPOLL))
2741  {
2742  /* we're in epoll mode, the epoll FD stands for
2743  the entire event set! */
2744  if (! MHD_SCKT_FD_FITS_FDSET_(daemon->epoll_fd,
2745  NULL))
2746  return MHD_NO; /* poll fd too big, fail hard */
2747  if (FD_ISSET (daemon->epoll_fd,
2748  read_fd_set))
2749  return MHD_run (daemon);
2750  return MHD_YES;
2751  }
2752 #endif
2753 
2754  /* select connection thread handling type */
2755  if ( (MHD_INVALID_SOCKET != (ds = daemon->socket_fd)) &&
2756  (FD_ISSET (ds,
2757  read_fd_set)) )
2758  (void) MHD_accept_connection (daemon);
2759 
2760  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2761  {
2762  /* do not have a thread per connection, process all connections now */
2763  next = daemon->connections_head;
2764  while (NULL != (pos = next))
2765  {
2766  next = pos->next;
2767  ds = pos->socket_fd;
2768  if (MHD_INVALID_SOCKET == ds)
2769  continue;
2770  call_handlers (pos,
2771  FD_ISSET (ds,
2772  read_fd_set),
2773  FD_ISSET (ds,
2774  write_fd_set),
2775  MHD_NO);
2776  }
2777  }
2778 
2779  /* handle upgraded HTTPS connections */
2780 #if HTTPS_SUPPORT
2781  for (urh = daemon->urh_head; NULL != urh; urh = urhn)
2782  {
2783  urhn = urh->next;
2784  /* update urh state based on select() output */
2785  urh_from_fdset (urh,
2786  read_fd_set,
2787  write_fd_set);
2788  /* call generic forwarding function for passing data */
2789  process_urh (urh);
2790  }
2791 #endif
2792  MHD_cleanup_connections (daemon);
2793  return MHD_YES;
2794 }
2795 
2796 
2805 static int
2806 MHD_select (struct MHD_Daemon *daemon,
2807  int may_block)
2808 {
2809  int num_ready;
2810  fd_set rs;
2811  fd_set ws;
2812  fd_set es;
2813  MHD_socket maxsock;
2814  struct timeval timeout;
2815  struct timeval *tv;
2816  MHD_UNSIGNED_LONG_LONG ltimeout;
2817  int err_state;
2818 
2819  timeout.tv_sec = 0;
2820  timeout.tv_usec = 0;
2821  if (MHD_YES == daemon->shutdown)
2822  return MHD_NO;
2823  FD_ZERO (&rs);
2824  FD_ZERO (&ws);
2825  FD_ZERO (&es);
2826  maxsock = MHD_INVALID_SOCKET;
2827  err_state = MHD_NO;
2828  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2829  {
2830  if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) &&
2831  (MHD_YES == resume_suspended_connections (daemon)) )
2832  may_block = MHD_NO;
2833 
2834  /* single-threaded, go over everything */
2835  if (MHD_NO ==
2836  MHD_get_fdset2 (daemon,
2837  &rs,
2838  &ws,
2839  &es,
2840  &maxsock,
2841  FD_SETSIZE))
2842  {
2843 #ifdef HAVE_MESSAGES
2844  MHD_DLOG (daemon,
2845  _("Could not obtain daemon fdsets"));
2846 #endif
2847  err_state = MHD_YES;
2848  }
2849  }
2850  else
2851  {
2852  /* accept only, have one thread per connection */
2853  if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
2854  (! MHD_add_to_fd_set_ (daemon->socket_fd,
2855  &rs,
2856  &maxsock,
2857  FD_SETSIZE)) )
2858  {
2859 #ifdef HAVE_MESSAGES
2860  MHD_DLOG (daemon,
2861  _("Could not add listen socket to fdset"));
2862 #endif
2863  return MHD_NO;
2864  }
2865  }
2866  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
2867  (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc),
2868  &rs,
2869  &maxsock,
2870  FD_SETSIZE)) )
2871  {
2872 #if defined(MHD_WINSOCK_SOCKETS)
2873  /* fdset limit reached, new connections
2874  cannot be handled. Remove listen socket FD
2875  from fdset and retry to add ITC FD. */
2876  if (MHD_INVALID_SOCKET != daemon->socket_fd)
2877  {
2878  FD_CLR (daemon->socket_fd,
2879  &rs);
2880  if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
2881  &rs,
2882  &maxsock,
2883  FD_SETSIZE))
2884  {
2885 #endif /* MHD_WINSOCK_SOCKETS */
2886 #ifdef HAVE_MESSAGES
2887  MHD_DLOG (daemon,
2888  _("Could not add control inter-thread communication channel FD to fdset"));
2889 #endif
2890  err_state = MHD_YES;
2891 #if defined(MHD_WINSOCK_SOCKETS)
2892  }
2893  }
2894 #endif /* MHD_WINSOCK_SOCKETS */
2895  }
2896  /* Stop listening if we are at the configured connection limit */
2897  /* If we're at the connection limit, no point in really
2898  accepting new connections; however, make sure we do not miss
2899  the shutdown OR the termination of an existing connection; so
2900  only do this optimization if we have a signaling ITC in
2901  place. */
2902  if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
2903  (MHD_ITC_IS_VALID_(daemon->itc)) &&
2904  (0 != (daemon->options & MHD_USE_ITC)) &&
2905  ( (daemon->connections == daemon->connection_limit) ||
2906  (MHD_YES == daemon->at_limit) ) )
2907  {
2908  FD_CLR (daemon->socket_fd,
2909  &rs);
2910  }
2911  tv = NULL;
2912  if (MHD_YES == err_state)
2913  may_block = MHD_NO;
2914  if (MHD_NO == may_block)
2915  {
2916  timeout.tv_usec = 0;
2917  timeout.tv_sec = 0;
2918  tv = &timeout;
2919  }
2920  else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2921  (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) )
2922  {
2923  /* ltimeout is in ms */
2924  timeout.tv_usec = (ltimeout % 1000) * 1000;
2925  if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
2926  timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
2927  else
2928  timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)(ltimeout / 1000);
2929  tv = &timeout;
2930  }
2931  num_ready = MHD_SYS_select_ (maxsock + 1,
2932  &rs,
2933  &ws,
2934  &es,
2935  tv);
2936  if (MHD_YES == daemon->shutdown)
2937  return MHD_NO;
2938  if (num_ready < 0)
2939  {
2940  const int err = MHD_socket_get_error_ ();
2941  if (MHD_SCKT_ERR_IS_EINTR_(err))
2942  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
2943 #ifdef HAVE_MESSAGES
2944  MHD_DLOG (daemon,
2945  _("select failed: %s\n"),
2946  MHD_socket_strerr_ (err));
2947 #endif
2948  return MHD_NO;
2949  }
2950  if (MHD_YES == MHD_run_from_select (daemon,
2951  &rs,
2952  &ws,
2953  &es))
2954  return (MHD_NO == err_state) ? MHD_YES : MHD_NO;
2955  return MHD_NO;
2956 }
2957 
2958 
2959 #ifdef HAVE_POLL
2960 
2968 static int
2969 MHD_poll_all (struct MHD_Daemon *daemon,
2970  int may_block)
2971 {
2972  unsigned int num_connections;
2973  struct MHD_Connection *pos;
2974  struct MHD_Connection *next;
2975 #if HTTPS_SUPPORT
2976  struct MHD_UpgradeResponseHandle *urh;
2977  struct MHD_UpgradeResponseHandle *urhn;
2978 #endif
2979 
2980  if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) &&
2981  (MHD_YES == resume_suspended_connections (daemon)) )
2982  may_block = MHD_NO;
2983 
2984  /* count number of connections and thus determine poll set size */
2985  num_connections = 0;
2986  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
2987  num_connections++;
2988 #if HTTPS_SUPPORT
2989  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
2990  num_connections += 2;
2991 #endif
2992  {
2993  MHD_UNSIGNED_LONG_LONG ltimeout;
2994  unsigned int i;
2995  int timeout;
2996  unsigned int poll_server;
2997  int poll_listen;
2998  int poll_itc_idx;
2999  struct pollfd *p;
3000 
3001  p = malloc (sizeof (struct pollfd) * (2 + num_connections));
3002  if (NULL == p)
3003  {
3004 #ifdef HAVE_MESSAGES
3005  MHD_DLOG (daemon,
3006  _("Error allocating memory: %s\n"),
3007  MHD_strerror_(errno));
3008 #endif
3009  return MHD_NO;
3010  }
3011  memset (p,
3012  0,
3013  sizeof (struct pollfd) * (2 + num_connections));
3014  poll_server = 0;
3015  poll_listen = -1;
3016  if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
3017  (daemon->connections < daemon->connection_limit) &&
3018  (MHD_NO == daemon->at_limit) )
3019  {
3020  /* only listen if we are not at the connection limit */
3021  p[poll_server].fd = daemon->socket_fd;
3022  p[poll_server].events = POLLIN;
3023  p[poll_server].revents = 0;
3024  poll_listen = (int) poll_server;
3025  poll_server++;
3026  }
3027  poll_itc_idx = -1;
3028  if (MHD_ITC_IS_VALID_(daemon->itc))
3029  {
3030  p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
3031  p[poll_server].events = POLLIN;
3032  p[poll_server].revents = 0;
3033  poll_itc_idx = (int) poll_server;
3034  poll_server++;
3035  }
3036  if (may_block == MHD_NO)
3037  timeout = 0;
3038  else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3039  (MHD_YES != MHD_get_timeout (daemon,
3040  &ltimeout)) )
3041  timeout = -1;
3042  else
3043  timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
3044 
3045  i = 0;
3046  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
3047  {
3048  p[poll_server+i].fd = pos->socket_fd;
3049  switch (pos->event_loop_info)
3050  {
3052  p[poll_server+i].events |= POLLIN;
3053  break;
3055  p[poll_server+i].events |= POLLOUT;
3056  if (pos->read_buffer_size > pos->read_buffer_offset)
3057  p[poll_server+i].events |= POLLIN;
3058  break;
3060  if (pos->read_buffer_size > pos->read_buffer_offset)
3061  p[poll_server+i].events |= POLLIN;
3062  break;
3064  timeout = 0; /* clean up "pos" immediately */
3065  break;
3066  }
3067  i++;
3068  }
3069 #if HTTPS_SUPPORT
3070  for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
3071  {
3072  p[poll_server+i].fd = urh->connection->socket_fd;
3073  if (urh->in_buffer_off < urh->in_buffer_size)
3074  p[poll_server+i].events |= POLLIN;
3075  if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
3076  p[poll_server+i].events |= POLLOUT;
3077  i++;
3078  p[poll_server+i].fd = urh->mhd.socket;
3079  if (urh->out_buffer_off < urh->out_buffer_size)
3080  p[poll_server+i].events |= POLLIN;
3081  if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
3082  p[poll_server+i].events |= POLLOUT;
3083  i++;
3084  }
3085 #endif
3086  if (0 == poll_server + num_connections)
3087  {
3088  free(p);
3089  return MHD_YES;
3090  }
3091  if (MHD_sys_poll_(p,
3092  poll_server + num_connections,
3093  timeout) < 0)
3094  {
3095  const int err = MHD_socket_get_error_ ();
3096  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3097  {
3098  free(p);
3099  return MHD_YES;
3100  }
3101 #ifdef HAVE_MESSAGES
3102  MHD_DLOG (daemon,
3103  _("poll failed: %s\n"),
3104  MHD_socket_strerr_ (err));
3105 #endif
3106  free(p);
3107  return MHD_NO;
3108  }
3109  /* handle ITC FD */
3110  /* do it before any other processing so
3111  new signals will be processed in next loop */
3112  if ( (-1 != poll_itc_idx) &&
3113  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3114  MHD_itc_clear_ (daemon->itc);
3115 
3116  /* handle shutdown */
3117  if (MHD_YES == daemon->shutdown)
3118  {
3119  free(p);
3120  return MHD_NO;
3121  }
3122  i = 0;
3123  next = daemon->connections_head;
3124  while (NULL != (pos = next))
3125  {
3126  next = pos->next;
3127  /* first, sanity checks */
3128  if (i >= num_connections)
3129  break; /* connection list changed somehow, retry later ... */
3130  if (p[poll_server+i].fd != pos->socket_fd)
3131  continue; /* fd mismatch, something else happened, retry later ... */
3132  call_handlers (pos,
3133  0 != (p[poll_server+i].revents & POLLIN),
3134  0 != (p[poll_server+i].revents & POLLOUT),
3135  MHD_NO);
3136  i++;
3137  }
3138 #if HTTPS_SUPPORT
3139  for (urh = daemon->urh_head; NULL != urh; urh = urhn)
3140  {
3141  if (i >= num_connections)
3142  break; /* connection list changed somehow, retry later ... */
3143  urhn = urh->next;
3144  if (p[poll_server+i].fd != urh->connection->socket_fd)
3145  continue; /* fd mismatch, something else happened, retry later ... */
3146  if (0 != (p[poll_server+i].revents & POLLIN))
3147  urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
3148  if (0 != (p[poll_server+i].revents & POLLOUT))
3149  urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
3150  i++;
3151  if (p[poll_server+i].fd != urh->mhd.socket)
3152  {
3153  /* fd mismatch, something else happened, retry later ... */
3154  /* may still be able to do something based on updates
3155  to socket_fd availability */
3156  process_urh (urh);
3157  continue;
3158  }
3159  if (0 != (p[poll_server+i].revents & POLLIN))
3160  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
3161  if (0 != (p[poll_server+i].revents & POLLOUT))
3162  urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
3163  i++;
3164  process_urh (urh);
3165  }
3166 #endif
3167  /* handle 'listen' FD */
3168  if ( (-1 != poll_listen) &&
3169  (0 != (p[poll_listen].revents & POLLIN)) )
3170  (void) MHD_accept_connection (daemon);
3171 
3172  free(p);
3173  }
3174  return MHD_YES;
3175 }
3176 
3177 
3185 static int
3186 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3187  int may_block)
3188 {
3189  struct pollfd p[2];
3190  int timeout;
3191  unsigned int poll_count;
3192  int poll_listen;
3193  int poll_itc_idx;
3194 
3195  memset (&p,
3196  0,
3197  sizeof (p));
3198  poll_count = 0;
3199  poll_listen = -1;
3200  poll_itc_idx = -1;
3201  if (MHD_INVALID_SOCKET != daemon->socket_fd)
3202  {
3203  p[poll_count].fd = daemon->socket_fd;
3204  p[poll_count].events = POLLIN;
3205  p[poll_count].revents = 0;
3206  poll_listen = poll_count;
3207  poll_count++;
3208  }
3209  if (MHD_ITC_IS_VALID_(daemon->itc))
3210  {
3211  p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
3212  p[poll_count].events = POLLIN;
3213  p[poll_count].revents = 0;
3214  poll_itc_idx = poll_count;
3215  poll_count++;
3216  }
3217  if (MHD_NO == may_block)
3218  timeout = 0;
3219  else
3220  timeout = -1;
3221  if (0 == poll_count)
3222  return MHD_YES;
3223  if (MHD_sys_poll_(p,
3224  poll_count,
3225  timeout) < 0)
3226  {
3227  const int err = MHD_socket_get_error_ ();
3228 
3229  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3230  return MHD_YES;
3231 #ifdef HAVE_MESSAGES
3232  MHD_DLOG (daemon,
3233  _("poll failed: %s\n"),
3234  MHD_socket_strerr_ (err));
3235 #endif
3236  return MHD_NO;
3237  }
3238  if ( (-1 != poll_itc_idx) &&
3239  (0 != (p[poll_itc_idx].revents & POLLIN)) )
3240  MHD_itc_clear_ (daemon->itc);
3241 
3242  /* handle shutdown */
3243  if (MHD_YES == daemon->shutdown)
3244  return MHD_NO;
3245  if ( (-1 != poll_listen) &&
3246  (0 != (p[poll_listen].revents & POLLIN)) )
3247  (void) MHD_accept_connection (daemon);
3248  return MHD_YES;
3249 }
3250 #endif
3251 
3252 
3260 static int
3261 MHD_poll (struct MHD_Daemon *daemon,
3262  int may_block)
3263 {
3264 #ifdef HAVE_POLL
3265  if (MHD_YES == daemon->shutdown)
3266  return MHD_NO;
3267  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3268  return MHD_poll_all (daemon,
3269  may_block);
3270  return MHD_poll_listen_socket (daemon,
3271  may_block);
3272 #else
3273  return MHD_NO;
3274 #endif
3275 }
3276 
3277 
3278 #ifdef EPOLL_SUPPORT
3279 
3288 #define MAX_EVENTS 128
3289 
3290 
3291 #if HTTPS_SUPPORT
3292 
3299 static int
3300 run_epoll_for_upgrade (struct MHD_Daemon *daemon)
3301 {
3302  struct epoll_event events[MAX_EVENTS];
3303  int num_events;
3304  unsigned int i;
3305  unsigned int j;
3306 
3307  num_events = MAX_EVENTS;
3308  while (MAX_EVENTS == num_events)
3309  {
3310  /* update event masks */
3311  num_events = epoll_wait (daemon->epoll_upgrade_fd,
3312  events,
3313  MAX_EVENTS,
3314  0);
3315  if (-1 == num_events)
3316  {
3317  const int err = MHD_socket_get_error_ ();
3318  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3319  return MHD_YES;
3320 #ifdef HAVE_MESSAGES
3321  MHD_DLOG (daemon,
3322  _("Call to epoll_wait failed: %s\n"),
3323  MHD_socket_strerr_ (err));
3324 #endif
3325  return MHD_NO;
3326  }
3327  for (i=0;i<(unsigned int) num_events;i++)
3328  {
3329  struct UpgradeEpollHandle *ueh = events[i].data.ptr;
3330  struct MHD_UpgradeResponseHandle *urh;
3331 
3332  if (NULL == ueh)
3333  continue; /* was killed, see below */
3334  urh = ueh->urh;
3335 
3336  /* In case we get two events for the same upgrade handle,
3337  squash them together (otherwise the first one may
3338  cause us to free the 'urh', and the second one then
3339  causes a use-after-free). */
3340  for (j=i+1;j< (unsigned int) num_events;j++)
3341  {
3342  struct UpgradeEpollHandle *uehj = events[j].data.ptr;
3343  struct MHD_UpgradeResponseHandle *urhj;
3344 
3345  if (NULL == uehj)
3346  continue; /* was killed, see below */
3347  urhj = uehj->urh;
3348 
3349  if (urh == urhj) /* yep, indeed the same! */
3350  {
3351  if (0 != (events[j].events & EPOLLIN))
3353  if (0 != (events[j].events & EPOLLOUT))
3355  }
3356  events[j].data.ptr = NULL; /* kill this one */
3357  }
3358 
3359  /* Update our state based on what is ready according to epoll() */
3360  if (0 != (events[i].events & EPOLLIN))
3362  if (0 != (events[i].events & EPOLLOUT))
3364 
3365  /* shuffle data based on buffers and FD readyness */
3366  process_urh (urh);
3367  }
3368  }
3369  return MHD_YES;
3370 }
3371 #endif
3372 
3373 
3382 static int
3383 MHD_epoll (struct MHD_Daemon *daemon,
3384  int may_block)
3385 {
3386 #if HTTPS_SUPPORT
3387  static const char *upgrade_marker = "upgrade_ptr";
3388 #endif
3389  struct MHD_Connection *pos;
3390  struct MHD_Connection *next;
3391  struct epoll_event events[MAX_EVENTS];
3392  struct epoll_event event;
3393  int timeout_ms;
3394  MHD_UNSIGNED_LONG_LONG timeout_ll;
3395  int num_events;
3396  unsigned int i;
3397  unsigned int series_length;
3398 
3399  if (-1 == daemon->epoll_fd)
3400  return MHD_NO; /* we're down! */
3401  if (MHD_YES == daemon->shutdown)
3402  return MHD_NO;
3403  if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
3404  (daemon->connections < daemon->connection_limit) &&
3405  (MHD_NO == daemon->listen_socket_in_epoll) &&
3406  (MHD_NO == daemon->at_limit) )
3407  {
3408  event.events = EPOLLIN;
3409  event.data.ptr = daemon;
3410  if (0 != epoll_ctl (daemon->epoll_fd,
3411  EPOLL_CTL_ADD,
3412  daemon->socket_fd,
3413  &event))
3414  {
3415 #ifdef HAVE_MESSAGES
3416  MHD_DLOG (daemon,
3417  _("Call to epoll_ctl failed: %s\n"),
3419 #endif
3420  return MHD_NO;
3421  }
3422  daemon->listen_socket_in_epoll = MHD_YES;
3423  }
3424 #if HTTPS_SUPPORT
3425  if ( (MHD_NO == daemon->upgrade_fd_in_epoll) &&
3426  (-1 != daemon->epoll_upgrade_fd) )
3427  {
3428  event.events = EPOLLIN | EPOLLOUT;
3429  event.data.ptr = (void *) upgrade_marker;
3430  if (0 != epoll_ctl (daemon->epoll_fd,
3431  EPOLL_CTL_ADD,
3432  daemon->epoll_upgrade_fd,
3433  &event))
3434  {
3435 #ifdef HAVE_MESSAGES
3436  MHD_DLOG (daemon,
3437  _("Call to epoll_ctl failed: %s\n"),
3439 #endif
3440  return MHD_NO;
3441  }
3442  daemon->upgrade_fd_in_epoll = MHD_YES;
3443  }
3444 #endif
3445  if ( ( (MHD_YES == daemon->listen_socket_in_epoll) &&
3446  (daemon->connections == daemon->connection_limit) ) ||
3447  (MHD_YES == daemon->at_limit) )
3448  {
3449  /* we're at the connection limit, disable listen socket
3450  for event loop for now */
3451  if (0 != epoll_ctl (daemon->epoll_fd,
3452  EPOLL_CTL_DEL,
3453  daemon->socket_fd,
3454  NULL))
3455  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
3456  daemon->listen_socket_in_epoll = MHD_NO;
3457  }
3458  if (MHD_YES == may_block)
3459  {
3460  if (MHD_YES == MHD_get_timeout (daemon,
3461  &timeout_ll))
3462  {
3463  if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
3464  timeout_ms = INT_MAX;
3465  else
3466  timeout_ms = (int) timeout_ll;
3467  }
3468  else
3469  timeout_ms = -1;
3470  }
3471  else
3472  timeout_ms = 0;
3473 
3474  /* drain 'epoll' event queue; need to iterate as we get at most
3475  MAX_EVENTS in one system call here; in practice this should
3476  pretty much mean only one round, but better an extra loop here
3477  than unfair behavior... */
3478  num_events = MAX_EVENTS;
3479  while (MAX_EVENTS == num_events)
3480  {
3481  /* update event masks */
3482  num_events = epoll_wait (daemon->epoll_fd,
3483  events,
3484  MAX_EVENTS,
3485  timeout_ms);
3486  if (-1 == num_events)
3487  {
3488  const int err = MHD_socket_get_error_ ();
3489  if (MHD_SCKT_ERR_IS_EINTR_ (err))
3490  return MHD_YES;
3491 #ifdef HAVE_MESSAGES
3492  MHD_DLOG (daemon,
3493  _("Call to epoll_wait failed: %s\n"),
3494  MHD_socket_strerr_ (err));
3495 #endif
3496  return MHD_NO;
3497  }
3498  for (i=0;i<(unsigned int) num_events;i++)
3499  {
3500  /* First, check for the values of `ptr` that would indicate
3501  that this event is not about a normal connection. */
3502  if (NULL == events[i].data.ptr)
3503  continue; /* shutdown signal! */
3504 #if HTTPS_SUPPORT
3505  if (upgrade_marker == events[i].data.ptr)
3506  {
3507  /* activity on an upgraded connection, we process
3508  those in a separate epoll() */
3509  run_epoll_for_upgrade (daemon);
3510  continue;
3511  }
3512 #endif
3513  /* UGH: we're storing pointers and fds in the same union
3514  here; incredibly ugly and somewhat risky, even though a
3515  pointer with the same numeric value as the itc.fd[0] can
3516  be expected to be rare... FIXME (a construction similar
3517  to what we did with the `upgrade_marker` should do) */
3518  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
3519  (MHD_itc_r_fd_ (daemon->itc) == events[i].data.fd) )
3520  {
3521  /* It's OK to clear ITC here as all external
3522  conditions will be processed later. */
3523  MHD_itc_clear_ (daemon->itc);
3524  continue;
3525  }
3526  if (daemon == events[i].data.ptr)
3527  {
3528  /* run 'accept' until it fails or we are not allowed to take
3529  on more connections */
3530  series_length = 0;
3531  while ( (MHD_YES == MHD_accept_connection (daemon)) &&
3532  (daemon->connections < daemon->connection_limit) &&
3533  (series_length < 128) &&
3534  (MHD_NO == daemon->at_limit) )
3535  series_length++;
3536  continue;
3537  }
3538  /* this is an event relating to a 'normal' connection,
3539  remember the event and if appropriate mark the
3540  connection as 'eready'. */
3541  pos = events[i].data.ptr;
3542  /* normal processing: update read/write data */
3543  if (0 != (events[i].events & EPOLLIN))
3544  {
3545  pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
3546  if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
3547  (pos->read_buffer_size > pos->read_buffer_offset) ) &&
3548  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
3549  {
3550  EDLL_insert (daemon->eready_head,
3551  daemon->eready_tail,
3552  pos);
3553  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
3554  }
3555  }
3556  if (0 != (events[i].events & EPOLLOUT))
3557  {
3558  pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
3559  if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
3560  (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
3561  {
3562  EDLL_insert (daemon->eready_head,
3563  daemon->eready_tail,
3564  pos);
3565  pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
3566  }
3567  }
3568  }
3569  }
3570 
3571  /* we handle resumes here because we may have ready connections
3572  that will not be placed into the epoll list immediately. */
3574  (void) resume_suspended_connections (daemon);
3575 
3576  /* process events for connections */
3577  while (NULL != (pos = daemon->eready_tail))
3578  {
3579  EDLL_remove (daemon->eready_head,
3580  daemon->eready_tail,
3581  pos);
3582  pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3583  call_handlers (pos,
3586  MHD_NO);
3587  }
3588 
3589  /* Finally, handle timed-out connections; we need to do this here
3590  as the epoll mechanism won't call the 'idle_handler' on everything,
3591  as the other event loops do. As timeouts do not get an explicit
3592  event, we need to find those connections that might have timed out
3593  here.
3594 
3595  Connections with custom timeouts must all be looked at, as we
3596  do not bother to sort that (presumably very short) list. */
3597  next = daemon->manual_timeout_head;
3598  while (NULL != (pos = next))
3599  {
3600  next = pos->nextX;
3601  pos->idle_handler (pos);
3602  }
3603  /* Connections with the default timeout are sorted by prepending
3604  them to the head of the list whenever we touch the connection;
3605  thus it suffices to iterate from the tail until the first
3606  connection is NOT timed out */
3607  next = daemon->normal_timeout_tail;
3608  while (NULL != (pos = next))
3609  {
3610  next = pos->prevX;
3611  pos->idle_handler (pos);
3612  if (MHD_CONNECTION_CLOSED != pos->state)
3613  break; /* sorted by timeout, no need to visit the rest! */
3614  }
3615  return MHD_YES;
3616 }
3617 #endif
3618 
3619 
3639 int
3640 MHD_run (struct MHD_Daemon *daemon)
3641 {
3642  if ( (MHD_YES == daemon->shutdown) ||
3643  (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
3644  (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) )
3645  return MHD_NO;
3646  if (0 != (daemon->options & MHD_USE_POLL))
3647  {
3648  MHD_poll (daemon, MHD_NO);
3649  MHD_cleanup_connections (daemon);
3650  }
3651 #ifdef EPOLL_SUPPORT
3652  else if (0 != (daemon->options & MHD_USE_EPOLL))
3653  {
3654  MHD_epoll (daemon, MHD_NO);
3655  MHD_cleanup_connections (daemon);
3656  }
3657 #endif
3658  else
3659  {
3660  MHD_select (daemon, MHD_NO);
3661  /* MHD_select does MHD_cleanup_connections already */
3662  }
3663  return MHD_YES;
3664 }
3665 
3666 
3673 static void
3675 {
3676  struct MHD_Daemon *daemon = pos->daemon;
3677 
3678  MHD_connection_close_ (pos,
3680  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3681  return; /* must let thread to the rest */
3682  if (pos->connection_timeout == pos->daemon->connection_timeout)
3684  daemon->normal_timeout_tail,
3685  pos);
3686  else
3688  daemon->manual_timeout_tail,
3689  pos);
3690  DLL_remove (daemon->connections_head,
3691  daemon->connections_tail,
3692  pos);
3694  DLL_insert (daemon->cleanup_head,
3695  daemon->cleanup_tail,
3696  pos);
3697 }
3698 
3699 
3707 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
3709 {
3710  struct MHD_Daemon *daemon = cls;
3711  struct MHD_Connection *pos;
3712 
3713  while (MHD_YES != daemon->shutdown)
3714  {
3715  if (0 != (daemon->options & MHD_USE_POLL))
3716  MHD_poll (daemon, MHD_YES);
3717 #ifdef EPOLL_SUPPORT
3718  else if (0 != (daemon->options & MHD_USE_EPOLL))
3719  MHD_epoll (daemon, MHD_YES);
3720 #endif
3721  else
3722  MHD_select (daemon, MHD_YES);
3723  MHD_cleanup_connections (daemon);
3724  }
3725 
3726  /* give resumed formerly suspended connections a chance to
3727  be included in the cleanup */
3729  /* run clean up in this thread as well */
3730  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3731  {
3732  /* We did everything in this thread, so also the clean up */
3733  while (NULL != (pos = daemon->connections_head))
3734  close_connection (pos);
3735  }
3736  return (MHD_THRD_RTRN_TYPE_)0;
3737 }
3738 
3739 
3751 static size_t
3752 unescape_wrapper (void *cls,
3753  struct MHD_Connection *connection,
3754  char *val)
3755 {
3756  return MHD_http_unescape (val);
3757 }
3758 
3759 
3776 struct MHD_Daemon *
3777 MHD_start_daemon (unsigned int flags,
3778  uint16_t port,
3780  void *apc_cls,
3782  void *dh_cls,
3783  ...)
3784 {
3785  struct MHD_Daemon *daemon;
3786  va_list ap;
3787 
3788  va_start (ap,
3789  dh_cls);
3790  daemon = MHD_start_daemon_va (flags,
3791  port,
3792  apc,
3793  apc_cls,
3794  dh,
3795  dh_cls,
3796  ap);
3797  va_end (ap);
3798  return daemon;
3799 }
3800 
3801 
3821 MHD_socket
3823 {
3824  unsigned int i;
3825  MHD_socket ret;
3826 
3827  ret = daemon->socket_fd;
3828  if (MHD_INVALID_SOCKET == ret)
3829  return MHD_INVALID_SOCKET;
3830  if ( (MHD_ITC_IS_INVALID_(daemon->itc)) &&
3832  {
3833 #ifdef HAVE_MESSAGES
3834  MHD_DLOG (daemon,
3835  "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
3836 #endif
3837  return MHD_INVALID_SOCKET;
3838  }
3839 
3840  if (NULL != daemon->worker_pool)
3841  for (i = 0; i < daemon->worker_pool_size; i++)
3842  {
3844 #ifdef EPOLL_SUPPORT
3845  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3846  (-1 != daemon->worker_pool[i].epoll_fd) &&
3847  (MHD_YES == daemon->worker_pool[i].listen_socket_in_epoll) )
3848  {
3849  if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
3850  EPOLL_CTL_DEL,
3851  ret,
3852  NULL))
3853  MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
3854  daemon->worker_pool[i].listen_socket_in_epoll = MHD_NO;
3855  }
3856  else
3857 #endif
3858  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
3859  {
3860  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
3861  MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
3862  }
3863  }
3864  daemon->socket_fd = MHD_INVALID_SOCKET;
3865 #ifdef EPOLL_SUPPORT
3866  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3867  (-1 != daemon->epoll_fd) &&
3868  (MHD_YES == daemon->listen_socket_in_epoll) )
3869  {
3870  if (0 != epoll_ctl (daemon->epoll_fd,
3871  EPOLL_CTL_DEL,
3872  ret,
3873  NULL))
3874  MHD_PANIC ("Failed to remove listen FD from epoll set\n");
3875  daemon->listen_socket_in_epoll = MHD_NO;
3876  }
3877  else
3878 #endif
3879  if (MHD_ITC_IS_VALID_(daemon->itc))
3880  {
3881  if (! MHD_itc_activate_ (daemon->itc, "q"))
3882  MHD_PANIC (_("failed to signal quiesce via inter-thread communication channel"));
3883  }
3884 
3885  return ret;
3886 }
3887 
3888 
3896 typedef void
3898  const char *format,
3899  va_list va);
3900 
3901 
3910 static int
3911 parse_options_va (struct MHD_Daemon *daemon,
3912  const struct sockaddr **servaddr,
3913  va_list ap);
3914 
3915 
3924 static int
3925 parse_options (struct MHD_Daemon *daemon,
3926  const struct sockaddr **servaddr,
3927  ...)
3928 {
3929  va_list ap;
3930  int ret;
3931 
3932  va_start (ap, servaddr);
3933  ret = parse_options_va (daemon,
3934  servaddr,
3935  ap);
3936  va_end (ap);
3937  return ret;
3938 }
3939 
3940 
3949 static int
3951  const struct sockaddr **servaddr,
3952  va_list ap)
3953 {
3954  enum MHD_OPTION opt;
3955  struct MHD_OptionItem *oa;
3956  unsigned int i;
3957 #if HTTPS_SUPPORT
3958  int ret;
3959  const char *pstr;
3960 #endif
3961 
3962  while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
3963  {
3964  switch (opt)
3965  {
3967  daemon->pool_size = va_arg (ap,
3968  size_t);
3969  break;
3971  daemon->pool_increment= va_arg (ap,
3972  size_t);
3973  break;
3975  daemon->connection_limit = va_arg (ap,
3976  unsigned int);
3977  break;
3979  daemon->connection_timeout = va_arg (ap,
3980  unsigned int);
3981  break;
3983  daemon->notify_completed = va_arg (ap,
3985  daemon->notify_completed_cls = va_arg (ap,
3986  void *);
3987  break;
3989  daemon->notify_connection = va_arg (ap,
3991  daemon->notify_connection_cls = va_arg (ap,
3992  void *);
3993  break;
3995  daemon->per_ip_connection_limit = va_arg (ap,
3996  unsigned int);
3997  break;
3998  case MHD_OPTION_SOCK_ADDR:
3999  *servaddr = va_arg (ap,
4000  const struct sockaddr *);
4001  break;
4003  daemon->uri_log_callback = va_arg (ap,
4004  LogCallback);
4005  daemon->uri_log_callback_cls = va_arg (ap,
4006  void *);
4007  break;
4009  daemon->worker_pool_size = va_arg (ap,
4010  unsigned int);
4011  if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct MHD_Daemon)))
4012  {
4013 #ifdef HAVE_MESSAGES
4014  MHD_DLOG (daemon,
4015  _("Specified thread pool size (%u) too big\n"),
4016  daemon->worker_pool_size);
4017 #endif
4018  return MHD_NO;
4019  }
4020  break;
4021 #if HTTPS_SUPPORT
4023  if (0 != (daemon->options & MHD_USE_TLS))
4024  daemon->https_mem_key = va_arg (ap,
4025  const char *);
4026 #ifdef HAVE_MESSAGES
4027  else
4028  MHD_DLOG (daemon,
4029  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4030  opt);
4031 #endif
4032  break;
4034  if (0 != (daemon->options & MHD_USE_TLS))
4035  daemon->https_key_password = va_arg (ap,
4036  const char *);
4037 #ifdef HAVE_MESSAGES
4038  else
4039  MHD_DLOG (daemon,
4040  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4041  opt);
4042 #endif
4043  break;
4045  if (0 != (daemon->options & MHD_USE_TLS))
4046  daemon->https_mem_cert = va_arg (ap,
4047  const char *);
4048 #ifdef HAVE_MESSAGES
4049  else
4050  MHD_DLOG (daemon,
4051  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4052  opt);
4053 #endif
4054  break;
4056  if (0 != (daemon->options & MHD_USE_TLS))
4057  daemon->https_mem_trust = va_arg (ap,
4058  const char *);
4059 #ifdef HAVE_MESSAGES
4060  else
4061  MHD_DLOG (daemon,
4062  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4063  opt);
4064 #endif
4065  break;
4067  daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4068  int);
4069  break;
4071  if (0 != (daemon->options & MHD_USE_TLS))
4072  {
4073  const char *arg = va_arg (ap,
4074  const char *);
4075  gnutls_datum_t dhpar;
4076 
4077  if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4078  {
4079 #ifdef HAVE_MESSAGES
4080  MHD_DLOG (daemon,
4081  _("Error initializing DH parameters\n"));
4082 #endif
4083  return MHD_NO;
4084  }
4085  dhpar.data = (unsigned char *) arg;
4086  dhpar.size = strlen (arg);
4087  if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4088  &dhpar,
4089  GNUTLS_X509_FMT_PEM) < 0)
4090  {
4091 #ifdef HAVE_MESSAGES
4092  MHD_DLOG (daemon,
4093  _("Bad Diffie-Hellman parameters format\n"));
4094 #endif
4095  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4096  return MHD_NO;
4097  }
4098  daemon->have_dhparams = MHD_YES;
4099  }
4100  else
4101  {
4102 #ifdef HAVE_MESSAGES
4103  MHD_DLOG (daemon,
4104  _("MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4105  opt);
4106 #endif
4107  return MHD_NO;
4108  }
4109  break;
4111  if (0 != (daemon->options & MHD_USE_TLS))
4112  {
4113  gnutls_priority_deinit (daemon->priority_cache);
4114  ret = gnutls_priority_init (&daemon->priority_cache,
4115  pstr = va_arg (ap, const char*),
4116  NULL);
4117  if (GNUTLS_E_SUCCESS != ret)
4118  {
4119 #ifdef HAVE_MESSAGES
4120  MHD_DLOG (daemon,
4121  _("Setting priorities to `%s' failed: %s\n"),
4122  pstr,
4123  gnutls_strerror (ret));
4124 #endif
4125  daemon->priority_cache = NULL;
4126  return MHD_NO;
4127  }
4128  }
4129  break;
4131 #if GNUTLS_VERSION_MAJOR < 3
4132 #ifdef HAVE_MESSAGES
4133  MHD_DLOG (daemon,
4134  _("MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
4135 #endif
4136  return MHD_NO;
4137 #else
4138  if (0 != (daemon->options & MHD_USE_TLS))
4139  daemon->cert_callback = va_arg (ap,
4140  gnutls_certificate_retrieve_function2 *);
4141  break;
4142 #endif
4143 #endif
4144 #ifdef DAUTH_SUPPORT
4146  daemon->digest_auth_rand_size = va_arg (ap,
4147  size_t);
4148  daemon->digest_auth_random = va_arg (ap,
4149  const char *);
4150  break;
4152  daemon->nonce_nc_size = va_arg (ap,
4153  unsigned int);
4154  break;
4155 #endif
4157  daemon->socket_fd = va_arg (ap,
4158  MHD_socket);
4159  break;
4161 #ifdef HAVE_MESSAGES
4162  daemon->custom_error_log = va_arg (ap,
4164  daemon->custom_error_log_cls = va_arg (ap,
4165  void *);
4166 #else
4167  va_arg (ap,
4169  va_arg (ap,
4170  void *);
4171 #endif
4172  break;
4174  daemon->thread_stack_size = va_arg (ap,
4175  size_t);
4176  break;
4177 #ifdef TCP_FASTOPEN
4179  daemon->fastopen_queue_size = va_arg (ap,
4180  unsigned int);
4181  break;
4182 #endif
4184  daemon->listening_address_reuse = va_arg (ap,
4185  unsigned int) ? 1 : -1;
4186  break;
4188  daemon->listen_backlog_size = va_arg (ap,
4189  unsigned int);
4190  break;
4191  case MHD_OPTION_ARRAY:
4192  oa = va_arg (ap, struct MHD_OptionItem*);
4193  i = 0;
4194  while (MHD_OPTION_END != (opt = oa[i].option))
4195  {
4196  switch (opt)
4197  {
4198  /* all options taking 'size_t' */
4202  if (MHD_YES != parse_options (daemon,
4203  servaddr,
4204  opt,
4205  (size_t) oa[i].value,
4206  MHD_OPTION_END))
4207  return MHD_NO;
4208  break;
4209  /* all options taking 'unsigned int' */
4218  if (MHD_YES != parse_options (daemon,
4219  servaddr,
4220  opt,
4221  (unsigned int) oa[i].value,
4222  MHD_OPTION_END))
4223  return MHD_NO;
4224  break;
4225  /* all options taking 'enum' */
4227  if (MHD_YES != parse_options (daemon,
4228  servaddr,
4229  opt,
4230  (int) oa[i].value,
4231  MHD_OPTION_END))
4232  return MHD_NO;
4233  break;
4234  /* all options taking 'MHD_socket' */
4236  if (MHD_YES != parse_options (daemon,
4237  servaddr,
4238  opt,
4239  (MHD_socket) oa[i].value,
4240  MHD_OPTION_END))
4241  return MHD_NO;
4242  break;
4243  /* all options taking one pointer */
4244  case MHD_OPTION_SOCK_ADDR:
4251  case MHD_OPTION_ARRAY:
4253  if (MHD_YES != parse_options (daemon,
4254  servaddr,
4255  opt,
4256  oa[i].ptr_value,
4257  MHD_OPTION_END))
4258  return MHD_NO;
4259  break;
4260  /* all options taking two pointers */
4266  if (MHD_YES != parse_options (daemon,
4267  servaddr,
4268  opt,
4269  (void *) oa[i].value,
4270  oa[i].ptr_value,
4271  MHD_OPTION_END))
4272  return MHD_NO;
4273  break;
4274  /* options taking size_t-number followed by pointer */
4276  if (MHD_YES != parse_options (daemon,
4277  servaddr,
4278  opt,
4279  (size_t) oa[i].value,
4280  oa[i].ptr_value,
4281  MHD_OPTION_END))
4282  return MHD_NO;
4283  break;
4284  default:
4285  return MHD_NO;
4286  }
4287  i++;
4288  }
4289  break;
4291  daemon->unescape_callback = va_arg (ap,
4293  daemon->unescape_callback_cls = va_arg (ap,
4294  void *);
4295  break;
4296  default:
4297 #ifdef HAVE_MESSAGES
4298  if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
4299  (opt <= MHD_OPTION_HTTPS_PRIORITIES) ) ||
4300  (opt == MHD_OPTION_HTTPS_MEM_TRUST))
4301  {
4302  MHD_DLOG (daemon,
4303  _("MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
4304  opt);
4305  }
4306  else
4307  {
4308  MHD_DLOG (daemon,
4309  _("Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
4310  opt);
4311  }
4312 #endif
4313  return MHD_NO;
4314  }
4315  }
4316  return MHD_YES;
4317 }
4318 
4319 
4320 #ifdef EPOLL_SUPPORT
4321 static int
4322 setup_epoll_fd (struct MHD_Daemon *daemon)
4323 {
4324  int fd;
4325 
4326 #ifdef USE_EPOLL_CREATE1
4327  fd = epoll_create1 (EPOLL_CLOEXEC);
4328 #else /* ! USE_EPOLL_CREATE1 */
4329  fd = epoll_create (MAX_EVENTS);
4330 #endif /* ! USE_EPOLL_CREATE1 */
4331  if (MHD_INVALID_SOCKET == fd)
4332  {
4333 #ifdef HAVE_MESSAGES
4334  MHD_DLOG (daemon,
4335  _("Call to epoll_create1 failed: %s\n"),
4337 #endif
4338  return MHD_INVALID_SOCKET;
4339  }
4340 #if !defined(USE_EPOLL_CREATE1)
4341  if (! MHD_socket_noninheritable_ (fd))
4342  {
4343 #ifdef HAVE_MESSAGES
4344  MHD_DLOG (daemon,
4345  _("Failed to set noninheritable mode on epoll FD.\n"));
4346 #endif
4347  }
4348 #endif /* ! USE_EPOLL_CREATE1 */
4349  return fd;
4350 }
4351 
4352 
4360 static int
4361 setup_epoll_to_listen (struct MHD_Daemon *daemon)
4362 {
4363  struct epoll_event event;
4364 
4365  daemon->epoll_fd = setup_epoll_fd (daemon);
4366  if (-1 == daemon->epoll_fd)
4367  return MHD_NO;
4368 #if HTTPS_SUPPORT
4370  {
4371  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
4372  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
4373  return MHD_NO;
4374  }
4375 #endif
4376  if (MHD_INVALID_SOCKET == daemon->socket_fd)
4377  return MHD_YES; /* non-listening daemon */
4378  event.events = EPOLLIN;
4379  event.data.ptr = daemon;
4380  if (0 != epoll_ctl (daemon->epoll_fd,
4381  EPOLL_CTL_ADD,
4382  daemon->socket_fd,
4383  &event))
4384  {
4385 #ifdef HAVE_MESSAGES
4386  MHD_DLOG (daemon,
4387  _("Call to epoll_ctl failed: %s\n"),
4389 #endif
4390  return MHD_NO;
4391  }
4392  if ( (MHD_ITC_IS_VALID_(daemon->itc)) &&
4394  {
4395  event.events = EPOLLIN | EPOLLET;
4396  event.data.ptr = NULL;
4397  event.data.fd = MHD_itc_r_fd_ (daemon->itc);
4398  if (0 != epoll_ctl (daemon->epoll_fd,
4399  EPOLL_CTL_ADD,
4400  MHD_itc_r_fd_ (daemon->itc),
4401  &event))
4402  {
4403 #ifdef HAVE_MESSAGES
4404  MHD_DLOG (daemon,
4405  _("Call to epoll_ctl failed: %s\n"),
4407 #endif
4408  return MHD_NO;
4409  }
4410  }
4411  daemon->listen_socket_in_epoll = MHD_YES;
4412  return MHD_YES;
4413 }
4414 #endif
4415 
4416 
4434 struct MHD_Daemon *
4435 MHD_start_daemon_va (unsigned int flags,
4436  uint16_t port,
4438  void *apc_cls,
4440  void *dh_cls,
4441  va_list ap)
4442 {
4443  const MHD_SCKT_OPT_BOOL_ on = 1;
4444  struct MHD_Daemon *daemon;
4446  struct sockaddr_in servaddr4;
4447 #if HAVE_INET6
4448  struct sockaddr_in6 servaddr6;
4449 #endif
4450  const struct sockaddr *servaddr = NULL;
4451  socklen_t addrlen;
4452  unsigned int i;
4453  int use_itc;
4454 
4455 #ifndef HAVE_INET6
4456  if (0 != (flags & MHD_USE_IPv6))
4457  return NULL;
4458 #endif
4459 #ifndef HAVE_POLL
4460  if (0 != (flags & MHD_USE_POLL))
4461  return NULL;
4462 #endif
4463 #if ! HTTPS_SUPPORT
4464  if (0 != (flags & MHD_USE_TLS))
4465  return NULL;
4466 #endif
4467 #ifndef TCP_FASTOPEN
4468  if (0 != (flags & MHD_USE_TCP_FASTOPEN))
4469  return NULL;
4470 #endif
4471  if (NULL == dh)
4472  return NULL;
4473  if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon))))
4474  return NULL;
4475  memset (daemon,
4476  0,
4477  sizeof (struct MHD_Daemon));
4478 #ifdef EPOLL_SUPPORT
4479  daemon->epoll_fd = -1;
4480 #if HTTPS_SUPPORT
4481  daemon->epoll_upgrade_fd = -1;
4482 #endif
4483 #endif
4484  /* try to open listen socket */
4485 #if HTTPS_SUPPORT
4486  if (0 != (flags & MHD_USE_TLS))
4487  {
4488  gnutls_priority_init (&daemon->priority_cache,
4489  "@SYSTEM",
4490  NULL);
4491  }
4492 #endif
4493  daemon->socket_fd = MHD_INVALID_SOCKET;
4494  daemon->listening_address_reuse = 0;
4495  daemon->options = flags;
4496  daemon->port = port;
4497  daemon->apc = apc;
4498  daemon->apc_cls = apc_cls;
4499  daemon->default_handler = dh;
4500  daemon->default_handler_cls = dh_cls;
4501  daemon->connections = 0;
4503  daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
4504  daemon->pool_increment = MHD_BUF_INC_SIZE;
4506  daemon->connection_timeout = 0; /* no timeout */
4507  MHD_itc_set_invalid_ (daemon->itc);
4508 #ifdef SOMAXCONN
4509  daemon->listen_backlog_size = SOMAXCONN;
4510 #else /* !SOMAXCONN */
4511  daemon->listen_backlog_size = 511; /* should be safe value */
4512 #endif /* !SOMAXCONN */
4513 #ifdef HAVE_MESSAGES
4514  daemon->custom_error_log = (MHD_LogCallback) &vfprintf;
4515  daemon->custom_error_log_cls = stderr;
4516 #endif
4517 #ifdef HAVE_LISTEN_SHUTDOWN
4518  use_itc = (0 != (daemon->options & (MHD_USE_NO_LISTEN_SOCKET | MHD_USE_ITC)));
4519 #else
4520  use_itc = 1; /* yes, must use ITC to signal thread */
4521 #endif
4523  use_itc = 0; /* useless if we are using 'external' select */
4524  if (use_itc)
4525  {
4526  if (! MHD_itc_init_ (daemon->itc))
4527  {
4528 #ifdef HAVE_MESSAGES
4529  MHD_DLOG (daemon,
4530  _("Failed to create inter-thread communication channel: %s\n"),
4531  MHD_itc_last_strerror_ ());
4532 #endif
4533  free (daemon);
4534  return NULL;
4535  }
4536  }
4537  if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
4538  (1 == use_itc) &&
4539  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
4540  NULL)) )
4541  {
4542 #ifdef HAVE_MESSAGES
4543  MHD_DLOG (daemon,
4544  _("file descriptor for inter-thread communication channel exceeds maximum value\n"));
4545 #endif
4546  MHD_itc_destroy_chk_ (daemon->itc);
4547  free (daemon);
4548  return NULL;
4549  }
4550 #ifdef DAUTH_SUPPORT
4551  daemon->digest_auth_rand_size = 0;
4552  daemon->digest_auth_random = NULL;
4553  daemon->nonce_nc_size = 4; /* tiny */
4554 #endif
4555 #if HTTPS_SUPPORT
4556  if (0 != (flags & MHD_USE_TLS))
4557  {
4558  daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
4559  }
4560 #endif
4561 
4562 
4563  if (MHD_YES != parse_options_va (daemon,
4564  &servaddr,
4565  ap))
4566  {
4567 #if HTTPS_SUPPORT
4568  if ( (0 != (flags & MHD_USE_TLS)) &&
4569  (NULL != daemon->priority_cache) )
4570  gnutls_priority_deinit (daemon->priority_cache);
4571 #endif
4572  free (daemon);
4573  return NULL;
4574  }
4575 #ifdef DAUTH_SUPPORT
4576  if (daemon->nonce_nc_size > 0)
4577  {
4578  if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc))) /
4579  sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
4580  {
4581 #ifdef HAVE_MESSAGES
4582  MHD_DLOG (daemon,
4583  _("Specified value for NC_SIZE too large\n"));
4584 #endif
4585 #if HTTPS_SUPPORT
4586  if (0 != (flags & MHD_USE_TLS))
4587  gnutls_priority_deinit (daemon->priority_cache);
4588 #endif
4589  free (daemon);
4590  return NULL;
4591  }
4592  daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
4593  if (NULL == daemon->nnc)
4594  {
4595 #ifdef HAVE_MESSAGES
4596  MHD_DLOG (daemon,
4597  _("Failed to allocate memory for nonce-nc map: %s\n"),
4598  MHD_strerror_ (errno));
4599 #endif
4600 #if HTTPS_SUPPORT
4601  if (0 != (flags & MHD_USE_TLS))
4602  gnutls_priority_deinit (daemon->priority_cache);
4603 #endif
4604  free (daemon);
4605  return NULL;
4606  }
4607  }
4608 
4609  if (! MHD_mutex_init_ (&daemon->nnc_lock))
4610  {
4611 #ifdef HAVE_MESSAGES
4612  MHD_DLOG (daemon,
4613  _("MHD failed to initialize nonce-nc mutex\n"));
4614 #endif
4615 #if HTTPS_SUPPORT
4616  if (0 != (flags & MHD_USE_TLS))
4617  gnutls_priority_deinit (daemon->priority_cache);
4618 #endif
4619  free (daemon->nnc);
4620  free (daemon);
4621  return NULL;
4622  }
4623 #endif
4624 
4625  /* Thread pooling currently works only with internal select thread model */
4626  if ( (0 == (flags & MHD_USE_SELECT_INTERNALLY)) &&
4627  (daemon->worker_pool_size > 0) )
4628  {
4629 #ifdef HAVE_MESSAGES
4630  MHD_DLOG (daemon,
4631  _("MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n"));
4632 #endif
4633  goto free_and_fail;
4634  }
4635 
4636  if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
4637  (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) )
4638  {
4639 #ifdef HAVE_MESSAGES
4640  MHD_DLOG (daemon,
4641  _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_SUSPEND_RESUME is not supported.\n"));
4642 #endif
4643  goto free_and_fail;
4644  }
4645 
4646 #ifdef __SYMBIAN32__
4647  if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
4648  {
4649 #ifdef HAVE_MESSAGES
4650  MHD_DLOG (daemon,
4651  _("Threaded operations are not supported on Symbian.\n"));
4652 #endif
4653  goto free_and_fail;
4654  }
4655 #endif
4656  if ( (MHD_INVALID_SOCKET == daemon->socket_fd) &&
4657  (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
4658  {
4659  /* try to open listen socket */
4660  socket_fd = MHD_socket_create_listen_(flags & MHD_USE_IPv6);
4661  if (MHD_INVALID_SOCKET == socket_fd)
4662  {
4663 #ifdef HAVE_MESSAGES
4664  MHD_DLOG (daemon,
4665  _("Failed to create socket for listening: %s\n"),
4667 #endif
4668  goto free_and_fail;
4669  }
4670 
4671  /* Apply the socket options according to listening_address_reuse. */
4672  if (0 == daemon->listening_address_reuse)
4673  {
4674  /* No user requirement, use "traditional" default SO_REUSEADDR,
4675  and do not fail if it doesn't work */
4676  if (0 > setsockopt (socket_fd,
4677  SOL_SOCKET,
4678  SO_REUSEADDR,
4679  (void*)&on, sizeof (on)))
4680  {
4681 #ifdef HAVE_MESSAGES
4682  MHD_DLOG (daemon,
4683  _("setsockopt failed: %s\n"),
4685 #endif
4686  }
4687  }
4688  else if (daemon->listening_address_reuse > 0)
4689  {
4690  /* User requested to allow reusing listening address:port.
4691  * Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
4692  * Fail if SO_REUSEPORT does not exist or setsockopt fails.
4693  */
4694 #ifdef _WIN32
4695  /* SO_REUSEADDR on W32 has the same semantics
4696  as SO_REUSEPORT on BSD/Linux */
4697  if (0 > setsockopt (socket_fd,
4698  SOL_SOCKET,
4699  SO_REUSEADDR,
4700  (void*)&on, sizeof (on)))
4701  {
4702 #ifdef HAVE_MESSAGES
4703  MHD_DLOG (daemon,
4704  "setsockopt failed: %s\n",
4706 #endif
4707  goto free_and_fail;
4708  }
4709 #else
4710 #ifndef SO_REUSEPORT
4711 #ifdef LINUX
4712 /* Supported since Linux 3.9, but often not present (or commented out)
4713  in the headers at this time; but 15 is reserved for this and
4714  thus should be safe to use. */
4715 #define SO_REUSEPORT 15
4716 #endif
4717 #endif
4718 #ifdef SO_REUSEPORT
4719  if (0 > setsockopt (socket_fd,
4720  SOL_SOCKET,
4721  SO_REUSEPORT,
4722  (void *) &on,
4723  sizeof (on)))
4724  {
4725 #ifdef HAVE_MESSAGES
4726  MHD_DLOG (daemon,
4727  _("setsockopt failed: %s\n"),
4729 #endif
4730  goto free_and_fail;
4731  }
4732 #else
4733  /* we're supposed to allow address:port re-use, but
4734  on this platform we cannot; fail hard */
4735 #ifdef HAVE_MESSAGES
4736  MHD_DLOG (daemon,
4737  _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
4738 #endif
4739  goto free_and_fail;
4740 #endif
4741 #endif
4742  }
4743  else /* if (daemon->listening_address_reuse < 0) */
4744  {
4745  /* User requested to disallow reusing listening address:port.
4746  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
4747  * is used. Fail if it does not exist or setsockopt fails.
4748  */
4749 #ifdef _WIN32
4750 #ifdef SO_EXCLUSIVEADDRUSE
4751  if (0 > setsockopt (socket_fd,
4752  SOL_SOCKET,
4753  SO_EXCLUSIVEADDRUSE,
4754  (void *) &on,
4755  sizeof (on)))
4756  {
4757 #ifdef HAVE_MESSAGES
4758  MHD_DLOG (daemon,
4759  _("setsockopt failed: %s\n"),
4761 #endif
4762  goto free_and_fail;
4763  }
4764 #else /* SO_EXCLUSIVEADDRUSE not defined on W32? */
4765 #ifdef HAVE_MESSAGES
4766  MHD_DLOG (daemon,
4767  _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
4768 #endif
4769  goto free_and_fail;
4770 #endif
4771 #endif /* _WIN32 */
4772  }
4773 
4774  /* check for user supplied sockaddr */
4775 #if HAVE_INET6
4776  if (0 != (flags & MHD_USE_IPv6))
4777  addrlen = sizeof (struct sockaddr_in6);
4778  else
4779 #endif
4780  addrlen = sizeof (struct sockaddr_in);
4781  if (NULL == servaddr)
4782  {
4783 #if HAVE_INET6
4784  if (0 != (flags & MHD_USE_IPv6))
4785  {
4786  memset (&servaddr6,
4787  0,
4788  sizeof (struct sockaddr_in6));
4789  servaddr6.sin6_family = AF_INET6;
4790  servaddr6.sin6_port = htons (port);
4791 #if HAVE_SOCKADDR_IN_SIN_LEN
4792  servaddr6.sin6_len = sizeof (struct sockaddr_in6);
4793 #endif
4794  servaddr = (struct sockaddr *) &servaddr6;
4795  }
4796  else
4797 #endif
4798  {
4799  memset (&servaddr4,
4800  0,
4801  sizeof (struct sockaddr_in));
4802  servaddr4.sin_family = AF_INET;
4803  servaddr4.sin_port = htons (port);
4804 #if HAVE_SOCKADDR_IN_SIN_LEN
4805  servaddr4.sin_len = sizeof (struct sockaddr_in);
4806 #endif
4807  servaddr = (struct sockaddr *) &servaddr4;
4808  }
4809  }
4810  daemon->socket_fd = socket_fd;
4811 
4812  if (0 != (flags & MHD_USE_IPv6))
4813  {
4814 #ifdef IPPROTO_IPV6
4815 #ifdef IPV6_V6ONLY
4816  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
4817  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
4818  and may also be missing on older POSIX systems; good luck if you have any of those,
4819  your IPv6 socket may then also bind against IPv4 anyway... */
4820  const MHD_SCKT_OPT_BOOL_ v6_only =
4821  (MHD_USE_DUAL_STACK != (flags & MHD_USE_DUAL_STACK));
4822  if (0 > setsockopt (socket_fd,
4823  IPPROTO_IPV6, IPV6_V6ONLY,
4824  (const void *) &v6_only,
4825  sizeof (v6_only)))
4826  {
4827 #ifdef HAVE_MESSAGES
4828  MHD_DLOG (daemon,
4829  _("setsockopt failed: %s\n"),
4831 #endif
4832  }
4833 #endif
4834 #endif
4835  }
4836  if (-1 == bind (socket_fd, servaddr, addrlen))
4837  {
4838 #ifdef HAVE_MESSAGES
4839  MHD_DLOG (daemon,
4840  _("Failed to bind to port %u: %s\n"),
4841  (unsigned int) port,
4843 #endif
4844  MHD_socket_close_chk_ (socket_fd);
4845  goto free_and_fail;
4846  }
4847 #ifdef TCP_FASTOPEN
4848  if (0 != (flags & MHD_USE_TCP_FASTOPEN))
4849  {
4850  if (0 == daemon->fastopen_queue_size)
4851  daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
4852  if (0 != setsockopt (socket_fd,
4853  IPPROTO_TCP,
4854  TCP_FASTOPEN,
4855  &daemon->fastopen_queue_size,
4856  sizeof (daemon->fastopen_queue_size)))
4857  {
4858 #ifdef HAVE_MESSAGES
4859  MHD_DLOG (daemon,
4860  _("setsockopt failed: %s\n"),
4862 #endif
4863  }
4864  }
4865 #endif
4866  if (listen (socket_fd,
4867  daemon->listen_backlog_size) < 0)
4868  {
4869 #ifdef HAVE_MESSAGES
4870  MHD_DLOG (daemon,
4871  _("Failed to listen for connections: %s\n"),
4873 #endif
4874  MHD_socket_close_chk_ (socket_fd);
4875  goto free_and_fail;
4876  }
4877  }
4878  else
4879  {
4880  socket_fd = daemon->socket_fd;
4881  }
4882 
4883  if (!MHD_socket_nonblocking_ (socket_fd))
4884  {
4885 #ifdef HAVE_MESSAGES
4886  MHD_DLOG (daemon,
4887  _("Failed to set nonblocking mode on listening socket: %s\n"),
4889 #endif
4890  if (0 != (flags & MHD_USE_EPOLL) ||
4891  daemon->worker_pool_size > 0)
4892  {
4893  /* Accept must be non-blocking. Multiple children may wake up
4894  * to handle a new connection, but only one will win the race.
4895  * The others must immediately return. */
4896  MHD_socket_close_chk_ (socket_fd);
4897  goto free_and_fail;
4898  }
4899  }
4900  if ( (!MHD_SCKT_FD_FITS_FDSET_(socket_fd,
4901  NULL)) &&
4902  (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
4903  {
4904 #ifdef HAVE_MESSAGES
4905  MHD_DLOG (daemon,
4906  _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
4907  socket_fd,
4908  FD_SETSIZE);
4909 #endif
4910  MHD_socket_close_chk_ (socket_fd);
4911  goto free_and_fail;
4912  }
4913 
4914 #ifdef EPOLL_SUPPORT
4915  if ( (0 != (flags & MHD_USE_EPOLL)) &&
4916  (0 == daemon->worker_pool_size) &&
4917  (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
4918  {
4919  if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))
4920  {
4921 #ifdef HAVE_MESSAGES
4922  MHD_DLOG (daemon,
4923  _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
4924 #endif
4925  goto free_and_fail;
4926  }
4927  if (MHD_YES != setup_epoll_to_listen (daemon))
4928  goto free_and_fail;
4929  }
4930 #else
4931  if (0 != (flags & MHD_USE_EPOLL))
4932  {
4933 #ifdef HAVE_MESSAGES
4934  MHD_DLOG (daemon,
4935  _("epoll is not supported on this platform by this build.\n"));
4936 #endif
4937  goto free_and_fail;
4938  }
4939 #endif
4940 
4941  if (! MHD_mutex_init_ (&daemon->per_ip_connection_mutex))
4942  {
4943 #ifdef HAVE_MESSAGES
4944  MHD_DLOG (daemon,
4945  _("MHD failed to initialize IP connection limit mutex\n"));
4946 #endif
4947  if (MHD_INVALID_SOCKET != socket_fd)
4948  MHD_socket_close_chk_ (socket_fd);
4949  goto free_and_fail;
4950  }
4951  if (! MHD_mutex_init_ (&daemon->cleanup_connection_mutex))
4952  {
4953 #ifdef HAVE_MESSAGES
4954  MHD_DLOG (daemon,
4955  _("MHD failed to initialize IP connection limit mutex\n"));
4956 #endif
4958  if (MHD_INVALID_SOCKET != socket_fd)
4959  MHD_socket_close_chk_ (socket_fd);
4960  goto free_and_fail;
4961  }
4962 
4963 #if HTTPS_SUPPORT
4964  /* initialize HTTPS daemon certificate aspects & send / recv functions */
4965  if ( (0 != (flags & MHD_USE_TLS)) &&
4966  (0 != MHD_TLS_init (daemon)) )
4967  {
4968 #ifdef HAVE_MESSAGES
4969  MHD_DLOG (daemon,
4970  _("Failed to initialize TLS support\n"));
4971 #endif
4972  if (MHD_INVALID_SOCKET != socket_fd)
4973  MHD_socket_close_chk_ (socket_fd);
4976  goto free_and_fail;
4977  }
4978 #endif
4979  if ( ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) ||
4980  ( (0 != (flags & MHD_USE_SELECT_INTERNALLY)) &&
4981  (0 == daemon->worker_pool_size)) ) &&
4982  (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) &&
4983  (! MHD_create_named_thread_ (&daemon->pid,
4984  (flags & MHD_USE_THREAD_PER_CONNECTION) ?
4985  "MHD-listen" : "MHD-single",
4986  daemon->thread_stack_size,
4988  daemon) ) )
4989  {
4990 #ifdef HAVE_MESSAGES
4991  MHD_DLOG (daemon,
4992  _("Failed to create listen thread: %s\n"),
4993  MHD_strerror_ (errno));
4994 #endif
4997  if (MHD_INVALID_SOCKET != socket_fd)
4998  MHD_socket_close_chk_ (socket_fd);
4999  goto free_and_fail;
5000  }
5001  if ( (daemon->worker_pool_size > 0) &&
5002  (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
5003  {
5004  /* Coarse-grained count of connections per thread (note error
5005  * due to integer division). Also keep track of how many
5006  * connections are leftover after an equal split. */
5007  unsigned int conns_per_thread = daemon->connection_limit
5008  / daemon->worker_pool_size;
5009  unsigned int leftover_conns = daemon->connection_limit
5010  % daemon->worker_pool_size;
5011 
5012  i = 0; /* we need this in case fcntl or malloc fails */
5013 
5014  /* Allocate memory for pooled objects */
5015  daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
5016  * daemon->worker_pool_size);
5017  if (NULL == daemon->worker_pool)
5018  goto thread_failed;
5019 
5020  /* Start the workers in the pool */
5021  for (i = 0; i < daemon->worker_pool_size; ++i)
5022  {
5023  /* Create copy of the Daemon object for each worker */
5024  struct MHD_Daemon *d = &daemon->worker_pool[i];
5025 
5026  memcpy (d, daemon, sizeof (struct MHD_Daemon));
5027  /* Adjust pooling params for worker daemons; note that memcpy()
5028  has already copied MHD_USE_SELECT_INTERNALLY thread model into
5029  the worker threads. */
5030  d->master = daemon;
5031  d->worker_pool_size = 0;
5032  d->worker_pool = NULL;
5033 
5034  /* Always use individual control ITCs */
5035  if (1)
5036  {
5037  if (! MHD_itc_init_ (d->itc))
5038  {
5039 #ifdef HAVE_MESSAGES
5040  MHD_DLOG (daemon,
5041  _("Failed to create worker inter-thread communication channel: %s\n"),
5042  MHD_itc_last_strerror_() );
5043 #endif
5044  goto thread_failed;
5045  }
5046  }
5047  if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5048  (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
5049  NULL)) )
5050  {
5051 #ifdef HAVE_MESSAGES
5052  MHD_DLOG (daemon,
5053  _("File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
5054 #endif
5056  goto thread_failed;
5057  }
5058 
5059  /* Divide available connections evenly amongst the threads.
5060  * Thread indexes in [0, leftover_conns) each get one of the
5061  * leftover connections. */
5062  d->connection_limit = conns_per_thread;
5063  if (i < leftover_conns)
5064  ++d->connection_limit;
5065 #ifdef EPOLL_SUPPORT
5066  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5067  (MHD_YES != setup_epoll_to_listen (d)) )
5068  goto thread_failed;
5069 #endif
5070  /* Must init cleanup connection mutex for each worker */
5071  if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
5072  {
5073 #ifdef HAVE_MESSAGES
5074  MHD_DLOG (daemon,
5075  _("MHD failed to initialize cleanup connection mutex\n"));
5076 #endif
5077  goto thread_failed;
5078  }
5079 
5080  /* Spawn the worker thread */
5081  if (! MHD_create_named_thread_ (&d->pid,
5082  "MHD-worker",
5083  daemon->thread_stack_size,
5085  d))
5086  {
5087 #ifdef HAVE_MESSAGES
5088  MHD_DLOG (daemon,
5089  _("Failed to create pool thread: %s\n"),
5090  MHD_strerror_ (errno));
5091 #endif
5092  /* Free memory for this worker; cleanup below handles
5093  * all previously-created workers. */
5095  goto thread_failed;
5096  }
5097  }
5098  }
5099 #if HTTPS_SUPPORT
5100  /* API promises to never use the password after initialization,
5101  so we additionally NULL it here to not deref a dangling pointer. */
5102  daemon->https_key_password = NULL;
5103 #endif /* HTTPS_SUPPORT */
5104 
5105  return daemon;
5106 
5107 thread_failed:
5108  /* If no worker threads created, then shut down normally. Calling
5109  MHD_stop_daemon (as we do below) doesn't work here since it
5110  assumes a 0-sized thread pool means we had been in the default
5111  MHD_USE_SELECT_INTERNALLY mode. */
5112  if (0 == i)
5113  {
5114  if (MHD_INVALID_SOCKET != socket_fd)
5115  MHD_socket_close_chk_ (socket_fd);
5118  if (NULL != daemon->worker_pool)
5119  free (daemon->worker_pool);
5120  goto free_and_fail;
5121  }
5122 
5123  /* Shutdown worker threads we've already created. Pretend
5124  as though we had fully initialized our daemon, but
5125  with a smaller number of threads than had been
5126  requested. */
5127  daemon->worker_pool_size = i;
5128  MHD_stop_daemon (daemon);
5129  return NULL;
5130 
5131  free_and_fail:
5132  /* clean up basic memory state in 'daemon' and return NULL to
5133  indicate failure */
5134 #if HTTPS_SUPPORT
5135 #ifdef EPOLL_SUPPORT
5136  if (MHD_YES == daemon->upgrade_fd_in_epoll)
5137  {
5138  if (0 != epoll_ctl (daemon->epoll_fd,
5139  EPOLL_CTL_DEL,
5140  daemon->epoll_upgrade_fd,
5141  NULL))
5142  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
5143  daemon->upgrade_fd_in_epoll = MHD_NO;
5144  }
5145  if (-1 != daemon->epoll_fd)
5146  close (daemon->epoll_fd);
5147 #if HTTPS_SUPPORT
5148  if (-1 != daemon->epoll_upgrade_fd)
5149  close (daemon->epoll_upgrade_fd);
5150 #endif
5151 #endif
5152 #endif
5153 #ifdef DAUTH_SUPPORT
5154  free (daemon->nnc);
5155  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
5156 #endif
5157 #if HTTPS_SUPPORT
5158  if (0 != (flags & MHD_USE_TLS))
5159  gnutls_priority_deinit (daemon->priority_cache);
5160 #endif
5161  if (MHD_ITC_IS_VALID_(daemon->itc))
5162  MHD_itc_destroy_chk_ (daemon->itc);
5163  free (daemon);
5164  return NULL;
5165 }
5166 
5167 
5175 static void
5177 {
5178  struct MHD_Connection *pos;
5179 
5180  /* Give suspended connections a chance to resume to avoid
5181  running into the check for there not being any suspended
5182  connections left in case of a tight race with a recently
5183  resumed connection. */
5185  /* first, make sure all threads are aware of shutdown; need to
5186  traverse DLLs in peace... */
5187  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5189  if (NULL != daemon->suspended_connections_head)
5190  MHD_PANIC (_("MHD_stop_daemon() called while we have suspended connections.\n"));
5191  for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
5192  {
5193  shutdown (pos->socket_fd, SHUT_RDWR);
5194 #if MHD_WINSOCK_SOCKETS
5195  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
5196  (MHD_ITC_IS_VALID_(daemon->itc)) &&
5197  (! MHD_itc_activate_ (daemon->itc, "e")) )
5198  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
5199 #endif
5200  }
5201  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5203 
5204  /* now, collect per-connection threads */
5205  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
5206  {
5207  pos = daemon->connections_head;
5208  while (NULL != pos)
5209  {
5210  if (MHD_YES != pos->thread_joined)
5211  {
5212  if (! MHD_join_thread_ (pos->pid))
5213  MHD_PANIC (_("Failed to join a thread\n"));
5214  pos->thread_joined = MHD_YES;
5215  /* The thread may have concurrently modified the DLL,
5216  need to restart from the beginning */
5217  pos = daemon->connections_head;
5218  continue;
5219  }
5220  pos = pos->next;
5221  }
5222  }
5223  /* now that we're alone, move everyone to cleanup */
5224  while (NULL != (pos = daemon->connections_head))
5225  {
5226  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
5227  (MHD_YES != pos->thread_joined) )
5228  MHD_PANIC (_("Failed to join a thread\n"));
5229  close_connection (pos);
5230  }
5231  MHD_cleanup_connections (daemon);
5232 }
5233 
5234 
5235 #ifdef EPOLL_SUPPORT
5236 
5241 static void
5242 epoll_shutdown (struct MHD_Daemon *daemon)
5243 {
5244  struct epoll_event event;
5245 
5246  if (MHD_ITC_IS_INVALID_(daemon->itc))
5247  {
5248  /* itc was required in this mode, how could this happen? */
5249  MHD_PANIC (_("Internal error\n"));
5250  }
5251  event.events = EPOLLOUT;
5252  event.data.ptr = NULL;
5253  if (0 != epoll_ctl (daemon->epoll_fd,
5254  EPOLL_CTL_ADD,
5255  MHD_itc_w_fd_ (daemon->itc),
5256  &event))
5257  MHD_PANIC (_("Failed to add inter-thread communication channel FD to epoll set to signal termination\n"));
5258 }
5259 #endif
5260 
5261 
5268 void
5269 MHD_stop_daemon (struct MHD_Daemon *daemon)
5270 {
5271  MHD_socket fd;
5272  unsigned int i;
5273 #if HTTPS_SUPPORT
5274  struct MHD_UpgradeResponseHandle *urh;
5275  struct MHD_UpgradeResponseHandle *urhn;
5276 #endif
5277 
5278  if (NULL == daemon)
5279  return;
5280 
5281  /* give upgraded HTTPS connections a chance to finish */
5282 #if HTTPS_SUPPORT
5283  for (urh = daemon->urh_head; NULL != urh; urh = urhn)
5284  {
5285  urhn = urh->next;
5286  /* call generic forwarding function for passing data
5287  with chance to detect that application is done;
5288  fake read readyness just to be sure. */
5289  urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
5290  process_urh (urh);
5291  }
5292 #endif
5293  if (0 != (MHD_USE_SUSPEND_RESUME & daemon->options))
5295  daemon->shutdown = MHD_YES;
5296  fd = daemon->socket_fd;
5297  daemon->socket_fd = MHD_INVALID_SOCKET;
5298  /* Prepare workers for shutdown */
5299  if (NULL != daemon->worker_pool)
5300  {
5301  /* #MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */
5302  for (i = 0; i < daemon->worker_pool_size; ++i)
5303  {
5304  daemon->worker_pool[i].shutdown = MHD_YES;
5306 #ifdef EPOLL_SUPPORT
5307  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5308  (-1 != daemon->worker_pool[i].epoll_fd) &&
5309  (MHD_INVALID_SOCKET == fd) )
5310  epoll_shutdown (&daemon->worker_pool[i]);
5311 #endif
5312  }
5313  }
5314  if (MHD_ITC_IS_VALID_(daemon->itc))
5315  {
5316  if (! MHD_itc_activate_ (daemon->itc, "e"))
5317  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel"));
5318  }
5319 #ifdef HAVE_LISTEN_SHUTDOWN
5320  else
5321  {
5322  /* fd might be MHD_INVALID_SOCKET here due to 'MHD_quiesce_daemon' */
5323  if ( (MHD_INVALID_SOCKET != fd) &&
5324  (0 == (daemon->options & MHD_USE_ITC)) )
5325  (void) shutdown (fd,
5326  SHUT_RDWR);
5327  }
5328 #endif
5329 #ifdef EPOLL_SUPPORT
5330  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5331  (-1 != daemon->epoll_fd) &&
5332  (MHD_INVALID_SOCKET == fd) )
5333  epoll_shutdown (daemon);
5334 #endif
5335 
5336 #if DEBUG_CLOSE
5337 #ifdef HAVE_MESSAGES
5338  MHD_DLOG (daemon,
5339  _("MHD listen socket shutdown\n"));
5340 #endif
5341 #endif
5342 
5343 
5344  /* Signal workers to stop and clean them up */
5345  if (NULL != daemon->worker_pool)
5346  {
5347  /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */
5348  for (i = 0; i < daemon->worker_pool_size; ++i)
5349  {
5350  if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
5351  {
5352  if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
5353  MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
5354  }
5355  if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
5356  MHD_PANIC (_("Failed to join a thread\n"));
5357  close_all_connections (&daemon->worker_pool[i]);
5359 #ifdef EPOLL_SUPPORT
5360  if (-1 != daemon->worker_pool[i].epoll_fd)
5361  MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_fd);
5362 #if HTTPS_SUPPORT
5363  if (-1 != daemon->worker_pool[i].epoll_upgrade_fd)
5364  MHD_fd_close_chk_ (daemon->worker_pool[i].epoll_upgrade_fd);
5365 #endif
5366 #endif
5367  /* Individual ITCs are always used */
5368  if (1)
5369  {
5370  if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].itc) )
5371  {
5372  MHD_itc_destroy_chk_ (daemon->worker_pool[i].itc);
5373  }
5374  }
5375  }
5376  free (daemon->worker_pool);
5377  }
5378  else
5379  {
5380  /* clean up master threads */
5381  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
5382  ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
5383  (0 == daemon->worker_pool_size) ) )
5384  {
5385  if (! MHD_join_thread_ (daemon->pid))
5386  {
5387  MHD_PANIC (_("Failed to join a thread\n"));
5388  }
5389  }
5390  }
5391  close_all_connections (daemon);
5392  if (MHD_INVALID_SOCKET != fd)
5393  MHD_socket_close_chk_ (fd);
5394 
5395  /* TLS clean up */
5396 #if HTTPS_SUPPORT
5397  if (MHD_YES == daemon->have_dhparams)
5398  {
5399  gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5400  daemon->have_dhparams = MHD_NO;
5401  }
5402  if (0 != (daemon->options & MHD_USE_TLS))
5403  {
5404  gnutls_priority_deinit (daemon->priority_cache);
5405  if (daemon->x509_cred)
5406  gnutls_certificate_free_credentials (daemon->x509_cred);
5407  }
5408 #endif
5409 #ifdef EPOLL_SUPPORT
5410  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5411  (-1 != daemon->epoll_fd) )
5412  MHD_socket_close_chk_ (daemon->epoll_fd);
5413 #if HTTPS_SUPPORT
5414  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
5415  (-1 != daemon->epoll_upgrade_fd) )
5416  MHD_socket_close_chk_ (daemon->epoll_upgrade_fd);
5417 #endif
5418 #endif
5419 
5420 #ifdef DAUTH_SUPPORT
5421  free (daemon->nnc);
5422  MHD_mutex_destroy_chk_ (&daemon->nnc_lock);
5423 #endif
5426 
5427  if (MHD_ITC_IS_VALID_(daemon->itc))
5428  MHD_itc_destroy_chk_ (daemon->itc);
5429  free (daemon);
5430 }
5431 
5432 
5444 const union MHD_DaemonInfo *
5446  enum MHD_DaemonInfoType info_type,
5447  ...)
5448 {
5449  switch (info_type)
5450  {
5452  return NULL; /* no longer supported */
5454  return NULL; /* no longer supported */
5456  return (const union MHD_DaemonInfo *) &daemon->socket_fd;
5457 #ifdef EPOLL_SUPPORT
5459  return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
5460 #endif
5462  MHD_cleanup_connections (daemon);
5463  if (daemon->worker_pool)
5464  {
5465  /* Collect the connection information stored in the workers. */
5466  unsigned int i;
5467 
5468  daemon->connections = 0;
5469  for (i=0;i<daemon->worker_pool_size;i++)
5470  {
5471  MHD_cleanup_connections (&daemon->worker_pool[i]);
5472  daemon->connections += daemon->worker_pool[i].connections;
5473  }
5474  }
5475  return (const union MHD_DaemonInfo *) &daemon->connections;
5476  default:
5477  return NULL;
5478  };
5479 }
5480 
5481 
5498 void
5500  void *cls)
5501 {
5502  mhd_panic = cb;
5503  mhd_panic_cls = cls;
5504 }
5505 
5506 
5513 const char *
5515 {
5516 #ifdef PACKAGE_VERSION
5517  return PACKAGE_VERSION;
5518 #else /* !PACKAGE_VERSION */
5519  static char ver[12] = "\0\0\0\0\0\0\0\0\0\0\0";
5520  if (0 == ver[0])
5521  {
5522  int res = MHD_snprintf_(ver,
5523  sizeof(ver),
5524  "%x.%x.%x",
5525  (((int)MHD_VERSION >> 24) & 0xFF),
5526  (((int)MHD_VERSION >> 16) & 0xFF),
5527  (((int)MHD_VERSION >> 8) & 0xFF));
5528  if (0 >= res || sizeof(ver) <= res)
5529  return "0.0.0"; /* Can't return real version*/
5530  }
5531  return ver;
5532 #endif /* !PACKAGE_VERSION */
5533 }
5534 
5535 
5547 _MHD_EXTERN int
5549 {
5550  switch(feature)
5551  {
5552  case MHD_FEATURE_MESSGES:
5553 #ifdef HAVE_MESSAGES
5554  return MHD_YES;
5555 #else
5556  return MHD_NO;
5557 #endif
5558  case MHD_FEATURE_SSL:
5559 #if HTTPS_SUPPORT
5560  return MHD_YES;
5561 #else
5562  return MHD_NO;
5563 #endif
5565 #if HTTPS_SUPPORT && GNUTLS_VERSION_MAJOR >= 3
5566  return MHD_YES;
5567 #else
5568  return MHD_NO;
5569 #endif
5570  case MHD_FEATURE_IPv6:
5571 #ifdef HAVE_INET6
5572  return MHD_YES;
5573 #else
5574  return MHD_NO;
5575 #endif
5576  case MHD_FEATURE_IPv6_ONLY:
5577 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
5578  return MHD_YES;
5579 #else
5580  return MHD_NO;
5581 #endif
5582  case MHD_FEATURE_POLL:
5583 #ifdef HAVE_POLL
5584  return MHD_YES;
5585 #else
5586  return MHD_NO;
5587 #endif
5588  case MHD_FEATURE_EPOLL:
5589 #ifdef EPOLL_SUPPORT
5590  return MHD_YES;
5591 #else
5592  return MHD_NO;
5593 #endif
5595 #ifdef HAVE_LISTEN_SHUTDOWN
5596  return MHD_YES;
5597 #else
5598  return MHD_NO;
5599 #endif
5601 #ifdef _MHD_ITC_SOCKETPAIR
5602  return MHD_YES;
5603 #else
5604  return MHD_NO;
5605 #endif
5607 #ifdef TCP_FASTOPEN
5608  return MHD_YES;
5609 #else
5610  return MHD_NO;
5611 #endif
5613 #ifdef BAUTH_SUPPORT
5614  return MHD_YES;
5615 #else
5616  return MHD_NO;
5617 #endif
5619 #ifdef DAUTH_SUPPORT
5620  return MHD_YES;
5621 #else
5622  return MHD_NO;
5623 #endif
5625 #ifdef HAVE_POSTPROCESSOR
5626  return MHD_YES;
5627 #else
5628  return MHD_NO;
5629 #endif
5631 #if HTTPS_SUPPORT && GNUTLS_VERSION_NUMBER >= 0x030111
5632  return MHD_YES;
5633 #else
5634  return MHD_NO;
5635 #endif
5637 #if defined(HAVE___LSEEKI64) || defined(HAVE_LSEEK64)
5638  return MHD_YES;
5639 #else
5640  return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
5641 #endif
5642  case MHD_THREAD_NAMES:
5643 #if defined(MHD_USE_THREAD_NAME_)
5644  return MHD_YES;
5645 #else
5646  return MHD_NO;
5647 #endif
5648  }
5649  return MHD_NO;
5650 }
5651 
5652 
5653 #if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600
5654 #if defined(MHD_USE_POSIX_THREADS)
5655 GCRY_THREAD_OPTION_PTHREAD_IMPL;
5656 #elif defined(MHD_W32_MUTEX_)
5657 
5658 static int
5659 gcry_w32_mutex_init (void **ppmtx)
5660 {
5661  *ppmtx = malloc (sizeof (MHD_mutex_));
5662 
5663  if (NULL == *ppmtx)
5664  return ENOMEM;
5665  if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
5666  {
5667  free (*ppmtx);
5668  *ppmtx = NULL;
5669  return EPERM;
5670  }
5671 
5672  return 0;
5673 }
5674 
5675 
5676 static int
5677 gcry_w32_mutex_destroy (void **ppmtx)
5678 {
5679  int res = (MHD_mutex_destroy_chk_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
5680  free (*ppmtx);
5681  return res;
5682 }
5683 
5684 
5685 static int
5686 gcry_w32_mutex_lock (void **ppmtx)
5687 {
5688  MHD_mutex_lock_chk_ ((MHD_mutex_*)*ppmtx);
5689  return 0;
5690 }
5691 
5692 
5693 static int
5694 gcry_w32_mutex_unlock (void **ppmtx)
5695 {
5696  MHD_mutex_unlock_chk_ ((MHD_mutex_*)*ppmtx);
5697  return 0;
5698 }
5699 
5700 
5701 static struct gcry_thread_cbs gcry_threads_w32 = {
5702  (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
5703  NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
5704  gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
5705  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
5706 
5707 #endif /* defined(MHD_W32_MUTEX_) */
5708 #endif /* HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 */
5709 
5710 
5714 void
5716 {
5717 #ifdef _WIN32
5718  WSADATA wsd;
5719 #endif /* _WIN32 */
5721  mhd_panic_cls = NULL;
5722 
5723 #ifdef _WIN32
5724  if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
5725  MHD_PANIC (_("Failed to initialize winsock\n"));
5726  mhd_winsock_inited_ = 1;
5727  if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
5728  MHD_PANIC (_("Winsock version 2.2 is not available\n"));
5729 #endif
5730 #if HTTPS_SUPPORT
5731 #if GCRYPT_VERSION_NUMBER < 0x010600
5732 #if defined(MHD_USE_POSIX_THREADS)
5733  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
5734  &gcry_threads_pthread))
5735  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
5736 #elif defined(MHD_W32_MUTEX_)
5737  if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
5738  &gcry_threads_w32))
5739  MHD_PANIC (_("Failed to initialise multithreading in libgcrypt\n"));
5740 #endif /* defined(MHD_W32_MUTEX_) */
5741  gcry_check_version (NULL);
5742 #else
5743  if (NULL == gcry_check_version ("1.6.0"))
5744  MHD_PANIC (_("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
5745 #endif
5746  gnutls_global_init ();
5747 #endif
5749 }
5750 
5751 
5752 void
5754 {
5755 #if HTTPS_SUPPORT
5756  gnutls_global_deinit ();
5757 #endif
5758 #ifdef _WIN32
5759  if (mhd_winsock_inited_)
5760  WSACleanup();
5761 #endif
5763 }
5764 
5766 
5767 /* end of daemon.c */
unsigned int per_ip_connection_limit
Definition: internal.h:1398
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
void * unescape_callback_cls
Definition: internal.h:1247
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
uint64_t total_size
Definition: internal.h:319
enum MHD_EpollState celi
Definition: internal.h:973
_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:4435
void MHD_cleanup_upgraded_connection_(struct MHD_Connection *connection)
Definition: daemon.c:920
#define MHD_SCKT_EINVAL_
Definition: mhd_sockets.h:414
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
Definition: daemon.c:3925
uint64_t fd_off
Definition: internal.h:330
_MHD_EXTERN const char * MHD_get_version(void)
Definition: daemon.c:5514
#define DLL_insert(head, tail, element)
Definition: internal.h:1548
socklen_t addr_len
Definition: internal.h:756
int thread_joined
Definition: internal.h:795
void * socket_context
Definition: internal.h:643
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
Definition: internal.h:1087
enum MHD_CONNECTION_STATE state
Definition: internal.h:813
void * data
Definition: microhttpd.h:2108
struct MHD_UpgradeResponseHandle * urh
Definition: internal.h:890
uint64_t response_write_position
Definition: internal.h:745
#define NULL
Definition: reason_phrase.c:30
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_select_thread(void *cls)
Definition: daemon.c:3708
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:818
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Definition: daemon.c:3897
#define MHD_ITC_IS_INVALID_(itc)
Definition: mhd_itc.h:359
Methods for managing connections.
_MHD_EXTERN int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
Definition: daemon.c:2615
MHD_socket socket_fd
Definition: internal.h:1315
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:500
#define MHD_YES
Definition: microhttpd.h:134
#define MHD_socket_set_error_(err)
Definition: mhd_sockets.h:540
_MHD_EXTERN int MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
Definition: daemon.c:2353
struct MHD_Response * response
Definition: internal.h:616
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:473
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:404
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1175
Header for platform missing functions.
#define MHD_MAX_CONNECTIONS_DEFAULT
Definition: daemon.c:67
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
Definition: daemon.c:100
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1105
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: daemon.c:1625
int MHD_socket
Definition: microhttpd.h:181
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
Definition: daemon.c:190
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2158
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
Definition: daemon.c:3752
_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:3777
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:109
#define EDLL_insert(head, tail, element)
Definition: internal.h:1637
intptr_t value
Definition: microhttpd.h:1038
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:557
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
Definition: daemon.c:3950
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
struct MHD_UpgradeResponseHandle * urh
Definition: internal.h:951
Methods for managing response objects.
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
Definition: daemon.c:5499
void MHD_fini(void)
Definition: daemon.c:5753
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1237
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
Definition: daemon.c:142
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
Definition: microhttpd.h:1353
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
Definition: microhttpd.h:710
#define OFF_T_MAX
Definition: mhd_limits.h:88
struct MHD_Daemon * daemon
Definition: internal.h:601
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:871
int listening_address_reuse
Definition: internal.h:1324
MHD_mutex_ per_ip_connection_mutex
Definition: internal.h:1305
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1183
MHD_NotifyConnectionCallback notify_connection
Definition: internal.h:1218
struct MHD_Connection * cleanup_head
Definition: internal.h:1135
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
Definition: mhd_sockets.h:599
int client_aware
Definition: internal.h:775
#define XDLL_remove(head, tail, element)
Definition: internal.h:1614
void MHD_init(void)
Definition: daemon.c:5715
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
#define XDLL_insert(head, tail, element)
Definition: internal.h:1593
#define MHD_SCKT_EINTR_
Definition: mhd_sockets.h:364
MHD_socket MHD_socket_create_listen_(int use_ipv6)
Definition: mhd_sockets.c:471
struct MHD_Connection * cleanup_tail
Definition: internal.h:1140
Header for platform-independent inter-thread communication.
static int MHD_ip_addr_compare(const void *a1, const void *a2)
Definition: daemon.c:218
#define MHD_VERSION
Definition: microhttpd.h:129
size_t write_buffer_send_offset
Definition: internal.h:726
struct MHD_Daemon * worker_pool
Definition: internal.h:1270
void * mhd_panic_cls
Definition: daemon.c:124
size_t read_buffer_size
Definition: internal.h:710
#define MAYBE_SOCK_CLOEXEC
Definition: mhd_sockets.h:156
int fd
Definition: microhttpd.h:2218
void * client_context
Definition: internal.h:634
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:5269
struct MHD_Connection * nextX
Definition: internal.h:591
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1190
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:237
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:782
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:2806
#define MHD_POOL_SIZE_DEFAULT
Definition: daemon.c:75
void MHD_set_https_callbacks(struct MHD_Connection *connection)
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:131
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:702
unsigned int connection_limit
Definition: internal.h:1386
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
unsigned int worker_pool_size
Definition: internal.h:1295
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:588
enum MHD_FLAG options
Definition: internal.h:1403
_MHD_EXTERN int MHD_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
Definition: daemon.c:2712
LogCallback uri_log_callback
Definition: internal.h:1232
#define MHD_SYS_select_(n, r, w, e, t)
Definition: mhd_sockets.h:323
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:994
struct MHD_Connection * connection
Definition: internal.h:990
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
Definition: daemon.c:1289
int shutdown
Definition: internal.h:1362
#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:288
Methods for managing connections.
time_t _MHD_TIMEVAL_TV_SEC_TYPE
Definition: platform.h:122
uint16_t port
Definition: internal.h:1408
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:861
unsigned int connections
Definition: internal.h:1381
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1168
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:354
_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini)
static int call_handlers(struct MHD_Connection *con, int read_ready, int write_ready, int force_close)
Definition: daemon.c:871
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:876
size_t thread_stack_size
Definition: internal.h:1290
#define MAYBE_SOCK_NONBLOCK
Definition: mhd_sockets.h:162
limits values definitions
MHD_FEATURE
Definition: microhttpd.h:2746
Header for platform-independent threads abstraction.
void MHD_monotonic_sec_counter_init(void)
#define MHD_SCKT_ENOTCONN_
Definition: mhd_sockets.h:379
internal shared structures
UnescapeCallback unescape_callback
Definition: internal.h:1242
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:498
int off_t offset
Definition: microhttpd.h:2218
#define MHD_SCKT_LAST_ERR_IS_(code)
Definition: mhd_sockets.h:569
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:866
unsigned int listen_backlog_size
Definition: internal.h:1529
#define MHD_fd_close_chk_(fd)
Definition: internal.h:72
struct MHD_Connection * connections_head
Definition: internal.h:1115
struct MHD_Daemon * master
Definition: internal.h:1265
size_t pool_size
Definition: internal.h:1280
struct MHD_Connection * next
Definition: internal.h:577
#define ULLONG_MAX
Definition: mhd_limits.h:52
struct MHD_itc_ itc
Definition: internal.h:1357
MHD_AcceptPolicyCallback apc
Definition: internal.h:1196
time_t last_activity
Definition: internal.h:762
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
Definition: internal.h:1073
static int resume_suspended_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2255
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:491
unsigned int connection_timeout
Definition: internal.h:768
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:1412
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
Definition: daemon.c:3261
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:2517
int at_limit
Definition: internal.h:1371
struct MemoryPool * pool
Definition: internal.h:626
static int MHD_accept_connection(struct MHD_Daemon *daemon)
Definition: daemon.c:2399
_MHD_EXTERN int MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
Definition: daemon.c:634
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
Definition: daemon.c:202
void * ptr_value
Definition: microhttpd.h:1044
#define MHD_PANIC(msg)
Definition: internal.h:59
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:1435
size_t write_buffer_append_offset
Definition: internal.h:732
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
Definition: mhd_sockets.h:611
int resuming
Definition: internal.h:1376
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1207
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
struct MHD_Connection * prevX
Definition: internal.h:596
static void close_connection(struct MHD_Connection *pos)
Definition: daemon.c:3674
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3185
MHD_thread_handle_ pid
Definition: internal.h:1300
#define DLL_remove(head, tail, element)
Definition: internal.h:1569
void * notify_completed_cls
Definition: internal.h:1212
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:87
TransmitCallback send_cls
Definition: internal.h:881
#define EDLL_remove(head, tail, element)
Definition: internal.h:1656
_MHD_EXTERN int MHD_run(struct MHD_Daemon *daemon)
Definition: daemon.c:3640
MHD_OPTION
MHD options.
Definition: microhttpd.h:720
#define TIMEVAL_TV_SEC_MAX
Definition: mhd_limits.h:103
void * notify_connection_cls
Definition: internal.h:1223
void * apc_cls
Definition: internal.h:1201
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition: tsearch.c:27
struct sockaddr * addr
Definition: internal.h:696
MHD_PanicCallback mhd_panic
Definition: daemon.c:119
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1130
MHD_DaemonInfoType
Definition: microhttpd.h:1309
#define _(String)
Definition: mhd_options.h:42
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2223
void * per_ip_connection_count
Definition: internal.h:1275
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
Definition: daemon.c:5548
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:369
size_t read_buffer_offset
Definition: internal.h:716
_MHD_EXTERN int MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
Definition: daemon.c:753
void * default_handler_cls
Definition: internal.h:1110
static void thread_main_connection_upgrade(struct MHD_Connection *con)
Definition: daemon.c:1152
#define MHD_NO
Definition: microhttpd.h:139
unsigned int connection_timeout
Definition: internal.h:1392
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: daemon.c:1581
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:579
#define UINT_MAX
Definition: mhd_limits.h:39
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1310
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Definition: daemon.c:3822
Header for platform-independent locks abstraction.
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Definition: microhttpd.h:1367
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
Definition: microhttpd.h:1460
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
Definition: daemon.c:5445
_MHD_EXTERN size_t MHD_http_unescape(char *val)
Definition: internal.c:138
static void close_all_connections(struct MHD_Daemon *daemon)
Definition: daemon.c:5176
struct MHD_Connection * connections_tail
Definition: internal.h:1120
enum MHD_OPTION option
Definition: microhttpd.h:1031
#define MHD_socket_set_error_to_ENOMEM()
Definition: mhd_sockets.h:637
void MHD_monotonic_sec_counter_finish(void)
#define MHD_BUF_INC_SIZE
Definition: internal.h:94
#define SIZE_MAX
Definition: mhd_limits.h:83
size_t pool_increment
Definition: internal.h:1285
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add)
Definition: daemon.c:1766
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1125
#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...