"Junker, Gregory" <gregory.junker@intel.com>
Date:
12/04/2014 12:30 AM
To:
"libmicrohttpd@gnu.org" <libmicrohttpd@gnu.org>
Hi all
I need a tiny addition made to connection.c.
In keepalive_possible(), can we change the line that says
if (0 == strcasecmp (end, "close"))
to
if (0 == strcasecmp (end, "close") || 0 == strcasecmp (end, "upgrade"))
?
This would make it possible to use libmicrohttpd in a WebSocket (RFC6455) environment. Currently, the way that the WebSocket protocol works, it sends "Connection: Upgrade" in the headers with the initial handshake, which causes this check to fail and (ultimately) insert "Connection: Keep-Alive" in the response headers (which cause any compliant WebSocket client to fail the handshake, since it needs "Connection: Upgrade" in the response headers, and there is no way to remove this keepalive header from the response from outside of MHD, as it is added automatically to the response buffer).
Note that this is only an HTTP/1.1 issue, AFAIK (I am pretty sure, though not positive, that WebSocket is not compatible with HTTP/1.0).
Thanks!
Greg
the recently added MHD_DAEMON_INFO_CURRENT_CONNECTIONS can return quite
outdated values in MHD_USE_THREAD_PER_CONNECTION mode. The reason is
that closed connections are collected in MHD_cleanup_connections, which
is called only from the select thread. In the
MHD_USE_THREAD_PER_CONNECTION mode that happens only after accepting an
connection -- therefore, the last connection is always not collected and
MHD_DAEMON_INFO_CURRENT_CONNECTIONS returns >= 1, even when there are no
connections. That makes it very unusable to detect whether all
connections have been handled.
Would you consider the attached patch, which calls
MHD_cleanup_connections whenever MHD_DAEMON_INFO_CURRENT_CONNECTIONS is
called? It makes MHD_DAEMON_INFO_CURRENT_CONNECTIONS slower, but the
returned value is much more accurate.
Cheers,
Milan Straka
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.
Date: Wed, 29 Oct 2014 09:59:09 +0100
Subject: [PATCH 2/2] Add MHD_DAEMON_INFO_CURRENT_CONNECTIONS to
MHD_DaemonInfoType.
The MHD_DAEMON_INFO_CURRENT_CONNECTIONS returns number of current
connections handled by the daemon.
Useful after MHD_quiesce_daemon to find out whether all connections
have been served.
MHD_USE_DUAL_STACK in libmicrohttpd currently just *inhibits setting* the
IPV6_V6ONLY socket option, but per Microsoft's documentation
http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx
the default on Windows is that this is enabled, thus MHD_USE_DUAL_STACK will
not work (since it leaves the default). libmicrohttpd should probably just
unconditionally set IPV6_V6ONLY to the desired value when the option is
available.
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0a33b77..3cbf28e 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -3493,8 +3493,7 @@ MHD_start_daemon_va (unsigned int flags,
}
daemon->socket_fd = socket_fd;
- if ( (0 != (flags & MHD_USE_IPv6)) &&
- (MHD_USE_DUAL_STACK != (flags & MHD_USE_DUAL_STACK)) )
+ if (0 != (flags & MHD_USE_IPv6))
{
#ifdef IPPROTO_IPV6
#ifdef IPV6_V6ONLY
@@ -3503,10 +3502,11 @@ MHD_start_daemon_va (unsigned int flags,
and may also be missing on older POSIX systems; good luck if you have
any of those,
your IPv6 socket may then also bind against IPv4 anyway... */
#ifndef WINDOWS
- const int on = 1;
+ const int
#else
- const char on = 1;
+ 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))) &&