test_postform.c (20917B)
1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 Copyright (C) 2014-2023 Evgeny Grin (Karlson2k) 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_postform.c 24 * @brief Testcase for libmicrohttpd POST operations using multipart/postform data 25 * @author Christian Grothoff 26 * @author Karlson2k (Evgeny Grin) 27 */ 28 29 #include "MHD_config.h" 30 #include "platform.h" 31 #include <curl/curl.h> 32 #include <microhttpd.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #ifdef MHD_HTTPS_REQUIRE_GCRYPT 37 #ifdef HAVE_GCRYPT_H 38 #include <gcrypt.h> 39 #endif 40 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */ 41 #include <errno.h> 42 43 #ifndef WINDOWS 44 #include <unistd.h> 45 #endif 46 47 #ifndef CURL_VERSION_BITS 48 #define CURL_VERSION_BITS(x,y,z) ((x) << 16 | (y) << 8 | (z)) 49 #endif /* ! CURL_VERSION_BITS */ 50 #ifndef CURL_AT_LEAST_VERSION 51 #define CURL_AT_LEAST_VERSION(x,y,z) \ 52 (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS (x, y, z)) 53 #endif /* ! CURL_AT_LEAST_VERSION */ 54 55 #if CURL_AT_LEAST_VERSION (7,56,0) 56 #define HAS_CURL_MIME 1 57 #endif /* CURL_AT_LEAST_VERSION(7,56,0) */ 58 59 #include "mhd_has_in_name.h" 60 61 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this 62 test into a marked, classifiable test error (TESTING.md, P5). */ 63 #include "mhd_panic_tripwire.h" 64 65 #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 2 66 #undef MHD_CPU_COUNT 67 #endif 68 #if ! defined(MHD_CPU_COUNT) 69 #define MHD_CPU_COUNT 2 70 #endif 71 72 static int oneone; 73 74 struct CBC 75 { 76 char *buf; 77 size_t pos; 78 size_t size; 79 }; 80 81 82 static void 83 completed_cb (void *cls, 84 struct MHD_Connection *connection, 85 void **req_cls, 86 enum MHD_RequestTerminationCode toe) 87 { 88 struct MHD_PostProcessor *pp = *req_cls; 89 (void) cls; (void) connection; (void) toe; /* Unused. Silent compiler warning. */ 90 91 if (NULL != pp) 92 MHD_destroy_post_processor (pp); 93 *req_cls = NULL; 94 } 95 96 97 static size_t 98 copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) 99 { 100 struct CBC *cbc = ctx; 101 102 if (cbc->pos + size * nmemb > cbc->size) 103 return 0; /* overflow */ 104 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); 105 cbc->pos += size * nmemb; 106 return size * nmemb; 107 } 108 109 110 /** 111 * Note that this post_iterator is not perfect 112 * in that it fails to support incremental processing. 113 * (to be fixed in the future) 114 */ 115 static enum MHD_Result 116 post_iterator (void *cls, 117 enum MHD_ValueKind kind, 118 const char *key, 119 const char *filename, 120 const char *content_type, 121 const char *transfer_encoding, 122 const char *value, uint64_t off, size_t size) 123 { 124 int *eok = cls; 125 (void) kind; (void) filename; (void) content_type; /* Unused. Silent compiler warning. */ 126 (void) transfer_encoding; (void) off; /* Unused. Silent compiler warning. */ 127 128 #if 0 129 fprintf (stderr, "PI sees %s-%.*s\n", key, size, value); 130 #endif 131 if ((0 == strcmp (key, "name")) && 132 (size == strlen ("daniel")) && (0 == strncmp (value, "daniel", size))) 133 (*eok) |= 1; 134 if ((0 == strcmp (key, "project")) && 135 (size == strlen ("curl")) && (0 == strncmp (value, "curl", size))) 136 (*eok) |= 2; 137 return MHD_YES; 138 } 139 140 141 static enum MHD_Result 142 ahc_echo (void *cls, 143 struct MHD_Connection *connection, 144 const char *url, 145 const char *method, 146 const char *version, 147 const char *upload_data, size_t *upload_data_size, 148 void **req_cls) 149 { 150 static int eok; 151 struct MHD_Response *response; 152 struct MHD_PostProcessor *pp; 153 enum MHD_Result ret; 154 (void) cls; (void) version; /* Unused. Silent compiler warning. */ 155 156 if (0 != strcmp ("POST", method)) 157 { 158 printf ("METHOD: %s\n", method); 159 return MHD_NO; /* unexpected method */ 160 } 161 pp = *req_cls; 162 if (pp == NULL) 163 { 164 eok = 0; 165 pp = MHD_create_post_processor (connection, 166 1024, 167 &post_iterator, 168 &eok); 169 if (NULL == pp) 170 abort (); 171 *req_cls = pp; 172 } 173 if (MHD_YES != 174 MHD_post_process (pp, 175 upload_data, 176 *upload_data_size)) 177 abort (); 178 if ((eok == 3) && (0 == *upload_data_size)) 179 { 180 response = MHD_create_response_from_buffer_copy (strlen (url), 181 (const void *) url); 182 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 183 MHD_destroy_response (response); 184 MHD_destroy_post_processor (pp); 185 *req_cls = NULL; 186 return ret; 187 } 188 *upload_data_size = 0; 189 return MHD_YES; 190 } 191 192 193 struct mhd_test_postdata 194 { 195 #if defined(HAS_CURL_MIME) 196 curl_mime *mime; 197 #else /* ! HAS_CURL_MIME */ 198 struct curl_httppost *post; 199 #endif /* ! HAS_CURL_MIME */ 200 }; 201 202 /* Return non-zero if succeed */ 203 static int 204 add_test_form (CURL *handle, struct mhd_test_postdata *postdata) 205 { 206 #if defined(HAS_CURL_MIME) 207 postdata->mime = curl_mime_init (handle); 208 if (NULL == postdata->mime) 209 return 0; 210 else 211 { 212 curl_mimepart *part; 213 part = curl_mime_addpart (postdata->mime); 214 if (NULL != part) 215 { 216 if ( (CURLE_OK == curl_mime_data (part, "daniel", 217 CURL_ZERO_TERMINATED)) && 218 (CURLE_OK == curl_mime_name (part, "name")) ) 219 { 220 part = curl_mime_addpart (postdata->mime); 221 if (NULL != part) 222 { 223 if ( (CURLE_OK == curl_mime_data (part, "curl", 224 CURL_ZERO_TERMINATED)) && 225 (CURLE_OK == curl_mime_name (part, "project")) ) 226 { 227 if (CURLE_OK == curl_easy_setopt (handle, 228 CURLOPT_MIMEPOST, postdata->mime)) 229 { 230 return ! 0; 231 } 232 } 233 } 234 } 235 } 236 } 237 curl_mime_free (postdata->mime); 238 postdata->mime = NULL; 239 return 0; 240 #else /* ! HAS_CURL_MIME */ 241 postdata->post = NULL; 242 struct curl_httppost *last = NULL; 243 244 if (0 == curl_formadd (&postdata->post, &last, 245 CURLFORM_COPYNAME, "name", 246 CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END)) 247 { 248 if (0 == curl_formadd (&postdata->post, &last, 249 CURLFORM_COPYNAME, "project", 250 CURLFORM_COPYCONTENTS, "curl", CURLFORM_END)) 251 { 252 if (CURLE_OK == curl_easy_setopt (handle, 253 CURLOPT_HTTPPOST, postdata->post)) 254 { 255 return ! 0; 256 } 257 } 258 } 259 curl_formfree (postdata->post); 260 return 0; 261 #endif /* ! HAS_CURL_MIME */ 262 } 263 264 265 static void 266 free_test_form (struct mhd_test_postdata *postdata) 267 { 268 #if defined(HAS_CURL_MIME) 269 if (NULL != postdata->mime) 270 curl_mime_free (postdata->mime); 271 #else /* ! HAS_CURL_MIME */ 272 if (NULL != postdata->post) 273 curl_formfree (postdata->post); 274 #endif /* ! HAS_CURL_MIME */ 275 } 276 277 278 static unsigned int 279 testInternalPost (void) 280 { 281 struct MHD_Daemon *d; 282 CURL *c; 283 char buf[2048]; 284 struct CBC cbc; 285 CURLcode errornum; 286 struct mhd_test_postdata form; 287 uint16_t port; 288 289 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 290 port = 0; 291 else 292 { 293 port = 1390; 294 if (oneone) 295 port += 10; 296 } 297 298 cbc.buf = buf; 299 cbc.size = 2048; 300 cbc.pos = 0; 301 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 302 port, NULL, NULL, &ahc_echo, NULL, 303 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, 304 MHD_OPTION_END); 305 if (d == NULL) 306 return 1; 307 if (0 == port) 308 { 309 const union MHD_DaemonInfo *dinfo; 310 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 311 if ((NULL == dinfo) || (0 == dinfo->port) ) 312 { 313 MHD_stop_daemon (d); return 32; 314 } 315 port = dinfo->port; 316 } 317 c = curl_easy_init (); 318 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); 319 curl_easy_setopt (c, CURLOPT_PORT, (long) port); 320 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 321 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 322 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 323 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 324 if (oneone) 325 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 326 else 327 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 328 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 329 /* NOTE: use of CONNECTTIMEOUT without also 330 * setting NOSIGNAL results in really weird 331 * crashes on my system! */ 332 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 333 if (! add_test_form (c, &form)) 334 { 335 fprintf (stderr, "libcurl form initialisation error.\n"); 336 curl_easy_cleanup (c); 337 return 2; 338 } 339 if (CURLE_OK != (errornum = curl_easy_perform (c))) 340 { 341 fprintf (stderr, 342 "curl_easy_perform failed: `%s'\n", 343 curl_easy_strerror (errornum)); 344 curl_easy_cleanup (c); 345 free_test_form (&form); 346 MHD_stop_daemon (d); 347 return 2; 348 } 349 curl_easy_cleanup (c); 350 free_test_form (&form); 351 MHD_stop_daemon (d); 352 if (cbc.pos != strlen ("/hello_world")) 353 return 4; 354 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) 355 return 8; 356 return 0; 357 } 358 359 360 static unsigned int 361 testMultithreadedPost (void) 362 { 363 struct MHD_Daemon *d; 364 CURL *c; 365 char buf[2048]; 366 struct CBC cbc; 367 CURLcode errornum; 368 struct mhd_test_postdata form; 369 uint16_t port; 370 371 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 372 port = 0; 373 else 374 { 375 port = 1390; 376 if (oneone) 377 port += 10; 378 } 379 380 cbc.buf = buf; 381 cbc.size = 2048; 382 cbc.pos = 0; 383 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION 384 | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 385 port, NULL, NULL, &ahc_echo, NULL, 386 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, 387 MHD_OPTION_END); 388 if (d == NULL) 389 return 16; 390 if (0 == port) 391 { 392 const union MHD_DaemonInfo *dinfo; 393 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 394 if ((NULL == dinfo) || (0 == dinfo->port) ) 395 { 396 MHD_stop_daemon (d); return 32; 397 } 398 port = dinfo->port; 399 } 400 c = curl_easy_init (); 401 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); 402 curl_easy_setopt (c, CURLOPT_PORT, (long) port); 403 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 404 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 405 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 406 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 407 if (oneone) 408 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 409 else 410 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 411 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L); 412 /* NOTE: use of CONNECTTIMEOUT without also 413 * setting NOSIGNAL results in really weird 414 * crashes on my system! */ 415 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 416 if (! add_test_form (c, &form)) 417 { 418 fprintf (stderr, "libcurl form initialisation error.\n"); 419 curl_easy_cleanup (c); 420 return 2; 421 } 422 if (CURLE_OK != (errornum = curl_easy_perform (c))) 423 { 424 fprintf (stderr, 425 "curl_easy_perform failed: `%s'\n", 426 curl_easy_strerror (errornum)); 427 curl_easy_cleanup (c); 428 free_test_form (&form); 429 MHD_stop_daemon (d); 430 return 32; 431 } 432 curl_easy_cleanup (c); 433 free_test_form (&form); 434 MHD_stop_daemon (d); 435 if (cbc.pos != strlen ("/hello_world")) 436 return 64; 437 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) 438 return 128; 439 return 0; 440 } 441 442 443 static unsigned int 444 testMultithreadedPoolPost (void) 445 { 446 struct MHD_Daemon *d; 447 CURL *c; 448 char buf[2048]; 449 struct CBC cbc; 450 CURLcode errornum; 451 struct mhd_test_postdata form; 452 uint16_t port; 453 454 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 455 port = 0; 456 else 457 { 458 port = 1391; 459 if (oneone) 460 port += 10; 461 } 462 463 cbc.buf = buf; 464 cbc.size = 2048; 465 cbc.pos = 0; 466 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 467 port, NULL, NULL, &ahc_echo, NULL, 468 MHD_OPTION_THREAD_POOL_SIZE, MHD_CPU_COUNT, 469 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, 470 MHD_OPTION_END); 471 if (d == NULL) 472 return 16; 473 if (0 == port) 474 { 475 const union MHD_DaemonInfo *dinfo; 476 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 477 if ((NULL == dinfo) || (0 == dinfo->port) ) 478 { 479 MHD_stop_daemon (d); return 32; 480 } 481 port = dinfo->port; 482 } 483 c = curl_easy_init (); 484 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); 485 curl_easy_setopt (c, CURLOPT_PORT, (long) port); 486 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 487 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 488 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 489 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 490 if (oneone) 491 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 492 else 493 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 494 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L); 495 /* NOTE: use of CONNECTTIMEOUT without also 496 * setting NOSIGNAL results in really weird 497 * crashes on my system! */ 498 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 499 if (! add_test_form (c, &form)) 500 { 501 fprintf (stderr, "libcurl form initialisation error.\n"); 502 curl_easy_cleanup (c); 503 return 2; 504 } 505 if (CURLE_OK != (errornum = curl_easy_perform (c))) 506 { 507 fprintf (stderr, 508 "curl_easy_perform failed: `%s'\n", 509 curl_easy_strerror (errornum)); 510 curl_easy_cleanup (c); 511 free_test_form (&form); 512 MHD_stop_daemon (d); 513 return 32; 514 } 515 curl_easy_cleanup (c); 516 free_test_form (&form); 517 MHD_stop_daemon (d); 518 if (cbc.pos != strlen ("/hello_world")) 519 return 64; 520 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) 521 return 128; 522 return 0; 523 } 524 525 526 static unsigned int 527 testExternalPost (void) 528 { 529 struct MHD_Daemon *d; 530 CURL *c; 531 char buf[2048]; 532 struct CBC cbc; 533 CURLM *multi; 534 CURLMcode mret; 535 fd_set rs; 536 fd_set ws; 537 fd_set es; 538 MHD_socket maxsock; 539 #ifdef MHD_WINSOCK_SOCKETS 540 int maxposixs; /* Max socket number unused on W32 */ 541 #else /* MHD_POSIX_SOCKETS */ 542 #define maxposixs maxsock 543 #endif /* MHD_POSIX_SOCKETS */ 544 int running; 545 struct CURLMsg *msg; 546 time_t start; 547 struct timeval tv; 548 struct mhd_test_postdata form; 549 uint16_t port; 550 551 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 552 port = 0; 553 else 554 { 555 port = 1392; 556 if (oneone) 557 port += 10; 558 } 559 560 multi = NULL; 561 cbc.buf = buf; 562 cbc.size = 2048; 563 cbc.pos = 0; 564 d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_NO_THREAD_SAFETY, 565 port, NULL, NULL, &ahc_echo, NULL, 566 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL, 567 MHD_OPTION_APP_FD_SETSIZE, (int) FD_SETSIZE, 568 MHD_OPTION_END); 569 if (d == NULL) 570 return 256; 571 if (0 == port) 572 { 573 const union MHD_DaemonInfo *dinfo; 574 dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); 575 if ((NULL == dinfo) || (0 == dinfo->port) ) 576 { 577 MHD_stop_daemon (d); return 32; 578 } 579 port = dinfo->port; 580 } 581 c = curl_easy_init (); 582 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); 583 curl_easy_setopt (c, CURLOPT_PORT, (long) port); 584 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); 585 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); 586 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); 587 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); 588 if (oneone) 589 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 590 else 591 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 592 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); 593 /* NOTE: use of CONNECTTIMEOUT without also 594 * setting NOSIGNAL results in really weird 595 * crashes on my system! */ 596 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); 597 if (! add_test_form (c, &form)) 598 { 599 fprintf (stderr, "libcurl form initialisation error.\n"); 600 curl_easy_cleanup (c); 601 return 2; 602 } 603 604 multi = curl_multi_init (); 605 if (multi == NULL) 606 { 607 curl_easy_cleanup (c); 608 free_test_form (&form); 609 MHD_stop_daemon (d); 610 return 512; 611 } 612 mret = curl_multi_add_handle (multi, c); 613 if (mret != CURLM_OK) 614 { 615 curl_multi_cleanup (multi); 616 free_test_form (&form); 617 curl_easy_cleanup (c); 618 MHD_stop_daemon (d); 619 return 1024; 620 } 621 start = time (NULL); 622 while ((time (NULL) - start < 5) && (multi != NULL)) 623 { 624 maxsock = MHD_INVALID_SOCKET; 625 maxposixs = -1; 626 FD_ZERO (&rs); 627 FD_ZERO (&ws); 628 FD_ZERO (&es); 629 curl_multi_perform (multi, &running); 630 mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); 631 if (mret != CURLM_OK) 632 { 633 curl_multi_remove_handle (multi, c); 634 curl_multi_cleanup (multi); 635 curl_easy_cleanup (c); 636 MHD_stop_daemon (d); 637 free_test_form (&form); 638 return 2048; 639 } 640 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) 641 { 642 curl_multi_remove_handle (multi, c); 643 curl_multi_cleanup (multi); 644 curl_easy_cleanup (c); 645 free_test_form (&form); 646 MHD_stop_daemon (d); 647 return 4096; 648 } 649 tv.tv_sec = 0; 650 tv.tv_usec = 1000; 651 if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) 652 { 653 #ifdef MHD_POSIX_SOCKETS 654 if (EINTR != errno) 655 { 656 fprintf (stderr, "Unexpected select() error: %d. Line: %d\n", 657 (int) errno, __LINE__); 658 fflush (stderr); 659 exit (99); 660 } 661 #else 662 if ((WSAEINVAL != WSAGetLastError ()) || 663 (0 != rs.fd_count) || (0 != ws.fd_count) || (0 != es.fd_count) ) 664 { 665 fprintf (stderr, "Unexpected select() error: %d. Line: %d\n", 666 (int) WSAGetLastError (), __LINE__); 667 fflush (stderr); 668 exit (99); 669 } 670 Sleep (1); 671 #endif 672 } 673 curl_multi_perform (multi, &running); 674 if (0 == running) 675 { 676 int pending; 677 int curl_fine = 0; 678 while (NULL != (msg = curl_multi_info_read (multi, &pending))) 679 { 680 if (msg->msg == CURLMSG_DONE) 681 { 682 if (msg->data.result == CURLE_OK) 683 curl_fine = 1; 684 else 685 { 686 fprintf (stderr, 687 "%s failed at %s:%d: `%s'\n", 688 "curl_multi_perform", 689 __FILE__, 690 __LINE__, curl_easy_strerror (msg->data.result)); 691 abort (); 692 } 693 } 694 } 695 if (! curl_fine) 696 { 697 fprintf (stderr, "libcurl haven't returned OK code\n"); 698 abort (); 699 } 700 curl_multi_remove_handle (multi, c); 701 curl_multi_cleanup (multi); 702 curl_easy_cleanup (c); 703 c = NULL; 704 multi = NULL; 705 } 706 MHD_run (d); 707 } 708 if (multi != NULL) 709 { 710 curl_multi_remove_handle (multi, c); 711 curl_easy_cleanup (c); 712 curl_multi_cleanup (multi); 713 } 714 free_test_form (&form); 715 MHD_stop_daemon (d); 716 if (cbc.pos != strlen ("/hello_world")) 717 return 8192; 718 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) 719 return 16384; 720 return 0; 721 } 722 723 724 int 725 main (int argc, char *const *argv) 726 { 727 unsigned int errorCount = 0; 728 (void) argc; /* Unused. Silent compiler warning. */ 729 730 #ifdef MHD_HTTPS_REQUIRE_GCRYPT 731 #ifdef HAVE_GCRYPT_H 732 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); 733 #ifdef GCRYCTL_INITIALIZATION_FINISHED 734 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); 735 #endif 736 #endif 737 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */ 738 if ((NULL == argv) || (0 == argv[0])) 739 return 99; 740 oneone = has_in_name (argv[0], "11"); 741 if (0 != curl_global_init (CURL_GLOBAL_WIN32)) 742 return 2; 743 if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS)) 744 { 745 errorCount += testInternalPost (); 746 errorCount += testMultithreadedPost (); 747 errorCount += testMultithreadedPoolPost (); 748 } 749 errorCount += testExternalPost (); 750 if (errorCount != 0) 751 fprintf (stderr, "Error (code: %u)\n", errorCount); 752 curl_global_cleanup (); 753 return (0 == errorCount) ? 0 : 1; /* 0 == pass */ 754 }