GNU libmicrohttpd  0.9.72
daemon_start.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
25 #include "internal.h"
26 #include "connection_cleanup.h"
28 #include "daemon_select.h"
29 #include "daemon_poll.h"
30 #include "daemon_epoll.h"
31 #include "request_resume.h"
32 
33 
41 static enum MHD_StatusCode
42 configure_listen_reuse (struct MHD_Daemon *daemon)
43 {
44  const MHD_SCKT_OPT_BOOL_ on = 1;
45 
46  /* Apply the socket options according to
47  listening_address_reuse. */
48  if (daemon->allow_address_reuse)
49  {
50  /* User requested to allow reusing listening address:port. */
51 #ifndef MHD_WINSOCK_SOCKETS
52  /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
53  * it doesn't work. */
54  if (0 > setsockopt (daemon->listen_socket,
55  SOL_SOCKET,
56  SO_REUSEADDR,
57  (void *) &on,
58  sizeof (on)))
59  {
60 #ifdef HAVE_MESSAGES
61  MHD_DLOG (daemon,
62  MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
63  _ ("setsockopt failed: %s\n"),
65 #endif
66  return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
67  }
68  return MHD_SC_OK;
69 #endif /* ! MHD_WINSOCK_SOCKETS */
70  /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
71  * Fail if SO_REUSEPORT is not defined or setsockopt fails.
72  */
73  /* SO_REUSEADDR on W32 has the same semantics
74  as SO_REUSEPORT on BSD/Linux */
75 #if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
76  if (0 > setsockopt (daemon->listen_socket,
77  SOL_SOCKET,
78 #ifndef MHD_WINSOCK_SOCKETS
79  SO_REUSEPORT,
80 #else /* MHD_WINSOCK_SOCKETS */
81  SO_REUSEADDR,
82 #endif /* MHD_WINSOCK_SOCKETS */
83  (void *) &on,
84  sizeof (on)))
85  {
86 #ifdef HAVE_MESSAGES
87  MHD_DLOG (daemon,
88  MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
89  _ ("setsockopt failed: %s\n"),
91 #endif
92  return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
93  }
94  return MHD_SC_OK;
95 #else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
96  /* we're supposed to allow address:port re-use, but
97  on this platform we cannot; fail hard */
98 #ifdef HAVE_MESSAGES
99  MHD_DLOG (daemon,
100  MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED,
101  _ (
102  "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
103 #endif
104  return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED;
105 #endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
106  }
107 
108  /* if (! daemon->allow_address_reuse) */
109  /* User requested to disallow reusing listening address:port.
110  * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
111  * is used and Solaris with SO_EXCLBIND.
112  * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
113  * or setsockopt fails.
114  */
115 #if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
116  (defined(__sun) && defined(SO_EXCLBIND))
117  if (0 > setsockopt (daemon->listen_socket,
118  SOL_SOCKET,
119 #ifdef SO_EXCLUSIVEADDRUSE
120  SO_EXCLUSIVEADDRUSE,
121 #else /* SO_EXCLBIND */
122  SO_EXCLBIND,
123 #endif /* SO_EXCLBIND */
124  (void *) &on,
125  sizeof (on)))
126  {
127 #ifdef HAVE_MESSAGES
128  MHD_DLOG (daemon,
129  MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED,
130  _ ("setsockopt failed: %s\n"),
132 #endif
133  return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED;
134  }
135  return MHD_SC_OK;
136 #elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
137 #ifdef HAVE_MESSAGES
138  MHD_DLOG (daemon,
139  MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED,
140  _ (
141  "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
142 #endif
143  return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED;
144 #endif /* MHD_WINSOCK_SOCKETS */
145  /* Not on WINSOCK, simply doing nothing will do */
146  return MHD_SC_OK;
147 }
148 
149 
156 static enum MHD_StatusCode
157 open_listen_socket (struct MHD_Daemon *daemon)
158 {
159  enum MHD_StatusCode sc;
160  socklen_t addrlen;
161  struct sockaddr_storage ss;
162  const struct sockaddr *sa;
163  int pf;
164  bool use_v6;
165 
166  if (MHD_INVALID_SOCKET != daemon->listen_socket)
167  return MHD_SC_OK; /* application opened it for us! */
168  pf = -1;
169  /* Determine address family */
170  switch (daemon->listen_af)
171  {
172  case MHD_AF_NONE:
173  if (0 == daemon->listen_sa_len)
174  {
175  /* no listening desired, that's OK */
176  return MHD_SC_OK;
177  }
178  /* we have a listen address, get AF from there! */
179  switch (daemon->listen_sa.ss_family)
180  {
181  case AF_INET:
182  pf = PF_INET;
183  use_v6 = false;
184  break;
185 #ifdef AF_INET6
186  case AF_INET6:
187  pf = PF_INET6;
188  use_v6 = true;
189  break;
190 #endif
191 #ifdef AF_UNIX
192  case AF_UNIX:
193  pf = PF_UNIX;
194  use_v6 = false;
195  break;
196 #endif
197  default:
198  return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD;
199  } /* switch on ss_family */
200  break; /* MHD_AF_NONE */
201  case MHD_AF_AUTO:
202 #if HAVE_INET6
203  pf = PF_INET6;
204  use_v6 = true;
205 #else
206  pf = PF_INET;
207  use_v6 = false;
208 #endif
209  break;
210  case MHD_AF_INET4:
211  use_v6 = false;
212  pf = PF_INET;
213  break;
214  case MHD_AF_INET6:
215  case MHD_AF_DUAL:
216 #if HAVE_INET6
217  pf = PF_INET6;
218  use_v6 = true;
219  break;
220 #else
221 #ifdef HAVE_MESSAGES
222  MHD_DLOG (daemon,
223  MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD,
224  _ ("IPv6 not supported by this build.\n"));
225 #endif
226  return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD;
227 #endif
228  }
229  mhd_assert (-1 != pf);
230  /* try to open listen socket */
231 try_open_listen_socket:
233  if ( (MHD_INVALID_SOCKET == daemon->listen_socket) &&
234  (MHD_AF_AUTO == daemon->listen_af) &&
235  (use_v6) )
236  {
237  use_v6 = false;
238  pf = PF_INET;
239  goto try_open_listen_socket;
240  }
241  if (MHD_INVALID_SOCKET == daemon->listen_socket)
242  {
243 #ifdef HAVE_MESSAGES
244  MHD_DLOG (daemon,
245  MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET,
246  _ ("Failed to create socket for listening: %s\n"),
248 #endif
249  return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET;
250  }
251 
252  if (MHD_SC_OK !=
253  (sc = configure_listen_reuse (daemon)))
254  return sc;
255 
256  /* configure for dual stack (or not) */
257  if (use_v6)
258  {
259 #if defined IPPROTO_IPV6 && defined IPV6_V6ONLY
260  /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
261  (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
262  and may also be missing on older POSIX systems; good luck if you have any of those,
263  your IPv6 socket may then also bind against IPv4 anyway... */
264  const MHD_SCKT_OPT_BOOL_ v6_only =
265  (MHD_AF_INET6 == daemon->listen_af);
266  if (0 > setsockopt (daemon->listen_socket,
267  IPPROTO_IPV6,
268  IPV6_V6ONLY,
269  (const void *) &v6_only,
270  sizeof (v6_only)))
271  {
272 #ifdef HAVE_MESSAGES
273  MHD_DLOG (daemon,
274  MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_FAILED,
275  _ ("setsockopt failed: %s\n"),
277 #endif
278  }
279 #else
280 #ifdef HAVE_MESSAGES
281  MHD_DLOG (daemon,
282  MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED,
283  _ (
284  "Cannot explicitly setup dual stack behavior on this platform.\n"));
285 #endif
286 #endif
287  }
288 
289  /* Determine address to bind to */
290  if (0 != daemon->listen_sa_len)
291  {
292  /* Bind address explicitly given */
293  sa = (const struct sockaddr *) &daemon->listen_sa;
294  addrlen = daemon->listen_sa_len;
295  }
296  else
297  {
298  /* Compute bind address based on port and AF */
299 #if HAVE_INET6
300  if (use_v6)
301  {
302 #ifdef IN6ADDR_ANY_INIT
303  static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
304 #endif
305  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
306 
307  addrlen = sizeof (struct sockaddr_in6);
308  memset (sin6,
309  0,
310  sizeof (struct sockaddr_in6));
311  sin6->sin6_family = AF_INET6;
312  sin6->sin6_port = htons (daemon->listen_port);
313 #ifdef IN6ADDR_ANY_INIT
314  sin6->sin6_addr = static_in6any;
315 #endif
316 #if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
317  sin6->sin6_len = sizeof (struct sockaddr_in6);
318 #endif
319  }
320  else
321 #endif
322  {
323  struct sockaddr_in *sin4 = (struct sockaddr_in *) &ss;
324 
325  addrlen = sizeof (struct sockaddr_in);
326  memset (sin4,
327  0,
328  sizeof (struct sockaddr_in));
329  sin4->sin_family = AF_INET;
330  sin4->sin_port = htons (daemon->listen_port);
331  if (0 != INADDR_ANY)
332  sin4->sin_addr.s_addr = htonl (INADDR_ANY);
333 #if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
334  sin4->sin_len = sizeof (struct sockaddr_in);
335 #endif
336  }
337  sa = (const struct sockaddr *) &ss;
338  }
339 
340  /* actually do the bind() */
341  if (-1 == bind (daemon->listen_socket,
342  sa,
343  addrlen))
344  {
345 #ifdef HAVE_MESSAGES
346  unsigned int port = 0;
347 
348  switch (sa->sa_family)
349  {
350  case AF_INET:
351  if (addrlen == sizeof (struct sockaddr_in))
352  port = ntohs (((const struct sockaddr_in *) sa)->sin_port);
353  else
354  port = UINT16_MAX + 1; /* indicate size error */
355  break;
356  case AF_INET6:
357  if (addrlen == sizeof (struct sockaddr_in6))
358  port = ntohs (((const struct sockaddr_in6 *) sa)->sin6_port);
359  else
360  port = UINT16_MAX + 1; /* indicate size error */
361  break;
362  default:
363  port = UINT_MAX; /* AF_UNIX? */
364  break;
365  }
366  MHD_DLOG (daemon,
367  MHD_SC_LISTEN_SOCKET_BIND_FAILED,
368  _ ("Failed to bind to port %u: %s\n"),
369  port,
371 #endif
372  return MHD_SC_LISTEN_SOCKET_BIND_FAILED;
373  }
374 
375  /* setup TCP_FASTOPEN */
376 #ifdef TCP_FASTOPEN
377  if (MHD_FOM_DISABLE != daemon->fast_open_method)
378  {
379  if (0 != setsockopt (daemon->listen_socket,
380  IPPROTO_TCP,
381  TCP_FASTOPEN,
382  &daemon->fo_queue_length,
383  sizeof (daemon->fo_queue_length)))
384  {
385 #ifdef HAVE_MESSAGES
386  MHD_DLOG (daemon,
387  MHD_SC_FAST_OPEN_FAILURE,
388  _ ("setsockopt failed: %s\n"),
390 #endif
391  if (MHD_FOM_REQUIRE == daemon->fast_open_method)
392  return MHD_SC_FAST_OPEN_FAILURE;
393  }
394  }
395 #endif
396 
397  /* setup listening */
398  if (0 > listen (daemon->listen_socket,
399  daemon->listen_backlog))
400  {
401 #ifdef HAVE_MESSAGES
402  MHD_DLOG (daemon,
403  MHD_SC_LISTEN_FAILURE,
404  _ ("Failed to listen for connections: %s\n"),
406 #endif
407  return MHD_SC_LISTEN_FAILURE;
408  }
409  return MHD_SC_OK;
410 }
411 
412 
421 static void
423 {
424  struct sockaddr_storage servaddr;
425  socklen_t addrlen;
426 
427  if ( (0 != daemon->listen_port) ||
428  (MHD_INVALID_SOCKET == daemon->listen_socket) )
429  return; /* nothing to be done */
430 
431  memset (&servaddr,
432  0,
433  sizeof (struct sockaddr_storage));
434  addrlen = sizeof (servaddr);
435  if (0 != getsockname (daemon->listen_socket,
436  (struct sockaddr *) &servaddr,
437  &addrlen))
438  {
439 #ifdef HAVE_MESSAGES
440  MHD_DLOG (daemon,
441  MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
442  _ ("Failed to get listen port number: %s\n"),
444 #endif /* HAVE_MESSAGES */
445  return;
446  }
447 #ifdef MHD_POSIX_SOCKETS
448  if (sizeof (servaddr) < addrlen)
449  {
450  /* should be impossible with `struct sockaddr_storage` */
451 #ifdef HAVE_MESSAGES
452  MHD_DLOG (daemon,
453  MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
454  _ (
455  "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
456 #endif /* HAVE_MESSAGES */
457  return;
458  }
459 #endif /* MHD_POSIX_SOCKETS */
460  switch (servaddr.ss_family)
461  {
462  case AF_INET:
463  {
464  struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
465 
466  daemon->listen_port = ntohs (s4->sin_port);
467  break;
468  }
469 #ifdef HAVE_INET6
470  case AF_INET6:
471  {
472  struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
473 
474  daemon->listen_port = ntohs (s6->sin6_port);
475  break;
476  }
477 #endif /* HAVE_INET6 */
478 #ifdef AF_UNIX
479  case AF_UNIX:
480  daemon->listen_port = 0; /* special value for UNIX domain sockets */
481  break;
482 #endif
483  default:
484 #ifdef HAVE_MESSAGES
485  MHD_DLOG (daemon,
486  MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF,
487  _ ("Unknown address family!\n"));
488 #endif
489  daemon->listen_port = 0; /* ugh */
490  break;
491  }
492 }
493 
494 
495 #ifdef EPOLL_SUPPORT
502 static int
503 setup_epoll_fd (struct MHD_Daemon *daemon)
504 {
505  int fd;
506 
507 #ifndef HAVE_MESSAGES
508  (void) daemon; /* Mute compiler warning. */
509 #endif /* ! HAVE_MESSAGES */
510 
511 #ifdef USE_EPOLL_CREATE1
512  fd = epoll_create1 (EPOLL_CLOEXEC);
513 #else /* ! USE_EPOLL_CREATE1 */
514  fd = epoll_create (MAX_EVENTS);
515 #endif /* ! USE_EPOLL_CREATE1 */
516  if (MHD_INVALID_SOCKET == fd)
517  {
518 #ifdef HAVE_MESSAGES
519  MHD_DLOG (daemon,
520  MHD_SC_EPOLL_CTL_CREATE_FAILED,
521  _ ("Call to epoll_create1 failed: %s\n"),
523 #endif
524  return MHD_INVALID_SOCKET;
525  }
526 #if ! defined(USE_EPOLL_CREATE1)
528  {
529 #ifdef HAVE_MESSAGES
530  MHD_DLOG (daemon,
531  MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED,
532  _ ("Failed to set noninheritable mode on epoll FD.\n"));
533 #endif
534  }
535 #endif /* ! USE_EPOLL_CREATE1 */
536  return fd;
537 }
538 
539 
549 static enum MHD_StatusCode
550 setup_epoll_to_listen (struct MHD_Daemon *daemon)
551 {
552  struct epoll_event event;
553  MHD_socket ls;
554 
555  /* FIXME: update function! */
556  daemon->epoll_fd = setup_epoll_fd (daemon);
557  if (-1 == daemon->epoll_fd)
558  return MHD_SC_EPOLL_CTL_CREATE_FAILED;
559 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
560  if (! daemon->disallow_upgrade)
561  {
562  daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
563  if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
564  return MHD_SC_EPOLL_CTL_CREATE_FAILED;
565  }
566 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
567  if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_socket)) ||
568  (daemon->was_quiesced) )
569  return MHD_SC_OK; /* non-listening daemon */
570  event.events = EPOLLIN;
571  event.data.ptr = daemon;
572  if (0 != epoll_ctl (daemon->epoll_fd,
573  EPOLL_CTL_ADD,
574  ls,
575  &event))
576  {
577 #ifdef HAVE_MESSAGES
578  MHD_DLOG (daemon,
579  MHD_SC_EPOLL_CTL_ADD_FAILED,
580  _ ("Call to epoll_ctl failed: %s\n"),
582 #endif
583  return MHD_SC_EPOLL_CTL_ADD_FAILED;
584  }
585  daemon->listen_socket_in_epoll = true;
586  if (MHD_ITC_IS_VALID_ (daemon->itc))
587  {
588  event.events = EPOLLIN;
589  event.data.ptr = (void *) daemon->epoll_itc_marker;
590  if (0 != epoll_ctl (daemon->epoll_fd,
591  EPOLL_CTL_ADD,
592  MHD_itc_r_fd_ (daemon->itc),
593  &event))
594  {
595 #ifdef HAVE_MESSAGES
596  MHD_DLOG (daemon,
597  MHD_SC_EPOLL_CTL_ADD_FAILED,
598  _ ("Call to epoll_ctl failed: %s\n"),
600 #endif
601  return MHD_SC_EPOLL_CTL_ADD_FAILED;
602  }
603  }
604  return MHD_SC_OK;
605 }
606 
607 
608 #endif
609 
610 
618 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
620 {
621  struct MHD_Daemon *daemon = cls;
622 
623  MHD_thread_init_ (&daemon->pid);
624  while (! daemon->shutdown)
625  {
626  switch (daemon->event_loop_syscall)
627  {
628  case MHD_ELS_AUTO:
629  MHD_PANIC ("MHD_ELS_AUTO should have been mapped to preferred style.\n");
630  break;
631  case MHD_ELS_SELECT:
632  MHD_daemon_select_ (daemon,
633  MHD_YES);
634  break;
635  case MHD_ELS_POLL:
636 #if HAVE_POLL
637  MHD_daemon_poll_ (daemon,
638  MHD_YES);
639 #else
640  MHD_PANIC ("MHD_ELS_POLL not supported, should have failed earlier.\n");
641 #endif
642  break;
643  case MHD_ELS_EPOLL:
644 #ifdef EPOLL_SUPPORT
645  MHD_daemon_epoll_ (daemon,
646  MHD_YES);
647 #else
648  MHD_PANIC ("MHD_ELS_EPOLL not supported, should have failed earlier.\n");
649 #endif
650  break;
651  }
652  MHD_connection_cleanup_ (daemon);
653  }
654  /* Resume any pending for resume connections, join
655  * all connection's threads (if any) and finally cleanup
656  * everything. */
657  if (! daemon->disallow_suspend_resume)
660 
661  return (MHD_THRD_RTRN_TYPE_) 0;
662 }
663 
664 
671 static enum MHD_StatusCode
672 setup_thread_pool (struct MHD_Daemon *daemon)
673 {
674  /* Coarse-grained count of connections per thread (note error
675  * due to integer division). Also keep track of how many
676  * connections are leftover after an equal split. */
677  unsigned int conns_per_thread = daemon->global_connection_limit
678  / daemon->threading_mode;
679  unsigned int leftover_conns = daemon->global_connection_limit
680  % daemon->threading_mode;
681  int i;
682  enum MHD_StatusCode sc;
683 
684  /* Allocate memory for pooled objects */
685  daemon->worker_pool = MHD_calloc_ (daemon->threading_mode,
686  sizeof (struct MHD_Daemon));
687  if (NULL == daemon->worker_pool)
688  return MHD_SC_THREAD_POOL_MALLOC_FAILURE;
689 
690  /* Start the workers in the pool */
691  for (i = 0; i < daemon->threading_mode; i++)
692  {
693  /* Create copy of the Daemon object for each worker */
694  struct MHD_Daemon *d = &daemon->worker_pool[i];
695 
696  memcpy (d,
697  daemon,
698  sizeof (struct MHD_Daemon));
699  /* Adjust pooling params for worker daemons; note that memcpy()
700  has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
701  the worker threads. */
702  d->master = daemon;
703  d->worker_pool_size = 0;
704  d->worker_pool = NULL;
705  /* Divide available connections evenly amongst the threads.
706  * Thread indexes in [0, leftover_conns) each get one of the
707  * leftover connections. */
708  d->global_connection_limit = conns_per_thread;
709  if (((unsigned int) i) < leftover_conns)
711 
712  if (! daemon->disable_itc)
713  {
714  if (! MHD_itc_init_ (d->itc))
715  {
716 #ifdef HAVE_MESSAGES
717  MHD_DLOG (daemon,
718  MHD_SC_ITC_INITIALIZATION_FAILED,
719  _ (
720  "Failed to create worker inter-thread communication channel: %s\n"),
721  MHD_itc_last_strerror_ () );
722 #endif
723  sc = MHD_SC_ITC_INITIALIZATION_FAILED;
724  goto thread_failed;
725  }
726  if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
727  (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
728  NULL)) )
729  {
730 #ifdef HAVE_MESSAGES
731  MHD_DLOG (daemon,
732  MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
733  _ (
734  "File descriptor for inter-thread communication channel exceeds maximum value.\n"));
735 #endif
737  sc = MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
738  goto thread_failed;
739  }
740  }
741  else
742  {
743  MHD_itc_set_invalid_ (d->itc);
744  }
745 
746 #ifdef EPOLL_SUPPORT
747  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
748  (MHD_SC_OK != (sc = setup_epoll_to_listen (d))) )
749  goto thread_failed;
750 #endif
751 
752  /* Must init cleanup connection mutex for each worker */
754  {
755 #ifdef HAVE_MESSAGES
756  MHD_DLOG (daemon,
757  MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE,
758  _ ("MHD failed to initialize cleanup connection mutex.\n"));
759 #endif
760  if (! daemon->disable_itc)
762  sc = MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE;
763  goto thread_failed;
764  }
765 
766  /* Spawn the worker thread */
767  if (! MHD_create_named_thread_ (&d->pid,
768  "MHD-worker",
769  daemon->thread_stack_limit_b,
771  d))
772  {
773 #ifdef HAVE_MESSAGES
774  MHD_DLOG (daemon,
775  MHD_SC_THREAD_POOL_LAUNCH_FAILURE,
776  _ ("Failed to create pool thread: %s\n"),
777  MHD_strerror_ (errno));
778 #endif
779  /* Free memory for this worker; cleanup below handles
780  * all previously-created workers. */
781  if (! daemon->disable_itc)
784  sc = MHD_SC_THREAD_POOL_LAUNCH_FAILURE;
785  goto thread_failed;
786  }
787  } /* end for() */
788  return MHD_SC_OK;
789 
790 thread_failed:
791  /* If no worker threads created, then shut down normally. Calling
792  MHD_stop_daemon (as we do below) doesn't work here since it
793  assumes a 0-sized thread pool means we had been in the default
794  MHD_USE_INTERNAL_POLLING_THREAD mode. */
795  if (0 == i)
796  {
797  if (NULL != daemon->worker_pool)
798  {
799  free (daemon->worker_pool);
800  daemon->worker_pool = NULL;
801  }
802  return MHD_SC_THREAD_LAUNCH_FAILURE;
803  }
804  /* Shutdown worker threads we've already created. Pretend
805  as though we had fully initialized our daemon, but
806  with a smaller number of threads than had been
807  requested. */
808  daemon->worker_pool_size = i;
809  daemon->listen_socket = MHD_daemon_quiesce (daemon);
810  return sc;
811 }
812 
813 
822 enum MHD_StatusCode
823 MHD_daemon_start (struct MHD_Daemon *daemon)
824 {
825  enum MHD_StatusCode sc;
826 
827  if (MHD_ELS_AUTO == daemon->event_loop_syscall)
828  {
829 #if EPOLL_SUPPORT
830  /* We do not support thread-per-connection in combination
831  with epoll, so use poll in this case, otherwise prefer
832  epoll. */
833  if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
834  daemon->event_loop_syscall = MHD_ELS_POLL;
835  else
836  daemon->event_loop_syscall = MHD_ELS_EPOLL;
837 #elif HAVE_POLL
838  daemon->event_loop_syscall = MHD_ELS_POLL;
839 #else
840  daemon->event_loop_syscall = MHD_ELS_SELECT;
841 #endif
842  }
843 
844 #ifdef EPOLL_SUPPORT
845  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
846  (0 == daemon->worker_pool_size) &&
847  (MHD_INVALID_SOCKET != daemon->listen_socket) &&
848  (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) )
849  {
850 #ifdef HAVE_MESSAGES
851  MHD_DLOG (daemon,
852  MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID,
853  _ (
854  "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
855 #endif
856  return MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID;
857  }
858 #endif
859 
860  /* Setup ITC */
861  if ( (! daemon->disable_itc) &&
862  (0 == daemon->worker_pool_size) )
863  {
864  if (! MHD_itc_init_ (daemon->itc))
865  {
866 #ifdef HAVE_MESSAGES
867  MHD_DLOG (daemon,
868  MHD_SC_ITC_INITIALIZATION_FAILED,
869  _ ("Failed to create inter-thread communication channel: %s\n"),
870  MHD_itc_last_strerror_ ());
871 #endif
872  return MHD_SC_ITC_INITIALIZATION_FAILED;
873  }
874  if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
875  (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
876  NULL)) )
877  {
878 #ifdef HAVE_MESSAGES
879  MHD_DLOG (daemon,
880  MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
881  _ (
882  "File descriptor for inter-thread communication channel exceeds maximum value.\n"));
883 #endif
884  return MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
885  }
886  }
887 
888  if (MHD_SC_OK != (sc = open_listen_socket (daemon)))
889  return sc;
890 
891  /* Check listen socket is in range (if we are limited) */
892  if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
893  (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
895  NULL)) )
896  {
897 #ifdef HAVE_MESSAGES
898  MHD_DLOG (daemon,
899  MHD_SC_LISTEN_SOCKET_TOO_LARGE,
900  _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
901  daemon->listen_socket,
902  FD_SETSIZE);
903 #endif
904  return MHD_SC_LISTEN_SOCKET_TOO_LARGE;
905  }
906 
907  /* set listen socket to non-blocking */
908  if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
909  (! MHD_socket_nonblocking_ (daemon->listen_socket)) )
910  {
911 #ifdef HAVE_MESSAGES
912  MHD_DLOG (daemon,
913  MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE,
914  _ ("Failed to set nonblocking mode on listening socket: %s\n"),
916 #endif
917  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) ||
918  (daemon->worker_pool_size > 0) )
919  {
920  /* Accept must be non-blocking. Multiple children may wake
921  * up to handle a new connection, but only one will win the
922  * race. The others must immediately return. As this is
923  * not possible, we must fail hard here. */
924  return MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE;
925  }
926  }
927 
928 #ifdef EPOLL_SUPPORT
929  /* Setup epoll */
930  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
931  (0 == daemon->worker_pool_size) &&
932  (MHD_INVALID_SOCKET != daemon->listen_socket) &&
933  (MHD_SC_OK != (sc = setup_epoll_to_listen (daemon))) )
934  return sc;
935 #endif
936 
937  /* Setup main listen thread (only if we have no thread pool or
938  external event loop and do have a listen socket) */
939  /* FIXME: why no worker thread if we have no listen socket? */
940  if ( ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) ||
941  (1 == daemon->threading_mode) ) &&
942  (MHD_INVALID_SOCKET != daemon->listen_socket) &&
943  (! MHD_create_named_thread_ (&daemon->pid,
944  (MHD_TM_THREAD_PER_CONNECTION ==
945  daemon->threading_mode)
946  ? "MHD-listen"
947  : "MHD-single",
948  daemon->thread_stack_limit_b,
950  daemon) ) )
951  {
952 #ifdef HAVE_MESSAGES
953  MHD_DLOG (daemon,
954  MHD_SC_THREAD_MAIN_LAUNCH_FAILURE,
955  _ ("Failed to create listen thread: %s\n"),
956  MHD_strerror_ (errno));
957 #endif
958  return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE;
959  }
960 
961  /* Setup worker threads */
962  /* FIXME: why no thread pool if we have no listen socket? */
963  if ( (1 < daemon->threading_mode) &&
964  (MHD_INVALID_SOCKET != daemon->listen_socket) &&
965  (MHD_SC_OK != (sc = setup_thread_pool (daemon))) )
966  return sc;
967 
968  /* make sure we know our listen port (if any) */
969  get_listen_port_number (daemon);
970 
971  return MHD_SC_OK;
972 }
973 
974 
975 /* end of daemon_start.c */
void MHD_connection_cleanup_(struct MHD_Daemon *daemon)
functions to cleanup completed connection
void MHD_daemon_close_all_connections_(struct MHD_Daemon *daemon)
function to close all connections open at a daemon
non-public functions provided by daemon_epoll.c
enum MHD_StatusCode MHD_daemon_poll_(struct MHD_Daemon *daemon, bool may_block)
Definition: daemon_poll.c:447
non-public functions provided by daemon_poll.c
enum MHD_StatusCode MHD_daemon_select_(struct MHD_Daemon *daemon, int may_block)
non-public functions provided by daemon_select.c
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
Definition: daemon_start.c:619
static enum MHD_StatusCode configure_listen_reuse(struct MHD_Daemon *daemon)
Definition: daemon_start.c:42
static enum MHD_StatusCode setup_thread_pool(struct MHD_Daemon *daemon)
Definition: daemon_start.c:672
static void get_listen_port_number(struct MHD_Daemon *daemon)
Definition: daemon_start.c:422
static enum MHD_StatusCode open_listen_socket(struct MHD_Daemon *daemon)
Definition: daemon_start.c:157
enum MHD_StatusCode MHD_daemon_start(struct MHD_Daemon *daemon)
Definition: daemon_start.c:823
MHD_socket MHD_daemon_quiesce(struct MHD_Daemon *daemon)
#define MHD_PANIC(msg)
Definition: internal.h:69
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:98
#define MHD_strerror_(errnum)
Definition: mhd_compat.h:44
#define MHD_itc_destroy_chk_(itc)
Definition: mhd_itc.h:353
#define UINT_MAX
Definition: mhd_limits.h:45
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:121
int MHD_socket_noninheritable_(MHD_socket sock)
Definition: mhd_sockets.c:442
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:407
MHD_socket MHD_socket_create_listen_(int pf)
Definition: mhd_sockets.c:474
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:203
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:549
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:309
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:216
#define NULL
Definition: reason_phrase.c:30
#define _(String)
Definition: mhd_options.h:42
internal shared structures
#define MHD_mutex_init_(ignore)
Definition: mhd_locks.h:189
int MHD_socket
Definition: microhttpd.h:196
@ MHD_YES
Definition: microhttpd.h:151
int fd
Definition: microhttpd.h:3195
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:197
bool MHD_resume_suspended_connections_(struct MHD_Daemon *daemon)
implementation of MHD_request_resume()
enum MHD_AddressFamily listen_af
Definition: internal.h:1429
bool was_quiesced
Definition: internal.h:1505
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
int listen_backlog
Definition: internal.h:1336
uint16_t listen_port
Definition: internal.h:1449
size_t listen_sa_len
Definition: internal.h:1271
unsigned int worker_pool_size
Definition: internal.h:1366
struct MHD_itc_ itc
Definition: internal.h:1410
bool disable_itc
Definition: internal.h:1462
enum MHD_FastOpenMethod fast_open_method
Definition: internal.h:1423
enum MHD_EventLoopSyscall event_loop_syscall
Definition: internal.h:1436
bool disallow_upgrade
Definition: internal.h:1474
volatile bool shutdown
Definition: internal.h:1526
bool disallow_suspend_resume
Definition: internal.h:1468
struct sockaddr_storage listen_sa
Definition: internal.h:1254
bool allow_address_reuse
Definition: internal.h:1516
struct MHD_Daemon * worker_pool
Definition: internal.h:1073
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
MHD_socket listen_socket
Definition: internal.h:1377
struct MHD_Daemon * master
Definition: internal.h:1068
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1417
unsigned int global_connection_limit
Definition: internal.h:1351
size_t thread_stack_limit_b
Definition: internal.h:1302
unsigned int fo_queue_length
Definition: internal.h:1346