aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--configure.ac6
-rw-r--r--doc/libmicrohttpd.texi2
-rw-r--r--po/libmicrohttpd.pot297
-rw-r--r--src/include/microhttpd.h2
-rw-r--r--src/microhttpd/.gitignore2
-rw-r--r--src/microhttpd/Makefile.am34
-rw-r--r--src/microhttpd/connection.c30
-rw-r--r--src/microhttpd/daemon.c310
-rw-r--r--src/microhttpd/response.c80
-rw-r--r--src/microhttpd/test_upgrade_large.c1386
11 files changed, 1811 insertions, 361 deletions
diff --git a/ChangeLog b/ChangeLog
index 6a057b73..92161c6f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
1Thu 01 Aug 2019 01:23:36 PM CEST
2 Releasing libmicrohttpd 0.9.66. -CG
3
4Thu 01 Aug 2019 12:53:49 AM CEST
5 Fix issue with discarding unhandled upload data discovered
6 by Florian Dold. -CG
7
8Mon 29 Jul 2019 08:01:50 PM CEST
9 Fix hanging situation with large transmission over upgraded
10 (i.e. Web socket) connection with epoll() and HTTPS enabled
11 (as reported by Viet on the mailinglist). -CG
12
13Thu 25 Jul 2019 02:40:12 PM CEST
14 Fixing regression introduced in cc5032b85 (bit mask matching
15 of the header kinds in MHD_lookup_connection_value()), as
16 reported by Jose Bollo on the mailinglist. -CG/JB
17
1Tue Jul 16 19:56:14 CEST 2019 18Tue Jul 16 19:56:14 CEST 2019
2 Add MHD_OPTION_HTTPS_CERT_CALLBACK2 to allow OCSP stapling 19 Add MHD_OPTION_HTTPS_CERT_CALLBACK2 to allow OCSP stapling
3 and MHD_FEATURE_HTTPS_CERT_CALLBACK2 to check for. -TR 20 and MHD_FEATURE_HTTPS_CERT_CALLBACK2 to check for. -TR
4 21
5Fri Jul 05 2019 22:30:40 MSK 22Fri Jul 05 2019 22:30:40 MSK
6 Releasing libmicrohttpd 0.9.65. -EG 23 Releasing libmicrohttpd 0.9.65. -EG
@@ -102,7 +119,7 @@ Sun Apr 21 16:40:00 MSK 2019
102 119
103Fri Apr 19 23:00:00 MSK 2019 120Fri Apr 19 23:00:00 MSK 2019
104 Rewritten SHA-256 calculations from scratch to avoid changing LGPL version; 121 Rewritten SHA-256 calculations from scratch to avoid changing LGPL version;
105 Added usage of GCC/Clang built-ins for bytes swap to significantly improve 122 Added usage of GCC/Clang built-ins for bytes swap to significantly improve
106 speed of MD5 and SHA-256 calculation on platforms with known endianness. 123 speed of MD5 and SHA-256 calculation on platforms with known endianness.
107 Added test for SHA-256 calculations. -EG 124 Added test for SHA-256 calculations. -EG
108 125
diff --git a/configure.ac b/configure.ac
index 8e4f4a9b..1a0870b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,15 +22,15 @@
22# 22#
23AC_PREREQ([2.64]) 23AC_PREREQ([2.64])
24LT_PREREQ([2.4.0]) 24LT_PREREQ([2.4.0])
25AC_INIT([GNU Libmicrohttpd],[0.9.65],[libmicrohttpd@gnu.org]) 25AC_INIT([GNU Libmicrohttpd],[0.9.66],[libmicrohttpd@gnu.org])
26AC_CONFIG_AUX_DIR([build-aux]) 26AC_CONFIG_AUX_DIR([build-aux])
27AM_INIT_AUTOMAKE([silent-rules] [subdir-objects]) 27AM_INIT_AUTOMAKE([silent-rules] [subdir-objects])
28AC_CONFIG_HEADERS([MHD_config.h]) 28AC_CONFIG_HEADERS([MHD_config.h])
29AC_CONFIG_MACRO_DIR([m4]) 29AC_CONFIG_MACRO_DIR([m4])
30 30
31LIB_VERSION_CURRENT=64 31LIB_VERSION_CURRENT=65
32LIB_VERSION_REVISION=0 32LIB_VERSION_REVISION=0
33LIB_VERSION_AGE=52 33LIB_VERSION_AGE=53
34AC_SUBST(LIB_VERSION_CURRENT) 34AC_SUBST(LIB_VERSION_CURRENT)
35AC_SUBST(LIB_VERSION_REVISION) 35AC_SUBST(LIB_VERSION_REVISION)
36AC_SUBST(LIB_VERSION_AGE) 36AC_SUBST(LIB_VERSION_AGE)
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi
index 6f34d799..4424337f 100644
--- a/doc/libmicrohttpd.texi
+++ b/doc/libmicrohttpd.texi
@@ -12,7 +12,7 @@ This manual is for GNU libmicrohttpd
12(version @value{VERSION}, @value{UPDATED}), a library for embedding 12(version @value{VERSION}, @value{UPDATED}), a library for embedding
13an HTTP(S) server into C applications. 13an HTTP(S) server into C applications.
14 14
15Copyright @copyright{} 2007--2017 Christian Grothoff 15Copyright @copyright{} 2007--2019 Christian Grothoff
16 16
17@quotation 17@quotation
18Permission is granted to copy, distribute and/or modify this document 18Permission is granted to copy, distribute and/or modify this document
diff --git a/po/libmicrohttpd.pot b/po/libmicrohttpd.pot
index feb037c6..0f089638 100644
--- a/po/libmicrohttpd.pot
+++ b/po/libmicrohttpd.pot
@@ -6,9 +6,9 @@
6#, fuzzy 6#, fuzzy
7msgid "" 7msgid ""
8msgstr "" 8msgstr ""
9"Project-Id-Version: GNU libmicrohttpd 0.9.65\n" 9"Project-Id-Version: GNU libmicrohttpd 0.9.66\n"
10"Report-Msgid-Bugs-To: libmicrohttpd@gnu.org\n" 10"Report-Msgid-Bugs-To: libmicrohttpd@gnu.org\n"
11"POT-Creation-Date: 2019-07-05 22:27+0300\n" 11"POT-Creation-Date: 2019-08-01 13:26+0200\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n" 14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -104,513 +104,518 @@ msgstr ""
104msgid "Previously-added IP address had counter of zero\n" 104msgid "Previously-added IP address had counter of zero\n"
105msgstr "" 105msgstr ""
106 106
107#: src/microhttpd/daemon.c:614 107#: src/microhttpd/daemon.c:622
108msgid "" 108msgid ""
109"Failed to setup x509 certificate/key: pre 3.X.X version of GnuTLS does not " 109"Failed to setup x509 certificate/key: pre 3.X.X version of GnuTLS does not "
110"support setting key password" 110"support setting key password"
111msgstr "" 111msgstr ""
112 112
113#: src/microhttpd/daemon.c:668 113#: src/microhttpd/daemon.c:680
114#, c-format 114#, c-format
115msgid "Error: invalid credentials type %d specified.\n" 115msgid "Error: invalid credentials type %d specified.\n"
116msgstr "" 116msgstr ""
117 117
118#: src/microhttpd/daemon.c:1067 118#: src/microhttpd/daemon.c:1079
119#, c-format 119#, c-format
120msgid "Maximum socket in select set: %d\n" 120msgid "Maximum socket in select set: %d\n"
121msgstr "" 121msgstr ""
122 122
123#: src/microhttpd/daemon.c:1128 123#: src/microhttpd/daemon.c:1140
124msgid "" 124msgid ""
125"MHD_get_fdset2() called with except_fd_set set to NULL. Such behavior is " 125"MHD_get_fdset2() called with except_fd_set set to NULL. Such behavior is "
126"unsupported.\n" 126"unsupported.\n"
127msgstr "" 127msgstr ""
128 128
129#: src/microhttpd/daemon.c:1334 src/microhttpd/daemon.c:6573 129#: src/microhttpd/daemon.c:1346 src/microhttpd/daemon.c:6611
130msgid "" 130msgid ""
131"Initiated daemon shutdown while \"upgraded\" connection was not closed.\n" 131"Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"
132msgstr "" 132msgstr ""
133 133
134#: src/microhttpd/daemon.c:1348 src/microhttpd/daemon.c:1583 134#: src/microhttpd/daemon.c:1360 src/microhttpd/daemon.c:1595
135msgid "Failed to forward to application " 135msgid "Failed to forward to application "
136msgstr "" 136msgstr ""
137 137
138#: src/microhttpd/daemon.c:1515 src/microhttpd/daemon.c:1637 138#: src/microhttpd/daemon.c:1527 src/microhttpd/daemon.c:1649
139msgid "Failed to forward to remote client " 139msgid "Failed to forward to remote client "
140msgstr "" 140msgstr ""
141 141
142#: src/microhttpd/daemon.c:1702 142#: src/microhttpd/daemon.c:1714
143msgid "Error preparing select\n" 143msgid "Error preparing select\n"
144msgstr "" 144msgstr ""
145 145
146#: src/microhttpd/daemon.c:1736 src/microhttpd/daemon.c:1888 146#: src/microhttpd/daemon.c:1748 src/microhttpd/daemon.c:1900
147#: src/microhttpd/daemon.c:2032 147#: src/microhttpd/daemon.c:2044
148#, c-format 148#, c-format
149msgid "Error during select (%d): `%s'\n" 149msgid "Error during select (%d): `%s'\n"
150msgstr "" 150msgstr ""
151 151
152#: src/microhttpd/daemon.c:1785 src/microhttpd/daemon.c:1909 152#: src/microhttpd/daemon.c:1797 src/microhttpd/daemon.c:1921
153#: src/microhttpd/daemon.c:2101 153#: src/microhttpd/daemon.c:2113
154#, c-format 154#, c-format
155msgid "Error during poll: `%s'\n" 155msgid "Error during poll: `%s'\n"
156msgstr "" 156msgstr ""
157 157
158#: src/microhttpd/daemon.c:1872 src/microhttpd/daemon.c:2014 158#: src/microhttpd/daemon.c:1884 src/microhttpd/daemon.c:2026
159msgid "Failed to add FD to fd_set\n" 159msgid "Failed to add FD to fd_set\n"
160msgstr "" 160msgstr ""
161 161
162#: src/microhttpd/daemon.c:2153 162#: src/microhttpd/daemon.c:2165
163msgid "Processing thread terminating. Closing connection\n" 163msgid "Processing thread terminating. Closing connection\n"
164msgstr "" 164msgstr ""
165 165
166#: src/microhttpd/daemon.c:2182 166#: src/microhttpd/daemon.c:2194
167msgid "" 167msgid ""
168"Failed to signal thread termination via inter-thread communication channel." 168"Failed to signal thread termination via inter-thread communication channel."
169msgstr "" 169msgstr ""
170 170
171#: src/microhttpd/daemon.c:2253 171#: src/microhttpd/daemon.c:2265
172msgid "Internal server error. This should be impossible.\n" 172msgid "Internal server error. This should be impossible.\n"
173msgstr "" 173msgstr ""
174 174
175#: src/microhttpd/daemon.c:2263 src/microhttpd/daemon.c:2300 175#: src/microhttpd/daemon.c:2275 src/microhttpd/daemon.c:2312
176msgid "PSK not supported by this server.\n" 176msgid "PSK not supported by this server.\n"
177msgstr "" 177msgstr ""
178 178
179#: src/microhttpd/daemon.c:2277 179#: src/microhttpd/daemon.c:2289
180msgid "PSK authentication failed: gnutls_malloc failed to allocate memory\n" 180msgid "PSK authentication failed: gnutls_malloc failed to allocate memory\n"
181msgstr "" 181msgstr ""
182 182
183#: src/microhttpd/daemon.c:2286 183#: src/microhttpd/daemon.c:2298
184msgid "PSK authentication failed: PSK too long\n" 184msgid "PSK authentication failed: PSK too long\n"
185msgstr "" 185msgstr ""
186 186
187#: src/microhttpd/daemon.c:2382 src/microhttpd/daemon.c:6217 187#: src/microhttpd/daemon.c:2394 src/microhttpd/daemon.c:6255
188#, c-format 188#, c-format
189msgid "Socket descriptor larger than FD_SETSIZE: %d > %d\n" 189msgid "Socket descriptor larger than FD_SETSIZE: %d > %d\n"
190msgstr "" 190msgstr ""
191 191
192#: src/microhttpd/daemon.c:2398 192#: src/microhttpd/daemon.c:2410
193#, c-format 193#, c-format
194msgid "Failed to set SO_NOSIGPIPE on accepted socket: %s\n" 194msgid "Failed to set SO_NOSIGPIPE on accepted socket: %s\n"
195msgstr "" 195msgstr ""
196 196
197#: src/microhttpd/daemon.c:2415 src/microhttpd/daemon.c:3238 197#: src/microhttpd/daemon.c:2427 src/microhttpd/daemon.c:3251
198#, c-format 198#, c-format
199msgid "Accepted connection on socket %d\n" 199msgid "Accepted connection on socket %d\n"
200msgstr "" 200msgstr ""
201 201
202#: src/microhttpd/daemon.c:2427 src/microhttpd/daemon.c:2617 202#: src/microhttpd/daemon.c:2439 src/microhttpd/daemon.c:2629
203msgid "Server reached connection limit. Closing inbound connection.\n" 203msgid "Server reached connection limit. Closing inbound connection.\n"
204msgstr "" 204msgstr ""
205 205
206#: src/microhttpd/daemon.c:2445 206#: src/microhttpd/daemon.c:2457
207msgid "Connection rejected by application. Closing connection.\n" 207msgid "Connection rejected by application. Closing connection.\n"
208msgstr "" 208msgstr ""
209 209
210#: src/microhttpd/daemon.c:2478 src/microhttpd/daemon.c:2498 210#: src/microhttpd/daemon.c:2490 src/microhttpd/daemon.c:2510
211#: src/microhttpd/daemon.c:3824 211#: src/microhttpd/daemon.c:3837
212#, c-format 212#, c-format
213msgid "Error allocating memory: %s\n" 213msgid "Error allocating memory: %s\n"
214msgstr "" 214msgstr ""
215 215
216#: src/microhttpd/daemon.c:2570 216#: src/microhttpd/daemon.c:2582
217#, c-format 217#, c-format
218msgid "Failed to setup TLS credentials: unknown credential type %d\n" 218msgid "Failed to setup TLS credentials: unknown credential type %d\n"
219msgstr "" 219msgstr ""
220 220
221#: src/microhttpd/daemon.c:2579 221#: src/microhttpd/daemon.c:2591
222msgid "Unknown credential type" 222msgid "Unknown credential type"
223msgstr "" 223msgstr ""
224 224
225#: src/microhttpd/daemon.c:2681 src/microhttpd/daemon.c:4314 225#: src/microhttpd/daemon.c:2693 src/microhttpd/daemon.c:4328
226#: src/microhttpd/daemon.c:4347 src/microhttpd/daemon.c:5509 226#: src/microhttpd/daemon.c:4361 src/microhttpd/daemon.c:5547
227#: src/microhttpd/daemon.c:5526 src/microhttpd/connection.c:4130 227#: src/microhttpd/daemon.c:5564 src/microhttpd/connection.c:4142
228#: src/microhttpd/response.c:1003 src/microhttpd/response.c:1029 228#: src/microhttpd/response.c:1003 src/microhttpd/response.c:1029
229#, c-format 229#, c-format
230msgid "Call to epoll_ctl failed: %s\n" 230msgid "Call to epoll_ctl failed: %s\n"
231msgstr "" 231msgstr ""
232 232
233#: src/microhttpd/daemon.c:2706 233#: src/microhttpd/daemon.c:2718
234msgid "Failed to signal new connection via inter-thread communication channel." 234msgid "Failed to signal new connection via inter-thread communication channel."
235msgstr "" 235msgstr ""
236 236
237#: src/microhttpd/daemon.c:2811 src/microhttpd/daemon.c:3322 237#: src/microhttpd/daemon.c:2823 src/microhttpd/daemon.c:3335
238#: src/microhttpd/daemon.c:6463 src/microhttpd/connection.c:1190 238#: src/microhttpd/daemon.c:6501 src/microhttpd/connection.c:1190
239#: src/microhttpd/connection.c:1209 239#: src/microhttpd/connection.c:1209
240msgid "Failed to remove FD from epoll set\n" 240msgid "Failed to remove FD from epoll set\n"
241msgstr "" 241msgstr ""
242 242
243#: src/microhttpd/daemon.c:2860 243#: src/microhttpd/daemon.c:2872
244msgid "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n" 244msgid "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"
245msgstr "" 245msgstr ""
246 246
247#: src/microhttpd/daemon.c:2866 247#: src/microhttpd/daemon.c:2878
248msgid "Error: connection scheduled for \"upgrade\" cannot be suspended" 248msgid "Error: connection scheduled for \"upgrade\" cannot be suspended"
249msgstr "" 249msgstr ""
250 250
251#: src/microhttpd/daemon.c:2889 251#: src/microhttpd/daemon.c:2901
252msgid "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n" 252msgid "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"
253msgstr "" 253msgstr ""
254 254
255#: src/microhttpd/daemon.c:2903 255#: src/microhttpd/daemon.c:2915
256msgid "Failed to signal resume via inter-thread communication channel." 256msgid "Failed to signal resume via inter-thread communication channel."
257msgstr "" 257msgstr ""
258 258
259#: src/microhttpd/daemon.c:3035 259#: src/microhttpd/daemon.c:3047
260msgid "" 260msgid ""
261"Failed to signal resume of connection via inter-thread communication channel." 261"Failed to signal resume of connection via inter-thread communication channel."
262msgstr "" 262msgstr ""
263 263
264#: src/microhttpd/daemon.c:3081 264#: src/microhttpd/daemon.c:3094
265#, c-format 265#, c-format
266msgid "Failed to set nonblocking mode on new client socket: %s\n" 266msgid "Failed to set nonblocking mode on new client socket: %s\n"
267msgstr "" 267msgstr ""
268 268
269#: src/microhttpd/daemon.c:3094 269#: src/microhttpd/daemon.c:3107
270msgid "Failed to set noninheritable mode on new client socket.\n" 270msgid "Failed to set noninheritable mode on new client socket.\n"
271msgstr "" 271msgstr ""
272 272
273#: src/microhttpd/daemon.c:3103 273#: src/microhttpd/daemon.c:3116
274msgid "Failed to reset buffering mode on new client socket.\n" 274msgid "Failed to reset buffering mode on new client socket.\n"
275msgstr "" 275msgstr ""
276 276
277#: src/microhttpd/daemon.c:3176 277#: src/microhttpd/daemon.c:3189
278#, c-format 278#, c-format
279msgid "Error accepting connection: %s\n" 279msgid "Error accepting connection: %s\n"
280msgstr "" 280msgstr ""
281 281
282#: src/microhttpd/daemon.c:3193 282#: src/microhttpd/daemon.c:3206
283msgid "" 283msgid ""
284"Hit process or system resource limit at FIRST connection. This is really bad " 284"Hit process or system resource limit at FIRST connection. This is really bad "
285"as there is no sane way to proceed. Will try busy waiting for system " 285"as there is no sane way to proceed. Will try busy waiting for system "
286"resources to become magically available.\n" 286"resources to become magically available.\n"
287msgstr "" 287msgstr ""
288 288
289#: src/microhttpd/daemon.c:3207 289#: src/microhttpd/daemon.c:3220
290#, c-format 290#, c-format
291msgid "" 291msgid ""
292"Hit process or system resource limit at %u connections, temporarily " 292"Hit process or system resource limit at %u connections, temporarily "
293"suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n" 293"suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"
294msgstr "" 294msgstr ""
295 295
296#: src/microhttpd/daemon.c:3219 296#: src/microhttpd/daemon.c:3232
297#, c-format 297#, c-format
298msgid "Failed to set nonblocking mode on incoming connection socket: %s\n" 298msgid "Failed to set nonblocking mode on incoming connection socket: %s\n"
299msgstr "" 299msgstr ""
300 300
301#: src/microhttpd/daemon.c:3231 301#: src/microhttpd/daemon.c:3244
302msgid "Failed to set noninheritable mode on incoming connection socket.\n" 302msgid "Failed to set noninheritable mode on incoming connection socket.\n"
303msgstr "" 303msgstr ""
304 304
305#: src/microhttpd/daemon.c:3279 src/microhttpd/daemon.c:6615 305#: src/microhttpd/daemon.c:3292 src/microhttpd/daemon.c:6653
306#: src/microhttpd/daemon.c:6647 src/microhttpd/daemon.c:6747 306#: src/microhttpd/daemon.c:6685 src/microhttpd/daemon.c:6785
307msgid "Failed to join a thread\n" 307msgid "Failed to join a thread\n"
308msgstr "" 308msgstr ""
309 309
310#: src/microhttpd/daemon.c:3383 310#: src/microhttpd/daemon.c:3396
311msgid "Illegal call to MHD_get_timeout\n" 311msgid "Illegal call to MHD_get_timeout\n"
312msgstr "" 312msgstr ""
313 313
314#: src/microhttpd/daemon.c:3580 314#: src/microhttpd/daemon.c:3593
315msgid "" 315msgid ""
316"MHD_run_from_select() called with except_fd_set set to NULL. Such behavior " 316"MHD_run_from_select() called with except_fd_set set to NULL. Such behavior "
317"is deprecated.\n" 317"is deprecated.\n"
318msgstr "" 318msgstr ""
319 319
320#: src/microhttpd/daemon.c:3660 320#: src/microhttpd/daemon.c:3673
321msgid "Could not obtain daemon fdsets" 321msgid "Could not obtain daemon fdsets"
322msgstr "" 322msgstr ""
323 323
324#: src/microhttpd/daemon.c:3677 324#: src/microhttpd/daemon.c:3690
325msgid "Could not add listen socket to fdset" 325msgid "Could not add listen socket to fdset"
326msgstr "" 326msgstr ""
327 327
328#: src/microhttpd/daemon.c:3705 328#: src/microhttpd/daemon.c:3718
329msgid "Could not add control inter-thread communication channel FD to fdset" 329msgid "Could not add control inter-thread communication channel FD to fdset"
330msgstr "" 330msgstr ""
331 331
332#: src/microhttpd/daemon.c:3761 332#: src/microhttpd/daemon.c:3774
333#, c-format 333#, c-format
334msgid "select failed: %s\n" 334msgid "select failed: %s\n"
335msgstr "" 335msgstr ""
336 336
337#: src/microhttpd/daemon.c:3906 src/microhttpd/daemon.c:4053 337#: src/microhttpd/daemon.c:3919 src/microhttpd/daemon.c:4066
338#, c-format 338#, c-format
339msgid "poll failed: %s\n" 339msgid "poll failed: %s\n"
340msgstr "" 340msgstr ""
341 341
342#: src/microhttpd/daemon.c:4183 src/microhttpd/daemon.c:4414 342#: src/microhttpd/daemon.c:4197 src/microhttpd/daemon.c:4428
343#, c-format 343#, c-format
344msgid "Call to epoll_wait failed: %s\n" 344msgid "Call to epoll_wait failed: %s\n"
345msgstr "" 345msgstr ""
346 346
347#: src/microhttpd/daemon.c:4366 src/microhttpd/daemon.c:4823 347#: src/microhttpd/daemon.c:4380 src/microhttpd/daemon.c:4837
348msgid "Failed to remove listen FD from epoll set\n" 348msgid "Failed to remove listen FD from epoll set\n"
349msgstr "" 349msgstr ""
350 350
351#: src/microhttpd/daemon.c:4831 351#: src/microhttpd/daemon.c:4845
352msgid "Failed to signal quiesce via inter-thread communication channel" 352msgid "Failed to signal quiesce via inter-thread communication channel"
353msgstr "" 353msgstr ""
354 354
355#: src/microhttpd/daemon.c:4853 355#: src/microhttpd/daemon.c:4867
356msgid "failed to signal quiesce via inter-thread communication channel" 356msgid "failed to signal quiesce via inter-thread communication channel"
357msgstr "" 357msgstr ""
358 358
359#: src/microhttpd/daemon.c:4964 359#: src/microhttpd/daemon.c:4981
360msgid "Warning: Too large timeout value, ignored.\n" 360msgid "Warning: Too large timeout value, ignored.\n"
361msgstr "" 361msgstr ""
362 362
363#: src/microhttpd/daemon.c:5003 363#: src/microhttpd/daemon.c:5020
364msgid "" 364msgid ""
365"Warning: Zero size, specified for thread pool size, is ignored. Thread pool " 365"Warning: Zero size, specified for thread pool size, is ignored. Thread pool "
366"is not used.\n" 366"is not used.\n"
367msgstr "" 367msgstr ""
368 368
369#: src/microhttpd/daemon.c:5011 369#: src/microhttpd/daemon.c:5028
370msgid "" 370msgid ""
371"Warning: \"1\", specified for thread pool size, is ignored. Thread pool is " 371"Warning: \"1\", specified for thread pool size, is ignored. Thread pool is "
372"not used.\n" 372"not used.\n"
373msgstr "" 373msgstr ""
374 374
375#: src/microhttpd/daemon.c:5023 375#: src/microhttpd/daemon.c:5040
376#, c-format 376#, c-format
377msgid "Specified thread pool size (%u) too big\n" 377msgid "Specified thread pool size (%u) too big\n"
378msgstr "" 378msgstr ""
379 379
380#: src/microhttpd/daemon.c:5034 380#: src/microhttpd/daemon.c:5051
381msgid "" 381msgid ""
382"MHD_OPTION_THREAD_POOL_SIZE option is specified but " 382"MHD_OPTION_THREAD_POOL_SIZE option is specified but "
383"MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n" 383"MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"
384msgstr "" 384msgstr ""
385 385
386#: src/microhttpd/daemon.c:5043 386#: src/microhttpd/daemon.c:5060
387msgid "" 387msgid ""
388"Both MHD_OPTION_THREAD_POOL_SIZE option and MHD_USE_THREAD_PER_CONNECTION " 388"Both MHD_OPTION_THREAD_POOL_SIZE option and MHD_USE_THREAD_PER_CONNECTION "
389"flag are specified.\n" 389"flag are specified.\n"
390msgstr "" 390msgstr ""
391 391
392#: src/microhttpd/daemon.c:5060 src/microhttpd/daemon.c:5072 392#: src/microhttpd/daemon.c:5077 src/microhttpd/daemon.c:5089
393#: src/microhttpd/daemon.c:5084 src/microhttpd/daemon.c:5096 393#: src/microhttpd/daemon.c:5101 src/microhttpd/daemon.c:5113
394#: src/microhttpd/daemon.c:5147 src/microhttpd/daemon.c:5175 394#: src/microhttpd/daemon.c:5164 src/microhttpd/daemon.c:5192
395#: src/microhttpd/daemon.c:5194 395#: src/microhttpd/daemon.c:5211 src/microhttpd/daemon.c:5231
396#, c-format 396#, c-format
397msgid "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n" 397msgid "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"
398msgstr "" 398msgstr ""
399 399
400#: src/microhttpd/daemon.c:5116 400#: src/microhttpd/daemon.c:5133
401msgid "Error initializing DH parameters\n" 401msgid "Error initializing DH parameters\n"
402msgstr "" 402msgstr ""
403 403
404#: src/microhttpd/daemon.c:5126 404#: src/microhttpd/daemon.c:5143
405msgid "Diffie-Hellman parameters string too long\n" 405msgid "Diffie-Hellman parameters string too long\n"
406msgstr "" 406msgstr ""
407 407
408#: src/microhttpd/daemon.c:5137 408#: src/microhttpd/daemon.c:5154
409msgid "Bad Diffie-Hellman parameters format\n" 409msgid "Bad Diffie-Hellman parameters format\n"
410msgstr "" 410msgstr ""
411 411
412#: src/microhttpd/daemon.c:5164 412#: src/microhttpd/daemon.c:5181
413#, c-format 413#, c-format
414msgid "Setting priorities to `%s' failed: %s\n" 414msgid "Setting priorities to `%s' failed: %s\n"
415msgstr "" 415msgstr ""
416 416
417#: src/microhttpd/daemon.c:5183 417#: src/microhttpd/daemon.c:5200
418msgid "" 418msgid ""
419"MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n" 419"MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"
420msgstr "" 420msgstr ""
421 421
422#: src/microhttpd/daemon.c:5217 422#: src/microhttpd/daemon.c:5220
423msgid ""
424"MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3\n"
425msgstr ""
426
427#: src/microhttpd/daemon.c:5254
423msgid "" 428msgid ""
424"MHD_OPTION_LISTEN_SOCKET specified for daemon with MHD_USE_NO_LISTEN_SOCKET " 429"MHD_OPTION_LISTEN_SOCKET specified for daemon with MHD_USE_NO_LISTEN_SOCKET "
425"flag set.\n" 430"flag set.\n"
426msgstr "" 431msgstr ""
427 432
428#: src/microhttpd/daemon.c:5253 433#: src/microhttpd/daemon.c:5290
429msgid "TCP fastopen is not supported on this platform\n" 434msgid "TCP fastopen is not supported on this platform\n"
430msgstr "" 435msgstr ""
431 436
432#: src/microhttpd/daemon.c:5272 437#: src/microhttpd/daemon.c:5309
433msgid "" 438msgid ""
434"Flag MHD_USE_PEDANTIC_CHECKS is ignored because another behavior is " 439"Flag MHD_USE_PEDANTIC_CHECKS is ignored because another behavior is "
435"specified by MHD_OPTION_STRICT_CLIENT.\n" 440"specified by MHD_OPTION_STRICT_CLIENT.\n"
436msgstr "" 441msgstr ""
437 442
438#: src/microhttpd/daemon.c:5404 443#: src/microhttpd/daemon.c:5442
439#, c-format 444#, c-format
440msgid "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3\n" 445msgid "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3\n"
441msgstr "" 446msgstr ""
442 447
443#: src/microhttpd/daemon.c:5417 448#: src/microhttpd/daemon.c:5455
444#, c-format 449#, c-format
445msgid "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n" 450msgid "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"
446msgstr "" 451msgstr ""
447 452
448#: src/microhttpd/daemon.c:5423 453#: src/microhttpd/daemon.c:5461
449#, c-format 454#, c-format
450msgid "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n" 455msgid "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"
451msgstr "" 456msgstr ""
452 457
453#: src/microhttpd/daemon.c:5453 458#: src/microhttpd/daemon.c:5491
454#, c-format 459#, c-format
455msgid "Call to epoll_create1 failed: %s\n" 460msgid "Call to epoll_create1 failed: %s\n"
456msgstr "" 461msgstr ""
457 462
458#: src/microhttpd/daemon.c:5463 463#: src/microhttpd/daemon.c:5501
459msgid "Failed to set noninheritable mode on epoll FD.\n" 464msgid "Failed to set noninheritable mode on epoll FD.\n"
460msgstr "" 465msgstr ""
461 466
462#: src/microhttpd/daemon.c:5706 467#: src/microhttpd/daemon.c:5744
463msgid "" 468msgid ""
464"Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with " 469"Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
465"MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD was " 470"MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD was "
466"added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n" 471"added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"
467msgstr "" 472msgstr ""
468 473
469#: src/microhttpd/daemon.c:5754 474#: src/microhttpd/daemon.c:5792
470msgid "Using debug build of libmicrohttpd.\n" 475msgid "Using debug build of libmicrohttpd.\n"
471msgstr "" 476msgstr ""
472 477
473#: src/microhttpd/daemon.c:5768 478#: src/microhttpd/daemon.c:5806
474#, c-format 479#, c-format
475msgid "Failed to create inter-thread communication channel: %s\n" 480msgid "Failed to create inter-thread communication channel: %s\n"
476msgstr "" 481msgstr ""
477 482
478#: src/microhttpd/daemon.c:5784 483#: src/microhttpd/daemon.c:5822
479msgid "" 484msgid ""
480"file descriptor for inter-thread communication channel exceeds maximum " 485"file descriptor for inter-thread communication channel exceeds maximum "
481"value\n" 486"value\n"
482msgstr "" 487msgstr ""
483 488
484#: src/microhttpd/daemon.c:5804 489#: src/microhttpd/daemon.c:5842
485msgid "Specified value for NC_SIZE too large\n" 490msgid "Specified value for NC_SIZE too large\n"
486msgstr "" 491msgstr ""
487 492
488#: src/microhttpd/daemon.c:5818 493#: src/microhttpd/daemon.c:5856
489#, c-format 494#, c-format
490msgid "Failed to allocate memory for nonce-nc map: %s\n" 495msgid "Failed to allocate memory for nonce-nc map: %s\n"
491msgstr "" 496msgstr ""
492 497
493#: src/microhttpd/daemon.c:5835 498#: src/microhttpd/daemon.c:5873
494msgid "MHD failed to initialize nonce-nc mutex\n" 499msgid "MHD failed to initialize nonce-nc mutex\n"
495msgstr "" 500msgstr ""
496 501
497#: src/microhttpd/daemon.c:5855 502#: src/microhttpd/daemon.c:5893
498msgid "MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n" 503msgid "MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"
499msgstr "" 504msgstr ""
500 505
501#: src/microhttpd/daemon.c:5879 506#: src/microhttpd/daemon.c:5917
502#, c-format 507#, c-format
503msgid "Failed to create socket for listening: %s\n" 508msgid "Failed to create socket for listening: %s\n"
504msgstr "" 509msgstr ""
505 510
506#: src/microhttpd/daemon.c:5900 src/microhttpd/daemon.c:5919 511#: src/microhttpd/daemon.c:5938 src/microhttpd/daemon.c:5957
507#: src/microhttpd/daemon.c:5942 src/microhttpd/daemon.c:5979 512#: src/microhttpd/daemon.c:5980 src/microhttpd/daemon.c:6017
508#: src/microhttpd/daemon.c:6056 src/microhttpd/daemon.c:6087 513#: src/microhttpd/daemon.c:6094 src/microhttpd/daemon.c:6125
509#, c-format 514#, c-format
510msgid "setsockopt failed: %s\n" 515msgid "setsockopt failed: %s\n"
511msgstr "" 516msgstr ""
512 517
513#: src/microhttpd/daemon.c:5952 518#: src/microhttpd/daemon.c:5990
514msgid "Cannot allow listening address reuse: SO_REUSEPORT not defined\n" 519msgid "Cannot allow listening address reuse: SO_REUSEPORT not defined\n"
515msgstr "" 520msgstr ""
516 521
517#: src/microhttpd/daemon.c:5987 522#: src/microhttpd/daemon.c:6025
518msgid "" 523msgid ""
519"Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n" 524"Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"
520msgstr "" 525msgstr ""
521 526
522#: src/microhttpd/daemon.c:6067 527#: src/microhttpd/daemon.c:6105
523#, c-format 528#, c-format
524msgid "Failed to bind to port %u: %s\n" 529msgid "Failed to bind to port %u: %s\n"
525msgstr "" 530msgstr ""
526 531
527#: src/microhttpd/daemon.c:6098 532#: src/microhttpd/daemon.c:6136
528#, c-format 533#, c-format
529msgid "Failed to listen for connections: %s\n" 534msgid "Failed to listen for connections: %s\n"
530msgstr "" 535msgstr ""
531 536
532#: src/microhttpd/daemon.c:6129 537#: src/microhttpd/daemon.c:6167
533#, c-format 538#, c-format
534msgid "Failed to get listen port number: %s\n" 539msgid "Failed to get listen port number: %s\n"
535msgstr "" 540msgstr ""
536 541
537#: src/microhttpd/daemon.c:6139 542#: src/microhttpd/daemon.c:6177
538msgid "" 543msgid ""
539"Failed to get listen port number (`struct sockaddr_storage` too small!?)\n" 544"Failed to get listen port number (`struct sockaddr_storage` too small!?)\n"
540msgstr "" 545msgstr ""
541 546
542#: src/microhttpd/daemon.c:6180 547#: src/microhttpd/daemon.c:6218
543msgid "Unknown address family!\n" 548msgid "Unknown address family!\n"
544msgstr "" 549msgstr ""
545 550
546#: src/microhttpd/daemon.c:6194 551#: src/microhttpd/daemon.c:6232
547#, c-format 552#, c-format
548msgid "Failed to set nonblocking mode on listening socket: %s\n" 553msgid "Failed to set nonblocking mode on listening socket: %s\n"
549msgstr "" 554msgstr ""
550 555
551#: src/microhttpd/daemon.c:6236 556#: src/microhttpd/daemon.c:6274
552msgid "" 557msgid ""
553"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n" 558"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"
554msgstr "" 559msgstr ""
555 560
556#: src/microhttpd/daemon.c:6250 src/microhttpd/daemon.c:6263 561#: src/microhttpd/daemon.c:6288 src/microhttpd/daemon.c:6301
557msgid "MHD failed to initialize IP connection limit mutex\n" 562msgid "MHD failed to initialize IP connection limit mutex\n"
558msgstr "" 563msgstr ""
559 564
560#: src/microhttpd/daemon.c:6282 565#: src/microhttpd/daemon.c:6320
561msgid "Failed to initialize TLS support\n" 566msgid "Failed to initialize TLS support\n"
562msgstr "" 567msgstr ""
563 568
564#: src/microhttpd/daemon.c:6309 569#: src/microhttpd/daemon.c:6347
565#, c-format 570#, c-format
566msgid "Failed to create listen thread: %s\n" 571msgid "Failed to create listen thread: %s\n"
567msgstr "" 572msgstr ""
568 573
569#: src/microhttpd/daemon.c:6357 574#: src/microhttpd/daemon.c:6395
570#, c-format 575#, c-format
571msgid "Failed to create worker inter-thread communication channel: %s\n" 576msgid "Failed to create worker inter-thread communication channel: %s\n"
572msgstr "" 577msgstr ""
573 578
574#: src/microhttpd/daemon.c:6368 579#: src/microhttpd/daemon.c:6406
575msgid "" 580msgid ""
576"File descriptor for worker inter-thread communication channel exceeds " 581"File descriptor for worker inter-thread communication channel exceeds "
577"maximum value\n" 582"maximum value\n"
578msgstr "" 583msgstr ""
579 584
580#: src/microhttpd/daemon.c:6393 585#: src/microhttpd/daemon.c:6431
581msgid "MHD failed to initialize cleanup connection mutex\n" 586msgid "MHD failed to initialize cleanup connection mutex\n"
582msgstr "" 587msgstr ""
583 588
584#: src/microhttpd/daemon.c:6407 589#: src/microhttpd/daemon.c:6445
585#, c-format 590#, c-format
586msgid "Failed to create pool thread: %s\n" 591msgid "Failed to create pool thread: %s\n"
587msgstr "" 592msgstr ""
588 593
589#: src/microhttpd/daemon.c:6560 src/microhttpd/daemon.c:6591 594#: src/microhttpd/daemon.c:6598 src/microhttpd/daemon.c:6629
590msgid "MHD_stop_daemon() called while we have suspended connections.\n" 595msgid "MHD_stop_daemon() called while we have suspended connections.\n"
591msgstr "" 596msgstr ""
592 597
593#: src/microhttpd/daemon.c:6600 src/microhttpd/daemon.c:6729 598#: src/microhttpd/daemon.c:6638 src/microhttpd/daemon.c:6767
594msgid "Failed to signal shutdown via inter-thread communication channel" 599msgid "Failed to signal shutdown via inter-thread communication channel"
595msgstr "" 600msgstr ""
596 601
597#: src/microhttpd/daemon.c:6692 602#: src/microhttpd/daemon.c:6730
598msgid "Failed to signal shutdown via inter-thread communication channel." 603msgid "Failed to signal shutdown via inter-thread communication channel."
599msgstr "" 604msgstr ""
600 605
601#: src/microhttpd/daemon.c:7159 606#: src/microhttpd/daemon.c:7203
602msgid "Failed to initialize winsock\n" 607msgid "Failed to initialize winsock\n"
603msgstr "" 608msgstr ""
604 609
605#: src/microhttpd/daemon.c:7162 610#: src/microhttpd/daemon.c:7206
606msgid "Winsock version 2.2 is not available\n" 611msgid "Winsock version 2.2 is not available\n"
607msgstr "" 612msgstr ""
608 613
609#: src/microhttpd/daemon.c:7170 src/microhttpd/daemon.c:7174 614#: src/microhttpd/daemon.c:7214 src/microhttpd/daemon.c:7218
610msgid "Failed to initialise multithreading in libgcrypt\n" 615msgid "Failed to initialise multithreading in libgcrypt\n"
611msgstr "" 616msgstr ""
612 617
613#: src/microhttpd/daemon.c:7179 618#: src/microhttpd/daemon.c:7223
614msgid "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n" 619msgid "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"
615msgstr "" 620msgstr ""
616 621
@@ -637,17 +642,17 @@ msgid ""
637"connection.\n" 642"connection.\n"
638msgstr "" 643msgstr ""
639 644
640#: src/microhttpd/connection.c:2055 src/microhttpd/connection.c:3068 645#: src/microhttpd/connection.c:2055 src/microhttpd/connection.c:3080
641msgid "Closing connection (failed to queue response)\n" 646msgid "Closing connection (failed to queue response)\n"
642msgstr "" 647msgstr ""
643 648
644#: src/microhttpd/connection.c:2065 src/microhttpd/connection.c:3842 649#: src/microhttpd/connection.c:2065 src/microhttpd/connection.c:3854
645#: src/microhttpd/connection.c:3965 650#: src/microhttpd/connection.c:3977
646msgid "Closing connection (failed to create response header)\n" 651msgid "Closing connection (failed to create response header)\n"
647msgstr "" 652msgstr ""
648 653
649#: src/microhttpd/connection.c:2111 src/microhttpd/connection.c:3223 654#: src/microhttpd/connection.c:2111 src/microhttpd/connection.c:3235
650#: src/microhttpd/connection.c:3291 src/microhttpd/connection.c:3607 655#: src/microhttpd/connection.c:3303 src/microhttpd/connection.c:3619
651#, c-format 656#, c-format
652msgid "In function %s handling connection at state: %s\n" 657msgid "In function %s handling connection at state: %s\n"
653msgstr "" 658msgstr ""
@@ -660,96 +665,96 @@ msgstr ""
660msgid "Not enough memory in pool to parse cookies!\n" 665msgid "Not enough memory in pool to parse cookies!\n"
661msgstr "" 666msgstr ""
662 667
663#: src/microhttpd/connection.c:2605 src/microhttpd/connection.c:2790 668#: src/microhttpd/connection.c:2605 src/microhttpd/connection.c:2802
664msgid "Application reported internal error, closing connection.\n" 669msgid "Application reported internal error, closing connection.\n"
665msgstr "" 670msgstr ""
666 671
667#: src/microhttpd/connection.c:2658 src/microhttpd/connection.c:2735 672#: src/microhttpd/connection.c:2670 src/microhttpd/connection.c:2747
668msgid "" 673msgid ""
669"Received malformed HTTP request (bad chunked encoding). Closing connection.\n" 674"Received malformed HTTP request (bad chunked encoding). Closing connection.\n"
670msgstr "" 675msgstr ""
671 676
672#: src/microhttpd/connection.c:2798 677#: src/microhttpd/connection.c:2810
673msgid "libmicrohttpd API violation" 678msgid "libmicrohttpd API violation"
674msgstr "" 679msgstr ""
675 680
676#: src/microhttpd/connection.c:2813 681#: src/microhttpd/connection.c:2825
677msgid "" 682msgid ""
678"WARNING: incomplete upload processing and connection not suspended may " 683"WARNING: incomplete upload processing and connection not suspended may "
679"result in hung connection.\n" 684"result in hung connection.\n"
680msgstr "" 685msgstr ""
681 686
682#: src/microhttpd/connection.c:2884 687#: src/microhttpd/connection.c:2896
683msgid "Received malformed line (no colon). Closing connection.\n" 688msgid "Received malformed line (no colon). Closing connection.\n"
684msgstr "" 689msgstr ""
685 690
686#: src/microhttpd/connection.c:3046 691#: src/microhttpd/connection.c:3058
687msgid "Received HTTP 1.1 request without `Host' header.\n" 692msgid "Received HTTP 1.1 request without `Host' header.\n"
688msgstr "" 693msgstr ""
689 694
690#: src/microhttpd/connection.c:3057 695#: src/microhttpd/connection.c:3069
691msgid "Closing connection (failed to create response)\n" 696msgid "Closing connection (failed to create response)\n"
692msgstr "" 697msgstr ""
693 698
694#: src/microhttpd/connection.c:3202 699#: src/microhttpd/connection.c:3214
695msgid "Socket disconnected while reading request.\n" 700msgid "Socket disconnected while reading request.\n"
696msgstr "" 701msgstr ""
697 702
698#: src/microhttpd/connection.c:3208 703#: src/microhttpd/connection.c:3220
699msgid "Connection socket is closed due to error when reading request.\n" 704msgid "Connection socket is closed due to error when reading request.\n"
700msgstr "" 705msgstr ""
701 706
702#: src/microhttpd/connection.c:3317 707#: src/microhttpd/connection.c:3329
703#, c-format 708#, c-format
704msgid "Failed to send data in request for %s.\n" 709msgid "Failed to send data in request for %s.\n"
705msgstr "" 710msgstr ""
706 711
707#: src/microhttpd/connection.c:3326 712#: src/microhttpd/connection.c:3338
708#, c-format 713#, c-format
709msgid "Sent 100 continue response: `%.*s'\n" 714msgid "Sent 100 continue response: `%.*s'\n"
710msgstr "" 715msgstr ""
711 716
712#: src/microhttpd/connection.c:3350 717#: src/microhttpd/connection.c:3362
713msgid "Connection was closed while sending response headers.\n" 718msgid "Connection was closed while sending response headers.\n"
714msgstr "" 719msgstr ""
715 720
716#: src/microhttpd/connection.c:3391 721#: src/microhttpd/connection.c:3403
717msgid "Data offset exceeds limit" 722msgid "Data offset exceeds limit"
718msgstr "" 723msgstr ""
719 724
720#: src/microhttpd/connection.c:3400 725#: src/microhttpd/connection.c:3412
721#, c-format 726#, c-format
722msgid "Sent %d-byte DATA response: `%.*s'\n" 727msgid "Sent %d-byte DATA response: `%.*s'\n"
723msgstr "" 728msgstr ""
724 729
725#: src/microhttpd/connection.c:3417 730#: src/microhttpd/connection.c:3429
726#, c-format 731#, c-format
727msgid "Failed to send data in request for `%s'.\n" 732msgid "Failed to send data in request for `%s'.\n"
728msgstr "" 733msgstr ""
729 734
730#: src/microhttpd/connection.c:3445 src/microhttpd/connection.c:3473 735#: src/microhttpd/connection.c:3457 src/microhttpd/connection.c:3485
731msgid "Connection was closed while sending response body.\n" 736msgid "Connection was closed while sending response body.\n"
732msgstr "" 737msgstr ""
733 738
734#: src/microhttpd/connection.c:3496 739#: src/microhttpd/connection.c:3508
735msgid "Internal error\n" 740msgid "Internal error\n"
736msgstr "" 741msgstr ""
737 742
738#: src/microhttpd/connection.c:3569 743#: src/microhttpd/connection.c:3581
739msgid "" 744msgid ""
740"Failed to signal end of connection via inter-thread communication channel" 745"Failed to signal end of connection via inter-thread communication channel"
741msgstr "" 746msgstr ""
742 747
743#: src/microhttpd/connection.c:4316 748#: src/microhttpd/connection.c:4328
744msgid "Attempted to queue response on wrong thread!\n" 749msgid "Attempted to queue response on wrong thread!\n"
745msgstr "" 750msgstr ""
746 751
747#: src/microhttpd/connection.c:4327 752#: src/microhttpd/connection.c:4339
748msgid "" 753msgid ""
749"Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n" 754"Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"
750msgstr "" 755msgstr ""
751 756
752#: src/microhttpd/connection.c:4336 757#: src/microhttpd/connection.c:4348
753msgid "Application used invalid status code for 'upgrade' response!\n" 758msgid "Application used invalid status code for 'upgrade' response!\n"
754msgstr "" 759msgstr ""
755 760
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 9d28cdb1..c2fc90a4 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -132,7 +132,7 @@ typedef intptr_t ssize_t;
132 * Current version of the library. 132 * Current version of the library.
133 * 0x01093001 = 1.9.30-1. 133 * 0x01093001 = 1.9.30-1.
134 */ 134 */
135#define MHD_VERSION 0x00096502 135#define MHD_VERSION 0x00096600
136 136
137/** 137/**
138 * MHD-internal return code for "YES". 138 * MHD-internal return code for "YES".
diff --git a/src/microhttpd/.gitignore b/src/microhttpd/.gitignore
index ec2e027d..611f88ec 100644
--- a/src/microhttpd/.gitignore
+++ b/src/microhttpd/.gitignore
@@ -57,3 +57,5 @@ test_shutdown_poll
57test_shutdown_select 57test_shutdown_select
58test_md5 58test_md5
59test_sha256 59test_sha256
60test_upgrade_large
61test_upgrade_large_tls
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 7a484371..597a2d56 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -166,17 +166,17 @@ check_PROGRAMS = \
166if HAVE_POSIX_THREADS 166if HAVE_POSIX_THREADS
167if ENABLE_UPGRADE 167if ENABLE_UPGRADE
168if USE_POSIX_THREADS 168if USE_POSIX_THREADS
169 check_PROGRAMS += test_upgrade 169 check_PROGRAMS += test_upgrade test_upgrade_large
170endif 170endif
171if USE_W32_THREADS 171if USE_W32_THREADS
172 check_PROGRAMS += test_upgrade 172 check_PROGRAMS += test_upgrade test_upgrade_large
173endif 173endif
174if ENABLE_HTTPS 174if ENABLE_HTTPS
175if USE_POSIX_THREADS 175if USE_POSIX_THREADS
176check_PROGRAMS += test_upgrade_tls 176check_PROGRAMS += test_upgrade_tls test_upgrade_large_tls
177endif 177endif
178if USE_W32_THREADS 178if USE_W32_THREADS
179check_PROGRAMS += test_upgrade_tls 179check_PROGRAMS += test_upgrade_tls test_upgrade_large_tls
180endif 180endif
181endif 181endif
182endif 182endif
@@ -231,6 +231,19 @@ test_upgrade_LDADD = \
231 $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \ 231 $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \
232 $(PTHREAD_LIBS) 232 $(PTHREAD_LIBS)
233 233
234test_upgrade_large_SOURCES = \
235 test_upgrade_large.c test_helpers.h mhd_sockets.h
236test_upgrade_large_CPPFLAGS = \
237 $(AM_CPPFLAGS) $(MHD_TLS_LIB_CPPFLAGS)
238test_upgrade_large_CFLAGS = \
239 $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(MHD_TLS_LIB_CFLAGS)
240test_upgrade_large_LDFLAGS = \
241 $(MHD_TLS_LIB_LDFLAGS)
242test_upgrade_large_LDADD = \
243 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
244 $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \
245 $(PTHREAD_LIBS)
246
234test_upgrade_tls_SOURCES = \ 247test_upgrade_tls_SOURCES = \
235 test_upgrade.c test_helpers.h mhd_sockets.h 248 test_upgrade.c test_helpers.h mhd_sockets.h
236test_upgrade_tls_CPPFLAGS = \ 249test_upgrade_tls_CPPFLAGS = \
@@ -244,6 +257,19 @@ test_upgrade_tls_LDADD = \
244 $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \ 257 $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \
245 $(PTHREAD_LIBS) 258 $(PTHREAD_LIBS)
246 259
260test_upgrade_large_tls_SOURCES = \
261 test_upgrade_large.c test_helpers.h mhd_sockets.h
262test_upgrade_large_tls_CPPFLAGS = \
263 $(AM_CPPFLAGS) $(MHD_TLS_LIB_CPPFLAGS)
264test_upgrade_large_tls_CFLAGS = \
265 $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(MHD_TLS_LIB_CFLAGS)
266test_upgrade_large_tls_LDFLAGS = \
267 $(MHD_TLS_LIB_LDFLAGS)
268test_upgrade_large_tls_LDADD = \
269 $(top_builddir)/src/microhttpd/libmicrohttpd.la \
270 $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \
271 $(PTHREAD_LIBS)
272
247test_postprocessor_SOURCES = \ 273test_postprocessor_SOURCES = \
248 test_postprocessor.c 274 test_postprocessor.c
249test_postprocessor_CPPFLAGS = \ 275test_postprocessor_CPPFLAGS = \
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 643ef52a..dab28878 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -800,7 +800,7 @@ MHD_lookup_connection_value_n (struct MHD_Connection *connection,
800 { 800 {
801 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 801 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
802 { 802 {
803 if ( (kind == pos->kind) && 803 if ( (0 != (kind & pos->kind)) &&
804 (NULL == pos->header) ) 804 (NULL == pos->header) )
805 break; 805 break;
806 } 806 }
@@ -809,7 +809,7 @@ MHD_lookup_connection_value_n (struct MHD_Connection *connection,
809 { 809 {
810 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 810 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
811 { 811 {
812 if ( (kind == pos->kind) && 812 if ( (0 != (kind & pos->kind)) &&
813 (key_size == pos->header_size) && 813 (key_size == pos->header_size) &&
814 ( (key == pos->header) || 814 ( (key == pos->header) ||
815 (MHD_str_equal_caseless_bin_n_ (key, 815 (MHD_str_equal_caseless_bin_n_ (key,
@@ -2454,7 +2454,19 @@ process_request_body (struct MHD_Connection *connection)
2454 char *buffer_head; 2454 char *buffer_head;
2455 2455
2456 if (NULL != connection->response) 2456 if (NULL != connection->response)
2457 return; /* already queued a response */ 2457 {
2458 /* already queued a response, discard remaining upload
2459 (but not more, there might be another request after it) */
2460 uint64_t purge = MHD_MIN (connection->remaining_upload_size,
2461 connection->read_buffer_offset);
2462 connection->remaining_upload_size -= purge;
2463 if (connection->read_buffer_offset > purge)
2464 memmove (connection->read_buffer,
2465 &connection->read_buffer[purge],
2466 connection->read_buffer_offset - purge);
2467 connection->read_buffer_offset -= purge;
2468 return;
2469 }
2458 2470
2459 buffer_head = connection->read_buffer; 2471 buffer_head = connection->read_buffer;
2460 available = connection->read_buffer_offset; 2472 available = connection->read_buffer_offset;
@@ -2589,19 +2601,19 @@ process_request_body (struct MHD_Connection *connection)
2589 { 2601 {
2590 /* no chunked encoding, give all to the client */ 2602 /* no chunked encoding, give all to the client */
2591 if ( (0 != connection->remaining_upload_size) && 2603 if ( (0 != connection->remaining_upload_size) &&
2592 (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) && 2604 (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2593 (connection->remaining_upload_size < available) ) 2605 (connection->remaining_upload_size < available) )
2594 { 2606 {
2595 to_be_processed = (size_t)connection->remaining_upload_size; 2607 to_be_processed = (size_t)connection->remaining_upload_size;
2596 } 2608 }
2597 else 2609 else
2598 { 2610 {
2599 /** 2611 /**
2600 * 1. no chunked encoding, give all to the client 2612 * 1. no chunked encoding, give all to the client
2601 * 2. client may send large chunked data, but only a smaller part is available at one time. 2613 * 2. client may send large chunked data, but only a smaller part is available at one time.
2602 */ 2614 */
2603 to_be_processed = available; 2615 to_be_processed = available;
2604 } 2616 }
2605 } 2617 }
2606 left_unprocessed = to_be_processed; 2618 left_unprocessed = to_be_processed;
2607 connection->client_aware = true; 2619 connection->client_aware = true;
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index d3595fe0..bf01ba9b 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -721,8 +721,8 @@ int
721MHD_get_fdset (struct MHD_Daemon *daemon, 721MHD_get_fdset (struct MHD_Daemon *daemon,
722 fd_set *read_fd_set, 722 fd_set *read_fd_set,
723 fd_set *write_fd_set, 723 fd_set *write_fd_set,
724 fd_set *except_fd_set, 724 fd_set *except_fd_set,
725 MHD_socket *max_fd) 725 MHD_socket *max_fd)
726{ 726{
727 return MHD_get_fdset2 (daemon, 727 return MHD_get_fdset2 (daemon,
728 read_fd_set, 728 read_fd_set,
@@ -2344,11 +2344,11 @@ psk_gnutls_adapter (gnutls_session_t session,
2344 */ 2344 */
2345static int 2345static int
2346internal_add_connection (struct MHD_Daemon *daemon, 2346internal_add_connection (struct MHD_Daemon *daemon,
2347 MHD_socket client_socket, 2347 MHD_socket client_socket,
2348 const struct sockaddr *addr, 2348 const struct sockaddr *addr,
2349 socklen_t addrlen, 2349 socklen_t addrlen,
2350 bool external_add, 2350 bool external_add,
2351 bool non_blck) 2351 bool non_blck)
2352{ 2352{
2353 struct MHD_Connection *connection; 2353 struct MHD_Connection *connection;
2354#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2354#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
@@ -2362,8 +2362,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2362 if ((external_add) && (NULL != daemon->worker_pool)) 2362 if ((external_add) && (NULL != daemon->worker_pool))
2363 { 2363 {
2364 /* have a pool, try to find a pool with capacity; we use the 2364 /* have a pool, try to find a pool with capacity; we use the
2365 socket as the initial offset into the pool for load 2365 socket as the initial offset into the pool for load
2366 balancing */ 2366 balancing */
2367 for (i = 0; i < daemon->worker_pool_size; ++i) 2367 for (i = 0; i < daemon->worker_pool_size; ++i)
2368 { 2368 {
2369 struct MHD_Daemon * const worker = 2369 struct MHD_Daemon * const worker =
@@ -2448,7 +2448,7 @@ internal_add_connection (struct MHD_Daemon *daemon,
2448 /* apply connection acceptance policy if present */ 2448 /* apply connection acceptance policy if present */
2449 if ( (NULL != daemon->apc) && 2449 if ( (NULL != daemon->apc) &&
2450 (MHD_NO == daemon->apc (daemon->apc_cls, 2450 (MHD_NO == daemon->apc (daemon->apc_cls,
2451 addr, 2451 addr,
2452 addrlen)) ) 2452 addrlen)) )
2453 { 2453 {
2454#if DEBUG_CLOSE 2454#if DEBUG_CLOSE
@@ -2472,8 +2472,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2472 eno = errno; 2472 eno = errno;
2473#ifdef HAVE_MESSAGES 2473#ifdef HAVE_MESSAGES
2474 MHD_DLOG (daemon, 2474 MHD_DLOG (daemon,
2475 "Error allocating memory: %s\n", 2475 "Error allocating memory: %s\n",
2476 MHD_strerror_ (errno)); 2476 MHD_strerror_ (errno));
2477#endif 2477#endif
2478 MHD_socket_close_chk_ (client_socket); 2478 MHD_socket_close_chk_ (client_socket);
2479 MHD_ip_limit_del (daemon, 2479 MHD_ip_limit_del (daemon,
@@ -2487,8 +2487,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2487 { 2487 {
2488#ifdef HAVE_MESSAGES 2488#ifdef HAVE_MESSAGES
2489 MHD_DLOG (daemon, 2489 MHD_DLOG (daemon,
2490 _("Error allocating memory: %s\n"), 2490 _("Error allocating memory: %s\n"),
2491 MHD_strerror_ (errno)); 2491 MHD_strerror_ (errno));
2492#endif 2492#endif
2493 MHD_socket_close_chk_ (client_socket); 2493 MHD_socket_close_chk_ (client_socket);
2494 MHD_ip_limit_del (daemon, 2494 MHD_ip_limit_del (daemon,
@@ -2507,8 +2507,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2507 eno = errno; 2507 eno = errno;
2508#ifdef HAVE_MESSAGES 2508#ifdef HAVE_MESSAGES
2509 MHD_DLOG (daemon, 2509 MHD_DLOG (daemon,
2510 _("Error allocating memory: %s\n"), 2510 _("Error allocating memory: %s\n"),
2511 MHD_strerror_ (errno)); 2511 MHD_strerror_ (errno));
2512#endif 2512#endif
2513 MHD_socket_close_chk_ (client_socket); 2513 MHD_socket_close_chk_ (client_socket);
2514 MHD_ip_limit_del (daemon, 2514 MHD_ip_limit_del (daemon,
@@ -2566,8 +2566,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2566 /* set needed credentials for certificate authentication. */ 2566 /* set needed credentials for certificate authentication. */
2567 case GNUTLS_CRD_CERTIFICATE: 2567 case GNUTLS_CRD_CERTIFICATE:
2568 gnutls_credentials_set (connection->tls_session, 2568 gnutls_credentials_set (connection->tls_session,
2569 GNUTLS_CRD_CERTIFICATE, 2569 GNUTLS_CRD_CERTIFICATE,
2570 daemon->x509_cred); 2570 daemon->x509_cred);
2571 break; 2571 break;
2572 case GNUTLS_CRD_PSK: 2572 case GNUTLS_CRD_PSK:
2573 gnutls_credentials_set (connection->tls_session, 2573 gnutls_credentials_set (connection->tls_session,
@@ -2596,18 +2596,18 @@ internal_add_connection (struct MHD_Daemon *daemon,
2596 } 2596 }
2597#if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64) 2597#if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64)
2598 gnutls_transport_set_int (connection->tls_session, 2598 gnutls_transport_set_int (connection->tls_session,
2599 (int)(client_socket)); 2599 (int)(client_socket));
2600#else /* GnuTLS before 3.1.9 or Win x64 */ 2600#else /* GnuTLS before 3.1.9 or Win x64 */
2601 gnutls_transport_set_ptr (connection->tls_session, 2601 gnutls_transport_set_ptr (connection->tls_session,
2602 (gnutls_transport_ptr_t)(intptr_t)(client_socket)); 2602 (gnutls_transport_ptr_t)(intptr_t)(client_socket));
2603#endif /* GnuTLS before 3.1.9 */ 2603#endif /* GnuTLS before 3.1.9 */
2604#ifdef MHD_TLSLIB_NEED_PUSH_FUNC 2604#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2605 gnutls_transport_set_push_function (connection->tls_session, 2605 gnutls_transport_set_push_function (connection->tls_session,
2606 MHD_tls_push_func_); 2606 MHD_tls_push_func_);
2607#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */ 2607#endif /* MHD_TLSLIB_NEED_PUSH_FUNC */
2608 if (daemon->https_mem_trust) 2608 if (daemon->https_mem_trust)
2609 gnutls_certificate_server_set_request (connection->tls_session, 2609 gnutls_certificate_server_set_request (connection->tls_session,
2610 GNUTLS_CERT_REQUEST); 2610 GNUTLS_CERT_REQUEST);
2611#else /* ! HTTPS_SUPPORT */ 2611#else /* ! HTTPS_SUPPORT */
2612 eno = EINVAL; 2612 eno = EINVAL;
2613 goto cleanup; 2613 goto cleanup;
@@ -2641,8 +2641,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2641 connection); 2641 connection);
2642 } 2642 }
2643 DLL_insert (daemon->connections_head, 2643 DLL_insert (daemon->connections_head,
2644 daemon->connections_tail, 2644 daemon->connections_tail,
2645 connection); 2645 connection);
2646#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2646#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2647 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); 2647 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2648#endif 2648#endif
@@ -2661,13 +2661,13 @@ internal_add_connection (struct MHD_Daemon *daemon,
2661 &thread_main_handle_connection, 2661 &thread_main_handle_connection,
2662 connection)) 2662 connection))
2663 { 2663 {
2664 eno = errno; 2664 eno = errno;
2665#ifdef HAVE_MESSAGES 2665#ifdef HAVE_MESSAGES
2666 MHD_DLOG (daemon, 2666 MHD_DLOG (daemon,
2667 "Failed to create a thread: %s\n", 2667 "Failed to create a thread: %s\n",
2668 MHD_strerror_ (eno)); 2668 MHD_strerror_ (eno));
2669#endif 2669#endif
2670 goto cleanup; 2670 goto cleanup;
2671 } 2671 }
2672 } 2672 }
2673 else 2673 else
@@ -2683,9 +2683,9 @@ internal_add_connection (struct MHD_Daemon *daemon,
2683 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET; 2683 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2684 event.data.ptr = connection; 2684 event.data.ptr = connection;
2685 if (0 != epoll_ctl (daemon->epoll_fd, 2685 if (0 != epoll_ctl (daemon->epoll_fd,
2686 EPOLL_CTL_ADD, 2686 EPOLL_CTL_ADD,
2687 client_socket, 2687 client_socket,
2688 &event)) 2688 &event))
2689 { 2689 {
2690 eno = errno; 2690 eno = errno;
2691#ifdef HAVE_MESSAGES 2691#ifdef HAVE_MESSAGES
@@ -2702,8 +2702,8 @@ internal_add_connection (struct MHD_Daemon *daemon,
2702 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY 2702 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
2703 | MHD_EPOLL_STATE_IN_EREADY_EDLL; 2703 | MHD_EPOLL_STATE_IN_EREADY_EDLL;
2704 EDLL_insert (daemon->eready_head, 2704 EDLL_insert (daemon->eready_head,
2705 daemon->eready_tail, 2705 daemon->eready_tail,
2706 connection); 2706 connection);
2707 } 2707 }
2708 } 2708 }
2709 else /* This 'else' is combined with next 'if'. */ 2709 else /* This 'else' is combined with next 'if'. */
@@ -3041,12 +3041,12 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
3041 { /* Wake up suspended connections. */ 3041 { /* Wake up suspended connections. */
3042 if (! MHD_itc_activate_(daemon->itc, 3042 if (! MHD_itc_activate_(daemon->itc,
3043 "w")) 3043 "w"))
3044 { 3044 {
3045#ifdef HAVE_MESSAGES 3045#ifdef HAVE_MESSAGES
3046 MHD_DLOG (daemon, 3046 MHD_DLOG (daemon,
3047 _("Failed to signal resume of connection via inter-thread communication channel.")); 3047 _("Failed to signal resume of connection via inter-thread communication channel."));
3048#endif 3048#endif
3049 } 3049 }
3050 } 3050 }
3051 return ret; 3051 return ret;
3052} 3052}
@@ -3081,11 +3081,12 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
3081 */ 3081 */
3082int 3082int
3083MHD_add_connection (struct MHD_Daemon *daemon, 3083MHD_add_connection (struct MHD_Daemon *daemon,
3084 MHD_socket client_socket, 3084 MHD_socket client_socket,
3085 const struct sockaddr *addr, 3085 const struct sockaddr *addr,
3086 socklen_t addrlen) 3086 socklen_t addrlen)
3087{ 3087{
3088 bool sk_nonbl; 3088 bool sk_nonbl;
3089
3089 if (! MHD_socket_nonblocking_ (client_socket)) 3090 if (! MHD_socket_nonblocking_ (client_socket))
3090 { 3091 {
3091#ifdef HAVE_MESSAGES 3092#ifdef HAVE_MESSAGES
@@ -3116,11 +3117,11 @@ MHD_add_connection (struct MHD_Daemon *daemon,
3116#endif 3117#endif
3117 } 3118 }
3118 return internal_add_connection (daemon, 3119 return internal_add_connection (daemon,
3119 client_socket, 3120 client_socket,
3120 addr, 3121 addr,
3121 addrlen, 3122 addrlen,
3122 true, 3123 true,
3123 sk_nonbl); 3124 sk_nonbl);
3124} 3125}
3125 3126
3126 3127
@@ -3253,9 +3254,9 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
3253#endif 3254#endif
3254 (void) internal_add_connection (daemon, 3255 (void) internal_add_connection (daemon,
3255 s, 3256 s,
3256 addr, 3257 addr,
3257 addrlen, 3258 addrlen,
3258 false, 3259 false,
3259 sk_nonbl); 3260 sk_nonbl);
3260 return MHD_YES; 3261 return MHD_YES;
3261} 3262}
@@ -3381,7 +3382,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
3381 */ 3382 */
3382int 3383int
3383MHD_get_timeout (struct MHD_Daemon *daemon, 3384MHD_get_timeout (struct MHD_Daemon *daemon,
3384 MHD_UNSIGNED_LONG_LONG *timeout) 3385 MHD_UNSIGNED_LONG_LONG *timeout)
3385{ 3386{
3386 time_t earliest_deadline; 3387 time_t earliest_deadline;
3387 time_t now; 3388 time_t now;
@@ -4177,28 +4178,29 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4177 struct MHD_UpgradeResponseHandle * prev; 4178 struct MHD_UpgradeResponseHandle * prev;
4178 4179
4179 num_events = MAX_EVENTS; 4180 num_events = MAX_EVENTS;
4180 while (MAX_EVENTS == num_events) 4181 while (0 != num_events)
4181 { 4182 {
4182 unsigned int i; 4183 unsigned int i;
4183 /* update event masks */ 4184 /* update event masks */
4184 num_events = epoll_wait (daemon->epoll_upgrade_fd, 4185 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4185 events, 4186 events,
4186 MAX_EVENTS, 4187 MAX_EVENTS,
4187 0); 4188 0);
4188 if (-1 == num_events) 4189 if (-1 == num_events)
4189 { 4190 {
4190 const int err = MHD_socket_get_error_ (); 4191 const int err = MHD_socket_get_error_ ();
4192
4191 if (MHD_SCKT_ERR_IS_EINTR_ (err)) 4193 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4192 return MHD_YES; 4194 return MHD_YES;
4193#ifdef HAVE_MESSAGES 4195#ifdef HAVE_MESSAGES
4194 MHD_DLOG (daemon, 4196 MHD_DLOG (daemon,
4195 _("Call to epoll_wait failed: %s\n"), 4197 _("Call to epoll_wait failed: %s\n"),
4196 MHD_socket_strerr_ (err)); 4198 MHD_socket_strerr_ (err));
4197#endif 4199#endif
4198 return MHD_NO; 4200 return MHD_NO;
4199 } 4201 }
4200 for (i = 0; i < (unsigned int) num_events; i++) 4202 for (i = 0; i < (unsigned int) num_events; i++)
4201 { 4203 {
4202 struct UpgradeEpollHandle * const ueh = events[i].data.ptr; 4204 struct UpgradeEpollHandle * const ueh = events[i].data.ptr;
4203 struct MHD_UpgradeResponseHandle * const urh = ueh->urh; 4205 struct MHD_UpgradeResponseHandle * const urh = ueh->urh;
4204 bool new_err_state = false; 4206 bool new_err_state = false;
@@ -4216,24 +4218,24 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4216 4218
4217 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) && 4219 if ( (0 == (ueh->celi & MHD_EPOLL_STATE_ERROR)) &&
4218 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) ) 4220 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4219 { 4221 {
4220 /* Process new error state only one time 4222 /* Process new error state only one time
4221 * and avoid continuously marking this connection 4223 * and avoid continuously marking this connection
4222 * as 'ready'. */ 4224 * as 'ready'. */
4223 ueh->celi |= MHD_EPOLL_STATE_ERROR; 4225 ueh->celi |= MHD_EPOLL_STATE_ERROR;
4224 new_err_state = true; 4226 new_err_state = true;
4225 } 4227 }
4226 4228
4227 if (! urh->in_eready_list) 4229 if (! urh->in_eready_list)
4228 { 4230 {
4229 if (new_err_state || 4231 if (new_err_state ||
4230 is_urh_ready(urh)) 4232 is_urh_ready(urh))
4231 { 4233 {
4232 EDLL_insert (daemon->eready_urh_head, 4234 EDLL_insert (daemon->eready_urh_head,
4233 daemon->eready_urh_tail, 4235 daemon->eready_urh_tail,
4234 urh); 4236 urh);
4235 urh->in_eready_list = true; 4237 urh->in_eready_list = true;
4236 } 4238 }
4237 } 4239 }
4238 } 4240 }
4239 } 4241 }
@@ -4245,8 +4247,8 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4245 if (! is_urh_ready(pos)) 4247 if (! is_urh_ready(pos))
4246 { 4248 {
4247 EDLL_remove (daemon->eready_urh_head, 4249 EDLL_remove (daemon->eready_urh_head,
4248 daemon->eready_urh_tail, 4250 daemon->eready_urh_tail,
4249 pos); 4251 pos);
4250 pos->in_eready_list = false; 4252 pos->in_eready_list = false;
4251 } 4253 }
4252 /* Finished forwarding? */ 4254 /* Finished forwarding? */
@@ -4261,7 +4263,7 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
4261 * will be moved immediately to cleanup list. Otherwise 4263 * will be moved immediately to cleanup list. Otherwise
4262 * connection will stay in suspended list until 'pos' will 4264 * connection will stay in suspended list until 'pos' will
4263 * be marked with 'was_closed' by application. */ 4265 * be marked with 'was_closed' by application. */
4264 MHD_resume_connection(pos->connection); 4266 MHD_resume_connection (pos->connection);
4265 } 4267 }
4266 } 4268 }
4267 4269
@@ -4286,7 +4288,7 @@ static const char * const epoll_itc_marker = "itc_marker";
4286 */ 4288 */
4287static int 4289static int
4288MHD_epoll (struct MHD_Daemon *daemon, 4290MHD_epoll (struct MHD_Daemon *daemon,
4289 int may_block) 4291 int may_block)
4290{ 4292{
4291#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4293#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4292 static const char * const upgrade_marker = "upgrade_ptr"; 4294 static const char * const upgrade_marker = "upgrade_ptr";
@@ -4301,7 +4303,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
4301 unsigned int i; 4303 unsigned int i;
4302 MHD_socket ls; 4304 MHD_socket ls;
4303#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4305#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4304 int run_upgraded = MHD_NO; 4306 bool run_upgraded = false;
4305#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4307#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4306 4308
4307 if (-1 == daemon->epoll_fd) 4309 if (-1 == daemon->epoll_fd)
@@ -4317,50 +4319,50 @@ MHD_epoll (struct MHD_Daemon *daemon,
4317 event.events = EPOLLIN; 4319 event.events = EPOLLIN;
4318 event.data.ptr = daemon; 4320 event.data.ptr = daemon;
4319 if (0 != epoll_ctl (daemon->epoll_fd, 4321 if (0 != epoll_ctl (daemon->epoll_fd,
4320 EPOLL_CTL_ADD, 4322 EPOLL_CTL_ADD,
4321 ls, 4323 ls,
4322 &event)) 4324 &event))
4323 { 4325 {
4324#ifdef HAVE_MESSAGES 4326#ifdef HAVE_MESSAGES
4325 MHD_DLOG (daemon, 4327 MHD_DLOG (daemon,
4326 _("Call to epoll_ctl failed: %s\n"), 4328 _("Call to epoll_ctl failed: %s\n"),
4327 MHD_socket_last_strerr_ ()); 4329 MHD_socket_last_strerr_ ());
4328#endif 4330#endif
4329 return MHD_NO; 4331 return MHD_NO;
4330 } 4332 }
4331 daemon->listen_socket_in_epoll = true; 4333 daemon->listen_socket_in_epoll = true;
4332 } 4334 }
4333 if ( (daemon->was_quiesced) && 4335 if ( (daemon->was_quiesced) &&
4334 (daemon->listen_socket_in_epoll) ) 4336 (daemon->listen_socket_in_epoll) )
4335 { 4337 {
4336 if ( (0 != epoll_ctl (daemon->epoll_fd, 4338 if ( (0 != epoll_ctl (daemon->epoll_fd,
4337 EPOLL_CTL_DEL, 4339 EPOLL_CTL_DEL,
4338 ls, 4340 ls,
4339 NULL)) && 4341 NULL)) &&
4340 (ENOENT != errno) ) /* ENOENT can happen due to race with 4342 (ENOENT != errno) ) /* ENOENT can happen due to race with
4341 #MHD_quiesce_daemon() */ 4343 #MHD_quiesce_daemon() */
4342 MHD_PANIC ("Failed to remove listen FD from epoll set\n"); 4344 MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4343 daemon->listen_socket_in_epoll = false; 4345 daemon->listen_socket_in_epoll = false;
4344 } 4346 }
4345 4347
4346#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4348#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4347 if ( (! daemon->upgrade_fd_in_epoll) && 4349 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4348 (-1 != daemon->epoll_upgrade_fd) ) 4350 (-1 != daemon->epoll_upgrade_fd) ) )
4349 { 4351 {
4350 event.events = EPOLLIN | EPOLLOUT; 4352 event.events = EPOLLIN | EPOLLOUT;
4351 event.data.ptr = (void *) upgrade_marker; 4353 event.data.ptr = (void *) upgrade_marker;
4352 if (0 != epoll_ctl (daemon->epoll_fd, 4354 if (0 != epoll_ctl (daemon->epoll_fd,
4353 EPOLL_CTL_ADD, 4355 EPOLL_CTL_ADD,
4354 daemon->epoll_upgrade_fd, 4356 daemon->epoll_upgrade_fd,
4355 &event)) 4357 &event))
4356 { 4358 {
4357#ifdef HAVE_MESSAGES 4359#ifdef HAVE_MESSAGES
4358 MHD_DLOG (daemon, 4360 MHD_DLOG (daemon,
4359 _("Call to epoll_ctl failed: %s\n"), 4361 _("Call to epoll_ctl failed: %s\n"),
4360 MHD_socket_last_strerr_ ()); 4362 MHD_socket_last_strerr_ ());
4361#endif 4363#endif
4362 return MHD_NO; 4364 return MHD_NO;
4363 } 4365 }
4364 daemon->upgrade_fd_in_epoll = true; 4366 daemon->upgrade_fd_in_epoll = true;
4365 } 4367 }
4366#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4368#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
@@ -4372,10 +4374,10 @@ MHD_epoll (struct MHD_Daemon *daemon,
4372 /* we're at the connection limit, disable listen socket 4374 /* we're at the connection limit, disable listen socket
4373 for event loop for now */ 4375 for event loop for now */
4374 if (0 != epoll_ctl (daemon->epoll_fd, 4376 if (0 != epoll_ctl (daemon->epoll_fd,
4375 EPOLL_CTL_DEL, 4377 EPOLL_CTL_DEL,
4376 ls, 4378 ls,
4377 NULL)) 4379 NULL))
4378 MHD_PANIC (_("Failed to remove listen FD from epoll set\n")); 4380 MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4379 daemon->listen_socket_in_epoll = false; 4381 daemon->listen_socket_in_epoll = false;
4380 } 4382 }
4381 4383
@@ -4386,15 +4388,15 @@ MHD_epoll (struct MHD_Daemon *daemon,
4386 if (MHD_YES == may_block) 4388 if (MHD_YES == may_block)
4387 { 4389 {
4388 if (MHD_YES == MHD_get_timeout (daemon, 4390 if (MHD_YES == MHD_get_timeout (daemon,
4389 &timeout_ll)) 4391 &timeout_ll))
4390 { 4392 {
4391 if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX) 4393 if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
4392 timeout_ms = INT_MAX; 4394 timeout_ms = INT_MAX;
4393 else 4395 else
4394 timeout_ms = (int) timeout_ll; 4396 timeout_ms = (int) timeout_ll;
4395 } 4397 }
4396 else 4398 else
4397 timeout_ms = -1; 4399 timeout_ms = -1;
4398 } 4400 }
4399 else 4401 else
4400 timeout_ms = 0; 4402 timeout_ms = 0;
@@ -4413,33 +4415,33 @@ MHD_epoll (struct MHD_Daemon *daemon,
4413 { 4415 {
4414 /* update event masks */ 4416 /* update event masks */
4415 num_events = epoll_wait (daemon->epoll_fd, 4417 num_events = epoll_wait (daemon->epoll_fd,
4416 events, 4418 events,
4417 MAX_EVENTS, 4419 MAX_EVENTS,
4418 timeout_ms); 4420 timeout_ms);
4419 if (-1 == num_events) 4421 if (-1 == num_events)
4420 { 4422 {
4421 const int err = MHD_socket_get_error_ (); 4423 const int err = MHD_socket_get_error_ ();
4422 if (MHD_SCKT_ERR_IS_EINTR_ (err)) 4424 if (MHD_SCKT_ERR_IS_EINTR_ (err))
4423 return MHD_YES; 4425 return MHD_YES;
4424#ifdef HAVE_MESSAGES 4426#ifdef HAVE_MESSAGES
4425 MHD_DLOG (daemon, 4427 MHD_DLOG (daemon,
4426 _("Call to epoll_wait failed: %s\n"), 4428 _("Call to epoll_wait failed: %s\n"),
4427 MHD_socket_strerr_ (err)); 4429 MHD_socket_strerr_ (err));
4428#endif 4430#endif
4429 return MHD_NO; 4431 return MHD_NO;
4430 } 4432 }
4431 for (i=0;i<(unsigned int) num_events;i++) 4433 for (i=0;i<(unsigned int) num_events;i++)
4432 { 4434 {
4433 /* First, check for the values of `ptr` that would indicate 4435 /* First, check for the values of `ptr` that would indicate
4434 that this event is not about a normal connection. */ 4436 that this event is not about a normal connection. */
4435 if (NULL == events[i].data.ptr) 4437 if (NULL == events[i].data.ptr)
4436 continue; /* shutdown signal! */ 4438 continue; /* shutdown signal! */
4437#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4439#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4438 if (upgrade_marker == events[i].data.ptr) 4440 if (upgrade_marker == events[i].data.ptr)
4439 { 4441 {
4440 /* activity on an upgraded connection, we process 4442 /* activity on an upgraded connection, we process
4441 those in a separate epoll() */ 4443 those in a separate epoll() */
4442 run_upgraded = MHD_YES; 4444 run_upgraded = true;
4443 continue; 4445 continue;
4444 } 4446 }
4445#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4447#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
@@ -4450,8 +4452,8 @@ MHD_epoll (struct MHD_Daemon *daemon,
4450 MHD_itc_clear_ (daemon->itc); 4452 MHD_itc_clear_ (daemon->itc);
4451 continue; 4453 continue;
4452 } 4454 }
4453 if (daemon == events[i].data.ptr) 4455 if (daemon == events[i].data.ptr)
4454 { 4456 {
4455 /* Check for error conditions on listen socket. */ 4457 /* Check for error conditions on listen socket. */
4456 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */ 4458 /* FIXME: Initiate MHD_quiesce_daemon() to prevent busy waiting? */
4457 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP))) 4459 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
@@ -4466,9 +4468,9 @@ MHD_epoll (struct MHD_Daemon *daemon,
4466 (daemon->connections < daemon->connection_limit) && 4468 (daemon->connections < daemon->connection_limit) &&
4467 (! daemon->at_limit) ) 4469 (! daemon->at_limit) )
4468 series_length++; 4470 series_length++;
4469 } 4471 }
4470 continue; 4472 continue;
4471 } 4473 }
4472 /* this is an event relating to a 'normal' connection, 4474 /* this is an event relating to a 'normal' connection,
4473 remember the event and if appropriate mark the 4475 remember the event and if appropriate mark the
4474 connection as 'eready'. */ 4476 connection as 'eready'. */
@@ -4517,7 +4519,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
4517 } 4519 }
4518 4520
4519#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4521#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4520 if (MHD_YES == run_upgraded) 4522 if (run_upgraded || (NULL != daemon->eready_urh_head))
4521 run_epoll_for_upgrade (daemon); 4523 run_epoll_for_upgrade (daemon);
4522#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4524#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4523 4525
@@ -4605,22 +4607,22 @@ MHD_run (struct MHD_Daemon *daemon)
4605 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) ) 4607 (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
4606 return MHD_NO; 4608 return MHD_NO;
4607 if (0 != (daemon->options & MHD_USE_POLL)) 4609 if (0 != (daemon->options & MHD_USE_POLL))
4608 { 4610 {
4609 MHD_poll (daemon, MHD_NO); 4611 MHD_poll (daemon, MHD_NO);
4610 MHD_cleanup_connections (daemon); 4612 MHD_cleanup_connections (daemon);
4611 } 4613 }
4612#ifdef EPOLL_SUPPORT 4614#ifdef EPOLL_SUPPORT
4613 else if (0 != (daemon->options & MHD_USE_EPOLL)) 4615 else if (0 != (daemon->options & MHD_USE_EPOLL))
4614 { 4616 {
4615 MHD_epoll (daemon, MHD_NO); 4617 MHD_epoll (daemon, MHD_NO);
4616 MHD_cleanup_connections (daemon); 4618 MHD_cleanup_connections (daemon);
4617 } 4619 }
4618#endif 4620#endif
4619 else 4621 else
4620 { 4622 {
4621 MHD_select (daemon, MHD_NO); 4623 MHD_select (daemon, MHD_NO);
4622 /* MHD_select does MHD_cleanup_connections already */ 4624 /* MHD_select does MHD_cleanup_connections already */
4623 } 4625 }
4624 return MHD_YES; 4626 return MHD_YES;
4625} 4627}
4626 4628
@@ -4822,26 +4824,26 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon)
4822 if (NULL != daemon->worker_pool) 4824 if (NULL != daemon->worker_pool)
4823 for (i = 0; i < daemon->worker_pool_size; i++) 4825 for (i = 0; i < daemon->worker_pool_size; i++)
4824 { 4826 {
4825 daemon->worker_pool[i].was_quiesced = true; 4827 daemon->worker_pool[i].was_quiesced = true;
4826#ifdef EPOLL_SUPPORT 4828#ifdef EPOLL_SUPPORT
4827 if ( (0 != (daemon->options & MHD_USE_EPOLL)) && 4829 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4828 (-1 != daemon->worker_pool[i].epoll_fd) && 4830 (-1 != daemon->worker_pool[i].epoll_fd) &&
4829 (daemon->worker_pool[i].listen_socket_in_epoll) ) 4831 (daemon->worker_pool[i].listen_socket_in_epoll) )
4830 {
4831 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4832 EPOLL_CTL_DEL,
4833 ret,
4834 NULL))
4835 MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4836 daemon->worker_pool[i].listen_socket_in_epoll = false;
4837 }
4838 else
4839#endif
4840 if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
4841 { 4832 {
4842 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q")) 4833 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
4843 MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel")); 4834 EPOLL_CTL_DEL,
4835 ret,
4836 NULL))
4837 MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
4838 daemon->worker_pool[i].listen_socket_in_epoll = false;
4844 } 4839 }
4840 else
4841#endif
4842 if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc))
4843 {
4844 if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "q"))
4845 MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
4846 }
4845 } 4847 }
4846#endif 4848#endif
4847 daemon->was_quiesced = true; 4849 daemon->was_quiesced = true;
@@ -4856,7 +4858,7 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon)
4856 NULL)) && 4858 NULL)) &&
4857 (ENOENT != errno) ) /* ENOENT can happen due to race with 4859 (ENOENT != errno) ) /* ENOENT can happen due to race with
4858 #MHD_epoll() */ 4860 #MHD_epoll() */
4859 MHD_PANIC ("Failed to remove listen FD from epoll set\n"); 4861 MHD_PANIC ("Failed to remove listen FD from epoll set\n");
4860 daemon->listen_socket_in_epoll = false; 4862 daemon->listen_socket_in_epoll = false;
4861 } 4863 }
4862#endif 4864#endif
@@ -4890,8 +4892,8 @@ typedef void
4890 */ 4892 */
4891static int 4893static int
4892parse_options_va (struct MHD_Daemon *daemon, 4894parse_options_va (struct MHD_Daemon *daemon,
4893 const struct sockaddr **servaddr, 4895 const struct sockaddr **servaddr,
4894 va_list ap); 4896 va_list ap);
4895 4897
4896 4898
4897/** 4899/**
@@ -4929,8 +4931,8 @@ parse_options (struct MHD_Daemon *daemon,
4929 */ 4931 */
4930static int 4932static int
4931parse_options_va (struct MHD_Daemon *daemon, 4933parse_options_va (struct MHD_Daemon *daemon,
4932 const struct sockaddr **servaddr, 4934 const struct sockaddr **servaddr,
4933 va_list ap) 4935 va_list ap)
4934{ 4936{
4935 enum MHD_OPTION opt; 4937 enum MHD_OPTION opt;
4936 struct MHD_OptionItem *oa; 4938 struct MHD_OptionItem *oa;
@@ -6493,10 +6495,10 @@ thread_failed:
6493 if (daemon->upgrade_fd_in_epoll) 6495 if (daemon->upgrade_fd_in_epoll)
6494 { 6496 {
6495 if (0 != epoll_ctl (daemon->epoll_fd, 6497 if (0 != epoll_ctl (daemon->epoll_fd,
6496 EPOLL_CTL_DEL, 6498 EPOLL_CTL_DEL,
6497 daemon->epoll_upgrade_fd, 6499 daemon->epoll_upgrade_fd,
6498 NULL)) 6500 NULL))
6499 MHD_PANIC (_("Failed to remove FD from epoll set\n")); 6501 MHD_PANIC (_("Failed to remove FD from epoll set\n"));
6500 daemon->upgrade_fd_in_epoll = false; 6502 daemon->upgrade_fd_in_epoll = false;
6501 } 6503 }
6502#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 6504#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 6e569d77..7b98a45c 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -80,9 +80,9 @@
80 */ 80 */
81static int 81static int
82add_response_entry (struct MHD_Response *response, 82add_response_entry (struct MHD_Response *response,
83 enum MHD_ValueKind kind, 83 enum MHD_ValueKind kind,
84 const char *header, 84 const char *header,
85 const char *content) 85 const char *content)
86{ 86{
87 struct MHD_HTTP_Header *hdr; 87 struct MHD_HTTP_Header *hdr;
88 88
@@ -280,7 +280,7 @@ MHD_get_response_headers (struct MHD_Response *response,
280 */ 280 */
281const char * 281const char *
282MHD_get_response_header (struct MHD_Response *response, 282MHD_get_response_header (struct MHD_Response *response,
283 const char *key) 283 const char *key)
284{ 284{
285 struct MHD_HTTP_Header *pos; 285 struct MHD_HTTP_Header *pos;
286 size_t key_size; 286 size_t key_size;
@@ -732,8 +732,8 @@ MHD_create_response_from_data (size_t size,
732 */ 732 */
733struct MHD_Response * 733struct MHD_Response *
734MHD_create_response_from_buffer (size_t size, 734MHD_create_response_from_buffer (size_t size,
735 void *buffer, 735 void *buffer,
736 enum MHD_ResponseMemoryMode mode) 736 enum MHD_ResponseMemoryMode mode)
737{ 737{
738 return MHD_create_response_from_data (size, 738 return MHD_create_response_from_data (size,
739 buffer, 739 buffer,
@@ -754,15 +754,15 @@ MHD_create_response_from_buffer (size_t size,
754 */ 754 */
755_MHD_EXTERN struct MHD_Response * 755_MHD_EXTERN struct MHD_Response *
756MHD_create_response_from_buffer_with_free_callback (size_t size, 756MHD_create_response_from_buffer_with_free_callback (size_t size,
757 void *buffer, 757 void *buffer,
758 MHD_ContentReaderFreeCallback crfc) 758 MHD_ContentReaderFreeCallback crfc)
759{ 759{
760 struct MHD_Response *r; 760 struct MHD_Response *r;
761 761
762 r = MHD_create_response_from_data (size, 762 r = MHD_create_response_from_data (size,
763 buffer, 763 buffer,
764 MHD_YES, 764 MHD_YES,
765 MHD_NO); 765 MHD_NO);
766 if (NULL == r) 766 if (NULL == r)
767 return r; 767 return r;
768 r->crfc = crfc; 768 r->crfc = crfc;
@@ -997,17 +997,17 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
997 EPOLL_CTL_ADD, 997 EPOLL_CTL_ADD,
998 connection->socket_fd, 998 connection->socket_fd,
999 &event)) 999 &event))
1000 { 1000 {
1001#ifdef HAVE_MESSAGES 1001#ifdef HAVE_MESSAGES
1002 MHD_DLOG (daemon, 1002 MHD_DLOG (daemon,
1003 _("Call to epoll_ctl failed: %s\n"), 1003 _("Call to epoll_ctl failed: %s\n"),
1004 MHD_socket_last_strerr_ ()); 1004 MHD_socket_last_strerr_ ());
1005#endif 1005#endif
1006 MHD_socket_close_chk_ (sv[0]); 1006 MHD_socket_close_chk_ (sv[0]);
1007 MHD_socket_close_chk_ (sv[1]); 1007 MHD_socket_close_chk_ (sv[1]);
1008 free (urh); 1008 free (urh);
1009 return MHD_NO; 1009 return MHD_NO;
1010 } 1010 }
1011 1011
1012 /* Second, add our end of the UNIX socketpair() */ 1012 /* Second, add our end of the UNIX socketpair() */
1013 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET; 1013 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
@@ -1016,28 +1016,28 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
1016 EPOLL_CTL_ADD, 1016 EPOLL_CTL_ADD,
1017 urh->mhd.socket, 1017 urh->mhd.socket,
1018 &event)) 1018 &event))
1019 { 1019 {
1020 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI; 1020 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
1021 event.data.ptr = &urh->app; 1021 event.data.ptr = &urh->app;
1022 if (0 != epoll_ctl (daemon->epoll_upgrade_fd, 1022 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1023 EPOLL_CTL_DEL, 1023 EPOLL_CTL_DEL,
1024 connection->socket_fd, 1024 connection->socket_fd,
1025 &event)) 1025 &event))
1026 MHD_PANIC (_("Error cleaning up while handling epoll error")); 1026 MHD_PANIC (_("Error cleaning up while handling epoll error"));
1027#ifdef HAVE_MESSAGES 1027#ifdef HAVE_MESSAGES
1028 MHD_DLOG (daemon, 1028 MHD_DLOG (daemon,
1029 _("Call to epoll_ctl failed: %s\n"), 1029 _("Call to epoll_ctl failed: %s\n"),
1030 MHD_socket_last_strerr_ ()); 1030 MHD_socket_last_strerr_ ());
1031#endif 1031#endif
1032 MHD_socket_close_chk_ (sv[0]); 1032 MHD_socket_close_chk_ (sv[0]);
1033 MHD_socket_close_chk_ (sv[1]); 1033 MHD_socket_close_chk_ (sv[1]);
1034 free (urh); 1034 free (urh);
1035 return MHD_NO; 1035 return MHD_NO;
1036 } 1036 }
1037 EDLL_insert (daemon->eready_urh_head, 1037 EDLL_insert (daemon->eready_urh_head,
1038 daemon->eready_urh_tail, 1038 daemon->eready_urh_tail,
1039 urh); 1039 urh);
1040 urh->in_eready_list = true; 1040 urh->in_eready_list = true;
1041 } 1041 }
1042#endif /* EPOLL_SUPPORT */ 1042#endif /* EPOLL_SUPPORT */
1043 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) ) 1043 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
diff --git a/src/microhttpd/test_upgrade_large.c b/src/microhttpd/test_upgrade_large.c
new file mode 100644
index 00000000..6f2a1b94
--- /dev/null
+++ b/src/microhttpd/test_upgrade_large.c
@@ -0,0 +1,1386 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2016, 2019 Christian Grothoff
4
5 libmicrohttpd is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libmicrohttpd is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libmicrohttpd; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file test_upgrade_large.c
23 * @brief Testcase for libmicrohttpd upgrading a connection,
24 * modified to test the "large" corner case reported
25 * by Viet on the mailinglist in 6'2019
26 * @author Christian Grothoff
27 * @author Karlson2k (Evgeny Grin)
28 */
29
30#include "mhd_options.h"
31#include <stdlib.h>
32#include <string.h>
33#include <stdio.h>
34#include <pthread.h>
35#include <stdlib.h>
36#include <stddef.h>
37#ifndef WINDOWS
38#include <unistd.h>
39#endif
40#ifdef HAVE_STDBOOL_H
41#include <stdbool.h>
42#endif /* HAVE_STDBOOL_H */
43
44#include "mhd_sockets.h"
45#ifdef HAVE_NETINET_IP_H
46#include <netinet/ip.h>
47#endif /* HAVE_NETINET_IP_H */
48
49#include "platform.h"
50#include "microhttpd.h"
51
52#include "test_helpers.h"
53
54#define LARGE_STRING "HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello"
55
56#define LARGE_REPLY_STRING "WorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorldWorld"
57
58#ifdef HTTPS_SUPPORT
59#include <gnutls/gnutls.h>
60#include "../testcurl/https/tls_test_keys.h"
61
62#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
63#include <sys/types.h>
64#include <sys/wait.h>
65#endif /* HAVE_FORK && HAVE_WAITPID */
66#endif /* HTTPS_SUPPORT */
67
68static int verbose = 0;
69
70static int kicker[2] = {-1, -1} ;
71
72enum tls_tool
73{
74 TLS_CLI_NO_TOOL = 0,
75 TLS_CLI_GNUTLS,
76 TLS_CLI_OPENSSL,
77 TLS_LIB_GNUTLS
78};
79
80enum tls_tool use_tls_tool;
81
82#if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID)
83/**
84 * Fork child that connects via GnuTLS-CLI to our @a port. Allows us to
85 * talk to our port over a socket in @a sp without having to worry
86 * about TLS.
87 *
88 * @param location where the socket is returned
89 * @return -1 on error, otherwise PID of TLS child process
90 */
91static pid_t
92gnutlscli_connect (int *sock,
93 uint16_t port)
94{
95 pid_t chld;
96 int sp[2];
97 char destination[30];
98
99 if (0 != socketpair (AF_UNIX,
100 SOCK_STREAM,
101 0,
102 sp))
103 return -1;
104 chld = fork ();
105 if (0 != chld)
106 {
107 *sock = sp[1];
108 MHD_socket_close_chk_ (sp[0]);
109 return chld;
110 }
111 MHD_socket_close_chk_ (sp[1]);
112 (void) close (0);
113 (void) close (1);
114 if (-1 == dup2 (sp[0], 0))
115 abort ();
116 if (-1 == dup2 (sp[0], 1))
117 abort ();
118 MHD_socket_close_chk_ (sp[0]);
119 if (TLS_CLI_GNUTLS == use_tls_tool)
120 {
121 snprintf (destination,
122 sizeof(destination),
123 "%u",
124 (unsigned int) port);
125 execlp ("gnutls-cli",
126 "gnutls-cli",
127 "--insecure",
128 "-p",
129 destination,
130 "127.0.0.1",
131 (char *) NULL);
132 }
133 else if (TLS_CLI_OPENSSL == use_tls_tool)
134 {
135 snprintf (destination,
136 sizeof(destination),
137 "127.0.0.1:%u",
138 (unsigned int) port);
139 execlp ("openssl",
140 "openssl",
141 "s_client",
142 "-connect",
143 destination,
144 "-verify",
145 "1",
146 (char *) NULL);
147 }
148 _exit (1);
149}
150#endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */
151
152
153/**
154 * Wrapper structure for plain&TLS sockets
155 */
156struct wr_socket
157{
158 /**
159 * Real network socket
160 */
161 MHD_socket fd;
162
163 /**
164 * Type of this socket
165 */
166 enum wr_type
167 {
168 wr_invalid = 0,
169 wr_plain = 1,
170 wr_tls = 2
171 } t;
172#ifdef HTTPS_SUPPORT
173 /**
174 * TLS credentials
175 */
176 gnutls_certificate_credentials_t tls_crd;
177
178 /**
179 * TLS session.
180 */
181 gnutls_session_t tls_s;
182
183 /**
184 * TLS handshake already succeed?
185 */
186 bool tls_connected;
187#endif
188};
189
190
191/**
192 * Get underlying real socket.
193 * @return FD of real socket
194 */
195#define wr_fd(s) ((s)->fd)
196
197
198/**
199 * Create wr_socket with plain TCP underlying socket
200 * @return created socket on success, NULL otherwise
201 */
202static struct wr_socket *
203wr_create_plain_sckt(void)
204{
205 struct wr_socket *s = malloc(sizeof(struct wr_socket));
206 if (NULL == s)
207 return NULL;
208 s->t = wr_plain;
209 s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
210 if (MHD_INVALID_SOCKET != s->fd)
211 return s;
212 free(s);
213 return NULL;
214}
215
216
217/**
218 * Create wr_socket with TLS TCP underlying socket
219 * @return created socket on success, NULL otherwise
220 */
221static struct wr_socket *
222wr_create_tls_sckt(void)
223{
224#ifdef HTTPS_SUPPORT
225 struct wr_socket *s = malloc(sizeof(struct wr_socket));
226 if (NULL == s)
227 return NULL;
228 s->t = wr_tls;
229 s->tls_connected = 0;
230 s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
231 if (MHD_INVALID_SOCKET != s->fd)
232 {
233 if (GNUTLS_E_SUCCESS == gnutls_init (&(s->tls_s), GNUTLS_CLIENT))
234 {
235 if (GNUTLS_E_SUCCESS == gnutls_set_default_priority (s->tls_s))
236 {
237 if (GNUTLS_E_SUCCESS == gnutls_certificate_allocate_credentials (&(s->tls_crd)))
238 {
239 if (GNUTLS_E_SUCCESS == gnutls_credentials_set (s->tls_s, GNUTLS_CRD_CERTIFICATE, s->tls_crd))
240 {
241#if GNUTLS_VERSION_NUMBER+0 >= 0x030109
242 gnutls_transport_set_int (s->tls_s, (int)(s->fd));
243#else /* GnuTLS before 3.1.9 */
244 gnutls_transport_set_ptr (s->tls_s, (gnutls_transport_ptr_t)(intptr_t)(s->fd));
245#endif /* GnuTLS before 3.1.9 */
246 return s;
247 }
248 gnutls_certificate_free_credentials (s->tls_crd);
249 }
250 }
251 gnutls_deinit (s->tls_s);
252 }
253 (void)MHD_socket_close_ (s->fd);
254 }
255 free(s);
256#endif /* HTTPS_SUPPORT */
257 return NULL;
258}
259
260
261/**
262 * Create wr_socket with plain TCP underlying socket
263 * from already created TCP socket.
264 * @param plain_sk real TCP socket
265 * @return created socket on success, NULL otherwise
266 */
267static struct wr_socket *
268wr_create_from_plain_sckt(MHD_socket plain_sk)
269{
270 struct wr_socket *s = malloc(sizeof(struct wr_socket));
271
272 if (NULL == s)
273 return NULL;
274 s->t = wr_plain;
275 s->fd = plain_sk;
276 return s;
277}
278
279
280/**
281 * Connect socket to specified address.
282 * @param s socket to use
283 * @param addr address to connect
284 * @param length of sturcture pointed by @a addr
285 * @return zero on success, -1 otherwise.
286 */
287static int
288wr_connect(struct wr_socket *s,
289 const struct sockaddr *addr,
290 int length)
291{
292 if (0 != connect (s->fd, addr, length))
293 return -1;
294 if (wr_plain == s->t)
295 return 0;
296#ifdef HTTPS_SUPPORT
297 if (wr_tls == s->t)
298 {
299 /* Do not try handshake here as
300 * it require processing on MHD side and
301 * when testing with "external" polling,
302 * test will call MHD processing only
303 * after return from wr_connect(). */
304 s->tls_connected = 0;
305 return 0;
306 }
307#endif /* HTTPS_SUPPORT */
308 return -1;
309}
310
311#ifdef HTTPS_SUPPORT
312/* Only to be called from wr_send() and wr_recv() ! */
313static bool
314wr_handshake(struct wr_socket *s)
315{
316 int res = gnutls_handshake (s->tls_s);
317 if (GNUTLS_E_SUCCESS == res)
318 s->tls_connected = true;
319 else if (GNUTLS_E_AGAIN == res)
320 MHD_socket_set_error_ (MHD_SCKT_EAGAIN_);
321 else
322 MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */
323 return s->tls_connected;
324}
325#endif /* HTTPS_SUPPORT */
326
327
328/**
329 * Send data to remote by socket.
330 * @param s the socket to use
331 * @param buf the buffer with data to send
332 * @param len the length of data in @a buf
333 * @return number of bytes were sent if succeed,
334 * -1 if failed. Use #MHD_socket_get_error_()
335 * to get socket error.
336 */
337static ssize_t
338wr_send (struct wr_socket *s,
339 const void *buf,
340 size_t len)
341{
342 if (wr_plain == s->t)
343 return MHD_send_(s->fd, buf, len);
344#ifdef HTTPS_SUPPORT
345 if (wr_tls == s->t)
346 {
347 ssize_t ret;
348 if (!s->tls_connected && !wr_handshake (s))
349 return -1;
350
351 ret = gnutls_record_send (s->tls_s, buf, len);
352 if (ret > 0)
353 return ret;
354 if (GNUTLS_E_AGAIN == ret)
355 MHD_socket_set_error_ (MHD_SCKT_EAGAIN_);
356 else
357 MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */
358 }
359#endif /* HTTPS_SUPPORT */
360 return -1;
361}
362
363
364/**
365 * Receive data from remote by socket.
366 * @param s the socket to use
367 * @param buf the buffer to store received data
368 * @param len the length of @a buf
369 * @return number of bytes were received if succeed,
370 * -1 if failed. Use #MHD_socket_get_error_()
371 * to get socket error.
372 */
373static ssize_t
374wr_recv (struct wr_socket *s,
375 void *buf,
376 size_t len)
377{
378 if (wr_plain == s->t)
379 return MHD_recv_ (s->fd, buf, len);
380#ifdef HTTPS_SUPPORT
381 if (wr_tls == s->t)
382 {
383 ssize_t ret;
384 if (!s->tls_connected && !wr_handshake (s))
385 return -1;
386
387 ret = gnutls_record_recv (s->tls_s, buf, len);
388 if (ret > 0)
389 return ret;
390 if (GNUTLS_E_AGAIN == ret)
391 MHD_socket_set_error_ (MHD_SCKT_EAGAIN_);
392 else
393 MHD_socket_set_error_ (MHD_SCKT_ECONNABORTED_); /* hard error */
394 }
395#endif /* HTTPS_SUPPORT */
396 return -1;
397}
398
399
400/**
401 * Close socket and release allocated resourced
402 * @param s the socket to close
403 * @return zero on succeed, -1 otherwise
404 */
405static int
406wr_close (struct wr_socket *s)
407{
408 int ret = (MHD_socket_close_(s->fd)) ? 0 : -1;
409#ifdef HTTPS_SUPPORT
410 if (wr_tls == s->t)
411 {
412 gnutls_deinit (s->tls_s);
413 gnutls_certificate_free_credentials (s->tls_crd);
414 }
415#endif /* HTTPS_SUPPORT */
416 free (s);
417 return ret;
418}
419
420
421/**
422 * Thread we use to run the interaction with the upgraded socket.
423 */
424static pthread_t pt;
425
426/**
427 * Will be set to the upgraded socket.
428 */
429static struct wr_socket *usock;
430
431/**
432 * Thread we use to run the interaction with the upgraded socket.
433 */
434static pthread_t pt_client;
435
436/**
437 * Flag set to 1 once the test is finished.
438 */
439static volatile bool done;
440
441
442/**
443 * Callback used by MHD to notify the application about completed
444 * requests. Frees memory.
445 *
446 * @param cls client-defined closure
447 * @param connection connection handle
448 * @param con_cls value as set by the last call to
449 * the #MHD_AccessHandlerCallback
450 * @param toe reason for request termination
451 */
452static void
453notify_completed_cb (void *cls,
454 struct MHD_Connection *connection,
455 void **con_cls,
456 enum MHD_RequestTerminationCode toe)
457{
458 pthread_t* ppth = *con_cls;
459
460 (void) cls;
461 (void) connection; /* Unused. Silent compiler warning. */
462 if ( (toe != MHD_REQUEST_TERMINATED_COMPLETED_OK) &&
463 (toe != MHD_REQUEST_TERMINATED_CLIENT_ABORT) &&
464 (toe != MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN) )
465 abort ();
466 if (! pthread_equal (**((pthread_t**)con_cls),
467 pthread_self ()))
468 abort ();
469 if (NULL != ppth)
470 free (*con_cls);
471 *con_cls = NULL;
472}
473
474
475/**
476 * Logging callback.
477 *
478 * @param cls logging closure (NULL)
479 * @param uri access URI
480 * @param connection connection handle
481 * @return #TEST_PTR
482 */
483static void *
484log_cb (void *cls,
485 const char *uri,
486 struct MHD_Connection *connection)
487{
488 pthread_t *ppth;
489
490 (void) cls;
491 (void) connection; /* Unused. Silent compiler warning. */
492 if (0 != strcmp (uri,
493 "/"))
494 abort ();
495 ppth = malloc (sizeof (pthread_t));
496 if (NULL == ppth)
497 abort();
498 *ppth = pthread_self ();
499 return (void *) ppth;
500}
501
502
503/**
504 * Function to check that MHD properly notifies about starting
505 * and stopping.
506 *
507 * @param cls client-defined closure
508 * @param connection connection handle
509 * @param socket_context socket-specific pointer where the
510 * client can associate some state specific
511 * to the TCP connection; note that this is
512 * different from the "con_cls" which is per
513 * HTTP request. The client can initialize
514 * during #MHD_CONNECTION_NOTIFY_STARTED and
515 * cleanup during #MHD_CONNECTION_NOTIFY_CLOSED
516 * and access in the meantime using
517 * #MHD_CONNECTION_INFO_SOCKET_CONTEXT.
518 * @param toe reason for connection notification
519 * @see #MHD_OPTION_NOTIFY_CONNECTION
520 * @ingroup request
521 */
522static void
523notify_connection_cb (void *cls,
524 struct MHD_Connection *connection,
525 void **socket_context,
526 enum MHD_ConnectionNotificationCode toe)
527{
528 static int started;
529
530 (void) cls;
531 (void) connection; /* Unused. Silent compiler warning. */
532 switch (toe)
533 {
534 case MHD_CONNECTION_NOTIFY_STARTED:
535 if (MHD_NO != started)
536 abort ();
537 started = MHD_YES;
538 *socket_context = &started;
539 break;
540 case MHD_CONNECTION_NOTIFY_CLOSED:
541 if (MHD_YES != started)
542 abort ();
543 if (&started != *socket_context)
544 abort ();
545 *socket_context = NULL;
546 started = MHD_NO;
547 break;
548 }
549}
550
551
552/**
553 * Change socket to blocking.
554 *
555 * @param fd the socket to manipulate
556 * @return non-zero if succeeded, zero otherwise
557 */
558static void
559make_blocking (MHD_socket fd)
560{
561#if defined(MHD_POSIX_SOCKETS)
562 int flags;
563
564 flags = fcntl (fd, F_GETFL);
565 if (-1 == flags)
566 return;
567 if ((flags & ~O_NONBLOCK) != flags)
568 if (-1 == fcntl (fd, F_SETFL, flags & ~O_NONBLOCK))
569 abort ();
570#elif defined(MHD_WINSOCK_SOCKETS)
571 unsigned long flags = 1;
572
573 ioctlsocket (fd, FIONBIO, &flags);
574#endif /* MHD_WINSOCK_SOCKETS */
575}
576
577
578static void
579kick_select ()
580{
581 if (-1 != kicker[1])
582 {
583 write (kicker[1], "K", 1);
584 fprintf (stderr, "KICKING\n");
585 }
586}
587
588
589static void
590send_all (struct wr_socket *sock,
591 const char *text)
592{
593 size_t len = strlen (text);
594 ssize_t ret;
595 size_t off;
596
597 make_blocking (wr_fd (sock));
598 for (off = 0; off < len; off += ret)
599 {
600 ret = wr_send (sock,
601 &text[off],
602 len - off);
603 kick_select ();
604 if (0 > ret)
605 {
606 if (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ()))
607 {
608 ret = 0;
609 continue;
610 }
611 abort ();
612 }
613 }
614}
615
616
617/**
618 * Read character-by-character until we
619 * get '\r\n\r\n'.
620 */
621static void
622recv_hdr (struct wr_socket *sock)
623{
624 unsigned int i;
625 char next;
626 char c;
627 ssize_t ret;
628
629 make_blocking (wr_fd (sock));
630 next = '\r';
631 i = 0;
632 while (i < 4)
633 {
634 ret = wr_recv (sock,
635 &c,
636 1);
637 kick_select ();
638 if (0 > ret)
639 {
640 if (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ()))
641 continue;
642 abort ();
643 }
644 if (0 == ret)
645 continue;
646 if (c == next)
647 {
648 i++;
649 if (next == '\r')
650 next = '\n';
651 else
652 next = '\r';
653 continue;
654 }
655 if (c == '\r')
656 {
657 i = 1;
658 next = '\n';
659 continue;
660 }
661 i = 0;
662 next = '\r';
663 }
664}
665
666
667static void
668recv_all (struct wr_socket *sock,
669 const char *text)
670{
671 size_t len = strlen (text);
672 char buf[len];
673 ssize_t ret;
674 size_t off;
675
676 make_blocking (wr_fd (sock));
677 for (off = 0; off < len; off += ret)
678 {
679 ret = wr_recv (sock,
680 &buf[off],
681 len - off);
682 if (0 > ret)
683 {
684 if (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ()))
685 {
686 ret = 0;
687 continue;
688 }
689 abort ();
690 }
691 }
692 if (0 != strncmp (text, buf, len))
693 abort();
694}
695
696
697/**
698 * Main function for the thread that runs the interaction with
699 * the upgraded socket.
700 *
701 * @param cls the handle for the upgrade
702 */
703static void *
704run_usock (void *cls)
705{
706 struct MHD_UpgradeResponseHandle *urh = cls;
707
708 send_all (usock,
709 LARGE_STRING);
710 recv_all (usock,
711 LARGE_REPLY_STRING);
712 send_all (usock,
713 "Finished");
714 MHD_upgrade_action (urh,
715 MHD_UPGRADE_ACTION_CLOSE);
716 free (usock);
717 usock = NULL;
718 return NULL;
719}
720
721
722/**
723 * Main function for the thread that runs the client-side of the
724 * interaction with the upgraded socket.
725 *
726 * @param cls the client socket
727 */
728static void *
729run_usock_client (void *cls)
730{
731 struct wr_socket *sock = cls;
732
733 send_all (sock,
734 "GET / HTTP/1.1\r\nConnection: Upgrade\r\n\r\n");
735 recv_hdr (sock);
736 recv_all (sock,
737 LARGE_STRING);
738 send_all (sock,
739 LARGE_REPLY_STRING);
740 recv_all (sock,
741 "Finished");
742 wr_close (sock);
743 done = true;
744 return NULL;
745}
746
747
748/**
749 * Function called after a protocol "upgrade" response was sent
750 * successfully and the socket should now be controlled by some
751 * protocol other than HTTP.
752 *
753 * Any data already received on the socket will be made available in
754 * @e extra_in. This can happen if the application sent extra data
755 * before MHD send the upgrade response. The application should
756 * treat data from @a extra_in as if it had read it from the socket.
757 *
758 * Note that the application must not close() @a sock directly,
759 * but instead use #MHD_upgrade_action() for special operations
760 * on @a sock.
761 *
762 * Except when in 'thread-per-connection' mode, implementations
763 * of this function should never block (as it will still be called
764 * from within the main event loop).
765 *
766 * @param cls closure, whatever was given to #MHD_create_response_for_upgrade().
767 * @param connection original HTTP connection handle,
768 * giving the function a last chance
769 * to inspect the original HTTP request
770 * @param con_cls last value left in `con_cls` of the `MHD_AccessHandlerCallback`
771 * @param extra_in if we happened to have read bytes after the
772 * HTTP header already (because the client sent
773 * more than the HTTP header of the request before
774 * we sent the upgrade response),
775 * these are the extra bytes already read from @a sock
776 * by MHD. The application should treat these as if
777 * it had read them from @a sock.
778 * @param extra_in_size number of bytes in @a extra_in
779 * @param sock socket to use for bi-directional communication
780 * with the client. For HTTPS, this may not be a socket
781 * that is directly connected to the client and thus certain
782 * operations (TCP-specific setsockopt(), getsockopt(), etc.)
783 * may not work as expected (as the socket could be from a
784 * socketpair() or a TCP-loopback). The application is expected
785 * to perform read()/recv() and write()/send() calls on the socket.
786 * The application may also call shutdown(), but must not call
787 * close() directly.
788 * @param urh argument for #MHD_upgrade_action()s on this @a connection.
789 * Applications must eventually use this callback to (indirectly)
790 * perform the close() action on the @a sock.
791 */
792static void
793upgrade_cb (void *cls,
794 struct MHD_Connection *connection,
795 void *con_cls,
796 const char *extra_in,
797 size_t extra_in_size,
798 MHD_socket sock,
799 struct MHD_UpgradeResponseHandle *urh)
800{
801 (void) cls;
802 (void) connection;
803 (void) con_cls;
804 (void) extra_in; /* Unused. Silent compiler warning. */
805
806 usock = wr_create_from_plain_sckt (sock);
807 if (0 != extra_in_size)
808 abort ();
809 if (0 != pthread_create (&pt,
810 NULL,
811 &run_usock,
812 urh))
813 abort ();
814}
815
816
817/**
818 * A client has requested the given url using the given method
819 * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT,
820 * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback
821 * must call MHD callbacks to provide content to give back to the
822 * client and return an HTTP status code (i.e. #MHD_HTTP_OK,
823 * #MHD_HTTP_NOT_FOUND, etc.).
824 *
825 * @param cls argument given together with the function
826 * pointer when the handler was registered with MHD
827 * @param url the requested url
828 * @param method the HTTP method used (#MHD_HTTP_METHOD_GET,
829 * #MHD_HTTP_METHOD_PUT, etc.)
830 * @param version the HTTP version string (i.e.
831 * #MHD_HTTP_VERSION_1_1)
832 * @param upload_data the data being uploaded (excluding HEADERS,
833 * for a POST that fits into memory and that is encoded
834 * with a supported encoding, the POST data will NOT be
835 * given in upload_data and is instead available as
836 * part of #MHD_get_connection_values; very large POST
837 * data *will* be made available incrementally in
838 * @a upload_data)
839 * @param upload_data_size set initially to the size of the
840 * @a upload_data provided; the method must update this
841 * value to the number of bytes NOT processed;
842 * @param con_cls pointer that the callback can set to some
843 * address and that will be preserved by MHD for future
844 * calls for this request; since the access handler may
845 * be called many times (i.e., for a PUT/POST operation
846 * with plenty of upload data) this allows the application
847 * to easily associate some request-specific state.
848 * If necessary, this state can be cleaned up in the
849 * global #MHD_RequestCompletedCallback (which
850 * can be set with the #MHD_OPTION_NOTIFY_COMPLETED).
851 * Initially, `*con_cls` will be NULL.
852 * @return #MHD_YES if the connection was handled successfully,
853 * #MHD_NO if the socket must be closed due to a serios
854 * error while handling the request
855 */
856static int
857ahc_upgrade (void *cls,
858 struct MHD_Connection *connection,
859 const char *url,
860 const char *method,
861 const char *version,
862 const char *upload_data,
863 size_t *upload_data_size,
864 void **con_cls)
865{
866 struct MHD_Response *resp;
867 int ret;
868 (void) cls;
869 (void) url;
870 (void) method; /* Unused. Silent compiler warning. */
871 (void) version;
872 (void) upload_data;
873 (void) upload_data_size; /* Unused. Silent compiler warning. */
874
875 if (NULL == *con_cls)
876 abort ();
877 if (! pthread_equal (**((pthread_t**)con_cls), pthread_self ()))
878 abort ();
879 resp = MHD_create_response_for_upgrade (&upgrade_cb,
880 NULL);
881 MHD_add_response_header (resp,
882 MHD_HTTP_HEADER_UPGRADE,
883 "Hello World Protocol");
884 ret = MHD_queue_response (connection,
885 MHD_HTTP_SWITCHING_PROTOCOLS,
886 resp);
887 MHD_destroy_response (resp);
888 return ret;
889}
890
891
892/**
893 * Run the MHD external event loop using select.
894 *
895 * @param daemon daemon to run it for
896 */
897static void
898run_mhd_select_loop (struct MHD_Daemon *daemon)
899{
900 fd_set rs;
901 fd_set ws;
902 fd_set es;
903 MHD_socket max_fd;
904 MHD_UNSIGNED_LONG_LONG to;
905 struct timeval tv;
906 char drain[128];
907
908 if (0 != pipe (kicker))
909 abort ();
910 while (! done)
911 {
912 FD_ZERO (&rs);
913 FD_ZERO (&ws);
914 FD_ZERO (&es);
915 max_fd = -1;
916 to = 1000;
917
918 FD_SET (kicker[0], &rs);
919 if (MHD_YES !=
920 MHD_get_fdset (daemon,
921 &rs,
922 &ws,
923 &es,
924 &max_fd))
925 abort ();
926 (void) MHD_get_timeout (daemon,
927 &to);
928 if (1000 < to)
929 to = 1000;
930 tv.tv_sec = to / 1000;
931 tv.tv_usec = 1000 * (to % 1000);
932 if (0 > MHD_SYS_select_ (max_fd + 1,
933 &rs,
934 &ws,
935 &es,
936 &tv))
937 abort ();
938 if (FD_ISSET (kicker[0], &rs))
939 (void) read (kicker[0], drain, sizeof (drain));
940 MHD_run_from_select (daemon,
941 &rs,
942 &ws,
943 &es);
944 }
945 close (kicker[0]);
946 close (kicker[1]);
947 kicker[0] = -1;
948 kicker[1] = -1;
949}
950
951#ifdef HAVE_POLL
952
953/**
954 * Run the MHD external event loop using select.
955 *
956 * @param daemon daemon to run it for
957 */
958static void
959run_mhd_poll_loop (struct MHD_Daemon *daemon)
960{
961 (void)daemon; /* Unused. Silent compiler warning. */
962 abort (); /* currently not implementable with existing MHD API */
963}
964#endif /* HAVE_POLL */
965
966
967#ifdef EPOLL_SUPPORT
968/**
969 * Run the MHD external event loop using select.
970 *
971 * @param daemon daemon to run it for
972 */
973static void
974run_mhd_epoll_loop (struct MHD_Daemon *daemon)
975{
976 const union MHD_DaemonInfo *di;
977 MHD_socket ep;
978 fd_set rs;
979 MHD_UNSIGNED_LONG_LONG to;
980 struct timeval tv;
981 int ret;
982 char drain[128];
983
984 di = MHD_get_daemon_info (daemon,
985 MHD_DAEMON_INFO_EPOLL_FD);
986 ep = di->listen_fd;
987 if (0 != pipe (kicker))
988 abort ();
989 while (! done)
990 {
991 FD_ZERO (&rs);
992 to = 1000;
993 FD_SET (kicker[0], &rs);
994 FD_SET (ep, &rs);
995 (void) MHD_get_timeout (daemon,
996 &to);
997 if (1000 < to)
998 to = 1000;
999 tv.tv_sec = to / 1000;
1000 tv.tv_usec = 1000 * (to % 1000);
1001 ret = select (ep + 1,
1002 &rs,
1003 NULL,
1004 NULL,
1005 &tv);
1006 if ( (-1 == ret) &&
1007 (EAGAIN != errno) &&
1008 (EINTR != errno) )
1009 abort ();
1010 if (FD_ISSET (kicker[0], &rs))
1011 (void) read (kicker[0], drain, sizeof (drain));
1012 MHD_run (daemon);
1013 }
1014 close (kicker[0]);
1015 close (kicker[1]);
1016 kicker[0] = -1;
1017 kicker[1] = -1;
1018}
1019#endif /* EPOLL_SUPPORT */
1020
1021/**
1022 * Run the MHD external event loop using select.
1023 *
1024 * @param daemon daemon to run it for
1025 */
1026static void
1027run_mhd_loop (struct MHD_Daemon *daemon,
1028 int flags)
1029{
1030 if (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL)))
1031 run_mhd_select_loop (daemon);
1032#ifdef HAVE_POLL
1033 else if (0 != (flags & MHD_USE_POLL))
1034 run_mhd_poll_loop (daemon);
1035#endif /* HAVE_POLL */
1036#if EPOLL_SUPPORT
1037 else if (0 != (flags & MHD_USE_EPOLL))
1038 run_mhd_epoll_loop (daemon);
1039#endif
1040 else
1041 abort ();
1042}
1043
1044
1045static bool test_tls;
1046
1047/**
1048 * Test upgrading a connection.
1049 *
1050 * @param flags which event loop style should be tested
1051 * @param pool size of the thread pool, 0 to disable
1052 */
1053static int
1054test_upgrade (int flags,
1055 unsigned int pool)
1056{
1057 struct MHD_Daemon *d = NULL;
1058 struct wr_socket *sock;
1059 struct sockaddr_in sa;
1060 const union MHD_DaemonInfo *real_flags;
1061 const union MHD_DaemonInfo *dinfo;
1062#if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID)
1063 pid_t pid = -1;
1064#endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */
1065
1066 done = false;
1067
1068 if (! test_tls)
1069 d = MHD_start_daemon (flags | MHD_USE_ERROR_LOG | MHD_ALLOW_UPGRADE,
1070 MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT) ?
1071 0 : 1090,
1072 NULL, NULL,
1073 &ahc_upgrade, NULL,
1074 MHD_OPTION_CONNECTION_MEMORY_LIMIT, 512,
1075 MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL,
1076 MHD_OPTION_NOTIFY_COMPLETED, &notify_completed_cb, NULL,
1077 MHD_OPTION_NOTIFY_CONNECTION, &notify_connection_cb, NULL,
1078 MHD_OPTION_THREAD_POOL_SIZE, pool,
1079 MHD_OPTION_END);
1080#ifdef HTTPS_SUPPORT
1081 else
1082 d = MHD_start_daemon (flags | MHD_USE_ERROR_LOG | MHD_ALLOW_UPGRADE | MHD_USE_TLS,
1083 MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT) ?
1084 0 : 1090,
1085 NULL, NULL,
1086 &ahc_upgrade, NULL,
1087 MHD_OPTION_CONNECTION_MEMORY_LIMIT, 512,
1088 MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL,
1089 MHD_OPTION_NOTIFY_COMPLETED, &notify_completed_cb, NULL,
1090 MHD_OPTION_NOTIFY_CONNECTION, &notify_connection_cb, NULL,
1091 MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
1092 MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
1093 MHD_OPTION_THREAD_POOL_SIZE, pool,
1094 MHD_OPTION_END);
1095#endif /* HTTPS_SUPPORT */
1096 if (NULL == d)
1097 return 2;
1098 real_flags = MHD_get_daemon_info (d,
1099 MHD_DAEMON_INFO_FLAGS);
1100 if (NULL == real_flags)
1101 abort ();
1102 dinfo = MHD_get_daemon_info (d,
1103 MHD_DAEMON_INFO_BIND_PORT);
1104 if ( (NULL == dinfo) ||
1105 (0 == dinfo->port) )
1106 abort ();
1107 if (!test_tls || TLS_LIB_GNUTLS == use_tls_tool)
1108 {
1109 sock = test_tls ? wr_create_tls_sckt () : wr_create_plain_sckt ();
1110 if (NULL == sock)
1111 abort ();
1112 sa.sin_family = AF_INET;
1113 sa.sin_port = htons (dinfo->port);
1114 sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
1115 if (0 != wr_connect (sock,
1116 (struct sockaddr *) &sa,
1117 sizeof (sa)))
1118 abort ();
1119 }
1120 else
1121 {
1122#if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID)
1123 MHD_socket tls_fork_sock;
1124 uint16_t port;
1125
1126 /* make address sanitizer happy */
1127 memcpy (&port,
1128 dinfo /* ->port */,
1129 sizeof (port));
1130 if (-1 == (pid = gnutlscli_connect (&tls_fork_sock,
1131 port)))
1132 {
1133 MHD_stop_daemon (d);
1134 return 4;
1135 }
1136
1137 sock = wr_create_from_plain_sckt (tls_fork_sock);
1138 if (NULL == sock)
1139 abort ();
1140#else /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */
1141 abort ();
1142#endif /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */
1143 }
1144
1145 if (0 != pthread_create (&pt_client,
1146 NULL,
1147 &run_usock_client,
1148 sock))
1149 abort ();
1150 if (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD) )
1151 {
1152 enum MHD_FLAG flags;
1153
1154 /* make address sanitizer happy */
1155 memcpy (&flags,
1156 real_flags /* ->flags */,
1157 sizeof (flags));
1158 run_mhd_loop (d, flags);
1159 }
1160 pthread_join (pt_client,
1161 NULL);
1162 pthread_join (pt,
1163 NULL);
1164#if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID)
1165 if (test_tls && TLS_LIB_GNUTLS != use_tls_tool)
1166 waitpid (pid, NULL, 0);
1167#endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */
1168 MHD_stop_daemon (d);
1169 return 0;
1170}
1171
1172
1173int
1174main (int argc,
1175 char *const *argv)
1176{
1177 int error_count = 0;
1178 int res;
1179
1180 use_tls_tool = TLS_CLI_NO_TOOL;
1181 test_tls = has_in_name(argv[0], "_tls");
1182
1183 verbose = 1;
1184 if (has_param(argc, argv, "-q") ||
1185 has_param(argc, argv, "--quiet"))
1186 verbose = 0;
1187
1188 if (test_tls)
1189 {
1190#ifdef HTTPS_SUPPORT
1191 if (has_param(argc, argv, "--use-gnutls-cli"))
1192 use_tls_tool = TLS_CLI_GNUTLS;
1193 else if (has_param(argc, argv, "--use-openssl"))
1194 use_tls_tool = TLS_CLI_OPENSSL;
1195 else if (has_param(argc, argv, "--use-gnutls-lib"))
1196 use_tls_tool = TLS_LIB_GNUTLS;
1197#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
1198 else if (0 == system ("gnutls-cli --version 1> /dev/null 2> /dev/null"))
1199 use_tls_tool = TLS_CLI_GNUTLS;
1200 else if (0 == system ("openssl version 1> /dev/null 2> /dev/null"))
1201 use_tls_tool = TLS_CLI_OPENSSL;
1202#endif /* HAVE_FORK && HAVE_WAITPID */
1203 else
1204 use_tls_tool = TLS_LIB_GNUTLS; /* Should be available as MHD use it. */
1205 if (verbose)
1206 {
1207 switch (use_tls_tool)
1208 {
1209 case TLS_CLI_GNUTLS:
1210 printf ("GnuTLS-CLI will be used for testing.\n");
1211 break;
1212 case TLS_CLI_OPENSSL:
1213 printf ("Command line version of OpenSSL will be used for testing.\n");
1214 break;
1215 case TLS_LIB_GNUTLS:
1216 printf ("GnuTLS library will be used for testing.\n");
1217 break;
1218 default:
1219 abort ();
1220 }
1221 }
1222 if ( (TLS_LIB_GNUTLS == use_tls_tool) &&
1223 (GNUTLS_E_SUCCESS != gnutls_global_init()) )
1224 abort ();
1225
1226#else /* ! HTTPS_SUPPORT */
1227 fprintf (stderr, "HTTPS support was disabled by configure.\n");
1228 return 77;
1229#endif /* ! HTTPS_SUPPORT */
1230 }
1231
1232 /* run tests */
1233 if (verbose)
1234 printf ("Starting HTTP \"Upgrade\" tests with %s connections.\n",
1235 test_tls ? "TLS" : "plain");
1236 /* try external select */
1237 res = test_upgrade (0,
1238 0);
1239 error_count += res;
1240 if (res)
1241 fprintf (stderr,
1242 "FAILED: Upgrade with external select, return code %d.\n",
1243 res);
1244 else if (verbose)
1245 printf ("PASSED: Upgrade with external select.\n");
1246
1247 /* Try external auto */
1248 res = test_upgrade (MHD_USE_AUTO,
1249 0);
1250 error_count += res;
1251 if (res)
1252 fprintf (stderr,
1253 "FAILED: Upgrade with external 'auto', return code %d.\n",
1254 res);
1255 else if (verbose)
1256 printf ("PASSED: Upgrade with external 'auto'.\n");
1257
1258#ifdef EPOLL_SUPPORT
1259 res = test_upgrade (MHD_USE_EPOLL,
1260 0);
1261 error_count += res;
1262 if (res)
1263 fprintf (stderr,
1264 "FAILED: Upgrade with external select with EPOLL, return code %d.\n",
1265 res);
1266 else if (verbose)
1267 printf ("PASSED: Upgrade with external select with EPOLL.\n");
1268#endif
1269
1270 /* Test thread-per-connection */
1271 res = test_upgrade (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION,
1272 0);
1273 error_count += res;
1274 if (res)
1275 fprintf (stderr,
1276 "FAILED: Upgrade with thread per connection, return code %d.\n",
1277 res);
1278 else if (verbose)
1279 printf ("PASSED: Upgrade with thread per connection.\n");
1280
1281 res = test_upgrade (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION,
1282 0);
1283 error_count += res;
1284 if (res)
1285 fprintf (stderr,
1286 "FAILED: Upgrade with thread per connection and 'auto', return code %d.\n",
1287 res);
1288 else if (verbose)
1289 printf ("PASSED: Upgrade with thread per connection and 'auto'.\n");
1290#ifdef HAVE_POLL
1291 res = test_upgrade (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION | MHD_USE_POLL,
1292 0);
1293 error_count += res;
1294 if (res)
1295 fprintf (stderr,
1296 "FAILED: Upgrade with thread per connection and poll, return code %d.\n",
1297 res);
1298 else if (verbose)
1299 printf ("PASSED: Upgrade with thread per connection and poll.\n");
1300#endif /* HAVE_POLL */
1301
1302 /* Test different event loops, with and without thread pool */
1303 res = test_upgrade (MHD_USE_INTERNAL_POLLING_THREAD,
1304 0);
1305 error_count += res;
1306 if (res)
1307 fprintf (stderr,
1308 "FAILED: Upgrade with internal select, return code %d.\n",
1309 res);
1310 else if (verbose)
1311 printf ("PASSED: Upgrade with internal select.\n");
1312 res = test_upgrade (MHD_USE_INTERNAL_POLLING_THREAD,
1313 2);
1314 error_count += res;
1315 if (res)
1316 fprintf (stderr,
1317 "FAILED: Upgrade with internal select with thread pool, return code %d.\n",
1318 res);
1319 else if (verbose)
1320 printf ("PASSED: Upgrade with internal select with thread pool.\n");
1321 res = test_upgrade (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD,
1322 0);
1323 error_count += res;
1324 if (res)
1325 fprintf (stderr,
1326 "FAILED: Upgrade with internal 'auto' return code %d.\n",
1327 res);
1328 else if (verbose)
1329 printf ("PASSED: Upgrade with internal 'auto'.\n");
1330 res = test_upgrade (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD,
1331 2);
1332 error_count += res;
1333 if (res)
1334 fprintf (stderr,
1335 "FAILED: Upgrade with internal 'auto' with thread pool, return code %d.\n",
1336 res);
1337 else if (verbose)
1338 printf ("PASSED: Upgrade with internal 'auto' with thread pool.\n");
1339#ifdef HAVE_POLL
1340 res = test_upgrade (MHD_USE_POLL_INTERNAL_THREAD,
1341 0);
1342 error_count += res;
1343 if (res)
1344 fprintf (stderr,
1345 "FAILED: Upgrade with internal poll, return code %d.\n",
1346 res);
1347 else if (verbose)
1348 printf ("PASSED: Upgrade with internal poll.\n");
1349 res = test_upgrade (MHD_USE_POLL_INTERNAL_THREAD,
1350 2);
1351 if (res)
1352 fprintf (stderr,
1353 "FAILED: Upgrade with internal poll with thread pool, return code %d.\n",
1354 res);
1355 else if (verbose)
1356 printf ("PASSED: Upgrade with internal poll with thread pool.\n");
1357#endif
1358#ifdef EPOLL_SUPPORT
1359 res = test_upgrade (MHD_USE_EPOLL_INTERNAL_THREAD,
1360 0);
1361 if (res)
1362 fprintf (stderr,
1363 "FAILED: Upgrade with internal epoll, return code %d.\n",
1364 res);
1365 else if (verbose)
1366 printf ("PASSED: Upgrade with internal epoll.\n");
1367 res = test_upgrade (MHD_USE_EPOLL_INTERNAL_THREAD,
1368 2);
1369 if (res)
1370 fprintf (stderr,
1371 "FAILED: Upgrade with internal epoll, return code %d.\n",
1372 res);
1373 else if (verbose)
1374 printf ("PASSED: Upgrade with internal epoll.\n");
1375#endif
1376 /* report result */
1377 if (0 != error_count)
1378 fprintf (stderr,
1379 "Error (code: %u)\n",
1380 error_count);
1381#ifdef HTTPS_SUPPORT
1382 if (test_tls && (TLS_LIB_GNUTLS == use_tls_tool))
1383 gnutls_global_deinit();
1384#endif /* HTTPS_SUPPORT */
1385 return error_count != 0; /* 0 == pass */
1386}