[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r34392 - in libmicrohttpd: . doc src/include src/microhttpd
From: |
gnunet |
Subject: |
[GNUnet-SVN] r34392 - in libmicrohttpd: . doc src/include src/microhttpd |
Date: |
Wed, 29 Oct 2014 20:50:58 +0100 |
Author: grothoff
Date: 2014-10-29 20:50:58 +0100 (Wed, 29 Oct 2014)
New Revision: 34392
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/doc/libmicrohttpd.texi
libmicrohttpd/src/include/microhttpd.h
libmicrohttpd/src/microhttpd/connection.c
libmicrohttpd/src/microhttpd/connection_https.c
libmicrohttpd/src/microhttpd/daemon.c
libmicrohttpd/src/microhttpd/internal.c
libmicrohttpd/src/microhttpd/internal.h
Log:
Hi Christian,
I attach the first attempt on SO_REUSEPORT. The patch is available
either at
https://github.com/foxik/libmicrohttpd/commit/9ce9422742e10458f87275ea202a982e00c2b88c
or attached. (It is against the version with
MHD_DAEMON_OPTION_CURRENT_CONNECTIONS, but I can rebase it to current
SVN HEAD if you want.)
It seems that a reasonably multiplatform way of detecting SO_REUSEPORT is
#ifdef SO_REPOSEPORT
which is used for example by Perl. For SO_EXCLUSIVEADDRUSE, the same
strategy seems to work too, according to Windows SDK headers and MinGW
WinAPI headers.
The current patch adds an option to allowing/disallowing address:port
reuse. One remark:
- currently both nonexisting SO_xxx and setsockopt failure are fatal and
MHD_start_daemon fails. That may be too harsh -- maybe the
MHD_OPTION_LISTENING_ADDRESS_REUSE should be only a hint.
Nevertheless, as one can freely not use
MHD_OPTION_LISTENING_ADDRESS_REUSE option, I chose the "fail on error"
behaviour.
Thanks,
cheers,
Milan Straka
Original patch modified to get rid of some redundant USE_DEBUG
checks, fix indentation, and #ifndef SO_REUSEPORT on Linux,
we try be #defining it to 15 ourselves.
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2014-10-29 15:53:17 UTC (rev 34391)
+++ libmicrohttpd/ChangeLog 2014-10-29 19:50:58 UTC (rev 34392)
@@ -1,3 +1,8 @@
+Wed Oct 29 20:45:21 CET 2014
+ Adding MHD_OPTION_LISTENING_ADDRESS_REUSE option allowing clients
+ to force allowing re-use of the address:port combination
+ (SO_REUSEPORT). -MS
+
Wed Oct 29 16:27:05 CET 2014
Adding MHD_DAEMON_INFO_CURRENT_CONNECTIONS to allow clients
to query the number of active connections. -MS
Modified: libmicrohttpd/doc/libmicrohttpd.texi
===================================================================
--- libmicrohttpd/doc/libmicrohttpd.texi 2014-10-29 15:53:17 UTC (rev
34391)
+++ libmicrohttpd/doc/libmicrohttpd.texi 2014-10-29 19:50:58 UTC (rev
34392)
@@ -856,6 +856,20 @@
a @code{const char *} argument. The argument would be a zero-terminated
string with a PEM encoded PKCS3 DH parameters structure suitable
for passing to @code{gnutls_dh_parms_import_pkcs3}.
+
address@hidden MHD_OPTION_LISTENING_ADDRESS_REUSE
address@hidden bind, restricting bind
address@hidden reusing listening address
+This option must be followed by a @code{unsigned int} argument.
+If this option is present and true (nonzero) parameter is given, allow reusing
+the address:port of the listening socket (using @code{SO_REUSEPORT} on most
+platforms, and @code{SO_REUSEADDR} on Windows). If a false (zero) parameter is
+given, disallow reusing the the address:port of the listening socket (this
+usually requires no special action, but @code{SO_EXCLUSIVEADDRUSE} is needed on
+Windows). If this option is not present, default behaviour is undefined
+(currently, @code{SO_REUSEADDR} is used on all platforms, which disallows
+address:port reusing with the exception of Windows).
+
@end table
@end deftp
Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h 2014-10-29 15:53:17 UTC (rev
34391)
+++ libmicrohttpd/src/include/microhttpd.h 2014-10-29 19:50:58 UTC (rev
34392)
@@ -846,8 +846,16 @@
* HTTPS daemon for key exchange.
* This option must be followed by a `const char *` argument.
*/
- MHD_OPTION_HTTPS_MEM_DHPARAMS = 24
+ MHD_OPTION_HTTPS_MEM_DHPARAMS = 24,
+ /**
+ * If present and set to true, allow reusing address:port socket
+ * (by using SO_REUSEPORT on most platform, or platform-specific ways).
+ * If present and set to false, disallow reusing address:port socket
+ * (does nothing on most plaform, but uses SO_EXCLUSIVEADDRUSE on Windows).
+ * This option must be followed by a `unsigned int` argument.
+ */
+ MHD_OPTION_LISTENING_ADDRESS_REUSE = 25,
};
Modified: libmicrohttpd/src/microhttpd/connection.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection.c 2014-10-29 15:53:17 UTC (rev
34391)
+++ libmicrohttpd/src/microhttpd/connection.c 2014-10-29 19:50:58 UTC (rev
34392)
@@ -1306,7 +1306,8 @@
if (NULL == cpy)
{
#if HAVE_MESSAGES
- MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
+ MHD_DLOG (connection->daemon,
+ "Not enough memory to parse cookies!\n");
#endif
transmit_error_response (connection, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
REQUEST_TOO_BIG);
Modified: libmicrohttpd/src/microhttpd/connection_https.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection_https.c 2014-10-29 15:53:17 UTC
(rev 34391)
+++ libmicrohttpd/src/microhttpd/connection_https.c 2014-10-29 19:50:58 UTC
(rev 34392)
@@ -134,8 +134,10 @@
unsigned int timeout;
#if DEBUG_STATES
- MHD_DLOG (connection->daemon, "%s: state: %s\n",
- __FUNCTION__, MHD_state_to_string (connection->state));
+ MHD_DLOG (connection->daemon,
+ "%s: state: %s\n",
+ __FUNCTION__,
+ MHD_state_to_string (connection->state));
#endif
timeout = connection->connection_timeout;
if ( (timeout != 0) && (timeout <= (MHD_monotonic_time() -
connection->last_activity)))
Modified: libmicrohttpd/src/microhttpd/daemon.c
===================================================================
--- libmicrohttpd/src/microhttpd/daemon.c 2014-10-29 15:53:17 UTC (rev
34391)
+++ libmicrohttpd/src/microhttpd/daemon.c 2014-10-29 19:50:58 UTC (rev
34392)
@@ -552,7 +552,8 @@
return 0;
#endif
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
+ MHD_DLOG (daemon,
+ "You need to specify a certificate and key location\n");
#endif
return -1;
}
@@ -736,7 +737,9 @@
#if DEBUG_CONNECT
#if HAVE_MESSAGES
if (NULL != max_fd)
- MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
+ MHD_DLOG (daemon,
+ "Maximum socket in select set: %d\n",
+ *max_fd);
#endif
#endif
return MHD_YES;
@@ -826,7 +829,7 @@
{
#if HAVE_MESSAGES
MHD_DLOG (con->daemon,
- "Can't add FD to fd_set\n");
+ "Can't add FD to fd_set\n");
#endif
goto exit;
}
@@ -1200,7 +1203,9 @@
#if HAVE_MESSAGES
#if DEBUG_CONNECT
- MHD_DLOG (daemon, "Accepted connection on socket %d\n", client_socket);
+ MHD_DLOG (daemon,
+ "Accepted connection on socket %d\n",
+ client_socket);
#endif
#endif
if ( (daemon->connections == daemon->connection_limit) ||
@@ -1226,7 +1231,8 @@
{
#if DEBUG_CLOSE
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Connection rejected, closing connection\n");
+ MHD_DLOG (daemon,
+ "Connection rejected, closing connection\n");
#endif
#endif
if (0 != MHD_socket_close_ (client_socket))
@@ -1415,7 +1421,8 @@
{
eno = errno;
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Failed to create a thread: %s\n",
+ MHD_DLOG (daemon,
+ "Failed to create a thread: %s\n",
MHD_strerror_ (res_thread_create));
#endif
goto cleanup;
@@ -1839,7 +1846,9 @@
#endif
#if HAVE_MESSAGES
#if DEBUG_CONNECT
- MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
+ MHD_DLOG (daemon,
+ "Accepted connection on socket %d\n",
+ s);
#endif
#endif
(void) internal_add_connection (daemon, s,
@@ -1961,7 +1970,8 @@
if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
{
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "Illegal call to MHD_get_timeout\n");
+ MHD_DLOG (daemon,
+ "Illegal call to MHD_get_timeout\n");
#endif
return MHD_NO;
}
@@ -2196,7 +2206,9 @@
if (EINTR == MHD_socket_errno_)
return MHD_YES;
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "select failed: %s\n", MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "select failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -2401,7 +2413,9 @@
if (EINTR == MHD_socket_errno_)
return MHD_YES;
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "poll failed: %s\n", MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "poll failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -2492,10 +2506,9 @@
&event))
{
#if HAVE_MESSAGES
- if (0 != (daemon->options & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to epoll_ctl failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Call to epoll_ctl failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -2544,10 +2557,9 @@
if (EINTR == MHD_socket_errno_)
return MHD_YES;
#if HAVE_MESSAGES
- if (0 != (daemon->options & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to epoll_wait failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Call to epoll_wait failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -2994,7 +3006,8 @@
if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
{
#if HAVE_MESSAGES
- MHD_DLOG(daemon, "Error initializing DH parameters\n");
+ MHD_DLOG(daemon,
+ "Error initializing DH parameters\n");
#endif
return MHD_NO;
}
@@ -3004,7 +3017,8 @@
GNUTLS_X509_FMT_PEM) < 0)
{
#if HAVE_MESSAGES
- MHD_DLOG(daemon, "Bad Diffie-Hellman parameters format\n");
+ MHD_DLOG(daemon,
+ "Bad Diffie-Hellman parameters format\n");
#endif
gnutls_dh_params_deinit (daemon->https_mem_dhparams);
return MHD_NO;
@@ -3028,7 +3042,7 @@
ret = gnutls_priority_init (&daemon->priority_cache,
pstr = va_arg (ap, const char*),
NULL);
- if (ret != GNUTLS_E_SUCCESS)
+ if (GNUTLS_E_SUCCESS != ret)
{
#if HAVE_MESSAGES
MHD_DLOG (daemon,
@@ -3084,6 +3098,9 @@
daemon->fastopen_queue_size = va_arg (ap, unsigned int);
break;
#endif
+ case MHD_OPTION_LISTENING_ADDRESS_REUSE:
+ daemon->listening_address_reuse = va_arg (ap, unsigned int) ? 1 : -1;
+ break;
case MHD_OPTION_ARRAY:
oa = va_arg (ap, struct MHD_OptionItem*);
i = 0;
@@ -3109,6 +3126,7 @@
case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
case MHD_OPTION_THREAD_POOL_SIZE:
case MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE:
+ case MHD_OPTION_LISTENING_ADDRESS_REUSE:
if (MHD_YES != parse_options (daemon,
servaddr,
opt,
@@ -3254,10 +3272,9 @@
if (-1 == daemon->epoll_fd)
{
#if HAVE_MESSAGES
- if (0 != (daemon->options & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to epoll_create1 failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Call to epoll_create1 failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -3274,10 +3291,9 @@
&event))
{
#if HAVE_MESSAGES
- if (0 != (daemon->options & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to epoll_ctl failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Call to epoll_ctl failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -3293,10 +3309,9 @@
&event))
{
#if HAVE_MESSAGES
- if (0 != (daemon->options & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to epoll_ctl failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Call to epoll_ctl failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
return MHD_NO;
}
@@ -3379,6 +3394,7 @@
}
#endif
daemon->socket_fd = MHD_INVALID_SOCKET;
+ daemon->listening_address_reuse = 0;
daemon->options = (enum MHD_OPTION) flags;
#if WINDOWS
/* Winsock is broken with respect to 'shutdown';
@@ -3553,25 +3569,111 @@
if (MHD_INVALID_SOCKET == socket_fd)
{
#if HAVE_MESSAGES
- if (0 != (flags & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to socket failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Call to socket failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
goto free_and_fail;
}
- if ( (0 > setsockopt (socket_fd,
- SOL_SOCKET,
- SO_REUSEADDR,
- (void*)&on, sizeof (on))) &&
- (0 != (flags & MHD_USE_DEBUG)) )
- {
+
+ /* Apply the socket options according to listening_address_reuse. */
+ if (0 == daemon->listening_address_reuse)
+ {
+ /* No user requirement, use "traditional" default SO_REUSEADDR,
+ and do not fail if it doesn't work */
+ if (0 > setsockopt (socket_fd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (void*)&on, sizeof (on)))
#if HAVE_MESSAGES
- MHD_DLOG (daemon,
- "setsockopt failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "setsockopt failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
- }
+ }
+ else if (daemon->listening_address_reuse > 0)
+ {
+ /* User requested to allow reusing listening address:port.
+ * Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms.
+ * Fail if SO_REUSEPORT does not exist or setsockopt fails.
+ */
+#ifdef _WIN32
+ /* SO_REUSEADDR on W32 has the same semantics
+ as SO_REUSEPORT on BSD/Linux */
+ if (0 > setsockopt (socket_fd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (void*)&on, sizeof (on)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "setsockopt failed: %s\n",
+ MHD_socket_last_strerr_ ());
+#endif
+ goto free_and_fail;
+ }
+#else
+#ifndef SO_REUSEPORT
+#ifdef LINUX
+/* Supported since Linux 3.9, but often not present (or commented out)
+ in the headers at this time; but 15 is reserved for this and
+ thus should be safe to use. */
+#define SO_REUSEPORT 15
+#endif
+#endif
+#ifdef SO_REUSEPORT
+ if (0 > setsockopt (socket_fd,
+ SOL_SOCKET,
+ SO_REUSEPORT,
+ (void*)&on, sizeof (on)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "setsockopt failed: %s\n",
+ MHD_socket_last_strerr_ ());
+#endif
+ goto free_and_fail;
+ }
+#else
+ /* we're supposed to allow address:port re-use, but
+ on this platform we cannot; fail hard */
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Cannot allow listening address reuse: SO_REUSEPORT not
defined\n");
+#endif
+ goto free_and_fail;
+#endif
+#endif
+ }
+ else /* if (daemon->listening_address_reuse < 0) */
+ {
+ /* User requested to disallow reusing listening address:port.
+ * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE
+ * is used. Fail if it does not exist or setsockopt fails.
+ */
+#ifdef _WIN32
+#ifdef SO_EXCLUSIVEADDRUSE
+ if (0 > setsockopt (socket_fd,
+ SOL_SOCKET,
+ SO_EXCLUSIVEADDRUSE,
+ (void*)&on, sizeof (on)))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "setsockopt failed: %s\n",
+ MHD_socket_last_strerr_ ());
+#endif
+ goto free_and_fail;
+ }
+#else /* SO_EXCLUSIVEADDRUSE not defined on W32? */
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Cannot disallow listening address reuse:
SO_EXCLUSIVEADDRUSE not defined\n");
+#endif
+ goto free_and_fail;
+#endif
+#endif /* _WIN32 */
+ }
/* check for user supplied sockaddr */
#if HAVE_INET6
@@ -3621,28 +3723,24 @@
const char
#endif
on = (MHD_USE_DUAL_STACK != (flags & MHD_USE_DUAL_STACK));
- if ( (0 > setsockopt (socket_fd,
- IPPROTO_IPV6, IPV6_V6ONLY,
- &on, sizeof (on))) &&
- (0 != (flags & MHD_USE_DEBUG)) )
- {
+ if (0 > setsockopt (socket_fd,
+ IPPROTO_IPV6, IPV6_V6ONLY,
+ &on, sizeof (on)))
#if HAVE_MESSAGES
- MHD_DLOG (daemon,
- "setsockopt failed: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "setsockopt failed: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
- }
#endif
#endif
}
if (-1 == bind (socket_fd, servaddr, addrlen))
{
#if HAVE_MESSAGES
- if (0 != (flags & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Failed to bind to port %u: %s\n",
- (unsigned int) port,
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Failed to bind to port %u: %s\n",
+ (unsigned int) port,
+ MHD_socket_last_strerr_ ());
#endif
if (0 != MHD_socket_close_ (socket_fd))
MHD_PANIC ("close failed\n");
@@ -3686,10 +3784,9 @@
if (listen (socket_fd, 32) < 0)
{
#if HAVE_MESSAGES
- if (0 != (flags & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Failed to listen for connections: %s\n",
- MHD_socket_last_strerr_ ());
+ MHD_DLOG (daemon,
+ "Failed to listen for connections: %s\n",
+ MHD_socket_last_strerr_ ());
#endif
if (0 != MHD_socket_close_ (socket_fd))
MHD_PANIC ("close failed\n");
@@ -3705,11 +3802,10 @@
(0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY)) ) )
{
#if HAVE_MESSAGES
- if ((flags & MHD_USE_DEBUG) != 0)
- MHD_DLOG (daemon,
- "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
- socket_fd,
- FD_SETSIZE);
+ MHD_DLOG (daemon,
+ "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
+ socket_fd,
+ FD_SETSIZE);
#endif
if (0 != MHD_socket_close_ (socket_fd))
MHD_PANIC ("close failed\n");
@@ -4123,7 +4219,8 @@
#if DEBUG_CLOSE
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "MHD listen socket shutdown\n");
+ MHD_DLOG (daemon,
+ "MHD listen socket shutdown\n");
#endif
#endif
Modified: libmicrohttpd/src/microhttpd/internal.c
===================================================================
--- libmicrohttpd/src/microhttpd/internal.c 2014-10-29 15:53:17 UTC (rev
34391)
+++ libmicrohttpd/src/microhttpd/internal.c 2014-10-29 19:50:58 UTC (rev
34392)
@@ -95,7 +95,7 @@
{
va_list va;
- if ((daemon->options & MHD_USE_DEBUG) == 0)
+ if (0 == (daemon->options & MHD_USE_DEBUG))
return;
va_start (va, format);
daemon->custom_error_log (daemon->custom_error_log_cls, format, va);
Modified: libmicrohttpd/src/microhttpd/internal.h
===================================================================
--- libmicrohttpd/src/microhttpd/internal.h 2014-10-29 15:53:17 UTC (rev
34391)
+++ libmicrohttpd/src/microhttpd/internal.h 2014-10-29 19:50:58 UTC (rev
34392)
@@ -1099,6 +1099,15 @@
*/
MHD_socket socket_fd;
+ /**
+ * Whether to allow/disallow/ignore reuse of listening address.
+ * The semantics is the following:
+ * 0: ignore (user did not ask for neither allow/disallow, use SO_REUSEADDR)
+ * >0: allow (use SO_REUSEPORT on most platforms, SO_REUSEADDR on Windows)
+ * <0: disallow (mostly no action, SO_EXCLUSIVEADDRUSE on Windows)
+ */
+ int listening_address_reuse;
+
#if EPOLL_SUPPORT
/**
* File descriptor associated with our epoll loop.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r34392 - in libmicrohttpd: . doc src/include src/microhttpd,
gnunet <=