#include #include #include #include #include #include /*#define INTERNAL_SELECT 1*/ /*#define TIMEOUT 1*/ struct Request { struct MHD_Connection *con; char *url; }; static void * process_cb (void *cls) { struct Request *req = cls; struct MHD_Response *res; const union MHD_ConnectionInfo *info; const char *msg = "hello"; if (0 == strcmp (req->url, "/sleep")) { usleep (1000 * 1000 * 10); /* Simulates a slow processing. */ msg = "sleep"; } res = MHD_create_response_from_buffer (strlen (msg), (void *) msg, MHD_RESPMEM_PERSISTENT); MHD_queue_response (req->con, MHD_HTTP_OK, res); MHD_resume_connection (req->con); info = MHD_get_connection_info (req->con, MHD_CONNECTION_INFO_DAEMON); if (NULL != info) MHD_run (info->daemon); MHD_destroy_response (res); free (req->url); free (req); pthread_exit (NULL); } static int ahc_cb (void *cls, struct MHD_Connection *con, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { struct Request *req; pthread_t thrd; (void) cls; /* Unused. Silence compiler warning. */ (void) method; /* Unused. Silence compiler warning. */ (void) version; /* Unused. Silence compiler warning. */ (void) upload_data; /* Unused. Silence compiler warning. */ (void) upload_data_size; /* Unused. Silence compiler warning. */ if (NULL == *ptr) { *ptr = (void *) 1; return MHD_YES; } *ptr = NULL; MHD_suspend_connection (con); req = malloc (sizeof (struct Request)); if (NULL == req) return MHD_NO; req->con = con; req->url = strdup (url); if (NULL == req->url) { free (req); return MHD_NO; } if (0 != pthread_create (&thrd, NULL, process_cb, req)) { free (req->url); free (req); return MHD_NO; } pthread_detach (thrd); return MHD_YES; } int main (int argc, char *const *argv) { struct MHD_Daemon *d; unsigned int flags = MHD_USE_SUSPEND_RESUME | MHD_USE_ERROR_LOG; #ifndef INTERNAL_SELECT struct timeval tv; struct timeval *tvp; fd_set rs; fd_set ws; fd_set es; MHD_socket max; MHD_UNSIGNED_LONG_LONG timeout; int errnum; if (argc != 2) { printf ("%s PORT\n", argv[0]); return 1; } #else flags += MHD_USE_AUTO_INTERNAL_THREAD; #endif d = MHD_start_daemon (flags, 8080, NULL, NULL, &ahc_cb, NULL, MHD_OPTION_END); if (NULL == d) return 1; #ifdef INTERNAL_SELECT (void) getc (stdin); #else while (1) { max = 0; FD_ZERO(&rs); FD_ZERO(&ws); FD_ZERO(&es); timeout = (MHD_UNSIGNED_LONG_LONG) -1; if (MHD_YES != MHD_get_fdset(d, &rs, &ws, &es, &max)) break; if (MHD_YES == MHD_get_timeout (d, &timeout)) { tv.tv_sec = (time_t) (timeout / 1000L); tv.tv_usec = (suseconds_t) ((timeout % 1000L) * 1000L); tvp = &tv; } else { #ifdef TIMEOUT tv.tv_sec = 0; tv.tv_usec = 1000; tvp = &tv; #else tvp = NULL; #endif } if (-1 == select (max + 1, &rs, &ws, &es, tvp)) { errnum = errno; if (EINTR != errnum) { fprintf (stderr, "Aborting due to error during select: %s\n", strerror (errnum)); fflush (stderr); } break; } if (!MHD_run_from_select (d, &rs, &ws, &es)) return 1; } #endif MHD_stop_daemon (d); return 0; }