int main(int argc, char* argv[]) { // Parse any command-line options. namespace po = boost::program_options; po::options_description desc("Allowed options"); desc.add_options() ("help", "show help") ("debug-httpd", po::value<bool>(&mp3d_debug_httpd), "show httpd debug output") ("root", po::value<std::string>(&mp3d_music_root), "root of file system mp3 tree") ("port", po::value<int>(&mp3d_port), "httpd port number") ; po::variables_map args; po::store(po::parse_command_line(argc, argv, desc), args); po::notify(args); if (args.count("help")) { std::cout << desc << std::endl; return 1; } // Index all the mp3s. Paths paths; find_mp3_files(mp3d_music_root, paths); std::cerr << ".mp3 files found: " << paths.size() << std::endl; int old_percentage = -1; size_t id = 0; for (Paths::const_iterator it = paths.begin(); it != paths.end(); ++it) { Mp3Info mp3; mp3.filename = (*it).string(); const ID3_Tag tag(mp3.filename.c_str()); ID3_Tag::ConstIterator* it = tag.CreateIterator(); for (size_t i = 0; i < tag.NumFrames(); ++i) { const ID3_Frame* frame = it->GetNext(); if (frame != 0) { std::string* dst; switch (frame->GetID()) { case ID3FID_ALBUM: dst = &mp3.album; break; case ID3FID_LEADARTIST: dst = &mp3.artist; break; case ID3FID_TITLE: dst = &mp3.title; break; default: continue; } char* text = ID3_GetString(frame, ID3FN_TEXT); dst->assign(text); ID3_FreeString(text); } } // FIXME: maybe a hash, to enable bookmarks? mp3.id = id++; all_mp3s.push_back(mp3); // Show progress. Not really useful when we're not debugging. // FIXME: start the web server straight away, and say "Indexing..." there. const int new_percentage = (100*all_mp3s.size())/paths.size(); if (new_percentage != old_percentage) { std::cout << "\rScanned: " << new_percentage << "%" << std::flush; old_percentage = new_percentage; } } std::cout << "\r.mp3 files scanned: " << all_mp3s.size() << std::endl; // Set up the static files we need to serve. read_static_file("/static/add.png", "/usr/share/icons/gnome/16x16/actions/gtk-add.png"); read_static_file("/static/play.png", "/usr/share/icons/gnome/16x16/actions/gtk-media-play-ltr.png"); read_static_file("/static/remove.png", "/usr/share/icons/gnome/16x16/actions/gtk-remove.png"); static_file_map["/static/site.css"] = make_css(); // Start the mp3 player thread. boost::thread mp3_player_thread(mp3_play_loop); // Start the HTTP server. std::cerr << "Starting HTTP server on port " << mp3d_port << "..." << std::endl; const int mhd_flags = MHD_USE_SELECT_INTERNALLY; MHD_Daemon* daemon = MHD_start_daemon(mhd_flags, mp3d_port, 0, 0, &handle_request, 0, MHD_OPTION_END); if (daemon == 0) { fail("MHD_start_daemon failed!"); } getchar(); // Wait for the user to hit enter. MHD_stop_daemon(daemon); //mp3_player_thread.join(); return 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 i; MHD_socket fd; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_DEBUG, 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); if (d == NULL) return 256; c = setupCURL(&cbc); 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; } for (i = 0; i < 2; i++) { 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; select (maxposixs + 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 (i == 0 && msg->data.result != CURLE_OK) printf ("%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); else if (i == 1 && msg->data.result == CURLE_OK) printf ("%s should have failed at %s:%d\n", "curl_multi_perform", __FILE__, __LINE__); curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); c = NULL; multi = NULL; } } MHD_run (d); } if (i == 0) { /* quiesce the daemon on the 1st iteration, so the 2nd should fail */ fd = MHD_quiesce_daemon(d); if (MHD_INVALID_SOCKET == fd) { fprintf (stderr, "MHD_quiesce_daemon failed.\n"); curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 2; } c = setupCURL (&cbc); multi = curl_multi_init (); mret = curl_multi_add_handle (multi, c); if (mret != CURLM_OK) { curl_multi_remove_handle (multi, c); curl_multi_cleanup (multi); curl_easy_cleanup (c); MHD_stop_daemon (d); return 32768; } } } if (multi != NULL) { curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); curl_multi_cleanup (multi); } MHD_stop_daemon (d); MHD_socket_close_ (fd); if (cbc.pos != strlen ("/hello_world")) return 8192; if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 16384; return 0; }
static int testExternalPut () { struct MHD_Daemon *d; CURL *c; 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 pos = 0; int done_flag = 0; char buf[2048]; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; multi = NULL; d = MHD_start_daemon (MHD_USE_ERROR_LOG, 1082, NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (PUT_SIZE * 4), MHD_OPTION_END); if (d == NULL) return 256; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1082/hello_world"); 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, (long) PUT_SIZE); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); 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, 1); 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)) { if (EINTR != errno) abort (); } 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")) { fprintf (stderr, "Got invalid response `%.*s'\n", (int)cbc.pos, cbc.buf); return 8192; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 16384; return 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; int max; int running; time_t start; struct timeval tv; int i; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_NO_FLAG /* | MHD_USE_DEBUG */ , 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); if (d == NULL) return 256; multi = curl_multi_init (); if (multi == NULL) { MHD_stop_daemon (d); return 512; } zzuf_socat_start (); for (i = 0; i < LOOP_COUNT; i++) { fprintf (stderr, "."); c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world"); 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_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt (c, CURLOPT_TIMEOUT_MS, CURL_TIMEOUT); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT_MS, CURL_TIMEOUT); // 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); zzuf_socat_stop (); 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); zzuf_socat_stop (); 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); zzuf_socat_stop (); 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) { curl_multi_info_read (multi, &running); 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); } } fprintf (stderr, "\n"); curl_multi_cleanup (multi); zzuf_socat_stop (); MHD_stop_daemon (d); return 0; }
static int testLongUrlGet () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; char *url; long code; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , 1080, &apc_all, NULL, &ahc_echo, "GET", MHD_OPTION_CONNECTION_MEMORY_LIMIT, VERY_LONG / 2, MHD_OPTION_END); if (d == NULL) return 1; c = curl_easy_init (); url = malloc (VERY_LONG); memset (url, 'a', VERY_LONG); url[VERY_LONG - 1] = '\0'; memcpy (url, "http://localhost:1080/", strlen ("http://localhost:1080/")); 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); 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 == 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_REQUEST_URI_TOO_LONG) return 8; return 0; }
/* **************************************************************************** * * restStart - */ static int restStart(IpVersion ipVersion, const char* httpsKey = NULL, const char* httpsCertificate = NULL) { if (port == 0) LM_RE(1, ("Please call restInit before starting the REST service")); if ((ipVersion == IPV4) || (ipVersion == IPDUAL)) { memset(&sad, 0, sizeof(sad)); if (inet_pton(AF_INET, bindIp, &(sad.sin_addr.s_addr)) != 1) LM_RE(2, ("V4 inet_pton fail for %s", bindIp)); sad.sin_family = AF_INET; sad.sin_port = htons(port); if ((httpsKey != NULL) && (httpsCertificate != NULL)) { mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL, // MHD_USE_SELECT_INTERNALLY htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_HTTPS_MEM_KEY, httpsKey, MHD_OPTION_HTTPS_MEM_CERT, httpsCertificate, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, 2 * PAYLOAD_SIZE, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad, MHD_OPTION_END); } else { LM_V(("Starting HTTP daemon on IPv4 %s port %d", bindIp, port)); mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, // MHD_USE_SELECT_INTERNALLY htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, 2 * PAYLOAD_SIZE, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad, MHD_OPTION_END); } if (mhdDaemon == NULL) LM_RE(3, ("MHD_start_daemon failed")); } if ((ipVersion == IPV6) || (ipVersion == IPDUAL)) { memset(&sad_v6, 0, sizeof(sad_v6)); if (inet_pton(AF_INET6, bindIPv6, &(sad_v6.sin6_addr.s6_addr)) != 1) LM_RE(1, ("V6 inet_pton fail for %s", bindIPv6)); sad_v6.sin6_family = AF_INET6; sad_v6.sin6_port = htons(port); if ((httpsKey != NULL) && (httpsCertificate != NULL)) { LM_V(("Starting HTTPS daemon on IPv6 %s port %d", bindIPv6, port)); mhdDaemon_v6 = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_IPv6 | MHD_USE_SSL, htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_HTTPS_MEM_KEY, httpsKey, MHD_OPTION_HTTPS_MEM_CERT, httpsCertificate, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, 2 * PAYLOAD_SIZE, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad_v6, MHD_OPTION_END); } else { LM_V(("Starting HTTP daemon on IPv6 %s port %d", bindIPv6, port)); mhdDaemon_v6 = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_IPv6, htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, 2 * PAYLOAD_SIZE, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad_v6, MHD_OPTION_END); } if (mhdDaemon_v6 == NULL) LM_RE(1, ("MHD_start_daemon_v6 failed")); } return 0; }
static int testExternalPut () { 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; int max; int running; struct CURLMsg *msg; time_t start; struct timeval tv; unsigned int pos = 0; int done_flag = 0; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_DEBUG, 11082, NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_END); if (d == NULL) return 256; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11082/hello_world"); 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); /* // by not giving the file size, we force chunking! curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L); */ curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L); // NOTE: use of CONNECTTIMEOUT without also // setting NOSIGNAL results in really weird // crashes on my system! curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); 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)) { 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_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; }
/**@internal * Main execution loop */ static void main_loop(void) { int result = 0; pthread_t tid; s_config *config; config = config_get_config(); /* Set the time when nodogsplash started */ if (!started_time) { debug(LOG_INFO, "Setting started_time"); started_time = time(NULL); } else if (started_time < MINIMUM_STARTED_TIME) { debug(LOG_WARNING, "Detected possible clock skew - re-setting started_time"); started_time = time(NULL); } /* If we don't have the Gateway IP address, get it. Exit on failure. */ if (!config->gw_address) { debug(LOG_DEBUG, "Finding IP address of %s", config->gw_interface); if ((config->gw_address = get_iface_ip(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config->gw_interface); exit(1); } } if ((config->gw_mac = get_iface_mac(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get MAC address information of %s, exiting...", config->gw_interface); exit(1); } debug(LOG_NOTICE, "Detected gateway %s at %s (%s)", config->gw_interface, config->gw_address, config->gw_mac); /* Initializes the web server */ if ((webserver = MHD_start_daemon( MHD_USE_EPOLL_INTERNALLY, config->gw_port, NULL, NULL, libmicrohttpd_cb, NULL, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, MHD_OPTION_LISTENING_ADDRESS_REUSE, 1, MHD_OPTION_END)) == NULL) { debug(LOG_ERR, "Could not create web server: %s", strerror(errno)); exit(1); } /* TODO: set listening socket */ debug(LOG_NOTICE, "Created web server on %s:%d", config->gw_address, config->gw_port); /* httpdAddCContent(webserver, "/", "", 0, NULL, http_nodogsplash_callback_index); httpdAddCWildcardContent(webserver, config->authdir, NULL, http_nodogsplash_callback_auth); httpdAddCWildcardContent(webserver, config->denydir, NULL, http_nodogsplash_callback_deny); httpdAddC404Content(webserver, http_nodogsplash_callback_404); */ /* Reset the firewall (cleans it, in case we are restarting after nodogsplash crash) */ fw_destroy(); /* Then initialize it */ debug(LOG_NOTICE, "Initializing firewall rules"); if (fw_init() != 0) { debug(LOG_ERR, "Error initializing firewall rules! Cleaning up"); fw_destroy(); debug(LOG_ERR, "Exiting because of error initializing firewall rules"); exit(1); } /* Start client statistics and timeout clean-up thread */ result = pthread_create(&tid_client_check, NULL, thread_client_timeout_check, NULL); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create thread_client_timeout_check - exiting"); termination_handler(0); } pthread_detach(tid_client_check); /* Start control thread */ result = pthread_create(&tid, NULL, thread_ndsctl, (void *)(config->ndsctl_sock)); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create thread_ndsctl - exiting"); termination_handler(1); } result = pthread_join(tid, NULL); if (result) { debug(LOG_INFO, "Failed to wait for nodogsplash thread."); } MHD_stop_daemon(webserver); termination_handler(result); }
/* **************************************************************************** * * restStart - */ static int restStart(IpVersion ipVersion, const char* httpsKey = NULL, const char* httpsCertificate = NULL) { bool mhdStartError = true; size_t memoryLimit = 2 * PAYLOAD_SIZE; if (port == 0) { LM_X(1, ("Fatal Error (please call restInit before starting the REST service)")); } if ((ipVersion == IPV4) || (ipVersion == IPDUAL)) { memset(&sad, 0, sizeof(sad)); if (inet_pton(AF_INET, bindIp, &(sad.sin_addr.s_addr)) != 1) { LM_X(2, ("Fatal Error (V4 inet_pton fail for %s)", bindIp)); } sad.sin_family = AF_INET; sad.sin_port = htons(port); if ((httpsKey != NULL) && (httpsCertificate != NULL)) { LM_T(LmtMhd, ("Starting HTTPS daemon on IPv4 %s port %d", bindIp, port)); mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL, // MHD_USE_SELECT_INTERNALLY htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_HTTPS_MEM_KEY, httpsKey, MHD_OPTION_HTTPS_MEM_CERT, httpsCertificate, MHD_OPTION_CONNECTION_MEMORY_LIMIT, memoryLimit, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_END); } else { LM_T(LmtMhd, ("Starting HTTP daemon on IPv4 %s port %d", bindIp, port)); mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, // MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, memoryLimit, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_END); } if (mhdDaemon != NULL) { mhdStartError = false; } } if ((ipVersion == IPV6) || (ipVersion == IPDUAL)) { memset(&sad_v6, 0, sizeof(sad_v6)); if (inet_pton(AF_INET6, bindIPv6, &(sad_v6.sin6_addr.s6_addr)) != 1) { LM_X(4, ("Fatal Error (V6 inet_pton fail for %s)", bindIPv6)); } sad_v6.sin6_family = AF_INET6; sad_v6.sin6_port = htons(port); if ((httpsKey != NULL) && (httpsCertificate != NULL)) { LM_T(LmtMhd, ("Starting HTTPS daemon on IPv6 %s port %d", bindIPv6, port)); mhdDaemon_v6 = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_IPv6 | MHD_USE_SSL, htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_HTTPS_MEM_KEY, httpsKey, MHD_OPTION_HTTPS_MEM_CERT, httpsCertificate, MHD_OPTION_CONNECTION_MEMORY_LIMIT, memoryLimit, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad_v6, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_END); } else { LM_T(LmtMhd, ("Starting HTTP daemon on IPv6 %s port %d", bindIPv6, port)); mhdDaemon_v6 = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_IPv6, htons(port), NULL, NULL, connectionTreat, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, memoryLimit, MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad_v6, MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL, MHD_OPTION_END); } if (mhdDaemon_v6 != NULL) { mhdStartError = false; } } if (mhdStartError == true) { LM_X(5, ("Fatal Error (error starting REST interface)")); } 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 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; }
/** * Main function * @param argc : number of arguments given on the command line. * @param argv : an array of strings that contains command line arguments. * @returns always 0 */ int main(int argc, char **argv) { server_struct_t *server_struct = NULL; /** main structure for 'server' program. */ guint id_int = 0; guint id_term = 0; #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init(); /** g_type_init() is deprecated since glib 2.36 */ #endif ignore_sigpipe(); /** into order to get libmicrohttpd portable */ init_international_languages(); server_struct = init_server_main_structure(argc, argv); if (server_struct != NULL && server_struct->opt != NULL && server_struct->backend != NULL) { server_struct->loop = g_main_loop_new(g_main_context_default(), FALSE); id_int = g_unix_signal_add(SIGINT, int_signal_handler, server_struct); id_term = g_unix_signal_add(SIGTERM, int_signal_handler, server_struct); if (id_int <= 0 || id_term <= 0) { print_error(__FILE__, __LINE__, _("Unable to add signal handler\n")); } /* Initializing the choosen backend by calling it's function */ if (server_struct->backend->init_backend != NULL) { server_struct->backend->init_backend(server_struct); } /* Before starting anything else, start the threads */ server_struct->meta_thread = g_thread_new("meta-data", meta_data_thread, server_struct); server_struct->data_thread = g_thread_new("data", data_thread, server_struct); /* Starting the libmicrohttpd daemon */ server_struct->d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, server_struct->opt->port, NULL, NULL, &ahc, server_struct, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) 131070 , MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, MHD_OPTION_END); if (server_struct->d == NULL) { print_error(__FILE__, __LINE__, _("Error while spawning libmicrohttpd daemon\n")); return 1; } /* Unless on error we will never join the threads as they * contain a while (TRUE) loop ! */ g_main_loop_run(server_struct->loop); /* g_thread_join(server_struct->meta_thread); */ /* g_thread_join(server_struct->data_thread); */ } else { print_error(__FILE__, __LINE__, _("Error: initialization failed.\n")); } 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 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 testInternalSelectGet () { 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; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem, MHD_OPTION_END); if (d == NULL) return 256; char *aes256_sha = "AES256-SHA"; if (curl_uses_nss_ssl() == 0) { aes256_sha = "rsa_aes_256_sha"; } c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "https://127.0.0.1:1082/hello_world"); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); /* TLS options */ curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3); curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha); curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0); 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); 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)) { max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); 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; } 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_multi_cleanup (multi); curl_easy_cleanup (c); c = NULL; multi = NULL; } } } if (multi != NULL) { curl_multi_remove_handle (multi, c); curl_easy_cleanup (c); curl_multi_cleanup (multi); } MHD_stop_daemon (d); if (cbc.pos != 0) return 8192; return 0; }
static int testLongHeaderGet () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; char *url; long code; struct curl_slist *header = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY /* | MHD_USE_DEBUG */ , 1080, &apc_all, NULL, &ahc_echo, "GET", MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (VERY_LONG / 2), MHD_OPTION_END); if (d == NULL) return 16; c = curl_easy_init (); url = malloc (VERY_LONG); if (url == NULL) { MHD_stop_daemon (d); return 16; } memset (url, 'a', VERY_LONG); url[VERY_LONG - 1] = '\0'; url[VERY_LONG / 2] = ':'; url[VERY_LONG / 2 + 1] = ' '; header = curl_slist_append (header, url); curl_easy_setopt (c, CURLOPT_HTTPHEADER, header); curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1080/hello_world"); 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 == curl_easy_perform (c)) { curl_easy_cleanup (c); MHD_stop_daemon (d); curl_slist_free_all (header); free (url); return 32; } if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code)) { curl_slist_free_all (header); curl_easy_cleanup (c); MHD_stop_daemon (d); free (url); return 64; } curl_slist_free_all (header); curl_easy_cleanup (c); MHD_stop_daemon (d); free (url); if (code != MHD_HTTP_REQUEST_ENTITY_TOO_LARGE) return 128; return 0; }
static int testMultithreadedPoolPost () { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLcode errornum; int i; char url[1024]; cbc.buf = buf; cbc.size = 2048; d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, 1081, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END); if (d == NULL) return 16; for (i = 0; i < LOOPCOUNT; i++) { if (99 == i % 100) fprintf (stderr, "."); c = curl_easy_init (); cbc.pos = 0; buf[0] = '\0'; sprintf (url, "http://127.0.0.1:1081/hw%d", 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, 1); 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, 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 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; }
int main(int argc,char *argv[]) { extern char *optarg; extern int optind; int ch; struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"debug", no_argument, 0, 'd'}, {"quiet", no_argument, 0, 'q'}, {"log", required_argument, 0, 'l'}, {"command", required_argument, 0, 'c'}, #ifdef HAVE_LIBMICROHTTPD {"port", required_argument, 0, 'p'}, #endif {0, 0, 0, 0} }; int contest_offset; char *tmp; char buf[BUF_SIZE]; int ttylog,lu,i,q; struct winsize ws; #ifdef HAVE_LIBMICROHTTPD unsigned int port = 0; #endif regmatch_t pmatch[2]; char defcmd[] = "dnetc", logfile[128] = "stdout"; int pos_cpu[MAX_CPU]; char p[] = "a"; int log_fd; /* check arguments */ #ifdef HAVE_LIBMICROHTTPD while ((ch = getopt_long(argc, argv, "hdVql:c:p:", long_options, NULL)) != -1) #else while ((ch = getopt_long(argc, argv, "hdVql:c:", long_options, NULL)) != -1) #endif { switch(ch) { case 'd': dflag = 1; break; case 'V': printf("%s\n",GKRELLDNET_VERSION); exit(0); break; #ifdef HAVE_LIBMICROHTTPD case 'p': port = atoi(optarg); break; #endif case 'q': qflag = 1; break; case 'c': nargc = get_arg(&nargv,optarg); break; case 'l': strcpy(logfile,optarg); break; case 'h': default: usage(argv[0]); } } if(argc - optind != 0) usage(argv[0]); /* continue in background if in quiet mode */ if(qflag == 1 && ((new_pid = fork()) != 0)) { if(new_pid < 0) clean_and_exit("forking daemon",1); else exit(0); } /* default command line */ if(nargv == NULL) nargc = get_arg(&nargv,defcmd); /* change output to logfile */ if(strcmp(logfile,"stdout") != 0) { if((log_fd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) clean_and_exit("opening logfile",1); if(dup2(log_fd,1) == -1) clean_and_exit("dup2",1); } ttylog = isatty(1); /* creat shared memory segment */ if((shmid = my_shmcreate(sizeof(struct dnetc_values),IPC_CREAT|IPC_EXCL|0644)) == -1) clean_and_exit("shmget",1); if((int) (shmem = shmat(shmid,0,0)) == -1) clean_and_exit("shmat",1); /* init shared memory content */ shmem->running = TRUE; strcpy(shmem->contest,"???"); shmem->cmode = CRUNCH_RELATIVE; shmem->wu_in = shmem->wu_out = 0; shmem->n_cpu = 1; for(i=0;i<MAX_CPU;i++) shmem->val_cpu[i] = 0; /* precompile regex */ if(regcomp(&preg_in,"[0-9]+.packets?.+remains?.in",REG_EXTENDED) != 0) clean_and_exit(NULL,1); if(regcomp(&preg_out,"[0-9]+.packets?(.+in.buff-out|.\\(.+stats?.units?\\).(are|is).in)",REG_EXTENDED) != 0) clean_and_exit(NULL,1); if(regcomp(&preg_contest,"[A-Z0-9-]{3,6}(.#[a-z])?:.Loaded",REG_EXTENDED) != 0) clean_and_exit(NULL,1); if(regcomp(&preg_proxy,"((Retrieved|Sent).+(stat..unit|packet)|Attempting.to.resolve|Connect(ing|ed).to)",REG_EXTENDED) !=0) clean_and_exit(NULL,1); contest_offset = 0; if(regcomp(&preg_absolute,"(#[0-9]+: [A-Z0-9-]{3,6}|[A-Z0-9-]{3,6}(.#[a-z])?):.+\\[[,0-9]+\\]",REG_EXTENDED) != 0) clean_and_exit(NULL,1); if(regcomp(&preg_cruncher,"[0-9]+.cruncher.*started",REG_EXTENDED) != 0) clean_and_exit(NULL,1); regex_flag = 1; /* obtain a pseudo-terminal */ ws.ws_col = 132; ws.ws_row = 10; ws.ws_xpixel = ws.ws_ypixel = 0; if((openpty(&fd,&tty_fd,NULL,NULL,&ws)) == -1) clean_and_exit("openpty",1); /* start dnet client and start reading tty */ if((fils = fork()) == -1) clean_and_exit("fork",1); if(fils == 0) { /* change to dnetc directory */ change_dir(); /* start dnet client */ if(dup2(tty_fd,1) == -1) clean_and_exit("dup2",1); if(execvp(nargv[0],nargv) == -1) clean_and_exit("execvp",1); } #ifdef HAVE_LIBMICROHTTPD /* start http server */ if(port > 0) { struct sockaddr_in so; so.sin_family = AF_INET; so.sin_port = htons(port); so.sin_addr.s_addr = htonl(INADDR_LOOPBACK); http_daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, port, NULL, NULL, &answer_to_connection, shmem, MHD_OPTION_SOCK_ADDR, &so, MHD_OPTION_END); if(http_daemon == NULL) clean_and_exit("MHD_start_daemon",1); } #endif /* set signal handler */ if(signal(SIGHUP,got_signal) == SIG_ERR || signal(SIGINT,got_signal) == SIG_ERR || signal(SIGQUIT,got_signal) == SIG_ERR || signal(SIGCHLD,got_signal) == SIG_ERR || signal(SIGTERM,got_signal) == SIG_ERR) clean_and_exit("signal",1); /* some more init */ for(i=0;i<MAX_CPU;i++) shmem->val_cpu[i] = 0; /* main loop */ while((lu = mygets(fd,buf,BUF_SIZE)) > 0) { if(dflag) fprintf(stderr,"buf[0] = %x\n<--\n%s\n-->\n",buf[0],buf); if(buf[1] == '.' || buf[lu-1] != '\n') { if(dflag) fprintf(stderr,"lu: %02d, ",lu); /* fix line with two 0x0d char */ if((tmp = strchr(&buf[1],0x0d)) != NULL) lu = tmp-buf; /* skip line with proxy comm. */ q = regexec(&preg_proxy,buf,1,pmatch,0); if(q != 0) { /* check if line match absolute crunch-o-meter */ if(regexec(&preg_absolute,buf,1,pmatch,0) == 0) { /* set crunch-o-meter mode */ shmem->cmode = CRUNCH_ABSOLUTE; /* read CPU num */ tmp = strchr(&buf[pmatch[0].rm_so],'#'); if(tmp != NULL) { if(isdigit(tmp[1])) i = strtol(&buf[pmatch[0].rm_so+1],(char **) NULL,10) - 1; else if(islower(tmp[1])) i = tmp[1] - 'a'; /* avoid core dump */ i %= MAX_CPU; } else i = 0; /* read k(keys|nodes) */ shmem->val_cpu[i] = extract_val(&buf[pmatch[0].rm_so]); if(dflag) { fprintf(stderr,"\ncpu = %d, %llu nodes|keys\n",i,shmem->val_cpu[i]); fprintf(stderr,"found: %s\n",&buf[pmatch[0].rm_so]); } } else { /* set crunch-o-meter mode */ shmem->cmode = CRUNCH_RELATIVE; for(i=0;i<shmem->n_cpu;i++) { if(shmem->n_cpu != 1) { p[0] = 'a' + i; if((tmp = strstr(buf,p)) != NULL) pos_cpu[i] = tmp - buf; } else pos_cpu[i] = lu - 1; shmem->val_cpu[i] = (pos_cpu[i] - (pos_cpu[i]/8)*3) * 2; if(shmem->val_cpu[i] > 100) shmem->val_cpu[i] = 100; if(dflag) fprintf(stderr,"cpu%d: %llu,",i,shmem->val_cpu[i]); } if(dflag) fprintf(stderr,"\n"); } } if(!qflag && (ttylog || q == 0)) { printf("%s",buf); fflush(stdout); } } else { if(regexec(&preg_in,buf,1,pmatch,0) == 0) shmem->wu_in = strtol(&buf[pmatch[0].rm_so],NULL,10); if(regexec(&preg_out,buf,1,pmatch,0) == 0) shmem->wu_out = strtol(&buf[pmatch[0].rm_so],NULL,10); if(regexec(&preg_contest,buf,1,pmatch,0) == 0) strncpy(shmem->contest,&buf[pmatch[0].rm_so+contest_offset],3); if(regexec(&preg_cruncher,buf,1,pmatch,0) == 0) { shmem->n_cpu = strtol(&buf[pmatch[0].rm_so],NULL,10); /* too many crunchers */ if(shmem->n_cpu > MAX_CPU) { fprintf(stderr,"dnetw: too many crunchers\n"); clean_and_exit(NULL,1); } } if(dflag) fprintf(stderr,"contest = %s, in = %d, out = %d, n_cpu = %d\n",shmem->contest, shmem->wu_in, shmem->wu_out, shmem->n_cpu); if(!qflag) { printf("%s",buf); fflush(stdout); } } } clean_and_exit(NULL,0); 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 max; int running; struct CURLMsg *msg; time_t start; struct timeval tv; int i; unsigned long long timeout; long ctimeout; char url[1024]; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_DEBUG, 1082, NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); if (d == NULL) return 256; 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'; sprintf (url, "http://127.0.0.1:1082/hw%d", 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, 1); 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, 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) && (multi != NULL)) { max = 0; 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, &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; } if (MHD_NO == MHD_get_timeout (d, &timeout)) timeout = 100; /* 100ms == INFTY -- CURL bug... */ if ((CURLM_OK == curl_multi_timeout (multi, &ctimeout)) && (ctimeout < 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 (max + 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; }
/** * Test upgrading a connection. * * @param flags which event loop style should be tested * @param pool size of the thread pool, 0 to disable */ static int test_upgrade (int flags, unsigned int pool) { struct MHD_Daemon *d = NULL; wr_socket sock; struct sockaddr_in sa; #if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID) pid_t pid = -1; #endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */ done = 0; if (!test_tls) d = MHD_start_daemon (flags | MHD_USE_ERROR_LOG | MHD_ALLOW_UPGRADE, 1080, NULL, NULL, &ahc_upgrade, NULL, MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, MHD_OPTION_NOTIFY_COMPLETED, ¬ify_completed_cb, NULL, MHD_OPTION_NOTIFY_CONNECTION, ¬ify_connection_cb, NULL, MHD_OPTION_THREAD_POOL_SIZE, pool, MHD_OPTION_END); #ifdef HTTPS_SUPPORT else d = MHD_start_daemon (flags | MHD_USE_ERROR_LOG | MHD_ALLOW_UPGRADE | MHD_USE_TLS, 1080, NULL, NULL, &ahc_upgrade, NULL, MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, MHD_OPTION_NOTIFY_COMPLETED, ¬ify_completed_cb, NULL, MHD_OPTION_NOTIFY_CONNECTION, ¬ify_connection_cb, NULL, MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, MHD_OPTION_THREAD_POOL_SIZE, pool, MHD_OPTION_END); #endif /* HTTPS_SUPPORT */ if (NULL == d) return 2; if (!test_tls || TLS_LIB_GNUTLS == use_tls_tool) { sock = test_tls ? wr_create_tls_sckt () : wr_create_plain_sckt (); if (WR_BAD == sock) abort (); sa.sin_family = AF_INET; sa.sin_port = htons (1080); sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); if (0 != wr_connect (sock, (struct sockaddr *) &sa, sizeof (sa))) abort (); } else { #if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID) MHD_socket tls_fork_sock; if (-1 == (pid = gnutlscli_connect (&tls_fork_sock, 1080))) { MHD_stop_daemon (d); return 4; } sock = wr_create_from_plain_sckt (tls_fork_sock); if (WR_BAD == sock) abort (); #else /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */ abort (); #endif /* !HTTPS_SUPPORT || !HAVE_FORK || !HAVE_WAITPID */ } if (0 != pthread_create (&pt_client, NULL, &run_usock_client, &sock)) abort (); if (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD) ) run_mhd_loop (d, flags); pthread_join (pt_client, NULL); pthread_join (pt, NULL); #if defined(HTTPS_SUPPORT) && defined(HAVE_FORK) && defined(HAVE_WAITPID) if (test_tls && TLS_LIB_GNUTLS != use_tls_tool) waitpid (pid, NULL, 0); #endif /* HTTPS_SUPPORT && HAVE_FORK && HAVE_WAITPID */ MHD_stop_daemon (d); return 0; }
/** * Entry point to demo. Note: this HTTP server will make all * files in the current directory and its subdirectories available * to anyone. Press ENTER to stop the server once it has started. * * @param argc number of arguments in argv * @param argv first and only argument should be the port number * @return 0 on success */ int main (int argc, char *const *argv) { struct MHD_Daemon *d; unsigned int port; if ( (argc != 2) || (1 != sscanf (argv[1], "%u", &port)) || (UINT16_MAX < port) ) { fprintf (stderr, "%s PORT\n", argv[0]); return 1; } #ifndef MINGW ignore_sigpipe (); #endif magic = magic_open (MAGIC_MIME_TYPE); (void) magic_load (magic, NULL); (void) pthread_mutex_init (&mutex, NULL); file_not_found_response = MHD_create_response_from_buffer (strlen (FILE_NOT_FOUND_PAGE), (void *) FILE_NOT_FOUND_PAGE, MHD_RESPMEM_PERSISTENT); mark_as_html (file_not_found_response); request_refused_response = MHD_create_response_from_buffer (strlen (REQUEST_REFUSED_PAGE), (void *) REQUEST_REFUSED_PAGE, MHD_RESPMEM_PERSISTENT); mark_as_html (request_refused_response); internal_error_response = MHD_create_response_from_buffer (strlen (INTERNAL_ERROR_PAGE), (void *) INTERNAL_ERROR_PAGE, MHD_RESPMEM_PERSISTENT); mark_as_html (internal_error_response); update_directory (); d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG #if EPOLL_SUPPORT | MHD_USE_EPOLL_LINUX_ONLY #endif , port, NULL, NULL, &generate_page, NULL, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (256 * 1024), #if PRODUCTION MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) (64), #endif MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) (120 /* seconds */), MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS, MHD_OPTION_NOTIFY_COMPLETED, &response_completed_callback, NULL, MHD_OPTION_END); if (NULL == d) return 1; fprintf (stderr, "HTTP server running. Press ENTER to stop the server\n"); (void) getc (stdin); MHD_stop_daemon (d); MHD_destroy_response (file_not_found_response); MHD_destroy_response (request_refused_response); MHD_destroy_response (internal_error_response); update_cached_response (NULL); (void) pthread_mutex_destroy (&mutex); magic_close (magic); 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 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 testDigestAuth () { int fd; CURL *c; CURLcode errornum; struct MHD_Daemon *d; struct CBC cbc; size_t len; size_t off = 0; char buf[2048]; char rnd[8]; 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 == -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, 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_SELECT_INTERNALLY | MHD_USE_DEBUG, 1337, 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; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1337/foo?key=value"); 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, 1); 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, 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 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 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 testGet (int type, int pool_count, int poll_flag) { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLcode errornum; MHD_socket fd; pthread_t thrd; const char *thrdRet; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; if (pool_count > 0) { d = MHD_start_daemon (type | MHD_USE_DEBUG | MHD_USE_PIPE_FOR_SHUTDOWN | poll_flag, 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_THREAD_POOL_SIZE, pool_count, MHD_OPTION_END); } else { d = MHD_start_daemon (type | MHD_USE_DEBUG | MHD_USE_PIPE_FOR_SHUTDOWN | poll_flag, 11080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); } if (d == NULL) return 1; c = setupCURL(&cbc); 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; } if (cbc.pos != strlen ("/hello_world")) { curl_easy_cleanup (c); MHD_stop_daemon (d); return 4; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) { curl_easy_cleanup (c); MHD_stop_daemon (d); return 8; } fd = MHD_quiesce_daemon (d); if (MHD_INVALID_SOCKET == fd) { fprintf (stderr, "MHD_quiesce_daemon failed.\n"); curl_easy_cleanup (c); MHD_stop_daemon (d); return 2; } if (0 != pthread_create(&thrd, NULL, &ServeOneRequest, (void*)(intptr_t) fd)) { fprintf (stderr, "pthread_create failed\n"); curl_easy_cleanup (c); MHD_stop_daemon (d); return 16; } cbc.pos = 0; 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; } if (0 != pthread_join(thrd, (void**)&thrdRet)) { fprintf (stderr, "pthread_join failed\n"); curl_easy_cleanup (c); MHD_stop_daemon (d); return 16; } if (NULL != thrdRet) { fprintf (stderr, "ServeOneRequest() error: %s\n", thrdRet); curl_easy_cleanup (c); MHD_stop_daemon (d); return 16; } if (cbc.pos != strlen ("/hello_world")) { fprintf(stderr, "%s\n", cbc.buf); curl_easy_cleanup (c); MHD_stop_daemon (d); MHD_socket_close_(fd); return 4; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) { fprintf(stderr, "%s\n", cbc.buf); curl_easy_cleanup (c); MHD_stop_daemon (d); MHD_socket_close_(fd); return 8; } /* at this point, the forked server quit, and the new * server has quiesced, so new requests should fail */ if (CURLE_OK == (errornum = curl_easy_perform (c))) { fprintf (stderr, "curl_easy_perform should fail\n"); curl_easy_cleanup (c); MHD_stop_daemon (d); MHD_socket_close_(fd); return 2; } curl_easy_cleanup (c); MHD_stop_daemon (d); MHD_socket_close_(fd); return 0; }
int main(int argc, char *const *argv) { struct MHD_Daemon *d; if (argc != 4) { printf("%s PORT DHT-PEER-NAME DHT-PEER-PORT\n", argv[0]); return 1; } printf("Setting up server...\n"); printf("\n\n[[[ API ]]]\n GET: /dht/:key\n POST: /dht with data url-encoded in body\n DELETE: /dht/:key\n\n"); // SET UP DHT PEER //Resolv hostname to IP Address if ((he = gethostbyname(argv[2])) == NULL) { // get the host info herror("gethostbyname"); printf("Fatal: Couldn't resolve host."); exit(1); } their_addr.sin_family = AF_INET; server_port = htons(atoi(argv[3])); their_addr.sin_port = server_port; their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero); addrlen = sizeof(their_addr); printf("init port with %d\n", their_addr.sin_port); // straight from the docs: /** * Start a webserver on the given port. Variadic version of * #MHD_start_daemon_va. * * @param flags combination of `enum MHD_FLAG` values * @param port port to bind to * @param apc callback to call to check which clients * will be allowed to connect; you can pass NULL * in which case connections from any IP will be * accepted * @param apc_cls extra argument to apc * @param dh handler called for all requests (repeatedly) * @param dh_cls extra argument to @a dh * @return NULL on error, handle to daemon on success * @ingroup event */ port = atoi(argv[1]); d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, port, NULL, NULL, &answer_to_connection, NULL, MHD_OPTION_NOTIFY_COMPLETED, request_completed, NULL, MHD_OPTION_END); if (d == NULL) { return 1; } printf("DHT REST API started.\nHit any key to shut down...\n\n"); // wait for input and exit getc(stdin); printf("Shutdown signal recieved.\n"); MHD_stop_daemon(d); printf("Server shut down.\n\n"); return 0; }
static int testMultithreadedPoolPut () { struct MHD_Daemon *d; CURL *c; struct CBC cbc; unsigned int pos = 0; int done_flag = 0; CURLcode errornum; char buf[2048]; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 1081, NULL, NULL, &ahc_echo, &done_flag, MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (1024*1024), MHD_OPTION_END); if (d == NULL) return 16; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world"); 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, (long) PUT_SIZE); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); 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, 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 32; } curl_easy_cleanup (c); MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) { fprintf (stderr, "Got invalid response `%.*s'\n", (int)cbc.pos, cbc.buf); return 64; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) return 128; return 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 max; int running; struct CURLMsg *msg; time_t start; struct timeval tv; multi = NULL; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_DEBUG, 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); if (d == NULL) return 256; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world"); 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); 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)) { 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_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; }
void httpd_proc(int rank) { #ifdef LIBMICROHTTPD int status; fd_set rs; fd_set ws; fd_set es; int max; #endif struct httpd_cb *cb = httpd_cb_list; /*child's initial settings*/ if (init_mi_child()!=0) { LM_ERR("failed to init the mi child process\n"); return; } /* Allocating http response buffer */ buffer.s = (char*)pkg_malloc(sizeof(char)*buffer.len); if (buffer.s==NULL) { LM_ERR("oom\n"); return; } while(cb) { if (cb->init_proc_callback) cb->init_proc_callback(); cb = cb->next; } #ifdef LIBMICROHTTPD struct timeval tv; struct sockaddr_in saddr_in; memset(&saddr_in, 0, sizeof(saddr_in)); if (ip.s) saddr_in.sin_addr.s_addr = inet_addr(ip.s); else saddr_in.sin_addr.s_addr = INADDR_ANY; saddr_in.sin_family = AF_INET; saddr_in.sin_port = htons(port); LM_DBG("init_child [%d] - [%d] HTTP Server init [%s:%d]\n", rank, getpid(), (ip.s?ip.s:"INADDR_ANY"), port); set_proc_attrs("HTTPD %s:%d", (ip.s?ip.s:"INADDR_ANY"), port); dmn = MHD_start_daemon(MHD_NO_FLAG|MHD_USE_DEBUG, port, NULL, NULL, &(answer_to_connection), NULL, MHD_OPTION_SOCK_ADDR, &saddr_in, MHD_OPTION_END); if (NULL == dmn) { LM_ERR("unable to start http daemon\n"); return; } while(1) { max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); if (MHD_YES != MHD_get_fdset (dmn, &rs, &ws, &es, &max)) { LM_ERR("unable to get file descriptors\n"); return; } tv.tv_sec = 1; tv.tv_usec = 0; //LM_DBG("select(%d,%p,%p,%p,%p)\n",max+1, &rs, &ws, &es, &tv); status = select(max+1, &rs, &ws, &es, &tv); switch(status){ case EBADF: LM_ERR("error returned by select: EBADF [%d] " "(Bad file descriptor)\n", status); return; break; case EINTR: LM_WARN("error returned by select: EINTR [%d] " "(Non blocked signal caught)\n", status); break; case EINVAL: LM_ERR("error returned by select: EINVAL [%d] " "(Invalid # of fd [%d] or timeout)\n", status, max+1); return; break; case ENOMEM: LM_ERR("error returned by select: ENOMEM [%d] " "(No more memory)\n", status); return; break; default: if(status<0){ switch(errno){ case EINTR: LM_WARN("error returned by select:" " [%d] [%d][%s]\n", status, errno, strerror(errno)); break; default: LM_WARN("error returned by select:" " [%d] [%d][%s]\n", status, errno, strerror(errno)); return; } } } //LM_DBG("select returned %d\n", status); status = MHD_run(dmn); if (status == MHD_NO) { LM_ERR("unable to run http daemon\n"); return; } } #endif LM_DBG("HTTP Server stopped!\n"); }
static int testMultithreadedPostCancelPart(int flags) { struct MHD_Daemon *d; CURL *c; char buf[2048]; struct CBC cbc; CURLcode errornum; struct curl_slist *headers = NULL; long response_code; CURLcode cc; int result = 0; struct CRBC crbc; /* Don't test features that aren't available with HTTP/1.0 in * HTTP/1.0 mode. */ if (!oneone && (flags & (FLAG_EXPECT_CONTINUE | FLAG_CHUNKED))) return 0; cbc.buf = buf; cbc.size = 2048; cbc.pos = 0; d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, 1081, NULL, NULL, &ahc_cancel, NULL, MHD_OPTION_END); if (d == NULL) return 32768; crbc.buffer = "Test content"; crbc.size = strlen(crbc.buffer); crbc.pos = 0; c = curl_easy_init (); curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world"); curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (c, CURLOPT_READFUNCTION, (flags & FLAG_SLOW_READ) ? &slowReadBuffer : &readBuffer); curl_easy_setopt (c, CURLOPT_READDATA, &crbc); curl_easy_setopt (c, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, crbc.size); curl_easy_setopt (c, CURLOPT_POST, 1L); curl_easy_setopt (c, CURLOPT_FAILONERROR, 1); 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, 1); if (flags & FLAG_CHUNKED) headers = curl_slist_append(headers, "Transfer-Encoding: chunked"); if (!(flags & FLAG_FORM_DATA)) headers = curl_slist_append(headers, "Content-Type: application/octet-stream"); if (flags & FLAG_EXPECT_CONTINUE) headers = curl_slist_append(headers, "Expect: 100-Continue"); curl_easy_setopt(c, CURLOPT_HTTPHEADER, headers); if (CURLE_HTTP_RETURNED_ERROR != (errornum = curl_easy_perform (c))) { fprintf (stderr, "flibbet curl_easy_perform didn't fail as expected: `%s' %d\n", curl_easy_strerror (errornum), errornum); curl_easy_cleanup (c); MHD_stop_daemon (d); curl_slist_free_all(headers); return 65536; } if (CURLE_OK != (cc = curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &response_code))) { fprintf(stderr, "curl_easy_getinfo failed: '%s'\n", curl_easy_strerror(errornum)); result = 65536; } if (!result && (response_code != 500)) { fprintf(stderr, "Unexpected response code: %ld\n", response_code); result = 131072; } if (!result && (cbc.pos != 0)) result = 262144; curl_easy_cleanup (c); MHD_stop_daemon (d); curl_slist_free_all(headers); return result; }