commit 55bafbb567a97fe7ab852b46cefc5703ff90f3ca Author: David Reiss Date: Sun Aug 23 16:21:35 2009 -0700 Allow MHD_get_daemon_info to return the daemon's listen socket Includes a test case that uses this functionality to bind a server to an OS-assigned port, look the port up with getsockname, and curl it. diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index cc6c036..ef292cb 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -1496,7 +1496,13 @@ const union MHD_DaemonInfo * MHD_get_daemon_info (struct MHD_Daemon *daemon, enum MHD_DaemonInfoType infoType, ...) { - return NULL; + switch (infoType) + { + case MHD_DAEMON_INFO_LISTEN_FD: + return (const union MHD_DaemonInfo *) &daemon->socket_fd; + default: + return NULL; + }; } /** diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 6f358fe..256c8fc 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h @@ -595,7 +595,13 @@ enum MHD_DaemonInfoType * algorithm should be passed as an extra * argument (of type 'enum MHD_GNUTLS_HashAlgorithm'). */ - MHD_DAEMON_INFO_MAC_KEY_SIZE + MHD_DAEMON_INFO_MAC_KEY_SIZE, + + /** + * Request the file descriptor for the listening socket. + * No extra arguments should be passed. + */ + MHD_DAEMON_INFO_LISTEN_FD }; @@ -1176,6 +1182,11 @@ union MHD_DaemonInfo * Size of the mac key (unit??) */ size_t mac_key_size; + + /** + * Listen socket file descriptor + */ + int listen_fd; }; /** diff --git a/src/testcurl/daemontest_get.c b/src/testcurl/daemontest_get.c index acf2bcc..26feee9 100644 --- a/src/testcurl/daemontest_get.c +++ b/src/testcurl/daemontest_get.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifndef WINDOWS #include @@ -360,6 +361,79 @@ testExternalGet () return 0; } +static int +testUnknownPortGet () +{ + 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, + 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; +} + int @@ -374,6 +448,7 @@ main (int argc, char *const *argv) errorCount += testMultithreadedGet (); errorCount += testMultithreadedPoolGet (); errorCount += testExternalGet (); + errorCount += testUnknownPortGet (); if (errorCount != 0) fprintf (stderr, "Error (code: %u)\n", errorCount); curl_global_cleanup ();