/** * Run the MHD external event loop using select. * * @param daemon daemon to run it for */ static void run_mhd_select_loop (struct MHD_Daemon *daemon) { fd_set rs; fd_set ws; fd_set es; MHD_socket max_fd; MHD_UNSIGNED_LONG_LONG to; struct timeval tv; while (! done) { FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); max_fd = -1; to = 1000; if (MHD_YES != MHD_get_fdset (daemon, &rs, &ws, &es, &max_fd)) abort (); (void) MHD_get_timeout (daemon, &to); if (1000 < to) to = 1000; tv.tv_sec = to / 1000; tv.tv_usec = 1000 * (to % 1000); if (0 > MHD_SYS_select_ (max_fd + 1, &rs, &ws, &es, &tv)) abort (); MHD_run_from_select (daemon, &rs, &ws, &es); } }
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 max; int running; struct CURLMsg *msg; time_t start; struct timeval tv; unsigned int i; char url[64]; sprintf(url, "http://127.0.0.1:%d/hello_world", port); multi = NULL; cbc.buf = buf; cbc.size = 2048; d = MHD_start_daemon (MHD_USE_DEBUG, port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); if (d == NULL) return 256; 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, 1); 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, 1); 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)) { max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); 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, &max)) { 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; select (max + 1, &rs, &ws, &es, &tv); 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 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; }