aboutsummaryrefslogtreecommitdiff
path: root/src/lib/daemon_start.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/daemon_start.c')
-rw-r--r--src/lib/daemon_start.c928
1 files changed, 928 insertions, 0 deletions
diff --git a/src/lib/daemon_start.c b/src/lib/daemon_start.c
new file mode 100644
index 00000000..51c48a28
--- /dev/null
+++ b/src/lib/daemon_start.c
@@ -0,0 +1,928 @@
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
20/**
21 * @file lib/daemon.c
22 * @brief functions to start a daemon
23 * @author Christian Grothoff
24 */
25#include "internal.h"
26
27/* ************************* event loops ********************** */
28
29
30
31/* TODO: migrate! */
32
33
34/* ************* Functions for MHD_daemon_start() ************ */
35
36
37/**
38 * Set listen socket options to allow port rebinding (or not)
39 * depending on how MHD was configured.
40 *
41 * @param daemon[in,out] the daemon with the listen socket to configure
42 * @return #MHD_SC_OK on success (or non-fatal errors)
43 */
44static enum MHD_StatusCode
45configure_listen_reuse (struct MHD_Daemon *daemon)
46{
47 const MHD_SCKT_OPT_BOOL_ on = 1;
48
49 /* Apply the socket options according to
50 listening_address_reuse. */
51 /* FIXME: used to be -1/0/1, now defined as a bool!
52 MISMATCH! */
53 if (0 == daemon->listening_address_reuse)
54 {
55#ifndef MHD_WINSOCK_SOCKETS
56 /* No user requirement, use "traditional" default SO_REUSEADDR
57 * on non-W32 platforms, and do not fail if it doesn't work.
58 * Don't use it on W32, because on W32 it will allow multiple
59 * bind to the same address:port, like SO_REUSEPORT on others. */
60 if (0 > setsockopt (listen_fd,
61 SOL_SOCKET,
62 SO_REUSEADDR,
63 (void*) &on, sizeof (on)))
64 {
65#ifdef HAVE_MESSAGES
66 MHD_DLOG (daemon,
67 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
68 _("setsockopt failed: %s\n"),
69 MHD_socket_last_strerr_ ());
70#endif
71 }
72#endif /* ! MHD_WINSOCK_SOCKETS */
73 return MHD_SC_OK;
74 }
75 if (daemon->listening_address_reuse > 0)
76 {
77 /* User requested to allow reusing listening address:port. */
78#ifndef MHD_WINSOCK_SOCKETS
79 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
80 * it doesn't work. */
81 if (0 > setsockopt (listen_fd,
82 SOL_SOCKET,
83 SO_REUSEADDR,
84 (void*)&on, sizeof (on)))
85 {
86#ifdef HAVE_MESSAGES
87 MHD_DLOG (daemon,
88 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
89 _("setsockopt failed: %s\n"),
90 MHD_socket_last_strerr_ ());
91#endif
92 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
93 }
94#endif /* ! MHD_WINSOCK_SOCKETS */
95 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
96 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
97 */
98 /* SO_REUSEADDR on W32 has the same semantics
99 as SO_REUSEPORT on BSD/Linux */
100#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
101 if (0 > setsockopt (listen_fd,
102 SOL_SOCKET,
103#ifndef MHD_WINSOCK_SOCKETS
104 SO_REUSEPORT,
105#else /* MHD_WINSOCK_SOCKETS */
106 SO_REUSEADDR,
107#endif /* MHD_WINSOCK_SOCKETS */
108 (void *) &on,
109 sizeof (on)))
110 {
111#ifdef HAVE_MESSAGES
112 MHD_DLOG (daemon,
113 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
114 _("setsockopt failed: %s\n"),
115 MHD_socket_last_strerr_ ());
116#endif
117 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
118 }
119#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
120 /* we're supposed to allow address:port re-use, but
121 on this platform we cannot; fail hard */
122#ifdef HAVE_MESSAGES
123 MHD_DLOG (daemon,
124 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED,
125 _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
126#endif
127 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED;
128#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
129 }
130
131 /* if (daemon->listening_address_reuse < 0) */
132 /* User requested to disallow reusing listening address:port.
133 * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
134 * is used and Solaris with SO_EXCLBIND.
135 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
136 * or setsockopt fails.
137 */
138#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
139 (defined(__sun) && defined(SO_EXCLBIND))
140 if (0 > setsockopt (listen_fd,
141 SOL_SOCKET,
142#ifdef SO_EXCLUSIVEADDRUSE
143 SO_EXCLUSIVEADDRUSE,
144#else /* SO_EXCLBIND */
145 SO_EXCLBIND,
146#endif /* SO_EXCLBIND */
147 (void *) &on,
148 sizeof (on)))
149 {
150#ifdef HAVE_MESSAGES
151 MHD_DLOG (daemon,
152 MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED,
153 _("setsockopt failed: %s\n"),
154 MHD_socket_last_strerr_ ());
155#endif
156 return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED;
157 }
158#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
159#ifdef HAVE_MESSAGES
160 MHD_DLOG (daemon,
161 MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED,
162 _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
163#endif
164 return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED;
165#endif /* MHD_WINSOCK_SOCKETS */
166 return MHD_SC_OK;
167}
168
169
170/**
171 * Open, configure and bind the listen socket (if required).
172 *
173 * @param daemon[in,out] daemon to open the socket for
174 * @return #MHD_SC_OK on success
175 */
176static enum MHD_StatusCode
177open_listen_socket (struct MHD_Daemon *daemon)
178{
179 enum MHD_StatusCode sc;
180 bool usev6;
181 socklen_t addrlen;
182 struct sockaddr_storage ss;
183 const struct sockaddr *sa;
184
185 if (MHD_INVALID_SOCKET != daemon->listen_fd)
186 return MHD_SC_OK; /* application opened it for us! */
187
188 /* Determine address family */
189 if (MHD_AF_NONE != daemon->address_family)
190 {
191 switch (daemon->address_family)
192 {
193 case MHD_AF_NONE:
194 abort ();
195 case MHD_AF_AUTO:
196#if HAVE_INET6
197 use_v6 = true;
198#else
199 use_v6 = false;
200#endif
201 break;
202 case MHD_AF_INET:
203 use_v6 = false;
204 break;
205 case MHD_AF_INET6:
206 case MHD_AF_DUAL:
207#if HAVE_INET6
208 use_v6 = true;
209 break;
210#else
211#ifdef HAVE_MESSAGES
212 MHD_DLOG (daemon,
213 MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD,
214 _("IPv6 not supported by this build\n"));
215#endif
216 return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD;
217#endif
218 }
219 }
220 else if (0 != daemon->listen_sa_len)
221 {
222 /* we have a listen address, get AF from there! */
223 switch (daemon->listen_sa.ss_family)
224 {
225 case AF_INET:
226 use_v6 = false;
227 break;
228#ifdef AF_INET6
229 case AF_INET6:
230 use_v6 = true;
231 break;
232#endif
233#ifdef AF_UNIX
234 case AF_UNIX:
235 // FIXME: not implemented
236 // (need to change MHD_socket_create_listen_() API!)
237#endif
238 default:
239 return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD;
240 }
241 }
242 else
243 {
244 /* no listening desired, that's OK */
245 return MHD_SC_OK;
246 }
247
248 /* try to open listen socket */
249 try_open_listen_socket:
250 daemon->listen_socket = MHD_socket_create_listen_(use_v6);
251 if ( (MHD_INVALID_SOCKET == daemon->listen_socket) &&
252 (MHD_AF_AUTO == daemon->address_family) &&
253 (use_v6) )
254 {
255 use_v6 = false;
256 goto try_open_listen_socket;
257 }
258 if (MHD_INVALID_SOCKET == daemon->listen_socket)
259 {
260#ifdef HAVE_MESSAGES
261 MHD_DLOG (daemon,
262 MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET,
263 _("Failed to create socket for listening: %s\n"),
264 MHD_socket_last_strerr_ ());
265#endif
266 return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET;
267 }
268
269 if (MHD_SC_OK !=
270 (sc = configure_listen_reuse (daemon)))
271 return sc;
272
273 /* configure for dual stack (or not) */
274 if (use_v6)
275 {
276#if defined IPPROTO_IPV6 && defined IPV6_V6ONLY
277 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options"
278 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx);
279 and may also be missing on older POSIX systems; good luck if you have any of those,
280 your IPv6 socket may then also bind against IPv4 anyway... */
281 const MHD_SCKT_OPT_BOOL_ v6_only =
282 (MHD_AF_INET6 == daemon->address_family);
283 if (0 > setsockopt (listen_fd,
284 IPPROTO_IPV6,
285 IPV6_V6ONLY,
286 (const void *) &v6_only,
287 sizeof (v6_only)))
288 {
289#ifdef HAVE_MESSAGES
290 MHD_DLOG (daemon,
291 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_FAILED,
292 _("setsockopt failed: %s\n"),
293 MHD_socket_last_strerr_ ());
294#endif
295 }
296#else
297#ifdef HAVE_MESSAGES
298 MHD_DLOG (daemon,
299 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED,
300 _("Cannot explicitly setup dual stack behavior on this platform\n"));
301#endif
302#endif
303 }
304
305 /* Determine address to bind to */
306 if (0 != daemon->listen_sa_len)
307 {
308 /* Bind address explicitly given */
309 sa = daemon->listen_sa;
310 addrlen = daemon->listen_sa_len;
311 }
312 else
313 {
314 /* Compute bind address based on port and AF */
315#if HAVE_INET6
316 if (use_v6)
317 {
318#ifdef IN6ADDR_ANY_INIT
319 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
320#endif
321 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
322
323 addrlen = sizeof (struct sockaddr_in6);
324 memset (sin6,
325 0,
326 sizeof (struct sockaddr_in6));
327 sin6->sin6_family = AF_INET6;
328 sin6->sin6_port = htons (daemon->listen_port);
329#ifdef IN6ADDR_ANY_INIT
330 sin6->sin6_addr = static_in6any;
331#endif
332#if HAVE_SOCKADDR_IN_SIN_LEN
333 sin6->sin6_len = sizeof (struct sockaddr_in6);
334#endif
335 }
336 else
337#endif
338 {
339 struct sockaddr_in *sin4 = (struct sockaddr_in *) &ss;
340
341 addrlen = sizeof (struct sockaddr_in);
342 memset (sin4,
343 0,
344 sizeof (struct sockaddr_in));
345 sin4->sin_family = AF_INET;
346 sin4->sin_port = htons (daemon->listen_port);
347 if (0 != INADDR_ANY)
348 sin4->sin_addr.s_addr = htonl (INADDR_ANY);
349#if HAVE_SOCKADDR_IN_SIN_LEN
350 sin4->sin_len = sizeof (struct sockaddr_in);
351#endif
352 }
353 sa = (const struct sockaddr *) ss;
354 }
355
356 /* actually do the bind() */
357 if (-1 == bind (daemon->listen_socket,
358 sa,
359 addrlen))
360 {
361#ifdef HAVE_MESSAGES
362 unsigned int port = 0;
363
364 switch (sa->sa_family)
365 {
366 case AF_INET:
367 if (addrlen == sizeof (struct sockaddr_in))
368 port = ntohs (((const struct sockaddr_in*)sa)->sin_port);
369 else
370 port = UINT16_MAX + 1; /* indicate size error */
371 break;
372 case AF_INET6:
373 if (addrlen == sizeof (struct sockaddr_in6))
374 port = ntohs (((const struct sockaddr_in6*)sa)->sin_port);
375 else
376 port = UINT16_MAX + 1; /* indicate size error */
377 break;
378 default:
379 port = UINT_MAX; /* AF_UNIX? */
380 break;
381 }
382 MHD_DLOG (daemon,
383 MHD_SC_LISTEN_SOCKET_BIND_FAILED,
384 _("Failed to bind to port %u: %s\n"),
385 port,
386 MHD_socket_last_strerr_ ());
387#endif
388 return MHD_SC_LISTEN_SOCKET_BIND_FAILED;
389 }
390
391 /* setup TCP_FASTOPEN */
392#ifdef TCP_FASTOPEN
393 if (MHD_FOM_DISABLE != daemon->fast_open_method)
394 {
395 if (0 != setsockopt (daemon->listen_socket,
396 IPPROTO_TCP,
397 TCP_FASTOPEN,
398 &daemon->fastopen_queue_size,
399 sizeof (daemon->fastopen_queue_size)))
400 {
401#ifdef HAVE_MESSAGES
402 MHD_DLOG (daemon,
403 MHD_SC_FAST_OPEN_FAILURE,
404 _("setsockopt failed: %s\n"),
405 MHD_socket_last_strerr_ ());
406#endif
407 if (MHD_FOM_REQUIRE == daemon->fast_open_method)
408 return MHD_SC_FAST_OPEN_FAILURE;
409 }
410 }
411#endif
412
413 /* setup listening */
414 if (0 > listen (daemon->listen_socket,
415 daemon->listen_backlog_size))
416 {
417#ifdef HAVE_MESSAGES
418 MHD_DLOG (daemon,
419 MHD_SC_LISTEN_FAILURE,
420 _("Failed to listen for connections: %s\n"),
421 MHD_socket_last_strerr_ ());
422#endif
423 return MHD_SC_LISTEN_FAILURE;
424 }
425 return MHD_SC_OK;
426}
427
428
429/**
430 * Obtain the listen port number from the socket (if it
431 * was not explicitly set by us, i.e. if we were given
432 * a listen socket or if the port was 0 and the OS picked
433 * a free one).
434 *
435 * @param daemon[in,out] daemon to obtain the port number for
436 */
437static void
438get_listen_port_number (struct MHD_Daemon *daemon)
439{
440 struct sockaddr_storage servaddr;
441 socklen_t addrlen;
442
443 if ( (0 != daemon->port) ||
444 (MHD_INVALID_SOCKET == daemon->listen_socket) )
445 return; /* nothing to be done */
446
447 memset (&servaddr,
448 0,
449 sizeof (struct sockaddr_storage));
450 addrlen = sizeof (servaddr);
451 if (0 != getsockname (daemon->listen_socket,
452 (struct sockaddr *) &servaddr,
453 &addrlen))
454 {
455#ifdef HAVE_MESSAGES
456 MHD_DLOG (daemon,
457 MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
458 _("Failed to get listen port number: %s\n"),
459 MHD_socket_last_strerr_ ());
460#endif /* HAVE_MESSAGES */
461 return;
462 }
463#ifdef MHD_POSIX_SOCKETS
464 if (sizeof (servaddr) < addrlen)
465 {
466 /* should be impossible with `struct sockaddr_storage` */
467#ifdef HAVE_MESSAGES
468 MHD_DLOG (daemon,
469 MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
470 _("Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"));
471#endif /* HAVE_MESSAGES */
472 return;
473 }
474#endif /* MHD_POSIX_SOCKETS */
475 switch (servaddr.ss_family)
476 {
477 case AF_INET:
478 {
479 struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
480
481 daemon->port = ntohs (s4->sin_port);
482 break;
483 }
484#ifdef HAVE_INET6
485 case AF_INET6:
486 {
487 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
488
489 daemon->port = ntohs(s6->sin6_port);
490 break;
491 }
492#endif /* HAVE_INET6 */
493#ifdef AF_UNIX
494 case AF_UNIX:
495 daemon->port = 0; /* special value for UNIX domain sockets */
496 break;
497#endif
498 default:
499#ifdef HAVE_MESSAGES
500 MHD_DLOG (daemon,
501 MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF,
502 _("Unknown address family!\n"));
503#endif
504 daemon->port = 0; /* ugh */
505 break;
506 }
507}
508
509
510/**
511 * Setup epoll() FD for the daemon and initialize it to listen
512 * on the listen FD.
513 * @remark To be called only from thread that process
514 * daemon's select()/poll()/etc.
515 *
516 * @param daemon daemon to initialize for epoll()
517 * @return #MHD_SC_OK on success
518 */
519static enum MHD_StatusCode
520setup_epoll_to_listen (struct MHD_Daemon *daemon)
521{
522 struct epoll_event event;
523 MHD_socket ls;
524
525 /* FIXME: update function! */
526 daemon->epoll_fd = setup_epoll_fd (daemon);
527 if (-1 == daemon->epoll_fd)
528 return MHD_NO;
529#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
530 if (0 != (MHD_ALLOW_UPGRADE & daemon->options))
531 {
532 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
533 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
534 return MHD_NO;
535 }
536#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
537 if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) ||
538 (daemon->was_quiesced) )
539 return MHD_YES; /* non-listening daemon */
540 event.events = EPOLLIN;
541 event.data.ptr = daemon;
542 if (0 != epoll_ctl (daemon->epoll_fd,
543 EPOLL_CTL_ADD,
544 ls,
545 &event))
546 {
547#ifdef HAVE_MESSAGES
548 MHD_DLOG (daemon,
549 _("Call to epoll_ctl failed: %s\n"),
550 MHD_socket_last_strerr_ ());
551#endif
552 return MHD_NO;
553 }
554 daemon->listen_socket_in_epoll = true;
555 if (MHD_ITC_IS_VALID_(daemon->itc))
556 {
557 event.events = EPOLLIN;
558 event.data.ptr = (void *) epoll_itc_marker;
559 if (0 != epoll_ctl (daemon->epoll_fd,
560 EPOLL_CTL_ADD,
561 MHD_itc_r_fd_ (daemon->itc),
562 &event))
563 {
564#ifdef HAVE_MESSAGES
565 MHD_DLOG (daemon,
566 _("Call to epoll_ctl failed: %s\n"),
567 MHD_socket_last_strerr_ ());
568#endif
569 return MHD_NO;
570 }
571 }
572 return MHD_SC_OK;
573}
574#endif
575
576
577/**
578 * Thread that runs the polling loop until the daemon
579 * is explicitly shut down.
580 *
581 * @param cls `struct MHD_Deamon` to run select loop in a thread for
582 * @return always 0 (on shutdown)
583 */
584static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
585MHD_polling_thread (void *cls)
586{
587 struct MHD_Daemon *daemon = cls;
588
589 MHD_thread_init_ (&daemon->pid);
590 while (! daemon->shutdown)
591 {
592 switch (daemon->event_loop_syscall)
593 {
594 case MHD_ELS_AUTO:
595 MHD_PANIC ("MHD_ELS_AUTO should have been mapped to preferred style");
596 break;
597 case MHD_ELS_SELECT:
598 MHD_select (daemon,
599 MHD_YES);
600 break;
601 case MHD_ELS_POLL:
602 MHD_poll (daemon,
603 MHD_YES);
604 break;
605 case MHD_ELS_EPOLL:
606#ifdef EPOLL_SUPPORT
607 MHD_epoll (daemon,
608 MHD_YES);
609#else
610 MHD_PANIC ("MHD_ELS_EPOLL not supported, should have failed earlier");
611#endif
612 break;
613 }
614 MHD_cleanup_connections (daemon);
615 }
616 /* Resume any pending for resume connections, join
617 * all connection's threads (if any) and finally cleanup
618 * everything. */
619 close_all_connections (daemon);
620
621 return (MHD_THRD_RTRN_TYPE_)0;
622}
623
624
625/**
626 * Setup the thread pool (if needed).
627 *
628 * @param daemon[in,out] daemon to setup thread pool for
629 * @return #MHD_SC_OK on success
630 */
631static enum MHD_StatusCode
632setup_thread_pool (struct MHD_Daemon *daemon)
633{
634 /* Coarse-grained count of connections per thread (note error
635 * due to integer division). Also keep track of how many
636 * connections are leftover after an equal split. */
637 unsigned int conns_per_thread = daemon->connection_limit
638 / daemon->threading_model;
639 unsigned int leftover_conns = daemon->connection_limit
640 % daemon->threading_model;
641 unsigned int i;
642 enum MHD_StatusCode sc;
643
644 /* Allocate memory for pooled objects */
645 daemon->worker_pool = MHD_calloc_ (daemon->threading_model,
646 sizeof (struct MHD_Daemon));
647 if (NULL == daemon->worker_pool)
648 return MHD_SC_THREAD_POOL_MALLOC_FAILURE;
649
650 /* Start the workers in the pool */
651 for (i = 0; i < daemon->threading_model; i++)
652 {
653 /* Create copy of the Daemon object for each worker */
654 struct MHD_Daemon *d = &daemon->worker_pool[i];
655
656 memcpy (d,
657 daemon,
658 sizeof (struct MHD_Daemon));
659 /* Adjust pooling params for worker daemons; note that memcpy()
660 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread model into
661 the worker threads. */
662 d->master = daemon;
663 d->worker_pool_size = 0;
664 d->worker_pool = NULL;
665 /* Divide available connections evenly amongst the threads.
666 * Thread indexes in [0, leftover_conns) each get one of the
667 * leftover connections. */
668 d->connection_limit = conns_per_thread;
669 if (i < leftover_conns)
670 ++d->connection_limit;
671
672 if (! daemon->disable_itc)
673 {
674 if (! MHD_itc_init_ (d->itc))
675 {
676#ifdef HAVE_MESSAGES
677 MHD_DLOG (daemon,
678 MHD_SC_ITC_INITIALIZATION_FAILED,
679 _("Failed to create worker inter-thread communication channel: %s\n"),
680 MHD_itc_last_strerror_() );
681#endif
682 sc = MHD_SC_ITC_INITIALIZATION_FAILED;
683 goto thread_failed;
684 }
685 if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
686 (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc),
687 NULL)) )
688 {
689#ifdef HAVE_MESSAGES
690 MHD_DLOG (daemon,
691 MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
692 _("File descriptor for inter-thread communication channel exceeds maximum value\n"));
693#endif
694 MHD_itc_destroy_chk_ (d->itc);
695 sc = MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
696 goto thread_failed;
697 }
698 }
699 else
700 {
701 MHD_itc_set_invalid_ (d->itc);
702 }
703
704#ifdef EPOLL_SUPPORT
705 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
706 (MHD_SC_OK != (sc = setup_epoll_to_listen (d))) )
707 goto thread_failed;
708#endif
709
710 /* Must init cleanup connection mutex for each worker */
711 if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
712 {
713#ifdef HAVE_MESSAGES
714 MHD_DLOG (daemon,
715 MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE,
716 _("MHD failed to initialize cleanup connection mutex\n"));
717#endif
718 if (! daemon->disable_itc)
719 MHD_itc_destroy_chk_ (d->itc);
720 sc = MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE;
721 goto thread_failed;
722 }
723
724 /* Spawn the worker thread */
725 if (! MHD_create_named_thread_ (&d->pid,
726 "MHD-worker",
727 daemon->thread_stack_size,
728 &MHD_polling_thread,
729 d))
730 {
731#ifdef HAVE_MESSAGES
732 MHD_DLOG (daemon,
733 MHD_SC_THREAD_POOL_LAUNCH_FAILURE,
734 _("Failed to create pool thread: %s\n"),
735 MHD_strerror_ (errno));
736#endif
737 sc = MHD_SC_THREAD_POOL_LAUNCH_FAILURE;
738 /* Free memory for this worker; cleanup below handles
739 * all previously-created workers. */
740 if (! daemon->disable_itc)
741 MHD_itc_destroy_chk_ (d->itc);
742 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
743 goto thread_failed;
744 }
745 } /* end for() */
746 return MHD_SC_OK;
747
748thread_failed:
749 /* If no worker threads created, then shut down normally. Calling
750 MHD_stop_daemon (as we do below) doesn't work here since it
751 assumes a 0-sized thread pool means we had been in the default
752 MHD_USE_INTERNAL_POLLING_THREAD mode. */
753 if (0 == i)
754 {
755 if (NULL != daemon->worker_pool)
756 {
757 free (daemon->worker_pool);
758 daemon->worker_pool = NULL;
759 }
760 return MHD_SC_THREAD_LAUNCH_FAILURE;
761 }
762 /* Shutdown worker threads we've already created. Pretend
763 as though we had fully initialized our daemon, but
764 with a smaller number of threads than had been
765 requested. */
766 daemon->worker_pool_size = i;
767 daemon->listen_socket = MHD_daemon_quiesce (daemon);
768 return MHD_SC_THREAD_LAUNCH_FAILURE;
769}
770
771
772/**
773 * Start a webserver.
774 *
775 * @param daemon daemon to start; you can no longer set
776 * options on this daemon after this call!
777 * @return #MHD_SC_OK on success
778 * @ingroup event
779 */
780enum MHD_StatusCode
781MHD_daemon_start (struct MHD_Daemon *daemon)
782{
783 enum MHD_StatusCode sc;
784
785 if (MHD_ELS_AUTO == daemon->event_loop_syscall)
786 {
787#if EPOLL_SUPPORT
788 /* We do not support thread-per-connection in combination
789 with epoll, so use poll in this case, otherwise prefer
790 epoll. */
791 if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model)
792 daemon->event_loop_syscall = MHD_ELS_POLL;
793 else
794 daemon->event_loop_syscall = MHD_ELS_EPOLL;
795#elif HAVE_POLL
796 daemon->event_loop_syscall = MHD_ELS_POLL;
797#else
798 daemon->event_loop_syscall = MHD_ELS_SELECT;
799#endif
800 }
801
802#ifdef EPOLL_SUPPORT
803 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
804 (0 == daemon->worker_pool_size) &&
805 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
806 (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model) )
807 {
808#ifdef HAVE_MESSAGES
809 MHD_DLOG (daemon,
810 MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID,
811 _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
812#endif
813 return MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID;
814 }
815#endif
816
817 /* Setup ITC */
818 if ( (! daemon->disable_itc) &&
819 (0 == daemon->worker_pool_size) )
820 {
821 if (! MHD_itc_init_ (daemon->itc))
822 {
823#ifdef HAVE_MESSAGES
824 MHD_DLOG (daemon,
825 MHD_SC_ITC_INITIALIZATION_FAILED,
826 _("Failed to create inter-thread communication channel: %s\n"),
827 MHD_itc_last_strerror_ ());
828#endif
829 return MHD_SC_ITC_INITIALIZATION_FAILED;
830 }
831 if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
832 (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc),
833 NULL)) )
834 {
835#ifdef HAVE_MESSAGES
836 MHD_DLOG (daemon,
837 MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
838 _("File descriptor for inter-thread communication channel exceeds maximum value\n"));
839#endif
840 return MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
841 }
842 }
843
844 if (MHD_SC_OK != (sc = open_listen_socket (daemon)))
845 return sc;
846
847 /* Check listen socket is in range (if we are limited) */
848 if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
849 (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
850 (! MHD_SCKT_FD_FITS_FDSET_(daemon->listen_socket,
851 NULL)) )
852 {
853#ifdef HAVE_MESSAGES
854 MHD_DLOG (daemon,
855 MHD_SC_LISTEN_SOCKET_TOO_LARGE,
856 _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
857 daemon->listen_socket,
858 FD_SETSIZE);
859#endif
860 return MHD_SC_LISTEN_SOCKET_TOO_LARGE;
861 }
862
863 /* set listen socket to non-blocking */
864 if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
865 (! MHD_socket_nonblocking_ (daemon->listen_socket)) )
866 {
867#ifdef HAVE_MESSAGES
868 MHD_DLOG (daemon,
869 MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE,
870 _("Failed to set nonblocking mode on listening socket: %s\n"),
871 MHD_socket_last_strerr_());
872#endif
873 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) ||
874 (daemon->worker_pool_size > 0) )
875 {
876 /* Accept must be non-blocking. Multiple children may wake
877 * up to handle a new connection, but only one will win the
878 * race. The others must immediately return. As this is
879 * not possible, we must fail hard here. */
880 return MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE;
881 }
882 }
883
884#ifdef EPOLL_SUPPORT
885 /* Setup epoll */
886 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
887 (0 == daemon->worker_pool_size) &&
888 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
889 (MHD_SC_OK != (sc = setup_epoll_to_listen (daemon))) )
890 return sc;
891#endif
892
893 /* Setup main listen thread (only if we have no thread pool or
894 external event loop and do have a listen socket) */
895 /* FIXME: why no worker thread if we have no listen socket? */
896 if ( ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model) ||
897 (1 == daemon->threading_model) ) &&
898 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
899 (! MHD_create_named_thread_ (&daemon->pid,
900 (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model)
901 ? "MHD-listen"
902 : "MHD-single",
903 daemon->thread_stack_size,
904 &MHD_polling_thread,
905 daemon) )
906 {
907#ifdef HAVE_MESSAGES
908 MHD_DLOG (daemon,
909 MHD_SC_THREAD_MAIN_LAUNCH_FAILURE,
910 _("Failed to create listen thread: %s\n"),
911 MHD_strerror_ (errno));
912#endif
913 return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE;
914 }
915
916 /* Setup worker threads */
917 /* FIXME: why no thread pool if we have no listen socket? */
918 if ( (1 < daemon->threading_model) &&
919 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
920 (MHD_SC_OK != (sc = setup_thread_pool (daemon))) )
921 return sc;
922
923 return MHD_SC_OK;
924}
925
926
927
928/* end of daemon.c */