/** * Run the MHD external event loop using select. * * @param daemon daemon to run it for */ static void run_mhd_epoll_loop (struct MHD_Daemon *daemon) { const union MHD_DaemonInfo *di; MHD_socket ep; fd_set rs; MHD_UNSIGNED_LONG_LONG to; struct timeval tv; di = MHD_get_daemon_info (daemon, MHD_DAEMON_INFO_EPOLL_FD); ep = di->listen_fd; while (! done) { FD_ZERO (&rs); to = 1000; FD_SET (ep, &rs); (void) MHD_get_timeout (daemon, &to); if (1000 < to) to = 1000; tv.tv_sec = to / 1000; tv.tv_usec = 1000 * (to % 1000); select (ep + 1, &rs, NULL, NULL, &tv); MHD_run (daemon); } }
/* perform a HTTP GET request via SSL/TLS */ static int test_secure_get (FILE * test_fd, const char *cipher_suite, int proto_version) { int ret; struct MHD_Daemon *d; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else port = 3041; d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS | MHD_USE_ERROR_LOG, port, NULL, NULL, &http_ahc, NULL, MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, MHD_OPTION_END); if (d == NULL) { fprintf (stderr, MHD_E_SERVER_INIT); return -1; } if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return -1; } port = (int)dinfo->port; } ret = test_https_transfer (test_fd, port, cipher_suite, proto_version); MHD_stop_daemon (d); return ret; }
static int testMultithreadedPoolGet () { struct MHD_Daemon *d; char buf[2048]; int k; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1261; if (oneone) port += 5; } /* Test only valid for HTTP/1.1 (uses persistent connections) */ if (!oneone) return 0; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2, MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END); if (d == NULL) return 16; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } for (k = 0; k < 3; ++k) { struct CBC cbc[3]; CURL *cenv[3]; int i; for (i = 0; i < 3; ++i) { CURL *c; CURLcode errornum; cenv[i] = c = curl_easy_init (); cbc[i].buf = buf; cbc[i].size = 2048; cbc[i].pos = 0; curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); curl_easy_setopt (c, CURLOPT_PORT, (long)port); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L); curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also * setting NOSIGNAL results in really weird * crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); errornum = curl_easy_perform (c); if ( ( (CURLE_OK != errornum) && (i < 2) ) || ( (CURLE_OK == errornum) && (i == 2) ) ) { int j; /* First 2 should succeed */ if (i < 2) fprintf (stderr, "curl_easy_perform failed: `%s'\n", curl_easy_strerror (errornum)); /* Last request should have failed */ else fprintf (stderr, "No error on IP address over limit\n"); for (j = 0; j < i; ++j) curl_easy_cleanup (cenv[j]); MHD_stop_daemon (d); return 32; } } /* Cleanup the environments */ for (i = 0; i < 3; ++i) curl_easy_cleanup (cenv[i]); (void)sleep(2); for (i = 0; i < 2; ++i) { if (cbc[i].pos != strlen ("/hello_world")) { MHD_stop_daemon (d); return 64; } if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world"))) { MHD_stop_daemon (d); return 128; } } } MHD_stop_daemon (d); return 0; }
static int testMultithreadedGet () { struct MHD_Daemon *d; char buf[2048]; int k; unsigned int success; unsigned int failure; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1260; if (oneone) port += 5; } /* Test only valid for HTTP/1.1 (uses persistent connections) */ if (!oneone) return 0; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2, MHD_OPTION_END); if (d == NULL) return 16; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } for (k = 0; k < 3; ++k) { struct CBC cbc[3]; CURL *cenv[3]; int i; success = 0; failure = 0; for (i = 0; i < 3; ++i) { CURL *c; CURLcode errornum; cenv[i] = c = curl_easy_init (); cbc[i].buf = buf; cbc[i].size = 2048; cbc[i].pos = 0; curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); curl_easy_setopt (c, CURLOPT_PORT, (long)port); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L); curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also * setting NOSIGNAL results in really weird * crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); errornum = curl_easy_perform (c); if (CURLE_OK == errornum) success++; else failure++; } /* Cleanup the environments */ for (i = 0; i < 3; ++i) curl_easy_cleanup (cenv[i]); if ( (2 != success) || (1 != failure) ) { fprintf (stderr, "Unexpected number of success (%u) or failure (%u)\n", success, failure); MHD_stop_daemon (d); return 32; } (void)sleep(2); for (i = 0; i < 2; ++i) { if (cbc[i].pos != strlen ("/hello_world")) { MHD_stop_daemon (d); return 64; } if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world"))) { MHD_stop_daemon (d); return 128; } } } MHD_stop_daemon (d); return 0; }
int main (int argc, char *const *argv) { int errorCount = 0;; struct MHD_Daemon *d; gnutls_session_t session; gnutls_datum_t key; gnutls_datum_t cert; gnutls_certificate_credentials_t xcred; int port; (void)argc; /* Unused. Silent compiler warning. */ if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else port = 3070; #ifdef MHD_HTTPS_REQUIRE_GRYPT gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); #ifdef GCRYCTL_INITIALIZATION_FINISHED gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); #endif #endif /* MHD_HTTPS_REQUIRE_GRYPT */ gnutls_global_init (); gnutls_global_set_log_level (11); d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS | MHD_USE_ERROR_LOG, port, NULL, NULL, &http_dummy_ahc, NULL, MHD_OPTION_CONNECTION_TIMEOUT, TIME_OUT, MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, MHD_OPTION_END); if (NULL == d) { fprintf (stderr, MHD_E_SERVER_INIT); return -1; } if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return -1; } port = (int)dinfo->port; } if (0 != setup_session (&session, &key, &cert, &xcred)) { fprintf (stderr, "failed to setup session\n"); return 1; } errorCount += test_tls_session_time_out (session, port); teardown_session (session, &key, &cert, xcred); print_test_result (errorCount, argv[0]); MHD_stop_daemon (d); gnutls_global_deinit (); return errorCount != 0 ? 1 : 0; }
static int testExternalGet () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLM *multi; CURLMcode mret; fd_set rs; fd_set ws; fd_set es; MHD_socket maxsock; #ifdef MHD_WINSOCK_SOCKETS int maxposixs; /* Max socket number unused on W32 */ #else /* MHD_POSIX_SOCKETS */ #define maxposixs maxsock #endif /* MHD_POSIX_SOCKETS */ int running; struct CURLMsg *msg; time_t start; struct timeval tv; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1410; if (oneone) port += 5; } multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); if (d == NULL) return 256; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello+world?k=v+x&hash=%23foo&space=%A0bar"); curl_easy_setopt (c, CURLOPT_PORT, (long)port); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also setting NOSIGNAL results in really weird crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); multi = curl_multi_init (); if (multi == NULL) { curl_easy_cleanup (c); MHD_stop_daemon (d); return 512; } mret = curl_multi_add_handle (multi, c); if (mret != CURLM_OK) { curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 1024; } start = time (NULL); while ((time (NULL) - start < 5) && (multi != NULL)) { maxsock = MHD_INVALID_SOCKET; maxposixs = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); if (mret != CURLM_OK) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 2048; } if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 4096; } tv.tv_sec = 0; tv.tv_usec = 1000; if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) { #ifdef MHD_POSIX_SOCKETS if (EINTR != errno) abort (); #else if (WSAEINVAL != WSAGetLastError() || 0 != rs.fd_count || 0 != ws.fd_count || 0 != es.fd_count) abort (); Sleep (1000); #endif } curl_multi_perform (multi, &running); if (running == 0) { msg = curl_multi_info_read (multi, &running); if (msg == NULL) break; if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) printf ("%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); c = NULL; multi = NULL; } } MHD_run (d); } if (multi != NULL) { curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); curl_multi_cleanup (multi); } MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello+world")) return 8192; if (0 != strncmp ("/hello+world", cbc.buf, strlen ("/hello+world"))) return 16384; return 0; }
static int testUnknownPortGet (int poll_flag) { struct MHD_Daemon *d; const union MHD_DaemonInfo *di; CURL *c; char buf[2048]; struct CBC cbc; CURLcode errornum; struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | poll_flag, 1, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_SOCK_ADDR, &addr, MHD_OPTION_END); if (d == NULL) return 32768; di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD); if (di == NULL) return 65536; if (0 != getsockname(di->listen_fd, &addr, &addr_len)) return 131072; if (addr.sin_family != AF_INET) return 26214; snprintf(buf, sizeof(buf), "http://localhost:%hu/hello_world", ntohs(addr.sin_port)); c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, buf); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); /* NOTE: use of CONNECTTIMEOUT without also setting NOSIGNAL results in really weird crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); if (CURLE_OK != (errornum = curl_easy_perform (c))) { fprintf (stderr, "curl_easy_perform failed: `%s'\n", curl_easy_strerror (errornum)); curl_easy_cleanup (c); MHD_stop_daemon (d); return 524288; } curl_easy_cleanup (c); MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) return 1048576; if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 2097152; return 0; }
static int testExternalPost () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLM *multi; CURLMcode mret; fd_set rs; fd_set ws; fd_set es; MHD_socket maxsock; #ifdef MHD_WINSOCK_SOCKETS int maxposixs; /* Max socket number unused on W32 */ #else /* MHD_POSIX_SOCKETS */ #define maxposixs maxsock #endif /* MHD_POSIX_SOCKETS */ int running; struct CURLMsg *msg; time_t start; struct timeval tv; int i; unsigned long long timeout; long ctimeout; char url[1024]; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1353; if (oneone) port += 10; } multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); if (d == NULL) return 256; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } multi = curl_multi_init (); if (multi == NULL) { MHD_stop_daemon (d); return 512; } for (i = 0; i < LOOPCOUNT; i++) { if (99 == i % 100) fprintf (stderr, "."); c = curl_easy_init (); cbc.pos = 0; buf[0] = '\0'; snprintf (url, sizeof (url), "http://127.0.0.1:%d/hw%d", port, i); curl_easy_setopt (c, CURLOPT_URL, url); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); curl_easy_setopt (c, CURLOPT_POST, 1L); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also * setting NOSIGNAL results in really weird * crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); mret = curl_multi_add_handle (multi, c); if (mret != CURLM_OK) { curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 1024; } start = time (NULL); while ((time (NULL) - start < 5) && (multi != NULL)) { maxsock = MHD_INVALID_SOCKET; maxposixs = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform (multi, &running)); mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); if (mret != CURLM_OK) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 2048; } if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 4096; } if (MHD_NO == MHD_get_timeout (d, &timeout)) timeout = 100; /* 100ms == INFTY -- CURL bug... */ if ((CURLM_OK == curl_multi_timeout (multi, &ctimeout)) && (ctimeout < (long long)timeout) && (ctimeout >= 0)) timeout = ctimeout; if ( (c == NULL) || (running == 0) ) timeout = 0; /* terminate quickly... */ tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) { if (EINTR == errno) continue; fprintf (stderr, "select failed: %s\n", strerror (errno)); break; } while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform (multi, &running)); if (running == 0) { msg = curl_multi_info_read (multi, &running); if (msg == NULL) break; if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) printf ("%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); c = NULL; } } MHD_run (d); } if (c != NULL) { curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); } if ((buf[0] != 'O') || (buf[1] != 'K')) { curl_multi_cleanup (multi); MHD_stop_daemon (d); return 8192; } } curl_multi_cleanup (multi); MHD_stop_daemon (d); if (LOOPCOUNT >= 99) fprintf (stderr, "\n"); return 0; }
static int testMultithreadedPoolPost () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLcode errornum; int i; char url[1024]; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1352; if (oneone) port += 10; } cbc.buf = buf; cbc.size = 2048; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END); if (d == NULL) return 16; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } for (i = 0; i < LOOPCOUNT; i++) { if (99 == i % 100) fprintf (stderr, "."); c = curl_easy_init (); cbc.pos = 0; buf[0] = '\0'; snprintf (url, sizeof (url), "http://127.0.0.1:%d/hw%d", port, i); curl_easy_setopt (c, CURLOPT_URL, url); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA); curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA)); curl_easy_setopt (c, CURLOPT_POST, 1L); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also * setting NOSIGNAL results in really weird * crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); if (CURLE_OK != (errornum = curl_easy_perform (c))) { fprintf (stderr, "curl_easy_perform failed: `%s'\n", curl_easy_strerror (errornum)); curl_easy_cleanup (c); MHD_stop_daemon (d); return 32; } curl_easy_cleanup (c); if ((buf[0] != 'O') || (buf[1] != 'K')) { MHD_stop_daemon (d); return 64; } } MHD_stop_daemon (d); if (LOOPCOUNT >= 99) fprintf (stderr, "\n"); return 0; }
static int testDigestAuth () { CURL *c; CURLcode errornum; struct MHD_Daemon *d; struct CBC cbc; char buf[2048]; char rnd[8]; int port; char url[128]; #ifndef WINDOWS int fd; size_t len; size_t off = 0; #endif /* ! WINDOWS */ if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else port = 1160; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; #ifndef WINDOWS fd = open("/dev/urandom", O_RDONLY); if (-1 == fd) { fprintf(stderr, "Failed to open `%s': %s\n", "/dev/urandom", strerror(errno)); return 1; } while (off < 8) { len = read(fd, rnd, 8); if (len == (size_t)-1) { fprintf(stderr, "Failed to read `%s': %s\n", "/dev/urandom", strerror(errno)); (void) close(fd); return 1; } off += len; } (void) close(fd); #else { HCRYPTPROV cc; BOOL b; b = CryptAcquireContext (&cc, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (b == 0) { fprintf (stderr, "Failed to acquire crypto provider context: %lu\n", GetLastError ()); return 1; } b = CryptGenRandom (cc, 8, (BYTE*)rnd); if (b == 0) { fprintf (stderr, "Failed to generate 8 random bytes: %lu\n", GetLastError ()); } CryptReleaseContext (cc, 0); if (b == 0) return 1; } #endif d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_DIGEST_AUTH_RANDOM, sizeof (rnd), rnd, MHD_OPTION_NONCE_NC_SIZE, 300, MHD_OPTION_END); if (d == NULL) return 1; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } snprintf (url, sizeof (url), "http://127.0.0.1:%d/bar%%20foo%%3Fkey%%3Dvalue", port); c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, url); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); curl_easy_setopt (c, CURLOPT_USERPWD, "testuser:testpass"); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); /* NOTE: use of CONNECTTIMEOUT without also setting NOSIGNAL results in really weird crashes on my system!*/ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); if (CURLE_OK != (errornum = curl_easy_perform (c))) { fprintf (stderr, "curl_easy_perform failed: `%s'\n", curl_easy_strerror (errornum)); curl_easy_cleanup (c); MHD_stop_daemon (d); return 2; } curl_easy_cleanup (c); MHD_stop_daemon (d); if (cbc.pos != strlen (PAGE)) return 4; if (0 != strncmp (PAGE, cbc.buf, strlen (PAGE))) return 8; return 0; }
static int testMultithreadedPoolPut () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; unsigned int pos = 0; int done_flag = 0; CURLcode errornum; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1452; if (oneone) port += 10; } cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END); if (d == NULL) return 16; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/hello_world"); curl_easy_setopt (c, CURLOPT_PORT, (long)port); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer); curl_easy_setopt (c, CURLOPT_READDATA, &pos); curl_easy_setopt (c, CURLOPT_UPLOAD, 1L); curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also * setting NOSIGNAL results in really weird * crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); if (CURLE_OK != (errornum = curl_easy_perform (c))) { fprintf (stderr, "curl_easy_perform failed: `%s'\n", curl_easy_strerror (errornum)); curl_easy_cleanup (c); MHD_stop_daemon (d); return 32; } curl_easy_cleanup (c); MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) return 64; if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 128; return 0; }
static int testExternalGet (int port) { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLM *multi; CURLMcode mret; fd_set rs; fd_set ws; fd_set es; MHD_socket maxsock; #ifdef MHD_WINSOCK_SOCKETS int maxposixs; /* Max socket number unused on W32 */ #else /* MHD_POSIX_SOCKETS */ #define maxposixs maxsock #endif /* MHD_POSIX_SOCKETS */ int running; struct CURLMsg *msg; time_t start; struct timeval tv; unsigned int i; char url[64]; if (MHD_NO != MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; multi = NULL; cbc.buf = buf; cbc.size = 2048; d = MHD_start_daemon (MHD_USE_ERROR_LOG, port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); if (NULL == d) return 256; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } snprintf (url, sizeof (url), "http://127.0.0.1:%d/hello_world", port); start_timer (); multi = curl_multi_init (); if (multi == NULL) { MHD_stop_daemon (d); return 512; } for (i=0;i<ROUNDS;i++) { cbc.pos = 0; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, url); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also setting NOSIGNAL results in really weird crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); mret = curl_multi_add_handle (multi, c); if (mret != CURLM_OK) { curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 1024; } start = time (NULL); while ((time (NULL) - start < 5) && (c != NULL)) { maxsock = MHD_INVALID_SOCKET; maxposixs = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); if (mret != CURLM_OK) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 2048; } if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 4096; } tv.tv_sec = 0; tv.tv_usec = 1000; if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) { #ifdef MHD_POSIX_SOCKETS if (EINTR != errno) abort (); #else if (WSAEINVAL != WSAGetLastError() || 0 != rs.fd_count || 0 != ws.fd_count || 0 != es.fd_count) abort (); Sleep (1000); #endif } curl_multi_perform (multi, &running); if (running == 0) { msg = curl_multi_info_read (multi, &running); if (msg == NULL) break; if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) printf ("%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); c = NULL; } } /* two possibilities here; as select sets are tiny, this makes virtually no difference in actual runtime right now, even though the number of select calls is virtually cut in half (and 'select' is the most expensive of our system calls according to 'strace') */ if (0) MHD_run (d); else MHD_run_from_select (d, &rs, &ws, &es); } if (NULL != c) { curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); fprintf (stderr, "Timeout!?\n"); } } stop ("external select"); if (multi != NULL) { curl_multi_cleanup (multi); } MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) return 8192; if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 16384; return 0; }
static int testMultithreadedPoolGet (int port, int poll_flag) { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLcode errornum; unsigned int i; char url[64]; if (MHD_NO != MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; cbc.buf = buf; cbc.size = 2048; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | poll_flag, port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END); if (d == NULL) return 16; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } snprintf (url, sizeof (url), "http://127.0.0.1:%d/hello_world", port); start_timer (); for (i=0;i<ROUNDS;i++) { cbc.pos = 0; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, url); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); /* NOTE: use of CONNECTTIMEOUT without also setting NOSIGNAL results in really weird crashes on my system!*/ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); if (CURLE_OK != (errornum = curl_easy_perform (c))) { fprintf (stderr, "curl_easy_perform failed: `%s'\n", curl_easy_strerror (errornum)); curl_easy_cleanup (c); MHD_stop_daemon (d); return 32; } curl_easy_cleanup (c); } stop (0 != (poll_flag & MHD_USE_AUTO) ? "internal thread pool with 'auto'" : 0 != (poll_flag & MHD_USE_POLL) ? "internal thread pool with poll()" : 0 != (poll_flag & MHD_USE_EPOLL) ? "internal thread pool with epoll" : "internal thread pool with select()"); MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) return 64; if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 128; return 0; }
static int testLongUrlGet () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; char *url; long code; int port; if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) port = 0; else { port = 1330; if (oneone) port += 5; } cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD /* | MHD_USE_ERROR_LOG */ , port, &apc_all, NULL, &ahc_echo, "GET", MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (VERY_LONG / 2), MHD_OPTION_END); if (d == NULL) return 1; if (0 == port) { const union MHD_DaemonInfo *dinfo; dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); if (NULL == dinfo || 0 == dinfo->port) { MHD_stop_daemon (d); return 32; } port = (int)dinfo->port; } c = curl_easy_init (); url = malloc (VERY_LONG); if (url == NULL) { MHD_stop_daemon (d); return 1; } memset (url, 'a', VERY_LONG); url[VERY_LONG - 1] = '\0'; memcpy (url, "http://127.0.0.1/", strlen ("http://127.0.0.1/")); curl_easy_setopt (c, CURLOPT_URL, url); curl_easy_setopt (c, CURLOPT_PORT, (long)port); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); if (oneone) curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); else curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); /* NOTE: use of CONNECTTIMEOUT without also setting NOSIGNAL results in really weird crashes on my system! */ curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); if (CURLE_OK == curl_easy_perform (c)) { curl_easy_cleanup (c); MHD_stop_daemon (d); free (url); return 2; } if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code)) { curl_easy_cleanup (c); MHD_stop_daemon (d); free (url); return 4; } curl_easy_cleanup (c); MHD_stop_daemon (d); free (url); if (code != MHD_HTTP_URI_TOO_LONG) return 8; return 0; }