commit b90f356c47e467407ae407723ddb02161b849f6a
parent 21b2dd96aaffa8e2d0937a339bbdace882db0fee
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 6 Feb 2018 17:50:46 +0100
starting with mhd2 api implementation
Diffstat:
8 files changed, 1416 insertions(+), 17 deletions(-)
diff --git a/configure.ac b/configure.ac
@@ -2003,6 +2003,13 @@ AC_SUBST(LDFLAGS)
AC_SUBST([ac_configure_args])
AC_SUBST([EMPTY_VAR], [[]])
+# We define the paths here, because MinGW/GCC expands paths
+# passed through the command line ("-DDIR=..."). This would
+# lead to hard-coded paths ("C:\mingw\mingw\bin...") that do
+# not contain the actual installation.
+AC_DEFINE_DIR([MHD_PLUGIN_INSTALL_PREFIX], [libdir/libmicrohttpd], [tls plugins])
+
+
AC_CONFIG_FILES([libmicrohttpd.pc
w32/common/microhttpd_dll_res_vc.rc
po/configure.acT:po/configure.ac.in
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
@@ -145,6 +145,17 @@ enum MHD_StatusCode
* supported by the selected backend.
*/
MHD_TLS_CIPHERS_INVALID = 50002
+
+ /**
+ * The application attempted to setup TLS paramters before
+ * enabling TLS.
+ */
+ MHD_TLS_BACKEND_UNINITIALIZED = 50003,
+
+ /**
+ * The selected TLS backend does not yet support this operation.
+ */
+ MHD_TLS_BACKEND_OPERATION_UNSUPPORTED = 50004,
};
@@ -403,8 +414,9 @@ typedef struct MHD_Action *
*
* @param cb function to be called for incoming requests
* @param cb_cls closure for @a cb
+ * @return NULL on error
*/
-struct MHD_Daemon *
+_MHD_EXTERN struct MHD_Daemon *
MHD_daemon_create (MHD_RequestCallback cb,
void *cb_cls);
@@ -621,7 +633,7 @@ enum MHD_AddressFamily
/**
* Pick "best" available method automatically.
*/
- MHD_AF_AUTO,
+ MHD_AF_AUTO = 0,
/**
* Use IPv4.
@@ -672,7 +684,7 @@ MHD_daemon_bind_port (struct MHD_Daemon *daemon,
_MHD_EXTERN void
MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
const struct sockaddr *sa,
- size_t sa_lem);
+ size_t sa_len);
/**
@@ -683,8 +695,8 @@ MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
* @param listen_backlog backlog to use
*/
_MHD_EXTERN void
-MHD_daemon_listen_queue (struct MHD_Daemon *daemon,
- int listen_backlog);
+MHD_daemon_listen_backlog (struct MHD_Daemon *daemon,
+ int listen_backlog);
/**
@@ -810,7 +822,7 @@ MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon,
* @param daemon which instance should be configured
* @param tls_backend which TLS backend should be used,
* currently only "gnutls" is supported. You can
- * also specify "NULL" for best-available (which is the default).
+ * also specify NULL for best-available (which is the default).
* @param ciphers which ciphers should be used by TLS, default is
* "NORMAL"
* @return status code, #MHD_SC_OK upon success
@@ -1054,8 +1066,6 @@ typedef void
* @param daemon daemon to set callback for
* @param ncc function to call to check the policy
* @param ncc_cls closure for @a apc
- * @param ccc function to call upon completion, NULL for none
- * @param ccc_cls closure for @a ccc
*/
_MHD_EXTERN void
MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
@@ -1064,7 +1074,7 @@ MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
/**
- * Maximum memory size per connection (followed by a `size_t`).
+ * Maximum memory size per connection.
* Default is 32 kb (#MHD_POOL_SIZE_DEFAULT).
* Values above 128k are unlikely to result in much benefit, as half
* of the memory will be typically used for IO, and TCP buffers are
@@ -1178,15 +1188,15 @@ MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon,
/**
- * Size of the internal array holding the map of the nonce and
+ * Length of the internal array holding the map of the nonce and
* the nonce counter.
*
* @param daemon daemon to configure
* @param nc_length desired array length
*/
_MHD_EXTERN void
-MHD_daemon_digest_auth_nc_size (struct MHD_Daemon *daemon,
- size_t stack_limit_b);
+MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon,
+ size_t nc_length);
/* ********************* connection options ************** */
@@ -1201,7 +1211,7 @@ MHD_daemon_digest_auth_nc_size (struct MHD_Daemon *daemon,
* @param connection connection to configure timeout for
* @param timeout_s new timeout in seconds
*/
-struct MHD_ConnectionOption
+_MHD_EXTERN struct MHD_ConnectionOption
MHD_connection_timeout (struct MHD_Connection *connection,
unsigned int timeout_s);
@@ -1443,7 +1453,7 @@ MHD_request_resume (struct MHD_Request *request);
* as a response *is* an action. As no memory is
* allocated, this operation cannot fail.
*/
-struct MHD_Action *
+_MHD_EXTERN struct MHD_Action *
MHD_action_from_response (struct MHD_Response *response,
enum MHD_bool destroy_after_use);
@@ -1484,7 +1494,7 @@ typedef void
* @param termination_cb function to call
* @param termination_cb_cls closure for @e termination_cb
*/
-void
+_MHD_EXTERN void
MHD_response_option_termination_callback (struct MHD_Response *response,
MHD_RequestTerminationCallback termination_cb,
void *termination_cb_cls);
diff --git a/src/lib/connection_options.c b/src/lib/connection_options.c
@@ -0,0 +1,16 @@
+
+/**
+ * Generate option to set a custom timeout for the given connection.
+ * Specified as the number of seconds. Use zero for no timeout. If
+ * timeout was set to zero (or unset) before, setting of a new value
+ * by MHD_connection_set_option() will reset timeout timer.
+ *
+ * @param connection connection to configure timeout for
+ * @param timeout_s new timeout in seconds
+ */
+struct MHD_ConnectionOption
+MHD_connection_timeout (struct MHD_Connection *connection,
+ unsigned int timeout_s);
+
+
+
diff --git a/src/lib/daemon.c b/src/lib/daemon.c
@@ -0,0 +1,172 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file lib/daemon.c
+ * @brief main functions to create, start, quiesce and destroy a daemon
+ * @author Christian Grothoff
+ */
+#include "internal.h"
+
+
+/**
+ * Logging implementation that logs to a file given
+ * as the @a cls.
+ *
+ * @param cls a `FILE *` to log to
+ * @param sc status code of the event (ignored)
+ * @param fm format string (`printf()`-style)
+ * @param ap arguments to @a fm
+ * @ingroup logging
+ */
+static void
+file_logger (void *cls,
+ enum MHD_StatusCode sc,
+ const char *fm,
+ va_list ap)
+{
+ FILE *f = cls;
+
+ (void) sc;
+ (void) vfprintf (f,
+ fm,
+ ap);
+}
+
+
+/**
+ * Process escape sequences ('%HH') Updates val in place; the
+ * result should be UTF-8 encoded and cannot be larger than the input.
+ * The result must also still be 0-terminated.
+ *
+ * @param cls closure (use NULL)
+ * @param req handle to request, not used
+ * @param val value to unescape (modified in the process)
+ * @return length of the resulting val (strlen(val) maybe
+ * shorter afterwards due to elimination of escape sequences)
+ */
+static size_t
+unescape_wrapper (void *cls,
+ struct MHD_Request *req,
+ char *val)
+{
+ (void) cls; /* Mute compiler warning. */
+ (void) req; /* Mute compiler warning. */
+ return MHD_http_unescape (val);
+}
+
+
+/**
+ * Create (but do not yet start) an MHD daemon.
+ * Usually, you will want to set various options before
+ * starting the daemon with #MHD_daemon_start().
+ *
+ * @param cb function to be called for incoming requests
+ * @param cb_cls closure for @a cb
+ * @return NULL on error
+ */
+struct MHD_Daemon *
+MHD_daemon_create (MHD_RequestCallback cb,
+ void *cb_cls)
+{
+ struct MHD_Daemon *daemon;
+
+ MHD_check_global_init_();
+ if (NULL == cb)
+ return NULL;
+ if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon))))
+ return NULL;
+ memset (daemon,
+ 0,
+ sizeof (struct MHD_Daemon));
+ daemon->rc = cb;
+ daemon->rc_cls = cb_cls;
+ daemon->logger = &file_logger;
+ daemon->logger_cls = stderr;
+ daemon->unescape_cb = &unescape_wrapper;
+ daemon->tls_ciphers = TLS_CIPHERS_DEFAULT;
+ daemon->connection_memory_limit_b = MHD_POOL_SIZE_DEFAULT;
+ daemon->connection_memory_increment_b = BUF_INC_SIZE_DEFAULT;
+#if ENABLE_DAUTH
+ daemon->digest_nc_length = DIGEST_NC_LENGTH_DEFAULT;
+#endif
+ daemon->listen_backlog = LISTEN_BACKLOG_DEFAULT;
+ daemon->fo_queue_length = FO_QUEUE_LENGTH_DEFAULT;
+ daemon->listen_socket = MHD_INVALID_SOCKET;
+ return daemon;
+}
+
+
+/**
+ * Start a webserver.
+ *
+ * @param daemon daemon to start; you can no longer set
+ * options on this daemon after this call!
+ * @return #MHD_SC_OK on success
+ * @ingroup event
+ */
+enum MHD_StatusCode
+MHD_daemon_start (struct MHD_Daemon *daemon)
+{
+
+ return -1;
+}
+
+
+/**
+ * Stop accepting connections from the listening socket. Allows
+ * clients to continue processing, but stops accepting new
+ * connections. Note that the caller is responsible for closing the
+ * returned socket; however, if MHD is run using threads (anything but
+ * external select mode), it must not be closed until AFTER
+ * #MHD_stop_daemon has been called (as it is theoretically possible
+ * that an existing thread is still using it).
+ *
+ * Note that some thread modes require the caller to have passed
+ * #MHD_USE_ITC when using this API. If this daemon is
+ * in one of those modes and this option was not given to
+ * #MHD_start_daemon, this function will return #MHD_INVALID_SOCKET.
+ *
+ * @param daemon daemon to stop accepting new connections for
+ * @return old listen socket on success, #MHD_INVALID_SOCKET if
+ * the daemon was already not listening anymore, or
+ * was never started
+ * @ingroup specialized
+ */
+MHD_socket
+MHD_daemon_quiesce (struct MHD_Daemon *daemon)
+{
+ return -1;
+}
+
+
+/**
+ * Shutdown and destroy an HTTP daemon.
+ *
+ * @param daemon daemon to stop
+ * @ingroup event
+ */
+void
+MHD_daemon_destroy (struct MHD_Daemon *daemon)
+{
+ free (daemon);
+}
+
+
+/* end of daemon.c */
diff --git a/src/lib/daemon_options.c b/src/lib/daemon_options.c
@@ -0,0 +1,713 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file lib/daemon_options.c
+ * @brief boring functions to manipulate daemon options
+ * @author Christian Grothoff
+ */
+#include "internal.h"
+
+
+/**
+ * Set logging method. Specify NULL to disable logging entirely. By
+ * default (if this option is not given), we log error messages to
+ * stderr.
+ *
+ * @param daemon which instance to setup logging for
+ * @param logger function to invoke
+ * @param logger_cls closure for @a logger
+ */
+void
+MHD_daemon_set_logger (struct MHD_Daemon *daemon,
+ MHD_LoggingCallback logger,
+ void *logger_cls)
+{
+ daemon->logger = logger;
+ daemon->logger_cls = logger_cls;
+}
+
+
+/**
+ * Suppress use of "Date" header as this system has no RTC.
+ *
+ * @param daemon which instance to disable clock for.
+ */
+void
+MHD_daemon_suppress_date_no_clock (struct MHD_Daemon *daemon)
+{
+ daemon->suppress_date = true;
+}
+
+
+/**
+ * Disable use of inter-thread communication channel.
+ * #MHD_daemon_disable_itc() can be used with
+ * #MHD_daemon_thread_internal() to perform some additional
+ * optimizations (in particular, not creating a pipe for IPC
+ * signalling). If it is used, certain functions like
+ * #MHD_daemon_quiesce() or #MHD_connection_add() or
+ * #MHD_action_suspend() cannot be used anymore.
+ * #MHD_daemon_disable_itc() is not beneficial on platforms where
+ * select()/poll()/other signal shutdown() of a listen socket.
+ *
+ * You should only use this function if you are sure you do
+ * satisfy all of its requirements and need a generally minor
+ * boost in performance.
+ *
+ * @param daemon which instance to disable itc for
+ */
+void
+MHD_daemon_disable_itc (struct MHD_Daemon *daemon)
+{
+ daemon->disable_itc = true;
+}
+
+
+/**
+ * Enable `turbo`. Disables certain calls to `shutdown()`,
+ * enables aggressive non-blocking optimistic reads and
+ * other potentially unsafe optimizations.
+ * Most effects only happen with #MHD_ELS_EPOLL.
+ *
+ * @param daemon which instance to enable turbo for
+ */
+void
+MHD_daemon_enable_turbo (struct MHD_Daemon *daemon)
+{
+ daemon->enable_turbo = true;
+}
+
+
+/**
+ * Disable #MHD_action_suspend() functionality.
+ *
+ * You should only use this function if you are sure you do
+ * satisfy all of its requirements and need a generally minor
+ * boost in performance.
+ *
+ * @param daemon which instance to disable suspend for
+ */
+void
+MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon)
+{
+ daemon->disallow_suspend_resume = true;
+}
+
+
+/**
+ * You need to set this option if you want to disable use of HTTP "Upgrade".
+ * "Upgrade" may require usage of additional internal resources,
+ * which we can avoid providing if they will not be used.
+ *
+ * You should only use this function if you are sure you do
+ * satisfy all of its requirements and need a generally minor
+ * boost in performance.
+ *
+ * @param daemon which instance to enable suspend/resume for
+ */
+void
+MHD_daemon_disallow_upgrade (struct MHD_Daemon *daemon)
+{
+ daemon->disallow_upgrade;
+}
+
+
+/**
+ * Configure TCP_FASTOPEN option, including setting a
+ * custom @a queue_length.
+ *
+ * Note that having a larger queue size can cause resource exhaustion
+ * attack as the TCP stack has to now allocate resources for the SYN
+ * packet along with its DATA.
+ *
+ * @param daemon which instance to configure TCP_FASTOPEN for
+ * @param fom under which conditions should we use TCP_FASTOPEN?
+ * @param queue_length queue length to use, default is 50 if this
+ * option is never given.
+ * @return #MHD_YES upon success, #MHD_NO if #MHD_FOM_REQUIRE was
+ * given, but TCP_FASTOPEN is not available on the platform
+ */
+enum MHD_Bool
+MHD_daemon_tcp_fastopen (struct MHD_Daemon *daemon,
+ enum MHD_FastOpenMethod fom,
+ unsigned int queue_length)
+{
+ daemon->fast_open_method = fom;
+ daemon->fast_open_queue_length = queue_length;
+ switch (fom)
+ {
+ case MHD_FOM_DISABLE:
+ return MHD_YES;
+ case MHD_FOM_AUTO:
+ return MHD_YES;
+ case MHD_FOM_REQUIRE:
+#ifdef TCP_FASTOPEN
+ return MHD_YES;
+#else
+ return MHD_NO;
+#endif
+ }
+}
+
+
+/**
+ * Bind to the given TCP port and address family.
+ *
+ * Ineffective in conjunction with #MHD_daemon_listen_socket().
+ * Ineffective in conjunction with #MHD_daemon_bind_sa().
+ *
+ * If neither this option nor the other two mentioned above
+ * is specified, MHD will simply not listen on any socket!
+ *
+ * @param daemon which instance to configure the TCP port for
+ * @param af address family to use
+ * @param port port to use, 0 to bind to a random (free) port
+ */
+void
+MHD_daemon_bind_port (struct MHD_Daemon *daemon,
+ enum MHD_AddressFamily af,
+ uint16_t port)
+{
+ daemon->listen_af = af;
+ daemon->listen_port = port;
+}
+
+
+/**
+ * Bind to the given socket address.
+ * Ineffective in conjunction with #MHD_daemon_listen_socket().
+ *
+ * @param daemon which instance to configure the binding address for
+ * @param sa address to bind to; can be IPv4 (AF_INET), IPv6 (AF_INET6)
+ * or even a UNIX domain socket (AF_UNIX)
+ * @param sa_len number of bytes in @a sa
+ */
+void
+MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon,
+ const struct sockaddr *sa,
+ size_t sa_len)
+{
+ daemon->sa_given = true;
+ memcpy (&daemon->listen_sa,
+ sa,
+ sa_len);
+ daemon->listen_sa_len = sa_len;
+}
+
+
+/**
+ * Use the given backlog for the listen() call.
+ * Ineffective in conjunction with #MHD_daemon_listen_socket().
+ *
+ * @param daemon which instance to configure the backlog for
+ * @param listen_backlog backlog to use
+ */
+void
+MHD_daemon_listen_backlog (struct MHD_Daemon *daemon,
+ int listen_backlog)
+{
+ daemon->listen_backlog = listen_backlog;
+}
+
+
+/**
+ * If present 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).
+ * Ineffective in conjunction with #MHD_daemon_listen_socket().
+ *
+ * @param daemon daemon to configure address reuse for
+ */
+void
+MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon)
+{
+ daemon->allow_address_reuse = true;
+}
+
+
+/**
+ * Accept connections from the given socket. Socket
+ * must be a TCP or UNIX domain (stream) socket.
+ *
+ * Unless -1 is given, this disables other listen options, including
+ * #MHD_daemon_bind_sa(), #MHD_daemon_bind_port(),
+ * #MHD_daemon_listen_queue() and
+ * #MHD_daemon_listen_allow_address_reuse().
+ *
+ * @param daemon daemon to set listen socket for
+ * @param listen_socket listen socket to use,
+ * MHD_INVALID_SOCKET value will cause this call to be
+ * ignored (other binding options may still be effective)
+ */
+void
+MHD_daemon_listen_socket (struct MHD_Daemon *daemon,
+ MHD_socket listen_socket)
+{
+ daemon->listen_socket = listen_socket;
+}
+
+
+/**
+ * Force use of a particular event loop system call.
+ *
+ * @param daemon daemon to set event loop style for
+ * @param els event loop syscall to use
+ * @return #MHD_NO on failure, #MHD_YES on success
+ */
+enum MHD_Bool
+MHD_daemon_event_loop (struct MHD_Daemon *daemon,
+ enum MHD_EventLoopSyscall els)
+{
+ switch (els)
+ {
+ case MHD_ELS_AUTO:
+ break; /* should always be OK */
+ case MHD_ELS_SELECT:
+ break; /* should always be OK */
+ case MHD_ELS_POLL:
+#ifdef HAVE_POLL
+ break;
+#else
+ return MHD_NO; /* not supported */
+#endif
+ case MHD_ELS_EPOLL:
+#ifdef EPOLL_SUPPORT
+ break;
+#else
+ return MHD_NO; /* not supported */
+#endif
+ default:
+ return MHD_NO; /* not supported (presumably future ABI extension) */
+ }
+ daemon->event_loop_syscall = els;
+ return MHD_YES;
+}
+
+
+/**
+ * Set how strictly MHD will enforce the HTTP protocol.
+ *
+ * @param daemon daemon to configure strictness for
+ * @param sl how strict should we be
+ */
+void
+MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon,
+ enum MHD_ProtocolStrictLevel sl)
+{
+ daemon->protocol_strict_level = sl;
+}
+
+
+/**
+ * Enable and configure TLS.
+ *
+ * @param daemon which instance should be configured
+ * @param tls_backend which TLS backend should be used,
+ * currently only "gnutls" is supported. You can
+ * also specify NULL for best-available (which is the default).
+ * @param ciphers which ciphers should be used by TLS, default is
+ * "NORMAL"
+ * @return status code, #MHD_SC_OK upon success
+ * #MHD_TLS_BACKEND_UNSUPPORTED if the @a backend is unknown
+ * #MHD_TLS_DISABLED if this build of MHD does not support TLS
+ * #MHD_TLS_CIPHERS_INVALID if the given @a ciphers are not supported
+ * by this backend
+ */
+enum MHD_StatusCode
+MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon,
+ const char *tls_backend,
+ const char *ciphers)
+{
+#ifndef HTTPS_SUPPORT
+ return MHD_TLS_DISABLED;
+#else
+ char filename[1024];
+ int res;
+ MHD_TLS_PluginInit init;
+
+ /* todo: .dll on W32? */
+ res = MHD_snprintf (filename,
+ sizeof (filename),
+ "%s/libmicrohttpd_tls_%s.so",
+ MHD_PLUGIN_INSTALL_PREFIX,
+ tls_backend);
+ if (0 >= res)
+ return MHD_BACKEND_UNSUPPORTED; /* string too long? */
+ if (NULL ==
+ (daemon->tls_backend_lib = dlopen (filename,
+ RTLD_NOW | RTLD_LOCAL)))
+ return MHD_BACKEND_UNSUPPORTED; /* plugin not found */
+ if (NULL == (init = dlsym (daemon->tls_backend_lib,
+ "MHD_TLS_init_" MHD_TLS_ABI_VERSION_STR)))
+
+ {
+ dlclose (daemon->tls_backend_lib);
+ daemon->tls_backend_lib = NULL;
+ return MHD_BACKEND_UNSUPPORTED; /* possibly wrong version installed */
+ }
+ if (NULL == (daemon->tls_backend = init (ciphers)))
+ {
+ dlclose (daemon->tls_backend_lib);
+ daemon->tls_backend_lib = NULL;
+ return MHD_CIPHERS_INVALID; /* possibly wrong version installed */
+ }
+ return MHD_SC_OK;
+#endif
+}
+
+
+/**
+ * Provide TLS key and certificate data in-memory.
+ *
+ * @param daemon which instance should be configured
+ * @param mem_key private key (key.pem) to be used by the
+ * HTTPS daemon. Must be the actual data in-memory, not a filename.
+ * @param mem_cert certificate (cert.pem) to be used by the
+ * HTTPS daemon. Must be the actual data in-memory, not a filename.
+ * @param pass passphrase phrase to decrypt 'key.pem', NULL
+ * if @param mem_key is in cleartext already
+ * @return #MHD_SC_OK upon success; MHD_BACKEND_UNINITIALIZED
+ * if the TLS backend is not yet setup.
+ */
+enum MHD_StatusCode
+MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon,
+ const char *mem_key,
+ const char *mem_cert,
+ const char *pass)
+{
+ struct MHD_TLS_Plugin *plugin;
+
+ if (NULL == (plugin = daemon->tls_backend))
+ return MHD_TLS_BACKEND_UNINITIALIZED;
+ return plugin->init_kcp (plugin->cls,
+ mem_key,
+ mem_cert,
+ pass);
+}
+
+
+/**
+ * Configure DH parameters (dh.pem) to use for the TLS key
+ * exchange.
+ *
+ * @param daemon daemon to configure tls for
+ * @param dh parameters to use
+ * @return #MHD_SC_OK upon success; MHD_BACKEND_UNINITIALIZED
+ * if the TLS backend is not yet setup.
+ */
+enum MHD_StatusCode
+MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon,
+ const char *dh)
+{
+ struct MHD_TLS_Plugin *plugin;
+
+ if (NULL == (plugin = daemon->tls_backend))
+ return MHD_TLS_BACKEND_UNINITIALIZED;
+ return plugin->init_dhparams (plugin->cls,
+ dh);
+}
+
+
+/**
+ * Memory pointer for the certificate (ca.pem) to be used by the
+ * HTTPS daemon for client authentification.
+ *
+ * @param daemon daemon to configure tls for
+ * @param mem_trust memory pointer to the certificate
+ * @return #MHD_SC_OK upon success; MHD_BACKEND_UNINITIALIZED
+ * if the TLS backend is not yet setup.
+ */
+enum MHD_StatusCode
+MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon,
+ const char *mem_trust)
+{
+ struct MHD_TLS_Plugin *plugin;
+
+ if (NULL == (plugin = daemon->tls_backend))
+ return MHD_TLS_BACKEND_UNINITIALIZED;
+ return plugin->init_mem_trust (plugin->cls,
+ mem_trust);
+}
+
+
+/**
+ * Configure daemon credentials type for GnuTLS.
+ *
+ * @param gnutls_credentials must be a value of
+ * type `gnutls_credentials_type_t`
+ * @return #MHD_SC_OK upon success; TODO: define failure modes
+ */
+enum MHD_StatusCode
+MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon,
+ int gnutls_credentials)
+{
+ struct MHD_TLS_Plugin *plugin;
+
+ if (NULL == (plugin = daemon->tls_backend))
+ return MHD_TLS_BACKEND_UNINITIALIZED;
+ return MHD_TLS_BACKEND_OPERATION_UNSUPPORTED;
+}
+
+
+/**
+ * Provide TLS key and certificate data via callback.
+ *
+ * Use a callback to determine which X.509 certificate should be used
+ * for a given HTTPS connection. This option provides an alternative
+ * to #MHD_daemon_tls_key_and_cert_from_memory(). You must use this
+ * version if multiple domains are to be hosted at the same IP address
+ * using TLS's Server Name Indication (SNI) extension. In this case,
+ * the callback is expected to select the correct certificate based on
+ * the SNI information provided. The callback is expected to access
+ * the SNI data using `gnutls_server_name_get()`. Using this option
+ * requires GnuTLS 3.0 or higher.
+ *
+ * @param daemon daemon to configure callback for
+ * @param cb must be of type `gnutls_certificate_retrieve_function2 *`.
+ */
+void
+MHD_daemon_gnutls_key_and_cert_from_callback (struct MHD_Daemon *daemon,
+ void *cb)
+{
+ struct MHD_TLS_Plugin *plugin;
+
+ if (NULL == (plugin = daemon->tls_backend))
+ return MHD_TLS_BACKEND_UNINITIALIZED;
+ return MHD_TLS_BACKEND_OPERATION_UNSUPPORTED;
+}
+
+
+/**
+ * Specify threading model to use.
+ *
+ * @param daemon daemon to configure
+ * @param tm model to use (positive values indicate the
+ * number of worker threads to be used)
+ */
+void
+MHD_daemon_threading_model (struct MHD_Daemon *daemon,
+ enum MHD_ThreadingModel tm)
+{
+ daemon->threading_model = tm;
+}
+
+
+/**
+ * Set a policy callback that accepts/rejects connections
+ * based on the client's IP address. This function will be called
+ * before a connection object is created.
+ *
+ * @param daemon daemon to set policy for
+ * @param apc function to call to check the policy
+ * @param apc_cls closure for @a apc
+ */
+void
+MHD_daemon_accept_policy (struct MHD_Daemon *daemon,
+ MHD_AcceptPolicyCallback apc,
+ void *apc_cls)
+{
+ daemon->accept_policy_cb = apc;
+ daemon->accept_policy_cb_cls = apc_cls;
+}
+
+
+/**
+ * Register a callback to be called first for every request
+ * (before any parsing of the header). Makes it easy to
+ * log the full URL.
+ *
+ * @param daemon daemon for which to set the logger
+ * @param cb function to call
+ * @param cb_cls closure for @a cb
+ */
+void
+MHD_daemon_set_early_uri_logger (struct MHD_Daemon *daemon,
+ MHD_EarlyUriLogCallback cb,
+ void *cb_cls)
+{
+ daemon->early_uri_logger_cb = cb;
+ daemon->early_uri_logger_cb_cls = cb_cls;
+}
+
+
+/**
+ * Register a function that should be called whenever a connection is
+ * started or closed.
+ *
+ * @param daemon daemon to set callback for
+ * @param ncc function to call to check the policy
+ * @param ncc_cls closure for @a apc
+ */
+void
+MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon,
+ MHD_NotifyConnectionCallback ncc,
+ void *ncc_cls)
+{
+ daemon->notify_connection_cb = ncc;
+ daemon->notify_connection_cb_cls = ncc_cls;
+}
+
+
+/**
+ * Maximum memory size per connection.
+ * Default is 32 kb (#MHD_POOL_SIZE_DEFAULT).
+ * Values above 128k are unlikely to result in much benefit, as half
+ * of the memory will be typically used for IO, and TCP buffers are
+ * unlikely to support window sizes above 64k on most systems.
+ *
+ * @param daemon daemon to configure
+ * @param memory_limit_b connection memory limit to use in bytes
+ * @param memory_increment_b increment to use when growing the read buffer, must be smaller than @a memory_limit_b
+ */
+void
+MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon,
+ size_t memory_limit_b,
+ size_t memory_increment_b)
+{
+ if (memory_increment_b >= memory_limit_b)
+ MHD_PANIC ("sane memory increment must be below memory limit");
+ daemon->connection_memory_limit_b = memory_limit_b;
+ daemon->connection_memory_increment_b = memory_increment_b;
+}
+
+
+/**
+ * Desired size of the stack for threads created by MHD. Use 0 for
+ * system default. Only useful if the selected threading model
+ * is not #MHD_TM_EXTERNAL_EVENT_LOOP.
+ *
+ * @param daemon daemon to configure
+ * @param stack_limit_b stack size to use in bytes
+ */
+void
+MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon,
+ size_t stack_limit_b)
+{
+ daemon->thread_stack_limit_b = stack_limit_b;
+}
+
+
+/**
+ * Set maximum number of concurrent connections to accept. If not
+ * given, MHD will not enforce any limits (modulo running into
+ * OS limits). Values of 0 mean no limit.
+ *
+ * @param daemon daemon to configure
+ * @param global_connection_limit maximum number of (concurrent)
+ connections
+ * @param ip_connection_limit limit on the number of (concurrent)
+ * connections made to the server from the same IP address.
+ * Can be used to prevent one IP from taking over all of
+ * the allowed connections. If the same IP tries to
+ * establish more than the specified number of
+ * connections, they will be immediately rejected.
+ */
+void
+MHD_daemon_connection_limits (struct MHD_Daemon *daemon,
+ unsigned int global_connection_limit,
+ unsigned int ip_connection_limit)
+{
+ daemon->global_connection_limit = global_connection_limit;
+ daemon->ip_connection_limit = ip_connection_limit;
+}
+
+
+/**
+ * After how many seconds of inactivity should a
+ * connection automatically be timed out?
+ * Use zero for no timeout, which is also the (unsafe!) default.
+ *
+ * @param daemon daemon to configure
+ * @param timeout_s number of seconds of timeout to use
+ */
+void
+MHD_daemon_connection_default_timeout (struct MHD_Daemon *daemon,
+ unsigned int timeout_s)
+{
+ daemon->connection_default_timeout_s = timeout_s;
+}
+
+
+/**
+ * Specify a function that should be called for unescaping escape
+ * sequences in URIs and URI arguments. Note that this function
+ * will NOT be used by the `struct MHD_PostProcessor`. If this
+ * option is not specified, the default method will be used which
+ * decodes escape sequences of the form "%HH".
+ *
+ * @param daemon daemon to configure
+ * @param unescape_cb function to use, NULL for default
+ * @param unescape_cb_cls closure for @a unescape_cb
+ */
+void
+MHD_daemon_unescape_cb (struct MHD_Daemon *daemon,
+ MHD_UnescapeCallback unescape_cb,
+ void *unescape_cb_cls)
+{
+ daemon->unescape_cb = unescape_cb;
+ daemon->unescape_cb_cls = unescape_cb_cls;
+}
+
+
+/**
+ * Set random values to be used by the Digest Auth module. Note that
+ * the application must ensure that @a buf remains allocated and
+ * unmodified while the deamon is running.
+ *
+ * @param daemon daemon to configure
+ * @param buf_size number of bytes in @a buf
+ * @param buf entropy buffer
+ */
+void
+MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon,
+ size_t buf_size,
+ const void *buf)
+{
+#if ENABLE_DAUTH
+ daemon->digest_auth_random_buf = buf;
+ daemon->digest_auth_random_buf_size = buf_size;
+#else
+ MHD_PANIC ("digest authentication not supported by this build");
+#endif
+}
+
+
+/**
+ * Length of the internal array holding the map of the nonce and
+ * the nonce counter.
+ *
+ * @param daemon daemon to configure
+ * @param nc_length desired array length
+ */
+void
+MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon,
+ size_t nc_length)
+{
+#if ENABLE_DAUTH
+ daemon->digest_nc_length = nc_length;
+#else
+ MHD_PANIC ("digest authentication not supported by this build");
+#endif
+}
+
+
+/* end of daemon_options.c */
diff --git a/src/lib/internal.h b/src/lib/internal.h
@@ -0,0 +1,412 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2007-2017 Daniel Pittman and Christian Grothoff
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file microhttpd/internal.h
+ * @brief internal shared structures
+ * @author Daniel Pittman
+ * @author Christian Grothoff
+ */
+
+#ifndef INTERNAL_H
+#define INTERNAL_H
+
+#include "mhd_options.h"
+#include "platform.h"
+#include "microhttpd2.h"
+#include "microhttpd_tls.h"
+#include "mhd_assert.h"
+
+#ifdef HTTPS_SUPPORT
+#include <gnutls/gnutls.h>
+#if GNUTLS_VERSION_MAJOR >= 3
+#include <gnutls/abstract.h>
+#endif
+#endif /* HTTPS_SUPPORT */
+
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+#ifdef MHD_PANIC
+/* Override any defined MHD_PANIC macro with proper one */
+#undef MHD_PANIC
+#endif /* MHD_PANIC */
+
+#ifdef HAVE_MESSAGES
+/**
+ * Trigger 'panic' action based on fatal errors.
+ *
+ * @param msg error message (const char *)
+ */
+#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, msg); BUILTIN_NOT_REACHED; } while (0)
+#else
+/**
+ * Trigger 'panic' action based on fatal errors.
+ *
+ * @param msg error message (const char *)
+ */
+#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); BUILTIN_NOT_REACHED; } while (0)
+#endif
+
+#include "mhd_threads.h"
+#include "mhd_locks.h"
+#include "mhd_sockets.h"
+#include "mhd_itc_types.h"
+
+
+/**
+ * Close FD and abort execution if error is detected.
+ * @param fd the FD to close
+ */
+#define MHD_fd_close_chk_(fd) do { \
+ if (0 == close ((fd)) && (EBADF == errno)) \
+ MHD_PANIC(_("Failed to close FD.\n")); \
+ } while(0)
+
+/**
+ * Should we perform additional sanity checks at runtime (on our internal
+ * invariants)? This may lead to aborts, but can be useful for debugging.
+ */
+#define EXTRA_CHECKS MHD_NO
+
+#define MHD_MAX(a,b) (((a)<(b)) ? (b) : (a))
+#define MHD_MIN(a,b) (((a)<(b)) ? (a) : (b))
+
+
+/**
+ * Minimum size by which MHD tries to increment read/write buffers.
+ * We usually begin with half the available pool space for the
+ * IO-buffer, but if absolutely needed we additively grow by the
+ * number of bytes given here (up to -- theoretically -- the full pool
+ * space).
+ */
+#define MHD_BUF_INC_SIZE 1024
+
+
+/**
+ * Handler for fatal errors.
+ */
+extern MHD_PanicCallback mhd_panic;
+
+/**
+ * Closure argument for "mhd_panic".
+ */
+extern void *mhd_panic_cls;
+
+/* If we have Clang or gcc >= 4.5, use __buildin_unreachable() */
+#if defined(__clang__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define BUILTIN_NOT_REACHED __builtin_unreachable()
+#elif defined(_MSC_FULL_VER)
+#define BUILTIN_NOT_REACHED __assume(0)
+#else
+#define BUILTIN_NOT_REACHED
+#endif
+
+#ifndef MHD_STATICSTR_LEN_
+/**
+ * Determine length of static string / macro strings at compile time.
+ */
+#define MHD_STATICSTR_LEN_(macro) (sizeof(macro)/sizeof(char) - 1)
+#endif /* ! MHD_STATICSTR_LEN_ */
+
+
+/**
+ * State kept for each MHD daemon. All connections are kept in two
+ * doubly-linked lists. The first one reflects the state of the
+ * connection in terms of what operations we are waiting for (read,
+ * write, locally blocked, cleanup) whereas the second is about its
+ * timeout state (default or custom).
+ */
+struct MHD_Daemon
+{
+ /**
+ * Function to call to handle incoming requests.
+ */
+ MHD_RequestCallback rc;
+
+ /**
+ * Closure for @e rc.
+ */
+ void *rc_cls;
+
+ /**
+ * Function to call for logging.
+ */
+ MHD_LoggingCallback logger;
+
+ /**
+ * Closure for @e logger.
+ */
+ void *logger_cls;
+
+ /**
+ * Function to call to accept/reject connections based on
+ * the client's IP address.
+ */
+ MHD_AcceptPolicyCallback accept_policy_cb;
+
+ /**
+ * Closure for @e accept_policy_cb.
+ */
+ void *accept_policy_cb_cls;
+
+ /**
+ * Function to call on the full URL early for logging.
+ */
+ MHD_EarlyUriLogCallback early_uri_logger_cb;
+
+ /**
+ * Closure for @e early_uri_logger_cb.
+ */
+ void *early_uri_logger_cls;
+
+ /**
+ * Function to call whenever a connection is started or
+ * closed.
+ */
+ MHD_NotifyConnectionCallback notify_connection_cb;
+
+ /**
+ * Closure for @e notify_connection_cb.
+ */
+ void *notify_connection_cb_cls;
+
+ /**
+ * Function to call to unescape sequences in URIs and URI arguments.
+ * See #MHD_daemon_unescape_cb().
+ */
+ MHD_UnescapeCallback unescape_cb;
+
+ /**
+ * Closure for @e unescape_cb.
+ */
+ void *unescape_cb_cls;
+
+#if HTTPS_SUPPORT
+ /**
+ * Which TLS backend should be used. NULL for no TLS.
+ * This is merely the handle to the dlsym() object, not
+ * the API.
+ */
+ void *tls_backend_lib;
+
+ /**
+ * Callback functions to use for TLS operations.
+ */
+ struct MHD_TLS_Plugin *tls_api;
+#endif
+#if ENABLE_DAUTH
+
+ /**
+ * Random values to be used by digest authentication module.
+ * Size given in @e digest_auth_random_buf_size.
+ */
+ const void *digest_auth_random_buf;
+#endif
+
+ /**
+ * Socket address to bind to for the listen socket.
+ */
+ struct sockaddr_storage listen_sa;
+
+ /**
+ * Number of (valid) bytes in @e listen_sa. Zero
+ * if @e listen_sa is not initialized.
+ */
+ size_t listen_sa_len;
+
+ /**
+ * Buffer size to use for each connection. Default
+ * is #MHD_POOL_SIZE_DEFAULT.
+ */
+ size_t connection_memory_limit_b;
+
+/**
+ * Default minimum size by which MHD tries to increment read/write
+ * buffers. We usually begin with half the available pool space for
+ * the IO-buffer, but if absolutely needed we additively grow by the
+ * number of bytes given here (up to -- theoretically -- the full pool
+ * space).
+ */
+#define BUF_INC_SIZE_DEFAULT 1024
+
+ /**
+ * Increment to use when growing the read buffer. Smaller
+ * than @e connection_memory_limit_b.
+ */
+ size_t connection_memory_increment_b;
+
+ /**
+ * Desired size of the stack for threads created by MHD,
+ * 0 for system default.
+ */
+ size_t thread_stack_limit_b;
+
+#if ENABLE_DAUTH
+
+ /**
+ * Size of @e digest_auth_random_buf.
+ */
+ size_t digest_auth_random_buf_size;
+
+ /**
+ * Default value for @e digest_nc_length.
+ */
+#define DIGEST_NC_LENGTH_DEFAULT 4
+
+ /**
+ * Desired length of the internal array with the nonce and
+ * nonce counters for digest authentication.
+ */
+ size_t digest_nc_length;
+#endif
+
+ /**
+ * Default value we use for the listen backlog.
+ */
+#ifdef SOMAXCONN
+#define LISTEN_BACKLOG_DEFAULT SOMAXCONN
+#else /* !SOMAXCONN */
+#define LISTEN_BACKLOG_DEFAULT 511
+#endif
+
+ /**
+ * Backlog argument to use for listen. See
+ * #MHD_daemon_listen_backlog().
+ */
+ int listen_backlog;
+
+ /**
+ * Default queue length to use with fast open.
+ */
+#define FO_QUEUE_LENGTH_DEFAULT 50
+
+ /**
+ * Queue length to use with fast open.
+ */
+ unsigned int fo_queue_length;
+
+ /**
+ * Maximum number of connections MHD accepts. 0 for unlimited.
+ */
+ unsigned int global_connection_limit;
+
+ /**
+ * Maximum number of connections we accept per IP, 0 for unlimited.
+ */
+ unsigned int ip_connection_limit;
+
+ /**
+ * Default timeout in seconds for idle connections.
+ */
+ unsigned int connection_default_timeout_s;
+
+ /**
+ * Listen socket we should use, MHD_INVALID_SOCKET means
+ * we are to initialize the socket from the other options given.
+ */
+ MHD_socket listen_socket;
+
+ /**
+ * Which threading model do we use? Postive
+ * numbers indicate the number of worker threads to be used.
+ */
+ enum MHD_ThreadingModel threading_model;
+
+ /**
+ * When should we use TCP_FASTOPEN?
+ * See #MHD_daemon_tcp_fastopen().
+ */
+ enum MHD_FastOpenMethod fast_open_method;
+
+ /**
+ * Address family to use when listening.
+ * Default is #MHD_AF_AUTO.
+ */
+ enum MHD_AddressFamily listen_af;
+
+ /**
+ * Sets active/desired style of the event loop.
+ * (Auto only possible during initialization, later set to
+ * the actual style we use.)
+ */
+ enum MHD_EventLoopSyscall event_loop_syscall;
+
+ /**
+ * How strictly do we enforce the HTTP protocol?
+ * See #MHD_daemon_protocol_strict_level().
+ */
+ enum MHD_ProtocolStrictLevel protocol_strict_level;
+
+ /**
+ * On which port should we listen on? Only effective if we were not
+ * given a listen socket or a full address via
+ * #MHD_daemon_bind_sa(). 0 means not set, which means to default
+ * to 80 (http) or 443 (https) respectively.
+ */
+ uint16_t listen_port;
+
+ /**
+ * Suppress generating the "Date:" header, this system
+ * lacks an RTC (or developer is hyper-optimizing). See
+ * #MHD_daemon_suppress_date_no_clock().
+ */
+ bool suppress_date;
+
+ /**
+ * The use of the inter-thread communication channel is disabled.
+ * See #MHD_daemon_disable_itc().
+ */
+ bool disable_itc;
+
+ /**
+ * Disable #MHD_action_suspend() functionality. See
+ * #MHD_daemon_disallow_suspend_resume().
+ */
+ bool disallow_suspend_resume;
+
+ /**
+ * Disable #MHD_action_upgrade() functionality. See
+ * #MHD_daemon_disallow_upgrade().
+ */
+ bool disallow_upgrade;
+
+ /**
+ * Disables optional calls to `shutdown()` and enables aggressive
+ * non-blocking optimistic reads and other potentially unsafe
+ * optimizations. See #MHD_daemon_enable_turbo().
+ */
+ bool enable_turbo;
+
+ /**
+ * Allow reusing the address:port combination when binding.
+ * See #MHD_daemon_listen_allow_address_reuse().
+ */
+ bool allow_address_reuse;
+
+
+
+};
+
+
+
+
+
+
+#endif
diff --git a/src/lib/request.c b/src/lib/request.c
@@ -0,0 +1,68 @@
+/**
+ * Get all of the headers from the request.
+ *
+ * @param request request to get values from
+ * @param kind types of values to iterate over, can be a bitmask
+ * @param iterator callback to call on each header;
+ * maybe NULL (then just count headers)
+ * @param iterator_cls extra argument to @a iterator
+ * @return number of entries iterated over
+ * @ingroup request
+ */
+_MHD_EXTERN unsigned int
+MHD_request_get_values (struct MHD_Request *request,
+ enum MHD_ValueKind kind,
+ MHD_KeyValueIterator iterator,
+ void *iterator_cls);
+
+
+/**
+ * This function can be used to add an entry to the HTTP headers of a
+ * request (so that the #MHD_request_get_values function will
+ * return them -- and the `struct MHD_PostProcessor` will also see
+ * them). This maybe required in certain situations (see Mantis
+ * #1399) where (broken) HTTP implementations fail to supply values
+ * needed by the post processor (or other parts of the application).
+ *
+ * This function MUST only be called from within the
+ * request callbacks (otherwise, access maybe improperly
+ * synchronized). Furthermore, the client must guarantee that the key
+ * and value arguments are 0-terminated strings that are NOT freed
+ * until the connection is closed. (The easiest way to do this is by
+ * passing only arguments to permanently allocated strings.).
+ *
+ * @param request the request for which a
+ * value should be set
+ * @param kind kind of the value
+ * @param key key for the value
+ * @param value the value itself
+ * @return #MHD_NO if the operation could not be
+ * performed due to insufficient memory;
+ * #MHD_YES on success
+ * @ingroup request
+ */
+_MHD_EXTERN enum MHD_Bool
+MHD_request_set_value (struct MHD_Request *request,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *value);
+
+
+/**
+ * Get a particular header value. If multiple
+ * values match the kind, return any one of them.
+ *
+ * @param request request to get values from
+ * @param kind what kind of value are we looking for
+ * @param key the header to look for, NULL to lookup 'trailing' value without a key
+ * @return NULL if no such item was found
+ * @ingroup request
+ */
+_MHD_EXTERN const char *
+MHD_request_lookup_value (struct MHD_Request *request,
+ enum MHD_ValueKind kind,
+ const char *key);
+
+
+
+
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
@@ -4456,8 +4456,8 @@ unescape_wrapper (void *cls,
struct MHD_Connection *connection,
char *val)
{
- (void)cls; /* Mute compiler warning. */
- (void)connection; /* Mute compiler warning. */
+ (void) cls; /* Mute compiler warning. */
+ (void) connection; /* Mute compiler warning. */
return MHD_http_unescape (val);
}
@@ -5425,6 +5425,7 @@ MHD_start_daemon_va (unsigned int flags,
MHD_DLOG (daemon, _("Using debug build of libmicrohttpd.\n") );
#endif /* HAVE_MESSAGES */
#endif /* ! NDEBUG */
+
if ( (0 != (*pflags & MHD_USE_ITC)) &&
(0 == daemon->worker_pool_size) )
{