diff options
Diffstat (limited to 'src/lib/daemon_start.c')
-rw-r--r-- | src/lib/daemon_start.c | 1013 |
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: | 231 | try_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 | ||
782 | thread_failed: | 788 | thread_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) */ |