aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/test_get_iovec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/test_get_iovec.c')
-rw-r--r--src/testcurl/test_get_iovec.c757
1 files changed, 757 insertions, 0 deletions
diff --git a/src/testcurl/test_get_iovec.c b/src/testcurl/test_get_iovec.c
new file mode 100644
index 00000000..1d817851
--- /dev/null
+++ b/src/testcurl/test_get_iovec.c
@@ -0,0 +1,757 @@
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2021 Christian Grothoff
4 Copyright (C) 2014-2021 Evgeny Grin
5
6 libmicrohttpd is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2, or (at your
9 option) any later version.
10
11 libmicrohttpd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with libmicrohttpd; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @file test_get_iovec.c
24 * @brief Testcase for libmicrohttpd response from scatter/gather array
25 * @author Christian Grothoff
26 * @author Karlson2k (Evgeny Grin)
27 * @author Lawrence Sebald
28 */
29
30/*
31 * This test is largely derived from the test_get_sendfile.c file, with the
32 * daemon using MHD_create_response_from_iovec instead of working from an fd.
33 */
34
35#include "MHD_config.h"
36#include "platform.h"
37#include <curl/curl.h>
38#include <microhttpd.h>
39#include <stdlib.h>
40#include <string.h>
41#include <time.h>
42#include <sys/types.h>
43#include <fcntl.h>
44#include "mhd_sockets.h"
45#include "mhd_has_in_name.h"
46
47#ifndef WINDOWS
48#include <sys/socket.h>
49#include <unistd.h>
50#endif
51
52#if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 2
53#undef MHD_CPU_COUNT
54#endif
55#if ! defined(MHD_CPU_COUNT)
56#define MHD_CPU_COUNT 2
57#endif
58
59#define TESTSTR_IOVLEN 20480
60#define TESTSTR_IOVCNT 20
61#define TESTSTR_SIZE (TESTSTR_IOVCNT * TESTSTR_IOVLEN)
62
63static int oneone;
64
65static int readbuf[TESTSTR_SIZE * 2 / sizeof(int)];
66
67struct CBC
68{
69 char *buf;
70 size_t pos;
71 size_t size;
72};
73
74
75static size_t
76copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
77{
78 struct CBC *cbc = ctx;
79
80 if (cbc->pos + size * nmemb > cbc->size)
81 _exit (7); /* overflow */
82 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
83 cbc->pos += size * nmemb;
84 return size * nmemb;
85}
86
87
88static void
89iov_free_callback (void *cls)
90{
91 free (cls);
92}
93
94
95static void
96iovncont_free_callback (void *cls)
97{
98 struct MHD_IoVec *iov = (struct MHD_IoVec *) cls;
99 int i;
100
101 for (i = 0; i < TESTSTR_IOVCNT; ++i)
102 {
103 free (iov[i].iov_base);
104 }
105
106 free (iov);
107}
108
109
110static int
111check_read_data (const void *ptr, size_t len)
112{
113 const int *buf;
114 size_t i;
115
116 if (len % sizeof(int))
117 return -1;
118
119 buf = (const int *) ptr;
120
121 for (i = 0; i < len / sizeof(int); ++i)
122 {
123 if (buf[i] != (int) i)
124 return -1;
125 }
126
127 return 0;
128}
129
130
131static enum MHD_Result
132ahc_echo (void *cls,
133 struct MHD_Connection *connection,
134 const char *url,
135 const char *method,
136 const char *version,
137 const char *upload_data, size_t *upload_data_size,
138 void **unused)
139{
140 static int ptr;
141 const char *me = cls;
142 struct MHD_Response *response;
143 enum MHD_Result ret;
144 int *data;
145 struct MHD_IoVec iov[TESTSTR_IOVCNT];
146 int i;
147 (void) url; (void) version; /* Unused. Silent compiler warning. */
148 (void) upload_data; (void) upload_data_size; /* Unused. Silent compiler warning. */
149
150 if (0 != strcmp (me, method))
151 return MHD_NO; /* unexpected method */
152 if (&ptr != *unused)
153 {
154 *unused = &ptr;
155 return MHD_YES;
156 }
157 *unused = NULL;
158
159 /* Create some test data. */
160 if (NULL == (data = malloc (TESTSTR_SIZE)))
161 return MHD_NO;
162
163 for (i = 0; i < (int) (TESTSTR_SIZE / sizeof(int)); ++i)
164 {
165 data[i] = i;
166 }
167
168 for (i = 0; i < TESTSTR_IOVCNT; ++i)
169 {
170 iov[i].iov_base = data + (i * (TESTSTR_SIZE / TESTSTR_IOVCNT
171 / sizeof(int)));
172 iov[i].iov_len = TESTSTR_SIZE / TESTSTR_IOVCNT;
173 }
174
175 response = MHD_create_response_from_iovec (iov,
176 TESTSTR_IOVCNT,
177 &iov_free_callback,
178 data);
179 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
180 MHD_destroy_response (response);
181 if (ret == MHD_NO)
182 abort ();
183 return ret;
184}
185
186
187static enum MHD_Result
188ncont_echo (void *cls,
189 struct MHD_Connection *connection,
190 const char *url,
191 const char *method,
192 const char *version,
193 const char *upload_data, size_t *upload_data_size,
194 void **unused)
195{
196 static int ptr;
197 const char *me = cls;
198 struct MHD_Response *response;
199 enum MHD_Result ret;
200 int *data;
201 struct MHD_IoVec *iov;
202 int i, j;
203 (void) url; (void) version; /* Unused. Silent compiler warning. */
204 (void) upload_data; (void) upload_data_size; /* Unused. Silent compiler warning. */
205
206 if (0 != strcmp (me, method))
207 return MHD_NO; /* unexpected method */
208 if (&ptr != *unused)
209 {
210 *unused = &ptr;
211 return MHD_YES;
212 }
213 *unused = NULL;
214
215 if (NULL == (iov = malloc (sizeof(struct MHD_IoVec) * TESTSTR_IOVCNT)))
216 return MHD_NO;
217
218 memset (iov, 0, sizeof(struct MHD_IoVec) * TESTSTR_IOVCNT);
219
220 /* Create some test data. */
221 for (j = TESTSTR_IOVCNT - 1; j >= 0; --j)
222 {
223 if (NULL == (data = malloc (TESTSTR_IOVLEN)))
224 goto err_out;
225
226 iov[j].iov_base = data;
227 iov[j].iov_len = TESTSTR_IOVLEN;
228
229 for (i = 0; i < (int) (TESTSTR_IOVLEN / sizeof(int)); ++i)
230 {
231 data[i] = i + (j * TESTSTR_IOVLEN / sizeof(int));
232 }
233 }
234
235 response = MHD_create_response_from_iovec (iov,
236 TESTSTR_IOVCNT,
237 &iovncont_free_callback,
238 iov);
239 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
240 MHD_destroy_response (response);
241 if (ret == MHD_NO)
242 abort ();
243 return ret;
244
245err_out:
246 for (j = 0; j < TESTSTR_IOVCNT; ++j)
247 {
248 if (NULL != iov[j].iov_base)
249 free (iov[j].iov_base);
250 }
251
252 return MHD_NO;
253}
254
255
256static int
257testInternalGet (bool contiguous)
258{
259 struct MHD_Daemon *d;
260 CURL *c;
261 struct CBC cbc;
262 CURLcode errornum;
263 int port;
264
265 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
266 port = 0;
267 else
268 {
269 port = 1200;
270 if (oneone)
271 port += 10;
272 }
273
274 cbc.buf = (char*) readbuf;
275 cbc.size = sizeof(readbuf);
276 cbc.pos = 0;
277
278 if (contiguous)
279 {
280 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
281 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
282 }
283 else
284 {
285 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
286 port, NULL, NULL, &ncont_echo, "GET", MHD_OPTION_END);
287 }
288
289 if (d == NULL)
290 return 1;
291 if (0 == port)
292 {
293 const union MHD_DaemonInfo *dinfo;
294 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
295 if ((NULL == dinfo) || (0 == dinfo->port) )
296 {
297 MHD_stop_daemon (d); return 32;
298 }
299 port = (int) dinfo->port;
300 }
301 c = curl_easy_init ();
302 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/");
303 curl_easy_setopt (c, CURLOPT_PORT, (long) port);
304 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
305 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
306 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
307 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
308 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
309 if (oneone)
310 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
311 else
312 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
313 /* NOTE: use of CONNECTTIMEOUT without also
314 setting NOSIGNAL results in really weird
315 crashes on my system!*/
316 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
317 if (CURLE_OK != (errornum = curl_easy_perform (c)))
318 {
319 fprintf (stderr,
320 "curl_easy_perform failed: `%s'\n",
321 curl_easy_strerror (errornum));
322 curl_easy_cleanup (c);
323 MHD_stop_daemon (d);
324 return 2;
325 }
326 curl_easy_cleanup (c);
327 MHD_stop_daemon (d);
328 if (cbc.pos != TESTSTR_SIZE)
329 return 4;
330 if (0 != check_read_data (cbc.buf, cbc.pos))
331 return 8;
332 return 0;
333}
334
335
336static int
337testMultithreadedGet ()
338{
339 struct MHD_Daemon *d;
340 CURL *c;
341 struct CBC cbc;
342 CURLcode errornum;
343 int port;
344
345 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
346 port = 0;
347 else
348 {
349 port = 1201;
350 if (oneone)
351 port += 10;
352 }
353
354 cbc.buf = (char*) readbuf;
355 cbc.size = sizeof(readbuf);
356 cbc.pos = 0;
357 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
358 | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG
359 | MHD_USE_AUTO,
360 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
361 if (d == NULL)
362 return 16;
363 if (0 == port)
364 {
365 const union MHD_DaemonInfo *dinfo;
366 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
367 if ((NULL == dinfo) || (0 == dinfo->port) )
368 {
369 MHD_stop_daemon (d); return 32;
370 }
371 port = (int) dinfo->port;
372 }
373 c = curl_easy_init ();
374 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/");
375 curl_easy_setopt (c, CURLOPT_PORT, (long) port);
376 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
377 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
378 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
379 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
380 if (oneone)
381 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
382 else
383 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
384 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
385 /* NOTE: use of CONNECTTIMEOUT without also
386 setting NOSIGNAL results in really weird
387 crashes on my system! */
388 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
389 if (CURLE_OK != (errornum = curl_easy_perform (c)))
390 {
391 fprintf (stderr,
392 "curl_easy_perform failed: `%s'\n",
393 curl_easy_strerror (errornum));
394 curl_easy_cleanup (c);
395 MHD_stop_daemon (d);
396 return 32;
397 }
398 curl_easy_cleanup (c);
399 MHD_stop_daemon (d);
400 if (cbc.pos != TESTSTR_SIZE)
401 return 64;
402 if (0 != check_read_data (cbc.buf, cbc.pos))
403 return 128;
404 return 0;
405}
406
407
408static int
409testMultithreadedPoolGet ()
410{
411 struct MHD_Daemon *d;
412 CURL *c;
413 struct CBC cbc;
414 CURLcode errornum;
415 int port;
416
417 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
418 port = 0;
419 else
420 {
421 port = 1202;
422 if (oneone)
423 port += 10;
424 }
425
426 cbc.buf = (char*) readbuf;
427 cbc.size = sizeof(readbuf);
428 cbc.pos = 0;
429 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG
430 | MHD_USE_AUTO,
431 port, NULL, NULL, &ahc_echo, "GET",
432 MHD_OPTION_THREAD_POOL_SIZE, MHD_CPU_COUNT,
433 MHD_OPTION_END);
434 if (d == NULL)
435 return 16;
436 if (0 == port)
437 {
438 const union MHD_DaemonInfo *dinfo;
439 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
440 if ((NULL == dinfo) || (0 == dinfo->port) )
441 {
442 MHD_stop_daemon (d); return 32;
443 }
444 port = (int) dinfo->port;
445 }
446 c = curl_easy_init ();
447 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/");
448 curl_easy_setopt (c, CURLOPT_PORT, (long) port);
449 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
450 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
451 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
452 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
453 if (oneone)
454 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
455 else
456 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
457 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
458 /* NOTE: use of CONNECTTIMEOUT without also
459 setting NOSIGNAL results in really weird
460 crashes on my system!*/
461 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
462 if (CURLE_OK != (errornum = curl_easy_perform (c)))
463 {
464 fprintf (stderr,
465 "curl_easy_perform failed: `%s'\n",
466 curl_easy_strerror (errornum));
467 curl_easy_cleanup (c);
468 MHD_stop_daemon (d);
469 return 32;
470 }
471 curl_easy_cleanup (c);
472 MHD_stop_daemon (d);
473 if (cbc.pos != TESTSTR_SIZE)
474 return 64;
475 if (0 != check_read_data (cbc.buf, cbc.pos))
476 return 128;
477 return 0;
478}
479
480
481static int
482testExternalGet ()
483{
484 struct MHD_Daemon *d;
485 CURL *c;
486 struct CBC cbc;
487 CURLM *multi;
488 CURLMcode mret;
489 fd_set rs;
490 fd_set ws;
491 fd_set es;
492 MHD_socket maxsock;
493#ifdef MHD_WINSOCK_SOCKETS
494 int maxposixs; /* Max socket number unused on W32 */
495#else /* MHD_POSIX_SOCKETS */
496#define maxposixs maxsock
497#endif /* MHD_POSIX_SOCKETS */
498 int running;
499 struct CURLMsg *msg;
500 time_t start;
501 struct timeval tv;
502 int port;
503
504 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
505 port = 0;
506 else
507 {
508 port = 1203;
509 if (oneone)
510 port += 10;
511 }
512
513 multi = NULL;
514 cbc.buf = (char*) readbuf;
515 cbc.size = sizeof(readbuf);
516 cbc.pos = 0;
517 d = MHD_start_daemon (MHD_USE_ERROR_LOG,
518 port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
519 if (d == NULL)
520 return 256;
521 if (0 == port)
522 {
523 const union MHD_DaemonInfo *dinfo;
524 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
525 if ((NULL == dinfo) || (0 == dinfo->port) )
526 {
527 MHD_stop_daemon (d); return 32;
528 }
529 port = (int) dinfo->port;
530 }
531 c = curl_easy_init ();
532 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/");
533 curl_easy_setopt (c, CURLOPT_PORT, (long) port);
534 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
535 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
536 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
537 if (oneone)
538 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
539 else
540 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
541 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
542 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
543 /* NOTE: use of CONNECTTIMEOUT without also
544 setting NOSIGNAL results in really weird
545 crashes on my system! */
546 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
547
548
549 multi = curl_multi_init ();
550 if (multi == NULL)
551 {
552 curl_easy_cleanup (c);
553 MHD_stop_daemon (d);
554 return 512;
555 }
556 mret = curl_multi_add_handle (multi, c);
557 if (mret != CURLM_OK)
558 {
559 curl_multi_cleanup (multi);
560 curl_easy_cleanup (c);
561 MHD_stop_daemon (d);
562 return 1024;
563 }
564 start = time (NULL);
565 while ((time (NULL) - start < 5) && (multi != NULL))
566 {
567 maxsock = MHD_INVALID_SOCKET;
568 maxposixs = -1;
569 FD_ZERO (&rs);
570 FD_ZERO (&ws);
571 FD_ZERO (&es);
572 curl_multi_perform (multi, &running);
573 mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
574 if (mret != CURLM_OK)
575 {
576 curl_multi_remove_handle (multi, c);
577 curl_multi_cleanup (multi);
578 curl_easy_cleanup (c);
579 MHD_stop_daemon (d);
580 return 2048;
581 }
582 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
583 {
584 curl_multi_remove_handle (multi, c);
585 curl_multi_cleanup (multi);
586 curl_easy_cleanup (c);
587 MHD_stop_daemon (d);
588 return 4096;
589 }
590 tv.tv_sec = 0;
591 tv.tv_usec = 1000;
592 if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv))
593 {
594#ifdef MHD_POSIX_SOCKETS
595 if (EINTR != errno)
596 abort ();
597#else
598 if ((WSAEINVAL != WSAGetLastError ()) || (0 != rs.fd_count) || (0 !=
599 ws.
600 fd_count)
601 || (0 != es.fd_count) )
602 abort ();
603 Sleep (1000);
604#endif
605 }
606 curl_multi_perform (multi, &running);
607 if (running == 0)
608 {
609 msg = curl_multi_info_read (multi, &running);
610 if (msg == NULL)
611 break;
612 if (msg->msg == CURLMSG_DONE)
613 {
614 if (msg->data.result != CURLE_OK)
615 printf ("%s failed at %s:%d: `%s'\n",
616 "curl_multi_perform",
617 __FILE__,
618 __LINE__, curl_easy_strerror (msg->data.result));
619 curl_multi_remove_handle (multi, c);
620 curl_multi_cleanup (multi);
621 curl_easy_cleanup (c);
622 c = NULL;
623 multi = NULL;
624 }
625 }
626 MHD_run (d);
627 }
628 if (multi != NULL)
629 {
630 curl_multi_remove_handle (multi, c);
631 curl_easy_cleanup (c);
632 curl_multi_cleanup (multi);
633 }
634 MHD_stop_daemon (d);
635 if (cbc.pos != TESTSTR_SIZE)
636 return 8192;
637 if (0 != check_read_data (cbc.buf, cbc.pos))
638 return 16384;
639 return 0;
640}
641
642
643static int
644testUnknownPortGet ()
645{
646 struct MHD_Daemon *d;
647 const union MHD_DaemonInfo *di;
648 CURL *c;
649 struct CBC cbc;
650 CURLcode errornum;
651 int port;
652 char buf[2048];
653
654 struct sockaddr_in addr;
655 socklen_t addr_len = sizeof(addr);
656 memset (&addr, 0, sizeof(addr));
657 addr.sin_family = AF_INET;
658 addr.sin_port = 0;
659 addr.sin_addr.s_addr = INADDR_ANY;
660
661 cbc.buf = (char*) readbuf;
662 cbc.size = sizeof(readbuf);
663 cbc.pos = 0;
664 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
665 0, NULL, NULL, &ahc_echo, "GET",
666 MHD_OPTION_SOCK_ADDR, &addr,
667 MHD_OPTION_END);
668 if (d == NULL)
669 return 32768;
670
671 if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
672 {
673 di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD);
674 if (di == NULL)
675 return 65536;
676
677 if (0 != getsockname (di->listen_fd, (struct sockaddr *) &addr, &addr_len))
678 return 131072;
679
680 if (addr.sin_family != AF_INET)
681 return 26214;
682 port = (int) ntohs (addr.sin_port);
683 }
684 else
685 {
686 const union MHD_DaemonInfo *dinfo;
687 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
688 if ((NULL == dinfo) || (0 == dinfo->port) )
689 {
690 MHD_stop_daemon (d); return 32;
691 }
692 port = (int) dinfo->port;
693 }
694
695 snprintf (buf, sizeof(buf), "http://127.0.0.1:%d/",
696 port);
697
698 c = curl_easy_init ();
699 curl_easy_setopt (c, CURLOPT_URL, buf);
700 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
701 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
702 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
703 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
704 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
705 if (oneone)
706 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
707 else
708 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
709 /* NOTE: use of CONNECTTIMEOUT without also
710 setting NOSIGNAL results in really weird
711 crashes on my system! */
712 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
713 if (CURLE_OK != (errornum = curl_easy_perform (c)))
714 {
715 fprintf (stderr,
716 "curl_easy_perform failed: `%s'\n",
717 curl_easy_strerror (errornum));
718 curl_easy_cleanup (c);
719 MHD_stop_daemon (d);
720 return 524288;
721 }
722 curl_easy_cleanup (c);
723 MHD_stop_daemon (d);
724 if (cbc.pos != TESTSTR_SIZE)
725 return 1048576;
726 if (0 != check_read_data (cbc.buf, cbc.pos))
727 return 2097152;
728 return 0;
729}
730
731
732int
733main (int argc, char *const *argv)
734{
735 unsigned int errorCount = 0;
736 (void) argc; /* Unused. Silent compiler warning. */
737
738 if ((NULL == argv) || (0 == argv[0]))
739 return 99;
740 oneone = has_in_name (argv[0], "11");
741
742 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
743 return 2;
744 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS))
745 {
746 errorCount += testInternalGet (true);
747 errorCount += testInternalGet (false);
748 errorCount += testMultithreadedGet ();
749 errorCount += testMultithreadedPoolGet ();
750 errorCount += testUnknownPortGet ();
751 }
752 errorCount += testExternalGet ();
753 if (errorCount != 0)
754 fprintf (stderr, "Error (code: %u)\n", errorCount);
755 curl_global_cleanup ();
756 return errorCount != 0; /* 0 == pass */
757}