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.c1013
1 files changed, 511 insertions, 502 deletions
diff --git a/src/lib/daemon_start.c b/src/lib/daemon_start.c
index 52124c77..c8c498be 100644
--- a/src/lib/daemon_start.c
+++ b/src/lib/daemon_start.c
@@ -46,63 +46,64 @@ configure_listen_reuse (struct MHD_Daemon *daemon)
46 /* Apply the socket options according to 46 /* Apply the socket options according to
47 listening_address_reuse. */ 47 listening_address_reuse. */
48 if (daemon->allow_address_reuse) 48 if (daemon->allow_address_reuse)
49 { 49 {
50 /* User requested to allow reusing listening address:port. */ 50 /* User requested to allow reusing listening address:port. */
51#ifndef MHD_WINSOCK_SOCKETS 51#ifndef MHD_WINSOCK_SOCKETS
52 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if 52 /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if
53 * it doesn't work. */ 53 * it doesn't work. */
54 if (0 > setsockopt (daemon->listen_socket, 54 if (0 > setsockopt (daemon->listen_socket,
55 SOL_SOCKET, 55 SOL_SOCKET,
56 SO_REUSEADDR, 56 SO_REUSEADDR,
57 (void *) &on, 57 (void *) &on,
58 sizeof (on))) 58 sizeof (on)))
59 { 59 {
60#ifdef HAVE_MESSAGES 60#ifdef HAVE_MESSAGES
61 MHD_DLOG (daemon, 61 MHD_DLOG (daemon,
62 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED, 62 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
63 _("setsockopt failed: %s\n"), 63 _ ("setsockopt failed: %s\n"),
64 MHD_socket_last_strerr_ ()); 64 MHD_socket_last_strerr_ ());
65#endif 65#endif
66 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED; 66 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
67 } 67 }
68 return MHD_SC_OK; 68 return MHD_SC_OK;
69#endif /* ! MHD_WINSOCK_SOCKETS */ 69#endif /* ! MHD_WINSOCK_SOCKETS */
70 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms. 70 /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
71 * Fail if SO_REUSEPORT is not defined or setsockopt fails. 71 * Fail if SO_REUSEPORT is not defined or setsockopt fails.
72 */ 72 */
73 /* SO_REUSEADDR on W32 has the same semantics 73 /* SO_REUSEADDR on W32 has the same semantics
74 as SO_REUSEPORT on BSD/Linux */ 74 as SO_REUSEPORT on BSD/Linux */
75#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT) 75#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
76 if (0 > setsockopt (daemon->listen_socket, 76 if (0 > setsockopt (daemon->listen_socket,
77 SOL_SOCKET, 77 SOL_SOCKET,
78#ifndef MHD_WINSOCK_SOCKETS 78#ifndef MHD_WINSOCK_SOCKETS
79 SO_REUSEPORT, 79 SO_REUSEPORT,
80#else /* MHD_WINSOCK_SOCKETS */ 80#else /* MHD_WINSOCK_SOCKETS */
81 SO_REUSEADDR, 81 SO_REUSEADDR,
82#endif /* MHD_WINSOCK_SOCKETS */ 82#endif /* MHD_WINSOCK_SOCKETS */
83 (void *) &on, 83 (void *) &on,
84 sizeof (on))) 84 sizeof (on)))
85 { 85 {
86#ifdef HAVE_MESSAGES 86#ifdef HAVE_MESSAGES
87 MHD_DLOG (daemon, 87 MHD_DLOG (daemon,
88 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED, 88 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED,
89 _("setsockopt failed: %s\n"), 89 _ ("setsockopt failed: %s\n"),
90 MHD_socket_last_strerr_ ()); 90 MHD_socket_last_strerr_ ());
91#endif 91#endif
92 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED; 92 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED;
93 } 93 }
94 return MHD_SC_OK; 94 return MHD_SC_OK;
95#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */ 95#else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
96 /* we're supposed to allow address:port re-use, but 96 /* we're supposed to allow address:port re-use, but
97 on this platform we cannot; fail hard */ 97 on this platform we cannot; fail hard */
98#ifdef HAVE_MESSAGES 98#ifdef HAVE_MESSAGES
99 MHD_DLOG (daemon, 99 MHD_DLOG (daemon,
100 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED, 100 MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED,
101 _("Cannot allow listening address reuse: SO_REUSEPORT not defined\n")); 101 _ (
102 "Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
102#endif 103#endif
103 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED; 104 return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_NOT_SUPPORTED;
104#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */ 105#endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */
105 } 106 }
106 107
107 /* if (! daemon->allow_address_reuse) */ 108 /* if (! daemon->allow_address_reuse) */
108 /* User requested to disallow reusing listening address:port. 109 /* User requested to disallow reusing listening address:port.
@@ -111,32 +112,33 @@ configure_listen_reuse (struct MHD_Daemon *daemon)
111 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE 112 * Fail if MHD was compiled for W32 without SO_EXCLUSIVEADDRUSE
112 * or setsockopt fails. 113 * or setsockopt fails.
113 */ 114 */
114#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \ 115#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
115 (defined(__sun) && defined(SO_EXCLBIND)) 116 (defined(__sun) && defined(SO_EXCLBIND))
116 if (0 > setsockopt (daemon->listen_socket, 117 if (0 > setsockopt (daemon->listen_socket,
117 SOL_SOCKET, 118 SOL_SOCKET,
118#ifdef SO_EXCLUSIVEADDRUSE 119#ifdef SO_EXCLUSIVEADDRUSE
119 SO_EXCLUSIVEADDRUSE, 120 SO_EXCLUSIVEADDRUSE,
120#else /* SO_EXCLBIND */ 121#else /* SO_EXCLBIND */
121 SO_EXCLBIND, 122 SO_EXCLBIND,
122#endif /* SO_EXCLBIND */ 123#endif /* SO_EXCLBIND */
123 (void *) &on, 124 (void *) &on,
124 sizeof (on))) 125 sizeof (on)))
125 { 126 {
126#ifdef HAVE_MESSAGES 127#ifdef HAVE_MESSAGES
127 MHD_DLOG (daemon, 128 MHD_DLOG (daemon,
128 MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED, 129 MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED,
129 _("setsockopt failed: %s\n"), 130 _ ("setsockopt failed: %s\n"),
130 MHD_socket_last_strerr_ ()); 131 MHD_socket_last_strerr_ ());
131#endif 132#endif
132 return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED; 133 return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED;
133 } 134 }
134 return MHD_SC_OK; 135 return MHD_SC_OK;
135#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */ 136#elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */
136#ifdef HAVE_MESSAGES 137#ifdef HAVE_MESSAGES
137 MHD_DLOG (daemon, 138 MHD_DLOG (daemon,
138 MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED, 139 MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED,
139 _("Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n")); 140 _ (
141 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
140#endif 142#endif
141 return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED; 143 return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED;
142#endif /* MHD_WINSOCK_SOCKETS */ 144#endif /* MHD_WINSOCK_SOCKETS */
@@ -166,86 +168,86 @@ open_listen_socket (struct MHD_Daemon *daemon)
166 pf = -1; 168 pf = -1;
167 /* Determine address family */ 169 /* Determine address family */
168 switch (daemon->listen_af) 170 switch (daemon->listen_af)
171 {
172 case MHD_AF_NONE:
173 if (0 == daemon->listen_sa_len)
169 { 174 {
170 case MHD_AF_NONE: 175 /* no listening desired, that's OK */
171 if (0 == daemon->listen_sa_len) 176 return MHD_SC_OK;
172 { 177 }
173 /* no listening desired, that's OK */ 178 /* we have a listen address, get AF from there! */
174 return MHD_SC_OK; 179 switch (daemon->listen_sa.ss_family)
175 } 180 {
176 /* we have a listen address, get AF from there! */ 181 case AF_INET:
177 switch (daemon->listen_sa.ss_family) 182 pf = PF_INET;
178 { 183 use_v6 = false;
179 case AF_INET: 184 break;
180 pf = PF_INET;
181 use_v6 = false;
182 break;
183#ifdef AF_INET6 185#ifdef AF_INET6
184 case AF_INET6: 186 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; 187 pf = PF_INET6;
202 use_v6 = true; 188 use_v6 = true;
203#else
204 pf = PF_INET;
205 use_v6 = false;
206#endif
207 break; 189 break;
208 case MHD_AF_INET4: 190#endif
191#ifdef AF_UNIX
192 case AF_UNIX:
193 pf = PF_UNIX;
209 use_v6 = false; 194 use_v6 = false;
210 pf = PF_INET;
211 break; 195 break;
212 case MHD_AF_INET6: 196#endif
213 case MHD_AF_DUAL: 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:
214#if HAVE_INET6 202#if HAVE_INET6
215 pf = PF_INET6; 203 pf = PF_INET6;
216 use_v6 = true; 204 use_v6 = true;
217 break; 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;
218#else 220#else
219#ifdef HAVE_MESSAGES 221#ifdef HAVE_MESSAGES
220 MHD_DLOG (daemon, 222 MHD_DLOG (daemon,
221 MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD, 223 MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD,
222 _("IPv6 not supported by this build\n")); 224 _ ("IPv6 not supported by this build\n"));
223#endif 225#endif
224 return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD; 226 return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD;
225#endif 227#endif
226 } 228 }
227 mhd_assert (-1 != pf); 229 mhd_assert (-1 != pf);
228 /* try to open listen socket */ 230 /* try to open listen socket */
229 try_open_listen_socket: 231try_open_listen_socket:
230 daemon->listen_socket = MHD_socket_create_listen_(pf); 232 daemon->listen_socket = MHD_socket_create_listen_ (pf);
231 if ( (MHD_INVALID_SOCKET == daemon->listen_socket) && 233 if ( (MHD_INVALID_SOCKET == daemon->listen_socket) &&
232 (MHD_AF_AUTO == daemon->listen_af) && 234 (MHD_AF_AUTO == daemon->listen_af) &&
233 (use_v6) ) 235 (use_v6) )
234 { 236 {
235 use_v6 = false; 237 use_v6 = false;
236 pf = PF_INET; 238 pf = PF_INET;
237 goto try_open_listen_socket; 239 goto try_open_listen_socket;
238 } 240 }
239 if (MHD_INVALID_SOCKET == daemon->listen_socket) 241 if (MHD_INVALID_SOCKET == daemon->listen_socket)
240 { 242 {
241#ifdef HAVE_MESSAGES 243#ifdef HAVE_MESSAGES
242 MHD_DLOG (daemon, 244 MHD_DLOG (daemon,
243 MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET, 245 MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET,
244 _("Failed to create socket for listening: %s\n"), 246 _ ("Failed to create socket for listening: %s\n"),
245 MHD_socket_last_strerr_ ()); 247 MHD_socket_last_strerr_ ());
246#endif 248#endif
247 return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET; 249 return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET;
248 } 250 }
249 251
250 if (MHD_SC_OK != 252 if (MHD_SC_OK !=
251 (sc = configure_listen_reuse (daemon))) 253 (sc = configure_listen_reuse (daemon)))
@@ -253,156 +255,157 @@ open_listen_socket (struct MHD_Daemon *daemon)
253 255
254 /* configure for dual stack (or not) */ 256 /* configure for dual stack (or not) */
255 if (use_v6) 257 if (use_v6)
256 { 258 {
257#if defined IPPROTO_IPV6 && defined IPV6_V6ONLY 259#if defined IPPROTO_IPV6 && defined IPV6_V6ONLY
258 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options" 260 /* 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); 261 (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, 262 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... */ 263 your IPv6 socket may then also bind against IPv4 anyway... */
262 const MHD_SCKT_OPT_BOOL_ v6_only = 264 const MHD_SCKT_OPT_BOOL_ v6_only =
263 (MHD_AF_INET6 == daemon->listen_af); 265 (MHD_AF_INET6 == daemon->listen_af);
264 if (0 > setsockopt (daemon->listen_socket, 266 if (0 > setsockopt (daemon->listen_socket,
265 IPPROTO_IPV6, 267 IPPROTO_IPV6,
266 IPV6_V6ONLY, 268 IPV6_V6ONLY,
267 (const void *) &v6_only, 269 (const void *) &v6_only,
268 sizeof (v6_only))) 270 sizeof (v6_only)))
269 { 271 {
270#ifdef HAVE_MESSAGES 272#ifdef HAVE_MESSAGES
271 MHD_DLOG (daemon, 273 MHD_DLOG (daemon,
272 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_FAILED, 274 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_FAILED,
273 _("setsockopt failed: %s\n"), 275 _ ("setsockopt failed: %s\n"),
274 MHD_socket_last_strerr_ ()); 276 MHD_socket_last_strerr_ ());
275#endif 277#endif
276 } 278 }
277#else 279#else
278#ifdef HAVE_MESSAGES 280#ifdef HAVE_MESSAGES
279 MHD_DLOG (daemon, 281 MHD_DLOG (daemon,
280 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED, 282 MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_NOT_SUPPORTED,
281 _("Cannot explicitly setup dual stack behavior on this platform\n")); 283 _ (
284 "Cannot explicitly setup dual stack behavior on this platform\n"));
282#endif 285#endif
283#endif 286#endif
284 } 287 }
285 288
286 /* Determine address to bind to */ 289 /* Determine address to bind to */
287 if (0 != daemon->listen_sa_len) 290 if (0 != daemon->listen_sa_len)
288 { 291 {
289 /* Bind address explicitly given */ 292 /* Bind address explicitly given */
290 sa = (const struct sockaddr *) &daemon->listen_sa; 293 sa = (const struct sockaddr *) &daemon->listen_sa;
291 addrlen = daemon->listen_sa_len; 294 addrlen = daemon->listen_sa_len;
292 } 295 }
293 else 296 else
294 { 297 {
295 /* Compute bind address based on port and AF */ 298 /* Compute bind address based on port and AF */
296#if HAVE_INET6 299#if HAVE_INET6
297 if (use_v6) 300 if (use_v6)
298 { 301 {
299#ifdef IN6ADDR_ANY_INIT 302#ifdef IN6ADDR_ANY_INIT
300 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT; 303 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
301#endif 304#endif
302 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss; 305 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
303 306
304 addrlen = sizeof (struct sockaddr_in6); 307 addrlen = sizeof (struct sockaddr_in6);
305 memset (sin6, 308 memset (sin6,
306 0, 309 0,
307 sizeof (struct sockaddr_in6)); 310 sizeof (struct sockaddr_in6));
308 sin6->sin6_family = AF_INET6; 311 sin6->sin6_family = AF_INET6;
309 sin6->sin6_port = htons (daemon->listen_port); 312 sin6->sin6_port = htons (daemon->listen_port);
310#ifdef IN6ADDR_ANY_INIT 313#ifdef IN6ADDR_ANY_INIT
311 sin6->sin6_addr = static_in6any; 314 sin6->sin6_addr = static_in6any;
312#endif 315#endif
313#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 316#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
314 sin6->sin6_len = sizeof (struct sockaddr_in6); 317 sin6->sin6_len = sizeof (struct sockaddr_in6);
315#endif 318#endif
316 } 319 }
317 else 320 else
318#endif 321#endif
319 { 322 {
320 struct sockaddr_in *sin4 = (struct sockaddr_in *) &ss; 323 struct sockaddr_in *sin4 = (struct sockaddr_in *) &ss;
321 324
322 addrlen = sizeof (struct sockaddr_in); 325 addrlen = sizeof (struct sockaddr_in);
323 memset (sin4, 326 memset (sin4,
324 0, 327 0,
325 sizeof (struct sockaddr_in)); 328 sizeof (struct sockaddr_in));
326 sin4->sin_family = AF_INET; 329 sin4->sin_family = AF_INET;
327 sin4->sin_port = htons (daemon->listen_port); 330 sin4->sin_port = htons (daemon->listen_port);
328 if (0 != INADDR_ANY) 331 if (0 != INADDR_ANY)
329 sin4->sin_addr.s_addr = htonl (INADDR_ANY); 332 sin4->sin_addr.s_addr = htonl (INADDR_ANY);
330#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 333#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
331 sin4->sin_len = sizeof (struct sockaddr_in); 334 sin4->sin_len = sizeof (struct sockaddr_in);
332#endif 335#endif
333 }
334 sa = (const struct sockaddr *) &ss;
335 } 336 }
337 sa = (const struct sockaddr *) &ss;
338 }
336 339
337 /* actually do the bind() */ 340 /* actually do the bind() */
338 if (-1 == bind (daemon->listen_socket, 341 if (-1 == bind (daemon->listen_socket,
339 sa, 342 sa,
340 addrlen)) 343 addrlen))
341 { 344 {
342#ifdef HAVE_MESSAGES 345#ifdef HAVE_MESSAGES
343 unsigned int port = 0; 346 unsigned int port = 0;
344 347
345 switch (sa->sa_family) 348 switch (sa->sa_family)
346 { 349 {
347 case AF_INET: 350 case AF_INET:
348 if (addrlen == sizeof (struct sockaddr_in)) 351 if (addrlen == sizeof (struct sockaddr_in))
349 port = ntohs (((const struct sockaddr_in *) sa)->sin_port); 352 port = ntohs (((const struct sockaddr_in *) sa)->sin_port);
350 else 353 else
351 port = UINT16_MAX + 1; /* indicate size error */ 354 port = UINT16_MAX + 1; /* indicate size error */
352 break; 355 break;
353 case AF_INET6: 356 case AF_INET6:
354 if (addrlen == sizeof (struct sockaddr_in6)) 357 if (addrlen == sizeof (struct sockaddr_in6))
355 port = ntohs (((const struct sockaddr_in6 *) sa)->sin6_port); 358 port = ntohs (((const struct sockaddr_in6 *) sa)->sin6_port);
356 else 359 else
357 port = UINT16_MAX + 1; /* indicate size error */ 360 port = UINT16_MAX + 1; /* indicate size error */
358 break; 361 break;
359 default: 362 default:
360 port = UINT_MAX; /* AF_UNIX? */ 363 port = UINT_MAX; /* AF_UNIX? */
361 break; 364 break;
362 }
363 MHD_DLOG (daemon,
364 MHD_SC_LISTEN_SOCKET_BIND_FAILED,
365 _("Failed to bind to port %u: %s\n"),
366 port,
367 MHD_socket_last_strerr_ ());
368#endif
369 return MHD_SC_LISTEN_SOCKET_BIND_FAILED;
370 } 365 }
366 MHD_DLOG (daemon,
367 MHD_SC_LISTEN_SOCKET_BIND_FAILED,
368 _ ("Failed to bind to port %u: %s\n"),
369 port,
370 MHD_socket_last_strerr_ ());
371#endif
372 return MHD_SC_LISTEN_SOCKET_BIND_FAILED;
373 }
371 374
372 /* setup TCP_FASTOPEN */ 375 /* setup TCP_FASTOPEN */
373#ifdef TCP_FASTOPEN 376#ifdef TCP_FASTOPEN
374 if (MHD_FOM_DISABLE != daemon->fast_open_method) 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)))
375 { 384 {
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 385#ifdef HAVE_MESSAGES
383 MHD_DLOG (daemon, 386 MHD_DLOG (daemon,
384 MHD_SC_FAST_OPEN_FAILURE, 387 MHD_SC_FAST_OPEN_FAILURE,
385 _("setsockopt failed: %s\n"), 388 _ ("setsockopt failed: %s\n"),
386 MHD_socket_last_strerr_ ()); 389 MHD_socket_last_strerr_ ());
387#endif 390#endif
388 if (MHD_FOM_REQUIRE == daemon->fast_open_method) 391 if (MHD_FOM_REQUIRE == daemon->fast_open_method)
389 return MHD_SC_FAST_OPEN_FAILURE; 392 return MHD_SC_FAST_OPEN_FAILURE;
390 } 393 }
391 } 394 }
392#endif 395#endif
393 396
394 /* setup listening */ 397 /* setup listening */
395 if (0 > listen (daemon->listen_socket, 398 if (0 > listen (daemon->listen_socket,
396 daemon->listen_backlog)) 399 daemon->listen_backlog))
397 { 400 {
398#ifdef HAVE_MESSAGES 401#ifdef HAVE_MESSAGES
399 MHD_DLOG (daemon, 402 MHD_DLOG (daemon,
400 MHD_SC_LISTEN_FAILURE, 403 MHD_SC_LISTEN_FAILURE,
401 _("Failed to listen for connections: %s\n"), 404 _ ("Failed to listen for connections: %s\n"),
402 MHD_socket_last_strerr_ ()); 405 MHD_socket_last_strerr_ ());
403#endif 406#endif
404 return MHD_SC_LISTEN_FAILURE; 407 return MHD_SC_LISTEN_FAILURE;
405 } 408 }
406 return MHD_SC_OK; 409 return MHD_SC_OK;
407} 410}
408 411
@@ -426,65 +429,66 @@ get_listen_port_number (struct MHD_Daemon *daemon)
426 return; /* nothing to be done */ 429 return; /* nothing to be done */
427 430
428 memset (&servaddr, 431 memset (&servaddr,
429 0, 432 0,
430 sizeof (struct sockaddr_storage)); 433 sizeof (struct sockaddr_storage));
431 addrlen = sizeof (servaddr); 434 addrlen = sizeof (servaddr);
432 if (0 != getsockname (daemon->listen_socket, 435 if (0 != getsockname (daemon->listen_socket,
433 (struct sockaddr *) &servaddr, 436 (struct sockaddr *) &servaddr,
434 &addrlen)) 437 &addrlen))
435 { 438 {
436#ifdef HAVE_MESSAGES 439#ifdef HAVE_MESSAGES
437 MHD_DLOG (daemon, 440 MHD_DLOG (daemon,
438 MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE, 441 MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
439 _("Failed to get listen port number: %s\n"), 442 _ ("Failed to get listen port number: %s\n"),
440 MHD_socket_last_strerr_ ()); 443 MHD_socket_last_strerr_ ());
441#endif /* HAVE_MESSAGES */ 444#endif /* HAVE_MESSAGES */
442 return; 445 return;
443 } 446 }
444#ifdef MHD_POSIX_SOCKETS 447#ifdef MHD_POSIX_SOCKETS
445 if (sizeof (servaddr) < addrlen) 448 if (sizeof (servaddr) < addrlen)
446 { 449 {
447 /* should be impossible with `struct sockaddr_storage` */ 450 /* should be impossible with `struct sockaddr_storage` */
448#ifdef HAVE_MESSAGES 451#ifdef HAVE_MESSAGES
449 MHD_DLOG (daemon, 452 MHD_DLOG (daemon,
450 MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE, 453 MHD_SC_LISTEN_PORT_INTROSPECTION_FAILURE,
451 _("Failed to get listen port number (`struct sockaddr_storage` too small!?)\n")); 454 _ (
455 "Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"));
452#endif /* HAVE_MESSAGES */ 456#endif /* HAVE_MESSAGES */
453 return; 457 return;
454 } 458 }
455#endif /* MHD_POSIX_SOCKETS */ 459#endif /* MHD_POSIX_SOCKETS */
456 switch (servaddr.ss_family) 460 switch (servaddr.ss_family)
461 {
462 case AF_INET:
457 { 463 {
458 case AF_INET: 464 struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
459 {
460 struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr;
461 465
462 daemon->listen_port = ntohs (s4->sin_port); 466 daemon->listen_port = ntohs (s4->sin_port);
463 break; 467 break;
464 } 468 }
465#ifdef HAVE_INET6 469#ifdef HAVE_INET6
466 case AF_INET6: 470 case AF_INET6:
467 { 471 {
468 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr; 472 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr;
469 473
470 daemon->listen_port = ntohs(s6->sin6_port); 474 daemon->listen_port = ntohs (s6->sin6_port);
471 break; 475 break;
472 } 476 }
473#endif /* HAVE_INET6 */ 477#endif /* HAVE_INET6 */
474#ifdef AF_UNIX 478#ifdef AF_UNIX
475 case AF_UNIX: 479 case AF_UNIX:
476 daemon->listen_port = 0; /* special value for UNIX domain sockets */ 480 daemon->listen_port = 0; /* special value for UNIX domain sockets */
477 break; 481 break;
478#endif 482#endif
479 default: 483 default:
480#ifdef HAVE_MESSAGES 484#ifdef HAVE_MESSAGES
481 MHD_DLOG (daemon, 485 MHD_DLOG (daemon,
482 MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF, 486 MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF,
483 _("Unknown address family!\n")); 487 _ ("Unknown address family!\n"));
484#endif 488#endif
485 daemon->listen_port = 0; /* ugh */ 489 daemon->listen_port = 0; /* ugh */
486 break; 490 break;
487 } 491 }
488} 492}
489 493
490 494
@@ -501,7 +505,7 @@ setup_epoll_fd (struct MHD_Daemon *daemon)
501 int fd; 505 int fd;
502 506
503#ifndef HAVE_MESSAGES 507#ifndef HAVE_MESSAGES
504 (void)daemon; /* Mute compiler warning. */ 508 (void) daemon; /* Mute compiler warning. */
505#endif /* ! HAVE_MESSAGES */ 509#endif /* ! HAVE_MESSAGES */
506 510
507#ifdef USE_EPOLL_CREATE1 511#ifdef USE_EPOLL_CREATE1
@@ -510,24 +514,24 @@ setup_epoll_fd (struct MHD_Daemon *daemon)
510 fd = epoll_create (MAX_EVENTS); 514 fd = epoll_create (MAX_EVENTS);
511#endif /* ! USE_EPOLL_CREATE1 */ 515#endif /* ! USE_EPOLL_CREATE1 */
512 if (MHD_INVALID_SOCKET == fd) 516 if (MHD_INVALID_SOCKET == fd)
513 { 517 {
514#ifdef HAVE_MESSAGES 518#ifdef HAVE_MESSAGES
515 MHD_DLOG (daemon, 519 MHD_DLOG (daemon,
516 MHD_SC_EPOLL_CTL_CREATE_FAILED, 520 MHD_SC_EPOLL_CTL_CREATE_FAILED,
517 _("Call to epoll_create1 failed: %s\n"), 521 _ ("Call to epoll_create1 failed: %s\n"),
518 MHD_socket_last_strerr_ ()); 522 MHD_socket_last_strerr_ ());
519#endif 523#endif
520 return MHD_INVALID_SOCKET; 524 return MHD_INVALID_SOCKET;
521 } 525 }
522#if !defined(USE_EPOLL_CREATE1) 526#if ! defined(USE_EPOLL_CREATE1)
523 if (! MHD_socket_noninheritable_ (fd)) 527 if (! MHD_socket_noninheritable_ (fd))
524 { 528 {
525#ifdef HAVE_MESSAGES 529#ifdef HAVE_MESSAGES
526 MHD_DLOG (daemon, 530 MHD_DLOG (daemon,
527 MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED, 531 MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED,
528 _("Failed to set noninheritable mode on epoll FD.\n")); 532 _ ("Failed to set noninheritable mode on epoll FD.\n"));
529#endif 533#endif
530 } 534 }
531#endif /* ! USE_EPOLL_CREATE1 */ 535#endif /* ! USE_EPOLL_CREATE1 */
532 return fd; 536 return fd;
533} 537}
@@ -554,11 +558,11 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
554 return MHD_SC_EPOLL_CTL_CREATE_FAILED; 558 return MHD_SC_EPOLL_CTL_CREATE_FAILED;
555#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 559#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
556 if (! daemon->disallow_upgrade) 560 if (! daemon->disallow_upgrade)
557 { 561 {
558 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon); 562 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
559 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd) 563 if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd)
560 return MHD_SC_EPOLL_CTL_CREATE_FAILED; 564 return MHD_SC_EPOLL_CTL_CREATE_FAILED;
561 } 565 }
562#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 566#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
563 if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_socket)) || 567 if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_socket)) ||
564 (daemon->was_quiesced) ) 568 (daemon->was_quiesced) )
@@ -566,37 +570,37 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
566 event.events = EPOLLIN; 570 event.events = EPOLLIN;
567 event.data.ptr = daemon; 571 event.data.ptr = daemon;
568 if (0 != epoll_ctl (daemon->epoll_fd, 572 if (0 != epoll_ctl (daemon->epoll_fd,
569 EPOLL_CTL_ADD, 573 EPOLL_CTL_ADD,
570 ls, 574 ls,
571 &event)) 575 &event))
572 { 576 {
573#ifdef HAVE_MESSAGES 577#ifdef HAVE_MESSAGES
574 MHD_DLOG (daemon, 578 MHD_DLOG (daemon,
575 MHD_SC_EPOLL_CTL_ADD_FAILED, 579 MHD_SC_EPOLL_CTL_ADD_FAILED,
576 _("Call to epoll_ctl failed: %s\n"), 580 _ ("Call to epoll_ctl failed: %s\n"),
577 MHD_socket_last_strerr_ ()); 581 MHD_socket_last_strerr_ ());
578#endif 582#endif
579 return MHD_SC_EPOLL_CTL_ADD_FAILED; 583 return MHD_SC_EPOLL_CTL_ADD_FAILED;
580 } 584 }
581 daemon->listen_socket_in_epoll = true; 585 daemon->listen_socket_in_epoll = true;
582 if (MHD_ITC_IS_VALID_(daemon->itc)) 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))
583 { 594 {
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 595#ifdef HAVE_MESSAGES
592 MHD_DLOG (daemon, 596 MHD_DLOG (daemon,
593 MHD_SC_EPOLL_CTL_ADD_FAILED, 597 MHD_SC_EPOLL_CTL_ADD_FAILED,
594 _("Call to epoll_ctl failed: %s\n"), 598 _ ("Call to epoll_ctl failed: %s\n"),
595 MHD_socket_last_strerr_ ()); 599 MHD_socket_last_strerr_ ());
596#endif 600#endif
597 return MHD_SC_EPOLL_CTL_ADD_FAILED; 601 return MHD_SC_EPOLL_CTL_ADD_FAILED;
598 }
599 } 602 }
603 }
600 return MHD_SC_OK; 604 return MHD_SC_OK;
601} 605}
602#endif 606#endif
@@ -616,35 +620,35 @@ MHD_polling_thread (void *cls)
616 620
617 MHD_thread_init_ (&daemon->pid); 621 MHD_thread_init_ (&daemon->pid);
618 while (! daemon->shutdown) 622 while (! daemon->shutdown)
623 {
624 switch (daemon->event_loop_syscall)
619 { 625 {
620 switch (daemon->event_loop_syscall) 626 case MHD_ELS_AUTO:
621 { 627 MHD_PANIC ("MHD_ELS_AUTO should have been mapped to preferred style");
622 case MHD_ELS_AUTO: 628 break;
623 MHD_PANIC ("MHD_ELS_AUTO should have been mapped to preferred style"); 629 case MHD_ELS_SELECT:
624 break; 630 MHD_daemon_select_ (daemon,
625 case MHD_ELS_SELECT: 631 MHD_YES);
626 MHD_daemon_select_ (daemon, 632 break;
627 MHD_YES); 633 case MHD_ELS_POLL:
628 break;
629 case MHD_ELS_POLL:
630#if HAVE_POLL 634#if HAVE_POLL
631 MHD_daemon_poll_ (daemon, 635 MHD_daemon_poll_ (daemon,
632 MHD_YES); 636 MHD_YES);
633#else 637#else
634 MHD_PANIC ("MHD_ELS_POLL not supported, should have failed earlier"); 638 MHD_PANIC ("MHD_ELS_POLL not supported, should have failed earlier");
635#endif 639#endif
636 break; 640 break;
637 case MHD_ELS_EPOLL: 641 case MHD_ELS_EPOLL:
638#ifdef EPOLL_SUPPORT 642#ifdef EPOLL_SUPPORT
639 MHD_daemon_epoll_ (daemon, 643 MHD_daemon_epoll_ (daemon,
640 MHD_YES); 644 MHD_YES);
641#else 645#else
642 MHD_PANIC ("MHD_ELS_EPOLL not supported, should have failed earlier"); 646 MHD_PANIC ("MHD_ELS_EPOLL not supported, should have failed earlier");
643#endif 647#endif
644 break; 648 break;
645 }
646 MHD_connection_cleanup_ (daemon);
647 } 649 }
650 MHD_connection_cleanup_ (daemon);
651 }
648 /* Resume any pending for resume connections, join 652 /* Resume any pending for resume connections, join
649 * all connection's threads (if any) and finally cleanup 653 * all connection's threads (if any) and finally cleanup
650 * everything. */ 654 * everything. */
@@ -652,7 +656,7 @@ MHD_polling_thread (void *cls)
652 MHD_resume_suspended_connections_ (daemon); 656 MHD_resume_suspended_connections_ (daemon);
653 MHD_daemon_close_all_connections_ (daemon); 657 MHD_daemon_close_all_connections_ (daemon);
654 658
655 return (MHD_THRD_RTRN_TYPE_)0; 659 return (MHD_THRD_RTRN_TYPE_) 0;
656} 660}
657 661
658 662
@@ -669,114 +673,116 @@ setup_thread_pool (struct MHD_Daemon *daemon)
669 * due to integer division). Also keep track of how many 673 * due to integer division). Also keep track of how many
670 * connections are leftover after an equal split. */ 674 * connections are leftover after an equal split. */
671 unsigned int conns_per_thread = daemon->global_connection_limit 675 unsigned int conns_per_thread = daemon->global_connection_limit
672 / daemon->threading_mode; 676 / daemon->threading_mode;
673 unsigned int leftover_conns = daemon->global_connection_limit 677 unsigned int leftover_conns = daemon->global_connection_limit
674 % daemon->threading_mode; 678 % daemon->threading_mode;
675 int i; 679 int i;
676 enum MHD_StatusCode sc; 680 enum MHD_StatusCode sc;
677 681
678 /* Allocate memory for pooled objects */ 682 /* Allocate memory for pooled objects */
679 daemon->worker_pool = MHD_calloc_ (daemon->threading_mode, 683 daemon->worker_pool = MHD_calloc_ (daemon->threading_mode,
680 sizeof (struct MHD_Daemon)); 684 sizeof (struct MHD_Daemon));
681 if (NULL == daemon->worker_pool) 685 if (NULL == daemon->worker_pool)
682 return MHD_SC_THREAD_POOL_MALLOC_FAILURE; 686 return MHD_SC_THREAD_POOL_MALLOC_FAILURE;
683 687
684 /* Start the workers in the pool */ 688 /* Start the workers in the pool */
685 for (i = 0; i < daemon->threading_mode; i++) 689 for (i = 0; i < daemon->threading_mode; i++)
690 {
691 /* Create copy of the Daemon object for each worker */
692 struct MHD_Daemon *d = &daemon->worker_pool[i];
693
694 memcpy (d,
695 daemon,
696 sizeof (struct MHD_Daemon));
697 /* Adjust pooling params for worker daemons; note that memcpy()
698 has already copied MHD_USE_INTERNAL_POLLING_THREAD thread mode into
699 the worker threads. */
700 d->master = daemon;
701 d->worker_pool_size = 0;
702 d->worker_pool = NULL;
703 /* Divide available connections evenly amongst the threads.
704 * Thread indexes in [0, leftover_conns) each get one of the
705 * leftover connections. */
706 d->global_connection_limit = conns_per_thread;
707 if (((unsigned int) i) < leftover_conns)
708 ++d->global_connection_limit;
709
710 if (! daemon->disable_itc)
686 { 711 {
687 /* Create copy of the Daemon object for each worker */ 712 if (! MHD_itc_init_ (d->itc))
688 struct MHD_Daemon *d = &daemon->worker_pool[i]; 713 {
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)
704 ++d->global_connection_limit;
705
706 if (! daemon->disable_itc)
707 {
708 if (! MHD_itc_init_ (d->itc))
709 {
710#ifdef HAVE_MESSAGES 714#ifdef HAVE_MESSAGES
711 MHD_DLOG (daemon, 715 MHD_DLOG (daemon,
712 MHD_SC_ITC_INITIALIZATION_FAILED, 716 MHD_SC_ITC_INITIALIZATION_FAILED,
713 _("Failed to create worker inter-thread communication channel: %s\n"), 717 _ (
714 MHD_itc_last_strerror_() ); 718 "Failed to create worker inter-thread communication channel: %s\n"),
715#endif 719 MHD_itc_last_strerror_ () );
716 sc = MHD_SC_ITC_INITIALIZATION_FAILED; 720#endif
717 goto thread_failed; 721 sc = MHD_SC_ITC_INITIALIZATION_FAILED;
718 } 722 goto thread_failed;
719 if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) && 723 }
720 (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (d->itc), 724 if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
721 NULL)) ) 725 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (d->itc),
722 { 726 NULL)) )
727 {
723#ifdef HAVE_MESSAGES 728#ifdef HAVE_MESSAGES
724 MHD_DLOG (daemon, 729 MHD_DLOG (daemon,
725 MHD_SC_ITC_DESCRIPTOR_TOO_LARGE, 730 MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
726 _("File descriptor for inter-thread communication channel exceeds maximum value\n")); 731 _ (
727#endif 732 "File descriptor for inter-thread communication channel exceeds maximum value\n"));
728 MHD_itc_destroy_chk_ (d->itc); 733#endif
729 sc = MHD_SC_ITC_DESCRIPTOR_TOO_LARGE; 734 MHD_itc_destroy_chk_ (d->itc);
730 goto thread_failed; 735 sc = MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
731 } 736 goto thread_failed;
732 } 737 }
733 else 738 }
734 { 739 else
735 MHD_itc_set_invalid_ (d->itc); 740 {
736 } 741 MHD_itc_set_invalid_ (d->itc);
742 }
737 743
738#ifdef EPOLL_SUPPORT 744#ifdef EPOLL_SUPPORT
739 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && 745 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
740 (MHD_SC_OK != (sc = setup_epoll_to_listen (d))) ) 746 (MHD_SC_OK != (sc = setup_epoll_to_listen (d))) )
741 goto thread_failed; 747 goto thread_failed;
742#endif 748#endif
743 749
744 /* Must init cleanup connection mutex for each worker */ 750 /* Must init cleanup connection mutex for each worker */
745 if (! MHD_mutex_init_ (&d->cleanup_connection_mutex)) 751 if (! MHD_mutex_init_ (&d->cleanup_connection_mutex))
746 { 752 {
747#ifdef HAVE_MESSAGES 753#ifdef HAVE_MESSAGES
748 MHD_DLOG (daemon, 754 MHD_DLOG (daemon,
749 MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE, 755 MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE,
750 _("MHD failed to initialize cleanup connection mutex\n")); 756 _ ("MHD failed to initialize cleanup connection mutex\n"));
751#endif 757#endif
752 if (! daemon->disable_itc) 758 if (! daemon->disable_itc)
753 MHD_itc_destroy_chk_ (d->itc); 759 MHD_itc_destroy_chk_ (d->itc);
754 sc = MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE; 760 sc = MHD_SC_THREAD_POOL_CREATE_MUTEX_FAILURE;
755 goto thread_failed; 761 goto thread_failed;
756 } 762 }
757 763
758 /* Spawn the worker thread */ 764 /* Spawn the worker thread */
759 if (! MHD_create_named_thread_ (&d->pid, 765 if (! MHD_create_named_thread_ (&d->pid,
760 "MHD-worker", 766 "MHD-worker",
761 daemon->thread_stack_limit_b, 767 daemon->thread_stack_limit_b,
762 &MHD_polling_thread, 768 &MHD_polling_thread,
763 d)) 769 d))
764 { 770 {
765#ifdef HAVE_MESSAGES 771#ifdef HAVE_MESSAGES
766 MHD_DLOG (daemon, 772 MHD_DLOG (daemon,
767 MHD_SC_THREAD_POOL_LAUNCH_FAILURE, 773 MHD_SC_THREAD_POOL_LAUNCH_FAILURE,
768 _("Failed to create pool thread: %s\n"), 774 _ ("Failed to create pool thread: %s\n"),
769 MHD_strerror_ (errno)); 775 MHD_strerror_ (errno));
770#endif 776#endif
771 /* Free memory for this worker; cleanup below handles 777 /* Free memory for this worker; cleanup below handles
772 * all previously-created workers. */ 778 * all previously-created workers. */
773 if (! daemon->disable_itc) 779 if (! daemon->disable_itc)
774 MHD_itc_destroy_chk_ (d->itc); 780 MHD_itc_destroy_chk_ (d->itc);
775 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex); 781 MHD_mutex_destroy_chk_ (&d->cleanup_connection_mutex);
776 sc = MHD_SC_THREAD_POOL_LAUNCH_FAILURE; 782 sc = MHD_SC_THREAD_POOL_LAUNCH_FAILURE;
777 goto thread_failed; 783 goto thread_failed;
778 } 784 }
779 } /* end for() */ 785 } /* end for() */
780 return MHD_SC_OK; 786 return MHD_SC_OK;
781 787
782thread_failed: 788thread_failed:
@@ -785,14 +791,14 @@ thread_failed:
785 assumes a 0-sized thread pool means we had been in the default 791 assumes a 0-sized thread pool means we had been in the default
786 MHD_USE_INTERNAL_POLLING_THREAD mode. */ 792 MHD_USE_INTERNAL_POLLING_THREAD mode. */
787 if (0 == i) 793 if (0 == i)
794 {
795 if (NULL != daemon->worker_pool)
788 { 796 {
789 if (NULL != daemon->worker_pool) 797 free (daemon->worker_pool);
790 { 798 daemon->worker_pool = NULL;
791 free (daemon->worker_pool);
792 daemon->worker_pool = NULL;
793 }
794 return MHD_SC_THREAD_LAUNCH_FAILURE;
795 } 799 }
800 return MHD_SC_THREAD_LAUNCH_FAILURE;
801 }
796 /* Shutdown worker threads we've already created. Pretend 802 /* Shutdown worker threads we've already created. Pretend
797 as though we had fully initialized our daemon, but 803 as though we had fully initialized our daemon, but
798 with a smaller number of threads than had been 804 with a smaller number of threads than had been
@@ -817,63 +823,65 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
817 enum MHD_StatusCode sc; 823 enum MHD_StatusCode sc;
818 824
819 if (MHD_ELS_AUTO == daemon->event_loop_syscall) 825 if (MHD_ELS_AUTO == daemon->event_loop_syscall)
820 { 826 {
821#if EPOLL_SUPPORT 827#if EPOLL_SUPPORT
822 /* We do not support thread-per-connection in combination 828 /* We do not support thread-per-connection in combination
823 with epoll, so use poll in this case, otherwise prefer 829 with epoll, so use poll in this case, otherwise prefer
824 epoll. */ 830 epoll. */
825 if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) 831 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; 832 daemon->event_loop_syscall = MHD_ELS_POLL;
833 else
834 daemon->event_loop_syscall = MHD_ELS_EPOLL;
835#elif HAVE_POLL
836 daemon->event_loop_syscall = MHD_ELS_POLL;
831#else 837#else
832 daemon->event_loop_syscall = MHD_ELS_SELECT; 838 daemon->event_loop_syscall = MHD_ELS_SELECT;
833#endif 839#endif
834 } 840 }
835 841
836#ifdef EPOLL_SUPPORT 842#ifdef EPOLL_SUPPORT
837 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && 843 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
838 (0 == daemon->worker_pool_size) && 844 (0 == daemon->worker_pool_size) &&
839 (MHD_INVALID_SOCKET != daemon->listen_socket) && 845 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
840 (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) ) 846 (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) )
841 { 847 {
842#ifdef HAVE_MESSAGES 848#ifdef HAVE_MESSAGES
843 MHD_DLOG (daemon, 849 MHD_DLOG (daemon,
844 MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID, 850 MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID,
845 _("Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n")); 851 _ (
852 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
846#endif 853#endif
847 return MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID; 854 return MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID;
848 } 855 }
849#endif 856#endif
850 857
851 /* Setup ITC */ 858 /* Setup ITC */
852 if ( (! daemon->disable_itc) && 859 if ( (! daemon->disable_itc) &&
853 (0 == daemon->worker_pool_size) ) 860 (0 == daemon->worker_pool_size) )
861 {
862 if (! MHD_itc_init_ (daemon->itc))
854 { 863 {
855 if (! MHD_itc_init_ (daemon->itc))
856 {
857#ifdef HAVE_MESSAGES 864#ifdef HAVE_MESSAGES
858 MHD_DLOG (daemon, 865 MHD_DLOG (daemon,
859 MHD_SC_ITC_INITIALIZATION_FAILED, 866 MHD_SC_ITC_INITIALIZATION_FAILED,
860 _("Failed to create inter-thread communication channel: %s\n"), 867 _ ("Failed to create inter-thread communication channel: %s\n"),
861 MHD_itc_last_strerror_ ()); 868 MHD_itc_last_strerror_ ());
862#endif 869#endif
863 return MHD_SC_ITC_INITIALIZATION_FAILED; 870 return MHD_SC_ITC_INITIALIZATION_FAILED;
864 } 871 }
865 if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) && 872 if ( (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
866 (! MHD_SCKT_FD_FITS_FDSET_(MHD_itc_r_fd_ (daemon->itc), 873 (! MHD_SCKT_FD_FITS_FDSET_ (MHD_itc_r_fd_ (daemon->itc),
867 NULL)) ) 874 NULL)) )
868 { 875 {
869#ifdef HAVE_MESSAGES 876#ifdef HAVE_MESSAGES
870 MHD_DLOG (daemon, 877 MHD_DLOG (daemon,
871 MHD_SC_ITC_DESCRIPTOR_TOO_LARGE, 878 MHD_SC_ITC_DESCRIPTOR_TOO_LARGE,
872 _("File descriptor for inter-thread communication channel exceeds maximum value\n")); 879 _ (
880 "File descriptor for inter-thread communication channel exceeds maximum value\n"));
873#endif 881#endif
874 return MHD_SC_ITC_DESCRIPTOR_TOO_LARGE; 882 return MHD_SC_ITC_DESCRIPTOR_TOO_LARGE;
875 }
876 } 883 }
884 }
877 885
878 if (MHD_SC_OK != (sc = open_listen_socket (daemon))) 886 if (MHD_SC_OK != (sc = open_listen_socket (daemon)))
879 return sc; 887 return sc;
@@ -881,39 +889,39 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
881 /* Check listen socket is in range (if we are limited) */ 889 /* Check listen socket is in range (if we are limited) */
882 if ( (MHD_INVALID_SOCKET != daemon->listen_socket) && 890 if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
883 (MHD_ELS_SELECT == daemon->event_loop_syscall) && 891 (MHD_ELS_SELECT == daemon->event_loop_syscall) &&
884 (! MHD_SCKT_FD_FITS_FDSET_(daemon->listen_socket, 892 (! MHD_SCKT_FD_FITS_FDSET_ (daemon->listen_socket,
885 NULL)) ) 893 NULL)) )
886 { 894 {
887#ifdef HAVE_MESSAGES 895#ifdef HAVE_MESSAGES
888 MHD_DLOG (daemon, 896 MHD_DLOG (daemon,
889 MHD_SC_LISTEN_SOCKET_TOO_LARGE, 897 MHD_SC_LISTEN_SOCKET_TOO_LARGE,
890 _("Socket descriptor larger than FD_SETSIZE: %d > %d\n"), 898 _ ("Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
891 daemon->listen_socket, 899 daemon->listen_socket,
892 FD_SETSIZE); 900 FD_SETSIZE);
893#endif 901#endif
894 return MHD_SC_LISTEN_SOCKET_TOO_LARGE; 902 return MHD_SC_LISTEN_SOCKET_TOO_LARGE;
895 } 903 }
896 904
897 /* set listen socket to non-blocking */ 905 /* set listen socket to non-blocking */
898 if ( (MHD_INVALID_SOCKET != daemon->listen_socket) && 906 if ( (MHD_INVALID_SOCKET != daemon->listen_socket) &&
899 (! MHD_socket_nonblocking_ (daemon->listen_socket)) ) 907 (! MHD_socket_nonblocking_ (daemon->listen_socket)) )
900 { 908 {
901#ifdef HAVE_MESSAGES 909#ifdef HAVE_MESSAGES
902 MHD_DLOG (daemon, 910 MHD_DLOG (daemon,
903 MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE, 911 MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE,
904 _("Failed to set nonblocking mode on listening socket: %s\n"), 912 _ ("Failed to set nonblocking mode on listening socket: %s\n"),
905 MHD_socket_last_strerr_()); 913 MHD_socket_last_strerr_ ());
906#endif 914#endif
907 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) || 915 if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) ||
908 (daemon->worker_pool_size > 0) ) 916 (daemon->worker_pool_size > 0) )
909 { 917 {
910 /* Accept must be non-blocking. Multiple children may wake 918 /* Accept must be non-blocking. Multiple children may wake
911 * up to handle a new connection, but only one will win the 919 * up to handle a new connection, but only one will win the
912 * race. The others must immediately return. As this is 920 * race. The others must immediately return. As this is
913 * not possible, we must fail hard here. */ 921 * not possible, we must fail hard here. */
914 return MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE; 922 return MHD_SC_LISTEN_SOCKET_NONBLOCKING_FAILURE;
915 }
916 } 923 }
924 }
917 925
918#ifdef EPOLL_SUPPORT 926#ifdef EPOLL_SUPPORT
919 /* Setup epoll */ 927 /* Setup epoll */
@@ -928,30 +936,31 @@ MHD_daemon_start (struct MHD_Daemon *daemon)
928 external event loop and do have a listen socket) */ 936 external event loop and do have a listen socket) */
929 /* FIXME: why no worker thread if we have no listen socket? */ 937 /* FIXME: why no worker thread if we have no listen socket? */
930 if ( ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) || 938 if ( ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) ||
931 (1 == daemon->threading_mode) ) && 939 (1 == daemon->threading_mode) ) &&
932 (MHD_INVALID_SOCKET != daemon->listen_socket) && 940 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
933 (! MHD_create_named_thread_ (&daemon->pid, 941 (! MHD_create_named_thread_ (&daemon->pid,
934 (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) 942 (MHD_TM_THREAD_PER_CONNECTION ==
935 ? "MHD-listen" 943 daemon->threading_mode)
936 : "MHD-single", 944 ? "MHD-listen"
937 daemon->thread_stack_limit_b, 945 : "MHD-single",
938 &MHD_polling_thread, 946 daemon->thread_stack_limit_b,
939 daemon) ) ) 947 &MHD_polling_thread,
940 { 948 daemon) ) )
949 {
941#ifdef HAVE_MESSAGES 950#ifdef HAVE_MESSAGES
942 MHD_DLOG (daemon, 951 MHD_DLOG (daemon,
943 MHD_SC_THREAD_MAIN_LAUNCH_FAILURE, 952 MHD_SC_THREAD_MAIN_LAUNCH_FAILURE,
944 _("Failed to create listen thread: %s\n"), 953 _ ("Failed to create listen thread: %s\n"),
945 MHD_strerror_ (errno)); 954 MHD_strerror_ (errno));
946#endif 955#endif
947 return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE; 956 return MHD_SC_THREAD_MAIN_LAUNCH_FAILURE;
948 } 957 }
949 958
950 /* Setup worker threads */ 959 /* Setup worker threads */
951 /* FIXME: why no thread pool if we have no listen socket? */ 960 /* FIXME: why no thread pool if we have no listen socket? */
952 if ( (1 < daemon->threading_mode) && 961 if ( (1 < daemon->threading_mode) &&
953 (MHD_INVALID_SOCKET != daemon->listen_socket) && 962 (MHD_INVALID_SOCKET != daemon->listen_socket) &&
954 (MHD_SC_OK != (sc = setup_thread_pool (daemon))) ) 963 (MHD_SC_OK != (sc = setup_thread_pool (daemon))) )
955 return sc; 964 return sc;
956 965
957 /* make sure we know our listen port (if any) */ 966 /* make sure we know our listen port (if any) */