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