gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] 03/06: MHD_start_daemon(): added port autod


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] 03/06: MHD_start_daemon(): added port autodetection if '0' (autoselect) is used for port number, Added new MHD_FEATURE value MHD_FEATURE_AUTODETECT_BIND_PORT.
Date: Thu, 15 Jun 2017 23:43:28 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit da9f4fd6f2f37346d1cae368ec7683506df2287a
Author: Evgeny Grin (Karlson2k) <address@hidden>
AuthorDate: Thu Jun 15 10:37:40 2017 +0300

    MHD_start_daemon(): added port autodetection if '0' (autoselect) is used 
for port number,
    Added new MHD_FEATURE value MHD_FEATURE_AUTODETECT_BIND_PORT.
---
 configure.ac             | 113 +++++++++++++++++++++++++++++++++++++++++++++++
 src/include/microhttpd.h |  19 ++++++--
 src/microhttpd/daemon.c  |  92 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 219 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3b87c42b..443dcf24 100644
--- a/configure.ac
+++ b/configure.ac
@@ -756,6 +756,119 @@ AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
 #endif
    ])
 
+AC_CHECK_DECLS([getsockname],
+  [
+   AC_CHECK_FUNCS([getsockname], 
+     [
+      AC_CACHE_CHECK([[whether getsockname() is usable]], 
[[mhc_cv_getsockname_usable]],
+        [
+         AC_RUN_IFELSE(
+           [
+            AC_LANG_SOURCE(
+             [[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+
+static void zr_mem(void *ptr, socklen_t size)
+{ char *mem = ptr; while(size--) {mem[0] = 0; mem++;} }
+
+int main(void)
+{
+  const socklen_t c_addr_size = (socklen_t)sizeof(struct sockaddr_in);
+  struct sockaddr_in sa;
+  socklen_t addr_size;
+  int ret = 1;
+#if !defined(_WIN32) || defined(__CYGWIN__)
+  int sckt;
+  const int invld_sckt = -1;
+#else
+  SOCKET sckt;
+  const SOCKET invld_sckt = INVALID_SOCKET;
+  WSADATA wsa_data;
+
+  if (0 != WSAStartup(MAKEWORD(2, 2), &wsa_data) || MAKEWORD(2, 2) != 
wsa_data.wVersion)
+    return 20;
+#endif
+
+  sckt = socket (PF_INET, SOCK_STREAM, 0);
+  if (invld_sckt != sckt)
+  {
+    zr_mem(&sa, c_addr_size);
+    sa.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    sa.sin_len = c_addr_size;
+#endif
+    if (0 == bind (sckt, (struct sockaddr *)&sa, c_addr_size))
+    {
+      if (0 == listen (sckt, 1))
+      {
+        addr_size = c_addr_size;
+        if (0 == getsockname (sckt, (struct sockaddr  *)&sa, &addr_size))
+        {
+          if (c_addr_size >= addr_size)
+          {
+            if (0 != ntohs(sa.sin_port))
+            { ret = 0;
+            } else ret = 7;
+          } else ret = 6;
+        } else ret = 5;
+      } else ret = 4;
+    } else ret = 3;
+  } else ret = 2;
+#if !defined(_WIN32) || defined(__CYGWIN__)
+  close (sckt);
+#else
+  closesocket (sckt);
+  WSACleanup();
+#endif
+  return ret;
+}
+             ]]
+            )
+           ],
+           [[mhc_cv_getsockname_usable='yes']],
+           [[mhc_cv_getsockname_usable='no']],
+           [[mhc_cv_getsockname_usable='assuming yes']]
+         )
+        ]
+      )
+      AS_VAR_IF([[mhc_cv_getsockname_usable]], [["no"]], [:],
+        [AC_DEFINE([[MHD_USE_GETSOCKNAME]], [[1]], [Define if you have usable 
`getsockname' function.])])
+     ]
+   )
+  ], [],
+  [[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+  ]]
+)
 
 # Check for inter-thread signaling type
 AC_ARG_ENABLE([[itc]],
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index d3b87c05..2319eef3 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -2095,7 +2095,11 @@ typedef int
  * Start a webserver on the given port.
  *
  * @param flags combination of `enum MHD_FLAG` values
- * @param port port to bind to (in host byte order)
+ * @param port port to bind to (in host byte order),
+ *        use '0' to bind to random free port,
+ *        ignored if MHD_OPTION_SOCK_ADDR or
+ *        MHD_OPTION_LISTEN_SOCKET is provided
+ *        or MHD_USE_NO_LISTEN_SOCKET is specified
  * @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
@@ -2121,7 +2125,11 @@ MHD_start_daemon_va (unsigned int flags,
  * #MHD_start_daemon_va.
  *
  * @param flags combination of `enum MHD_FLAG` values
- * @param port port to bind to
+ * @param port port to bind to (in host byte order),
+ *        use '0' to bind to random free port,
+ *        ignored if MHD_OPTION_SOCK_ADDR or
+ *        MHD_OPTION_LISTEN_SOCKET is provided
+ *        or MHD_USE_NO_LISTEN_SOCKET is specified
  * @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
@@ -3425,7 +3433,12 @@ enum MHD_FEATURE
    * It's always safe to use same file FD in multiple responses if MHD
    * is run in any single thread mode.
    */
-  MHD_FEATURE_RESPONSES_SHARED_FD = 18
+  MHD_FEATURE_RESPONSES_SHARED_FD = 18,
+
+  /**
+   * Get whether MHD support automatic detection of bind port number.
+   */
+  MHD_FEATURE_AUTODETECT_BIND_PORT = 19
 };
 
 
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0bf97b7c..dfb92b4d 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -4346,7 +4346,11 @@ unescape_wrapper (void *cls,
  * #MHD_start_daemon_va.
  *
  * @param flags combination of `enum MHD_FLAG` values
- * @param port port to bind to
+ * @param port port to bind to (in host byte order),
+ *        use '0' to bind to random free port,
+ *        ignored if MHD_OPTION_SOCK_ADDR or
+ *        MHD_OPTION_LISTEN_SOCKET is provided
+ *        or MHD_USE_NO_LISTEN_SOCKET is specified
  * @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
@@ -5082,7 +5086,11 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
  * Start a webserver on the given port.
  *
  * @param flags combination of `enum MHD_FLAG` values
- * @param port port to bind to (in host byte order)
+ * @param port port to bind to (in host byte order),
+ *        use '0' to bind to random free port,
+ *        ignored if MHD_OPTION_SOCK_ADDR or
+ *        MHD_OPTION_LISTEN_SOCKET is provided
+ *        or MHD_USE_NO_LISTEN_SOCKET is specified
  * @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
@@ -5621,6 +5629,80 @@ MHD_start_daemon_va (unsigned int flags,
       listen_fd = daemon->listen_fd;
     }
 
+  if ( (0 == daemon->port) &&
+       (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
+    { /* Get port number. */
+      struct sockaddr *realaddr;
+#ifdef MHD_POSIX_SOCKETS
+      socklen_t alloc_len;
+#endif /* MHD_POSIX_SOCKETS */
+#ifdef HAVE_INET6
+      if (0 != (*pflags & MHD_USE_IPv6))
+        {
+          memset (&servaddr6,
+                  0,
+                  sizeof (struct sockaddr_in6));
+          servaddr6.sin6_family = AF_INET6;
+#ifdef HAVE_SOCKADDR_IN_SIN_LEN
+          servaddr6.sin6_len = sizeof (struct sockaddr_in6);
+#endif /* HAVE_SOCKADDR_IN_SIN_LEN */
+          addrlen = (socklen_t) sizeof (struct sockaddr_in6);
+          realaddr = (struct sockaddr *) &servaddr6;
+        }
+      else
+#else  /* ! HAVE_INET6 */
+      if (1)
+#endif /* ! HAVE_INET6 */
+        {
+          memset (&servaddr4,
+                  0,
+                  sizeof (struct sockaddr_in));
+          servaddr4.sin_family = AF_INET;
+#ifdef HAVE_SOCKADDR_IN_SIN_LEN
+          servaddr4.sin_len = sizeof (struct sockaddr_in);
+#endif /* HAVE_SOCKADDR_IN_SIN_LEN */
+          addrlen = (socklen_t) sizeof (struct sockaddr_in);
+          realaddr = (struct sockaddr *) &servaddr4;
+        }
+#ifdef MHD_POSIX_SOCKETS
+      alloc_len = addrlen;
+#endif /* MHD_POSIX_SOCKETS */
+      if (0 != getsockname (listen_fd, realaddr, &addrlen))
+        {
+#ifdef HAVE_MESSAGES
+      MHD_DLOG (daemon,
+                _("Failed to get listen port number: %s\n"),
+                MHD_socket_last_strerr_ ());
+#endif /* HAVE_MESSAGES */
+        }
+#ifdef MHD_POSIX_SOCKETS
+      else if (alloc_len < addrlen)
+        {
+#ifdef HAVE_MESSAGES
+      MHD_DLOG (daemon,
+                _("Failed to get listen port number due to small buffer\n"));
+#endif /* HAVE_MESSAGES */
+        }
+#endif /* MHD_POSIX_SOCKETS */
+      else
+        {
+#ifdef HAVE_INET6
+          if (0 != (*pflags & MHD_USE_IPv6))
+            {
+              mhd_assert (AF_INET6 == servaddr6.sin6_family);
+              daemon->port = ntohs(servaddr6.sin6_port);
+            }
+          else
+#else  /* ! HAVE_INET6 */
+          if (1)
+#endif /* ! HAVE_INET6 */
+            {
+              mhd_assert (AF_INET == servaddr4.sin_family);
+              daemon->port = ntohs(servaddr4.sin_port);
+            }
+        }
+    }
+
   if ( (MHD_INVALID_SOCKET != listen_fd) &&
        (! MHD_socket_nonblocking_ (listen_fd)) )
     {
@@ -6425,6 +6507,12 @@ MHD_is_feature_supported(enum MHD_FEATURE feature)
 #else
       return MHD_NO;
 #endif
+    case MHD_FEATURE_AUTODETECT_BIND_PORT:
+#ifdef MHD_USE_GETSOCKNAME
+      return MHD_YES;
+#else
+      return MHD_NO;
+#endif
     }
   return MHD_NO;
 }

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]