diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/daemon/daemon.c | 131 | ||||
-rw-r--r-- | src/daemon/internal.h | 10 | ||||
-rw-r--r-- | src/include/microhttpd.h | 11 | ||||
-rw-r--r-- | src/testcurl/daemontest_get.c | 50 | ||||
-rw-r--r-- | src/testcurl/daemontest_get_chunked.c | 43 | ||||
-rw-r--r-- | src/testcurl/daemontest_iplimit.c | 99 | ||||
-rw-r--r-- | src/testcurl/daemontest_large_put.c | 60 | ||||
-rw-r--r-- | src/testcurl/daemontest_post.c | 53 | ||||
-rw-r--r-- | src/testcurl/daemontest_post_loop.c | 65 | ||||
-rw-r--r-- | src/testcurl/daemontest_postform.c | 55 | ||||
-rw-r--r-- | src/testcurl/daemontest_process_headers.c | 50 | ||||
-rw-r--r-- | src/testcurl/daemontest_put.c | 59 | ||||
-rw-r--r-- | src/testcurl/daemontest_put_chunked.c | 59 |
13 files changed, 738 insertions, 7 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 3c90f5b4..18775c46 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of libmicrohttpd | 2 | This file is part of libmicrohttpd |
3 | (C) 2007, 2008 Daniel Pittman and Christian Grothoff | 3 | (C) 2007, 2008, 2009 Daniel Pittman and Christian Grothoff |
4 | 4 | ||
5 | This library is free software; you can redistribute it and/or | 5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public | 6 | modify it under the terms of the GNU Lesser General Public |
@@ -187,8 +187,8 @@ MHD_ip_limit_add(struct MHD_Daemon *daemon, | |||
187 | if (daemon->per_ip_connection_limit == 0) | 187 | if (daemon->per_ip_connection_limit == 0) |
188 | return MHD_YES; | 188 | return MHD_YES; |
189 | 189 | ||
190 | key = (struct MHD_IPCount*) malloc (sizeof(*key)); | 190 | key = malloc (sizeof(*key)); |
191 | if (!key) | 191 | if (NULL == key) |
192 | return MHD_NO; | 192 | return MHD_NO; |
193 | 193 | ||
194 | /* Initialize key */ | 194 | /* Initialize key */ |
@@ -625,7 +625,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
625 | #endif | 625 | #endif |
626 | #endif | 626 | #endif |
627 | connection = malloc (sizeof (struct MHD_Connection)); | 627 | connection = malloc (sizeof (struct MHD_Connection)); |
628 | if (connection == NULL) | 628 | if (NULL == connection) |
629 | { | 629 | { |
630 | #if HAVE_MESSAGES | 630 | #if HAVE_MESSAGES |
631 | MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); | 631 | MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno)); |
@@ -1017,6 +1017,7 @@ MHD_start_daemon_va (unsigned int options, | |||
1017 | const struct sockaddr *servaddr = NULL; | 1017 | const struct sockaddr *servaddr = NULL; |
1018 | socklen_t addrlen; | 1018 | socklen_t addrlen; |
1019 | enum MHD_OPTION opt; | 1019 | enum MHD_OPTION opt; |
1020 | unsigned int i; | ||
1020 | 1021 | ||
1021 | if ((port == 0) || (dh == NULL)) | 1022 | if ((port == 0) || (dh == NULL)) |
1022 | return NULL; | 1023 | return NULL; |
@@ -1080,6 +1081,9 @@ MHD_start_daemon_va (unsigned int options, | |||
1080 | va_arg (ap, LogCallback); | 1081 | va_arg (ap, LogCallback); |
1081 | retVal->uri_log_callback_cls = va_arg (ap, void *); | 1082 | retVal->uri_log_callback_cls = va_arg (ap, void *); |
1082 | break; | 1083 | break; |
1084 | case MHD_OPTION_THREAD_POOL_SIZE: | ||
1085 | retVal->worker_pool_size = va_arg (ap, unsigned int); | ||
1086 | break; | ||
1083 | #if HTTPS_SUPPORT | 1087 | #if HTTPS_SUPPORT |
1084 | case MHD_OPTION_PROTOCOL_VERSION: | 1088 | case MHD_OPTION_PROTOCOL_VERSION: |
1085 | _set_priority (&retVal->priority_cache->protocol, | 1089 | _set_priority (&retVal->priority_cache->protocol, |
@@ -1126,6 +1130,17 @@ MHD_start_daemon_va (unsigned int options, | |||
1126 | } | 1130 | } |
1127 | } | 1131 | } |
1128 | 1132 | ||
1133 | /* Thread pooling currently works only with internal select thread model */ | ||
1134 | if ((0 == (options & MHD_USE_SELECT_INTERNALLY)) | ||
1135 | && (retVal->worker_pool_size > 0)) | ||
1136 | { | ||
1137 | #if HAVE_MESSAGES | ||
1138 | FPRINTF (stderr, | ||
1139 | "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n"); | ||
1140 | #endif | ||
1141 | return NULL; | ||
1142 | } | ||
1143 | |||
1129 | if ((options & MHD_USE_IPv6) != 0) | 1144 | if ((options & MHD_USE_IPv6) != 0) |
1130 | #if HAVE_INET6 | 1145 | #if HAVE_INET6 |
1131 | socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); | 1146 | socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); |
@@ -1235,7 +1250,8 @@ MHD_start_daemon_va (unsigned int options, | |||
1235 | } | 1250 | } |
1236 | #endif | 1251 | #endif |
1237 | if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || | 1252 | if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || |
1238 | (0 != (options & MHD_USE_SELECT_INTERNALLY))) | 1253 | ((0 != (options & MHD_USE_SELECT_INTERNALLY)) |
1254 | && (0 == retVal->worker_pool_size))) | ||
1239 | && (0 != | 1255 | && (0 != |
1240 | pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal))) | 1256 | pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal))) |
1241 | { | 1257 | { |
@@ -1248,6 +1264,87 @@ MHD_start_daemon_va (unsigned int options, | |||
1248 | CLOSE (socket_fd); | 1264 | CLOSE (socket_fd); |
1249 | return NULL; | 1265 | return NULL; |
1250 | } | 1266 | } |
1267 | else if (retVal->worker_pool_size > 0) | ||
1268 | { | ||
1269 | /* Coarse-grained count of connections per thread (note error | ||
1270 | * due to integer division). Also keep track of how many | ||
1271 | * connections are leftover after an equal split. */ | ||
1272 | unsigned int conns_per_thread = retVal->max_connections | ||
1273 | / retVal->worker_pool_size; | ||
1274 | unsigned int leftover_conns = retVal->max_connections | ||
1275 | % retVal->worker_pool_size; | ||
1276 | |||
1277 | /* Allocate memory for pooled objects */ | ||
1278 | retVal->worker_pool = malloc (sizeof (*retVal->worker_pool) | ||
1279 | * retVal->worker_pool_size); | ||
1280 | |||
1281 | /* Start the workers in the pool */ | ||
1282 | for (i = 0; i < retVal->worker_pool_size; ++i) | ||
1283 | { | ||
1284 | /* Create copy of the Daemon object for each worker */ | ||
1285 | struct MHD_Daemon *d = (struct MHD_Daemon*) malloc (sizeof (*d)); | ||
1286 | if (!d) | ||
1287 | { | ||
1288 | #if HAVE_MESSAGES | ||
1289 | MHD_DLOG (retVal, | ||
1290 | "Failed to copy daemon object: %d\n", STRERROR (errno)); | ||
1291 | #endif | ||
1292 | goto thread_failed; | ||
1293 | } | ||
1294 | memcpy (d, retVal, sizeof (*d)); | ||
1295 | |||
1296 | /* Adjust pooling params for worker daemons; note that memcpy() | ||
1297 | * has already copied MHD_USE_SELECT_INTERNALLY thread model into | ||
1298 | * the worker threads. */ | ||
1299 | d->master = retVal; | ||
1300 | d->worker_pool_size = 0; | ||
1301 | d->worker_pool = NULL; | ||
1302 | |||
1303 | /* Divide available connections evenly amongst the threads. | ||
1304 | * Thread indexes in [0, leftover_conns) each get one of the | ||
1305 | * leftover connections. */ | ||
1306 | d->max_connections = conns_per_thread; | ||
1307 | if (i < leftover_conns) | ||
1308 | ++d->max_connections; | ||
1309 | |||
1310 | /* Spawn the worker thread */ | ||
1311 | if (0 != pthread_create (&d->pid, NULL, &MHD_select_thread, d)) | ||
1312 | { | ||
1313 | #if HAVE_MESSAGES | ||
1314 | MHD_DLOG (retVal, | ||
1315 | "Failed to create pool thread: %d\n", STRERROR (errno)); | ||
1316 | #endif | ||
1317 | /* Free memory for this worker; cleanup below handles | ||
1318 | * all previously-created workers. */ | ||
1319 | free (d); | ||
1320 | goto thread_failed; | ||
1321 | } | ||
1322 | |||
1323 | retVal->worker_pool[i] = d; | ||
1324 | continue; | ||
1325 | |||
1326 | thread_failed: | ||
1327 | /* If no worker threads created, then shut down normally. Calling | ||
1328 | * MHD_stop_daemon (as we do below) doesn't work here since it | ||
1329 | * assumes a 0-sized thread pool means we had been in the default | ||
1330 | * MHD_USE_SELECT_INTERNALLY mode. */ | ||
1331 | if (i == 0) | ||
1332 | { | ||
1333 | CLOSE (socket_fd); | ||
1334 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); | ||
1335 | free (retVal); | ||
1336 | return NULL; | ||
1337 | } | ||
1338 | |||
1339 | /* Shutdown worker threads we've already created. Pretend | ||
1340 | * as though we had fully initialized our daemon, but | ||
1341 | * with a smaller number of threads than had been | ||
1342 | * requested. */ | ||
1343 | retVal->worker_pool_size = i - 1; | ||
1344 | MHD_stop_daemon (retVal); | ||
1345 | return NULL; | ||
1346 | } | ||
1347 | } | ||
1251 | return retVal; | 1348 | return retVal; |
1252 | } | 1349 | } |
1253 | 1350 | ||
@@ -1281,20 +1378,42 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
1281 | { | 1378 | { |
1282 | void *unused; | 1379 | void *unused; |
1283 | int fd; | 1380 | int fd; |
1381 | unsigned int i; | ||
1284 | 1382 | ||
1285 | if (daemon == NULL) | 1383 | if (daemon == NULL) |
1286 | return; | 1384 | return; |
1287 | daemon->shutdown = MHD_YES; | 1385 | daemon->shutdown = MHD_YES; |
1288 | fd = daemon->socket_fd; | 1386 | fd = daemon->socket_fd; |
1289 | daemon->socket_fd = -1; | 1387 | daemon->socket_fd = -1; |
1388 | |||
1389 | /* Prepare workers for shutdown */ | ||
1390 | for (i = 0; i < daemon->worker_pool_size; ++i) | ||
1391 | { | ||
1392 | daemon->worker_pool[i]->shutdown = MHD_YES; | ||
1393 | daemon->worker_pool[i]->socket_fd = -1; | ||
1394 | } | ||
1395 | |||
1290 | #if DEBUG_CLOSE | 1396 | #if DEBUG_CLOSE |
1291 | #if HAVE_MESSAGES | 1397 | #if HAVE_MESSAGES |
1292 | MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n"); | 1398 | MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n"); |
1293 | #endif | 1399 | #endif |
1294 | #endif | 1400 | #endif |
1295 | CLOSE (fd); | 1401 | CLOSE (fd); |
1402 | |||
1403 | /* Signal workers to stop and clean them up */ | ||
1404 | for (i = 0; i < daemon->worker_pool_size; ++i) | ||
1405 | pthread_kill (daemon->worker_pool[i]->pid, SIGALRM); | ||
1406 | for (i = 0; i < daemon->worker_pool_size; ++i) | ||
1407 | { | ||
1408 | pthread_join (daemon->worker_pool[i]->pid, &unused); | ||
1409 | MHD_close_connections (daemon->worker_pool[i]); | ||
1410 | free (daemon->worker_pool[i]); | ||
1411 | } | ||
1412 | free (daemon->worker_pool); | ||
1413 | |||
1296 | if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || | 1414 | if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || |
1297 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) | 1415 | ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) |
1416 | && (0 == daemon->worker_pool_size))) | ||
1298 | { | 1417 | { |
1299 | pthread_kill (daemon->pid, SIGALRM); | 1418 | pthread_kill (daemon->pid, SIGALRM); |
1300 | pthread_join (daemon->pid, &unused); | 1419 | pthread_join (daemon->pid, &unused); |
diff --git a/src/daemon/internal.h b/src/daemon/internal.h index d739c369..fcc1fd57 100644 --- a/src/daemon/internal.h +++ b/src/daemon/internal.h | |||
@@ -775,6 +775,16 @@ struct MHD_Daemon | |||
775 | * Pointer to master daemon (NULL if this is the master) | 775 | * Pointer to master daemon (NULL if this is the master) |
776 | */ | 776 | */ |
777 | struct MHD_Daemon *master; | 777 | struct MHD_Daemon *master; |
778 | |||
779 | /** | ||
780 | * Worker daemons (one per thread) | ||
781 | */ | ||
782 | struct MHD_Daemon **worker_pool; | ||
783 | |||
784 | /** | ||
785 | * Number of worker daemons | ||
786 | */ | ||
787 | unsigned int worker_pool_size; | ||
778 | }; | 788 | }; |
779 | 789 | ||
780 | 790 | ||
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 8ac88a78..34ce1d98 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -429,8 +429,17 @@ enum MHD_OPTION | |||
429 | * if it was compiled without the "--enable-messages" | 429 | * if it was compiled without the "--enable-messages" |
430 | * flag being set. | 430 | * flag being set. |
431 | */ | 431 | */ |
432 | MHD_OPTION_EXTERNAL_LOGGER = 13 | 432 | MHD_OPTION_EXTERNAL_LOGGER = 13, |
433 | 433 | ||
434 | /** | ||
435 | * Number (unsigned int) of threads in thread pool. Enable | ||
436 | * thread pooling by setting this value to to something | ||
437 | * greater than 1. Currently, thread model must be | ||
438 | * MHD_USE_SELECT_INTERNALLY if thread pooling is enabled | ||
439 | * (MHD_start_daemon returns NULL for an unsupported thread | ||
440 | * model). | ||
441 | */ | ||
442 | MHD_OPTION_THREAD_POOL_SIZE = 14, | ||
434 | }; | 443 | }; |
435 | 444 | ||
436 | /** | 445 | /** |
diff --git a/src/testcurl/daemontest_get.c b/src/testcurl/daemontest_get.c index 94b15774..acf2bcc1 100644 --- a/src/testcurl/daemontest_get.c +++ b/src/testcurl/daemontest_get.c | |||
@@ -188,6 +188,55 @@ testMultithreadedGet () | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | static int | ||
192 | testMultithreadedPoolGet () | ||
193 | { | ||
194 | struct MHD_Daemon *d; | ||
195 | CURL *c; | ||
196 | char buf[2048]; | ||
197 | struct CBC cbc; | ||
198 | CURLcode errornum; | ||
199 | |||
200 | cbc.buf = buf; | ||
201 | cbc.size = 2048; | ||
202 | cbc.pos = 0; | ||
203 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
204 | 1081, NULL, NULL, &ahc_echo, "GET", | ||
205 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
206 | if (d == NULL) | ||
207 | return 16; | ||
208 | c = curl_easy_init (); | ||
209 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
210 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
211 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
212 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
213 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
214 | if (oneone) | ||
215 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
216 | else | ||
217 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
218 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
219 | // NOTE: use of CONNECTTIMEOUT without also | ||
220 | // setting NOSIGNAL results in really weird | ||
221 | // crashes on my system! | ||
222 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
223 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
224 | { | ||
225 | fprintf (stderr, | ||
226 | "curl_easy_perform failed: `%s'\n", | ||
227 | curl_easy_strerror (errornum)); | ||
228 | curl_easy_cleanup (c); | ||
229 | MHD_stop_daemon (d); | ||
230 | return 32; | ||
231 | } | ||
232 | curl_easy_cleanup (c); | ||
233 | MHD_stop_daemon (d); | ||
234 | if (cbc.pos != strlen ("/hello_world")) | ||
235 | return 64; | ||
236 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
237 | return 128; | ||
238 | return 0; | ||
239 | } | ||
191 | 240 | ||
192 | static int | 241 | static int |
193 | testExternalGet () | 242 | testExternalGet () |
@@ -323,6 +372,7 @@ main (int argc, char *const *argv) | |||
323 | return 2; | 372 | return 2; |
324 | errorCount += testInternalGet (); | 373 | errorCount += testInternalGet (); |
325 | errorCount += testMultithreadedGet (); | 374 | errorCount += testMultithreadedGet (); |
375 | errorCount += testMultithreadedPoolGet (); | ||
326 | errorCount += testExternalGet (); | 376 | errorCount += testExternalGet (); |
327 | if (errorCount != 0) | 377 | if (errorCount != 0) |
328 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 378 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_get_chunked.c b/src/testcurl/daemontest_get_chunked.c index 794430e8..da11e90c 100644 --- a/src/testcurl/daemontest_get_chunked.c +++ b/src/testcurl/daemontest_get_chunked.c | |||
@@ -227,6 +227,48 @@ testMultithreadedGet () | |||
227 | return validate (cbc, 64); | 227 | return validate (cbc, 64); |
228 | } | 228 | } |
229 | 229 | ||
230 | static int | ||
231 | testMultithreadedPoolGet () | ||
232 | { | ||
233 | struct MHD_Daemon *d; | ||
234 | CURL *c; | ||
235 | char buf[2048]; | ||
236 | struct CBC cbc; | ||
237 | CURLcode errornum; | ||
238 | |||
239 | cbc.buf = buf; | ||
240 | cbc.size = 2048; | ||
241 | cbc.pos = 0; | ||
242 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
243 | 1081, NULL, NULL, &ahc_echo, "GET", | ||
244 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
245 | if (d == NULL) | ||
246 | return 16; | ||
247 | c = curl_easy_init (); | ||
248 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
249 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
250 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
251 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
252 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
253 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
254 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
255 | // NOTE: use of CONNECTTIMEOUT without also | ||
256 | // setting NOSIGNAL results in really weird | ||
257 | // crashes on my system! | ||
258 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
259 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
260 | { | ||
261 | fprintf (stderr, | ||
262 | "curl_easy_perform failed: `%s'\n", | ||
263 | curl_easy_strerror (errornum)); | ||
264 | curl_easy_cleanup (c); | ||
265 | MHD_stop_daemon (d); | ||
266 | return 32; | ||
267 | } | ||
268 | curl_easy_cleanup (c); | ||
269 | MHD_stop_daemon (d); | ||
270 | return validate (cbc, 64); | ||
271 | } | ||
230 | 272 | ||
231 | static int | 273 | static int |
232 | testExternalGet () | 274 | testExternalGet () |
@@ -354,6 +396,7 @@ main (int argc, char *const *argv) | |||
354 | return 2; | 396 | return 2; |
355 | errorCount += testInternalGet (); | 397 | errorCount += testInternalGet (); |
356 | errorCount += testMultithreadedGet (); | 398 | errorCount += testMultithreadedGet (); |
399 | errorCount += testMultithreadedPoolGet (); | ||
357 | errorCount += testExternalGet (); | 400 | errorCount += testExternalGet (); |
358 | if (errorCount != 0) | 401 | if (errorCount != 0) |
359 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 402 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_iplimit.c b/src/testcurl/daemontest_iplimit.c index e8ec0e8d..f9b5aba5 100644 --- a/src/testcurl/daemontest_iplimit.c +++ b/src/testcurl/daemontest_iplimit.c | |||
@@ -90,6 +90,103 @@ ahc_echo (void *cls, | |||
90 | } | 90 | } |
91 | 91 | ||
92 | static int | 92 | static int |
93 | testMultithreadedGet () | ||
94 | { | ||
95 | struct MHD_Daemon *d; | ||
96 | char buf[2048]; | ||
97 | int k; | ||
98 | |||
99 | /* Test only valid for HTTP/1.1 (uses persistent connections) */ | ||
100 | if (!oneone) | ||
101 | return 0; | ||
102 | |||
103 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
104 | 1081, NULL, NULL, &ahc_echo, "GET", | ||
105 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2, | ||
106 | MHD_OPTION_END); | ||
107 | if (d == NULL) | ||
108 | return 16; | ||
109 | |||
110 | for (k = 0; k < 3; ++k) | ||
111 | { | ||
112 | struct CBC cbc[3]; | ||
113 | CURL *cenv[3]; | ||
114 | int i; | ||
115 | |||
116 | for (i = 0; i < 3; ++i) | ||
117 | { | ||
118 | CURL *c; | ||
119 | CURLcode errornum; | ||
120 | |||
121 | cenv[i] = c = curl_easy_init (); | ||
122 | cbc[i].buf = buf; | ||
123 | cbc[i].size = 2048; | ||
124 | cbc[i].pos = 0; | ||
125 | |||
126 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
127 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
128 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]); | ||
129 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
130 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
131 | curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L); | ||
132 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
133 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
134 | // NOTE: use of CONNECTTIMEOUT without also | ||
135 | // setting NOSIGNAL results in really weird | ||
136 | // crashes on my system! | ||
137 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
138 | |||
139 | errornum = curl_easy_perform (c); | ||
140 | if (CURLE_OK != errornum && i < 2 | ||
141 | || CURLE_OK == errornum && i == 2) | ||
142 | { | ||
143 | int j; | ||
144 | |||
145 | /* First 2 should succeed */ | ||
146 | if (i < 2) | ||
147 | fprintf (stderr, | ||
148 | "curl_easy_perform failed: `%s'\n", | ||
149 | curl_easy_strerror (errornum)); | ||
150 | |||
151 | /* Last request should have failed */ | ||
152 | else | ||
153 | fprintf (stderr, | ||
154 | "No error on IP address over limit\n"); | ||
155 | |||
156 | for (j = 0; j < i; ++j) | ||
157 | curl_easy_cleanup (cenv[j]); | ||
158 | MHD_stop_daemon (d); | ||
159 | return 32; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* Cleanup the environments */ | ||
164 | for (i = 0; i < 3; ++i) | ||
165 | curl_easy_cleanup (cenv[i]); | ||
166 | |||
167 | sleep(2); | ||
168 | |||
169 | for (i = 0; i < 2; ++i) | ||
170 | { | ||
171 | if (cbc[i].pos != strlen ("/hello_world")) | ||
172 | { | ||
173 | MHD_stop_daemon (d); | ||
174 | return 64; | ||
175 | } | ||
176 | if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world"))) | ||
177 | { | ||
178 | MHD_stop_daemon (d); | ||
179 | return 128; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | |||
184 | } | ||
185 | MHD_stop_daemon (d); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int | ||
93 | testMultithreadedPoolGet () | 190 | testMultithreadedPoolGet () |
94 | { | 191 | { |
95 | struct MHD_Daemon *d; | 192 | struct MHD_Daemon *d; |
@@ -103,6 +200,7 @@ testMultithreadedPoolGet () | |||
103 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | 200 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, |
104 | 1081, NULL, NULL, &ahc_echo, "GET", | 201 | 1081, NULL, NULL, &ahc_echo, "GET", |
105 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2, | 202 | MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2, |
203 | MHD_OPTION_THREAD_POOL_SIZE, 4, | ||
106 | MHD_OPTION_END); | 204 | MHD_OPTION_END); |
107 | if (d == NULL) | 205 | if (d == NULL) |
108 | return 16; | 206 | return 16; |
@@ -194,6 +292,7 @@ main (int argc, char *const *argv) | |||
194 | oneone = NULL != strstr (argv[0], "11"); | 292 | oneone = NULL != strstr (argv[0], "11"); |
195 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) | 293 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) |
196 | return 2; | 294 | return 2; |
295 | errorCount += testMultithreadedGet (); | ||
197 | errorCount += testMultithreadedPoolGet (); | 296 | errorCount += testMultithreadedPoolGet (); |
198 | if (errorCount != 0) | 297 | if (errorCount != 0) |
199 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 298 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_large_put.c b/src/testcurl/daemontest_large_put.c index 069916a2..a454c5c5 100644 --- a/src/testcurl/daemontest_large_put.c +++ b/src/testcurl/daemontest_large_put.c | |||
@@ -245,6 +245,65 @@ testMultithreadedPut () | |||
245 | return 0; | 245 | return 0; |
246 | } | 246 | } |
247 | 247 | ||
248 | static int | ||
249 | testMultithreadedPoolPut () | ||
250 | { | ||
251 | struct MHD_Daemon *d; | ||
252 | CURL *c; | ||
253 | struct CBC cbc; | ||
254 | unsigned int pos = 0; | ||
255 | int done_flag = 0; | ||
256 | CURLcode errornum; | ||
257 | char buf[2048]; | ||
258 | |||
259 | cbc.buf = buf; | ||
260 | cbc.size = 2048; | ||
261 | cbc.pos = 0; | ||
262 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
263 | 1081, | ||
264 | NULL, NULL, &ahc_echo, &done_flag, | ||
265 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
266 | if (d == NULL) | ||
267 | return 16; | ||
268 | c = curl_easy_init (); | ||
269 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
270 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
271 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
272 | curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); | ||
273 | curl_easy_setopt (c, CURLOPT_READDATA, &pos); | ||
274 | curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); | ||
275 | curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE); | ||
276 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
277 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
278 | if (oneone) | ||
279 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
280 | else | ||
281 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
282 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
283 | // NOTE: use of CONNECTTIMEOUT without also | ||
284 | // setting NOSIGNAL results in really weird | ||
285 | // crashes on my system! | ||
286 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
287 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
288 | { | ||
289 | fprintf (stderr, | ||
290 | "curl_easy_perform failed: `%s'\n", | ||
291 | curl_easy_strerror (errornum)); | ||
292 | curl_easy_cleanup (c); | ||
293 | MHD_stop_daemon (d); | ||
294 | return 32; | ||
295 | } | ||
296 | curl_easy_cleanup (c); | ||
297 | MHD_stop_daemon (d); | ||
298 | if (cbc.pos != strlen ("/hello_world")) | ||
299 | { | ||
300 | fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf); | ||
301 | return 64; | ||
302 | } | ||
303 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
304 | return 128; | ||
305 | return 0; | ||
306 | } | ||
248 | 307 | ||
249 | static int | 308 | static int |
250 | testExternalPut () | 309 | testExternalPut () |
@@ -394,6 +453,7 @@ main (int argc, char *const *argv) | |||
394 | memset (put_buffer, 1, PUT_SIZE); | 453 | memset (put_buffer, 1, PUT_SIZE); |
395 | errorCount += testInternalPut (); | 454 | errorCount += testInternalPut (); |
396 | errorCount += testMultithreadedPut (); | 455 | errorCount += testMultithreadedPut (); |
456 | errorCount += testMultithreadedPoolPut (); | ||
397 | errorCount += testExternalPut (); | 457 | errorCount += testExternalPut (); |
398 | free (put_buffer); | 458 | free (put_buffer); |
399 | if (errorCount != 0) | 459 | if (errorCount != 0) |
diff --git a/src/testcurl/daemontest_post.c b/src/testcurl/daemontest_post.c index 0ef2bbb7..715047fe 100644 --- a/src/testcurl/daemontest_post.c +++ b/src/testcurl/daemontest_post.c | |||
@@ -231,6 +231,58 @@ testMultithreadedPost () | |||
231 | return 0; | 231 | return 0; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int | ||
235 | testMultithreadedPoolPost () | ||
236 | { | ||
237 | struct MHD_Daemon *d; | ||
238 | CURL *c; | ||
239 | char buf[2048]; | ||
240 | struct CBC cbc; | ||
241 | CURLcode errornum; | ||
242 | |||
243 | cbc.buf = buf; | ||
244 | cbc.size = 2048; | ||
245 | cbc.pos = 0; | ||
246 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
247 | 1081, NULL, NULL, &ahc_echo, NULL, | ||
248 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
249 | if (d == NULL) | ||
250 | return 16; | ||
251 | c = curl_easy_init (); | ||
252 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
253 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
254 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
255 | curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); | ||
256 | curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); | ||
257 | curl_easy_setopt (c, CURLOPT_POST, 1L); | ||
258 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
259 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
260 | if (oneone) | ||
261 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
262 | else | ||
263 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
264 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
265 | // NOTE: use of CONNECTTIMEOUT without also | ||
266 | // setting NOSIGNAL results in really weird | ||
267 | // crashes on my system! | ||
268 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
269 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
270 | { | ||
271 | fprintf (stderr, | ||
272 | "curl_easy_perform failed: `%s'\n", | ||
273 | curl_easy_strerror (errornum)); | ||
274 | curl_easy_cleanup (c); | ||
275 | MHD_stop_daemon (d); | ||
276 | return 32; | ||
277 | } | ||
278 | curl_easy_cleanup (c); | ||
279 | MHD_stop_daemon (d); | ||
280 | if (cbc.pos != strlen ("/hello_world")) | ||
281 | return 64; | ||
282 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
283 | return 128; | ||
284 | return 0; | ||
285 | } | ||
234 | 286 | ||
235 | static int | 287 | static int |
236 | testExternalPost () | 288 | testExternalPost () |
@@ -369,6 +421,7 @@ main (int argc, char *const *argv) | |||
369 | return 2; | 421 | return 2; |
370 | errorCount += testInternalPost (); | 422 | errorCount += testInternalPost (); |
371 | errorCount += testMultithreadedPost (); | 423 | errorCount += testMultithreadedPost (); |
424 | errorCount += testMultithreadedPoolPost (); | ||
372 | errorCount += testExternalPost (); | 425 | errorCount += testExternalPost (); |
373 | if (errorCount != 0) | 426 | if (errorCount != 0) |
374 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 427 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_post_loop.c b/src/testcurl/daemontest_post_loop.c index 0c74f96a..b1e1ab3f 100644 --- a/src/testcurl/daemontest_post_loop.c +++ b/src/testcurl/daemontest_post_loop.c | |||
@@ -225,6 +225,70 @@ testMultithreadedPost () | |||
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int | ||
229 | testMultithreadedPoolPost () | ||
230 | { | ||
231 | struct MHD_Daemon *d; | ||
232 | CURL *c; | ||
233 | char buf[2048]; | ||
234 | struct CBC cbc; | ||
235 | CURLcode errornum; | ||
236 | int i; | ||
237 | char url[1024]; | ||
238 | |||
239 | cbc.buf = buf; | ||
240 | cbc.size = 2048; | ||
241 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
242 | 1081, NULL, NULL, &ahc_echo, NULL, | ||
243 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
244 | if (d == NULL) | ||
245 | return 16; | ||
246 | for (i = 0; i < LOOPCOUNT; i++) | ||
247 | { | ||
248 | if (99 == i % 100) | ||
249 | fprintf (stderr, "."); | ||
250 | c = curl_easy_init (); | ||
251 | cbc.pos = 0; | ||
252 | buf[0] = '\0'; | ||
253 | sprintf (url, "http://localhost:1081/hw%d", i); | ||
254 | curl_easy_setopt (c, CURLOPT_URL, url); | ||
255 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
256 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
257 | curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); | ||
258 | curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); | ||
259 | curl_easy_setopt (c, CURLOPT_POST, 1L); | ||
260 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
261 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
262 | if (oneone) | ||
263 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
264 | else | ||
265 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
266 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
267 | // NOTE: use of CONNECTTIMEOUT without also | ||
268 | // setting NOSIGNAL results in really weird | ||
269 | // crashes on my system! | ||
270 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
271 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
272 | { | ||
273 | fprintf (stderr, | ||
274 | "curl_easy_perform failed: `%s'\n", | ||
275 | curl_easy_strerror (errornum)); | ||
276 | curl_easy_cleanup (c); | ||
277 | MHD_stop_daemon (d); | ||
278 | return 32; | ||
279 | } | ||
280 | curl_easy_cleanup (c); | ||
281 | if ((buf[0] != 'O') || (buf[1] != 'K')) | ||
282 | { | ||
283 | MHD_stop_daemon (d); | ||
284 | return 64; | ||
285 | } | ||
286 | } | ||
287 | MHD_stop_daemon (d); | ||
288 | if (LOOPCOUNT >= 99) | ||
289 | fprintf (stderr, "\n"); | ||
290 | return 0; | ||
291 | } | ||
228 | 292 | ||
229 | static int | 293 | static int |
230 | testExternalPost () | 294 | testExternalPost () |
@@ -379,6 +443,7 @@ main (int argc, char *const *argv) | |||
379 | return 2; | 443 | return 2; |
380 | errorCount += testInternalPost (); | 444 | errorCount += testInternalPost (); |
381 | errorCount += testMultithreadedPost (); | 445 | errorCount += testMultithreadedPost (); |
446 | errorCount += testMultithreadedPoolPost (); | ||
382 | errorCount += testExternalPost (); | 447 | errorCount += testExternalPost (); |
383 | if (errorCount != 0) | 448 | if (errorCount != 0) |
384 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 449 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_postform.c b/src/testcurl/daemontest_postform.c index 477713c3..a1e29f69 100644 --- a/src/testcurl/daemontest_postform.c +++ b/src/testcurl/daemontest_postform.c | |||
@@ -251,6 +251,60 @@ testMultithreadedPost () | |||
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
253 | 253 | ||
254 | static int | ||
255 | testMultithreadedPoolPost () | ||
256 | { | ||
257 | struct MHD_Daemon *d; | ||
258 | CURL *c; | ||
259 | char buf[2048]; | ||
260 | struct CBC cbc; | ||
261 | CURLcode errornum; | ||
262 | struct curl_httppost *pd; | ||
263 | |||
264 | cbc.buf = buf; | ||
265 | cbc.size = 2048; | ||
266 | cbc.pos = 0; | ||
267 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
268 | 1081, NULL, NULL, &ahc_echo, NULL, | ||
269 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
270 | if (d == NULL) | ||
271 | return 16; | ||
272 | c = curl_easy_init (); | ||
273 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
274 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
275 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
276 | pd = make_form (); | ||
277 | curl_easy_setopt (c, CURLOPT_HTTPPOST, pd); | ||
278 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
279 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
280 | if (oneone) | ||
281 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
282 | else | ||
283 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
284 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L); | ||
285 | // NOTE: use of CONNECTTIMEOUT without also | ||
286 | // setting NOSIGNAL results in really weird | ||
287 | // crashes on my system! | ||
288 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
289 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
290 | { | ||
291 | fprintf (stderr, | ||
292 | "curl_easy_perform failed: `%s'\n", | ||
293 | curl_easy_strerror (errornum)); | ||
294 | curl_easy_cleanup (c); | ||
295 | curl_formfree (pd); | ||
296 | MHD_stop_daemon (d); | ||
297 | return 32; | ||
298 | } | ||
299 | curl_easy_cleanup (c); | ||
300 | curl_formfree (pd); | ||
301 | MHD_stop_daemon (d); | ||
302 | if (cbc.pos != strlen ("/hello_world")) | ||
303 | return 64; | ||
304 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
305 | return 128; | ||
306 | return 0; | ||
307 | } | ||
254 | 308 | ||
255 | static int | 309 | static int |
256 | testExternalPost () | 310 | testExternalPost () |
@@ -394,6 +448,7 @@ main (int argc, char *const *argv) | |||
394 | return 2; | 448 | return 2; |
395 | errorCount += testInternalPost (); | 449 | errorCount += testInternalPost (); |
396 | errorCount += testMultithreadedPost (); | 450 | errorCount += testMultithreadedPost (); |
451 | errorCount += testMultithreadedPoolPost (); | ||
397 | errorCount += testExternalPost (); | 452 | errorCount += testExternalPost (); |
398 | if (errorCount != 0) | 453 | if (errorCount != 0) |
399 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 454 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_process_headers.c b/src/testcurl/daemontest_process_headers.c index e59699db..cd4bd68c 100644 --- a/src/testcurl/daemontest_process_headers.c +++ b/src/testcurl/daemontest_process_headers.c | |||
@@ -235,6 +235,55 @@ testMultithreadedGet () | |||
235 | return 0; | 235 | return 0; |
236 | } | 236 | } |
237 | 237 | ||
238 | static int | ||
239 | testMultithreadedPoolGet () | ||
240 | { | ||
241 | struct MHD_Daemon *d; | ||
242 | CURL *c; | ||
243 | char buf[2048]; | ||
244 | struct CBC cbc; | ||
245 | CURLcode errornum; | ||
246 | |||
247 | cbc.buf = buf; | ||
248 | cbc.size = 2048; | ||
249 | cbc.pos = 0; | ||
250 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
251 | 21080, NULL, NULL, &ahc_echo, "GET", | ||
252 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
253 | if (d == NULL) | ||
254 | return 16; | ||
255 | c = curl_easy_init (); | ||
256 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world"); | ||
257 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
258 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
259 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
260 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
261 | if (oneone) | ||
262 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
263 | else | ||
264 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
265 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
266 | /* NOTE: use of CONNECTTIMEOUT without also | ||
267 | setting NOSIGNAL results in really weird | ||
268 | crashes on my system! */ | ||
269 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
270 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
271 | { | ||
272 | fprintf (stderr, | ||
273 | "curl_easy_perform failed: `%s'\n", | ||
274 | curl_easy_strerror (errornum)); | ||
275 | curl_easy_cleanup (c); | ||
276 | MHD_stop_daemon (d); | ||
277 | return 32; | ||
278 | } | ||
279 | curl_easy_cleanup (c); | ||
280 | MHD_stop_daemon (d); | ||
281 | if (cbc.pos != strlen ("/hello_world")) | ||
282 | return 64; | ||
283 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
284 | return 128; | ||
285 | return 0; | ||
286 | } | ||
238 | 287 | ||
239 | static int | 288 | static int |
240 | testExternalGet () | 289 | testExternalGet () |
@@ -370,6 +419,7 @@ main (int argc, char *const *argv) | |||
370 | return 2; | 419 | return 2; |
371 | errorCount += testInternalGet (); | 420 | errorCount += testInternalGet (); |
372 | errorCount += testMultithreadedGet (); | 421 | errorCount += testMultithreadedGet (); |
422 | errorCount += testMultithreadedPoolGet (); | ||
373 | errorCount += testExternalGet (); | 423 | errorCount += testExternalGet (); |
374 | if (errorCount != 0) | 424 | if (errorCount != 0) |
375 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 425 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_put.c b/src/testcurl/daemontest_put.c index 753af4f2..76e96320 100644 --- a/src/testcurl/daemontest_put.c +++ b/src/testcurl/daemontest_put.c | |||
@@ -223,6 +223,64 @@ testMultithreadedPut () | |||
223 | return 0; | 223 | return 0; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int | ||
227 | testMultithreadedPoolPut () | ||
228 | { | ||
229 | struct MHD_Daemon *d; | ||
230 | CURL *c; | ||
231 | char buf[2048]; | ||
232 | struct CBC cbc; | ||
233 | unsigned int pos = 0; | ||
234 | int done_flag = 0; | ||
235 | CURLcode errornum; | ||
236 | |||
237 | cbc.buf = buf; | ||
238 | cbc.size = 2048; | ||
239 | cbc.pos = 0; | ||
240 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
241 | 1081, | ||
242 | NULL, NULL, &ahc_echo, &done_flag, | ||
243 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
244 | if (d == NULL) | ||
245 | return 16; | ||
246 | c = curl_easy_init (); | ||
247 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world"); | ||
248 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
249 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
250 | curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); | ||
251 | curl_easy_setopt (c, CURLOPT_READDATA, &pos); | ||
252 | curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); | ||
253 | curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); | ||
254 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
255 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
256 | if (oneone) | ||
257 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
258 | else | ||
259 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
260 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
261 | // NOTE: use of CONNECTTIMEOUT without also | ||
262 | // setting NOSIGNAL results in really weird | ||
263 | // crashes on my system! | ||
264 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
265 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
266 | { | ||
267 | fprintf (stderr, | ||
268 | "curl_easy_perform failed: `%s'\n", | ||
269 | curl_easy_strerror (errornum)); | ||
270 | curl_easy_cleanup (c); | ||
271 | MHD_stop_daemon (d); | ||
272 | return 32; | ||
273 | } | ||
274 | curl_easy_cleanup (c); | ||
275 | MHD_stop_daemon (d); | ||
276 | if (cbc.pos != strlen ("/hello_world")) | ||
277 | return 64; | ||
278 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
279 | return 128; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
226 | 284 | ||
227 | static int | 285 | static int |
228 | testExternalPut () | 286 | testExternalPut () |
@@ -365,6 +423,7 @@ main (int argc, char *const *argv) | |||
365 | return 2; | 423 | return 2; |
366 | errorCount += testInternalPut (); | 424 | errorCount += testInternalPut (); |
367 | errorCount += testMultithreadedPut (); | 425 | errorCount += testMultithreadedPut (); |
426 | errorCount += testMultithreadedPoolPut (); | ||
368 | errorCount += testExternalPut (); | 427 | errorCount += testExternalPut (); |
369 | if (errorCount != 0) | 428 | if (errorCount != 0) |
370 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 429 | fprintf (stderr, "Error (code: %u)\n", errorCount); |
diff --git a/src/testcurl/daemontest_put_chunked.c b/src/testcurl/daemontest_put_chunked.c index 96c3f79c..3fa1f092 100644 --- a/src/testcurl/daemontest_put_chunked.c +++ b/src/testcurl/daemontest_put_chunked.c | |||
@@ -232,6 +232,64 @@ testMultithreadedPut () | |||
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | static int | ||
236 | testMultithreadedPoolPut () | ||
237 | { | ||
238 | struct MHD_Daemon *d; | ||
239 | CURL *c; | ||
240 | char buf[2048]; | ||
241 | struct CBC cbc; | ||
242 | unsigned int pos = 0; | ||
243 | int done_flag = 0; | ||
244 | CURLcode errornum; | ||
245 | |||
246 | cbc.buf = buf; | ||
247 | cbc.size = 2048; | ||
248 | cbc.pos = 0; | ||
249 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, | ||
250 | 11081, | ||
251 | NULL, NULL, &ahc_echo, &done_flag, | ||
252 | MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END); | ||
253 | if (d == NULL) | ||
254 | return 16; | ||
255 | c = curl_easy_init (); | ||
256 | curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); | ||
257 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
258 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
259 | curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); | ||
260 | curl_easy_setopt (c, CURLOPT_READDATA, &pos); | ||
261 | curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); | ||
262 | /* | ||
263 | // by not giving the file size, we force chunking! | ||
264 | curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); | ||
265 | */ | ||
266 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); | ||
267 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
268 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
269 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); | ||
270 | // NOTE: use of CONNECTTIMEOUT without also | ||
271 | // setting NOSIGNAL results in really weird | ||
272 | // crashes on my system! | ||
273 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | ||
274 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
275 | { | ||
276 | fprintf (stderr, | ||
277 | "curl_easy_perform failed: `%s'\n", | ||
278 | curl_easy_strerror (errornum)); | ||
279 | curl_easy_cleanup (c); | ||
280 | MHD_stop_daemon (d); | ||
281 | return 32; | ||
282 | } | ||
283 | curl_easy_cleanup (c); | ||
284 | MHD_stop_daemon (d); | ||
285 | if (cbc.pos != strlen ("/hello_world")) | ||
286 | return 64; | ||
287 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
288 | return 128; | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
235 | 293 | ||
236 | static int | 294 | static int |
237 | testExternalPut () | 295 | testExternalPut () |
@@ -373,6 +431,7 @@ main (int argc, char *const *argv) | |||
373 | return 2; | 431 | return 2; |
374 | errorCount += testInternalPut (); | 432 | errorCount += testInternalPut (); |
375 | errorCount += testMultithreadedPut (); | 433 | errorCount += testMultithreadedPut (); |
434 | errorCount += testMultithreadedPoolPut (); | ||
376 | errorCount += testExternalPut (); | 435 | errorCount += testExternalPut (); |
377 | if (errorCount != 0) | 436 | if (errorCount != 0) |
378 | fprintf (stderr, "Error (code: %u)\n", errorCount); | 437 | fprintf (stderr, "Error (code: %u)\n", errorCount); |