diff options
author | ng0 <ng0@n0.is> | 2019-08-01 14:28:34 +0000 |
---|---|---|
committer | ng0 <ng0@n0.is> | 2019-08-01 14:28:34 +0000 |
commit | 8ad5fab2e8173476b78c3fda9a416540b925cd0f (patch) | |
tree | 511af471e5c12c749792228281fcecb9e510e78f | |
parent | 9edfc8f8f7a548e0dad8f3d18f671b822601a384 (diff) | |
parent | 91826f50011e76014dc307e370e6b1f45b2df151 (diff) | |
download | libmicrohttpd-8ad5fab2e8173476b78c3fda9a416540b925cd0f.tar.gz libmicrohttpd-8ad5fab2e8173476b78c3fda9a416540b925cd0f.zip |
Merge remote-tracking branch 'origin/master' into dev/ng0/gsoc2019
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | doc/libmicrohttpd.texi | 2 | ||||
-rw-r--r-- | po/libmicrohttpd.pot | 297 | ||||
-rw-r--r-- | src/include/microhttpd.h | 2 | ||||
-rw-r--r-- | src/microhttpd/.gitignore | 2 | ||||
-rw-r--r-- | src/microhttpd/Makefile.am | 34 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 30 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 310 | ||||
-rw-r--r-- | src/microhttpd/response.c | 80 | ||||
-rw-r--r-- | src/microhttpd/test_upgrade_large.c | 1386 |
11 files changed, 1811 insertions, 361 deletions
@@ -1,6 +1,23 @@ | |||
1 | Thu 01 Aug 2019 01:23:36 PM CEST | ||
2 | Releasing libmicrohttpd 0.9.66. -CG | ||
3 | |||
4 | Thu 01 Aug 2019 12:53:49 AM CEST | ||
5 | Fix issue with discarding unhandled upload data discovered | ||
6 | by Florian Dold. -CG | ||
7 | |||
8 | Mon 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 | |||
13 | Thu 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 | |||
1 | Tue Jul 16 19:56:14 CEST 2019 | 18 | Tue 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 | ||
5 | Fri Jul 05 2019 22:30:40 MSK | 22 | Fri 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 | ||
103 | Fri Apr 19 23:00:00 MSK 2019 | 120 | Fri 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 | # |
23 | AC_PREREQ([2.64]) | 23 | AC_PREREQ([2.64]) |
24 | LT_PREREQ([2.4.0]) | 24 | LT_PREREQ([2.4.0]) |
25 | AC_INIT([GNU Libmicrohttpd],[0.9.65],[libmicrohttpd@gnu.org]) | 25 | AC_INIT([GNU Libmicrohttpd],[0.9.66],[libmicrohttpd@gnu.org]) |
26 | AC_CONFIG_AUX_DIR([build-aux]) | 26 | AC_CONFIG_AUX_DIR([build-aux]) |
27 | AM_INIT_AUTOMAKE([silent-rules] [subdir-objects]) | 27 | AM_INIT_AUTOMAKE([silent-rules] [subdir-objects]) |
28 | AC_CONFIG_HEADERS([MHD_config.h]) | 28 | AC_CONFIG_HEADERS([MHD_config.h]) |
29 | AC_CONFIG_MACRO_DIR([m4]) | 29 | AC_CONFIG_MACRO_DIR([m4]) |
30 | 30 | ||
31 | LIB_VERSION_CURRENT=64 | 31 | LIB_VERSION_CURRENT=65 |
32 | LIB_VERSION_REVISION=0 | 32 | LIB_VERSION_REVISION=0 |
33 | LIB_VERSION_AGE=52 | 33 | LIB_VERSION_AGE=53 |
34 | AC_SUBST(LIB_VERSION_CURRENT) | 34 | AC_SUBST(LIB_VERSION_CURRENT) |
35 | AC_SUBST(LIB_VERSION_REVISION) | 35 | AC_SUBST(LIB_VERSION_REVISION) |
36 | AC_SUBST(LIB_VERSION_AGE) | 36 | AC_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 |
13 | an HTTP(S) server into C applications. | 13 | an HTTP(S) server into C applications. |
14 | 14 | ||
15 | Copyright @copyright{} 2007--2017 Christian Grothoff | 15 | Copyright @copyright{} 2007--2019 Christian Grothoff |
16 | 16 | ||
17 | @quotation | 17 | @quotation |
18 | Permission is granted to copy, distribute and/or modify this document | 18 | Permission 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 |
7 | msgid "" | 7 | msgid "" |
8 | msgstr "" | 8 | msgstr "" |
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 "" | |||
104 | msgid "Previously-added IP address had counter of zero\n" | 104 | msgid "Previously-added IP address had counter of zero\n" |
105 | msgstr "" | 105 | msgstr "" |
106 | 106 | ||
107 | #: src/microhttpd/daemon.c:614 | 107 | #: src/microhttpd/daemon.c:622 |
108 | msgid "" | 108 | msgid "" |
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" |
111 | msgstr "" | 111 | msgstr "" |
112 | 112 | ||
113 | #: src/microhttpd/daemon.c:668 | 113 | #: src/microhttpd/daemon.c:680 |
114 | #, c-format | 114 | #, c-format |
115 | msgid "Error: invalid credentials type %d specified.\n" | 115 | msgid "Error: invalid credentials type %d specified.\n" |
116 | msgstr "" | 116 | msgstr "" |
117 | 117 | ||
118 | #: src/microhttpd/daemon.c:1067 | 118 | #: src/microhttpd/daemon.c:1079 |
119 | #, c-format | 119 | #, c-format |
120 | msgid "Maximum socket in select set: %d\n" | 120 | msgid "Maximum socket in select set: %d\n" |
121 | msgstr "" | 121 | msgstr "" |
122 | 122 | ||
123 | #: src/microhttpd/daemon.c:1128 | 123 | #: src/microhttpd/daemon.c:1140 |
124 | msgid "" | 124 | msgid "" |
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" |
127 | msgstr "" | 127 | msgstr "" |
128 | 128 | ||
129 | #: src/microhttpd/daemon.c:1334 src/microhttpd/daemon.c:6573 | 129 | #: src/microhttpd/daemon.c:1346 src/microhttpd/daemon.c:6611 |
130 | msgid "" | 130 | msgid "" |
131 | "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n" | 131 | "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n" |
132 | msgstr "" | 132 | msgstr "" |
133 | 133 | ||
134 | #: src/microhttpd/daemon.c:1348 src/microhttpd/daemon.c:1583 | 134 | #: src/microhttpd/daemon.c:1360 src/microhttpd/daemon.c:1595 |
135 | msgid "Failed to forward to application " | 135 | msgid "Failed to forward to application " |
136 | msgstr "" | 136 | msgstr "" |
137 | 137 | ||
138 | #: src/microhttpd/daemon.c:1515 src/microhttpd/daemon.c:1637 | 138 | #: src/microhttpd/daemon.c:1527 src/microhttpd/daemon.c:1649 |
139 | msgid "Failed to forward to remote client " | 139 | msgid "Failed to forward to remote client " |
140 | msgstr "" | 140 | msgstr "" |
141 | 141 | ||
142 | #: src/microhttpd/daemon.c:1702 | 142 | #: src/microhttpd/daemon.c:1714 |
143 | msgid "Error preparing select\n" | 143 | msgid "Error preparing select\n" |
144 | msgstr "" | 144 | msgstr "" |
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 |
149 | msgid "Error during select (%d): `%s'\n" | 149 | msgid "Error during select (%d): `%s'\n" |
150 | msgstr "" | 150 | msgstr "" |
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 |
155 | msgid "Error during poll: `%s'\n" | 155 | msgid "Error during poll: `%s'\n" |
156 | msgstr "" | 156 | msgstr "" |
157 | 157 | ||
158 | #: src/microhttpd/daemon.c:1872 src/microhttpd/daemon.c:2014 | 158 | #: src/microhttpd/daemon.c:1884 src/microhttpd/daemon.c:2026 |
159 | msgid "Failed to add FD to fd_set\n" | 159 | msgid "Failed to add FD to fd_set\n" |
160 | msgstr "" | 160 | msgstr "" |
161 | 161 | ||
162 | #: src/microhttpd/daemon.c:2153 | 162 | #: src/microhttpd/daemon.c:2165 |
163 | msgid "Processing thread terminating. Closing connection\n" | 163 | msgid "Processing thread terminating. Closing connection\n" |
164 | msgstr "" | 164 | msgstr "" |
165 | 165 | ||
166 | #: src/microhttpd/daemon.c:2182 | 166 | #: src/microhttpd/daemon.c:2194 |
167 | msgid "" | 167 | msgid "" |
168 | "Failed to signal thread termination via inter-thread communication channel." | 168 | "Failed to signal thread termination via inter-thread communication channel." |
169 | msgstr "" | 169 | msgstr "" |
170 | 170 | ||
171 | #: src/microhttpd/daemon.c:2253 | 171 | #: src/microhttpd/daemon.c:2265 |
172 | msgid "Internal server error. This should be impossible.\n" | 172 | msgid "Internal server error. This should be impossible.\n" |
173 | msgstr "" | 173 | msgstr "" |
174 | 174 | ||
175 | #: src/microhttpd/daemon.c:2263 src/microhttpd/daemon.c:2300 | 175 | #: src/microhttpd/daemon.c:2275 src/microhttpd/daemon.c:2312 |
176 | msgid "PSK not supported by this server.\n" | 176 | msgid "PSK not supported by this server.\n" |
177 | msgstr "" | 177 | msgstr "" |
178 | 178 | ||
179 | #: src/microhttpd/daemon.c:2277 | 179 | #: src/microhttpd/daemon.c:2289 |
180 | msgid "PSK authentication failed: gnutls_malloc failed to allocate memory\n" | 180 | msgid "PSK authentication failed: gnutls_malloc failed to allocate memory\n" |
181 | msgstr "" | 181 | msgstr "" |
182 | 182 | ||
183 | #: src/microhttpd/daemon.c:2286 | 183 | #: src/microhttpd/daemon.c:2298 |
184 | msgid "PSK authentication failed: PSK too long\n" | 184 | msgid "PSK authentication failed: PSK too long\n" |
185 | msgstr "" | 185 | msgstr "" |
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 |
189 | msgid "Socket descriptor larger than FD_SETSIZE: %d > %d\n" | 189 | msgid "Socket descriptor larger than FD_SETSIZE: %d > %d\n" |
190 | msgstr "" | 190 | msgstr "" |
191 | 191 | ||
192 | #: src/microhttpd/daemon.c:2398 | 192 | #: src/microhttpd/daemon.c:2410 |
193 | #, c-format | 193 | #, c-format |
194 | msgid "Failed to set SO_NOSIGPIPE on accepted socket: %s\n" | 194 | msgid "Failed to set SO_NOSIGPIPE on accepted socket: %s\n" |
195 | msgstr "" | 195 | msgstr "" |
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 |
199 | msgid "Accepted connection on socket %d\n" | 199 | msgid "Accepted connection on socket %d\n" |
200 | msgstr "" | 200 | msgstr "" |
201 | 201 | ||
202 | #: src/microhttpd/daemon.c:2427 src/microhttpd/daemon.c:2617 | 202 | #: src/microhttpd/daemon.c:2439 src/microhttpd/daemon.c:2629 |
203 | msgid "Server reached connection limit. Closing inbound connection.\n" | 203 | msgid "Server reached connection limit. Closing inbound connection.\n" |
204 | msgstr "" | 204 | msgstr "" |
205 | 205 | ||
206 | #: src/microhttpd/daemon.c:2445 | 206 | #: src/microhttpd/daemon.c:2457 |
207 | msgid "Connection rejected by application. Closing connection.\n" | 207 | msgid "Connection rejected by application. Closing connection.\n" |
208 | msgstr "" | 208 | msgstr "" |
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 |
213 | msgid "Error allocating memory: %s\n" | 213 | msgid "Error allocating memory: %s\n" |
214 | msgstr "" | 214 | msgstr "" |
215 | 215 | ||
216 | #: src/microhttpd/daemon.c:2570 | 216 | #: src/microhttpd/daemon.c:2582 |
217 | #, c-format | 217 | #, c-format |
218 | msgid "Failed to setup TLS credentials: unknown credential type %d\n" | 218 | msgid "Failed to setup TLS credentials: unknown credential type %d\n" |
219 | msgstr "" | 219 | msgstr "" |
220 | 220 | ||
221 | #: src/microhttpd/daemon.c:2579 | 221 | #: src/microhttpd/daemon.c:2591 |
222 | msgid "Unknown credential type" | 222 | msgid "Unknown credential type" |
223 | msgstr "" | 223 | msgstr "" |
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 |
230 | msgid "Call to epoll_ctl failed: %s\n" | 230 | msgid "Call to epoll_ctl failed: %s\n" |
231 | msgstr "" | 231 | msgstr "" |
232 | 232 | ||
233 | #: src/microhttpd/daemon.c:2706 | 233 | #: src/microhttpd/daemon.c:2718 |
234 | msgid "Failed to signal new connection via inter-thread communication channel." | 234 | msgid "Failed to signal new connection via inter-thread communication channel." |
235 | msgstr "" | 235 | msgstr "" |
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 |
240 | msgid "Failed to remove FD from epoll set\n" | 240 | msgid "Failed to remove FD from epoll set\n" |
241 | msgstr "" | 241 | msgstr "" |
242 | 242 | ||
243 | #: src/microhttpd/daemon.c:2860 | 243 | #: src/microhttpd/daemon.c:2872 |
244 | msgid "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n" | 244 | msgid "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n" |
245 | msgstr "" | 245 | msgstr "" |
246 | 246 | ||
247 | #: src/microhttpd/daemon.c:2866 | 247 | #: src/microhttpd/daemon.c:2878 |
248 | msgid "Error: connection scheduled for \"upgrade\" cannot be suspended" | 248 | msgid "Error: connection scheduled for \"upgrade\" cannot be suspended" |
249 | msgstr "" | 249 | msgstr "" |
250 | 250 | ||
251 | #: src/microhttpd/daemon.c:2889 | 251 | #: src/microhttpd/daemon.c:2901 |
252 | msgid "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n" | 252 | msgid "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n" |
253 | msgstr "" | 253 | msgstr "" |
254 | 254 | ||
255 | #: src/microhttpd/daemon.c:2903 | 255 | #: src/microhttpd/daemon.c:2915 |
256 | msgid "Failed to signal resume via inter-thread communication channel." | 256 | msgid "Failed to signal resume via inter-thread communication channel." |
257 | msgstr "" | 257 | msgstr "" |
258 | 258 | ||
259 | #: src/microhttpd/daemon.c:3035 | 259 | #: src/microhttpd/daemon.c:3047 |
260 | msgid "" | 260 | msgid "" |
261 | "Failed to signal resume of connection via inter-thread communication channel." | 261 | "Failed to signal resume of connection via inter-thread communication channel." |
262 | msgstr "" | 262 | msgstr "" |
263 | 263 | ||
264 | #: src/microhttpd/daemon.c:3081 | 264 | #: src/microhttpd/daemon.c:3094 |
265 | #, c-format | 265 | #, c-format |
266 | msgid "Failed to set nonblocking mode on new client socket: %s\n" | 266 | msgid "Failed to set nonblocking mode on new client socket: %s\n" |
267 | msgstr "" | 267 | msgstr "" |
268 | 268 | ||
269 | #: src/microhttpd/daemon.c:3094 | 269 | #: src/microhttpd/daemon.c:3107 |
270 | msgid "Failed to set noninheritable mode on new client socket.\n" | 270 | msgid "Failed to set noninheritable mode on new client socket.\n" |
271 | msgstr "" | 271 | msgstr "" |
272 | 272 | ||
273 | #: src/microhttpd/daemon.c:3103 | 273 | #: src/microhttpd/daemon.c:3116 |
274 | msgid "Failed to reset buffering mode on new client socket.\n" | 274 | msgid "Failed to reset buffering mode on new client socket.\n" |
275 | msgstr "" | 275 | msgstr "" |
276 | 276 | ||
277 | #: src/microhttpd/daemon.c:3176 | 277 | #: src/microhttpd/daemon.c:3189 |
278 | #, c-format | 278 | #, c-format |
279 | msgid "Error accepting connection: %s\n" | 279 | msgid "Error accepting connection: %s\n" |
280 | msgstr "" | 280 | msgstr "" |
281 | 281 | ||
282 | #: src/microhttpd/daemon.c:3193 | 282 | #: src/microhttpd/daemon.c:3206 |
283 | msgid "" | 283 | msgid "" |
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" |
287 | msgstr "" | 287 | msgstr "" |
288 | 288 | ||
289 | #: src/microhttpd/daemon.c:3207 | 289 | #: src/microhttpd/daemon.c:3220 |
290 | #, c-format | 290 | #, c-format |
291 | msgid "" | 291 | msgid "" |
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" |
294 | msgstr "" | 294 | msgstr "" |
295 | 295 | ||
296 | #: src/microhttpd/daemon.c:3219 | 296 | #: src/microhttpd/daemon.c:3232 |
297 | #, c-format | 297 | #, c-format |
298 | msgid "Failed to set nonblocking mode on incoming connection socket: %s\n" | 298 | msgid "Failed to set nonblocking mode on incoming connection socket: %s\n" |
299 | msgstr "" | 299 | msgstr "" |
300 | 300 | ||
301 | #: src/microhttpd/daemon.c:3231 | 301 | #: src/microhttpd/daemon.c:3244 |
302 | msgid "Failed to set noninheritable mode on incoming connection socket.\n" | 302 | msgid "Failed to set noninheritable mode on incoming connection socket.\n" |
303 | msgstr "" | 303 | msgstr "" |
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 |
307 | msgid "Failed to join a thread\n" | 307 | msgid "Failed to join a thread\n" |
308 | msgstr "" | 308 | msgstr "" |
309 | 309 | ||
310 | #: src/microhttpd/daemon.c:3383 | 310 | #: src/microhttpd/daemon.c:3396 |
311 | msgid "Illegal call to MHD_get_timeout\n" | 311 | msgid "Illegal call to MHD_get_timeout\n" |
312 | msgstr "" | 312 | msgstr "" |
313 | 313 | ||
314 | #: src/microhttpd/daemon.c:3580 | 314 | #: src/microhttpd/daemon.c:3593 |
315 | msgid "" | 315 | msgid "" |
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" |
318 | msgstr "" | 318 | msgstr "" |
319 | 319 | ||
320 | #: src/microhttpd/daemon.c:3660 | 320 | #: src/microhttpd/daemon.c:3673 |
321 | msgid "Could not obtain daemon fdsets" | 321 | msgid "Could not obtain daemon fdsets" |
322 | msgstr "" | 322 | msgstr "" |
323 | 323 | ||
324 | #: src/microhttpd/daemon.c:3677 | 324 | #: src/microhttpd/daemon.c:3690 |
325 | msgid "Could not add listen socket to fdset" | 325 | msgid "Could not add listen socket to fdset" |
326 | msgstr "" | 326 | msgstr "" |
327 | 327 | ||
328 | #: src/microhttpd/daemon.c:3705 | 328 | #: src/microhttpd/daemon.c:3718 |
329 | msgid "Could not add control inter-thread communication channel FD to fdset" | 329 | msgid "Could not add control inter-thread communication channel FD to fdset" |
330 | msgstr "" | 330 | msgstr "" |
331 | 331 | ||
332 | #: src/microhttpd/daemon.c:3761 | 332 | #: src/microhttpd/daemon.c:3774 |
333 | #, c-format | 333 | #, c-format |
334 | msgid "select failed: %s\n" | 334 | msgid "select failed: %s\n" |
335 | msgstr "" | 335 | msgstr "" |
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 |
339 | msgid "poll failed: %s\n" | 339 | msgid "poll failed: %s\n" |
340 | msgstr "" | 340 | msgstr "" |
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 |
344 | msgid "Call to epoll_wait failed: %s\n" | 344 | msgid "Call to epoll_wait failed: %s\n" |
345 | msgstr "" | 345 | msgstr "" |
346 | 346 | ||
347 | #: src/microhttpd/daemon.c:4366 src/microhttpd/daemon.c:4823 | 347 | #: src/microhttpd/daemon.c:4380 src/microhttpd/daemon.c:4837 |
348 | msgid "Failed to remove listen FD from epoll set\n" | 348 | msgid "Failed to remove listen FD from epoll set\n" |
349 | msgstr "" | 349 | msgstr "" |
350 | 350 | ||
351 | #: src/microhttpd/daemon.c:4831 | 351 | #: src/microhttpd/daemon.c:4845 |
352 | msgid "Failed to signal quiesce via inter-thread communication channel" | 352 | msgid "Failed to signal quiesce via inter-thread communication channel" |
353 | msgstr "" | 353 | msgstr "" |
354 | 354 | ||
355 | #: src/microhttpd/daemon.c:4853 | 355 | #: src/microhttpd/daemon.c:4867 |
356 | msgid "failed to signal quiesce via inter-thread communication channel" | 356 | msgid "failed to signal quiesce via inter-thread communication channel" |
357 | msgstr "" | 357 | msgstr "" |
358 | 358 | ||
359 | #: src/microhttpd/daemon.c:4964 | 359 | #: src/microhttpd/daemon.c:4981 |
360 | msgid "Warning: Too large timeout value, ignored.\n" | 360 | msgid "Warning: Too large timeout value, ignored.\n" |
361 | msgstr "" | 361 | msgstr "" |
362 | 362 | ||
363 | #: src/microhttpd/daemon.c:5003 | 363 | #: src/microhttpd/daemon.c:5020 |
364 | msgid "" | 364 | msgid "" |
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" |
367 | msgstr "" | 367 | msgstr "" |
368 | 368 | ||
369 | #: src/microhttpd/daemon.c:5011 | 369 | #: src/microhttpd/daemon.c:5028 |
370 | msgid "" | 370 | msgid "" |
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" |
373 | msgstr "" | 373 | msgstr "" |
374 | 374 | ||
375 | #: src/microhttpd/daemon.c:5023 | 375 | #: src/microhttpd/daemon.c:5040 |
376 | #, c-format | 376 | #, c-format |
377 | msgid "Specified thread pool size (%u) too big\n" | 377 | msgid "Specified thread pool size (%u) too big\n" |
378 | msgstr "" | 378 | msgstr "" |
379 | 379 | ||
380 | #: src/microhttpd/daemon.c:5034 | 380 | #: src/microhttpd/daemon.c:5051 |
381 | msgid "" | 381 | msgid "" |
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" |
384 | msgstr "" | 384 | msgstr "" |
385 | 385 | ||
386 | #: src/microhttpd/daemon.c:5043 | 386 | #: src/microhttpd/daemon.c:5060 |
387 | msgid "" | 387 | msgid "" |
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" |
390 | msgstr "" | 390 | msgstr "" |
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 |
397 | msgid "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n" | 397 | msgid "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n" |
398 | msgstr "" | 398 | msgstr "" |
399 | 399 | ||
400 | #: src/microhttpd/daemon.c:5116 | 400 | #: src/microhttpd/daemon.c:5133 |
401 | msgid "Error initializing DH parameters\n" | 401 | msgid "Error initializing DH parameters\n" |
402 | msgstr "" | 402 | msgstr "" |
403 | 403 | ||
404 | #: src/microhttpd/daemon.c:5126 | 404 | #: src/microhttpd/daemon.c:5143 |
405 | msgid "Diffie-Hellman parameters string too long\n" | 405 | msgid "Diffie-Hellman parameters string too long\n" |
406 | msgstr "" | 406 | msgstr "" |
407 | 407 | ||
408 | #: src/microhttpd/daemon.c:5137 | 408 | #: src/microhttpd/daemon.c:5154 |
409 | msgid "Bad Diffie-Hellman parameters format\n" | 409 | msgid "Bad Diffie-Hellman parameters format\n" |
410 | msgstr "" | 410 | msgstr "" |
411 | 411 | ||
412 | #: src/microhttpd/daemon.c:5164 | 412 | #: src/microhttpd/daemon.c:5181 |
413 | #, c-format | 413 | #, c-format |
414 | msgid "Setting priorities to `%s' failed: %s\n" | 414 | msgid "Setting priorities to `%s' failed: %s\n" |
415 | msgstr "" | 415 | msgstr "" |
416 | 416 | ||
417 | #: src/microhttpd/daemon.c:5183 | 417 | #: src/microhttpd/daemon.c:5200 |
418 | msgid "" | 418 | msgid "" |
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" |
420 | msgstr "" | 420 | msgstr "" |
421 | 421 | ||
422 | #: src/microhttpd/daemon.c:5217 | 422 | #: src/microhttpd/daemon.c:5220 |
423 | msgid "" | ||
424 | "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3\n" | ||
425 | msgstr "" | ||
426 | |||
427 | #: src/microhttpd/daemon.c:5254 | ||
423 | msgid "" | 428 | msgid "" |
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" |
426 | msgstr "" | 431 | msgstr "" |
427 | 432 | ||
428 | #: src/microhttpd/daemon.c:5253 | 433 | #: src/microhttpd/daemon.c:5290 |
429 | msgid "TCP fastopen is not supported on this platform\n" | 434 | msgid "TCP fastopen is not supported on this platform\n" |
430 | msgstr "" | 435 | msgstr "" |
431 | 436 | ||
432 | #: src/microhttpd/daemon.c:5272 | 437 | #: src/microhttpd/daemon.c:5309 |
433 | msgid "" | 438 | msgid "" |
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" |
436 | msgstr "" | 441 | msgstr "" |
437 | 442 | ||
438 | #: src/microhttpd/daemon.c:5404 | 443 | #: src/microhttpd/daemon.c:5442 |
439 | #, c-format | 444 | #, c-format |
440 | msgid "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3\n" | 445 | msgid "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3\n" |
441 | msgstr "" | 446 | msgstr "" |
442 | 447 | ||
443 | #: src/microhttpd/daemon.c:5417 | 448 | #: src/microhttpd/daemon.c:5455 |
444 | #, c-format | 449 | #, c-format |
445 | msgid "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n" | 450 | msgid "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n" |
446 | msgstr "" | 451 | msgstr "" |
447 | 452 | ||
448 | #: src/microhttpd/daemon.c:5423 | 453 | #: src/microhttpd/daemon.c:5461 |
449 | #, c-format | 454 | #, c-format |
450 | msgid "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n" | 455 | msgid "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n" |
451 | msgstr "" | 456 | msgstr "" |
452 | 457 | ||
453 | #: src/microhttpd/daemon.c:5453 | 458 | #: src/microhttpd/daemon.c:5491 |
454 | #, c-format | 459 | #, c-format |
455 | msgid "Call to epoll_create1 failed: %s\n" | 460 | msgid "Call to epoll_create1 failed: %s\n" |
456 | msgstr "" | 461 | msgstr "" |
457 | 462 | ||
458 | #: src/microhttpd/daemon.c:5463 | 463 | #: src/microhttpd/daemon.c:5501 |
459 | msgid "Failed to set noninheritable mode on epoll FD.\n" | 464 | msgid "Failed to set noninheritable mode on epoll FD.\n" |
460 | msgstr "" | 465 | msgstr "" |
461 | 466 | ||
462 | #: src/microhttpd/daemon.c:5706 | 467 | #: src/microhttpd/daemon.c:5744 |
463 | msgid "" | 468 | msgid "" |
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" |
467 | msgstr "" | 472 | msgstr "" |
468 | 473 | ||
469 | #: src/microhttpd/daemon.c:5754 | 474 | #: src/microhttpd/daemon.c:5792 |
470 | msgid "Using debug build of libmicrohttpd.\n" | 475 | msgid "Using debug build of libmicrohttpd.\n" |
471 | msgstr "" | 476 | msgstr "" |
472 | 477 | ||
473 | #: src/microhttpd/daemon.c:5768 | 478 | #: src/microhttpd/daemon.c:5806 |
474 | #, c-format | 479 | #, c-format |
475 | msgid "Failed to create inter-thread communication channel: %s\n" | 480 | msgid "Failed to create inter-thread communication channel: %s\n" |
476 | msgstr "" | 481 | msgstr "" |
477 | 482 | ||
478 | #: src/microhttpd/daemon.c:5784 | 483 | #: src/microhttpd/daemon.c:5822 |
479 | msgid "" | 484 | msgid "" |
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" |
482 | msgstr "" | 487 | msgstr "" |
483 | 488 | ||
484 | #: src/microhttpd/daemon.c:5804 | 489 | #: src/microhttpd/daemon.c:5842 |
485 | msgid "Specified value for NC_SIZE too large\n" | 490 | msgid "Specified value for NC_SIZE too large\n" |
486 | msgstr "" | 491 | msgstr "" |
487 | 492 | ||
488 | #: src/microhttpd/daemon.c:5818 | 493 | #: src/microhttpd/daemon.c:5856 |
489 | #, c-format | 494 | #, c-format |
490 | msgid "Failed to allocate memory for nonce-nc map: %s\n" | 495 | msgid "Failed to allocate memory for nonce-nc map: %s\n" |
491 | msgstr "" | 496 | msgstr "" |
492 | 497 | ||
493 | #: src/microhttpd/daemon.c:5835 | 498 | #: src/microhttpd/daemon.c:5873 |
494 | msgid "MHD failed to initialize nonce-nc mutex\n" | 499 | msgid "MHD failed to initialize nonce-nc mutex\n" |
495 | msgstr "" | 500 | msgstr "" |
496 | 501 | ||
497 | #: src/microhttpd/daemon.c:5855 | 502 | #: src/microhttpd/daemon.c:5893 |
498 | msgid "MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n" | 503 | msgid "MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n" |
499 | msgstr "" | 504 | msgstr "" |
500 | 505 | ||
501 | #: src/microhttpd/daemon.c:5879 | 506 | #: src/microhttpd/daemon.c:5917 |
502 | #, c-format | 507 | #, c-format |
503 | msgid "Failed to create socket for listening: %s\n" | 508 | msgid "Failed to create socket for listening: %s\n" |
504 | msgstr "" | 509 | msgstr "" |
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 |
510 | msgid "setsockopt failed: %s\n" | 515 | msgid "setsockopt failed: %s\n" |
511 | msgstr "" | 516 | msgstr "" |
512 | 517 | ||
513 | #: src/microhttpd/daemon.c:5952 | 518 | #: src/microhttpd/daemon.c:5990 |
514 | msgid "Cannot allow listening address reuse: SO_REUSEPORT not defined\n" | 519 | msgid "Cannot allow listening address reuse: SO_REUSEPORT not defined\n" |
515 | msgstr "" | 520 | msgstr "" |
516 | 521 | ||
517 | #: src/microhttpd/daemon.c:5987 | 522 | #: src/microhttpd/daemon.c:6025 |
518 | msgid "" | 523 | msgid "" |
519 | "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n" | 524 | "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n" |
520 | msgstr "" | 525 | msgstr "" |
521 | 526 | ||
522 | #: src/microhttpd/daemon.c:6067 | 527 | #: src/microhttpd/daemon.c:6105 |
523 | #, c-format | 528 | #, c-format |
524 | msgid "Failed to bind to port %u: %s\n" | 529 | msgid "Failed to bind to port %u: %s\n" |
525 | msgstr "" | 530 | msgstr "" |
526 | 531 | ||
527 | #: src/microhttpd/daemon.c:6098 | 532 | #: src/microhttpd/daemon.c:6136 |
528 | #, c-format | 533 | #, c-format |
529 | msgid "Failed to listen for connections: %s\n" | 534 | msgid "Failed to listen for connections: %s\n" |
530 | msgstr "" | 535 | msgstr "" |
531 | 536 | ||
532 | #: src/microhttpd/daemon.c:6129 | 537 | #: src/microhttpd/daemon.c:6167 |
533 | #, c-format | 538 | #, c-format |
534 | msgid "Failed to get listen port number: %s\n" | 539 | msgid "Failed to get listen port number: %s\n" |
535 | msgstr "" | 540 | msgstr "" |
536 | 541 | ||
537 | #: src/microhttpd/daemon.c:6139 | 542 | #: src/microhttpd/daemon.c:6177 |
538 | msgid "" | 543 | msgid "" |
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" |
540 | msgstr "" | 545 | msgstr "" |
541 | 546 | ||
542 | #: src/microhttpd/daemon.c:6180 | 547 | #: src/microhttpd/daemon.c:6218 |
543 | msgid "Unknown address family!\n" | 548 | msgid "Unknown address family!\n" |
544 | msgstr "" | 549 | msgstr "" |
545 | 550 | ||
546 | #: src/microhttpd/daemon.c:6194 | 551 | #: src/microhttpd/daemon.c:6232 |
547 | #, c-format | 552 | #, c-format |
548 | msgid "Failed to set nonblocking mode on listening socket: %s\n" | 553 | msgid "Failed to set nonblocking mode on listening socket: %s\n" |
549 | msgstr "" | 554 | msgstr "" |
550 | 555 | ||
551 | #: src/microhttpd/daemon.c:6236 | 556 | #: src/microhttpd/daemon.c:6274 |
552 | msgid "" | 557 | msgid "" |
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" |
554 | msgstr "" | 559 | msgstr "" |
555 | 560 | ||
556 | #: src/microhttpd/daemon.c:6250 src/microhttpd/daemon.c:6263 | 561 | #: src/microhttpd/daemon.c:6288 src/microhttpd/daemon.c:6301 |
557 | msgid "MHD failed to initialize IP connection limit mutex\n" | 562 | msgid "MHD failed to initialize IP connection limit mutex\n" |
558 | msgstr "" | 563 | msgstr "" |
559 | 564 | ||
560 | #: src/microhttpd/daemon.c:6282 | 565 | #: src/microhttpd/daemon.c:6320 |
561 | msgid "Failed to initialize TLS support\n" | 566 | msgid "Failed to initialize TLS support\n" |
562 | msgstr "" | 567 | msgstr "" |
563 | 568 | ||
564 | #: src/microhttpd/daemon.c:6309 | 569 | #: src/microhttpd/daemon.c:6347 |
565 | #, c-format | 570 | #, c-format |
566 | msgid "Failed to create listen thread: %s\n" | 571 | msgid "Failed to create listen thread: %s\n" |
567 | msgstr "" | 572 | msgstr "" |
568 | 573 | ||
569 | #: src/microhttpd/daemon.c:6357 | 574 | #: src/microhttpd/daemon.c:6395 |
570 | #, c-format | 575 | #, c-format |
571 | msgid "Failed to create worker inter-thread communication channel: %s\n" | 576 | msgid "Failed to create worker inter-thread communication channel: %s\n" |
572 | msgstr "" | 577 | msgstr "" |
573 | 578 | ||
574 | #: src/microhttpd/daemon.c:6368 | 579 | #: src/microhttpd/daemon.c:6406 |
575 | msgid "" | 580 | msgid "" |
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" |
578 | msgstr "" | 583 | msgstr "" |
579 | 584 | ||
580 | #: src/microhttpd/daemon.c:6393 | 585 | #: src/microhttpd/daemon.c:6431 |
581 | msgid "MHD failed to initialize cleanup connection mutex\n" | 586 | msgid "MHD failed to initialize cleanup connection mutex\n" |
582 | msgstr "" | 587 | msgstr "" |
583 | 588 | ||
584 | #: src/microhttpd/daemon.c:6407 | 589 | #: src/microhttpd/daemon.c:6445 |
585 | #, c-format | 590 | #, c-format |
586 | msgid "Failed to create pool thread: %s\n" | 591 | msgid "Failed to create pool thread: %s\n" |
587 | msgstr "" | 592 | msgstr "" |
588 | 593 | ||
589 | #: src/microhttpd/daemon.c:6560 src/microhttpd/daemon.c:6591 | 594 | #: src/microhttpd/daemon.c:6598 src/microhttpd/daemon.c:6629 |
590 | msgid "MHD_stop_daemon() called while we have suspended connections.\n" | 595 | msgid "MHD_stop_daemon() called while we have suspended connections.\n" |
591 | msgstr "" | 596 | msgstr "" |
592 | 597 | ||
593 | #: src/microhttpd/daemon.c:6600 src/microhttpd/daemon.c:6729 | 598 | #: src/microhttpd/daemon.c:6638 src/microhttpd/daemon.c:6767 |
594 | msgid "Failed to signal shutdown via inter-thread communication channel" | 599 | msgid "Failed to signal shutdown via inter-thread communication channel" |
595 | msgstr "" | 600 | msgstr "" |
596 | 601 | ||
597 | #: src/microhttpd/daemon.c:6692 | 602 | #: src/microhttpd/daemon.c:6730 |
598 | msgid "Failed to signal shutdown via inter-thread communication channel." | 603 | msgid "Failed to signal shutdown via inter-thread communication channel." |
599 | msgstr "" | 604 | msgstr "" |
600 | 605 | ||
601 | #: src/microhttpd/daemon.c:7159 | 606 | #: src/microhttpd/daemon.c:7203 |
602 | msgid "Failed to initialize winsock\n" | 607 | msgid "Failed to initialize winsock\n" |
603 | msgstr "" | 608 | msgstr "" |
604 | 609 | ||
605 | #: src/microhttpd/daemon.c:7162 | 610 | #: src/microhttpd/daemon.c:7206 |
606 | msgid "Winsock version 2.2 is not available\n" | 611 | msgid "Winsock version 2.2 is not available\n" |
607 | msgstr "" | 612 | msgstr "" |
608 | 613 | ||
609 | #: src/microhttpd/daemon.c:7170 src/microhttpd/daemon.c:7174 | 614 | #: src/microhttpd/daemon.c:7214 src/microhttpd/daemon.c:7218 |
610 | msgid "Failed to initialise multithreading in libgcrypt\n" | 615 | msgid "Failed to initialise multithreading in libgcrypt\n" |
611 | msgstr "" | 616 | msgstr "" |
612 | 617 | ||
613 | #: src/microhttpd/daemon.c:7179 | 618 | #: src/microhttpd/daemon.c:7223 |
614 | msgid "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n" | 619 | msgid "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n" |
615 | msgstr "" | 620 | msgstr "" |
616 | 621 | ||
@@ -637,17 +642,17 @@ msgid "" | |||
637 | "connection.\n" | 642 | "connection.\n" |
638 | msgstr "" | 643 | msgstr "" |
639 | 644 | ||
640 | #: src/microhttpd/connection.c:2055 src/microhttpd/connection.c:3068 | 645 | #: src/microhttpd/connection.c:2055 src/microhttpd/connection.c:3080 |
641 | msgid "Closing connection (failed to queue response)\n" | 646 | msgid "Closing connection (failed to queue response)\n" |
642 | msgstr "" | 647 | msgstr "" |
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 |
646 | msgid "Closing connection (failed to create response header)\n" | 651 | msgid "Closing connection (failed to create response header)\n" |
647 | msgstr "" | 652 | msgstr "" |
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 |
652 | msgid "In function %s handling connection at state: %s\n" | 657 | msgid "In function %s handling connection at state: %s\n" |
653 | msgstr "" | 658 | msgstr "" |
@@ -660,96 +665,96 @@ msgstr "" | |||
660 | msgid "Not enough memory in pool to parse cookies!\n" | 665 | msgid "Not enough memory in pool to parse cookies!\n" |
661 | msgstr "" | 666 | msgstr "" |
662 | 667 | ||
663 | #: src/microhttpd/connection.c:2605 src/microhttpd/connection.c:2790 | 668 | #: src/microhttpd/connection.c:2605 src/microhttpd/connection.c:2802 |
664 | msgid "Application reported internal error, closing connection.\n" | 669 | msgid "Application reported internal error, closing connection.\n" |
665 | msgstr "" | 670 | msgstr "" |
666 | 671 | ||
667 | #: src/microhttpd/connection.c:2658 src/microhttpd/connection.c:2735 | 672 | #: src/microhttpd/connection.c:2670 src/microhttpd/connection.c:2747 |
668 | msgid "" | 673 | msgid "" |
669 | "Received malformed HTTP request (bad chunked encoding). Closing connection.\n" | 674 | "Received malformed HTTP request (bad chunked encoding). Closing connection.\n" |
670 | msgstr "" | 675 | msgstr "" |
671 | 676 | ||
672 | #: src/microhttpd/connection.c:2798 | 677 | #: src/microhttpd/connection.c:2810 |
673 | msgid "libmicrohttpd API violation" | 678 | msgid "libmicrohttpd API violation" |
674 | msgstr "" | 679 | msgstr "" |
675 | 680 | ||
676 | #: src/microhttpd/connection.c:2813 | 681 | #: src/microhttpd/connection.c:2825 |
677 | msgid "" | 682 | msgid "" |
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" |
680 | msgstr "" | 685 | msgstr "" |
681 | 686 | ||
682 | #: src/microhttpd/connection.c:2884 | 687 | #: src/microhttpd/connection.c:2896 |
683 | msgid "Received malformed line (no colon). Closing connection.\n" | 688 | msgid "Received malformed line (no colon). Closing connection.\n" |
684 | msgstr "" | 689 | msgstr "" |
685 | 690 | ||
686 | #: src/microhttpd/connection.c:3046 | 691 | #: src/microhttpd/connection.c:3058 |
687 | msgid "Received HTTP 1.1 request without `Host' header.\n" | 692 | msgid "Received HTTP 1.1 request without `Host' header.\n" |
688 | msgstr "" | 693 | msgstr "" |
689 | 694 | ||
690 | #: src/microhttpd/connection.c:3057 | 695 | #: src/microhttpd/connection.c:3069 |
691 | msgid "Closing connection (failed to create response)\n" | 696 | msgid "Closing connection (failed to create response)\n" |
692 | msgstr "" | 697 | msgstr "" |
693 | 698 | ||
694 | #: src/microhttpd/connection.c:3202 | 699 | #: src/microhttpd/connection.c:3214 |
695 | msgid "Socket disconnected while reading request.\n" | 700 | msgid "Socket disconnected while reading request.\n" |
696 | msgstr "" | 701 | msgstr "" |
697 | 702 | ||
698 | #: src/microhttpd/connection.c:3208 | 703 | #: src/microhttpd/connection.c:3220 |
699 | msgid "Connection socket is closed due to error when reading request.\n" | 704 | msgid "Connection socket is closed due to error when reading request.\n" |
700 | msgstr "" | 705 | msgstr "" |
701 | 706 | ||
702 | #: src/microhttpd/connection.c:3317 | 707 | #: src/microhttpd/connection.c:3329 |
703 | #, c-format | 708 | #, c-format |
704 | msgid "Failed to send data in request for %s.\n" | 709 | msgid "Failed to send data in request for %s.\n" |
705 | msgstr "" | 710 | msgstr "" |
706 | 711 | ||
707 | #: src/microhttpd/connection.c:3326 | 712 | #: src/microhttpd/connection.c:3338 |
708 | #, c-format | 713 | #, c-format |
709 | msgid "Sent 100 continue response: `%.*s'\n" | 714 | msgid "Sent 100 continue response: `%.*s'\n" |
710 | msgstr "" | 715 | msgstr "" |
711 | 716 | ||
712 | #: src/microhttpd/connection.c:3350 | 717 | #: src/microhttpd/connection.c:3362 |
713 | msgid "Connection was closed while sending response headers.\n" | 718 | msgid "Connection was closed while sending response headers.\n" |
714 | msgstr "" | 719 | msgstr "" |
715 | 720 | ||
716 | #: src/microhttpd/connection.c:3391 | 721 | #: src/microhttpd/connection.c:3403 |
717 | msgid "Data offset exceeds limit" | 722 | msgid "Data offset exceeds limit" |
718 | msgstr "" | 723 | msgstr "" |
719 | 724 | ||
720 | #: src/microhttpd/connection.c:3400 | 725 | #: src/microhttpd/connection.c:3412 |
721 | #, c-format | 726 | #, c-format |
722 | msgid "Sent %d-byte DATA response: `%.*s'\n" | 727 | msgid "Sent %d-byte DATA response: `%.*s'\n" |
723 | msgstr "" | 728 | msgstr "" |
724 | 729 | ||
725 | #: src/microhttpd/connection.c:3417 | 730 | #: src/microhttpd/connection.c:3429 |
726 | #, c-format | 731 | #, c-format |
727 | msgid "Failed to send data in request for `%s'.\n" | 732 | msgid "Failed to send data in request for `%s'.\n" |
728 | msgstr "" | 733 | msgstr "" |
729 | 734 | ||
730 | #: src/microhttpd/connection.c:3445 src/microhttpd/connection.c:3473 | 735 | #: src/microhttpd/connection.c:3457 src/microhttpd/connection.c:3485 |
731 | msgid "Connection was closed while sending response body.\n" | 736 | msgid "Connection was closed while sending response body.\n" |
732 | msgstr "" | 737 | msgstr "" |
733 | 738 | ||
734 | #: src/microhttpd/connection.c:3496 | 739 | #: src/microhttpd/connection.c:3508 |
735 | msgid "Internal error\n" | 740 | msgid "Internal error\n" |
736 | msgstr "" | 741 | msgstr "" |
737 | 742 | ||
738 | #: src/microhttpd/connection.c:3569 | 743 | #: src/microhttpd/connection.c:3581 |
739 | msgid "" | 744 | msgid "" |
740 | "Failed to signal end of connection via inter-thread communication channel" | 745 | "Failed to signal end of connection via inter-thread communication channel" |
741 | msgstr "" | 746 | msgstr "" |
742 | 747 | ||
743 | #: src/microhttpd/connection.c:4316 | 748 | #: src/microhttpd/connection.c:4328 |
744 | msgid "Attempted to queue response on wrong thread!\n" | 749 | msgid "Attempted to queue response on wrong thread!\n" |
745 | msgstr "" | 750 | msgstr "" |
746 | 751 | ||
747 | #: src/microhttpd/connection.c:4327 | 752 | #: src/microhttpd/connection.c:4339 |
748 | msgid "" | 753 | msgid "" |
749 | "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n" | 754 | "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n" |
750 | msgstr "" | 755 | msgstr "" |
751 | 756 | ||
752 | #: src/microhttpd/connection.c:4336 | 757 | #: src/microhttpd/connection.c:4348 |
753 | msgid "Application used invalid status code for 'upgrade' response!\n" | 758 | msgid "Application used invalid status code for 'upgrade' response!\n" |
754 | msgstr "" | 759 | msgstr "" |
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 | |||
57 | test_shutdown_select | 57 | test_shutdown_select |
58 | test_md5 | 58 | test_md5 |
59 | test_sha256 | 59 | test_sha256 |
60 | test_upgrade_large | ||
61 | test_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 = \ | |||
166 | if HAVE_POSIX_THREADS | 166 | if HAVE_POSIX_THREADS |
167 | if ENABLE_UPGRADE | 167 | if ENABLE_UPGRADE |
168 | if USE_POSIX_THREADS | 168 | if USE_POSIX_THREADS |
169 | check_PROGRAMS += test_upgrade | 169 | check_PROGRAMS += test_upgrade test_upgrade_large |
170 | endif | 170 | endif |
171 | if USE_W32_THREADS | 171 | if USE_W32_THREADS |
172 | check_PROGRAMS += test_upgrade | 172 | check_PROGRAMS += test_upgrade test_upgrade_large |
173 | endif | 173 | endif |
174 | if ENABLE_HTTPS | 174 | if ENABLE_HTTPS |
175 | if USE_POSIX_THREADS | 175 | if USE_POSIX_THREADS |
176 | check_PROGRAMS += test_upgrade_tls | 176 | check_PROGRAMS += test_upgrade_tls test_upgrade_large_tls |
177 | endif | 177 | endif |
178 | if USE_W32_THREADS | 178 | if USE_W32_THREADS |
179 | check_PROGRAMS += test_upgrade_tls | 179 | check_PROGRAMS += test_upgrade_tls test_upgrade_large_tls |
180 | endif | 180 | endif |
181 | endif | 181 | endif |
182 | endif | 182 | endif |
@@ -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 | ||
234 | test_upgrade_large_SOURCES = \ | ||
235 | test_upgrade_large.c test_helpers.h mhd_sockets.h | ||
236 | test_upgrade_large_CPPFLAGS = \ | ||
237 | $(AM_CPPFLAGS) $(MHD_TLS_LIB_CPPFLAGS) | ||
238 | test_upgrade_large_CFLAGS = \ | ||
239 | $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(MHD_TLS_LIB_CFLAGS) | ||
240 | test_upgrade_large_LDFLAGS = \ | ||
241 | $(MHD_TLS_LIB_LDFLAGS) | ||
242 | test_upgrade_large_LDADD = \ | ||
243 | $(top_builddir)/src/microhttpd/libmicrohttpd.la \ | ||
244 | $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \ | ||
245 | $(PTHREAD_LIBS) | ||
246 | |||
234 | test_upgrade_tls_SOURCES = \ | 247 | test_upgrade_tls_SOURCES = \ |
235 | test_upgrade.c test_helpers.h mhd_sockets.h | 248 | test_upgrade.c test_helpers.h mhd_sockets.h |
236 | test_upgrade_tls_CPPFLAGS = \ | 249 | test_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 | ||
260 | test_upgrade_large_tls_SOURCES = \ | ||
261 | test_upgrade_large.c test_helpers.h mhd_sockets.h | ||
262 | test_upgrade_large_tls_CPPFLAGS = \ | ||
263 | $(AM_CPPFLAGS) $(MHD_TLS_LIB_CPPFLAGS) | ||
264 | test_upgrade_large_tls_CFLAGS = \ | ||
265 | $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(MHD_TLS_LIB_CFLAGS) | ||
266 | test_upgrade_large_tls_LDFLAGS = \ | ||
267 | $(MHD_TLS_LIB_LDFLAGS) | ||
268 | test_upgrade_large_tls_LDADD = \ | ||
269 | $(top_builddir)/src/microhttpd/libmicrohttpd.la \ | ||
270 | $(MHD_TLS_LIB_LDFLAGS) $(MHD_TLS_LIBDEPS) \ | ||
271 | $(PTHREAD_LIBS) | ||
272 | |||
247 | test_postprocessor_SOURCES = \ | 273 | test_postprocessor_SOURCES = \ |
248 | test_postprocessor.c | 274 | test_postprocessor.c |
249 | test_postprocessor_CPPFLAGS = \ | 275 | test_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 | |||
721 | MHD_get_fdset (struct MHD_Daemon *daemon, | 721 | MHD_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 | */ |
2345 | static int | 2345 | static int |
2346 | internal_add_connection (struct MHD_Daemon *daemon, | 2346 | internal_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 | */ |
3082 | int | 3082 | int |
3083 | MHD_add_connection (struct MHD_Daemon *daemon, | 3083 | MHD_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 | */ |
3382 | int | 3383 | int |
3383 | MHD_get_timeout (struct MHD_Daemon *daemon, | 3384 | MHD_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 | */ |
4287 | static int | 4289 | static int |
4288 | MHD_epoll (struct MHD_Daemon *daemon, | 4290 | MHD_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 | */ |
4891 | static int | 4893 | static int |
4892 | parse_options_va (struct MHD_Daemon *daemon, | 4894 | parse_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 | */ |
4930 | static int | 4932 | static int |
4931 | parse_options_va (struct MHD_Daemon *daemon, | 4933 | parse_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 | */ |
81 | static int | 81 | static int |
82 | add_response_entry (struct MHD_Response *response, | 82 | add_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 | */ |
281 | const char * | 281 | const char * |
282 | MHD_get_response_header (struct MHD_Response *response, | 282 | MHD_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 | */ |
733 | struct MHD_Response * | 733 | struct MHD_Response * |
734 | MHD_create_response_from_buffer (size_t size, | 734 | MHD_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 * |
756 | MHD_create_response_from_buffer_with_free_callback (size_t size, | 756 | MHD_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 | |||
68 | static int verbose = 0; | ||
69 | |||
70 | static int kicker[2] = {-1, -1} ; | ||
71 | |||
72 | enum tls_tool | ||
73 | { | ||
74 | TLS_CLI_NO_TOOL = 0, | ||
75 | TLS_CLI_GNUTLS, | ||
76 | TLS_CLI_OPENSSL, | ||
77 | TLS_LIB_GNUTLS | ||
78 | }; | ||
79 | |||
80 | enum 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 | */ | ||
91 | static pid_t | ||
92 | gnutlscli_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 | */ | ||
156 | struct 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 | */ | ||
202 | static struct wr_socket * | ||
203 | wr_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 | */ | ||
221 | static struct wr_socket * | ||
222 | wr_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 | */ | ||
267 | static struct wr_socket * | ||
268 | wr_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 | */ | ||
287 | static int | ||
288 | wr_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() ! */ | ||
313 | static bool | ||
314 | wr_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 | */ | ||
337 | static ssize_t | ||
338 | wr_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 | */ | ||
373 | static ssize_t | ||
374 | wr_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 | */ | ||
405 | static int | ||
406 | wr_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 | */ | ||
424 | static pthread_t pt; | ||
425 | |||
426 | /** | ||
427 | * Will be set to the upgraded socket. | ||
428 | */ | ||
429 | static struct wr_socket *usock; | ||
430 | |||
431 | /** | ||
432 | * Thread we use to run the interaction with the upgraded socket. | ||
433 | */ | ||
434 | static pthread_t pt_client; | ||
435 | |||
436 | /** | ||
437 | * Flag set to 1 once the test is finished. | ||
438 | */ | ||
439 | static 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 | */ | ||
452 | static void | ||
453 | notify_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 | */ | ||
483 | static void * | ||
484 | log_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 | */ | ||
522 | static void | ||
523 | notify_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 | */ | ||
558 | static void | ||
559 | make_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 | |||
578 | static void | ||
579 | kick_select () | ||
580 | { | ||
581 | if (-1 != kicker[1]) | ||
582 | { | ||
583 | write (kicker[1], "K", 1); | ||
584 | fprintf (stderr, "KICKING\n"); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | |||
589 | static void | ||
590 | send_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 | */ | ||
621 | static void | ||
622 | recv_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 | |||
667 | static void | ||
668 | recv_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 | */ | ||
703 | static void * | ||
704 | run_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 | */ | ||
728 | static void * | ||
729 | run_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 | */ | ||
792 | static void | ||
793 | upgrade_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 | */ | ||
856 | static int | ||
857 | ahc_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 | */ | ||
897 | static void | ||
898 | run_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 | */ | ||
958 | static void | ||
959 | run_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 | */ | ||
973 | static void | ||
974 | run_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 | */ | ||
1026 | static void | ||
1027 | run_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 | |||
1045 | static 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 | */ | ||
1053 | static int | ||
1054 | test_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, ¬ify_completed_cb, NULL, | ||
1077 | MHD_OPTION_NOTIFY_CONNECTION, ¬ify_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, ¬ify_completed_cb, NULL, | ||
1090 | MHD_OPTION_NOTIFY_CONNECTION, ¬ify_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 | |||
1173 | int | ||
1174 | main (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 | } | ||