libmicrohttpd-get_listen_sock.patch (4,477 bytes)
commit 55bafbb567a97fe7ab852b46cefc5703ff90f3ca
Author: David Reiss <dreiss@facebook.com>
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 <stdlib.h>
#include <string.h>
#include <time.h>
+#include <sys/socket.h>
#ifndef WINDOWS
#include <unistd.h>
@@ -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 ();