http://git-wip-us.apache.org/repos/asf/celix/blob/c4de9077/examples/celix-examples/civetweb/civetweb/civetweb.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/civetweb/civetweb/civetweb.c 
b/examples/celix-examples/civetweb/civetweb/civetweb.c
new file mode 100644
index 0000000..259663a
--- /dev/null
+++ b/examples/celix-examples/civetweb/civetweb/civetweb.c
@@ -0,0 +1,19792 @@
+/* Copyright (c) 2013-2018 the Civetweb developers
+ * Copyright (c) 2004-2013 Sergey Lyubka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if defined(__GNUC__) || defined(__MINGW32__)
+/* Disable unused macros warnings - not all defines are required
+ * for all systems and all compilers. */
+#pragma GCC diagnostic ignored "-Wunused-macros"
+/* A padding warning is just plain useless */
+#pragma GCC diagnostic ignored "-Wpadded"
+#endif
+
+#if defined(__clang__) /* GCC does not (yet) support this pragma */
+/* We must set some flags for the headers we include. These flags
+ * are reserved ids according to C99, so we need to disable a
+ * warning for that. */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wreserved-id-macro"
+#endif
+
+#if defined(_WIN32)
+#if !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
+#endif
+#if !defined(_WIN32_WINNT) /* defined for tdm-gcc so we can use getnameinfo */
+#define _WIN32_WINNT 0x0501
+#endif
+#else
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE /* for setgroups(), pthread_setname_np() */
+#endif
+#if defined(__linux__) && !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
+#endif
+#if !defined(_LARGEFILE_SOURCE)
+#define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
+#endif
+#if !defined(_FILE_OFFSET_BITS)
+#define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
+#endif
+#if !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
+#endif
+#if !defined(__STDC_LIMIT_MACROS)
+#define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
+#endif
+#if !defined(_DARWIN_UNLIMITED_SELECT)
+#define _DARWIN_UNLIMITED_SELECT
+#endif
+#if defined(__sun)
+#define __EXTENSIONS__  /* to expose flockfile and friends in stdio.h */
+#define __inline inline /* not recognized on older compiler versions */
+#endif
+#endif
+
+#if defined(__clang__)
+/* Enable reserved-id-macro warning again. */
+#pragma GCC diagnostic pop
+#endif
+
+
+#if defined(USE_LUA)
+#define USE_TIMERS
+#endif
+
+#if defined(_MSC_VER)
+/* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
+#pragma warning(disable : 4306)
+/* conditional expression is constant: introduced by FD_SET(..) */
+#pragma warning(disable : 4127)
+/* non-constant aggregate initializer: issued due to missing C99 support */
+#pragma warning(disable : 4204)
+/* padding added after data member */
+#pragma warning(disable : 4820)
+/* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+#pragma warning(disable : 4668)
+/* no function prototype given: converting '()' to '(void)' */
+#pragma warning(disable : 4255)
+/* function has been selected for automatic inline expansion */
+#pragma warning(disable : 4711)
+#endif
+
+
+/* This code uses static_assert to check some conditions.
+ * Unfortunately some compilers still do not support it, so we have a
+ * replacement function here. */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201100L
+#define mg_static_assert _Static_assert
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+#define mg_static_assert static_assert
+#else
+char static_assert_replacement[1];
+#define mg_static_assert(cond, txt)                                            
\
+       extern char static_assert_replacement[(cond) ? 1 : -1]
+#endif
+
+mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
+"int data type size check");
+mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
+"pointer data type size check");
+mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
+
+
+/* Alternative queue is well tested and should be the new default */
+#if defined(NO_ALTERNATIVE_QUEUE)
+#if defined(ALTERNATIVE_QUEUE)
+#error "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE or none, but not both"
+#endif
+#else
+#define ALTERNATIVE_QUEUE
+#endif
+
+
+/* DTL -- including winsock2.h works better if lean and mean */
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#if defined(__SYMBIAN32__)
+/* According to https://en.wikipedia.org/wiki/Symbian#History,
+ * Symbian is no longer maintained since 2014-01-01.
+ * Recent versions of CivetWeb are no longer tested for Symbian.
+ * It makes no sense, to support an abandoned operating system.
+ */
+#error "Symbian is no longer maintained. CivetWeb no longer supports Symbian."
+#define NO_SSL /* SSL is not supported */
+#define NO_CGI /* CGI is not supported */
+#define PATH_MAX FILENAME_MAX
+#endif /* __SYMBIAN32__ */
+
+
+#if !defined(CIVETWEB_HEADER_INCLUDED)
+/* Include the header file here, so the CivetWeb interface is defined for the
+ * entire implementation, including the following forward definitions. */
+#include "civetweb.h"
+#endif
+
+#if !defined(DEBUG_TRACE)
+#if defined(DEBUG)
+static void DEBUG_TRACE_FUNC(const char *func,
+unsigned line,
+PRINTF_FORMAT_STRING(const char *fmt),
+...) PRINTF_ARGS(3, 4);
+
+#define DEBUG_TRACE(fmt, ...)                                                  
\
+       DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
+
+#define NEED_DEBUG_TRACE_FUNC
+
+#else
+#define DEBUG_TRACE(fmt, ...)                                                  
\
+       do {                                                                    
   \
+       } while (0)
+#endif /* DEBUG */
+#endif /* DEBUG_TRACE */
+
+
+#if !defined(DEBUG_ASSERT)
+#if defined(DEBUG)
+#define DEBUG_ASSERT(cond)                                                     
\
+       do {                                                                    
   \
+               if (!(cond)) {                                                  
       \
+                       DEBUG_TRACE("ASSERTION FAILED: %s", #cond);             
           \
+                       exit(2); /* Exit with error */                          
           \
+               }                                                               
       \
+       } while (0)
+#else
+#define DEBUG_ASSERT(cond)
+#endif /* DEBUG */
+#endif
+
+
+#if !defined(IGNORE_UNUSED_RESULT)
+#define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
+#endif
+
+
+#if defined(__GNUC__) || defined(__MINGW32__)
+
+/* GCC unused function attribute seems fundamentally broken.
+ * Several attempts to tell the compiler "THIS FUNCTION MAY BE USED
+ * OR UNUSED" for individual functions failed.
+ * Either the compiler creates an "unused-function" warning if a
+ * function is not marked with __attribute__((unused)).
+ * On the other hand, if the function is marked with this attribute,
+ * but is used, the compiler raises a completely idiotic
+ * "used-but-marked-unused" warning - and
+ *   #pragma GCC diagnostic ignored "-Wused-but-marked-unused"
+ * raises error: unknown option after "#pragma GCC diagnostic".
+ * Disable this warning completely, until the GCC guys sober up
+ * again.
+ */
+
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+#define FUNCTION_MAY_BE_UNUSED /* __attribute__((unused)) */
+
+#else
+#define FUNCTION_MAY_BE_UNUSED
+#endif
+
+
+/* Some ANSI #includes are not available on Windows CE */
+#if !defined(_WIN32_WCE)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#endif /* !_WIN32_WCE */
+
+
+#if defined(__clang__)
+/* When using -Weverything, clang does not accept it's own headers
+ * in a release build configuration. Disable what is too much in
+ * -Weverything. */
+#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
+#endif
+
+#if defined(__GNUC__) || defined(__MINGW32__)
+/* Who on earth came to the conclusion, using __DATE__ should rise
+ * an "expansion of date or time macro is not reproducible"
+ * warning. That's exactly what was intended by using this macro.
+ * Just disable this nonsense warning. */
+
+/* And disabling them does not work either:
+ * #pragma clang diagnostic ignored "-Wno-error=date-time"
+ * #pragma clang diagnostic ignored "-Wdate-time"
+ * So we just have to disable ALL warnings for some lines
+ * of code.
+ * This seems to be a known GCC bug, not resolved since 2012:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
+ */
+#endif
+
+
+#if defined(__MACH__) /* Apple OSX section */
+
+#if defined(__clang__)
+#if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 
8))
+/* Avoid warnings for Xcode 7. It seems it does no longer exist in Xcode 8 */
+#pragma clang diagnostic ignored "-Wno-reserved-id-macro"
+#pragma clang diagnostic ignored "-Wno-keyword-macro"
+#endif
+#endif
+
+#define CLOCK_MONOTONIC (1)
+#define CLOCK_REALTIME (2)
+
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <mach/clock.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+
+/* clock_gettime is not implemented on OSX prior to 10.12 */
+static int
+_civet_clock_gettime(int clk_id, struct timespec *t)
+{
+memset(t, 0, sizeof(*t));
+if (clk_id == CLOCK_REALTIME) {
+struct timeval now;
+int rv = gettimeofday(&now, NULL);
+if (rv) {
+return rv;
+}
+t->tv_sec = now.tv_sec;
+t->tv_nsec = now.tv_usec * 1000;
+return 0;
+
+} else if (clk_id == CLOCK_MONOTONIC) {
+static uint64_t clock_start_time = 0;
+static mach_timebase_info_data_t timebase_ifo = {0, 0};
+
+uint64_t now = mach_absolute_time();
+
+if (clock_start_time == 0) {
+kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
+DEBUG_ASSERT(mach_status == KERN_SUCCESS);
+
+/* appease "unused variable" warning for release builds */
+(void)mach_status;
+
+clock_start_time = now;
+}
+
+now = (uint64_t)((double)(now - clock_start_time)
+* (double)timebase_ifo.numer
+/ (double)timebase_ifo.denom);
+
+t->tv_sec = now / 1000000000;
+t->tv_nsec = now % 1000000000;
+return 0;
+}
+return -1; /* EINVAL - Clock ID is unknown */
+}
+
+/* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
+#if defined(__CLOCK_AVAILABILITY)
+/* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be
+ * declared but it may be NULL at runtime. So we need to check before using
+ * it. */
+static int
+_civet_safe_clock_gettime(int clk_id, struct timespec *t)
+{
+if (clock_gettime) {
+return clock_gettime(clk_id, t);
+}
+return _civet_clock_gettime(clk_id, t);
+}
+#define clock_gettime _civet_safe_clock_gettime
+#else
+#define clock_gettime _civet_clock_gettime
+#endif
+
+#endif
+
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+
+/********************************************************************/
+/* CivetWeb configuration defines */
+/********************************************************************/
+
+/* Maximum number of threads that can be configured.
+ * The number of threads actually created depends on the "num_threads"
+ * configuration parameter, but this is the upper limit. */
+#if !defined(MAX_WORKER_THREADS)
+#define MAX_WORKER_THREADS (1024 * 64) /* in threads (count) */
+#endif
+
+/* Timeout interval for select/poll calls.
+ * The timeouts depend on "*_timeout_ms" configuration values, but long
+ * timeouts are split into timouts as small as SOCKET_TIMEOUT_QUANTUM.
+ * This reduces the time required to stop the server. */
+#if !defined(SOCKET_TIMEOUT_QUANTUM)
+#define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */
+#endif
+
+/* Do not try to compress files smaller than this limit. */
+#if !defined(MG_FILE_COMPRESSION_SIZE_LIMIT)
+#define MG_FILE_COMPRESSION_SIZE_LIMIT (1024) /* in bytes */
+#endif
+
+#if !defined(PASSWORDS_FILE_NAME)
+#define PASSWORDS_FILE_NAME ".htpasswd"
+#endif
+
+/* Initial buffer size for all CGI environment variables. In case there is
+ * not enough space, another block is allocated. */
+#if !defined(CGI_ENVIRONMENT_SIZE)
+#define CGI_ENVIRONMENT_SIZE (4096) /* in bytes */
+#endif
+
+/* Maximum number of environment variables. */
+#if !defined(MAX_CGI_ENVIR_VARS)
+#define MAX_CGI_ENVIR_VARS (256) /* in variables (count) */
+#endif
+
+/* General purpose buffer size. */
+#if !defined(MG_BUF_LEN) /* in bytes */
+#define MG_BUF_LEN (1024 * 8)
+#endif
+
+/* Size of the accepted socket queue (in case the old queue implementation
+ * is used). */
+#if !defined(MGSQLEN)
+#define MGSQLEN (20) /* count */
+#endif
+
+
+/********************************************************************/
+
+/* Helper makros */
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+
+/* Standard defines */
+#if !defined(INT64_MAX)
+#define INT64_MAX (9223372036854775807)
+#endif
+
+#define SHUTDOWN_RD (0)
+#define SHUTDOWN_WR (1)
+#define SHUTDOWN_BOTH (2)
+
+mg_static_assert(MAX_WORKER_THREADS >= 1,
+"worker threads must be a positive number");
+
+mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8,
+"size_t data type size check");
+
+#if defined(_WIN32)   /* WINDOWS include block */
+#include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
+#include <ws2tcpip.h>
+#include <windows.h>
+
+typedef const char *SOCK_OPT_TYPE;
+
+#if !defined(PATH_MAX)
+#define W_PATH_MAX (MAX_PATH)
+/* at most three UTF-8 chars per wchar_t */
+#define PATH_MAX (W_PATH_MAX * 3)
+#else
+#define W_PATH_MAX ((PATH_MAX + 2) / 3)
+#endif
+
+mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
+
+#if !defined(_IN_PORT_T)
+#if !defined(in_port_t)
+#define in_port_t u_short
+#endif
+#endif
+
+#if !defined(_WIN32_WCE)
+#include <process.h>
+#include <direct.h>
+#include <io.h>
+#else            /* _WIN32_WCE */
+#define NO_CGI   /* WinCE has no pipes */
+#define NO_POPEN /* WinCE has no popen */
+
+typedef long off_t;
+
+#define errno ((int)(GetLastError()))
+#define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
+#endif /* _WIN32_WCE */
+
+#define MAKEUQUAD(lo, hi)                                                      
\
+       ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
+#define RATE_DIFF (10000000) /* 100 nsecs */
+#define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
+#define SYS2UNIX_TIME(lo, hi)                                                  
\
+       ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
+
+/* Visual Studio 6 does not know __func__ or __FUNCTION__
+ * The rest of MS compilers use __FUNCTION__, not C99 __func__
+ * Also use _strtoui64 on modern M$ compilers */
+#if defined(_MSC_VER)
+#if (_MSC_VER < 1300)
+#define STRX(x) #x
+#define STR(x) STRX(x)
+#define __func__ __FILE__ ":" STR(__LINE__)
+#define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
+#define strtoll(x, y, z) (_atoi64(x))
+#else
+#define __func__ __FUNCTION__
+#define strtoull(x, y, z) (_strtoui64(x, y, z))
+#define strtoll(x, y, z) (_strtoi64(x, y, z))
+#endif
+#endif /* _MSC_VER */
+
+#define ERRNO ((int)(GetLastError()))
+#define NO_SOCKLEN_T
+
+#if defined(_WIN64) || defined(__MINGW64__)
+#if !defined(SSL_LIB)
+#define SSL_LIB "ssleay64.dll"
+#endif
+#if !defined(CRYPTO_LIB)
+#define CRYPTO_LIB "libeay64.dll"
+#endif
+#else
+#if !defined(SSL_LIB)
+#define SSL_LIB "ssleay32.dll"
+#endif
+#if !defined(CRYPTO_LIB)
+#define CRYPTO_LIB "libeay32.dll"
+#endif
+#endif
+
+#define O_NONBLOCK (0)
+#if !defined(W_OK)
+#define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
+#endif
+#if !defined(EWOULDBLOCK)
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif /* !EWOULDBLOCK */
+#define _POSIX_
+#define INT64_FMT "I64d"
+#define UINT64_FMT "I64u"
+
+#define WINCDECL __cdecl
+#define vsnprintf_impl _vsnprintf
+#define access _access
+#define mg_sleep(x) (Sleep(x))
+
+#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
+#if !defined(popen)
+#define popen(x, y) (_popen(x, y))
+#endif
+#if !defined(pclose)
+#define pclose(x) (_pclose(x))
+#endif
+#define close(x) (_close(x))
+#define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
+#define RTLD_LAZY (0)
+#define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0)
+#define fdopen(x, y) (_fdopen((x), (y)))
+#define write(x, y, z) (_write((x), (y), (unsigned)z))
+#define read(x, y, z) (_read((x), (y), (unsigned)z))
+#define flockfile(x) (EnterCriticalSection(&global_log_file_lock))
+#define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock))
+#define sleep(x) (Sleep((x)*1000))
+#define rmdir(x) (_rmdir(x))
+#if defined(_WIN64) || !defined(__MINGW32__)
+/* Only MinGW 32 bit is missing this function */
+#define timegm(x) (_mkgmtime(x))
+#else
+time_t timegm(struct tm *tm);
+#define NEED_TIMEGM
+#endif
+
+
+#if !defined(fileno)
+#define fileno(x) (_fileno(x))
+#endif /* !fileno MINGW #defines fileno */
+
+typedef HANDLE pthread_mutex_t;
+typedef DWORD pthread_key_t;
+typedef HANDLE pthread_t;
+typedef struct {
+CRITICAL_SECTION threadIdSec;
+struct mg_workerTLS *waiting_thread; /* The chain of threads */
+} pthread_cond_t;
+
+#if !defined(__clockid_t_defined)
+typedef DWORD clockid_t;
+#endif
+#if !defined(CLOCK_MONOTONIC)
+#define CLOCK_MONOTONIC (1)
+#endif
+#if !defined(CLOCK_REALTIME)
+#define CLOCK_REALTIME (2)
+#endif
+#if !defined(CLOCK_THREAD)
+#define CLOCK_THREAD (3)
+#endif
+#if !defined(CLOCK_PROCESS)
+#define CLOCK_PROCESS (4)
+#endif
+
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#define _TIMESPEC_DEFINED
+#endif
+#if !defined(_TIMESPEC_DEFINED)
+struct timespec {
+time_t tv_sec; /* seconds */
+long tv_nsec;  /* nanoseconds */
+};
+#endif
+
+#if !defined(WIN_PTHREADS_TIME_H)
+#define MUST_IMPLEMENT_CLOCK_GETTIME
+#endif
+
+#if defined(MUST_IMPLEMENT_CLOCK_GETTIME)
+#define clock_gettime mg_clock_gettime
+static int
+clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+FILETIME ft;
+ULARGE_INTEGER li, li2;
+BOOL ok = FALSE;
+double d;
+static double perfcnt_per_sec = 0.0;
+static BOOL initialized = FALSE;
+
+if (!initialized) {
+QueryPerformanceFrequency((LARGE_INTEGER *)&li);
+perfcnt_per_sec = 1.0 / li.QuadPart;
+initialized = TRUE;
+}
+
+if (tp) {
+memset(tp, 0, sizeof(*tp));
+
+if (clk_id == CLOCK_REALTIME) {
+
+/* BEGIN: CLOCK_REALTIME = wall clock (date and time) */
+GetSystemTimeAsFileTime(&ft);
+li.LowPart = ft.dwLowDateTime;
+li.HighPart = ft.dwHighDateTime;
+li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
+tp->tv_sec = (time_t)(li.QuadPart / 10000000);
+tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
+ok = TRUE;
+/* END: CLOCK_REALTIME */
+
+} else if (clk_id == CLOCK_MONOTONIC) {
+
+/* BEGIN: CLOCK_MONOTONIC = stopwatch (time differences) */
+QueryPerformanceCounter((LARGE_INTEGER *)&li);
+d = li.QuadPart * perfcnt_per_sec;
+tp->tv_sec = (time_t)d;
+d -= (double)tp->tv_sec;
+tp->tv_nsec = (long)(d * 1.0E9);
+ok = TRUE;
+/* END: CLOCK_MONOTONIC */
+
+} else if (clk_id == CLOCK_THREAD) {
+
+/* BEGIN: CLOCK_THREAD = CPU usage of thread */
+FILETIME t_create, t_exit, t_kernel, t_user;
+if (GetThreadTimes(GetCurrentThread(),
+&t_create,
+&t_exit,
+&t_kernel,
+&t_user)) {
+li.LowPart = t_user.dwLowDateTime;
+li.HighPart = t_user.dwHighDateTime;
+li2.LowPart = t_kernel.dwLowDateTime;
+li2.HighPart = t_kernel.dwHighDateTime;
+li.QuadPart += li2.QuadPart;
+tp->tv_sec = (time_t)(li.QuadPart / 10000000);
+tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
+ok = TRUE;
+}
+/* END: CLOCK_THREAD */
+
+} else if (clk_id == CLOCK_PROCESS) {
+
+/* BEGIN: CLOCK_PROCESS = CPU usage of process */
+FILETIME t_create, t_exit, t_kernel, t_user;
+if (GetProcessTimes(GetCurrentProcess(),
+&t_create,
+&t_exit,
+&t_kernel,
+&t_user)) {
+li.LowPart = t_user.dwLowDateTime;
+li.HighPart = t_user.dwHighDateTime;
+li2.LowPart = t_kernel.dwLowDateTime;
+li2.HighPart = t_kernel.dwHighDateTime;
+li.QuadPart += li2.QuadPart;
+tp->tv_sec = (time_t)(li.QuadPart / 10000000);
+tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
+ok = TRUE;
+}
+/* END: CLOCK_PROCESS */
+
+} else {
+
+/* BEGIN: unknown clock */
+/* ok = FALSE; already set by init */
+/* END: unknown clock */
+}
+}
+
+return ok ? 0 : -1;
+}
+#endif
+
+
+#define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
+
+static int pthread_mutex_lock(pthread_mutex_t *);
+static int pthread_mutex_unlock(pthread_mutex_t *);
+static void path_to_unicode(const struct mg_connection *conn,
+const char *path,
+wchar_t *wbuf,
+size_t wbuf_len);
+
+/* All file operations need to be rewritten to solve #246. */
+
+struct mg_file;
+
+static const char *
+mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p);
+
+
+/* POSIX dirent interface */
+struct dirent {
+char d_name[PATH_MAX];
+};
+
+typedef struct DIR {
+HANDLE handle;
+WIN32_FIND_DATAW info;
+struct dirent result;
+} DIR;
+
+#if defined(_WIN32)
+#if !defined(HAVE_POLL)
+struct pollfd {
+SOCKET fd;
+short events;
+short revents;
+};
+#endif
+#endif
+
+/* Mark required libraries */
+#if defined(_MSC_VER)
+#pragma comment(lib, "Ws2_32.lib")
+#endif
+
+#else /* defined(_WIN32) - WINDOWS vs UNIX include block */
+
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+typedef const void *SOCK_OPT_TYPE;
+
+#if defined(ANDROID)
+typedef unsigned short int in_port_t;
+#endif
+
+#include <pwd.h>
+#include <unistd.h>
+#include <grp.h>
+#include <dirent.h>
+#define vsnprintf_impl vsnprintf
+
+#if !defined(NO_SSL_DL) && !defined(NO_SSL)
+#include <dlfcn.h>
+#endif
+#include <pthread.h>
+#if defined(__MACH__)
+#define SSL_LIB "libssl.dylib"
+#define CRYPTO_LIB "libcrypto.dylib"
+#else
+#if !defined(SSL_LIB)
+#define SSL_LIB "libssl.so"
+#endif
+#if !defined(CRYPTO_LIB)
+#define CRYPTO_LIB "libcrypto.so"
+#endif
+#endif
+#if !defined(O_BINARY)
+#define O_BINARY (0)
+#endif /* O_BINARY */
+#define closesocket(a) (close(a))
+#define mg_mkdir(conn, path, mode) (mkdir(path, mode))
+#define mg_remove(conn, x) (remove(x))
+#define mg_sleep(x) (usleep((x)*1000))
+#define mg_opendir(conn, x) (opendir(x))
+#define mg_closedir(x) (closedir(x))
+#define mg_readdir(x) (readdir(x))
+#define ERRNO (errno)
+#define INVALID_SOCKET (-1)
+#define INT64_FMT PRId64
+#define UINT64_FMT PRIu64
+typedef int SOCKET;
+#define WINCDECL
+
+#if defined(__hpux)
+/* HPUX 11 does not have monotonic, fall back to realtime */
+#if !defined(CLOCK_MONOTONIC)
+#define CLOCK_MONOTONIC CLOCK_REALTIME
+#endif
+
+/* HPUX defines socklen_t incorrectly as size_t which is 64bit on
+ * Itanium.  Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
+ * the prototypes use int* rather than socklen_t* which matches the
+ * actual library expectation.  When called with the wrong size arg
+ * accept() returns a zero client inet addr and check_acl() always
+ * fails.  Since socklen_t is widely used below, just force replace
+ * their typedef with int. - DTL
+ */
+#define socklen_t int
+#endif /* hpux */
+
+#endif /* defined(_WIN32) - WINDOWS vs UNIX include block */
+
+/* Maximum queue length for pending connections. This value is passed as
+ * parameter to the "listen" socket call. */
+#if !defined(SOMAXCONN)
+/* This symbol may be defined in winsock2.h so this must after that include */
+#define SOMAXCONN (100) /* in pending connections (count) */
+#endif
+
+/* In case our C library is missing "timegm", provide an implementation */
+#if defined(NEED_TIMEGM)
+static inline int
+is_leap(int y)
+{
+return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
+}
+
+static inline int
+count_leap(int y)
+{
+return (y - 1969) / 4 - (y - 1901) / 100 + (y - 1601) / 400;
+}
+
+time_t
+timegm(struct tm *tm)
+{
+static const unsigned short ydays[] = {
+0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
+int year = tm->tm_year + 1900;
+int mon = tm->tm_mon;
+int mday = tm->tm_mday - 1;
+int hour = tm->tm_hour;
+int min = tm->tm_min;
+int sec = tm->tm_sec;
+
+if (year < 1970 || mon < 0 || mon > 11 || mday < 0
+|| (mday >= ydays[mon + 1] - ydays[mon]
++ (mon == 1 && is_leap(year) ? 1 : 0)) || hour < 0
+|| hour > 23
+|| min < 0
+|| min > 59
+|| sec < 0
+|| sec > 60)
+return -1;
+
+time_t res = year - 1970;
+res *= 365;
+res += mday;
+res += ydays[mon] + (mon > 1 && is_leap(year) ? 1 : 0);
+res += count_leap(year);
+
+res *= 24;
+res += hour;
+res *= 60;
+res += min;
+res *= 60;
+res += sec;
+return res;
+}
+#endif /* NEED_TIMEGM */
+
+
+/* va_copy should always be a macro, C99 and C++11 - DTL */
+#if !defined(va_copy)
+#define va_copy(x, y) ((x) = (y))
+#endif
+
+
+#if defined(_WIN32)
+/* Create substitutes for POSIX functions in Win32. */
+
+#if defined(__MINGW32__)
+/* Show no warning in case system functions are not used. */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+
+static CRITICAL_SECTION global_log_file_lock;
+
+FUNCTION_MAY_BE_UNUSED
+static DWORD
+pthread_self(void)
+{
+return GetCurrentThreadId();
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+pthread_key_create(
+pthread_key_t *key,
+void (*_ignored)(void *) /* destructor not supported for Windows */
+)
+{
+(void)_ignored;
+
+if ((key != 0)) {
+*key = TlsAlloc();
+return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
+}
+return -2;
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+pthread_key_delete(pthread_key_t key)
+{
+return TlsFree(key) ? 0 : 1;
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+pthread_setspecific(pthread_key_t key, void *value)
+{
+return TlsSetValue(key, value) ? 0 : 1;
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static void *
+pthread_getspecific(pthread_key_t key)
+{
+return TlsGetValue(key);
+}
+
+#if defined(__MINGW32__)
+/* Enable unused function warning again */
+#pragma GCC diagnostic pop
+#endif
+
+static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
+#else
+static pthread_mutexattr_t pthread_mutex_attr;
+#endif /* _WIN32 */
+
+
+#if defined(_WIN32_WCE)
+/* Create substitutes for POSIX functions in Win32. */
+
+#if defined(__MINGW32__)
+/* Show no warning in case system functions are not used. */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+
+FUNCTION_MAY_BE_UNUSED
+static time_t
+time(time_t *ptime)
+{
+time_t t;
+SYSTEMTIME st;
+FILETIME ft;
+
+GetSystemTime(&st);
+SystemTimeToFileTime(&st, &ft);
+t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
+
+if (ptime != NULL) {
+*ptime = t;
+}
+
+return t;
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static struct tm *
+localtime_s(const time_t *ptime, struct tm *ptm)
+{
+int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
+FILETIME ft, lft;
+SYSTEMTIME st;
+TIME_ZONE_INFORMATION tzinfo;
+
+if (ptm == NULL) {
+return NULL;
+}
+
+*(int64_t *)&ft = t;
+FileTimeToLocalFileTime(&ft, &lft);
+FileTimeToSystemTime(&lft, &st);
+ptm->tm_year = st.wYear - 1900;
+ptm->tm_mon = st.wMonth - 1;
+ptm->tm_wday = st.wDayOfWeek;
+ptm->tm_mday = st.wDay;
+ptm->tm_hour = st.wHour;
+ptm->tm_min = st.wMinute;
+ptm->tm_sec = st.wSecond;
+ptm->tm_yday = 0; /* hope nobody uses this */
+ptm->tm_isdst =
+(GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
+
+return ptm;
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static struct tm *
+gmtime_s(const time_t *ptime, struct tm *ptm)
+{
+/* FIXME(lsm): fix this. */
+return localtime_s(ptime, ptm);
+}
+
+
+static int mg_atomic_inc(volatile int *addr);
+static struct tm tm_array[MAX_WORKER_THREADS];
+static int tm_index = 0;
+
+
+FUNCTION_MAY_BE_UNUSED
+static struct tm *
+localtime(const time_t *ptime)
+{
+int i = mg_atomic_inc(&tm_index) % (sizeof(tm_array) / sizeof(tm_array[0]));
+return localtime_s(ptime, tm_array + i);
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static struct tm *
+gmtime(const time_t *ptime)
+{
+int i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array);
+return gmtime_s(ptime, tm_array + i);
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static size_t
+strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
+{
+/* TODO: (void)mg_snprintf(NULL, dst, dst_size, "implement strftime()
+        * for WinCE"); */
+return 0;
+}
+
+#define _beginthreadex(psec, stack, func, prm, flags, ptid)                    
\
+       (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid)
+
+#define remove(f) mg_remove(NULL, f)
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+rename(const char *a, const char *b)
+{
+wchar_t wa[W_PATH_MAX];
+wchar_t wb[W_PATH_MAX];
+path_to_unicode(NULL, a, wa, ARRAY_SIZE(wa));
+path_to_unicode(NULL, b, wb, ARRAY_SIZE(wb));
+
+return MoveFileW(wa, wb) ? 0 : -1;
+}
+
+
+struct stat {
+int64_t st_size;
+time_t st_mtime;
+};
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+stat(const char *name, struct stat *st)
+{
+wchar_t wbuf[W_PATH_MAX];
+WIN32_FILE_ATTRIBUTE_DATA attr;
+time_t creation_time, write_time;
+
+path_to_unicode(NULL, name, wbuf, ARRAY_SIZE(wbuf));
+memset(&attr, 0, sizeof(attr));
+
+GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
+st->st_size =
+(((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
+
+write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
+attr.ftLastWriteTime.dwHighDateTime);
+creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
+attr.ftCreationTime.dwHighDateTime);
+
+if (creation_time > write_time) {
+st->st_mtime = creation_time;
+} else {
+st->st_mtime = write_time;
+}
+return 0;
+}
+
+#define access(x, a) 1 /* not required anyway */
+
+/* WinCE-TODO: define stat, remove, rename, _rmdir, _lseeki64 */
+/* Values from errno.h in Windows SDK (Visual Studio). */
+#define EEXIST 17
+#define EACCES 13
+#define ENOENT 2
+
+#if defined(__MINGW32__)
+/* Enable unused function warning again */
+#pragma GCC diagnostic pop
+#endif
+
+#endif /* defined(_WIN32_WCE) */
+
+
+#if defined(__GNUC__) || defined(__MINGW32__)
+/* Show no warning in case system functions are not used. */
+#define GCC_VERSION                                                            
\
+       (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#if GCC_VERSION >= 40500
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif /* GCC_VERSION >= 40500 */
+#endif /* defined(__GNUC__) || defined(__MINGW32__) */
+#if defined(__clang__)
+/* Show no warning in case system functions are not used. */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
+
+static pthread_mutex_t global_lock_mutex;
+
+
+#if defined(_WIN32)
+/* Forward declaration for Windows */
+FUNCTION_MAY_BE_UNUSED
+static int pthread_mutex_lock(pthread_mutex_t *mutex);
+
+FUNCTION_MAY_BE_UNUSED
+static int pthread_mutex_unlock(pthread_mutex_t *mutex);
+#endif
+
+
+FUNCTION_MAY_BE_UNUSED
+static void
+mg_global_lock(void)
+{
+(void)pthread_mutex_lock(&global_lock_mutex);
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static void
+mg_global_unlock(void)
+{
+(void)pthread_mutex_unlock(&global_lock_mutex);
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+mg_atomic_inc(volatile int *addr)
+{
+int ret;
+#if defined(_WIN32) && !defined(NO_ATOMICS)
+/* Depending on the SDK, this function uses either
+        * (volatile unsigned int *) or (volatile LONG *),
+        * so whatever you use, the other SDK is likely to raise a warning. */
+ret = InterlockedIncrement((volatile long *)addr);
+#elif defined(__GNUC__)                                                        
\
+    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           
\
+    && !defined(NO_ATOMICS)
+ret = __sync_add_and_fetch(addr, 1);
+#else
+mg_global_lock();
+ret = (++(*addr));
+mg_global_unlock();
+#endif
+return ret;
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static int
+mg_atomic_dec(volatile int *addr)
+{
+int ret;
+#if defined(_WIN32) && !defined(NO_ATOMICS)
+/* Depending on the SDK, this function uses either
+        * (volatile unsigned int *) or (volatile LONG *),
+        * so whatever you use, the other SDK is likely to raise a warning. */
+ret = InterlockedDecrement((volatile long *)addr);
+#elif defined(__GNUC__)                                                        
\
+    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           
\
+    && !defined(NO_ATOMICS)
+ret = __sync_sub_and_fetch(addr, 1);
+#else
+mg_global_lock();
+ret = (--(*addr));
+mg_global_unlock();
+#endif
+return ret;
+}
+
+
+#if defined(USE_SERVER_STATS)
+static int64_t
+mg_atomic_add(volatile int64_t *addr, int64_t value)
+{
+int64_t ret;
+#if defined(_WIN64) && !defined(NO_ATOMICS)
+ret = InterlockedAdd64(addr, value);
+#elif defined(__GNUC__)                                                        
\
+    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           
\
+    && !defined(NO_ATOMICS)
+ret = __sync_add_and_fetch(addr, value);
+#else
+mg_global_lock();
+*addr += value;
+ret = (*addr);
+mg_global_unlock();
+#endif
+return ret;
+}
+#endif
+
+
+#if defined(__GNUC__)
+/* Show no warning in case system functions are not used. */
+#if GCC_VERSION >= 40500
+#pragma GCC diagnostic pop
+#endif /* GCC_VERSION >= 40500 */
+#endif /* defined(__GNUC__) */
+#if defined(__clang__)
+/* Show no warning in case system functions are not used. */
+#pragma clang diagnostic pop
+#endif
+
+
+#if defined(USE_SERVER_STATS)
+
+struct mg_memory_stat {
+volatile int64_t totalMemUsed;
+volatile int64_t maxMemUsed;
+volatile int blockCount;
+};
+
+
+static struct mg_memory_stat *get_memory_stat(struct mg_context *ctx);
+
+
+static void *
+mg_malloc_ex(size_t size,
+struct mg_context *ctx,
+const char *file,
+unsigned line)
+{
+void *data = malloc(size + 2 * sizeof(uintptr_t));
+void *memory = 0;
+struct mg_memory_stat *mstat = get_memory_stat(ctx);
+
+#if defined(MEMORY_DEBUGGING)
+char mallocStr[256];
+#else
+(void)file;
+(void)line;
+#endif
+
+if (data) {
+int64_t mmem = mg_atomic_add(&mstat->totalMemUsed, (int64_t)size);
+if (mmem > mstat->maxMemUsed) {
+/* could use atomic compare exchange, but this
+                        * seems overkill for statistics data */
+mstat->maxMemUsed = mmem;
+}
+
+mg_atomic_inc(&mstat->blockCount);
+((uintptr_t *)data)[0] = size;
+((uintptr_t *)data)[1] = (uintptr_t)mstat;
+memory = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
+}
+
+#if defined(MEMORY_DEBUGGING)
+sprintf(mallocStr,
+"MEM: %p %5lu alloc   %7lu %4lu --- %s:%u\n",
+memory,
+(unsigned long)size,
+(unsigned long)mstat->totalMemUsed,
+(unsigned long)mstat->blockCount,
+file,
+line);
+#if defined(_WIN32)
+OutputDebugStringA(mallocStr);
+#else
+DEBUG_TRACE("%s", mallocStr);
+#endif
+#endif
+
+return memory;
+}
+
+
+static void *
+mg_calloc_ex(size_t count,
+size_t size,
+struct mg_context *ctx,
+const char *file,
+unsigned line)
+{
+void *data = mg_malloc_ex(size * count, ctx, file, line);
+
+if (data) {
+memset(data, 0, size * count);
+}
+return data;
+}
+
+
+static void
+mg_free_ex(void *memory, const char *file, unsigned line)
+{
+void *data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
+
+
+#if defined(MEMORY_DEBUGGING)
+char mallocStr[256];
+#else
+(void)file;
+(void)line;
+#endif
+
+if (memory) {
+uintptr_t size = ((uintptr_t *)data)[0];
+struct mg_memory_stat *mstat =
+(struct mg_memory_stat *)(((uintptr_t *)data)[1]);
+mg_atomic_add(&mstat->totalMemUsed, -(int64_t)size);
+mg_atomic_dec(&mstat->blockCount);
+#if defined(MEMORY_DEBUGGING)
+sprintf(mallocStr,
+"MEM: %p %5lu free    %7lu %4lu --- %s:%u\n",
+memory,
+(unsigned long)size,
+(unsigned long)mstat->totalMemUsed,
+(unsigned long)mstat->blockCount,
+file,
+line);
+#if defined(_WIN32)
+OutputDebugStringA(mallocStr);
+#else
+DEBUG_TRACE("%s", mallocStr);
+#endif
+#endif
+free(data);
+}
+}
+
+
+static void *
+mg_realloc_ex(void *memory,
+size_t newsize,
+struct mg_context *ctx,
+const char *file,
+unsigned line)
+{
+void *data;
+void *_realloc;
+uintptr_t oldsize;
+
+#if defined(MEMORY_DEBUGGING)
+char mallocStr[256];
+#else
+(void)file;
+(void)line;
+#endif
+
+if (newsize) {
+if (memory) {
+/* Reallocate existing block */
+struct mg_memory_stat *mstat;
+data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
+oldsize = ((uintptr_t *)data)[0];
+mstat = (struct mg_memory_stat *)((uintptr_t *)data)[1];
+_realloc = realloc(data, newsize + 2 * sizeof(uintptr_t));
+if (_realloc) {
+data = _realloc;
+mg_atomic_add(&mstat->totalMemUsed, -(int64_t)oldsize);
+#if defined(MEMORY_DEBUGGING)
+sprintf(mallocStr,
+"MEM: %p %5lu r-free  %7lu %4lu --- %s:%u\n",
+memory,
+(unsigned long)oldsize,
+(unsigned long)mstat->totalMemUsed,
+(unsigned long)mstat->blockCount,
+file,
+line);
+#if defined(_WIN32)
+OutputDebugStringA(mallocStr);
+#else
+DEBUG_TRACE("%s", mallocStr);
+#endif
+#endif
+mg_atomic_add(&mstat->totalMemUsed, (int64_t)newsize);
+#if defined(MEMORY_DEBUGGING)
+sprintf(mallocStr,
+"MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
+memory,
+(unsigned long)newsize,
+(unsigned long)mstat->totalMemUsed,
+(unsigned long)mstat->blockCount,
+file,
+line);
+#if defined(_WIN32)
+OutputDebugStringA(mallocStr);
+#else
+DEBUG_TRACE("%s", mallocStr);
+#endif
+#endif
+*(uintptr_t *)data = newsize;
+data = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
+} else {
+#if defined(MEMORY_DEBUGGING)
+#if defined(_WIN32)
+OutputDebugStringA("MEM: realloc failed\n");
+#else
+DEBUG_TRACE("%s", "MEM: realloc failed\n");
+#endif
+#endif
+return _realloc;
+}
+} else {
+/* Allocate new block */
+data = mg_malloc_ex(newsize, ctx, file, line);
+}
+} else {
+/* Free existing block */
+data = 0;
+mg_free_ex(memory, file, line);
+}
+
+return data;
+}
+
+#define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__)
+#define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__)
+#define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__)
+#define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
+
+#define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__)
+#define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__)
+#define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__)
+
+#else /* USE_SERVER_STATS */
+
+static __inline void *
+mg_malloc(size_t a)
+{
+return malloc(a);
+}
+
+static __inline void *
+mg_calloc(size_t a, size_t b)
+{
+return calloc(a, b);
+}
+
+static __inline void *
+mg_realloc(void *a, size_t b)
+{
+return realloc(a, b);
+}
+
+static __inline void
+mg_free(void *a)
+{
+free(a);
+}
+
+#define mg_malloc_ctx(a, c) mg_malloc(a)
+#define mg_calloc_ctx(a, b, c) mg_calloc(a, b)
+#define mg_realloc_ctx(a, b, c) mg_realloc(a, b)
+#define mg_free_ctx(a, c) mg_free(a)
+
+#endif /* USE_SERVER_STATS */
+
+
+static void mg_vsnprintf(const struct mg_connection *conn,
+int *truncated,
+char *buf,
+size_t buflen,
+const char *fmt,
+va_list ap);
+
+static void mg_snprintf(const struct mg_connection *conn,
+int *truncated,
+char *buf,
+size_t buflen,
+PRINTF_FORMAT_STRING(const char *fmt),
+...) PRINTF_ARGS(5, 6);
+
+/* This following lines are just meant as a reminder to use the mg-functions
+ * for memory management */
+#if defined(malloc)
+#undef malloc
+#endif
+#if defined(calloc)
+#undef calloc
+#endif
+#if defined(realloc)
+#undef realloc
+#endif
+#if defined(free)
+#undef free
+#endif
+#if defined(snprintf)
+#undef snprintf
+#endif
+#if defined(vsnprintf)
+#undef vsnprintf
+#endif
+#define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
+#define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
+#define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
+#define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free
+#define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf
+#if defined(_WIN32)
+/* vsnprintf must not be used in any system,
+ * but this define only works well for Windows. */
+#define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
+#endif
+
+
+/* mg_init_library counter */
+static int mg_init_library_called = 0;
+
+#if !defined(NO_SSL)
+static int mg_ssl_initialized = 0;
+#endif
+
+static pthread_key_t sTlsKey; /* Thread local storage index */
+static int thread_idx_max = 0;
+
+#if defined(MG_LEGACY_INTERFACE)
+#define MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE
+#endif
+
+struct mg_workerTLS {
+int is_master;
+unsigned long thread_idx;
+#if defined(_WIN32)
+HANDLE pthread_cond_helper_mutex;
+struct mg_workerTLS *next_waiting_thread;
+#endif
+#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
+char txtbuf[4];
+#endif
+};
+
+
+#if defined(__GNUC__) || defined(__MINGW32__)
+/* Show no warning in case system functions are not used. */
+#if GCC_VERSION >= 40500
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif /* GCC_VERSION >= 40500 */
+#endif /* defined(__GNUC__) || defined(__MINGW32__) */
+#if defined(__clang__)
+/* Show no warning in case system functions are not used. */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
+
+
+/* Get a unique thread ID as unsigned long, independent from the data type
+ * of thread IDs defined by the operating system API.
+ * If two calls to mg_current_thread_id  return the same value, they calls
+ * are done from the same thread. If they return different values, they are
+ * done from different threads. (Provided this function is used in the same
+ * process context and threads are not repeatedly created and deleted, but
+ * CivetWeb does not do that).
+ * This function must match the signature required for SSL id callbacks:
+ * CRYPTO_set_id_callback
+ */
+FUNCTION_MAY_BE_UNUSED
+static unsigned long
+mg_current_thread_id(void)
+{
+#if defined(_WIN32)
+return GetCurrentThreadId();
+#else
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code"
+/* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
+ * or not, so one of the two conditions will be unreachable by construction.
+ * Unfortunately the C standard does not define a way to check this at
+ * compile time, since the #if preprocessor conditions can not use the sizeof
+ * operator as an argument. */
+#endif
+
+if (sizeof(pthread_t) > sizeof(unsigned long)) {
+/* This is the problematic case for CRYPTO_set_id_callback:
+                * The OS pthread_t can not be cast to unsigned long. */
+struct mg_workerTLS *tls =
+(struct mg_workerTLS *)pthread_getspecific(sTlsKey);
+if (tls == NULL) {
+/* SSL called from an unknown thread: Create some thread index.
+                        */
+tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
+tls->is_master = -2; /* -2 means "3rd party thread" */
+tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
+pthread_setspecific(sTlsKey, tls);
+}
+return tls->thread_idx;
+} else {
+/* pthread_t may be any data type, so a simple cast to unsigned long
+                * can rise a warning/error, depending on the platform.
+                * Here memcpy is used as an anything-to-anything cast. */
+unsigned long ret = 0;
+pthread_t t = pthread_self();
+memcpy(&ret, &t, sizeof(pthread_t));
+return ret;
+}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#endif
+}
+
+
+FUNCTION_MAY_BE_UNUSED
+static uint64_t
+mg_get_current_time_ns(void)
+{
+struct timespec tsnow;
+clock_gettime(CLOCK_REALTIME, &tsnow);
+return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
+}
+
+
+#if defined(__GNUC__)
+/* Show no warning in case system functions are not used. */
+#if GCC_VERSION >= 40500
+#pragma GCC diagnostic pop
+#endif /* GCC_VERSION >= 40500 */
+#endif /* defined(__GNUC__) */
+#if defined(__clang__)
+/* Show no warning in case system functions are not used. */
+#pragma clang diagnostic pop
+#endif
+
+
+#if defined(NEED_DEBUG_TRACE_FUNC)
+static void
+DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
+{
+va_list args;
+uint64_t nsnow;
+static uint64_t nslast;
+struct timespec tsnow;
+
+/* Get some operating system independent thread id */
+unsigned long thread_id = mg_current_thread_id();
+
+clock_gettime(CLOCK_REALTIME, &tsnow);
+nsnow = ((uint64_t)tsnow.tv_sec) * ((uint64_t)1000000000)
++ ((uint64_t)tsnow.tv_nsec);
+
+if (!nslast) {
+nslast = nsnow;
+}
+
+flockfile(stdout);
+printf("*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ",
+(unsigned long)tsnow.tv_sec,
+(unsigned long)tsnow.tv_nsec,
+nsnow - nslast,
+thread_id,
+func,
+line);
+va_start(args, fmt);
+vprintf(fmt, args);
+va_end(args);
+putchar('\n');
+fflush(stdout);
+funlockfile(stdout);
+nslast = nsnow;
+}
+#endif /* NEED_DEBUG_TRACE_FUNC */
+
+
+#define MD5_STATIC static
+#include "md5.inl"
+
+/* Darwin prior to 7.0 and Win32 do not have socklen_t */
+#if defined(NO_SOCKLEN_T)
+typedef int socklen_t;
+#endif /* NO_SOCKLEN_T */
+
+#define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
+
+#if !defined(MSG_NOSIGNAL)
+#define MSG_NOSIGNAL (0)
+#endif
+
+
+#if defined(NO_SSL)
+typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
+typedef struct SSL_CTX SSL_CTX;
+#else
+#if defined(NO_SSL_DL)
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/engine.h>
+#include <openssl/conf.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/opensslv.h>
+
+#if defined(WOLFSSL_VERSION)
+/* Additional defines for WolfSSL, see
+ * https://github.com/civetweb/civetweb/issues/583 */
+#include "wolfssl_extras.inl"
+#endif
+
+#else
+
+/* SSL loaded dynamically from DLL.
+ * I put the prototypes here to be independent from OpenSSL source
+ * installation. */
+
+typedef struct ssl_st SSL;
+typedef struct ssl_method_st SSL_METHOD;
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+typedef struct x509_name X509_NAME;
+typedef struct asn1_integer ASN1_INTEGER;
+typedef struct bignum BIGNUM;
+typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
+typedef struct evp_md EVP_MD;
+typedef struct x509 X509;
+
+
+#define SSL_CTRL_OPTIONS (32)
+#define SSL_CTRL_CLEAR_OPTIONS (77)
+#define SSL_CTRL_SET_ECDH_AUTO (94)
+
+#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
+#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
+#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
+
+#define SSL_VERIFY_NONE (0)
+#define SSL_VERIFY_PEER (1)
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
+#define SSL_VERIFY_CLIENT_ONCE (4)
+#define SSL_OP_ALL ((long)(0x80000BFFUL))
+#define SSL_OP_NO_SSLv2 (0x01000000L)
+#define SSL_OP_NO_SSLv3 (0x02000000L)
+#define SSL_OP_NO_TLSv1 (0x04000000L)
+#define SSL_OP_NO_TLSv1_2 (0x08000000L)
+#define SSL_OP_NO_TLSv1_1 (0x10000000L)
+#define SSL_OP_SINGLE_DH_USE (0x00100000L)
+#define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L)
+#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000L)
+#define SSL_OP_NO_COMPRESSION (0x00020000L)
+
+#define SSL_CB_HANDSHAKE_START (0x10)
+#define SSL_CB_HANDSHAKE_DONE (0x20)
+
+#define SSL_ERROR_NONE (0)
+#define SSL_ERROR_SSL (1)
+#define SSL_ERROR_WANT_READ (2)
+#define SSL_ERROR_WANT_WRITE (3)
+#define SSL_ERROR_WANT_X509_LOOKUP (4)
+#define SSL_ERROR_SYSCALL (5) /* see errno */
+#define SSL_ERROR_ZERO_RETURN (6)
+#define SSL_ERROR_WANT_CONNECT (7)
+#define SSL_ERROR_WANT_ACCEPT (8)
+
+#define TLSEXT_TYPE_server_name (0)
+#define TLSEXT_NAMETYPE_host_name (0)
+#define SSL_TLSEXT_ERR_OK (0)
+#define SSL_TLSEXT_ERR_ALERT_WARNING (1)
+#define SSL_TLSEXT_ERR_ALERT_FATAL (2)
+#define SSL_TLSEXT_ERR_NOACK (3)
+
+struct ssl_func {
+const char *name;  /* SSL function name */
+void (*ptr)(void); /* Function pointer */
+};
+
+
+#if defined(OPENSSL_API_1_1)
+
+#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
+#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
+#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
+#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
+#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
+#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
+#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
+#define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
+#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
+#define TLS_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
+#define OPENSSL_init_ssl                                                       
\
+       (*(int (*)(uint64_t opts,                                               
   \
+                  const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10].ptr)
+#define SSL_CTX_use_PrivateKey_file                                            
\
+       (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
+#define SSL_CTX_use_certificate_file                                           
\
+       (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
+#define SSL_CTX_set_default_passwd_cb                                          
\
+       (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
+#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
+#define SSL_CTX_use_certificate_chain_file                                     
\
+       (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr)
+#define TLS_client_method (*(SSL_METHOD * (*)(void))ssl_sw[16].ptr)
+#define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr)
+#define SSL_CTX_set_verify                                                     
\
+       (*(void (*)(SSL_CTX *,                                                  
   \
+                   int,                                                        
   \
+                   int (*verify_callback)(int, X509_STORE_CTX 
*)))ssl_sw[18].ptr)
+#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr)
+#define SSL_CTX_load_verify_locations                                          
\
+       (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr)
+#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr)
+#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr)
+#define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[23].ptr)
+#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr)
+#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[25].ptr)
+#define SSL_CIPHER_get_name                                                    
\
+       (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr)
+#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr)
+#define SSL_CTX_set_session_id_context                                         
\
+       (*(int (*)(SSL_CTX *, const unsigned char *, unsigned 
int))ssl_sw[28].ptr)
+#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr)
+#define SSL_CTX_set_cipher_list                                                
\
+       (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr)
+#define SSL_CTX_set_options                                                    
\
+       (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr)
+#define SSL_CTX_set_info_callback                                              
\
+       (*(void (*)(SSL_CTX * ctx,                                              
   \
+                   void (*callback)(SSL * s, int, int)))ssl_sw[32].ptr)
+#define SSL_get_ex_data (*(char *(*)(SSL *, int))ssl_sw[33].ptr)
+#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
+#define SSL_CTX_callback_ctrl                                                  
\
+       (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr)
+#define SSL_get_servername                                                     
\
+       (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr)
+#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *))ssl_sw[37].ptr)
+
+#define SSL_CTX_clear_options(ctx, op)                                         
\
+       SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
+#define SSL_CTX_set_ecdh_auto(ctx, onoff)                                      
\
+       SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
+
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb)                        
\
+       SSL_CTX_callback_ctrl(ctx,                                              
   \
+                             SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                
   \
+                             (void (*)(void))cb)
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)                            
\
+       SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg)
+
+#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
+#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
+
+#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
+#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
+
+#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr)
+#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr)
+#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[2].ptr)
+#define CONF_modules_unload (*(void (*)(int))crypto_sw[3].ptr)
+#define X509_free (*(void (*)(X509 *))crypto_sw[4].ptr)
+#define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[5].ptr)
+#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[6].ptr)
+#define X509_NAME_oneline                                                      
\
+       (*(char *(*)(X509_NAME *, char *, int))crypto_sw[7].ptr)
+#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[8].ptr)
+#define EVP_get_digestbyname                                                   
\
+       (*(const EVP_MD *(*)(const char *))crypto_sw[9].ptr)
+#define EVP_Digest                                                             
\
+       (*(int (*)(                                                             
   \
+           const void *, size_t, void *, unsigned int *, const EVP_MD *, void 
*)) \
+             crypto_sw[10].ptr)
+#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[11].ptr)
+#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[12].ptr)
+#define ASN1_INTEGER_to_BN                                                     
\
+       (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn))crypto_sw[13].ptr)
+#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[14].ptr)
+#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[15].ptr)
+
+#define OPENSSL_free(a) CRYPTO_free(a)
+
+
+/* init_ssl_ctx() function updates this array.
+ * It loads SSL library dynamically and changes NULLs to the actual addresses
+ * of respective functions. The macros above (like SSL_connect()) are really
+ * just calling these functions indirectly via the pointer. */
+static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
+{"SSL_accept", NULL},
+{"SSL_connect", NULL},
+{"SSL_read", NULL},
+{"SSL_write", NULL},
+{"SSL_get_error", NULL},
+{"SSL_set_fd", NULL},
+{"SSL_new", NULL},
+{"SSL_CTX_new", NULL},
+{"TLS_server_method", NULL},
+{"OPENSSL_init_ssl", NULL},
+{"SSL_CTX_use_PrivateKey_file", NULL},
+{"SSL_CTX_use_certificate_file", NULL},
+{"SSL_CTX_set_default_passwd_cb", NULL},
+{"SSL_CTX_free", NULL},
+{"SSL_CTX_use_certificate_chain_file", NULL},
+{"TLS_client_method", NULL},
+{"SSL_pending", NULL},
+{"SSL_CTX_set_verify", NULL},
+{"SSL_shutdown", NULL},
+{"SSL_CTX_load_verify_locations", NULL},
+{"SSL_CTX_set_default_verify_paths", NULL},
+{"SSL_CTX_set_verify_depth", NULL},
+{"SSL_get_peer_certificate", NULL},
+{"SSL_get_version", NULL},
+{"SSL_get_current_cipher", NULL},
+{"SSL_CIPHER_get_name", NULL},
+{"SSL_CTX_check_private_key", NULL},
+{"SSL_CTX_set_session_id_context", NULL},
+{"SSL_CTX_ctrl", NULL},
+{"SSL_CTX_set_cipher_list", NULL},
+{"SSL_CTX_set_options", NULL},
+{"SSL_CTX_set_info_callback", NULL},
+{"SSL_get_ex_data", NULL},
+{"SSL_set_ex_data", NULL},
+{"SSL_CTX_callback_ctrl", NULL},
+{"SSL_get_servername", NULL},
+{"SSL_set_SSL_CTX", NULL},
+{NULL, NULL}};
+
+
+/* Similar array as ssl_sw. These functions could be located in different
+ * lib. */
+static struct ssl_func crypto_sw[] = {{"ERR_get_error", NULL},
+{"ERR_error_string", NULL},
+{"ERR_remove_state", NULL},
+{"CONF_modules_unload", NULL},
+{"X509_free", NULL},
+{"X509_get_subject_name", NULL},
+{"X509_get_issuer_name", NULL},
+{"X509_NAME_oneline", NULL},
+{"X509_get_serialNumber", NULL},
+{"EVP_get_digestbyname", NULL},
+{"EVP_Digest", NULL},
+{"i2d_X509", NULL},
+{"BN_bn2hex", NULL},
+{"ASN1_INTEGER_to_BN", NULL},
+{"BN_free", NULL},
+{"CRYPTO_free", NULL},
+{NULL, NULL}};
+#else
+
+#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
+#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
+#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
+#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
+#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
+#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
+#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
+#define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
+#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
+#define SSLv23_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
+#define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
+#define SSL_CTX_use_PrivateKey_file                                            
\
+       (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
+#define SSL_CTX_use_certificate_file                                           
\
+       (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
+#define SSL_CTX_set_default_passwd_cb                                          
\
+       (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
+#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
+#define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
+#define SSL_CTX_use_certificate_chain_file                                     
\
+       (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
+#define SSLv23_client_method (*(SSL_METHOD * (*)(void))ssl_sw[17].ptr)
+#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
+#define SSL_CTX_set_verify                                                     
\
+       (*(void (*)(SSL_CTX *,                                                  
   \
+                   int,                                                        
   \
+                   int (*verify_callback)(int, X509_STORE_CTX 
*)))ssl_sw[19].ptr)
+#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
+#define SSL_CTX_load_verify_locations                                          
\
+       (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
+#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
+#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
+#define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[24].ptr)
+#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
+#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[26].ptr)
+#define SSL_CIPHER_get_name                                                    
\
+       (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
+#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
+#define SSL_CTX_set_session_id_context                                         
\
+       (*(int (*)(SSL_CTX *, const unsigned char *, unsigned 
int))ssl_sw[29].ptr)
+#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
+#define SSL_CTX_set_cipher_list                                                
\
+       (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
+#define SSL_CTX_set_info_callback                                              
\
+       (*(void (*)(SSL_CTX *, void (*callback)(SSL * s, int, 
int)))ssl_sw[32].ptr)
+#define SSL_get_ex_data (*(char *(*)(SSL *, int))ssl_sw[33].ptr)
+#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
+#define SSL_CTX_callback_ctrl                                                  
\
+       (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr)
+#define SSL_get_servername                                                     
\
+       (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr)
+#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *))ssl_sw[37].ptr)
+
+#define SSL_CTX_set_options(ctx, op)                                           
\
+       SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
+#define SSL_CTX_clear_options(ctx, op)                                         
\
+       SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
+#define SSL_CTX_set_ecdh_auto(ctx, onoff)                                      
\
+       SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
+
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb)                        
\
+       SSL_CTX_callback_ctrl(ctx,                                              
   \
+                             SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                
   \
+                             (void (*)(void))cb)
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)                            
\
+       SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg)
+
+#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
+#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
+
+#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
+#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
+
+#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
+#define CRYPTO_set_locking_callback                                            
\
+       (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
+#define CRYPTO_set_id_callback                                                 
\
+       (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
+#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
+#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
+#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
+#define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
+#define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
+#define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
+#define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
+#define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
+#define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr)
+#define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[12].ptr)
+#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[13].ptr)
+#define X509_NAME_oneline                                                      
\
+       (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr)
+#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[15].ptr)
+#define i2c_ASN1_INTEGER                                                       
\
+       (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr)
+#define EVP_get_digestbyname                                                   
\
+       (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr)
+#define EVP_Digest                                                             
\
+       (*(int (*)(                                                             
   \
+           const void *, size_t, void *, unsigned int *, const EVP_MD *, void 
*)) \
+             crypto_sw[18].ptr)
+#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr)
+#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr)
+#define ASN1_INTEGER_to_BN                                                     
\
+       (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn))crypto_sw[21].ptr)
+#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr)
+#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr)
+
+#define OPENSSL_free(a) CRYPTO_free(a)
+
+/* init_ssl_ctx() function updates this array.
+ * It loads SSL library dynamically and changes NULLs to the actual addresses
+ * of respective functions. The macros above (like SSL_connect()) are really
+ * just calling these functions indirectly via the pointer. */
+static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
+{"SSL_accept", NULL},
+{"SSL_connect", NULL},
+{"SSL_read", NULL},
+{"SSL_write", NULL},
+{"SSL_get_error", NULL},
+{"SSL_set_fd", NULL},
+{"SSL_new", NULL},
+{"SSL_CTX_new", NULL},
+{"SSLv23_server_method", NULL},
+{"SSL_library_init", NULL},
+{"SSL_CTX_use_PrivateKey_file", NULL},
+{"SSL_CTX_use_certificate_file", NULL},
+{"SSL_CTX_set_default_passwd_cb", NULL},
+{"SSL_CTX_free", NULL},
+{"SSL_load_error_strings", NULL},
+{"SSL_CTX_use_certificate_chain_file", NULL},
+{"SSLv23_client_method", NULL},
+{"SSL_pending", NULL},
+{"SSL_CTX_set_verify", NULL},
+{"SSL_shutdown", NULL},
+{"SSL_CTX_load_verify_locations", NULL},
+{"SSL_CTX_set_default_verify_paths", NULL},
+{"SSL_CTX_set_verify_depth", NULL},
+{"SSL_get_peer_certificate", NULL},
+{"SSL_get_version", NULL},
+{"SSL_get_current_cipher", NULL},
+{"SSL_CIPHER_get_name", NULL},
+{"SSL_CTX_check_private_key", NULL},
+{"SSL_CTX_set_session_id_context", NULL},
+{"SSL_CTX_ctrl", NULL},
+{"SSL_CTX_set_cipher_list", NULL},
+{"SSL_CTX_set_info_callback", NULL},
+{"SSL_get_ex_data", NULL},
+{"SSL_set_ex_data", NULL},
+{"SSL_CTX_callback_ctrl", NULL},
+{"SSL_get_servername", NULL},
+{"SSL_set_SSL_CTX", NULL},
+{NULL, NULL}};
+
+
+/* Similar array as ssl_sw. These functions could be located in different
+ * lib. */
+static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
+{"CRYPTO_set_locking_callback", NULL},
+{"CRYPTO_set_id_callback", NULL},
+{"ERR_get_error", NULL},
+{"ERR_error_string", NULL},
+{"ERR_remove_state", NULL},
+{"ERR_free_strings", NULL},
+{"ENGINE_cleanup", NULL},
+{"CONF_modules_unload", NULL},
+{"CRYPTO_cleanup_all_ex_data", NULL},
+{"EVP_cleanup", NULL},
+{"X509_free", NULL},
+{"X509_get_subject_name", NULL},
+{"X509_get_issuer_name", NULL},
+{"X509_NAME_oneline", NULL},
+{"X509_get_serialNumber", NULL},
+{"i2c_ASN1_INTEGER", NULL},
+{"EVP_get_digestbyname", NULL},
+{"EVP_Digest", NULL},
+{"i2d_X509", NULL},
+{"BN_bn2hex", NULL},
+{"ASN1_INTEGER_to_BN", NULL},
+{"BN_free", NULL},
+{"CRYPTO_free", NULL},
+{NULL, NULL}};
+#endif /* OPENSSL_API_1_1 */
+#endif /* NO_SSL_DL */
+#endif /* NO_SSL */
+
+
+#if !defined(NO_CACHING)
+static const char *month_names[] = {"Jan",
+"Feb",
+"Mar",
+"Apr",
+"May",
+"Jun",
+"Jul",
+"Aug",
+"Sep",
+"Oct",
+"Nov",
+"Dec"};
+#endif /* !NO_CACHING */
+
+/* Unified socket address. For IPv6 support, add IPv6 address structure in
+ * the
+ * union u. */
+union usa {
+struct sockaddr sa;
+struct sockaddr_in sin;
+#if defined(USE_IPV6)
+struct sockaddr_in6 sin6;
+#endif
+};
+
+/* Describes a string (chunk of memory). */
+struct vec {
+const char *ptr;
+size_t len;
+};
+
+struct mg_file_stat {
+/* File properties filled by mg_stat: */
+uint64_t size;
+time_t last_modified;
+int is_directory; /* Set to 1 if mg_stat is called for a directory */
+int is_gzipped;   /* Set to 1 if the content is gzipped, in which
+                          * case we need a "Content-Eencoding: gzip" header */
+int location;     /* 0 = nowhere, 1 = on disk, 2 = in memory */
+};
+
+struct mg_file_in_memory {
+char *p;
+uint32_t pos;
+char mode;
+};
+
+struct mg_file_access {
+/* File properties filled by mg_fopen: */
+FILE *fp;
+#if defined(MG_USE_OPEN_FILE)
+/* TODO (low): Remove obsolete "file in memory" implementation.
+        * In an "early 2017" discussion at Google groups
+        * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
+        * we decided to get rid of this feature (after some fade-out
+        * phase). */
+const char *membuf;
+#endif
+};
+
+struct mg_file {
+struct mg_file_stat stat;
+struct mg_file_access access;
+};
+
+#if defined(MG_USE_OPEN_FILE)
+
+#define STRUCT_FILE_INITIALIZER                                                
\
+       {                                                                       
   \
+               {                                                               
       \
+                       (uint64_t)0, (time_t)0, 0, 0, 0                         
           \
+               }                                                               
       \
+               ,                                                               
       \
+               {                                                               
       \
+                       (FILE *) NULL, (const char *)NULL                       
           \
+               }                                                               
       \
+       }
+
+#else
+
+#define STRUCT_FILE_INITIALIZER                                                
\
+       {                                                                       
   \
+               {                                                               
       \
+                       (uint64_t)0, (time_t)0, 0, 0, 0                         
           \
+               }                                                               
       \
+               ,                                                               
       \
+               {                                                               
       \
+                       (FILE *) NULL                                           
           \
+               }                                                               
       \
+       }
+
+#endif
+
+
+/* Describes listening socket, or socket which was accept()-ed by the master
+ * thread and queued for future handling by the worker thread. */
+struct socket {
+SOCKET sock;             /* Listening socket */
+union usa lsa;           /* Local socket address */
+union usa rsa;           /* Remote socket address */
+unsigned char is_ssl;    /* Is port SSL-ed */
+unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
+                                 * port */
+unsigned char in_use;    /* Is valid */
+};
+
+
+/* Enum const for all options must be in sync with
+ * static struct mg_option config_options[]
+ * This is tested in the unit test (test/private.c)
+ * "Private Config Options"
+ */
+enum {
+/* Once for each server */
+LISTENING_PORTS,
+NUM_THREADS,
+RUN_AS_USER,
+CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
+                         * socket option typedef TCP_NODELAY. */
+MAX_REQUEST_SIZE,
+LINGER_TIMEOUT,
+#if defined(__linux__)
+ALLOW_SENDFILE_CALL,
+#endif
+#if defined(_WIN32)
+CASE_SENSITIVE_FILES,
+#endif
+THROTTLE,
+ACCESS_LOG_FILE,
+ERROR_LOG_FILE,
+ENABLE_KEEP_ALIVE,
+REQUEST_TIMEOUT,
+KEEP_ALIVE_TIMEOUT,
+#if defined(USE_WEBSOCKET)
+WEBSOCKET_TIMEOUT,
+ENABLE_WEBSOCKET_PING_PONG,
+#endif
+DECODE_URL,
+#if defined(USE_LUA)
+LUA_BACKGROUND_SCRIPT,
+LUA_BACKGROUND_SCRIPT_PARAMS,
+#endif
+#if defined(USE_TIMERS)
+CGI_TIMEOUT,
+#endif
+
+/* Once for each domain */
+DOCUMENT_ROOT,
+CGI_EXTENSIONS,
+CGI_ENVIRONMENT,
+PUT_DELETE_PASSWORDS_FILE,
+CGI_INTERPRETER,
+PROTECT_URI,
+AUTHENTICATION_DOMAIN,
+ENABLE_AUTH_DOMAIN_CHECK,
+SSI_EXTENSIONS,
+ENABLE_DIRECTORY_LISTING,
+GLOBAL_PASSWORDS_FILE,
+INDEX_FILES,
+ACCESS_CONTROL_LIST,
+EXTRA_MIME_TYPES,
+SSL_CERTIFICATE,
+SSL_CERTIFICATE_CHAIN,
+URL_REWRITE_PATTERN,
+HIDE_FILES,
+SSL_DO_VERIFY_PEER,
+SSL_CA_PATH,
+SSL_CA_FILE,
+SSL_VERIFY_DEPTH,
+SSL_DEFAULT_VERIFY_PATHS,
+SSL_CIPHER_LIST,
+SSL_PROTOCOL_VERSION,
+SSL_SHORT_TRUST,
+
+#if defined(USE_LUA)
+LUA_PRELOAD_FILE,
+LUA_SCRIPT_EXTENSIONS,
+LUA_SERVER_PAGE_EXTENSIONS,
+#if defined(MG_EXPERIMENTAL_INTERFACES)
+LUA_DEBUG_PARAMS,
+#endif
+#endif
+#if defined(USE_DUKTAPE)
+DUKTAPE_SCRIPT_EXTENSIONS,
+#endif
+
+#if defined(USE_WEBSOCKET)
+WEBSOCKET_ROOT,
+#endif
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+LUA_WEBSOCKET_EXTENSIONS,
+#endif
+
+ACCESS_CONTROL_ALLOW_ORIGIN,
+ACCESS_CONTROL_ALLOW_METHODS,
+ACCESS_CONTROL_ALLOW_HEADERS,
+ERROR_PAGES,
+#if !defined(NO_CACHING)
+STATIC_FILE_MAX_AGE,
+#endif
+#if !defined(NO_SSL)
+STRICT_HTTPS_MAX_AGE,
+#endif
+ADDITIONAL_HEADER,
+ALLOW_INDEX_SCRIPT_SUB_RES,
+
+NUM_OPTIONS
+};
+
+
+/* Config option name, config types, default value.
+ * Must be in the same order as the enum const above.
+ */
+static const struct mg_option config_options[] = {
+
+/* Once for each server */
+{"listening_ports", MG_CONFIG_TYPE_STRING_LIST, "8080"},
+{"num_threads", MG_CONFIG_TYPE_NUMBER, "50"},
+{"run_as_user", MG_CONFIG_TYPE_STRING, NULL},
+{"tcp_nodelay", MG_CONFIG_TYPE_NUMBER, "0"},
+{"max_request_size", MG_CONFIG_TYPE_NUMBER, "16384"},
+{"linger_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
+#if defined(__linux__)
+{"allow_sendfile_call", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+#endif
+#if defined(_WIN32)
+{"case_sensitive", MG_CONFIG_TYPE_BOOLEAN, "no"},
+#endif
+{"throttle", MG_CONFIG_TYPE_STRING_LIST, NULL},
+{"access_log_file", MG_CONFIG_TYPE_FILE, NULL},
+{"error_log_file", MG_CONFIG_TYPE_FILE, NULL},
+{"enable_keep_alive", MG_CONFIG_TYPE_BOOLEAN, "no"},
+{"request_timeout_ms", MG_CONFIG_TYPE_NUMBER, "30000"},
+{"keep_alive_timeout_ms", MG_CONFIG_TYPE_NUMBER, "500"},
+#if defined(USE_WEBSOCKET)
+{"websocket_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
+{"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
+#endif
+{"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+#if defined(USE_LUA)
+{"lua_background_script", MG_CONFIG_TYPE_FILE, NULL},
+{"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL},
+#endif
+#if defined(USE_TIMERS)
+{"cgi_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
+#endif
+
+/* Once for each domain */
+{"document_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
+{"cgi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
+{"cgi_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
+{"put_delete_auth_file", MG_CONFIG_TYPE_FILE, NULL},
+{"cgi_interpreter", MG_CONFIG_TYPE_FILE, NULL},
+{"protect_uri", MG_CONFIG_TYPE_STRING_LIST, NULL},
+{"authentication_domain", MG_CONFIG_TYPE_STRING, "mydomain.com"},
+{"enable_auth_domain_check", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+{"ssi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
+{"enable_directory_listing", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+{"global_auth_file", MG_CONFIG_TYPE_FILE, NULL},
+{"index_files",
+MG_CONFIG_TYPE_STRING_LIST,
+#if defined(USE_LUA)
+"index.xhtml,index.html,index.htm,"
+"index.lp,index.lsp,index.lua,index.cgi,"
+"index.shtml,index.php"},
+#else
+"index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
+#endif
+{"access_control_list", MG_CONFIG_TYPE_STRING_LIST, NULL},
+{"extra_mime_types", MG_CONFIG_TYPE_STRING_LIST, NULL},
+{"ssl_certificate", MG_CONFIG_TYPE_FILE, NULL},
+{"ssl_certificate_chain", MG_CONFIG_TYPE_FILE, NULL},
+{"url_rewrite_patterns", MG_CONFIG_TYPE_STRING_LIST, NULL},
+{"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
+
+{"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"},
+
+{"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL},
+{"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL},
+{"ssl_verify_depth", MG_CONFIG_TYPE_NUMBER, "9"},
+{"ssl_default_verify_paths", MG_CONFIG_TYPE_BOOLEAN, "yes"},
+{"ssl_cipher_list", MG_CONFIG_TYPE_STRING, NULL},
+{"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "0"},
+{"ssl_short_trust", MG_CONFIG_TYPE_BOOLEAN, "no"},
+
+#if defined(USE_LUA)
+{"lua_preload_file", MG_CONFIG_TYPE_FILE, NULL},
+{"lua_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
+{"lua_server_page_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
+#if defined(MG_EXPERIMENTAL_INTERFACES)
+{"lua_debug", MG_CONFIG_TYPE_STRING, NULL},
+#endif
+#endif
+#if defined(USE_DUKTAPE)
+/* The support for duktape is still in alpha version state.
+     * The name of this config option might change. */
+{"duktape_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
+#endif
+
+#if defined(USE_WEBSOCKET)
+{"websocket_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
+#endif
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+{"lua_websocket_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
+#endif
+{"access_control_allow_origin", MG_CONFIG_TYPE_STRING, "*"},
+{"access_control_allow_methods", MG_CONFIG_TYPE_STRING, "*"},
+{"access_control_allow_headers", MG_CONFIG_TYPE_STRING, "*"},
+{"error_pages", MG_CONFIG_TYPE_DIRECTORY, NULL},
+#if !defined(NO_CACHING)
+{"static_file_max_age", MG_CONFIG_TYPE_NUMBER, "3600"},
+#endif
+#if !defined(NO_SSL)
+{"strict_transport_security_max_age", MG_CONFIG_TYPE_NUMBER, NULL},
+#endif
+{"additional_header", MG_CONFIG_TYPE_STRING_MULTILINE, NULL},
+{"allow_index_script_resource", MG_CONFIG_TYPE_BOOLEAN, "no"},
+
+{NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}};
+
+
+/* Check if the config_options and the corresponding enum have compatible
+ * sizes. */
+mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
+== (NUM_OPTIONS + 1),
+"config_options and enum not sync");
+
+
+enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
+
+
+struct mg_handler_info {
+/* Name/Pattern of the URI. */
+char *uri;
+size_t uri_len;
+
+/* handler type */
+int handler_type;
+
+/* Handler for http/https or authorization requests. */
+mg_request_handler handler;
+unsigned int refcount;
+pthread_mutex_t refcount_mutex; /* Protects refcount */
+pthread_cond_t
+refcount_cond; /* Signaled when handler refcount is decremented */
+
+/* Handler for ws/wss (websocket) requests. */
+mg_websocket_connect_handler connect_handler;
+mg_websocket_ready_handler ready_handler;
+mg_websocket_data_handler data_handler;
+mg_websocket_close_handler close_handler;
+
+/* accepted subprotocols for ws/wss requests. */
+struct mg_websocket_subprotocols *subprotocols;
+
+/* Handler for authorization requests */
+mg_authorization_handler auth_handler;
+
+/* User supplied argument for the handler function. */
+void *cbdata;
+
+/* next handler in a linked list */
+struct mg_handler_info *next;
+};
+
+
+enum {
+CONTEXT_INVALID,
+CONTEXT_SERVER,
+CONTEXT_HTTP_CLIENT,
+CONTEXT_WS_CLIENT
+};
+
+
+struct mg_domain_context {
+SSL_CTX *ssl_ctx;                 /* SSL context */
+char *config[NUM_OPTIONS];        /* Civetweb configuration parameters */
+struct mg_handler_info *handlers; /* linked list of uri handlers */
+
+/* Server nonce */
+uint64_t auth_nonce_mask;  /* Mask for all nonce values */
+unsigned long nonce_count; /* Used nonces, used for authentication */
+
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+/* linked list of shared lua websockets */
+struct mg_shared_lua_websocket_list *shared_lua_websockets;
+#endif
+
+/* Linked list of domains */
+struct mg_domain_context *next;
+};
+
+
+struct mg_context {
+
+/* Part 1 - Physical context:
+        * This holds threads, ports, timeouts, ...
+        * set for the entire server, independent from the
+        * addressed hostname.
+        */
+
+/* Connection related */
+int context_type; /* See CONTEXT_* above */
+
+struct socket *listening_sockets;
+struct pollfd *listening_socket_fds;
+unsigned int num_listening_sockets;
+
+struct mg_connection *worker_connections; /* The connection struct, pre-
+                                                  * allocated for each worker 
*/
+
+#if defined(USE_SERVER_STATS)
+int active_connections;
+int max_connections;
+int64_t total_connections;
+int64_t total_requests;
+int64_t total_data_read;
+int64_t total_data_written;
+#endif
+
+/* Thread related */
+volatile int stop_flag;       /* Should we stop event loop */
+pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
+
+pthread_t masterthreadid; /* The master thread ID */
+unsigned int
+cfg_worker_threads;      /* The number of configured worker threads. */
+pthread_t *worker_threadids; /* The worker thread IDs */
+
+/* Connection to thread dispatching */
+#if defined(ALTERNATIVE_QUEUE)
+struct socket *client_socks;
+void **client_wait_events;
+#else
+struct socket queue[MGSQLEN]; /* Accepted sockets */
+volatile int sq_head;         /* Head of the socket queue */
+volatile int sq_tail;         /* Tail of the socket queue */
+pthread_cond_t sq_full;       /* Signaled when socket is produced */
+pthread_cond_t sq_empty;      /* Signaled when socket is consumed */
+#endif
+
+/* Memory related */
+unsigned int max_request_size; /* The max request size */
+
+#if defined(USE_SERVER_STATS)
+struct mg_memory_stat ctx_memory;
+#endif
+
+/* Operating system related */
+char *systemName;  /* What operating system is running */
+time_t start_time; /* Server start time, used for authentication
+                           * and for diagnstics. */
+
+#if defined(USE_TIMERS)
+struct ttimers *timers;
+#endif
+
+/* Lua specific: Background operations and shared websockets */
+#if defined(USE_LUA)
+void *lua_background_state;
+#endif
+
+/* Server nonce */
+pthread_mutex_t nonce_mutex; /* Protects nonce_count */
+
+/* Server callbacks */
+struct mg_callbacks callbacks; /* User-defined callback function */
+void *user_data;               /* User-defined data */
+
+/* Part 2 - Logical domain:
+        * This holds hostname, TLS certificate, document root, ...
+        * set for a domain hosted at the server.
+        * There may be multiple domains hosted at one physical server.
+        * The default domain "dd" is the first element of a list of
+        * domains.
+        */
+struct mg_domain_context dd; /* default domain */
+};
+
+
+#if defined(USE_SERVER_STATS)
+static struct mg_memory_stat mg_common_memory = {0, 0, 0};
+
+static struct mg_memory_stat *
+get_memory_stat(struct mg_context *ctx)
+{
+if (ctx) {
+return &(ctx->ctx_memory);
+}
+return &mg_common_memory;
+}
+#endif
+
+enum {
+CONNECTION_TYPE_INVALID,
+CONNECTION_TYPE_REQUEST,
+CONNECTION_TYPE_RESPONSE
+};
+
+struct mg_connection {
+int connection_type; /* see CONNECTION_TYPE_* above */
+
+struct mg_request_info request_info;
+struct mg_response_info response_info;
+
+struct mg_context *phys_ctx;
+struct mg_domain_context *dom_ctx;
+
+#if defined(USE_SERVER_STATS)
+int conn_state; /* 0 = undef, numerical value may change in different
+                        * versions. For the current definition, see
+                        * mg_get_connection_info_impl */
+#endif
+
+const char *host;         /* Host (HTTP/1.1 header or SNI) */
+SSL *ssl;                 /* SSL descriptor */
+SSL_CTX *client_ssl_ctx;  /* SSL context for client connections */
+struct socket client;     /* Connected client */
+time_t conn_birth_time;   /* Time (wall clock) when connection was
+                                  * established */
+struct timespec req_time; /* Time (since system start) when the request
+                                  * was received */
+int64_t num_bytes_sent;   /* Total bytes sent to client */
+int64_t content_len;      /* Content-Length header value */
+int64_t consumed_content; /* How many bytes of content have been read */
+int is_chunked;           /* Transfer-Encoding is chunked:
+                                  * 0 = not chunked,
+                                  * 1 = chunked, do data read yet,
+                                  * 2 = chunked, some data read,
+                                  * 3 = chunked, all data read
+                                  */
+size_t chunk_remainder;   /* Unread data from the last chunk */
+char *buf;                /* Buffer for received data */
+char *path_info;          /* PATH_INFO part of the URL */
+
+int must_close;       /* 1 if connection must be closed */
+int accept_gzip;      /* 1 if gzip encoding is accepted */
+int in_error_handler; /* 1 if in handler for user defined error
+                              * pages */
+#if defined(USE_WEBSOCKET)
+int in_websocket_handling; /* 1 if in read_websocket */
+#endif
+int handled_requests; /* Number of requests handled by this connection
+                                */
+int buf_size;         /* Buffer size */
+int request_len;      /* Size of the request + headers in a buffer */
+int data_len;         /* Total size of data in a buffer */
+int status_code;      /* HTTP reply status code, e.g. 200 */
+int throttle;         /* Throttling, bytes/sec. <= 0 means no
+                              * throttle */
+
+time_t last_throttle_time;   /* Last time throttled data was sent */
+int64_t last_throttle_bytes; /* Bytes sent this second */
+pthread_mutex_t mutex;       /* Used by mg_(un)lock_connection to ensure
+                                     * atomic transmissions for websockets */
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+void *lua_websocket_state; /* Lua_State for a websocket connection */
+#endif
+
+int thread_index; /* Thread index within ctx */
+};
+
+
+/* Directory entry */
+struct de {
+struct mg_connection *conn;
+char *file_name;
+struct mg_file_stat file;
+};
+
+
+#if defined(USE_WEBSOCKET)
+static int is_websocket_protocol(const struct mg_connection *conn);
+#else
+#define is_websocket_protocol(conn) (0)
+#endif
+
+
+#define mg_cry_internal(conn, fmt, ...)                                        
\
+       mg_cry_internal_wrap(conn, __func__, __LINE__, fmt, __VA_ARGS__)
+
+static void mg_cry_internal_wrap(const struct mg_connection *conn,
+const char *func,
+unsigned line,
+const char *fmt,
+...) PRINTF_ARGS(4, 5);
+
+
+#if !defined(NO_THREAD_NAME)
+#if defined(_WIN32) && defined(_MSC_VER)
+/* Set the thread name for debugging purposes in Visual Studio
+ * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+ */
+#pragma pack(push, 8)
+typedef struct tagTHREADNAME_INFO {
+DWORD dwType;     /* Must be 0x1000. */
+LPCSTR szName;    /* Pointer to name (in user addr space). */
+DWORD dwThreadID; /* Thread ID (-1=caller thread). */
+DWORD dwFlags;    /* Reserved for future use, must be zero. */
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+#elif defined(__linux__)
+
+#include <sys/prctl.h>
+#include <sys/sendfile.h>
+#if defined(ALTERNATIVE_QUEUE)
+#include <sys/eventfd.h>
+#endif /* ALTERNATIVE_QUEUE */
+
+
+#if defined(ALTERNATIVE_QUEUE)
+
+static void *
+event_create(void)
+{
+int evhdl = eventfd(0, EFD_CLOEXEC);
+int *ret;
+
+if (evhdl == -1) {
+/* Linux uses -1 on error, Windows NULL. */
+/* However, Linux does not return 0 on success either. */
+return 0;
+}
+
+ret = (int *)mg_malloc(sizeof(int));
+if (ret) {
+*ret = evhdl;
+} else {
+(void)close(evhdl);
+}
+
+return (void *)ret;
+}
+
+
+static int
+event_wait(void *eventhdl)
+{
+uint64_t u;
+int evhdl, s;
+
+if (!eventhdl) {
+/* error */
+return 0;
+}
+evhdl = *(int *)eventhdl;
+
+s = (int)read(evhdl, &u, sizeof(u));
+if (s != sizeof(u)) {
+/* error */
+return 0;
+}
+(void)u; /* the value is not required */
+return 1;
+}
+
+
+static int
+event_signal(void *eventhdl)
+{
+uint64_t u = 1;
+int evhdl, s;
+
+if (!eventhdl) {
+/* error */
+return 0;
+}
+evhdl = *(int *)eventhdl;
+
+s = (int)write(evhdl, &u, sizeof(u));
+if (s != sizeof(u)) {
+/* error */
+return 0;
+}
+return 1;
+}
+
+
+static void
+event_destroy(void *eventhdl)
+{
+int evhdl;
+
+if (!eventhdl) {
+/* error */
+return;
+}
+evhdl = *(int *)eventhdl;
+
+close(evhdl);
+mg_free(eventhdl);
+}
+
+
+#endif
+
+#endif
+
+
+#if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE)
+
+struct posix_event {
+pthread_mutex_t mutex;
+pthread_cond_t cond;
+};
+
+
+static void *
+event_create(void)
+{
+struct posix_event *ret = mg_malloc(sizeof(struct posix_event));
+if (ret == 0) {
+/* out of memory */
+return 0;
+}
+if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
+/* pthread mutex not available */
+mg_free(ret);
+return 0;
+}
+if (0 != pthread_cond_init(&(ret->cond), NULL)) {
+/* pthread cond not available */
+pthread_mutex_destroy(&(ret->mutex));
+mg_free(ret);
+return 0;
+}
+return (void *)ret;
+}
+
+
+static int
+event_wait(void *eventhdl)
+{
+struct posix_event *ev = (struct posix_event *)eventhdl;
+pthread_mutex_lock(&(ev->mutex));
+pthread_cond_wait(&(ev->cond), &(ev->mutex));
+pthread_mutex_unlock(&(ev->mutex));
+return 1;
+}
+
+
+static int
+event_signal(void *eventhdl)
+{
+struct posix_event *ev = (struct posix_event *)eventhdl;
+pthread_mutex_lock(&(ev->mutex));
+pthread_cond_signal(&(ev->cond));
+pthread_mutex_unlock(&(ev->mutex));
+return 1;
+}
+
+
+static void
+event_destroy(void *eventhdl)
+{
+struct posix_event *ev = (struct posix_event *)eventhdl;
+pthread_cond_destroy(&(ev->cond));
+pthread_mutex_destroy(&(ev->mutex));
+mg_free(ev);
+}
+#endif
+
+
+static void
+mg_set_thread_name(const char *name)
+{
+char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
+
+mg_snprintf(
+NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
+
+#if defined(_WIN32)
+#if defined(_MSC_VER)
+/* Windows and Visual Studio Compiler */
+__try
+{
+THREADNAME_INFO info;
+info.dwType = 0x1000;
+info.szName = threadName;
+info.dwThreadID = ~0U;
+info.dwFlags = 0;
+
+RaiseException(0x406D1388,
+0,
+sizeof(info) / sizeof(ULONG_PTR),
+(ULONG_PTR *)&info);
+}
+__except(EXCEPTION_EXECUTE_HANDLER)
+{
+}
+#elif defined(__MINGW32__)
+/* No option known to set thread name for MinGW */
+#endif
+#elif defined(_GNU_SOURCE) && defined(__GLIBC__)                               
\
+    && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
+/* pthread_setname_np first appeared in glibc in version 2.12*/
+(void)pthread_setname_np(pthread_self(), threadName);
+#elif defined(__linux__)
+/* on linux we can use the old prctl function */
+(void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
+#endif
+}
+#else /* !defined(NO_THREAD_NAME) */
+void
+mg_set_thread_name(const char *threadName)
+{
+}
+#endif
+
+
+#if defined(MG_LEGACY_INTERFACE)
+const char **
+mg_get_valid_option_names(void)
+{
+/* This function is deprecated. Use mg_get_valid_options instead. */
+static const char *
+

<TRUNCATED>

Reply via email to