GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
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
41static 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 _ (
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
156static enum MHD_StatusCode
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 */
231try_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
421static 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
502static int
503setup_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
549static enum MHD_StatusCode
550setup_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
618static 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 }
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
671static enum MHD_StatusCode
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
790thread_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
822enum MHD_StatusCode
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) &&
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)
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)
static enum MHD_StatusCode configure_listen_reuse(struct MHD_Daemon *daemon)
static enum MHD_StatusCode setup_thread_pool(struct MHD_Daemon *daemon)
static void get_listen_port_number(struct MHD_Daemon *daemon)
static enum MHD_StatusCode open_listen_socket(struct MHD_Daemon *daemon)
enum MHD_StatusCode MHD_daemon_start(struct MHD_Daemon *daemon)
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)
int MHD_socket_nonblocking_(MHD_socket sock)
MHD_socket MHD_socket_create_listen_(int pf)
int MHD_SCKT_OPT_BOOL_
#define MHD_socket_last_strerr_()
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
#define MHD_create_named_thread_(t, n, s, r, a)
#define NULL
#define _(String)
Definition mhd_options.h:42
MHD internal shared structures.
#define MHD_mutex_init_(ignore)
Definition mhd_locks.h:191
int MHD_socket
Definition microhttpd.h:207
@ MHD_YES
Definition microhttpd.h:167
int fd
#define MHD_INVALID_SOCKET
Definition microhttpd.h:208
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