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