23#if defined(__GNUC__) || defined(__MINGW32__) 
   25   (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 
   26#if GCC_VERSION >= 40500 
   32#if defined(GCC_DIAGNOSTIC) 
   35#pragma GCC diagnostic ignored "-Wunused-macros" 
   37#pragma GCC diagnostic ignored "-Wpadded" 
   44#pragma GCC diagnostic push 
   45#pragma GCC diagnostic ignored "-Wreserved-id-macro" 
   49#if !defined(_CRT_SECURE_NO_WARNINGS) 
   50#define _CRT_SECURE_NO_WARNINGS  
   52#if !defined(_WIN32_WINNT)  
   53#define _WIN32_WINNT 0x0501 
   56#if !defined(_GNU_SOURCE) 
   59#if defined(__linux__) && !defined(_XOPEN_SOURCE) 
   60#define _XOPEN_SOURCE 600  
   62#if !defined(_LARGEFILE_SOURCE) 
   63#define _LARGEFILE_SOURCE  
   65#if !defined(_FILE_OFFSET_BITS) 
   66#define _FILE_OFFSET_BITS 64  
   68#if !defined(__STDC_FORMAT_MACROS) 
   69#define __STDC_FORMAT_MACROS  
   71#if !defined(__STDC_LIMIT_MACROS) 
   72#define __STDC_LIMIT_MACROS  
   74#if !defined(_DARWIN_UNLIMITED_SELECT) 
   75#define _DARWIN_UNLIMITED_SELECT 
   79#define __inline inline  
   85#pragma GCC diagnostic pop 
   95#pragma warning(disable : 4306) 
   97#pragma warning(disable : 4127) 
   99#pragma warning(disable : 4204) 
  101#pragma warning(disable : 4820) 
  103#pragma warning(disable : 4668) 
  105#pragma warning(disable : 4255) 
  107#pragma warning(disable : 4711) 
  114#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201100L 
  115#define mg_static_assert _Static_assert 
  116#elif defined(__cplusplus) && __cplusplus >= 201103L 
  117#define mg_static_assert static_assert 
  120#define mg_static_assert(cond, txt)                                            \ 
  121   extern char static_assert_replacement[(cond) ? 1 : -1] 
  125                 "int data type size check");
 
  127                 "pointer data type size check");
 
  132#if defined(NO_ALTERNATIVE_QUEUE) 
  133#if defined(ALTERNATIVE_QUEUE) 
  134#error "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE or none, but not both" 
  137#define ALTERNATIVE_QUEUE 
  142#if !defined(WIN32_LEAN_AND_MEAN) 
  143#define WIN32_LEAN_AND_MEAN 
  146#if defined(__SYMBIAN32__) 
  152#error "Symbian is no longer maintained. CivetWeb no longer supports Symbian." 
  155#define PATH_MAX FILENAME_MAX 
  159#if !defined(CIVETWEB_HEADER_INCLUDED) 
  165#if !defined(DEBUG_TRACE) 
  167static void DEBUG_TRACE_FUNC(
const char *func,
 
  172#define DEBUG_TRACE(fmt, ...)                                                  \ 
  173   DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__) 
  175#define NEED_DEBUG_TRACE_FUNC 
  178#define DEBUG_TRACE(fmt, ...)                                                  \ 
  185#if !defined(DEBUG_ASSERT) 
  187#define DEBUG_ASSERT(cond)                                                     \ 
  190         DEBUG_TRACE("ASSERTION FAILED: %s", #cond);                        \
 
  195#define DEBUG_ASSERT(cond) 
  200#if defined(__GNUC__) && defined(GCC_INSTRUMENTATION) 
  201void __cyg_profile_func_enter(
void *this_fn, 
void *call_site)
 
  202    __attribute__((no_instrument_function));
 
  204void __cyg_profile_func_exit(
void *this_fn, 
void *call_site)
 
  205    __attribute__((no_instrument_function));
 
  208__cyg_profile_func_enter(
void *this_fn, 
void *call_site)
 
  210   if ((
void *)this_fn != (
void *)printf) {
 
  211      printf(
"E %p %p\n", this_fn, call_site);
 
  216__cyg_profile_func_exit(
void *this_fn, 
void *call_site)
 
  218   if ((
void *)this_fn != (
void *)printf) {
 
  219      printf(
"X %p %p\n", this_fn, call_site);
 
  225#if !defined(IGNORE_UNUSED_RESULT) 
  226#define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1)) 
  230#if defined(__GNUC__) || defined(__MINGW32__) 
  246#pragma GCC diagnostic ignored "-Wunused-function" 
  248#define FUNCTION_MAY_BE_UNUSED  
  251#define FUNCTION_MAY_BE_UNUSED 
  256#if !defined(_WIN32_WCE) 
  261#include <sys/types.h> 
  265#if defined(__clang__) 
  269#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" 
  272#if defined(__GNUC__) || defined(__MINGW32__) 
  291#if defined(__clang__) 
  292#if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8)) 
  294#pragma clang diagnostic ignored "-Wno-reserved-id-macro" 
  295#pragma clang diagnostic ignored "-Wno-keyword-macro" 
  299#define CLOCK_MONOTONIC (1) 
  300#define CLOCK_REALTIME (2) 
  302#include <mach/clock.h> 
  303#include <mach/mach.h> 
  304#include <mach/mach_time.h> 
  305#include <sys/errno.h> 
  310_civet_clock_gettime(
int clk_id, 
struct timespec *t)
 
  312   memset(t, 0, 
sizeof(*t));
 
  313   if (clk_id == CLOCK_REALTIME) {
 
  315      int rv = gettimeofday(&now, NULL);
 
  319      t->tv_sec = now.tv_sec;
 
  320      t->tv_nsec = now.tv_usec * 1000;
 
  323   } 
else if (clk_id == CLOCK_MONOTONIC) {
 
  324      static uint64_t clock_start_time = 0;
 
  325      static mach_timebase_info_data_t timebase_ifo = {0, 0};
 
  327      uint64_t now = mach_absolute_time();
 
  329      if (clock_start_time == 0) {
 
  330         kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
 
  336         clock_start_time = now;
 
  339      now = (uint64_t)((
double)(now - clock_start_time)
 
  340                       * (
double)timebase_ifo.numer
 
  341                       / (
double)timebase_ifo.denom);
 
  343      t->tv_sec = now / 1000000000;
 
  344      t->tv_nsec = now % 1000000000;
 
  351#if defined(__CLOCK_AVAILABILITY) 
  356_civet_safe_clock_gettime(
int clk_id, 
struct timespec *t)
 
  359      return clock_gettime(clk_id, t);
 
  361   return _civet_clock_gettime(clk_id, t);
 
  363#define clock_gettime _civet_safe_clock_gettime 
  365#define clock_gettime _civet_clock_gettime 
  388#if !defined(MAX_WORKER_THREADS) 
  389#define MAX_WORKER_THREADS (1024 * 64)  
  396#if !defined(SOCKET_TIMEOUT_QUANTUM) 
  397#define SOCKET_TIMEOUT_QUANTUM (2000)  
  401#if !defined(MG_FILE_COMPRESSION_SIZE_LIMIT) 
  402#define MG_FILE_COMPRESSION_SIZE_LIMIT (1024)  
  405#if !defined(PASSWORDS_FILE_NAME) 
  406#define PASSWORDS_FILE_NAME ".htpasswd" 
  411#if !defined(CGI_ENVIRONMENT_SIZE) 
  412#define CGI_ENVIRONMENT_SIZE (4096)  
  416#if !defined(MAX_CGI_ENVIR_VARS) 
  417#define MAX_CGI_ENVIR_VARS (256)  
  421#if !defined(MG_BUF_LEN)  
  422#define MG_BUF_LEN (1024 * 8) 
  435#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 
  438#if !defined(INT64_MAX) 
  439#define INT64_MAX (9223372036854775807) 
  442#define SHUTDOWN_RD (0) 
  443#define SHUTDOWN_WR (1) 
  444#define SHUTDOWN_BOTH (2) 
  447                 "worker threads must be a positive number");
 
  450                 "size_t data type size check");
 
  459#if !defined(PATH_MAX) 
  460#define W_PATH_MAX (MAX_PATH) 
  462#define PATH_MAX (W_PATH_MAX * 3) 
  464#define W_PATH_MAX ((PATH_MAX + 2) / 3) 
  469#if !defined(_IN_PORT_T) 
  470#if !defined(in_port_t) 
  471#define in_port_t u_short 
  475#if !defined(_WIN32_WCE) 
  485#define errno ((int)(GetLastError())) 
  486#define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10)) 
  489#define MAKEUQUAD(lo, hi)                                                      \ 
  490   ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32)) 
  491#define RATE_DIFF (10000000)  
  492#define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de)) 
  493#define SYS2UNIX_TIME(lo, hi)                                                  \ 
  494   ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)) 
  502#define STR(x) STRX(x) 
  503#define __func__ __FILE__ ":" STR(__LINE__)
 
  504#define strtoull(x, y, z) ((unsigned __int64)_atoi64(x)) 
  505#define strtoll(x, y, z) (_atoi64(x)) 
  507#define __func__ __FUNCTION__ 
  508#define strtoull(x, y, z) (_strtoui64(x, y, z)) 
  509#define strtoll(x, y, z) (_strtoi64(x, y, z)) 
  513#define ERRNO ((int)(GetLastError())) 
  516#if defined(_WIN64) || defined(__MINGW64__) 
  518#define SSL_LIB "ssleay64.dll" 
  520#if !defined(CRYPTO_LIB) 
  521#define CRYPTO_LIB "libeay64.dll" 
  525#define SSL_LIB "ssleay32.dll" 
  527#if !defined(CRYPTO_LIB) 
  528#define CRYPTO_LIB "libeay32.dll" 
  532#define O_NONBLOCK (0) 
  536#if !defined(EWOULDBLOCK) 
  537#define EWOULDBLOCK WSAEWOULDBLOCK 
  540#define INT64_FMT "I64d" 
  541#define UINT64_FMT "I64u" 
  543#define WINCDECL __cdecl 
  544#define vsnprintf_impl _vsnprintf 
  545#define access _access 
  546#define mg_sleep(x) (Sleep(x)) 
  548#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY) 
  550#define popen(x, y) (_popen(x, y)) 
  553#define pclose(x) (_pclose(x)) 
  555#define close(x) (_close(x)) 
  556#define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y))) 
  558#define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0) 
  559#define fdopen(x, y) (_fdopen((x), (y))) 
  560#define write(x, y, z) (_write((x), (y), (unsigned)z)) 
  561#define read(x, y, z) (_read((x), (y), (unsigned)z)) 
  562#define flockfile(x) (EnterCriticalSection(&global_log_file_lock)) 
  563#define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock)) 
  564#define sleep(x) (Sleep((x)*1000)) 
  565#define rmdir(x) (_rmdir(x)) 
  566#if defined(_WIN64) || !defined(__MINGW32__) 
  568#define timegm(x) (_mkgmtime(x)) 
  570time_t timegm(
struct tm *tm);
 
  576#define fileno(x) (_fileno(x)) 
  579typedef HANDLE pthread_mutex_t;
 
  580typedef DWORD pthread_key_t;
 
  581typedef HANDLE pthread_t;
 
  583   CRITICAL_SECTION threadIdSec;
 
  584   struct mg_workerTLS *waiting_thread; 
 
  587#if !defined(__clockid_t_defined) 
  588typedef DWORD clockid_t;
 
  590#if !defined(CLOCK_MONOTONIC) 
  591#define CLOCK_MONOTONIC (1) 
  593#if !defined(CLOCK_REALTIME) 
  594#define CLOCK_REALTIME (2) 
  596#if !defined(CLOCK_THREAD) 
  597#define CLOCK_THREAD (3) 
  599#if !defined(CLOCK_PROCESS) 
  600#define CLOCK_PROCESS (4) 
  604#if defined(_MSC_VER) && (_MSC_VER >= 1900) 
  605#define _TIMESPEC_DEFINED 
  607#if !defined(_TIMESPEC_DEFINED) 
  614#if !defined(WIN_PTHREADS_TIME_H) 
  615#define MUST_IMPLEMENT_CLOCK_GETTIME 
  618#if defined(MUST_IMPLEMENT_CLOCK_GETTIME) 
  619#define clock_gettime mg_clock_gettime 
  621clock_gettime(clockid_t clk_id, 
struct timespec *tp)
 
  624   ULARGE_INTEGER li, li2;
 
  627   static double perfcnt_per_sec = 0.0;
 
  628   static BOOL initialized = 
FALSE;
 
  631      QueryPerformanceFrequency((LARGE_INTEGER *)&li);
 
  632      perfcnt_per_sec = 1.0 / li.QuadPart;
 
  637      memset(tp, 0, 
sizeof(*tp));
 
  639      if (clk_id == CLOCK_REALTIME) {
 
  642         GetSystemTimeAsFileTime(&ft);
 
  643         li.LowPart = ft.dwLowDateTime;
 
  644         li.HighPart = ft.dwHighDateTime;
 
  645         li.QuadPart -= 116444736000000000; 
 
  646         tp->tv_sec = (time_t)(li.QuadPart / 10000000);
 
  647         tp->tv_nsec = (
long)(li.QuadPart % 10000000) * 100;
 
  651      } 
else if (clk_id == CLOCK_MONOTONIC) {
 
  654         QueryPerformanceCounter((LARGE_INTEGER *)&li);
 
  655         d = li.QuadPart * perfcnt_per_sec;
 
  656         tp->tv_sec = (time_t)
d;
 
  658         tp->tv_nsec = (
long)(
d * 1.0E9);
 
  662      } 
else if (clk_id == CLOCK_THREAD) {
 
  665         FILETIME t_create, t_exit, t_kernel, t_user;
 
  666         if (GetThreadTimes(GetCurrentThread(),
 
  671            li.LowPart = t_user.dwLowDateTime;
 
  672            li.HighPart = t_user.dwHighDateTime;
 
  673            li2.LowPart = t_kernel.dwLowDateTime;
 
  674            li2.HighPart = t_kernel.dwHighDateTime;
 
  675            li.QuadPart += li2.QuadPart;
 
  676            tp->tv_sec = (time_t)(li.QuadPart / 10000000);
 
  677            tp->tv_nsec = (
long)(li.QuadPart % 10000000) * 100;
 
  682      } 
else if (clk_id == CLOCK_PROCESS) {
 
  685         FILETIME t_create, t_exit, t_kernel, t_user;
 
  686         if (GetProcessTimes(GetCurrentProcess(),
 
  691            li.LowPart = t_user.dwLowDateTime;
 
  692            li.HighPart = t_user.dwHighDateTime;
 
  693            li2.LowPart = t_kernel.dwLowDateTime;
 
  694            li2.HighPart = t_kernel.dwHighDateTime;
 
  695            li.QuadPart += li2.QuadPart;
 
  696            tp->tv_sec = (time_t)(li.QuadPart / 10000000);
 
  697            tp->tv_nsec = (
long)(li.QuadPart % 10000000) * 100;
 
  717static int pthread_mutex_lock(pthread_mutex_t *);
 
  718static int pthread_mutex_unlock(pthread_mutex_t *);
 
  719static void path_to_unicode(
const struct mg_connection *conn,
 
  729mg_fgets(
char *buf, 
size_t size, 
struct mg_file *filep, 
char **p);
 
  734   char d_name[PATH_MAX];
 
  739   WIN32_FIND_DATAW info;
 
  740   struct dirent result;
 
  744#if !defined(HAVE_POLL) 
  755#pragma comment(lib, "Ws2_32.lib")
 
  760#include <arpa/inet.h> 
  763#include <netinet/in.h> 
  764#include <netinet/tcp.h> 
  767#include <sys/socket.h> 
  769#include <sys/utsname.h> 
  774typedef unsigned short int in_port_t;
 
  781#define vsnprintf_impl vsnprintf 
  783#if !defined(NO_SSL_DL) && !defined(NO_SSL) 
  788#define SSL_LIB "libssl.dylib" 
  789#define CRYPTO_LIB "libcrypto.dylib" 
  792#define SSL_LIB "libssl.so" 
  794#if !defined(CRYPTO_LIB) 
  795#define CRYPTO_LIB "libcrypto.so" 
  798#if !defined(O_BINARY) 
  801#define closesocket(a) (close(a)) 
  802#define mg_mkdir(conn, path, mode) (mkdir(path, mode)) 
  803#define mg_remove(conn, x) (remove(x)) 
  804#define mg_sleep(x) (usleep((x)*1000)) 
  805#define mg_opendir(conn, x) (opendir(x)) 
  806#define mg_closedir(x) (closedir(x)) 
  807#define mg_readdir(x) (readdir(x)) 
  809#define INVALID_SOCKET (-1) 
  810#define INT64_FMT PRId64 
  811#define UINT64_FMT PRIu64 
  817#if !defined(CLOCK_MONOTONIC) 
  818#define CLOCK_MONOTONIC CLOCK_REALTIME 
  836#if !defined(SOMAXCONN) 
  838#define SOMAXCONN (100)  
  842#if defined(NEED_TIMEGM) 
  846   return (
y % 4 == 0 && 
y % 100 != 0) || 
y % 400 == 0;
 
  852   return (
y - 1969) / 4 - (
y - 1901) / 100 + (
y - 1601) / 400;
 
  858   static const unsigned short ydays[] = {
 
  859       0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
 
  860   int year = tm->tm_year + 1900;
 
  861   int mon = tm->tm_mon;
 
  862   int mday = tm->tm_mday - 1;
 
  863   int hour = tm->tm_hour;
 
  864   int min = tm->tm_min;
 
  865   int sec = tm->tm_sec;
 
  867   if (year < 1970 || mon < 0 || mon > 11 || mday < 0
 
  868       || (mday >= ydays[mon + 1] - ydays[mon]
 
  869                       + (mon == 1 && is_leap(year) ? 1 : 0))
 
  870       || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60)
 
  873   time_t res = year - 1970;
 
  876   res += ydays[mon] + (mon > 1 && is_leap(year) ? 1 : 0);
 
  877   res += count_leap(year);
 
  892#define va_copy(x, y) ((x) = (y)) 
  899#if defined(GCC_DIAGNOSTIC) 
  901#pragma GCC diagnostic push 
  902#pragma GCC diagnostic ignored "-Wunused-function" 
  906static CRITICAL_SECTION global_log_file_lock;
 
  912   return GetCurrentThreadId();
 
  920    void (*_ignored)(
void *) 
 
  927      return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
 
  935pthread_key_delete(pthread_key_t key)
 
  937   return TlsFree(key) ? 0 : 1;
 
  943pthread_setspecific(pthread_key_t key, 
void *value)
 
  945   return TlsSetValue(key, value) ? 0 : 1;
 
  951pthread_getspecific(pthread_key_t key)
 
  953   return TlsGetValue(key);
 
  956#if defined(GCC_DIAGNOSTIC) 
  958#pragma GCC diagnostic pop 
  967#if defined(_WIN32_WCE) 
  970#if defined(GCC_DIAGNOSTIC) 
  972#pragma GCC diagnostic push 
  973#pragma GCC diagnostic ignored "-Wunused-function" 
  986   SystemTimeToFileTime(&st, &ft);
 
  987   t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
 
  999localtime_s(
const time_t *ptime, 
struct tm *ptm)
 
 1001   int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
 
 1004   TIME_ZONE_INFORMATION tzinfo;
 
 1010   *(int64_t *)&ft = t;
 
 1011   FileTimeToLocalFileTime(&ft, &lft);
 
 1012   FileTimeToSystemTime(&lft, &st);
 
 1013   ptm->tm_year = st.wYear - 1900;
 
 1014   ptm->tm_mon = st.wMonth - 1;
 
 1015   ptm->tm_wday = st.wDayOfWeek;
 
 1016   ptm->tm_mday = st.wDay;
 
 1017   ptm->tm_hour = st.wHour;
 
 1018   ptm->tm_min = st.wMinute;
 
 1019   ptm->tm_sec = st.wSecond;
 
 1022       (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
 
 1030gmtime_s(
const time_t *ptime, 
struct tm *ptm)
 
 1033   return localtime_s(ptime, ptm);
 
 1039static int tm_index = 0;
 
 1044localtime(
const time_t *ptime)
 
 1046   int i = 
mg_atomic_inc(&tm_index) % (
sizeof(tm_array) / 
sizeof(tm_array[0]));
 
 1047   return localtime_s(ptime, tm_array + i);
 
 1053gmtime(
const time_t *ptime)
 
 1056   return gmtime_s(ptime, tm_array + i);
 
 1062strftime(
char *dst, 
size_t dst_size, 
const char *fmt, 
const struct tm *tm)
 
 1069#define _beginthreadex(psec, stack, func, prm, flags, ptid)                    \ 
 1070   (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid) 
 1072#define remove(f) mg_remove(NULL, f) 
 1077rename(
const char *
a, 
const char *
b)
 
 1079   wchar_t wa[W_PATH_MAX];
 
 1080   wchar_t wb[W_PATH_MAX];
 
 1084   return MoveFileW(wa, wb) ? 0 : -1;
 
 1096stat(
const char *
name, 
struct stat *st)
 
 1098   wchar_t wbuf[W_PATH_MAX];
 
 1099   WIN32_FILE_ATTRIBUTE_DATA attr;
 
 1100   time_t creation_time, write_time;
 
 1103   memset(&attr, 0, 
sizeof(attr));
 
 1105   GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
 
 1107       (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
 
 1109   write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
 
 1110                              attr.ftLastWriteTime.dwHighDateTime);
 
 1111   creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
 
 1112                                 attr.ftCreationTime.dwHighDateTime);
 
 1114   if (creation_time > write_time) {
 
 1115      st->st_mtime = creation_time;
 
 1117      st->st_mtime = write_time;
 
 1122#define access(x, a) 1  
 1130#if defined(GCC_DIAGNOSTIC) 
 1132#pragma GCC diagnostic pop 
 1138#if defined(GCC_DIAGNOSTIC) 
 1140#pragma GCC diagnostic push 
 1141#pragma GCC diagnostic ignored "-Wunused-function" 
 1143#if defined(__clang__) 
 1145#pragma clang diagnostic push 
 1146#pragma clang diagnostic ignored "-Wunused-function" 
 1155static int pthread_mutex_lock(pthread_mutex_t *mutex);
 
 1158static int pthread_mutex_unlock(pthread_mutex_t *mutex);
 
 1183#if defined(_WIN32) && !defined(NO_ATOMICS) 
 1187   ret = InterlockedIncrement((
volatile long *)addr);
 
 1188#elif defined(__GNUC__)                                                        \ 
 1189    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           \ 
 1190    && !defined(NO_ATOMICS) 
 1191   ret = __sync_add_and_fetch(addr, 1);
 
 1206#if defined(_WIN32) && !defined(NO_ATOMICS) 
 1210   ret = InterlockedDecrement((
volatile long *)addr);
 
 1211#elif defined(__GNUC__)                                                        \ 
 1212    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           \ 
 1213    && !defined(NO_ATOMICS) 
 1214   ret = __sync_sub_and_fetch(addr, 1);
 
 1224#if defined(USE_SERVER_STATS) 
 1226mg_atomic_add(
volatile int64_t *addr, int64_t value)
 
 1229#if defined(_WIN64) && !defined(NO_ATOMICS) 
 1230   ret = InterlockedAdd64(addr, value);
 
 1231#elif defined(__GNUC__)                                                        \ 
 1232    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))           \ 
 1233    && !defined(NO_ATOMICS) 
 1234   ret = __sync_add_and_fetch(addr, value);
 
 1246#if defined(GCC_DIAGNOSTIC) 
 1248#pragma GCC diagnostic pop 
 1250#if defined(__clang__) 
 1252#pragma clang diagnostic pop 
 1256#if defined(USE_SERVER_STATS) 
 1258struct mg_memory_stat {
 
 1259   volatile int64_t totalMemUsed;
 
 1260   volatile int64_t maxMemUsed;
 
 1261   volatile int blockCount;
 
 1265static struct mg_memory_stat *get_memory_stat(
struct mg_context *ctx);
 
 1269mg_malloc_ex(
size_t size,
 
 1270             struct mg_context *ctx,
 
 1274   void *data = 
malloc(size + 2 * 
sizeof(uintptr_t));
 
 1276   struct mg_memory_stat *mstat = get_memory_stat(ctx);
 
 1278#if defined(MEMORY_DEBUGGING) 
 1279   char mallocStr[256];
 
 1286      int64_t mmem = mg_atomic_add(&mstat->totalMemUsed, (int64_t)size);
 
 1287      if (mmem > mstat->maxMemUsed) {
 
 1290         mstat->maxMemUsed = mmem;
 
 1294      ((uintptr_t *)data)[0] = size;
 
 1295      ((uintptr_t *)data)[1] = (uintptr_t)mstat;
 
 1296      memory = (
void *)(((
char *)data) + 2 * 
sizeof(uintptr_t));
 
 1299#if defined(MEMORY_DEBUGGING) 
 1301           "MEM: %p %5lu alloc   %7lu %4lu --- %s:%u\n",
 
 1303           (
unsigned long)size,
 
 1304           (
unsigned long)mstat->totalMemUsed,
 
 1305           (
unsigned long)mstat->blockCount,
 
 1309   OutputDebugStringA(mallocStr);
 
 1320mg_calloc_ex(
size_t count,
 
 1322             struct mg_context *ctx,
 
 1326   void *data = mg_malloc_ex(size * count, ctx, 
file, 
line);
 
 1329      memset(data, 0, size * count);
 
 1336mg_free_ex(
void *memory, 
const char *
file, 
unsigned line)
 
 1338   void *data = (
void *)(((
char *)memory) - 2 * 
sizeof(uintptr_t));
 
 1341#if defined(MEMORY_DEBUGGING) 
 1342   char mallocStr[256];
 
 1349      uintptr_t size = ((uintptr_t *)data)[0];
 
 1350      struct mg_memory_stat *mstat =
 
 1351          (
struct mg_memory_stat *)(((uintptr_t *)data)[1]);
 
 1352      mg_atomic_add(&mstat->totalMemUsed, -(int64_t)size);
 
 1354#if defined(MEMORY_DEBUGGING) 
 1356              "MEM: %p %5lu free    %7lu %4lu --- %s:%u\n",
 
 1358              (
unsigned long)size,
 
 1359              (
unsigned long)mstat->totalMemUsed,
 
 1360              (
unsigned long)mstat->blockCount,
 
 1364      OutputDebugStringA(mallocStr);
 
 1375mg_realloc_ex(
void *memory,
 
 1377              struct mg_context *ctx,
 
 1385#if defined(MEMORY_DEBUGGING) 
 1386   char mallocStr[256];
 
 1395         struct mg_memory_stat *mstat;
 
 1396         data = (
void *)(((
char *)memory) - 2 * 
sizeof(uintptr_t));
 
 1397         oldsize = ((uintptr_t *)data)[0];
 
 1398         mstat = (
struct mg_memory_stat *)((uintptr_t *)data)[1];
 
 1399         _realloc = 
realloc(data, newsize + 2 * 
sizeof(uintptr_t));
 
 1402            mg_atomic_add(&mstat->totalMemUsed, -(int64_t)oldsize);
 
 1403#if defined(MEMORY_DEBUGGING) 
 1405                    "MEM: %p %5lu r-free  %7lu %4lu --- %s:%u\n",
 
 1407                    (
unsigned long)oldsize,
 
 1408                    (
unsigned long)mstat->totalMemUsed,
 
 1409                    (
unsigned long)mstat->blockCount,
 
 1413            OutputDebugStringA(mallocStr);
 
 1418            mg_atomic_add(&mstat->totalMemUsed, (int64_t)newsize);
 
 1419#if defined(MEMORY_DEBUGGING) 
 1421                    "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
 
 1423                    (
unsigned long)newsize,
 
 1424                    (
unsigned long)mstat->totalMemUsed,
 
 1425                    (
unsigned long)mstat->blockCount,
 
 1429            OutputDebugStringA(mallocStr);
 
 1434            *(uintptr_t *)data = newsize;
 
 1435            data = (
void *)(((
char *)data) + 2 * 
sizeof(uintptr_t));
 
 1437#if defined(MEMORY_DEBUGGING) 
 1439            OutputDebugStringA(
"MEM: realloc failed\n");
 
 1448         data = mg_malloc_ex(newsize, ctx, 
file, 
line);
 
 1459#define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__) 
 1460#define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__) 
 1461#define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__) 
 1462#define mg_free(a) mg_free_ex(a, __FILE__, __LINE__) 
 1464#define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__) 
 1465#define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__) 
 1466#define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__) 
 1470static __inline 
void *
 
 1476static __inline 
void *
 
 1482static __inline 
void *
 
 1494#define mg_malloc_ctx(a, c) mg_malloc(a) 
 1495#define mg_calloc_ctx(a, b, c) mg_calloc(a, b) 
 1496#define mg_realloc_ctx(a, b, c) mg_realloc(a, b) 
 1497#define mg_free_ctx(a, c) mg_free(a) 
 1502static void mg_vsnprintf(
const struct mg_connection *conn,
 
 1530#if defined(snprintf) 
 1533#if defined(vsnprintf) 
 1536#define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc 
 1537#define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc 
 1538#define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc 
 1539#define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free 
 1540#define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf 
 1544#define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf 
 1558#if defined(MG_LEGACY_INTERFACE) 
 1559#define MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE 
 1562struct mg_workerTLS {
 
 1564   unsigned long thread_idx;
 
 1566   HANDLE pthread_cond_helper_mutex;
 
 1567   struct mg_workerTLS *next_waiting_thread;
 
 1569#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE) 
 1575#if defined(GCC_DIAGNOSTIC) 
 1577#pragma GCC diagnostic push 
 1578#pragma GCC diagnostic ignored "-Wunused-function" 
 1580#if defined(__clang__) 
 1582#pragma clang diagnostic push 
 1583#pragma clang diagnostic ignored "-Wunused-function" 
 1602   return GetCurrentThreadId();
 
 1605#if defined(__clang__) 
 1606#pragma clang diagnostic push 
 1607#pragma clang diagnostic ignored "-Wunreachable-code" 
 1615   if (
sizeof(pthread_t) > 
sizeof(
unsigned long)) {
 
 1618      struct mg_workerTLS *tls =
 
 1619          (
struct mg_workerTLS *)pthread_getspecific(
sTlsKey);
 
 1623         tls = (
struct mg_workerTLS *)
mg_malloc(
sizeof(
struct mg_workerTLS));
 
 1624         tls->is_master = -2; 
 
 1626         pthread_setspecific(
sTlsKey, tls);
 
 1628      return tls->thread_idx;
 
 1633      unsigned long ret = 0;
 
 1634      pthread_t t = pthread_self();
 
 1635      memcpy(&ret, &t, 
sizeof(pthread_t));
 
 1639#if defined(__clang__) 
 1640#pragma clang diagnostic pop 
 1651   struct timespec tsnow;
 
 1652   clock_gettime(CLOCK_REALTIME, &tsnow);
 
 1653   return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
 
 1657#if defined(GCC_DIAGNOSTIC) 
 1659#pragma GCC diagnostic pop 
 1661#if defined(__clang__) 
 1663#pragma clang diagnostic pop 
 1667#if defined(NEED_DEBUG_TRACE_FUNC) 
 1669DEBUG_TRACE_FUNC(
const char *func, 
unsigned line, 
const char *fmt, ...)
 
 1673   static uint64_t nslast;
 
 1674   struct timespec tsnow;
 
 1679   clock_gettime(CLOCK_REALTIME, &tsnow);
 
 1680   nsnow = ((uint64_t)tsnow.tv_sec) * ((uint64_t)1000000000)
 
 1681           + ((uint64_t)tsnow.tv_nsec);
 
 1688   printf(
"*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ",
 
 1689          (
unsigned long)tsnow.tv_sec,
 
 1690          (
unsigned long)tsnow.tv_nsec,
 
 1695   va_start(args, fmt);
 
 1700   funlockfile(stdout);
 
 1706#define MD5_STATIC static 
 1710#if defined(NO_SOCKLEN_T) 
 1711typedef int socklen_t;
 
 1714#define IP_ADDR_STR_LEN (50)  
 1716#if !defined(MSG_NOSIGNAL) 
 1717#define MSG_NOSIGNAL (0) 
 1725#if defined(NO_SSL_DL) 
 1726#include <openssl/bn.h> 
 1727#include <openssl/conf.h> 
 1728#include <openssl/crypto.h> 
 1729#include <openssl/dh.h> 
 1730#include <openssl/engine.h> 
 1731#include <openssl/err.h> 
 1732#include <openssl/opensslv.h> 
 1733#include <openssl/pem.h> 
 1734#include <openssl/ssl.h> 
 1735#include <openssl/tls1.h> 
 1736#include <openssl/x509.h> 
 1738#if defined(WOLFSSL_VERSION) 
 1741#include "wolfssl_extras.inl" 
 1744#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) 
 1746#if !defined(OPENSSL_API_1_1) 
 1747#define OPENSSL_API_1_1 
 1749#define OPENSSL_REMOVE_THREAD_STATE() 
 1751#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL) 
 1772#define SSL_CTRL_OPTIONS (32) 
 1773#define SSL_CTRL_CLEAR_OPTIONS (77) 
 1774#define SSL_CTRL_SET_ECDH_AUTO (94) 
 1776#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L 
 1777#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L 
 1778#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L 
 1780#define SSL_VERIFY_NONE (0) 
 1781#define SSL_VERIFY_PEER (1) 
 1782#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2) 
 1783#define SSL_VERIFY_CLIENT_ONCE (4) 
 1784#define SSL_OP_ALL ((long)(0x80000BFFUL)) 
 1785#define SSL_OP_NO_SSLv2 (0x01000000L) 
 1786#define SSL_OP_NO_SSLv3 (0x02000000L) 
 1787#define SSL_OP_NO_TLSv1 (0x04000000L) 
 1788#define SSL_OP_NO_TLSv1_2 (0x08000000L) 
 1789#define SSL_OP_NO_TLSv1_1 (0x10000000L) 
 1790#define SSL_OP_SINGLE_DH_USE (0x00100000L) 
 1791#define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L) 
 1792#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000L) 
 1793#define SSL_OP_NO_COMPRESSION (0x00020000L) 
 1795#define SSL_CB_HANDSHAKE_START (0x10) 
 1796#define SSL_CB_HANDSHAKE_DONE (0x20) 
 1798#define SSL_ERROR_NONE (0) 
 1799#define SSL_ERROR_SSL (1) 
 1800#define SSL_ERROR_WANT_READ (2) 
 1801#define SSL_ERROR_WANT_WRITE (3) 
 1802#define SSL_ERROR_WANT_X509_LOOKUP (4) 
 1803#define SSL_ERROR_SYSCALL (5)  
 1804#define SSL_ERROR_ZERO_RETURN (6) 
 1805#define SSL_ERROR_WANT_CONNECT (7) 
 1806#define SSL_ERROR_WANT_ACCEPT (8) 
 1808#define TLSEXT_TYPE_server_name (0) 
 1809#define TLSEXT_NAMETYPE_host_name (0) 
 1810#define SSL_TLSEXT_ERR_OK (0) 
 1811#define SSL_TLSEXT_ERR_ALERT_WARNING (1) 
 1812#define SSL_TLSEXT_ERR_ALERT_FATAL (2) 
 1813#define SSL_TLSEXT_ERR_NOACK (3) 
 1821#if defined(OPENSSL_API_1_1) 
 1823#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) 
 1824#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) 
 1825#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) 
 1826#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) 
 1827#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) 
 1828#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) 
 1829#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) 
 1830#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr) 
 1831#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr) 
 1832#define TLS_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr) 
 1833#define OPENSSL_init_ssl                                                       \ 
 1834   (*(int (*)(uint64_t opts,                                                  \ 
 1835              const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10]               \ 
 1837#define SSL_CTX_use_PrivateKey_file                                            \ 
 1838   (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) 
 1839#define SSL_CTX_use_certificate_file                                           \ 
 1840   (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) 
 1841#define SSL_CTX_set_default_passwd_cb                                          \ 
 1842   (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) 
 1843#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) 
 1844#define SSL_CTX_use_certificate_chain_file                                     \ 
 1845   (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr) 
 1846#define TLS_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[16].ptr) 
 1847#define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr) 
 1848#define SSL_CTX_set_verify                                                     \ 
 1849   (*(void (*)(SSL_CTX *,                                                     \ 
 1851               int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18]      \ 
 1853#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr) 
 1854#define SSL_CTX_load_verify_locations                                          \ 
 1855   (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr) 
 1856#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr) 
 1857#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr) 
 1858#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[23].ptr) 
 1859#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr) 
 1860#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[25].ptr) 
 1861#define SSL_CIPHER_get_name                                                    \ 
 1862   (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr) 
 1863#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr) 
 1864#define SSL_CTX_set_session_id_context                                         \ 
 1865   (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr) 
 1866#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr) 
 1867#define SSL_CTX_set_cipher_list                                                \ 
 1868   (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr) 
 1869#define SSL_CTX_set_options                                                    \ 
 1870   (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr) 
 1871#define SSL_CTX_set_info_callback                                              \ 
 1872   (*(void (*)(SSL_CTX * ctx, void (*callback)(const SSL *, int, int)))       \ 
 1875#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr) 
 1876#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) 
 1877#define SSL_CTX_callback_ctrl                                                  \ 
 1878   (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr) 
 1879#define SSL_get_servername                                                     \ 
 1880   (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr) 
 1881#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr) 
 1882#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr) 
 1884#define SSL_CTX_clear_options(ctx, op)                                         \ 
 1885   SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) 
 1886#define SSL_CTX_set_ecdh_auto(ctx, onoff)                                      \ 
 1887   SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) 
 1889#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 
 1890#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 
 1891#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 
 1892#define SSL_CTX_set_tlsext_servername_callback(ctx, cb)                        \ 
 1893   SSL_CTX_callback_ctrl(ctx,                                                 \ 
 1894                         SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                   \ 
 1896#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)                            \ 
 1897   SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg) 
 1898#define SSL_set_tlsext_host_name(ctx, arg)                                     \ 
 1899   SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg) 
 1901#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) 
 1902#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) 
 1904#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) 
 1905#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) 
 1907#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr) 
 1908#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr) 
 1909#define CONF_modules_unload (*(void (*)(int))crypto_sw[2].ptr) 
 1910#define X509_free (*(void (*)(X509 *))crypto_sw[3].ptr) 
 1911#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[4].ptr) 
 1912#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[5].ptr) 
 1913#define X509_NAME_oneline                                                      \ 
 1914   (*(char *(*)(X509_NAME *, char *, int))crypto_sw[6].ptr) 
 1915#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[7].ptr) 
 1916#define EVP_get_digestbyname                                                   \ 
 1917   (*(const EVP_MD *(*)(const char *))crypto_sw[8].ptr) 
 1920       const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ 
 1923#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[10].ptr) 
 1924#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[11].ptr) 
 1925#define ASN1_INTEGER_to_BN                                                     \ 
 1926   (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[12].ptr) 
 1927#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[13].ptr) 
 1928#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[14].ptr) 
 1930#define OPENSSL_free(a) CRYPTO_free(a) 
 1932#define OPENSSL_REMOVE_THREAD_STATE() 
 1938static struct ssl_func 
ssl_sw[] = {{
"SSL_free", NULL},
 
 1939                                   {
"SSL_accept", NULL},
 
 1940                                   {
"SSL_connect", NULL},
 
 1942                                   {
"SSL_write", NULL},
 
 1943                                   {
"SSL_get_error", NULL},
 
 1944                                   {
"SSL_set_fd", NULL},
 
 1946                                   {
"SSL_CTX_new", NULL},
 
 1947                                   {
"TLS_server_method", NULL},
 
 1948                                   {
"OPENSSL_init_ssl", NULL},
 
 1949                                   {
"SSL_CTX_use_PrivateKey_file", NULL},
 
 1950                                   {
"SSL_CTX_use_certificate_file", NULL},
 
 1951                                   {
"SSL_CTX_set_default_passwd_cb", NULL},
 
 1952                                   {
"SSL_CTX_free", NULL},
 
 1953                                   {
"SSL_CTX_use_certificate_chain_file", NULL},
 
 1954                                   {
"TLS_client_method", NULL},
 
 1955                                   {
"SSL_pending", NULL},
 
 1956                                   {
"SSL_CTX_set_verify", NULL},
 
 1957                                   {
"SSL_shutdown", NULL},
 
 1958                                   {
"SSL_CTX_load_verify_locations", NULL},
 
 1959                                   {
"SSL_CTX_set_default_verify_paths", NULL},
 
 1960                                   {
"SSL_CTX_set_verify_depth", NULL},
 
 1961                                   {
"SSL_get_peer_certificate", NULL},
 
 1962                                   {
"SSL_get_version", NULL},
 
 1963                                   {
"SSL_get_current_cipher", NULL},
 
 1964                                   {
"SSL_CIPHER_get_name", NULL},
 
 1965                                   {
"SSL_CTX_check_private_key", NULL},
 
 1966                                   {
"SSL_CTX_set_session_id_context", NULL},
 
 1967                                   {
"SSL_CTX_ctrl", NULL},
 
 1968                                   {
"SSL_CTX_set_cipher_list", NULL},
 
 1969                                   {
"SSL_CTX_set_options", NULL},
 
 1970                                   {
"SSL_CTX_set_info_callback", NULL},
 
 1971                                   {
"SSL_get_ex_data", NULL},
 
 1972                                   {
"SSL_set_ex_data", NULL},
 
 1973                                   {
"SSL_CTX_callback_ctrl", NULL},
 
 1974                                   {
"SSL_get_servername", NULL},
 
 1975                                   {
"SSL_set_SSL_CTX", NULL},
 
 1982static struct ssl_func 
crypto_sw[] = {{
"ERR_get_error", NULL},
 
 1983                                      {
"ERR_error_string", NULL},
 
 1984                                      {
"CONF_modules_unload", NULL},
 
 1985                                      {
"X509_free", NULL},
 
 1986                                      {
"X509_get_subject_name", NULL},
 
 1987                                      {
"X509_get_issuer_name", NULL},
 
 1988                                      {
"X509_NAME_oneline", NULL},
 
 1989                                      {
"X509_get_serialNumber", NULL},
 
 1990                                      {
"EVP_get_digestbyname", NULL},
 
 1991                                      {
"EVP_Digest", NULL},
 
 1993                                      {
"BN_bn2hex", NULL},
 
 1994                                      {
"ASN1_INTEGER_to_BN", NULL},
 
 1996                                      {
"CRYPTO_free", NULL},
 
 2000#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) 
 2001#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) 
 2002#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) 
 2003#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) 
 2004#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) 
 2005#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) 
 2006#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) 
 2007#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr) 
 2008#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr) 
 2009#define SSLv23_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr) 
 2010#define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr) 
 2011#define SSL_CTX_use_PrivateKey_file                                            \ 
 2012   (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) 
 2013#define SSL_CTX_use_certificate_file                                           \ 
 2014   (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) 
 2015#define SSL_CTX_set_default_passwd_cb                                          \ 
 2016   (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) 
 2017#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) 
 2018#define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr) 
 2019#define SSL_CTX_use_certificate_chain_file                                     \ 
 2020   (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr) 
 2021#define SSLv23_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[17].ptr) 
 2022#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr) 
 2023#define SSL_CTX_set_verify                                                     \ 
 2024   (*(void (*)(SSL_CTX *,                                                     \ 
 2026               int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19]      \ 
 2028#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr) 
 2029#define SSL_CTX_load_verify_locations                                          \ 
 2030   (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr) 
 2031#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr) 
 2032#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr) 
 2033#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[24].ptr) 
 2034#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr) 
 2035#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[26].ptr) 
 2036#define SSL_CIPHER_get_name                                                    \ 
 2037   (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr) 
 2038#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr) 
 2039#define SSL_CTX_set_session_id_context                                         \ 
 2040   (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr) 
 2041#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr) 
 2042#define SSL_CTX_set_cipher_list                                                \ 
 2043   (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr) 
 2044#define SSL_CTX_set_info_callback                                              \ 
 2045   (*(void (*)(SSL_CTX *, void (*callback)(const SSL *, int, int)))ssl_sw[32] \ 
 2047#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr) 
 2048#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) 
 2049#define SSL_CTX_callback_ctrl                                                  \ 
 2050   (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr) 
 2051#define SSL_get_servername                                                     \ 
 2052   (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr) 
 2053#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr) 
 2054#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr) 
 2056#define SSL_CTX_set_options(ctx, op)                                           \ 
 2057   SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL) 
 2058#define SSL_CTX_clear_options(ctx, op)                                         \ 
 2059   SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) 
 2060#define SSL_CTX_set_ecdh_auto(ctx, onoff)                                      \ 
 2061   SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) 
 2063#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 
 2064#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 
 2065#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 
 2066#define SSL_CTX_set_tlsext_servername_callback(ctx, cb)                        \ 
 2067   SSL_CTX_callback_ctrl(ctx,                                                 \ 
 2068                         SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                   \ 
 2070#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)                            \ 
 2071   SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg) 
 2072#define SSL_set_tlsext_host_name(ctx, arg)                                     \ 
 2073   SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg) 
 2075#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) 
 2076#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) 
 2078#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) 
 2079#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) 
 2081#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr) 
 2082#define CRYPTO_set_locking_callback                                            \ 
 2083   (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr) 
 2084#define CRYPTO_set_id_callback                                                 \ 
 2085   (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr) 
 2086#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr) 
 2087#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr) 
 2088#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr) 
 2089#define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr) 
 2090#define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr) 
 2091#define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr) 
 2092#define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr) 
 2093#define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr) 
 2094#define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr) 
 2095#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[12].ptr) 
 2096#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[13].ptr) 
 2097#define X509_NAME_oneline                                                      \ 
 2098   (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr) 
 2099#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[15].ptr) 
 2100#define i2c_ASN1_INTEGER                                                       \ 
 2101   (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr) 
 2102#define EVP_get_digestbyname                                                   \ 
 2103   (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr) 
 2106       const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ 
 2109#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr) 
 2110#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr) 
 2111#define ASN1_INTEGER_to_BN                                                     \ 
 2112   (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[21].ptr) 
 2113#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr) 
 2114#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr) 
 2116#define OPENSSL_free(a) CRYPTO_free(a) 
 2121#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_state(0) 
 2127static struct ssl_func 
ssl_sw[] = {{
"SSL_free", NULL},
 
 2128                                   {
"SSL_accept", NULL},
 
 2129                                   {
"SSL_connect", NULL},
 
 2131                                   {
"SSL_write", NULL},
 
 2132                                   {
"SSL_get_error", NULL},
 
 2133                                   {
"SSL_set_fd", NULL},
 
 2135                                   {
"SSL_CTX_new", NULL},
 
 2136                                   {
"SSLv23_server_method", NULL},
 
 2137                                   {
"SSL_library_init", NULL},
 
 2138                                   {
"SSL_CTX_use_PrivateKey_file", NULL},
 
 2139                                   {
"SSL_CTX_use_certificate_file", NULL},
 
 2140                                   {
"SSL_CTX_set_default_passwd_cb", NULL},
 
 2141                                   {
"SSL_CTX_free", NULL},
 
 2142                                   {
"SSL_load_error_strings", NULL},
 
 2143                                   {
"SSL_CTX_use_certificate_chain_file", NULL},
 
 2144                                   {
"SSLv23_client_method", NULL},
 
 2145                                   {
"SSL_pending", NULL},
 
 2146                                   {
"SSL_CTX_set_verify", NULL},
 
 2147                                   {
"SSL_shutdown", NULL},
 
 2148                                   {
"SSL_CTX_load_verify_locations", NULL},
 
 2149                                   {
"SSL_CTX_set_default_verify_paths", NULL},
 
 2150                                   {
"SSL_CTX_set_verify_depth", NULL},
 
 2151                                   {
"SSL_get_peer_certificate", NULL},
 
 2152                                   {
"SSL_get_version", NULL},
 
 2153                                   {
"SSL_get_current_cipher", NULL},
 
 2154                                   {
"SSL_CIPHER_get_name", NULL},
 
 2155                                   {
"SSL_CTX_check_private_key", NULL},
 
 2156                                   {
"SSL_CTX_set_session_id_context", NULL},
 
 2157                                   {
"SSL_CTX_ctrl", NULL},
 
 2158                                   {
"SSL_CTX_set_cipher_list", NULL},
 
 2159                                   {
"SSL_CTX_set_info_callback", NULL},
 
 2160                                   {
"SSL_get_ex_data", NULL},
 
 2161                                   {
"SSL_set_ex_data", NULL},
 
 2162                                   {
"SSL_CTX_callback_ctrl", NULL},
 
 2163                                   {
"SSL_get_servername", NULL},
 
 2164                                   {
"SSL_set_SSL_CTX", NULL},
 
 2171static struct ssl_func 
crypto_sw[] = {{
"CRYPTO_num_locks", NULL},
 
 2172                                      {
"CRYPTO_set_locking_callback", NULL},
 
 2173                                      {
"CRYPTO_set_id_callback", NULL},
 
 2174                                      {
"ERR_get_error", NULL},
 
 2175                                      {
"ERR_error_string", NULL},
 
 2176                                      {
"ERR_remove_state", NULL},
 
 2177                                      {
"ERR_free_strings", NULL},
 
 2178                                      {
"ENGINE_cleanup", NULL},
 
 2179                                      {
"CONF_modules_unload", NULL},
 
 2180                                      {
"CRYPTO_cleanup_all_ex_data", NULL},
 
 2181                                      {
"EVP_cleanup", NULL},
 
 2182                                      {
"X509_free", NULL},
 
 2183                                      {
"X509_get_subject_name", NULL},
 
 2184                                      {
"X509_get_issuer_name", NULL},
 
 2185                                      {
"X509_NAME_oneline", NULL},
 
 2186                                      {
"X509_get_serialNumber", NULL},
 
 2187                                      {
"i2c_ASN1_INTEGER", NULL},
 
 2188                                      {
"EVP_get_digestbyname", NULL},
 
 2189                                      {
"EVP_Digest", NULL},
 
 2191                                      {
"BN_bn2hex", NULL},
 
 2192                                      {
"ASN1_INTEGER_to_BN", NULL},
 
 2194                                      {
"CRYPTO_free", NULL},
 
 2201#if !defined(NO_CACHING) 
 2221   struct sockaddr_in 
sin;
 
 2222#if defined(USE_IPV6) 
 2223   struct sockaddr_in6 sin6;
 
 2233struct mg_file_stat {
 
 2236   time_t last_modified;
 
 2243struct mg_file_in_memory {
 
 2249struct mg_file_access {
 
 2252#if defined(MG_USE_OPEN_FILE) 
 2263   struct mg_file_stat stat;
 
 2264   struct mg_file_access access;
 
 2267#if defined(MG_USE_OPEN_FILE) 
 2269#define STRUCT_FILE_INITIALIZER                                                \ 
 2271      {(uint64_t)0, (time_t)0, 0, 0, 0},                                     \ 
 2273         (FILE *)NULL, (const char *)NULL                                   \ 
 2279#define STRUCT_FILE_INITIALIZER                                                \ 
 2281      {(uint64_t)0, (time_t)0, 0, 0, 0},                                     \ 
 2296   unsigned char is_ssl;    
 
 2297   unsigned char ssl_redir; 
 
 2299   unsigned char in_use;    
 
 2317#if defined(__linux__) 
 2318   ALLOW_SENDFILE_CALL,
 
 2321   CASE_SENSITIVE_FILES,
 
 2329#if defined(USE_WEBSOCKET) 
 2331   ENABLE_WEBSOCKET_PING_PONG,
 
 2335   LUA_BACKGROUND_SCRIPT,
 
 2336   LUA_BACKGROUND_SCRIPT_PARAMS,
 
 2338#if defined(USE_TIMERS) 
 2372   LUA_SCRIPT_EXTENSIONS,
 
 2373   LUA_SERVER_PAGE_EXTENSIONS,
 
 2374#if defined(MG_EXPERIMENTAL_INTERFACES) 
 2378#if defined(USE_DUKTAPE) 
 2379   DUKTAPE_SCRIPT_EXTENSIONS,
 
 2382#if defined(USE_WEBSOCKET) 
 2385#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
 2386   LUA_WEBSOCKET_EXTENSIONS,
 
 2393#if !defined(NO_CACHING) 
 2418#if defined(__linux__) 
 2430#if defined(USE_WEBSOCKET) 
 2439#if defined(USE_TIMERS) 
 2458     "index.xhtml,index.html,index.htm," 
 2459     "index.lp,index.lsp,index.lua,index.cgi," 
 2460     "index.shtml,index.php"},
 
 2462     "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
 
 2485#if defined(MG_EXPERIMENTAL_INTERFACES) 
 2489#if defined(USE_DUKTAPE) 
 2495#if defined(USE_WEBSOCKET) 
 2498#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
 2505#if !defined(NO_CACHING) 
 2521                 "config_options and enum not sync");
 
 2527struct mg_handler_info {
 
 2537   unsigned int refcount;
 
 2538   pthread_mutex_t refcount_mutex; 
 
 2558   struct mg_handler_info *next;
 
 2570struct mg_domain_context {
 
 2573   struct mg_handler_info *handlers; 
 
 2576   uint64_t auth_nonce_mask;  
 
 2577   unsigned long nonce_count; 
 
 2579#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
 2581   struct mg_shared_lua_websocket_list *shared_lua_websockets;
 
 2585   struct mg_domain_context *next;
 
 2600   struct socket *listening_sockets;
 
 2601   struct pollfd *listening_socket_fds;
 
 2602   unsigned int num_listening_sockets;
 
 2604   struct mg_connection *worker_connections; 
 
 2607#if defined(USE_SERVER_STATS) 
 2608   int active_connections;
 
 2609   int max_connections;
 
 2610   int64_t total_connections;
 
 2611   int64_t total_requests;
 
 2612   int64_t total_data_read;
 
 2613   int64_t total_data_written;
 
 2617   volatile int stop_flag;       
 
 2618   pthread_mutex_t thread_mutex; 
 
 2620   pthread_t masterthreadid; 
 
 2623   pthread_t *worker_threadids; 
 
 2626#if defined(ALTERNATIVE_QUEUE) 
 2627   struct socket *client_socks;
 
 2628   void **client_wait_events;
 
 2631   volatile int sq_head;         
 
 2632   volatile int sq_tail;         
 
 2638   unsigned int max_request_size; 
 
 2640#if defined(USE_SERVER_STATS) 
 2641   struct mg_memory_stat ctx_memory;
 
 2649#if defined(USE_TIMERS) 
 2650   struct ttimers *timers;
 
 2655   void *lua_background_state;
 
 2659   pthread_mutex_t nonce_mutex; 
 
 2672   struct mg_domain_context dd; 
 
 2676#if defined(USE_SERVER_STATS) 
 2677static struct mg_memory_stat mg_common_memory = {0, 0, 0};
 
 2679static struct mg_memory_stat *
 
 2680get_memory_stat(
struct mg_context *ctx)
 
 2683      return &(ctx->ctx_memory);
 
 2685   return &mg_common_memory;
 
 2695struct mg_connection {
 
 2696   int connection_type; 
 
 2701   struct mg_context *phys_ctx;
 
 2702   struct mg_domain_context *dom_ctx;
 
 2704#if defined(USE_SERVER_STATS) 
 2713   struct socket client;     
 
 2714   time_t conn_birth_time;   
 
 2716   struct timespec req_time; 
 
 2718   int64_t num_bytes_sent;   
 
 2719   int64_t content_len;      
 
 2720   int64_t consumed_content; 
 
 2727   size_t chunk_remainder;   
 
 2733   int in_error_handler; 
 
 2735#if defined(USE_WEBSOCKET) 
 2736   int in_websocket_handling; 
 
 2738   int handled_requests; 
 
 2747   time_t last_throttle_time;   
 
 2748   int64_t last_throttle_bytes; 
 
 2749   pthread_mutex_t mutex;       
 
 2751#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
 2752   void *lua_websocket_state; 
 
 2761   struct mg_connection *conn;
 
 2763   struct mg_file_stat 
file;
 
 2767#if defined(USE_WEBSOCKET) 
 2770#define is_websocket_protocol(conn) (0) 
 2774#define mg_cry_internal(conn, fmt, ...)                                        \ 
 2775   mg_cry_internal_wrap(conn, __func__, __LINE__, fmt, __VA_ARGS__) 
 2784#if !defined(NO_THREAD_NAME) 
 2785#if defined(_WIN32) && defined(_MSC_VER) 
 2789#pragma pack(push, 8) 
 2790typedef struct tagTHREADNAME_INFO {
 
 2798#elif defined(__linux__) 
 2800#include <sys/prctl.h> 
 2801#include <sys/sendfile.h> 
 2802#if defined(ALTERNATIVE_QUEUE) 
 2803#include <sys/eventfd.h> 
 2807#if defined(ALTERNATIVE_QUEUE) 
 2812   int evhdl = eventfd(0, EFD_CLOEXEC);
 
 2842   evhdl = *(
int *)eventhdl;
 
 2844   s = (
int)read(evhdl, &u, 
sizeof(u));
 
 2845   if (s != 
sizeof(u)) {
 
 2864   evhdl = *(
int *)eventhdl;
 
 2866   s = (
int)write(evhdl, &u, 
sizeof(u));
 
 2867   if (s != 
sizeof(u)) {
 
 2884   evhdl = *(
int *)eventhdl;
 
 2896#if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE) 
 2899   pthread_mutex_t mutex;
 
 2907   struct posix_event *ret = 
mg_malloc(
sizeof(
struct posix_event));
 
 2912   if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
 
 2917   if (0 != pthread_cond_init(&(ret->cond), NULL)) {
 
 2919      pthread_mutex_destroy(&(ret->mutex));
 
 2930   struct posix_event *ev = (
struct posix_event *)eventhdl;
 
 2931   pthread_mutex_lock(&(ev->mutex));
 
 2932   pthread_cond_wait(&(ev->cond), &(ev->mutex));
 
 2933   pthread_mutex_unlock(&(ev->mutex));
 
 2941   struct posix_event *ev = (
struct posix_event *)eventhdl;
 
 2942   pthread_mutex_lock(&(ev->mutex));
 
 2943   pthread_cond_signal(&(ev->cond));
 
 2944   pthread_mutex_unlock(&(ev->mutex));
 
 2952   struct posix_event *ev = (
struct posix_event *)eventhdl;
 
 2953   pthread_cond_destroy(&(ev->cond));
 
 2954   pthread_mutex_destroy(&(ev->mutex));
 
 2963   char threadName[16 + 1]; 
 
 2966       NULL, NULL, threadName, 
sizeof(threadName), 
"civetweb-%s", 
name);
 
 2969#if defined(_MSC_VER) 
 2972      THREADNAME_INFO info;
 
 2973      info.dwType = 0x1000;
 
 2974      info.szName = threadName;
 
 2975      info.dwThreadID = ~0U;
 
 2978      RaiseException(0x406D1388,
 
 2980                     sizeof(info) / 
sizeof(ULONG_PTR),
 
 2981                     (ULONG_PTR *)&info);
 
 2982   } __except (EXCEPTION_EXECUTE_HANDLER) {
 
 2984#elif defined(__MINGW32__) 
 2987#elif defined(_GNU_SOURCE) && defined(__GLIBC__)                               \ 
 2988    && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12))) 
 2990#if defined(__MACH__) 
 2992   (
void)pthread_setname_np(threadName);
 
 2994   (
void)pthread_setname_np(pthread_self(), threadName);
 
 2996#elif defined(__linux__) 
 2998   (
void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
 
 3009#if defined(MG_LEGACY_INTERFACE) 
 3011mg_get_valid_option_names(
void)
 
 3036#define MG_FOPEN_MODE_NONE (0) 
 3039#define MG_FOPEN_MODE_READ (1) 
 3042#define MG_FOPEN_MODE_WRITE (2) 
 3045#define MG_FOPEN_MODE_APPEND (4) 
 3054                    struct mg_file *filep,
 
 3057#if defined(MG_USE_OPEN_FILE) 
 3060   const char *buf = NULL;
 
 3069   if (conn->phys_ctx->callbacks.open_file) {
 
 3070      buf = conn->phys_ctx->callbacks.open_file(conn, path, &size);
 
 3072         if (filep == NULL) {
 
 3083         filep->access.membuf = buf;
 
 3084         filep->access.fp = NULL;
 
 3087         filep->stat.size = size;
 
 3091         filep->stat.last_modified = time(NULL);
 
 3093         filep->stat.is_directory = 0;
 
 3094         filep->stat.is_gzipped = 0;
 
 3098   return (buf != NULL);
 
 3126#if defined(MG_USE_OPEN_FILE) 
 3127   return (fileacc->membuf != NULL) || (fileacc->fp != NULL);
 
 3129   return (fileacc->fp != NULL);
 
 3134static int mg_stat(
const struct mg_connection *conn,
 
 3136                   struct mg_file_stat *filep);
 
 3149         struct mg_file *filep)
 
 3156   filep->access.fp = NULL;
 
 3157#if defined(MG_USE_OPEN_FILE) 
 3158   filep->access.membuf = NULL;
 
 3165      found = 
mg_stat(conn, path, &(filep->stat));
 
 3174         wchar_t wbuf[W_PATH_MAX];
 
 3175         path_to_unicode(conn, path, wbuf, 
ARRAY_SIZE(wbuf));
 
 3178            filep->access.fp = _wfopen(wbuf, L
"rb");
 
 3181            filep->access.fp = _wfopen(wbuf, L
"wb");
 
 3184            filep->access.fp = _wfopen(wbuf, L
"ab");
 
 3192         filep->access.fp = fopen(path, 
"r");
 
 3195         filep->access.fp = fopen(path, 
"w");
 
 3198         filep->access.fp = fopen(path, 
"a");
 
 3207         found = 
mg_stat(conn, path, &(filep->stat));
 
 3212      return (filep->access.fp != NULL);
 
 3215#if defined(MG_USE_OPEN_FILE) 
 3219         return (filep->access.membuf != NULL);
 
 3234   if (fileacc != NULL) {
 
 3235      if (fileacc->fp != NULL) {
 
 3236         ret = fclose(fileacc->fp);
 
 3237#if defined(MG_USE_OPEN_FILE) 
 3238      } 
else if (fileacc->membuf != NULL) {
 
 3243      memset(fileacc, 0, 
sizeof(*fileacc));
 
 3252   for (; *src != 
'\0' && 
n > 1; 
n--) {
 
 3262   return tolower(*(
const unsigned char *)s);
 
 3274      } 
while (diff == 0 && 
s1[-1] != 
'\0' && --len > 0);
 
 3288   } 
while (diff == 0 && 
s1[-1] != 
'\0');
 
 3325   size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
 
 3327   if (big_len >= small_len) {
 
 3328      for (i = 0; i <= (big_len - small_len); i++) {
 
 3358#if defined(__clang__) 
 3359#pragma clang diagnostic push 
 3360#pragma clang diagnostic ignored "-Wformat-nonliteral" 
 3366   ok = (
n >= 0) && ((
size_t)
n < buflen);
 
 3368#if defined(__clang__) 
 3369#pragma clang diagnostic pop 
 3381                      "truncating vsnprintf buffer: [%.*s]",
 
 3382                      (
int)((buflen > 200) ? 200 : (buflen - 1)),
 
 3384      n = (
int)buflen - 1;
 
 3426   } 
else if (!ctx || ctx->dd.config[i] == NULL) {
 
 3429      return ctx->dd.config[i];
 
 3433#define mg_get_option DO_NOT_USE_THIS_FUNCTION_INTERNALLY__access_directly 
 3438   return (conn == NULL) ? (
struct mg_context *)NULL : (conn->phys_ctx);
 
 3445   return (ctx == NULL) ? NULL : ctx->user_data;
 
 3453      conn->request_info.conn_data = data;
 
 3462      return conn->request_info.conn_data;
 
 3468#if defined(MG_LEGACY_INTERFACE) 
 3471mg_get_ports(
const struct mg_context *ctx, 
size_t size, 
int *ports, 
int *ssl)
 
 3477   for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
 
 3478      ssl[i] = ctx->listening_sockets[i].is_ssl;
 
 3480#if defined(USE_IPV6) 
 3481          (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
 
 3482              ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
 
 3485              ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
 
 3502   memset(ports, 0, 
sizeof(*ports) * (
size_t)size);
 
 3506   if (!ctx->listening_sockets) {
 
 3510   for (i = 0; (i < size) && (i < (
int)ctx->num_listening_sockets); i++) {
 
 3513#if defined(USE_IPV6) 
 3514          (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
 
 3515              ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
 
 3518              ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
 
 3519      ports[cnt].
is_ssl = ctx->listening_sockets[i].is_ssl;
 
 3520      ports[cnt].
is_redirect = ctx->listening_sockets[i].ssl_redir;
 
 3522      if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
 
 3526      } 
else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
 
 3546   if (usa->sa.sa_family == AF_INET) {
 
 3547      getnameinfo(&usa->sa,
 
 3555#if defined(USE_IPV6) 
 3556   else if (usa->sa.sa_family == AF_INET6) {
 
 3557      getnameinfo(&usa->sa,
 
 3574#if !defined(REENTRANT_TIME) 
 3577   tm = ((t != NULL) ? gmtime(t) : NULL);
 
 3581   struct tm *tm = &_tm;
 
 3586      strftime(buf, buf_len, 
"%a, %d %b %Y %H:%M:%S GMT", tm);
 
 3588      mg_strlcpy(buf, 
"Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
 
 3589      buf[buf_len - 1] = 
'\0';
 
 3598   return (
double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
 
 3599          + (
double)(ts_now->tv_sec - ts_before->tv_sec);
 
 3603#if defined(MG_EXTERNAL_FUNCTION_mg_cry_internal_impl) 
 3609#include "external_mg_cry_internal_impl.inl" 
 3628#if defined(GCC_DIAGNOSTIC) 
 3629#pragma GCC diagnostic push 
 3630#pragma GCC diagnostic ignored "-Wformat-nonliteral" 
 3635#if defined(GCC_DIAGNOSTIC) 
 3636#pragma GCC diagnostic pop 
 3639   buf[
sizeof(buf) - 1] = 0;
 
 3651   if ((conn->phys_ctx->callbacks.log_message == NULL)
 
 3652       || (conn->phys_ctx->callbacks.log_message(conn, buf) == 0)) {
 
 3660            fi.access.fp = NULL;
 
 3663         fi.access.fp = NULL;
 
 3666      if (fi.access.fp != NULL) {
 
 3667         flockfile(fi.access.fp);
 
 3668         timestamp = time(NULL);
 
 3671         fprintf(fi.access.fp,
 
 3672                 "[%010lu] [error] [client %s] ",
 
 3673                 (
unsigned long)timestamp,
 
 3676         if (conn->request_info.request_method != NULL) {
 
 3677            fprintf(fi.access.fp,
 
 3679                    conn->request_info.request_method,
 
 3680                    conn->request_info.request_uri
 
 3681                        ? conn->request_info.request_uri
 
 3685         fprintf(fi.access.fp, 
"%s", buf);
 
 3686         fputc(
'\n', fi.access.fp);
 
 3687         fflush(fi.access.fp);
 
 3688         funlockfile(fi.access.fp);
 
 3713mg_cry(
const struct mg_connection *conn, 
const char *fmt, ...)
 
 3722#define mg_cry DO_NOT_USE_THIS_FUNCTION__USE_mg_cry_internal 
 3727static struct mg_connection *
 
 3728fc(
struct mg_context *ctx)
 
 3730   static struct mg_connection fake_connection;
 
 3731   fake_connection.phys_ctx = ctx;
 
 3732   fake_connection.dom_ctx = &(ctx->dd);
 
 3733   return &fake_connection;
 
 3750#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE) 
 3753      struct mg_workerTLS *tls =
 
 3754          (
struct mg_workerTLS *)pthread_getspecific(
sTlsKey);
 
 3756      sprintf(txt, 
"%03i", conn->response_info.status_code);
 
 3757      if (strlen(txt) == 3) {
 
 3758         memcpy(tls->txtbuf, txt, 4);
 
 3760         strcpy(tls->txtbuf, 
"ERR");
 
 3763      ((
struct mg_connection *)conn)->request_info.local_uri =
 
 3764          ((
struct mg_connection *)conn)->request_info.request_uri =
 
 3767      ((
struct mg_connection *)conn)->request_info.num_headers =
 
 3768          conn->response_info.num_headers;
 
 3769      memcpy(((
struct mg_connection *)conn)->request_info.http_headers,
 
 3770             conn->response_info.http_headers,
 
 3771             sizeof(conn->response_info.http_headers));
 
 3777   return &conn->request_info;
 
 3790   return &conn->response_info;
 
 3797#if defined(__clang__) 
 3798#pragma clang diagnostic push 
 3799#pragma clang diagnostic ignored "-Wunreachable-code" 
 3811                                    : (ri->
is_ssl ? 
"https" : 
"http"));
 
 3815#if defined(__clang__) 
 3816#pragma clang diagnostic pop 
 3824   if ((buflen < 1) || (buf == 0) || (conn == 0)) {
 
 3859#if defined(USE_IPV6) 
 3860         int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
 
 3861         int port = is_ipv6 ? htons(conn->client.lsa.sin6.sin6_port)
 
 3862                            : htons(conn->client.lsa.sin.sin_port);
 
 3864         int port = htons(conn->client.lsa.sin.sin_port);
 
 3866         int def_port = ri->
is_ssl ? 443 : 80;
 
 3867         int auth_domain_check_enabled =
 
 3871         const char *server_domain =
 
 3877         if (port != def_port) {
 
 3878            sprintf(portstr, 
":%u", (
unsigned)port);
 
 3883         if (!auth_domain_check_enabled || !server_domain) {
 
 3889            server_domain = server_ip;
 
 3916            const char *delimiters,
 
 3917            const char *whitespace,
 
 3920   char *p, *begin_word, *end_word, *end_whitespace;
 
 3923   end_word = begin_word + strcspn(begin_word, delimiters);
 
 3926   if (end_word > begin_word) {
 
 3928      while (*p == quotechar) {
 
 3935         if (*end_word != 
'\0') {
 
 3936            size_t end_off = strcspn(end_word + 1, delimiters);
 
 3937            memmove(p, end_word, end_off + 1);
 
 3939            end_word += end_off + 1;
 
 3945      for (p++; p < end_word; p++) {
 
 3950   if (*end_word == 
'\0') {
 
 3954#if defined(GCC_DIAGNOSTIC) 
 3956#pragma GCC diagnostic push 
 3957#pragma GCC diagnostic ignored "-Wsign-conversion" 
 3960      end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
 
 3962#if defined(GCC_DIAGNOSTIC) 
 3963#pragma GCC diagnostic pop 
 3966      for (p = end_word; p < end_whitespace; p++) {
 
 3970      *buf = end_whitespace;
 
 3982   for (i = 0; i < num_hdr; i++) {
 
 3984         return hdr[i].
value;
 
 3992#if defined(USE_WEBSOCKET) 
 3999                int output_max_size)
 
 4023      return get_header(conn->request_info.http_headers,
 
 4024                        conn->request_info.num_headers,
 
 4028      return get_header(conn->response_info.http_headers,
 
 4029                        conn->response_info.num_headers,
 
 4044      return conn->request_info.http_version;
 
 4047      return conn->response_info.http_version;
 
 4065   if (val == NULL || list == NULL || *list == 
'\0') {
 
 4071   while (*list == 
' ' || *list == 
'\t')
 
 4075   if ((list = strchr(val->ptr, 
',')) != NULL) {
 
 4077      val->len = ((size_t)(list - val->ptr));
 
 4081      list = val->ptr + strlen(val->ptr);
 
 4082      val->len = ((size_t)(list - val->ptr));
 
 4086   end = (
int)val->len - 1;
 
 4087   while (end >= 0 && ((val->ptr[end] == 
' ') || (val->ptr[end] == 
'\t')))
 
 4089   val->len = (size_t)(end + 1);
 
 4091   if (val->len == 0) {
 
 4096   if (eq_val != NULL) {
 
 4100      eq_val->ptr = (
const char *)memchr(val->ptr, 
'=', val->len);
 
 4101      if (eq_val->ptr != NULL) {
 
 4103         eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
 
 4104         val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
 
 4125   while ((header = 
next_option(header, &opt_vec, &eq_vec)) != NULL) {
 
 4139   ptrdiff_t i, j, len, res;
 
 4141   if ((or_str = (
const char *)memchr(pattern, 
'|', pattern_len)) != NULL) {
 
 4142      res = 
match_prefix(pattern, (
size_t)(or_str - pattern), str);
 
 4143      return (res > 0) ? res
 
 4145                                      (
size_t)((pattern + pattern_len)
 
 4150   for (i = 0, j = 0; (i < (ptrdiff_t)pattern_len); i++, j++) {
 
 4151      if ((pattern[i] == 
'?') && (str[j] != 
'\0')) {
 
 4153      } 
else if (pattern[i] == 
'$') {
 
 4154         return (str[j] == 
'\0') ? j : -1;
 
 4155      } 
else if (pattern[i] == 
'*') {
 
 4157         if (pattern[i] == 
'*') {
 
 4159            len = strlen(str + j);
 
 4161            len = strcspn(str + j, 
"/");
 
 4163         if (i == (ptrdiff_t)pattern_len) {
 
 4167            res = 
match_prefix(pattern + i, pattern_len - i, str + j + len);
 
 4168         } 
while (res == -1 && len-- > 0);
 
 4169         return (res == -1) ? -1 : j + res + len;
 
 4174   return (ptrdiff_t)j;
 
 4184   const char *http_version;
 
 4188   if ((conn == NULL) || conn->must_close) {
 
 4210   if (http_version && (0 == strcmp(http_version, 
"1.1"))) {
 
 4223   if (!conn || !conn->dom_ctx) {
 
 4243                    "Cache-Control: no-cache, no-store, " 
 4244                    "must-revalidate, private, max-age=0\r\n" 
 4245                    "Pragma: no-cache\r\n" 
 4253#if !defined(NO_CACHING) 
 4274   return mg_printf(conn, 
"Cache-Control: max-age=%u\r\n", (
unsigned)max_age);
 
 4292                        "Strict-Transport-Security: max-age=%u\r\n",
 
 4298   if (header && header[0]) {
 
 4308                                      struct mg_file *filep);
 
 4318   switch (response_code) {
 
 4323      return "Switching Protocols"; 
 
 4325      return "Processing"; 
 
 4335      return "Non-Authoritative Information"; 
 
 4337      return "No Content"; 
 
 4339      return "Reset Content"; 
 
 4341      return "Partial Content"; 
 
 4343      return "Multi-Status"; 
 
 4346      return "Already Reported"; 
 
 4353      return "Multiple Choices"; 
 
 4355      return "Moved Permanently"; 
 
 4361      return "Not Modified"; 
 
 4365      return "Temporary Redirect"; 
 
 4367      return "Permanent Redirect"; 
 
 4371      return "Bad Request"; 
 
 4373      return "Unauthorized"; 
 
 4375      return "Payment Required"; 
 
 4381      return "Method Not Allowed"; 
 
 4383      return "Not Acceptable"; 
 
 4385      return "Proxy Authentication Required"; 
 
 4387      return "Request Time-out"; 
 
 4393      return "Length Required"; 
 
 4395      return "Precondition Failed"; 
 
 4397      return "Request Entity Too Large"; 
 
 4399      return "Request-URI Too Large"; 
 
 4401      return "Unsupported Media Type"; 
 
 4403      return "Requested range not satisfiable"; 
 
 4406      return "Expectation Failed"; 
 
 4409      return "Misdirected Request"; 
 
 4411      return "Unproccessable entity"; 
 
 4416      return "Failed Dependency"; 
 
 4420      return "Upgrade Required"; 
 
 4423      return "Precondition Required"; 
 
 4425      return "Too Many Requests"; 
 
 4428      return "Request Header Fields Too Large"; 
 
 4431      return "Unavailable For Legal Reasons"; 
 
 4436      return "Internal Server Error"; 
 
 4438      return "Not Implemented"; 
 
 4440      return "Bad Gateway"; 
 
 4442      return "Service Unavailable"; 
 
 4444      return "Gateway Time-out"; 
 
 4446      return "HTTP Version not supported"; 
 
 4448      return "Variant Also Negotiates"; 
 
 4450      return "Insufficient Storage"; 
 
 4453      return "Loop Detected"; 
 
 4456      return "Not Extended"; 
 
 4458      return "Network Authentication Required"; 
 
 4464      return "I am a teapot"; 
 
 4466      return "Authentication Timeout"; 
 
 4468      return "Enhance Your Calm"; 
 
 4470      return "Login Timeout"; 
 
 4472      return "Bandwidth Limit Exceeded"; 
 
 4478                         "Unknown HTTP response code: %u",
 
 4483      if (response_code >= 100 && response_code < 200) {
 
 4485         return "Information";
 
 4487      if (response_code >= 200 && response_code < 300) {
 
 4491      if (response_code >= 300 && response_code < 400) {
 
 4493         return "Redirection";
 
 4495      if (response_code >= 400 && response_code < 500) {
 
 4497         return "Client Error";
 
 4499      if (response_code >= 500 && response_code < 600) {
 
 4501         return "Server Error";
 
 4517   char path_buf[PATH_MAX];
 
 4519   int len, i, page_handler_found, scope, truncated, has_body;
 
 4521   time_t curtime = time(NULL);
 
 4522   const char *error_handler = NULL;
 
 4524   const char *error_page_file_ext, *tstr;
 
 4525   int handled_by_callback = 0;
 
 4529   if ((conn == NULL) || (fmt == NULL)) {
 
 4534   conn->status_code = status;
 
 4537   has_body = ((status > 199) && (status != 204) && (status != 304));
 
 4541       || (!conn->in_error_handler
 
 4542           && (conn->phys_ctx->callbacks.http_error != NULL))) {
 
 4545      mg_vsnprintf(conn, NULL, errmsg_buf, 
sizeof(errmsg_buf), fmt, ap);
 
 4548      DEBUG_TRACE(
"Error %i - [%s]", status, errmsg_buf);
 
 4554   if (!conn->in_error_handler
 
 4555       && (conn->phys_ctx->callbacks.http_error != NULL)) {
 
 4557      conn->in_error_handler = 1;
 
 4558      handled_by_callback =
 
 4559          (conn->phys_ctx->callbacks.http_error(conn, status, errmsg_buf)
 
 4561      conn->in_error_handler = 0;
 
 4564   if (!handled_by_callback) {
 
 4566      if (conn->in_error_handler) {
 
 4568             "Recursion when handling error %u - fall back to default",
 
 4572         error_handler = conn->dom_ctx->config[
ERROR_PAGES];
 
 4573         error_page_file_ext = conn->dom_ctx->config[
INDEX_FILES];
 
 4574         page_handler_found = 0;
 
 4576         if (error_handler != NULL) {
 
 4577            for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
 
 4583                              sizeof(path_buf) - 32,
 
 4594                              sizeof(path_buf) - 32,
 
 4603                              sizeof(path_buf) - 32,
 
 4614               len = (
int)strlen(path_buf);
 
 4616               tstr = strchr(error_page_file_ext, 
'.');
 
 4620                       (i < 32) && (tstr[i] != 0) && (tstr[i] != 
',');
 
 4625                     path_buf[len + i - 1] = tstr[i];
 
 4630                  path_buf[len + i - 1] = 0;
 
 4632                  if (
mg_stat(conn, path_buf, &error_page_file.stat)) {
 
 4635                     page_handler_found = 1;
 
 4641                  tstr = strchr(tstr + i, 
'.');
 
 4646         if (page_handler_found) {
 
 4647            conn->in_error_handler = 1;
 
 4649            conn->in_error_handler = 0;
 
 4657      conn->must_close = 1;
 
 4658      mg_printf(conn, 
"HTTP/1.1 %d %s\r\n", status, status_text);
 
 4664                   "Content-Type: text/plain; charset=utf-8\r\n");
 
 4668                "Connection: close\r\n\r\n",
 
 4674         mg_printf(conn, 
"Error %d: %s\n", status, status_text);
 
 4675         mg_write(conn, errmsg_buf, strlen(errmsg_buf));
 
 4703                long long content_length)
 
 4706   time_t curtime = time(NULL);
 
 4716             "HTTP/1.1 200 OK\r\n" 
 4717             "Content-Type: %s\r\n" 
 4719             "Connection: %s\r\n",
 
 4726   if (content_length < 0) {
 
 4727      mg_printf(conn, 
"Transfer-Encoding: chunked\r\n\r\n");
 
 4731                (uint64_t)content_length);
 
 4740                      const char *target_url,
 
 4754   const char *redirect_text;
 
 4756   size_t content_len = 0;
 
 4760   if (redirect_code == 0) {
 
 4761      redirect_code = 307;
 
 4765   if ((redirect_code != 301) && (redirect_code != 302)
 
 4766       && (redirect_code != 303) && (redirect_code != 307)
 
 4767       && (redirect_code != 308)) {
 
 4776   if ((target_url == NULL) || (*target_url == 0)) {
 
 4780#if defined(MG_SEND_REDIRECT_BODY) 
 4808       "<html><head>%s</head><body><a href=\"%s\">%s</a></body></html>",
 
 4812   content_len = strlen(reply);
 
 4820                   "HTTP/1.1 %i %s\r\n" 
 4822                   "Content-Length: %u\r\n" 
 4823                   "Connection: %s\r\n\r\n",
 
 4827                   (
unsigned int)content_len,
 
 4833      if (0 != strcmp(conn->request_info.request_method, 
"HEAD")) {
 
 4834         ret = 
mg_write(conn, reply, content_len);
 
 4838   return (ret > 0) ? ret : -1;
 
 4845#if defined(GCC_DIAGNOSTIC) 
 4847#pragma GCC diagnostic push 
 4848#pragma GCC diagnostic ignored "-Wunused-function" 
 4854pthread_mutex_init(pthread_mutex_t *mutex, 
void *unused)
 
 4857   *mutex = CreateMutex(NULL, 
FALSE, NULL);
 
 4858   return (*mutex == NULL) ? -1 : 0;
 
 4863pthread_mutex_destroy(pthread_mutex_t *mutex)
 
 4865   return (CloseHandle(*mutex) == 0) ? -1 : 0;
 
 4871pthread_mutex_lock(pthread_mutex_t *mutex)
 
 4873   return (WaitForSingleObject(*mutex, (DWORD)INFINITE) == WAIT_OBJECT_0) ? 0
 
 4878#if defined(ENABLE_UNUSED_PTHREAD_FUNCTIONS) 
 4881pthread_mutex_trylock(pthread_mutex_t *mutex)
 
 4883   switch (WaitForSingleObject(*mutex, 0)) {
 
 4896pthread_mutex_unlock(pthread_mutex_t *mutex)
 
 4898   return (ReleaseMutex(*mutex) == 0) ? -1 : 0;
 
 4907   InitializeCriticalSection(&cv->threadIdSec);
 
 4908   cv->waiting_thread = NULL;
 
 4916                       pthread_mutex_t *mutex,
 
 4919   struct mg_workerTLS **ptls,
 
 4920       *tls = (
struct mg_workerTLS *)pthread_getspecific(
sTlsKey);
 
 4922   int64_t nsnow, nswaitabs, nswaitrel;
 
 4925   EnterCriticalSection(&cv->threadIdSec);
 
 4927   ptls = &cv->waiting_thread;
 
 4928   for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
 
 4930   tls->next_waiting_thread = NULL;
 
 4932   LeaveCriticalSection(&cv->threadIdSec);
 
 4937          (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
 
 4938      nswaitrel = nswaitabs - nsnow;
 
 4939      if (nswaitrel < 0) {
 
 4942      mswaitrel = (DWORD)(nswaitrel / 1000000);
 
 4944      mswaitrel = (DWORD)INFINITE;
 
 4947   pthread_mutex_unlock(mutex);
 
 4949         == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
 
 4952      EnterCriticalSection(&cv->threadIdSec);
 
 4953      ptls = &cv->waiting_thread;
 
 4954      for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
 
 4956            *ptls = tls->next_waiting_thread;
 
 4961      LeaveCriticalSection(&cv->threadIdSec);
 
 4963         WaitForSingleObject(tls->pthread_cond_helper_mutex,
 
 4968   pthread_mutex_lock(mutex);
 
 4978   return pthread_cond_timedwait(cv, mutex, NULL);
 
 4989   EnterCriticalSection(&cv->threadIdSec);
 
 4990   if (cv->waiting_thread) {
 
 4991      wkup = cv->waiting_thread->pthread_cond_helper_mutex;
 
 4992      cv->waiting_thread = cv->waiting_thread->next_waiting_thread;
 
 4994      ok = SetEvent(wkup);
 
 4997   LeaveCriticalSection(&cv->threadIdSec);
 
 5007   EnterCriticalSection(&cv->threadIdSec);
 
 5008   while (cv->waiting_thread) {
 
 5009      pthread_cond_signal(cv);
 
 5011   LeaveCriticalSection(&cv->threadIdSec);
 
 5021   EnterCriticalSection(&cv->threadIdSec);
 
 5023   LeaveCriticalSection(&cv->threadIdSec);
 
 5024   DeleteCriticalSection(&cv->threadIdSec);
 
 5030#if defined(ALTERNATIVE_QUEUE) 
 5035   return (
void *)CreateEvent(NULL, 
FALSE, 
FALSE, NULL);
 
 5043   int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE);
 
 5044   return (res == WAIT_OBJECT_0);
 
 5052   return (
int)SetEvent((HANDLE)eventhdl);
 
 5060   CloseHandle((HANDLE)eventhdl);
 
 5065#if defined(GCC_DIAGNOSTIC) 
 5067#pragma GCC diagnostic pop 
 5073change_slashes_to_backslashes(
char *path)
 
 5077   for (i = 0; path[i] != 
'\0'; i++) {
 
 5078      if (path[i] == 
'/') {
 
 5084      if ((path[i] == 
'\\') && (i > 0)) {
 
 5085         while ((path[i + 1] == 
'\\') || (path[i + 1] == 
'/')) {
 
 5086            (
void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
 
 5094mg_wcscasecmp(
const wchar_t *
s1, 
const wchar_t *s2)
 
 5099      diff = tolower(*
s1) - tolower(*s2);
 
 5102   } 
while ((diff == 0) && (
s1[-1] != 
'\0'));
 
 5111path_to_unicode(
const struct mg_connection *conn,
 
 5116   char buf[PATH_MAX], buf2[PATH_MAX];
 
 5117   wchar_t wbuf2[W_PATH_MAX + 1];
 
 5118   DWORD long_len, err;
 
 5119   int (*fcompare)(
const wchar_t *, 
const wchar_t *) = mg_wcscasecmp;
 
 5122   change_slashes_to_backslashes(buf);
 
 5126   memset(wbuf, 0, wbuf_len * 
sizeof(
wchar_t));
 
 5127   MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (
int)wbuf_len);
 
 5128   WideCharToMultiByte(
 
 5129       CP_UTF8, 0, wbuf, (
int)wbuf_len, buf2, 
sizeof(buf2), NULL, NULL);
 
 5130   if (strcmp(buf, buf2) != 0) {
 
 5144      if (conn->dom_ctx->config[CASE_SENSITIVE_FILES]
 
 5145          && !
mg_strcasecmp(conn->dom_ctx->config[CASE_SENSITIVE_FILES],
 
 5153#if !defined(_WIN32_WCE) 
 5155   memset(wbuf2, 0, 
ARRAY_SIZE(wbuf2) * 
sizeof(
wchar_t));
 
 5156   long_len = GetLongPathNameW(wbuf, wbuf2, 
ARRAY_SIZE(wbuf2) - 1);
 
 5157   if (long_len == 0) {
 
 5158      err = GetLastError();
 
 5159      if (err == ERROR_FILE_NOT_FOUND) {
 
 5164   if ((long_len >= 
ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
 
 5173   if (strchr(path, 
'~')) {
 
 5185path_cannot_disclose_cgi(
const char *path)
 
 5187   static const char *allowed_last_characters = 
"_-";
 
 5188   int last = path[strlen(path) - 1];
 
 5189   return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
 
 5194mg_stat(
const struct mg_connection *conn,
 
 5196        struct mg_file_stat *filep)
 
 5198   wchar_t wbuf[W_PATH_MAX];
 
 5199   WIN32_FILE_ATTRIBUTE_DATA info;
 
 5200   time_t creation_time;
 
 5205   memset(filep, 0, 
sizeof(*filep));
 
 5215      filep->size = tmp_file.stat.size;
 
 5216      filep->location = 2;
 
 5224      filep->last_modified = time(NULL); 
 
 5236   path_to_unicode(conn, path, wbuf, 
ARRAY_SIZE(wbuf));
 
 5237   if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
 
 5238      filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
 
 5239      filep->last_modified =
 
 5240          SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
 
 5241                        info.ftLastWriteTime.dwHighDateTime);
 
 5247      creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
 
 5248                                    info.ftCreationTime.dwHighDateTime);
 
 5249      if (creation_time > filep->last_modified) {
 
 5250         filep->last_modified = creation_time;
 
 5253      filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
 
 5258      if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
 
 5259         memset(filep, 0, 
sizeof(*filep));
 
 5271mg_remove(
const struct mg_connection *conn, 
const char *path)
 
 5273   wchar_t wbuf[W_PATH_MAX];
 
 5274   path_to_unicode(conn, path, wbuf, 
ARRAY_SIZE(wbuf));
 
 5275   return DeleteFileW(wbuf) ? 0 : -1;
 
 5280mg_mkdir(
const struct mg_connection *conn, 
const char *path, 
int mode)
 
 5282   wchar_t wbuf[W_PATH_MAX];
 
 5284   path_to_unicode(conn, path, wbuf, 
ARRAY_SIZE(wbuf));
 
 5285   return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
 
 5291#if defined(GCC_DIAGNOSTIC) 
 5293#pragma GCC diagnostic push 
 5294#pragma GCC diagnostic ignored "-Wunused-function" 
 5304   wchar_t wpath[W_PATH_MAX];
 
 5308      SetLastError(ERROR_BAD_ARGUMENTS);
 
 5309   } 
else if ((dir = (DIR *)
mg_malloc(
sizeof(*dir))) == NULL) {
 
 5310      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 
 5313      attrs = GetFileAttributesW(wpath);
 
 5314      if ((wcslen(wpath) + 2 < 
ARRAY_SIZE(wpath)) && (attrs != 0xFFFFFFFF)
 
 5315          && ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
 
 5316         (
void)wcscat(wpath, L
"\\*");
 
 5317         dir->handle = FindFirstFileW(wpath, &dir->info);
 
 5318         dir->result.d_name[0] = 
'\0';
 
 5337         result = FindClose(dir->handle) ? 0 : -1;
 
 5342      SetLastError(ERROR_BAD_ARGUMENTS);
 
 5350static struct dirent *
 
 5353   struct dirent *result = 0;
 
 5357         result = &dir->result;
 
 5358         (
void)WideCharToMultiByte(CP_UTF8,
 
 5360                                   dir->info.cFileName,
 
 5363                                   sizeof(result->d_name),
 
 5367         if (!FindNextFileW(dir->handle, &dir->info)) {
 
 5368            (
void)FindClose(dir->handle);
 
 5373         SetLastError(ERROR_FILE_NOT_FOUND);
 
 5376      SetLastError(ERROR_BAD_ARGUMENTS);
 
 5383#if !defined(HAVE_POLL) 
 5390poll(
struct pollfd *pfd, 
unsigned int n, 
int milliseconds)
 
 5399   memset(&tv, 0, 
sizeof(tv));
 
 5400   tv.tv_sec = milliseconds / 1000;
 
 5401   tv.tv_usec = (milliseconds % 1000) * 1000;
 
 5405   for (i = 0; i < 
n; i++) {
 
 5406      if (pfd[i].events & POLLIN) {
 
 5407         FD_SET((
SOCKET)pfd[i].fd, &rset);
 
 5408      } 
else if (pfd[i].events & POLLOUT) {
 
 5409         FD_SET((
SOCKET)pfd[i].fd, &wset);
 
 5413      if (pfd[i].fd > maxfd) {
 
 5418   if ((result = select((
int)maxfd + 1, &rset, &wset, NULL, &tv)) > 0) {
 
 5419      for (i = 0; i < 
n; i++) {
 
 5420         if (FD_ISSET(pfd[i].fd, &rset)) {
 
 5421            pfd[i].revents |= POLLIN;
 
 5423         if (FD_ISSET(pfd[i].fd, &wset)) {
 
 5424            pfd[i].revents |= POLLOUT;
 
 5441#if defined(GCC_DIAGNOSTIC) 
 5443#pragma GCC diagnostic pop 
 5451#if defined(_WIN32_WCE) 
 5454   (
void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
 
 5462#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) 
 5466   return ((_beginthread((
void(__cdecl *)(
void *))
f, USE_STACK_SIZE, p)
 
 5467            == ((uintptr_t)(-1L)))
 
 5472       (_beginthread((
void(__cdecl *)(
void *))
f, 0, p) == ((uintptr_t)(-1L)))
 
 5483                        pthread_t *threadidptr)
 
 5486   HANDLE threadhandle;
 
 5489   uip = _beginthreadex(NULL, 0, (
unsigned(__stdcall *)(
void *))
f, p, 0, NULL);
 
 5490   threadhandle = (HANDLE)uip;
 
 5491   if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
 
 5492      *threadidptr = threadhandle;
 
 5508   dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE);
 
 5509   if (dwevent == WAIT_FAILED) {
 
 5512      if (dwevent == WAIT_OBJECT_0) {
 
 5513         CloseHandle(threadid);
 
 5521#if !defined(NO_SSL_DL) && !defined(NO_SSL) 
 5525#if defined(GCC_DIAGNOSTIC) 
 5527#pragma GCC diagnostic push 
 5528#pragma GCC diagnostic ignored "-Wunused-function" 
 5534dlopen(
const char *dll_name, 
int flags)
 
 5536   wchar_t wbuf[W_PATH_MAX];
 
 5538   path_to_unicode(NULL, dll_name, wbuf, 
ARRAY_SIZE(wbuf));
 
 5539   return LoadLibraryW(wbuf);
 
 5545dlclose(
void *handle)
 
 5549   if (FreeLibrary((HMODULE)handle) != 0) {
 
 5559#if defined(GCC_DIAGNOSTIC) 
 5561#pragma GCC diagnostic pop 
 5572kill(pid_t pid, 
int sig_num)
 
 5574   (
void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
 
 5575   (
void)CloseHandle((HANDLE)pid);
 
 5580#if !defined(WNOHANG) 
 5586waitpid(pid_t pid, 
int *status, 
int flags)
 
 5588   DWORD timeout = INFINITE;
 
 5593   if ((flags | WNOHANG) == WNOHANG) {
 
 5597   waitres = WaitForSingleObject((HANDLE)pid, timeout);
 
 5598   if (waitres == WAIT_OBJECT_0) {
 
 5601   if (waitres == WAIT_TIMEOUT) {
 
 5609trim_trailing_whitespaces(
char *s)
 
 5611   char *
e = s + strlen(s) - 1;
 
 5612   while ((
e > s) && isspace(*(
unsigned char *)
e)) {
 
 5629   char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
 
 5630       cmdline[PATH_MAX], buf[PATH_MAX];
 
 5634   PROCESS_INFORMATION pi = {0};
 
 5638   memset(&si, 0, 
sizeof(si));
 
 5641   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
 
 5642   si.wShowWindow = SW_HIDE;
 
 5644   me = GetCurrentProcess();
 
 5646                   (HANDLE)_get_osfhandle(fdin[0]),
 
 5651                   DUPLICATE_SAME_ACCESS);
 
 5653                   (HANDLE)_get_osfhandle(fdout[1]),
 
 5658                   DUPLICATE_SAME_ACCESS);
 
 5660                   (HANDLE)_get_osfhandle(fderr[1]),
 
 5665                   DUPLICATE_SAME_ACCESS);
 
 5670   SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
 
 5671                        HANDLE_FLAG_INHERIT,
 
 5673   SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
 
 5674                        HANDLE_FLAG_INHERIT,
 
 5676   SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
 
 5677                        HANDLE_FLAG_INHERIT,
 
 5682   if (interp == NULL) {
 
 5683      buf[0] = buf[1] = 
'\0';
 
 5687          conn, &truncated, cmdline, 
sizeof(cmdline), 
"%s/%s", dir, prog);
 
 5690         pi.hProcess = (pid_t)-1;
 
 5695#if defined(MG_USE_OPEN_FILE) 
 5696         p = (
char *)
file.access.membuf;
 
 5702         buf[
sizeof(buf) - 1] = 
'\0';
 
 5705      if ((buf[0] == 
'#') && (buf[1] == 
'!')) {
 
 5706         trim_trailing_whitespaces(buf + 2);
 
 5713   if (interp[0] != 
'\0') {
 
 5714      GetFullPathNameA(interp, 
sizeof(full_interp), full_interp, NULL);
 
 5715      interp = full_interp;
 
 5717   GetFullPathNameA(dir, 
sizeof(full_dir), full_dir, NULL);
 
 5719   if (interp[0] != 
'\0') {
 
 5724                  "\"%s\" \"%s\\%s\"",
 
 5739      pi.hProcess = (pid_t)-1;
 
 5744   if (CreateProcessA(NULL,
 
 5749                      CREATE_NEW_PROCESS_GROUP,
 
 5756          conn, 
"%s: CreateProcess(%s): %ld", __func__, cmdline, (
long)
ERRNO);
 
 5757      pi.hProcess = (pid_t)-1;
 
 5762   (
void)CloseHandle(si.hStdOutput);
 
 5763   (
void)CloseHandle(si.hStdError);
 
 5764   (
void)CloseHandle(si.hStdInput);
 
 5765   if (pi.hThread != NULL) {
 
 5766      (
void)CloseHandle(pi.hThread);
 
 5769   return (pid_t)pi.hProcess;
 
 5777   unsigned long non_blocking = 0;
 
 5778   return ioctlsocket(sock, (
long)FIONBIO, &non_blocking);
 
 5784   unsigned long non_blocking = 1;
 
 5785   return ioctlsocket(sock, (
long)FIONBIO, &non_blocking);
 
 5793        struct mg_file_stat *filep)
 
 5799   memset(filep, 0, 
sizeof(*filep));
 
 5807      filep->size = tmp_file.stat.size;
 
 5808      filep->last_modified = time(NULL);
 
 5809      filep->location = 2;
 
 5815   if (0 == stat(path, &st)) {
 
 5816      filep->size = (uint64_t)(st.st_size);
 
 5817      filep->last_modified = st.st_mtime;
 
 5818      filep->is_directory = S_ISDIR(st.st_mode);
 
 5829   if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
 
 5832                         "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
 
 5843   pthread_t thread_id;
 
 5844   pthread_attr_t attr;
 
 5847   (
void)pthread_attr_init(&attr);
 
 5848   (
void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
 5850#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) 
 5853   (
void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
 
 5856   result = pthread_create(&thread_id, &attr, func, param);
 
 5857   pthread_attr_destroy(&attr);
 
 5867                        pthread_t *threadidptr)
 
 5869   pthread_t thread_id;
 
 5870   pthread_attr_t attr;
 
 5873   (
void)pthread_attr_init(&attr);
 
 5875#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) 
 5878   (
void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
 
 5881   result = pthread_create(&thread_id, &attr, func, param);
 
 5882   pthread_attr_destroy(&attr);
 
 5883   if ((result == 0) && (threadidptr != NULL)) {
 
 5884      *threadidptr = thread_id;
 
 5896   result = pthread_join(threadid, NULL);
 
 5921   if ((pid = fork()) == -1) {
 
 5925                         "Error: Creating CGI process\nfork(): %s",
 
 5927   } 
else if (pid == 0) {
 
 5929      if (chdir(dir) != 0) {
 
 5931             conn, 
"%s: chdir(%s): %s", __func__, dir, strerror(
ERRNO));
 
 5932      } 
else if (dup2(fdin[0], 0) == -1) {
 
 5934                         "%s: dup2(%d, 0): %s",
 
 5938      } 
else if (dup2(fdout[1], 1) == -1) {
 
 5940                         "%s: dup2(%d, 1): %s",
 
 5944      } 
else if (dup2(fderr[1], 2) == -1) {
 
 5946                         "%s: dup2(%d, 2): %s",
 
 5954         (
void)close(fdin[0]);
 
 5955         (
void)close(fdout[1]);
 
 5956         (
void)close(fderr[1]);
 
 5959         (
void)close(fdin[1]);
 
 5960         (
void)close(fdout[0]);
 
 5961         (
void)close(fderr[0]);
 
 5968         signal(SIGCHLD, SIG_DFL);
 
 5971         if (interp == NULL) {
 
 5972            (
void)execle(prog, prog, NULL, envp);
 
 5974                            "%s: execle(%s): %s",
 
 5979            (
void)execle(interp, interp, prog, NULL, envp);
 
 5981                            "%s: execle(%s %s): %s",
 
 5999   int flags = fcntl(sock, F_GETFL, 0);
 
 6004   if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) {
 
 6013   int flags = fcntl(sock, F_GETFL, 0);
 
 6018   if (fcntl(sock, F_SETFL, flags & (~(
int)(O_NONBLOCK))) < 0) {
 
 6032   static uint64_t lfsr = 0; 
 
 6033   static uint64_t lcg = 0;  
 
 6044             | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
 
 6046      lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
 
 6054   return (lfsr ^ lcg ^ now);
 
 6062        volatile int *stop_server)
 
 6077      if ((milliseconds >= 0) && (milliseconds < ms_now)) {
 
 6078         ms_now = milliseconds;
 
 6081      result = poll(pfd, 
n, ms_now);
 
 6089      if (milliseconds > 0) {
 
 6090         milliseconds -= ms_now;
 
 6093   } 
while (milliseconds != 0);
 
 6116   uint64_t start = 0, now = 0, timeout_ns = 0;
 
 6123   typedef size_t len_t;
 
 6129      timeout_ns = (uint64_t)(timeout * 1.0E9);
 
 6166         n = (
int)fwrite(buf, 1, (
size_t)len, fp);
 
 6175         err = (
n < 0) ? 
ERRNO : 0;
 
 6177         if (err == WSAEWOULDBLOCK) {
 
 6182         if (err == EWOULDBLOCK) {
 
 6193      if (ctx->stop_flag) {
 
 6197      if ((
n > 0) || ((
n == 0) && (len == 0))) {
 
 6223         struct pollfd pfd[1];
 
 6227         pfd[0].events = POLLOUT;
 
 6228         pollres = 
mg_poll(pfd, 1, (
int)(ms_wait), &(ctx->stop_flag));
 
 6229         if (ctx->stop_flag) {
 
 6239         if ((now - start) > timeout_ns) {
 
 6261   double timeout = -1.0;
 
 6262   int64_t 
n, nwritten = 0;
 
 6272   while ((len > 0) && (ctx->stop_flag == 0)) {
 
 6273      n = 
push_inner(ctx, fp, sock, ssl, buf + nwritten, (
int)len, timeout);
 
 6275         if (nwritten == 0) {
 
 6279      } 
else if (
n == 0) {
 
 6299           struct mg_connection *conn,
 
 6309   typedef size_t len_t;
 
 6321#if !defined(_WIN32_WCE) 
 6326      nread = (
int)read(fileno(fp), buf, (size_t)len);
 
 6329      nread = (
int)fread(buf, 1, (
size_t)len, fp);
 
 6331      err = (nread < 0) ? 
ERRNO : 0;
 
 6332      if ((nread == 0) && (len > 0)) {
 
 6338   } 
else if ((conn->ssl != NULL)
 
 6339              && ((ssl_pending = 
SSL_pending(conn->ssl)) > 0)) {
 
 6343      if (ssl_pending > len) {
 
 6346      nread = 
SSL_read(conn->ssl, buf, ssl_pending);
 
 6362   } 
else if (conn->ssl != NULL) {
 
 6364      struct pollfd pfd[1];
 
 6367      pfd[0].fd = conn->client.sock;
 
 6368      pfd[0].events = POLLIN;
 
 6371                        (
int)(timeout * 1000.0),
 
 6372                        &(conn->phys_ctx->stop_flag));
 
 6373      if (conn->phys_ctx->stop_flag) {
 
 6377         nread = 
SSL_read(conn->ssl, buf, len);
 
 6393      } 
else if (pollres < 0) {
 
 6403      struct pollfd pfd[1];
 
 6406      pfd[0].fd = conn->client.sock;
 
 6407      pfd[0].events = POLLIN;
 
 6410                        (
int)(timeout * 1000.0),
 
 6411                        &(conn->phys_ctx->stop_flag));
 
 6412      if (conn->phys_ctx->stop_flag) {
 
 6416         nread = (
int)recv(conn->client.sock, buf, (len_t)len, 0);
 
 6417         err = (nread < 0) ? 
ERRNO : 0;
 
 6422      } 
else if (pollres < 0) {
 
 6431   if (conn->phys_ctx->stop_flag) {
 
 6435   if ((nread > 0) || ((nread == 0) && (len == 0))) {
 
 6443      if (err == WSAEWOULDBLOCK) {
 
 6447      } 
else if (err == WSAETIMEDOUT) {
 
 6451      } 
else if (err == WSAECONNABORTED) {
 
 6464      if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == EINTR)) {
 
 6489pull_all(FILE *fp, 
struct mg_connection *conn, 
char *buf, 
int len)
 
 6492   double timeout = -1.0;
 
 6493   uint64_t start_time = 0, now = 0, timeout_ns = 0;
 
 6498   if (timeout >= 0.0) {
 
 6500      timeout_ns = (uint64_t)(timeout * 1.0E9);
 
 6503   while ((len > 0) && (conn->phys_ctx->stop_flag == 0)) {
 
 6504      n = 
pull_inner(fp, conn, buf + nread, len, timeout);
 
 6510      } 
else if (
n == -1) {
 
 6512         if (timeout >= 0.0) {
 
 6514            if ((now - start_time) <= timeout_ns) {
 
 6519      } 
else if (
n == 0) {
 
 6522         conn->consumed_content += 
n;
 
 6543   to_read = 
sizeof(buf);
 
 6545   if (conn->is_chunked) {
 
 6548      while (conn->is_chunked != 3) {
 
 6549         nread = 
mg_read(conn, buf, to_read);
 
 6557      while (conn->consumed_content < conn->content_len) {
 
 6559             > (
size_t)(conn->content_len - conn->consumed_content)) {
 
 6560            to_read = (size_t)(conn->content_len - conn->consumed_content);
 
 6563         nread = 
mg_read(conn, buf, to_read);
 
 6575   int64_t 
n, buffered_len, nread;
 
 6577       (int64_t)((len > INT_MAX) ? INT_MAX : len); 
 
 6589   if (conn->consumed_content == 0) {
 
 6590      if (conn->is_chunked == 1) {
 
 6591         conn->content_len = len64;
 
 6592         conn->is_chunked = 2;
 
 6593      } 
else if (conn->content_len == -1) {
 
 6597         conn->must_close = 1;
 
 6602   if (conn->consumed_content < conn->content_len) {
 
 6604      int64_t left_to_read = conn->content_len - conn->consumed_content;
 
 6605      if (left_to_read < len64) {
 
 6609         len64 = left_to_read;
 
 6613      buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
 
 6614                     - conn->consumed_content;
 
 6615      if (buffered_len > 0) {
 
 6616         if (len64 < buffered_len) {
 
 6617            buffered_len = len64;
 
 6619         body = conn->buf + conn->request_len + conn->consumed_content;
 
 6620         memcpy(buf, body, (
size_t)buffered_len);
 
 6621         len64 -= buffered_len;
 
 6622         conn->consumed_content += buffered_len;
 
 6623         nread += buffered_len;
 
 6624         buf = (
char *)buf + buffered_len;
 
 6630      if ((
n = 
pull_all(NULL, conn, (
char *)buf, (
int)len64)) >= 0) {
 
 6633         nread = ((nread > 0) ? nread : 
n);
 
 6655mg_read(
struct mg_connection *conn, 
void *buf, 
size_t len)
 
 6657   if (len > INT_MAX) {
 
 6665   if (conn->is_chunked) {
 
 6666      size_t all_read = 0;
 
 6669         if (conn->is_chunked == 3) {
 
 6674         if (conn->chunk_remainder) {
 
 6678                ((conn->chunk_remainder > len) ? (len)
 
 6679                                               : (conn->chunk_remainder));
 
 6681            conn->content_len += (
int)read_now;
 
 6690            all_read += (size_t)read_ret;
 
 6691            conn->chunk_remainder -= (size_t)read_ret;
 
 6692            len -= (size_t)read_ret;
 
 6694            if (conn->chunk_remainder == 0) {
 
 6698               conn->content_len += 2;
 
 6701               if ((
x1 != 
'\r') || (
x2 != 
'\n')) {
 
 6712            unsigned long chunkSize = 0;
 
 6714            for (i = 0; i < ((
int)
sizeof(lenbuf) - 1); i++) {
 
 6715               conn->content_len++;
 
 6717               if ((i > 0) && (lenbuf[i] == 
'\r')
 
 6718                   && (lenbuf[i - 1] != 
'\r')) {
 
 6721               if ((i > 1) && (lenbuf[i] == 
'\n')
 
 6722                   && (lenbuf[i - 1] == 
'\r')) {
 
 6724                  chunkSize = strtoul(lenbuf, &end, 16);
 
 6725                  if (chunkSize == 0) {
 
 6727                     conn->is_chunked = 3;
 
 6731               if (!isxdigit(lenbuf[i])) {
 
 6736            if ((end == NULL) || (*end != 
'\r')) {
 
 6740            if (chunkSize == 0) {
 
 6744            conn->chunk_remainder = chunkSize;
 
 6748      return (
int)all_read;
 
 6755mg_write(
struct mg_connection *conn, 
const void *buf, 
size_t len)
 
 6758   int64_t 
n, 
total, allowed;
 
 6764   if (conn->throttle > 0) {
 
 6765      if ((now = time(NULL)) != conn->last_throttle_time) {
 
 6766         conn->last_throttle_time = now;
 
 6767         conn->last_throttle_bytes = 0;
 
 6769      allowed = conn->throttle - conn->last_throttle_bytes;
 
 6770      if (allowed > (int64_t)len) {
 
 6771         allowed = (int64_t)len;
 
 6780         buf = (
const char *)buf + 
total;
 
 6781         conn->last_throttle_bytes += 
total;
 
 6782         while ((
total < (int64_t)len) && (conn->phys_ctx->stop_flag == 0)) {
 
 6783            allowed = (conn->throttle > ((int64_t)len - 
total))
 
 6784                          ? (int64_t)len - 
total 
 6796            conn->last_throttle_bytes = allowed;
 
 6797            conn->last_throttle_time = time(NULL);
 
 6798            buf = (
const char *)buf + 
n;
 
 6811      conn->num_bytes_sent += 
total;
 
 6821              unsigned int chunk_len)
 
 6829   sprintf(lenbuf, 
"%x\r\n", chunk_len);
 
 6830   lenbuf_len = strlen(lenbuf);
 
 6833   ret = 
mg_write(conn, lenbuf, lenbuf_len);
 
 6834   if (ret != (
int)lenbuf_len) {
 
 6839   ret = 
mg_write(conn, chunk, chunk_len);
 
 6840   if (ret != (
int)chunk_len) {
 
 6855#if defined(GCC_DIAGNOSTIC) 
 6858#pragma GCC diagnostic push 
 6859#pragma GCC diagnostic ignored "-Wformat-nonliteral" 
 6886      (*buf)[size - 1] = 0;
 
 6900              size_t prealloc_size,
 
 6926   } 
else if ((
size_t)(len) >= prealloc_size) {
 
 6929      *out_buf = (
char *)
mg_malloc((
size_t)(len) + 1);
 
 6947      *out_buf = prealloc_buf;
 
 6954#if defined(GCC_DIAGNOSTIC) 
 6956#pragma GCC diagnostic pop 
 6961mg_vprintf(
struct mg_connection *conn, 
const char *fmt, va_list ap)
 
 6967   if ((len = 
alloc_vprintf(&buf, mem, 
sizeof(mem), fmt, ap)) > 0) {
 
 6968      len = 
mg_write(conn, buf, (
size_t)len);
 
 6970   if ((buf != mem) && (buf != NULL)) {
 
 6997              int is_form_url_encoded)
 
 7000#define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W')) 
 7002   for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
 
 7003      if ((i < src_len - 2) && (src[i] == 
'%')
 
 7004          && isxdigit(*(
const unsigned char *)(src + i + 1))
 
 7005          && isxdigit(*(
const unsigned char *)(src + i + 2))) {
 
 7006         a = tolower(*(
const unsigned char *)(src + i + 1));
 
 7007         b = tolower(*(
const unsigned char *)(src + i + 2));
 
 7010      } 
else if (is_form_url_encoded && (src[i] == 
'+')) {
 
 7019   return (i >= src_len) ? j : -1;
 
 7042   const char *p, *
e, *s;
 
 7046   if ((dst == NULL) || (dst_len == 0)) {
 
 7048   } 
else if ((data == NULL) || (
name == NULL) || (data_len == 0)) {
 
 7052      name_len = strlen(
name);
 
 7053      e = data + data_len;
 
 7058      for (p = data; p + name_len < 
e; p++) {
 
 7059         if (((p == data) || (p[-1] == 
'&')) && (p[name_len] == 
'=')
 
 7065            s = (
const char *)memchr(p, 
'&', (
size_t)(
e - p));
 
 7094              const char *var_name,
 
 7098   const char *s, *p, *end;
 
 7099   int name_len, len = -1;
 
 7101   if ((dst == NULL) || (dst_size == 0)) {
 
 7106   if ((var_name == NULL) || ((s = cookie_header) == NULL)) {
 
 7110   name_len = (
int)strlen(var_name);
 
 7111   end = s + strlen(s);
 
 7112   for (; (s = 
mg_strcasestr(s, var_name)) != NULL; s += name_len) {
 
 7113      if (s[name_len] == 
'=') {
 
 7115         if ((s == cookie_header) || (s[-1] == 
' ')) {
 
 7117            if ((p = strchr(s, 
' ')) == NULL) {
 
 7123            if ((*s == 
'"') && (p[-1] == 
'"') && (p > s + 1)) {
 
 7127            if ((
size_t)(p - s) < dst_size) {
 
 7141#if defined(USE_WEBSOCKET) || defined(USE_LUA) 
 7143base64_encode(
const unsigned char *src, 
int src_len, 
char *dst)
 
 7145   static const char *b64 =
 
 7146       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 7149   for (i = j = 0; i < src_len; i += 3) {
 
 7151      b = ((i + 1) >= src_len) ? 0 : src[i + 1];
 
 7152      c = ((i + 2) >= src_len) ? 0 : src[i + 2];
 
 7154      dst[j++] = b64[
a >> 2];
 
 7155      dst[j++] = b64[((
a & 3) << 4) | (
b >> 4)];
 
 7156      if (i + 1 < src_len) {
 
 7157         dst[j++] = b64[(
b & 15) << 2 | (
c >> 6)];
 
 7159      if (i + 2 < src_len) {
 
 7160         dst[j++] = b64[
c & 63];
 
 7163   while (j % 4 != 0) {
 
 7173b64reverse(
char letter)
 
 7175   if ((letter >= 
'A') && (letter <= 
'Z')) {
 
 7176      return letter - 
'A';
 
 7178   if ((letter >= 
'a') && (letter <= 
'z')) {
 
 7179      return letter - 
'a' + 26;
 
 7181   if ((letter >= 
'0') && (letter <= 
'9')) {
 
 7182      return letter - 
'0' + 52;
 
 7184   if (letter == 
'+') {
 
 7187   if (letter == 
'/') {
 
 7190   if (letter == 
'=') {
 
 7198base64_decode(
const unsigned char *src, 
int src_len, 
char *dst, 
size_t *dst_len)
 
 7201   unsigned char a, 
b, 
c, 
d;
 
 7205   for (i = 0; i < src_len; i += 4) {
 
 7206      a = b64reverse(src[i]);
 
 7211      b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]);
 
 7216      c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]);
 
 7221      d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]);
 
 7226      dst[(*dst_len)++] = (
a << 2) + (
b >> 4);
 
 7228         dst[(*dst_len)++] = (
b << 4) + (
c >> 2);
 
 7230            dst[(*dst_len)++] = (
c << 6) + 
d;
 
 7243      const char *s = conn->request_info.request_method;
 
 7245             && (!strcmp(s, 
"PUT") || !strcmp(s, 
"DELETE")
 
 7246                 || !strcmp(s, 
"MKCOL") || !strcmp(s, 
"PATCH"));
 
 7252#if !defined(NO_FILES) 
 7255    struct mg_connection *conn, 
 
 7256    const char *filename        
 
 7268   if (
match_prefix(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS],
 
 7269                    strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS]),
 
 7275#if defined(USE_DUKTAPE) 
 7276   if (
match_prefix(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
 
 7277                    strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
 
 7299                      struct mg_file_stat *filestat)
 
 7301   const char *list = conn->dom_ctx->config[
INDEX_FILES];
 
 7302   struct vec filename_vec;
 
 7303   size_t n = strlen(path);
 
 7309   while ((
n > 0) && (path[
n - 1] == 
'/')) {
 
 7316   while ((list = 
next_option(list, &filename_vec, NULL)) != NULL) {
 
 7318      if ((filename_vec.len + 1) > (path_len - (
n + 1))) {
 
 7323      mg_strlcpy(path + 
n + 1, filename_vec.ptr, filename_vec.len + 1);
 
 7326      if (
mg_stat(conn, path, filestat)) {
 
 7346              size_t filename_buf_len,    
 
 7347              struct mg_file_stat *filestat, 
 
 7349              int *is_script_resource,       
 
 7350              int *is_websocket_request,     
 
 7351              int *is_put_or_delete_request  
 
 7354   char const *accept_encoding;
 
 7356#if !defined(NO_FILES) 
 7357   const char *uri = conn->request_info.local_uri;
 
 7359   const char *rewrite;
 
 7361   ptrdiff_t match_len;
 
 7362   char gz_path[PATH_MAX];
 
 7364#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) 
 7366   size_t tmp_str_len, sep_pos;
 
 7367   int allow_substitute_script_subresources;
 
 7370   (
void)filename_buf_len; 
 
 7374   memset(filestat, 0, 
sizeof(*filestat));
 
 7377   *is_script_resource = 0;
 
 7384#if defined(USE_WEBSOCKET) 
 7386#if !defined(NO_FILES) 
 7387   if (*is_websocket_request && conn->dom_ctx->config[WEBSOCKET_ROOT]) {
 
 7388      root = conn->dom_ctx->config[WEBSOCKET_ROOT];
 
 7392   *is_websocket_request = 0;
 
 7396   conn->accept_gzip = 0;
 
 7397   if ((accept_encoding = 
mg_get_header(conn, 
"Accept-Encoding")) != NULL) {
 
 7398      if (strstr(accept_encoding, 
"gzip") != NULL) {
 
 7399         conn->accept_gzip = 1;
 
 7403#if !defined(NO_FILES) 
 7419       conn, &truncated, filename, filename_buf_len - 1, 
"%s%s", root, uri);
 
 7422      goto interpret_cleanup;
 
 7432                     filename_buf_len - 1,
 
 7442      goto interpret_cleanup;
 
 7448   if (
mg_stat(conn, filename, filestat)) {
 
 7449      int uri_len = (
int)strlen(uri);
 
 7450      int is_uri_end_slash = (uri_len > 0) && (uri[uri_len - 1] == 
'/');
 
 7468         *is_script_resource = (!*is_put_or_delete_request);
 
 7473      if (filestat->is_directory && is_uri_end_slash) {
 
 7476         struct mg_file_stat tmp_filestat;
 
 7477         memset(&tmp_filestat, 0, 
sizeof(tmp_filestat));
 
 7480                 conn, filename, filename_buf_len, &tmp_filestat)) {
 
 7484            *filestat = tmp_filestat;
 
 7488               *is_script_resource = 1;
 
 7491               *is_script_resource = 0;
 
 7492               *is_found = (
mg_stat(conn, filename, filestat) ? 1 : 0);
 
 7508   if (conn->accept_gzip) {
 
 7510          conn, &truncated, gz_path, 
sizeof(gz_path), 
"%s.gz", filename);
 
 7513         goto interpret_cleanup;
 
 7516      if (
mg_stat(conn, gz_path, filestat)) {
 
 7518            filestat->is_gzipped = 1;
 
 7526#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) 
 7529   tmp_str_len = strlen(filename);
 
 7530   tmp_str = (
char *)
mg_malloc_ctx(tmp_str_len + PATH_MAX + 1, conn->phys_ctx);
 
 7533      goto interpret_cleanup;
 
 7535   memcpy(tmp_str, filename, tmp_str_len + 1);
 
 7538   allow_substitute_script_subresources =
 
 7542   sep_pos = tmp_str_len;
 
 7543   while (sep_pos > 0) {
 
 7545      if (tmp_str[sep_pos] == 
'/') {
 
 7546         int is_script = 0, does_exist = 0;
 
 7548         tmp_str[sep_pos] = 0;
 
 7551            does_exist = 
mg_stat(conn, tmp_str, filestat);
 
 7554         if (does_exist && is_script) {
 
 7555            filename[sep_pos] = 0;
 
 7556            memmove(filename + sep_pos + 2,
 
 7557                    filename + sep_pos + 1,
 
 7558                    strlen(filename + sep_pos + 1) + 1);
 
 7559            conn->path_info = filename + sep_pos + 1;
 
 7560            filename[sep_pos + 1] = 
'/';
 
 7561            *is_script_resource = 1;
 
 7566         if (allow_substitute_script_subresources) {
 
 7568                    conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) {
 
 7575                  DEBUG_TRACE(
"Substitute script %s serving path %s",
 
 7593                     goto interpret_cleanup;
 
 7595                  sep_pos = strlen(tmp_str);
 
 7596                  filename[sep_pos] = 0;
 
 7597                  conn->path_info = filename + sep_pos + 1;
 
 7598                  *is_script_resource = 1;
 
 7609                  filename[sep_pos] = 0;
 
 7610                  conn->path_info = 0;
 
 7611                  *is_script_resource = 0;
 
 7618         tmp_str[sep_pos] = 
'/';
 
 7628#if !defined(NO_FILES) 
 7631   memset(filestat, 0, 
sizeof(*filestat));
 
 7634   *is_script_resource = 0;
 
 7635   *is_websocket_request = 0;
 
 7636   *is_put_or_delete_request = 0;
 
 7649   for (i = 0; i < buflen; i++) {
 
 7651      const unsigned char c = ((
const unsigned char *)buf)[i];
 
 7653      if ((
c < 128) && ((char)
c != 
'\r') && ((char)
c != 
'\n')
 
 7659      if (i < buflen - 1) {
 
 7660         if ((buf[i] == 
'\n') && (buf[i + 1] == 
'\n')) {
 
 7669      if (i < buflen - 3) {
 
 7670         if ((buf[i] == 
'\r') && (buf[i + 1] == 
'\n') && (buf[i + 2] == 
'\r')
 
 7671             && (buf[i + 3] == 
'\n')) {
 
 7682#if !defined(NO_CACHING) 
 7703   char month_str[32] = {0};
 
 7704   int second, minute, hour, day, month, year;
 
 7705   time_t result = (time_t)0;
 
 7708   if ((sscanf(datetime,
 
 7709               "%d/%3s/%d %d:%d:%d",
 
 7717       || (sscanf(datetime,
 
 7718                  "%d %3s %d %d:%d:%d",
 
 7726       || (sscanf(datetime,
 
 7727                  "%*3s, %d %3s %d %d:%d:%d",
 
 7735       || (sscanf(datetime,
 
 7736                  "%d-%3s-%d %d:%d:%d",
 
 7745      if ((month >= 0) && (year >= 1970)) {
 
 7746         memset(&tm, 0, 
sizeof(tm));
 
 7747         tm.tm_year = year - 1900;
 
 7753         result = timegm(&tm);
 
 7769   while ((s[0] == 
'.') && (s[1] == 
'.')) {
 
 7773   while (*s != 
'\0') {
 
 7775      if ((s[-1] == 
'/') || (s[-1] == 
'\\')) {
 
 7777         while (s[0] != 
'\0') {
 
 7778            if ((s[0] == 
'/') || (s[0] == 
'\\')) {
 
 7780            } 
else if ((s[0] == 
'.') && (s[1] == 
'.')) {
 
 7792static const struct {
 
 7800    {
".doc", 4, 
"application/msword"},
 
 7801    {
".eps", 4, 
"application/postscript"},
 
 7802    {
".exe", 4, 
"application/octet-stream"},
 
 7803    {
".js", 3, 
"application/javascript"},
 
 7804    {
".json", 5, 
"application/json"},
 
 7805    {
".pdf", 4, 
"application/pdf"},
 
 7806    {
".ps", 3, 
"application/postscript"},
 
 7807    {
".rtf", 4, 
"application/rtf"},
 
 7808    {
".xhtml", 6, 
"application/xhtml+xml"},
 
 7809    {
".xsl", 4, 
"application/xml"},
 
 7810    {
".xslt", 5, 
"application/xml"},
 
 7813    {
".ttf", 4, 
"application/font-sfnt"},
 
 7814    {
".cff", 4, 
"application/font-sfnt"},
 
 7815    {
".otf", 4, 
"application/font-sfnt"},
 
 7816    {
".aat", 4, 
"application/font-sfnt"},
 
 7817    {
".sil", 4, 
"application/font-sfnt"},
 
 7818    {
".pfr", 4, 
"application/font-tdpfr"},
 
 7819    {
".woff", 5, 
"application/font-woff"},
 
 7822    {
".mp3", 4, 
"audio/mpeg"},
 
 7823    {
".oga", 4, 
"audio/ogg"},
 
 7824    {
".ogg", 4, 
"audio/ogg"},
 
 7827    {
".gif", 4, 
"image/gif"},
 
 7828    {
".ief", 4, 
"image/ief"},
 
 7829    {
".jpeg", 5, 
"image/jpeg"},
 
 7830    {
".jpg", 4, 
"image/jpeg"},
 
 7831    {
".jpm", 4, 
"image/jpm"},
 
 7832    {
".jpx", 4, 
"image/jpx"},
 
 7833    {
".png", 4, 
"image/png"},
 
 7834    {
".svg", 4, 
"image/svg+xml"},
 
 7835    {
".tif", 4, 
"image/tiff"},
 
 7836    {
".tiff", 5, 
"image/tiff"},
 
 7839    {
".wrl", 4, 
"model/vrml"},
 
 7842    {
".css", 4, 
"text/css"},
 
 7843    {
".csv", 4, 
"text/csv"},
 
 7844    {
".htm", 4, 
"text/html"},
 
 7845    {
".html", 5, 
"text/html"},
 
 7846    {
".sgm", 4, 
"text/sgml"},
 
 7847    {
".shtm", 5, 
"text/html"},
 
 7848    {
".shtml", 6, 
"text/html"},
 
 7849    {
".txt", 4, 
"text/plain"},
 
 7850    {
".xml", 4, 
"text/xml"},
 
 7853    {
".mov", 4, 
"video/quicktime"},
 
 7854    {
".mp4", 4, 
"video/mp4"},
 
 7855    {
".mpeg", 5, 
"video/mpeg"},
 
 7856    {
".mpg", 4, 
"video/mpeg"},
 
 7857    {
".ogv", 4, 
"video/ogg"},
 
 7858    {
".qt", 3, 
"video/quicktime"},
 
 7863    {
".arj", 4, 
"application/x-arj-compressed"},
 
 7864    {
".gz", 3, 
"application/x-gunzip"},
 
 7865    {
".rar", 4, 
"application/x-arj-compressed"},
 
 7866    {
".swf", 4, 
"application/x-shockwave-flash"},
 
 7867    {
".tar", 4, 
"application/x-tar"},
 
 7868    {
".tgz", 4, 
"application/x-tar-gz"},
 
 7869    {
".torrent", 8, 
"application/x-bittorrent"},
 
 7870    {
".ppt", 4, 
"application/x-mspowerpoint"},
 
 7871    {
".xls", 4, 
"application/x-msexcel"},
 
 7872    {
".zip", 4, 
"application/x-zip-compressed"},
 
 7876    {
".aif", 4, 
"audio/x-aif"},
 
 7877    {
".m3u", 4, 
"audio/x-mpegurl"},
 
 7878    {
".mid", 4, 
"audio/x-midi"},
 
 7879    {
".ra", 3, 
"audio/x-pn-realaudio"},
 
 7880    {
".ram", 4, 
"audio/x-pn-realaudio"},
 
 7881    {
".wav", 4, 
"audio/x-wav"},
 
 7882    {
".bmp", 4, 
"image/bmp"},
 
 7883    {
".ico", 4, 
"image/x-icon"},
 
 7884    {
".pct", 4, 
"image/x-pct"},
 
 7885    {
".pict", 5, 
"image/pict"},
 
 7886    {
".rgb", 4, 
"image/x-rgb"},
 
 7887    {
".webm", 5, 
"video/webm"}, 
 
 7888    {
".asf", 4, 
"video/x-ms-asf"},
 
 7889    {
".avi", 4, 
"video/x-msvideo"},
 
 7890    {
".m4v", 4, 
"video/x-m4v"},
 
 7900   path_len = strlen(path);
 
 7910   return "text/plain";
 
 7919   struct vec ext_vec, mime_vec;
 
 7920   const char *list, *ext;
 
 7923   path_len = strlen(path);
 
 7925   if ((conn == NULL) || (vec == NULL)) {
 
 7927         memset(vec, 
'\0', 
sizeof(
struct vec));
 
 7935   while ((list = 
next_option(list, &ext_vec, &mime_vec)) != NULL) {
 
 7937      ext = path + path_len - ext_vec.len;
 
 7945   vec->len = strlen(vec->ptr);
 
 7952bin2str(
char *to, 
const unsigned char *p, 
size_t len)
 
 7954   static const char *hex = 
"0123456789abcdef";
 
 7956   for (; len--; p++) {
 
 7957      *to++ = hex[p[0] >> 4];
 
 7958      *to++ = hex[p[0] & 0x0f];
 
 7977   while ((p = va_arg(ap, 
const char *)) != NULL) {
 
 7983   bin2str(buf, hash, 
sizeof(hash));
 
 7997               const char *response)
 
 7999   char ha2[32 + 1], expected_response[32 + 1];
 
 8002   if ((method == NULL) || (nonce == NULL) || (nc == NULL) || (cnonce == NULL)
 
 8003       || (qop == NULL) || (response == NULL)) {
 
 8008   if (strlen(response) != 32) {
 
 8012   mg_md5(ha2, method, 
":", uri, NULL);
 
 8013   mg_md5(expected_response,
 
 8036               struct mg_file *filep)
 
 8038   if ((conn != NULL) && (conn->dom_ctx != NULL)) {
 
 8039      char name[PATH_MAX];
 
 8044      if (gpass != NULL) {
 
 8057      } 
else if (
mg_stat(conn, path, &filep->stat)
 
 8058                 && filep->stat.is_directory) {
 
 8078         for (p = path, 
e = p + strlen(p) - 1; 
e > p; 
e--) {
 
 8108   char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
 
 8119   char *
name, *value, *s;
 
 8120   const char *auth_header;
 
 8127   (
void)memset(ah, 0, 
sizeof(*ah));
 
 8128   if (((auth_header = 
mg_get_header(conn, 
"Authorization")) == NULL)
 
 8140      while (isspace(*(
unsigned char *)s)) {
 
 8156      if (*
name == 
'\0') {
 
 8160      if (!strcmp(
name, 
"username")) {
 
 8162      } 
else if (!strcmp(
name, 
"cnonce")) {
 
 8164      } 
else if (!strcmp(
name, 
"response")) {
 
 8165         ah->response = value;
 
 8166      } 
else if (!strcmp(
name, 
"uri")) {
 
 8168      } 
else if (!strcmp(
name, 
"qop")) {
 
 8170      } 
else if (!strcmp(
name, 
"nc")) {
 
 8172      } 
else if (!strcmp(
name, 
"nonce")) {
 
 8177#if !defined(NO_NONCE_CHECK) 
 8179   if (ah->nonce == NULL) {
 
 8183   nonce = strtoull(ah->nonce, &s, 10);
 
 8184   if ((s == NULL) || (*s != 0)) {
 
 8189   nonce ^= conn->dom_ctx->auth_nonce_mask;
 
 8199   if (nonce < (uint64_t)conn->phys_ctx->start_time) {
 
 8206   if (nonce >= ((uint64_t)conn->phys_ctx->start_time
 
 8207                 + conn->dom_ctx->nonce_count)) {
 
 8215   if (ah->user != NULL) {
 
 8216      conn->request_info.remote_user =
 
 8227mg_fgets(
char *buf, 
size_t size, 
struct mg_file *filep, 
char **p)
 
 8229#if defined(MG_USE_OPEN_FILE) 
 8241#if defined(MG_USE_OPEN_FILE) 
 8242   if ((filep->access.membuf != NULL) && (*p != NULL)) {
 
 8243      memend = (
const char *)&filep->access.membuf[filep->stat.size];
 
 8245      eof = (
char *)memchr(*p, 
'\n', (
size_t)(memend - *p));
 
 8252          ((size_t)(eof - *p) > (size - 1)) ? (size - 1) : (size_t)(eof - *p);
 
 8253      memcpy(buf, *p, len);
 
 8256      return len ? eof : NULL;
 
 8259       if (filep->access.fp != NULL) {
 
 8260      return fgets(buf, (
int)size, filep->access.fp);
 
 8272#define INITIAL_DEPTH 9 
 8273#if INITIAL_DEPTH <= 0 
 8274#error Bad INITIAL_DEPTH for recursion, set to at least 1 
 8277struct read_auth_file_struct {
 
 8278   struct mg_connection *conn;
 
 8281   char buf[256 + 256 + 40];
 
 8283   const char *f_domain;
 
 8290               struct read_auth_file_struct *workdata,
 
 8294   int is_authorized = 0;
 
 8298   if (!filep || !workdata || (0 == depth)) {
 
 8303#if defined(MG_USE_OPEN_FILE) 
 8304   p = (
char *)filep->access.membuf;
 
 8306   while (
mg_fgets(workdata->buf, 
sizeof(workdata->buf), filep, &p) != NULL) {
 
 8307      l = strlen(workdata->buf);
 
 8309         if (isspace(workdata->buf[
l - 1])
 
 8310             || iscntrl(workdata->buf[
l - 1])) {
 
 8312            workdata->buf[
l] = 0;
 
 8320      workdata->f_user = workdata->buf;
 
 8322      if (workdata->f_user[0] == 
':') {
 
 8326         if (workdata->f_user[1] == 
'#') {
 
 8329         } 
else if (!strncmp(workdata->f_user + 1, 
"include=", 8)) {
 
 8331                         workdata->f_user + 9,
 
 8342               if (is_authorized) {
 
 8343                  return is_authorized;
 
 8347                               "%s: cannot open authorization file: %s",
 
 8356                         "%s: syntax error in authorization file: %s",
 
 8362      workdata->f_domain = strchr(workdata->f_user, 
':');
 
 8363      if (workdata->f_domain == NULL) {
 
 8365                         "%s: syntax error in authorization file: %s",
 
 8370      *(
char *)(workdata->f_domain) = 0;
 
 8371      (workdata->f_domain)++;
 
 8373      workdata->f_ha1 = strchr(workdata->f_domain, 
':');
 
 8374      if (workdata->f_ha1 == NULL) {
 
 8376                         "%s: syntax error in authorization file: %s",
 
 8381      *(
char *)(workdata->f_ha1) = 0;
 
 8382      (workdata->f_ha1)++;
 
 8384      if (!strcmp(workdata->ah.user, workdata->f_user)
 
 8385          && !strcmp(workdata->domain, workdata->f_domain)) {
 
 8386         return check_password(workdata->conn->request_info.request_method,
 
 8391                               workdata->ah.cnonce,
 
 8393                               workdata->ah.response);
 
 8397   return is_authorized;
 
 8403authorize(
struct mg_connection *conn, 
struct mg_file *filep, 
const char *realm)
 
 8405   struct read_auth_file_struct workdata;
 
 8408   if (!conn || !conn->dom_ctx) {
 
 8412   memset(&workdata, 0, 
sizeof(workdata));
 
 8413   workdata.conn = conn;
 
 8420      workdata.domain = realm;
 
 8433                                      const char *filename)
 
 8438   if (!conn || !filename) {
 
 8457   char fname[PATH_MAX];
 
 8458   struct vec uri_vec, filename_vec;
 
 8461   int authorized = 1, truncated;
 
 8463   if (!conn || !conn->dom_ctx) {
 
 8468   while ((list = 
next_option(list, &uri_vec, &filename_vec)) != NULL) {
 
 8469      if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
 
 8475                     (
int)filename_vec.len,
 
 8481                            "%s: cannot open %s: %s",
 
 8508   time_t curtime = time(NULL);
 
 8509   uint64_t nonce = (uint64_t)(conn->phys_ctx->start_time);
 
 8515   (
void)pthread_mutex_lock(&conn->phys_ctx->nonce_mutex);
 
 8516   nonce += conn->dom_ctx->nonce_count;
 
 8517   ++conn->dom_ctx->nonce_count;
 
 8518   (
void)pthread_mutex_unlock(&conn->phys_ctx->nonce_mutex);
 
 8520   nonce ^= conn->dom_ctx->auth_nonce_mask;
 
 8521   conn->status_code = 401;
 
 8522   conn->must_close = 1;
 
 8526   mg_printf(conn, 
"HTTP/1.1 401 Unauthorized\r\n");
 
 8531             "Connection: %s\r\n" 
 8532             "Content-Length: 0\r\n" 
 8533             "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", " 
 8549   if (conn && conn->dom_ctx) {
 
 8557#if !defined(NO_FILES) 
 8566      if (passfile != NULL
 
 8586   char line[512], u[512] = 
"", 
d[512] = 
"", ha1[33], tmp[PATH_MAX + 8];
 
 8593   if ((pass != NULL) && (pass[0] == 
'\0')) {
 
 8598   if ((fname == NULL) || (domain == NULL) || (user == NULL)) {
 
 8605   if (strchr(user, 
':') != NULL) {
 
 8608   if (strchr(domain, 
':') != NULL) {
 
 8614   for (i = 0; ((i < 255) && (user[i] != 0)); i++) {
 
 8615      if (iscntrl(user[i])) {
 
 8622   for (i = 0; ((i < 255) && (domain[i] != 0)); i++) {
 
 8623      if (iscntrl(domain[i])) {
 
 8632   if ((strlen(fname) + 4) >= PATH_MAX) {
 
 8638   strcat(tmp, 
".tmp");
 
 8642   if ((fp = fopen(fname, 
"a+")) != NULL) {
 
 8647   if ((fp = fopen(fname, 
"r")) == NULL) {
 
 8649   } 
else if ((fp2 = fopen(tmp, 
"w+")) == NULL) {
 
 8655   while (fgets(
line, 
sizeof(
line), fp) != NULL) {
 
 8656      if (sscanf(
line, 
"%255[^:]:%255[^:]:%*s", u, 
d) != 2) {
 
 8662      if (!strcmp(u, user) && !strcmp(
d, domain)) {
 
 8665            mg_md5(ha1, user, 
":", domain, 
":", pass, NULL);
 
 8666            fprintf(fp2, 
"%s:%s:%s\n", user, domain, ha1);
 
 8669         fprintf(fp2, 
"%s", 
line);
 
 8674   if (!found && (pass != NULL)) {
 
 8675      mg_md5(ha1, user, 
":", domain, 
":", pass, NULL);
 
 8676      fprintf(fp2, 
"%s:%s:%s\n", user, domain, ha1);
 
 8694   return (port <= 0xffff);
 
 8701   struct addrinfo hints, *res, *ressave;
 
 8705   memset(&hints, 0, 
sizeof(
struct addrinfo));
 
 8706   hints.ai_family = af;
 
 8708   gai_ret = getaddrinfo(src, NULL, &hints, &res);
 
 8723      if (dstlen >= (
size_t)res->ai_addrlen) {
 
 8724         memcpy(dst, res->ai_addr, res->ai_addrlen);
 
 8730   freeaddrinfo(ressave);
 
 8750   memset(sa, 0, 
sizeof(*sa));
 
 8777#if !defined(NO_SSL_DL) 
 8778#if defined(OPENSSL_API_1_1) 
 8779   if (use_ssl && (TLS_client_method == NULL)) {
 
 8785                  "SSL is not initialized");
 
 8795                  "SSL is not initialized");
 
 8807   if (
mg_inet_pton(AF_INET, host, &sa->sin, 
sizeof(sa->sin))) {
 
 8808      sa->sin.sin_family = AF_INET;
 
 8809      sa->sin.sin_port = htons((uint16_t)port);
 
 8811#if defined(USE_IPV6) 
 8812   } 
else if (
mg_inet_pton(AF_INET6, host, &sa->sin6, 
sizeof(sa->sin6))) {
 
 8813      sa->sin6.sin6_family = AF_INET6;
 
 8814      sa->sin6.sin6_port = htons((uint16_t)port);
 
 8816   } 
else if (host[0] == 
'[') {
 
 8819      size_t l = strlen(host + 1);
 
 8823         if (
mg_inet_pton(AF_INET6, 
h, &sa->sin6, 
sizeof(sa->sin6))) {
 
 8824            sa->sin6.sin6_family = AF_INET6;
 
 8825            sa->sin6.sin6_port = htons((uint16_t)port);
 
 8844      *sock = socket(PF_INET, SOCK_STREAM, 0);
 
 8846#if defined(USE_IPV6) 
 8847   else if (ip_ver == 6) {
 
 8848      *sock = socket(PF_INET6, SOCK_STREAM, 0);
 
 8867                  "Cannot set socket to non-blocking: %s",
 
 8878      conn_ret = connect(*sock,
 
 8879                         (
struct sockaddr *)((
void *)&sa->sin),
 
 8882#if defined(USE_IPV6) 
 8883   else if (ip_ver == 6) {
 
 8885      conn_ret = connect(*sock,
 
 8886                         (
struct sockaddr *)((
void *)&sa->sin6),
 
 8892   if (conn_ret != 0) {
 
 8893      DWORD err = WSAGetLastError(); 
 
 8894      conn_ret = (
int)err;
 
 8895#if !defined(EINPROGRESS) 
 8896#define EINPROGRESS (WSAEWOULDBLOCK)  
 8901   if ((conn_ret != 0) && (conn_ret != EINPROGRESS)) {
 
 8904      void *psockerr = &sockerr;
 
 8907      int len = (
int)
sizeof(sockerr);
 
 8909      socklen_t len = (socklen_t)
sizeof(sockerr);
 
 8913      struct pollfd pfd[1];
 
 8915      int ms_wait = 10000; 
 
 8923      pfd[0].events = POLLOUT;
 
 8924      pollres = 
mg_poll(pfd, 1, (
int)(ms_wait), &(ctx->stop_flag));
 
 8932                     "connect(%s:%d): timeout",
 
 8941      ret = getsockopt(*sock, SOL_SOCKET, SO_ERROR, (
char *)psockerr, &len);
 
 8943      ret = getsockopt(*sock, SOL_SOCKET, SO_ERROR, psockerr, &len);
 
 8946      if ((ret != 0) || (sockerr != 0)) {
 
 8952                     "connect(%s:%d): error %s",
 
 8969   static const char *dont_escape = 
"._-$,;~()";
 
 8970   static const char *hex = 
"0123456789abcdef";
 
 8972   const char *end = dst + dst_len - 1;
 
 8974   for (; ((*src != 
'\0') && (pos < end)); src++, pos++) {
 
 8975      if (isalnum(*(
const unsigned char *)src)
 
 8976          || (strchr(dont_escape, *(
const unsigned char *)src) != NULL)) {
 
 8978      } 
else if (pos + 2 < end) {
 
 8980         pos[1] = hex[(*(
const unsigned char *)src) >> 4];
 
 8981         pos[2] = hex[(*(
const unsigned char *)src) & 0xf];
 
 8989   return (*src == 
'\0') ? (
int)(pos - dst) : -1;
 
 8999   char size[64], mod[64];
 
 9000#if defined(REENTRANT_TIME) 
 9002   struct tm *tm = &_tm;
 
 9007   hrefsize = PATH_MAX * 3; 
 
 9012   if (de->file.is_directory) {
 
 9022      if (de->file.size < 1024) {
 
 9028                     (
int)de->file.size);
 
 9029      } 
else if (de->file.size < 0x100000) {
 
 9035                     (
double)de->file.size / 1024.0);
 
 9036      } 
else if (de->file.size < 0x40000000) {
 
 9042                     (
double)de->file.size / 1048576);
 
 9049                     (
double)de->file.size / 1073741824);
 
 9056#if defined(REENTRANT_TIME) 
 9057   localtime_r(&de->file.last_modified, tm);
 
 9059   tm = localtime(&de->file.last_modified);
 
 9062      strftime(mod, 
sizeof(mod), 
"%d-%b-%Y %H:%M", tm);
 
 9064      mg_strlcpy(mod, 
"01-Jan-1970 00:00", 
sizeof(mod));
 
 9065      mod[
sizeof(mod) - 1] = 
'\0';
 
 9069             "<tr><td><a href=\"%s%s%s\">%s%s</a></td>" 
 9070             "<td> %s</td><td>  %s</td></tr>\n",
 
 9071             de->conn->request_info.local_uri,
 
 9073             de->file.is_directory ? 
"/" : 
"",
 
 9075             de->file.is_directory ? 
"/" : 
"",
 
 9091      const struct de *
a = (
const struct de *)p1, *
b = (
const struct de *)p2;
 
 9092      const char *query_string = 
a->conn->request_info.query_string;
 
 9095      if (query_string == NULL) {
 
 9096         query_string = 
"na";
 
 9099      if (
a->file.is_directory && !
b->file.is_directory) {
 
 9101      } 
else if (!
a->file.is_directory && 
b->file.is_directory) {
 
 9103      } 
else if (*query_string == 
'n') {
 
 9104         cmp_result = strcmp(
a->file_name, 
b->file_name);
 
 9105      } 
else if (*query_string == 
's') {
 
 9106         cmp_result = (
a->file.size == 
b->file.size)
 
 9108                          : ((
a->file.size > 
b->file.size) ? 1 : -1);
 
 9109      } 
else if (*query_string == 
'd') {
 
 9111             (
a->file.last_modified == 
b->file.last_modified)
 
 9113                 : ((
a->file.last_modified > 
b->file.last_modified) ? 1
 
 9117      return (query_string[1] == 
'd') ? -cmp_result : cmp_result;
 
 9126   if (conn && conn->dom_ctx) {
 
 9128      const char *pattern = conn->dom_ctx->config[
HIDE_FILES];
 
 9129      return (
match_prefix(pw_pattern, strlen(pw_pattern), path) > 0)
 
 9130             || ((pattern != NULL)
 
 9131                 && (
match_prefix(pattern, strlen(pattern), path) > 0));
 
 9141               int (*cb)(
struct de *, 
void *))
 
 9143   char path[PATH_MAX];
 
 9149   if ((dirp = 
mg_opendir(conn, dir)) == NULL) {
 
 9156         if (!strcmp(dp->d_name, 
".") || !strcmp(dp->d_name, 
"..")
 
 9162             conn, &truncated, path, 
sizeof(path), 
"%s/%s", dir, dp->d_name);
 
 9169         memset(&de.file, 0, 
sizeof(de.file));
 
 9176         if (!
mg_stat(conn, path, &de.file)) {
 
 9178                            "%s: mg_stat(%s) failed: %s",
 
 9183         de.file_name = dp->d_name;
 
 9192#if !defined(NO_FILES) 
 9196   char path[PATH_MAX];
 
 9203   if ((dirp = 
mg_opendir(conn, dir)) == NULL) {
 
 9211         if (!strcmp(dp->d_name, 
".") || !strcmp(dp->d_name, 
"..")) {
 
 9216             conn, &truncated, path, 
sizeof(path), 
"%s/%s", dir, dp->d_name);
 
 9223         memset(&de.file, 0, 
sizeof(de.file));
 
 9231         if (!
mg_stat(conn, path, &de.file)) {
 
 9233                            "%s: mg_stat(%s) failed: %s",
 
 9240         if (de.file.is_directory) {
 
 9261struct dir_scan_data {
 
 9263   unsigned int num_entries;
 
 9264   unsigned int arr_size;
 
 9273   if (new_ptr == NULL) {
 
 9283   struct dir_scan_data *dsd = (
struct dir_scan_data *)data;
 
 9285   if ((dsd->entries == NULL) || (dsd->num_entries >= dsd->arr_size)) {
 
 9288          (
struct de *)
realloc2(dsd->entries,
 
 9289                                dsd->arr_size * 
sizeof(dsd->entries[0]));
 
 9291   if (dsd->entries == NULL) {
 
 9293      dsd->num_entries = 0;
 
 9295      dsd->entries[dsd->num_entries].file_name = 
mg_strdup(de->file_name);
 
 9296      dsd->entries[dsd->num_entries].file = de->file;
 
 9297      dsd->entries[dsd->num_entries].conn = de->conn;
 
 9310   struct dir_scan_data data = {NULL, 0, 128};
 
 9312   time_t curtime = time(NULL);
 
 9317                         "Error: Cannot open directory\nopendir(%s): %s",
 
 9329   sort_direction = ((conn->request_info.query_string != NULL)
 
 9330                     && (conn->request_info.query_string[1] == 
'd'))
 
 9334   conn->must_close = 1;
 
 9340             "Connection: close\r\n" 
 9341             "Content-Type: text/html; charset=utf-8\r\n\r\n",
 
 9344             "<html><head><title>Index of %s</title>" 
 9345             "<style>th {text-align: left;}</style></head>" 
 9346             "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">" 
 9347             "<tr><th><a href=\"?n%c\">Name</a></th>" 
 9348             "<th><a href=\"?d%c\">Modified</a></th>" 
 9349             "<th><a href=\"?s%c\">Size</a></th></tr>" 
 9350             "<tr><td colspan=\"3\"><hr></td></tr>",
 
 9351             conn->request_info.local_uri,
 
 9352             conn->request_info.local_uri,
 
 9359             "<tr><td><a href=\"%s%s\">%s</a></td>" 
 9360             "<td> %s</td><td>  %s</td></tr>\n",
 
 9361             conn->request_info.local_uri,
 
 9368   if (data.entries != NULL) {
 
 9370            (
size_t)data.num_entries,
 
 9371            sizeof(data.entries[0]),
 
 9373      for (i = 0; i < data.num_entries; i++) {
 
 9375         mg_free(data.entries[i].file_name);
 
 9380   mg_printf(conn, 
"%s", 
"</table></body></html>");
 
 9381   conn->status_code = 200;
 
 9388               struct mg_file *filep,
 
 9393   int to_read, num_read, num_written;
 
 9396   if (!filep || !conn) {
 
 9402                                         : (int64_t)(filep->stat.size);
 
 9403   offset = (offset < 0) ? 0 : ((offset > size) ? size : offset);
 
 9405#if defined(MG_USE_OPEN_FILE) 
 9406   if ((len > 0) && (filep->access.membuf != NULL) && (size > 0)) {
 
 9408      if (len > size - offset) {
 
 9409         len = size - offset;
 
 9411      mg_write(conn, filep->access.membuf + offset, (
size_t)len);
 
 9414       if (len > 0 && filep->access.fp != NULL) {
 
 9416#if defined(__linux__) 
 9418      if ((conn->ssl == 0) && (conn->throttle == 0)
 
 9419          && (!
mg_strcasecmp(conn->dom_ctx->config[ALLOW_SENDFILE_CALL],
 
 9421         off_t sf_offs = (off_t)offset;
 
 9423         int sf_file = fileno(filep->access.fp);
 
 9430                (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
 
 9432                sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
 
 9436            } 
else if (loop_cnt == 0) {
 
 9442            } 
else if (sf_sent == 0) {
 
 9448         } 
while ((len > 0) && (sf_sent >= 0));
 
 9457         offset = (int64_t)sf_offs;
 
 9460      if ((offset > 0) && (fseeko(filep->access.fp, offset, SEEK_SET) != 0)) {
 
 9462                         "%s: fseeko() failed: %s",
 
 9469             "Error: Unable to access file at requested position.");
 
 9473            to_read = 
sizeof(buf);
 
 9474            if ((int64_t)to_read > len) {
 
 9480                     (
int)fread(buf, 1, (
size_t)to_read, filep->access.fp))
 
 9486            if ((num_written = 
mg_write(conn, buf, (
size_t)num_read))
 
 9509   if ((filestat != NULL) && (buf != NULL)) {
 
 9515                  (
unsigned long)filestat->last_modified,
 
 9524   if (filep != NULL && filep->fp != NULL) {
 
 9528      if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
 
 9530                         "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
 
 9539#if defined(USE_ZLIB) 
 9540#include "mod_zlib.inl" 
 9547                           struct mg_file *filep,
 
 9549                           const char *additional_headers)
 
 9551   char date[64], lm[64], etag[64];
 
 9553   const char *msg = 
"OK", *hdr;
 
 9554   time_t curtime = time(NULL);
 
 9556   struct vec mime_vec;
 
 9558   char gz_path[PATH_MAX];
 
 9559   const char *encoding = 
"";
 
 9560   const char *cors1, *cors2, *cors3;
 
 9561   int is_head_request;
 
 9563#if defined(USE_ZLIB) 
 9567   int allow_on_the_fly_compression = 1;
 
 9570   if ((conn == NULL) || (conn->dom_ctx == NULL) || (filep == NULL)) {
 
 9574   is_head_request = !strcmp(conn->request_info.request_method, 
"HEAD");
 
 9585                         "Error: File size is too large to send\n%" INT64_FMT,
 
 9589   cl = (int64_t)filep->stat.size;
 
 9590   conn->status_code = 200;
 
 9593#if defined(USE_ZLIB) 
 9597   if (!conn->accept_gzip) {
 
 9598      allow_on_the_fly_compression = 0;
 
 9602   if (filep->stat.is_gzipped) {
 
 9603      mg_snprintf(conn, &truncated, gz_path, 
sizeof(gz_path), 
"%s.gz", path);
 
 9608                            "Error: Path of zipped file too long (%s)",
 
 9614      encoding = 
"Content-Encoding: gzip\r\n";
 
 9616#if defined(USE_ZLIB) 
 9618      allow_on_the_fly_compression = 0;
 
 9625                         "Error: Cannot open file\nfopen(%s): %s",
 
 9638       && (r1 >= 0) && (r2 >= 0)) {
 
 9641      if (filep->stat.is_gzipped) {
 
 9646             "Error: Range requests in gzipped files are not supported");
 
 9651      conn->status_code = 206;
 
 9652      cl = (
n == 2) ? (((r2 > cl) ? cl : r2) - r1 + 1) : (cl - r1);
 
 9657                  "Content-Range: bytes " 
 9662      msg = 
"Partial Content";
 
 9664#if defined(USE_ZLIB) 
 9666      allow_on_the_fly_compression = 0;
 
 9672#if defined(USE_ZLIB) 
 9675      allow_on_the_fly_compression = 0;
 
 9687      cors1 = 
"Access-Control-Allow-Origin: ";
 
 9691      cors1 = cors2 = cors3 = 
"";
 
 9703                   "HTTP/1.1 %d %s\r\n" 
 9706                   "Last-Modified: %s\r\n" 
 9708                   "Content-Type: %.*s\r\n" 
 9709                   "Connection: %s\r\n",
 
 9724#if defined(USE_ZLIB) 
 9726   if (allow_on_the_fly_compression) {
 
 9730                      "Content-Encoding: gzip\r\n" 
 9731                      "Transfer-Encoding: chunked\r\n");
 
 9740                      "Accept-Ranges: bytes\r\n" 
 9750   if (additional_headers != NULL) {
 
 9753                      (
int)strlen(additional_headers),
 
 9754                      additional_headers);
 
 9759   if (!is_head_request) {
 
 9760#if defined(USE_ZLIB) 
 9761      if (allow_on_the_fly_compression) {
 
 9763         send_compressed_data(conn, filep);
 
 9789#if !defined(NO_CACHING) 
 9793                const struct mg_file_stat *filestat)
 
 9807                                        struct mg_file *filep)
 
 9809   char date[64], lm[64], etag[64];
 
 9810   time_t curtime = time(NULL);
 
 9812   if ((conn == NULL) || (filep == NULL)) {
 
 9815   conn->status_code = 304;
 
 9821                   "HTTP/1.1 %d %s\r\n" 
 9829                   "Last-Modified: %s\r\n" 
 9831                   "Connection: %s\r\n" 
 9860                   const char *additional_headers)
 
 9870#if !defined(NO_CACHING) 
 9876          if (
file.stat.is_directory) {
 
 9884                               "Error: Directory listing denied");
 
 9903put_dir(
struct mg_connection *conn, 
const char *path)
 
 9911   for (s = p = path + 2; (p = strchr(s, 
'/')) != NULL; s = ++p) {
 
 9912      len = (size_t)(p - path);
 
 9913      if (len >= 
sizeof(buf)) {
 
 9918      memcpy(buf, path, len);
 
 9945                      "%s: Cannot remove invalid file %s",
 
 9960   if (conn->consumed_content != 0) {
 
 9980   ret = 
mg_read(conn, buf, 
sizeof(buf));
 
 9982      n = (
int)fwrite(buf, 1, (
size_t)ret, fi.access.fp);
 
 9990      ret = 
mg_read(conn, buf, 
sizeof(buf));
 
10014   while (isgraph(**ppw)) {
 
10021      if ((**ppw != 
'\r') && (**ppw != 
'\n')) {
 
10026      if (**ppw != 
' ') {
 
10035   } 
while ((**ppw) && isspace(**ppw));
 
10040      if (!isgraph(**ppw)) {
 
10058   int num_headers = 0;
 
10062      while ((*dp != 
':') && (*dp >= 33) && (*dp <= 126)) {
 
10077      hdr[i].name = *buf;
 
10080      } 
while (*dp == 
' ');
 
10084      *buf = dp + strcspn(dp, 
"\r\n");
 
10085      if (((*buf)[0] != 
'\r') || ((*buf)[1] != 
'\n')) {
 
10089      num_headers = i + 1;
 
10099      if ((*buf)[0] == 
'\r') {
 
10104   return num_headers;
 
10108struct mg_http_method_info {
 
10110   int request_has_body;
 
10111   int response_has_body;
 
10121    {
"GET", 0, 1, 1, 1, 1},
 
10122    {
"POST", 1, 1, 0, 0, 0},
 
10123    {
"PUT", 1, 0, 0, 1, 0},
 
10124    {
"DELETE", 0, 0, 0, 1, 0},
 
10125    {
"HEAD", 0, 0, 1, 1, 1},
 
10126    {
"OPTIONS", 0, 0, 1, 1, 0},
 
10127    {
"CONNECT", 1, 1, 0, 0, 0},
 
10131    {
"PATCH", 1, 0, 0, 0, 0},
 
10135    {
"PROPFIND", 0, 1, 1, 1, 0},
 
10141    {
"MKCOL", 0, 0, 0, 1, 0},
 
10163    {
"REPORT", 1, 1, 1, 1, 1},
 
10170    {NULL, 0, 0, 0, 0, 0}
 
10175static const struct mg_http_method_info *
 
10185      if (!strcmp(
m->name, method)) {
 
10213   int request_length;
 
10225   while ((len > 0) && isspace(*(
unsigned char *)buf)) {
 
10237   if (iscntrl(*(
unsigned char *)buf)) {
 
10243   if (request_length <= 0) {
 
10244      return request_length;
 
10246   buf[request_length - 1] = 
'\0';
 
10248   if ((*buf == 0) || (*buf == 
'\r') || (*buf == 
'\n')) {
 
10293   return request_length + init_skip;
 
10300   int response_length;
 
10312   while ((len > 0) && isspace(*(
unsigned char *)buf)) {
 
10324   if (iscntrl(*(
unsigned char *)buf)) {
 
10330   if (response_length <= 0) {
 
10331      return response_length;
 
10333   buf[response_length - 1] = 
'\0';
 
10335   if ((*buf == 0) || (*buf == 
'\r') || (*buf == 
'\n')) {
 
10341   if (strncmp(buf, 
"HTTP/", 5) != 0) {
 
10346   if (!isgraph(buf[0])) {
 
10363   l = strtol(tmp, &tmp2, 10);
 
10364   if ((
l < 100) || (
l >= 1000) || ((tmp2 - tmp) != 3) || (*tmp2 != 0)) {
 
10375   while (isprint(*buf)) {
 
10378   if ((*buf != 
'\r') && (*buf != 
'\n')) {
 
10385   } 
while ((*buf) && isspace(*buf));
 
10395   return response_length + init_skip;
 
10406             struct mg_connection *conn,
 
10411   int request_len, 
n = 0;
 
10412   struct timespec last_action_time;
 
10413   double request_timeout;
 
10419   memset(&last_action_time, 0, 
sizeof(last_action_time));
 
10423      request_timeout = atof(conn->dom_ctx->config[
REQUEST_TIMEOUT]) / 1000.0;
 
10425      request_timeout = -1.0;
 
10427   if (conn->handled_requests > 0) {
 
10437   clock_gettime(CLOCK_MONOTONIC, &last_action_time);
 
10439   while (request_len == 0) {
 
10441      if (conn->phys_ctx->stop_flag != 0) {
 
10446      if (*nread >= bufsiz) {
 
10452          fp, conn, buf + *nread, bufsiz - *nread, request_timeout);
 
10464      if ((request_len == 0) && (request_timeout >= 0)) {
 
10466             > request_timeout) {
 
10470         clock_gettime(CLOCK_MONOTONIC, &last_action_time);
 
10474   return request_len;
 
10478#if !defined(NO_CGI) || !defined(NO_FILES) 
10482   const char *expect, *body;
 
10484   int to_read, nread, success = 0;
 
10485   int64_t buffered_len;
 
10486   double timeout = -1.0;
 
10502   if ((conn->content_len == -1) && (!conn->is_chunked)) {
 
10507                         "Error: Client did not specify content length");
 
10508   } 
else if ((expect != NULL)
 
10514                         "Error: Can not fulfill expectation %s",
 
10517      if (expect != NULL) {
 
10518         (
void)
mg_printf(conn, 
"%s", 
"HTTP/1.1 100 Continue\r\n\r\n");
 
10519         conn->status_code = 100;
 
10521         conn->status_code = 200;
 
10524      buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
 
10525                     - conn->consumed_content;
 
10530      if ((buffered_len < 0) || (conn->consumed_content != 0)) {
 
10535      if (buffered_len > 0) {
 
10536         if ((int64_t)buffered_len > conn->content_len) {
 
10537            buffered_len = (
int)conn->content_len;
 
10539         body = conn->buf + conn->request_len + conn->consumed_content;
 
10541             conn->phys_ctx, fp, sock, ssl, body, (int64_t)buffered_len);
 
10542         conn->consumed_content += buffered_len;
 
10546      while (conn->consumed_content < conn->content_len) {
 
10547         to_read = 
sizeof(buf);
 
10548         if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
 
10549            to_read = (
int)(conn->content_len - conn->consumed_content);
 
10551         nread = 
pull_inner(NULL, conn, buf, to_read, timeout);
 
10557            if (
push_all(conn->phys_ctx, fp, sock, ssl, buf, nread)
 
10562         conn->consumed_content += nread;
 
10565      if (conn->consumed_content == conn->content_len) {
 
10566         success = (nread >= 0);
 
10583#if defined(USE_TIMERS) 
10585#define TIMER_API static 
10586#include "timer.inl" 
10591#if !defined(NO_CGI) 
10602struct cgi_environment {
 
10603   struct mg_connection *conn;
 
10622addenv(struct cgi_environment *env, const 
char *fmt, ...)
 
10630   space = (env->buflen - env->bufused);
 
10633   n = strlen(fmt) + 2 + 128;
 
10644                "%s: Cannot allocate memory for CGI variable [%s]",
 
10651         space = (env->buflen - env->bufused);
 
10655      added = env->buf + env->bufused;
 
10659      mg_vsnprintf(env->conn, &truncated, added, (
size_t)space, fmt, ap);
 
10668   } 
while (truncated);
 
10671   n = strlen(added) + 1;
 
10675   space = (env->varlen - env->varused);
 
10678                      "%s: Cannot register CGI variable [%s]",
 
10685   env->var[env->varused] = added;
 
10694                        struct cgi_environment *env)
 
10697   struct vec var_vec;
 
10699   int i, truncated, uri_len;
 
10701   if ((conn == NULL) || (prog == NULL) || (env == NULL)) {
 
10708   env->buf = (
char *)
mg_malloc_ctx(env->buflen, conn->phys_ctx);
 
10709   if (env->buf == NULL) {
 
10711                      "%s: Not enough memory for environmental buffer",
 
10718       (
char **)
mg_malloc_ctx(env->buflen * 
sizeof(
char *), conn->phys_ctx);
 
10719   if (env->var == NULL) {
 
10721                      "%s: Not enough memory for environmental variables",
 
10733   addenv(env, 
"%s", 
"GATEWAY_INTERFACE=CGI/1.1");
 
10734   addenv(env, 
"%s", 
"SERVER_PROTOCOL=HTTP/1.1");
 
10735   addenv(env, 
"%s", 
"REDIRECT_STATUS=200"); 
 
10737#if defined(USE_IPV6) 
10738   if (conn->client.lsa.sa.sa_family == AF_INET6) {
 
10739      addenv(env, 
"SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
 
10743      addenv(env, 
"SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
 
10747   addenv(env, 
"REMOTE_ADDR=%s", src_addr);
 
10749   addenv(env, 
"REQUEST_METHOD=%s", conn->request_info.request_method);
 
10750   addenv(env, 
"REMOTE_PORT=%d", conn->request_info.remote_port);
 
10752   addenv(env, 
"REQUEST_URI=%s", conn->request_info.request_uri);
 
10753   addenv(env, 
"LOCAL_URI=%s", conn->request_info.local_uri);
 
10756   uri_len = (
int)strlen(conn->request_info.local_uri);
 
10757   if (conn->path_info == NULL) {
 
10758      if (conn->request_info.local_uri[uri_len - 1] != 
'/') {
 
10760         addenv(env, 
"SCRIPT_NAME=%s", conn->request_info.local_uri);
 
10763         const char *index_file = strrchr(prog, 
'/');
 
10766                   "SCRIPT_NAME=%s%s",
 
10767                   conn->request_info.local_uri,
 
10774             "SCRIPT_NAME=%.*s",
 
10775             uri_len - (
int)strlen(conn->path_info),
 
10776             conn->request_info.local_uri);
 
10779   addenv(env, 
"SCRIPT_FILENAME=%s", prog);
 
10780   if (conn->path_info == NULL) {
 
10784             "PATH_TRANSLATED=%s%s",
 
10789   addenv(env, 
"HTTPS=%s", (conn->ssl == NULL) ? 
"off" : 
"on");
 
10792      addenv(env, 
"CONTENT_TYPE=%s", s);
 
10794   if (conn->request_info.query_string != NULL) {
 
10795      addenv(env, 
"QUERY_STRING=%s", conn->request_info.query_string);
 
10798      addenv(env, 
"CONTENT_LENGTH=%s", s);
 
10800   if ((s = getenv(
"PATH")) != NULL) {
 
10801      addenv(env, 
"PATH=%s", s);
 
10803   if (conn->path_info != NULL) {
 
10804      addenv(env, 
"PATH_INFO=%s", conn->path_info);
 
10807   if (conn->status_code > 0) {
 
10809      addenv(env, 
"STATUS=%d", conn->status_code);
 
10813   if ((s = getenv(
"COMSPEC")) != NULL) {
 
10814      addenv(env, 
"COMSPEC=%s", s);
 
10816   if ((s = getenv(
"SYSTEMROOT")) != NULL) {
 
10817      addenv(env, 
"SYSTEMROOT=%s", s);
 
10819   if ((s = getenv(
"SystemDrive")) != NULL) {
 
10820      addenv(env, 
"SystemDrive=%s", s);
 
10822   if ((s = getenv(
"ProgramFiles")) != NULL) {
 
10823      addenv(env, 
"ProgramFiles=%s", s);
 
10825   if ((s = getenv(
"ProgramFiles(x86)")) != NULL) {
 
10826      addenv(env, 
"ProgramFiles(x86)=%s", s);
 
10829   if ((s = getenv(
"LD_LIBRARY_PATH")) != NULL) {
 
10830      addenv(env, 
"LD_LIBRARY_PATH=%s", s);
 
10834   if ((s = getenv(
"PERLLIB")) != NULL) {
 
10835      addenv(env, 
"PERLLIB=%s", s);
 
10838   if (conn->request_info.remote_user != NULL) {
 
10839      addenv(env, 
"REMOTE_USER=%s", conn->request_info.remote_user);
 
10840      addenv(env, 
"%s", 
"AUTH_TYPE=Digest");
 
10844   for (i = 0; i < conn->request_info.num_headers; i++) {
 
10849                        sizeof(http_var_name),
 
10851                        conn->request_info.http_headers[i].name);
 
10855                         "%s: HTTP header variable too long [%s]",
 
10857                         conn->request_info.http_headers[i].name);
 
10862      for (p = http_var_name; *p != 
'\0'; p++) {
 
10866         *p = (char)toupper(*(
unsigned char *)p);
 
10872             conn->request_info.http_headers[i].value);
 
10877   while ((s = 
next_option(s, &var_vec, NULL)) != NULL) {
 
10878      addenv(env, 
"%.*s", (
int)var_vec.len, var_vec.ptr);
 
10881   env->var[env->varused] = NULL;
 
10882   env->buf[env->bufused] = 
'\0';
 
10889struct process_control_data {
 
10900   struct process_control_data *proc = (
struct process_control_data *)data;
 
10905   ret_pid = waitpid(proc->pid, &status, WNOHANG);
 
10906   if ((ret_pid != (pid_t)-1) && (status == 0)) {
 
10908      DEBUG_TRACE(
"CGI timer: Stop child process %p\n", proc->pid);
 
10909      kill(proc->pid, SIGABRT);
 
10912      while (waitpid(proc->pid, &status, 0) != (pid_t)-1) 
 
10915      DEBUG_TRACE(
"CGI timer: Child process %p already stopped\n", proc->pid);
 
10933   int headers_len, data_len, i, truncated;
 
10934   int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
 
10935   const char *status, *status_text, *connection_state;
 
10936   char *pbuf, dir[PATH_MAX], *p;
 
10938   struct cgi_environment 
blk;
 
10939   FILE *in = NULL, *out = NULL, *err = NULL;
 
10941   pid_t pid = (pid_t)-1;
 
10942   struct process_control_data *proc = NULL;
 
10944#if defined(USE_TIMERS) 
10945   double cgi_timeout = -1.0;
 
10946   if (conn->dom_ctx->config[CGI_TIMEOUT]) {
 
10948      cgi_timeout = atof(conn->dom_ctx->config[CGI_TIMEOUT]) * 0.001;
 
10952   if (conn == NULL) {
 
10957   buflen = conn->phys_ctx->max_request_size;
 
10971      mg_cry_internal(conn, 
"Error: CGI program \"%s\": Path too long", prog);
 
10976   if ((p = strrchr(dir, 
'/')) != NULL) {
 
10984   if ((pipe(fdin) != 0) || (pipe(fdout) != 0) || (pipe(fderr) != 0)) {
 
10985      status = strerror(
ERRNO);
 
10988          "Error: CGI program \"%s\": Can not create CGI pipes: %s",
 
10993                         "Error: Cannot create CGI pipe: %s",
 
10998   proc = (
struct process_control_data *)
 
10999       mg_malloc_ctx(
sizeof(
struct process_control_data), conn->phys_ctx);
 
11000   if (proc == NULL) {
 
11001      mg_cry_internal(conn, 
"Error: CGI program \"%s\": Out or memory", prog);
 
11009   if (pid == (pid_t)-1) {
 
11010      status = strerror(
ERRNO);
 
11013          "Error: CGI program \"%s\": Can not spawn CGI process: %s",
 
11018                         "Error: Cannot spawn CGI process [%s]: %s",
 
11028   proc->references = 1;
 
11030#if defined(USE_TIMERS) 
11031   if (cgi_timeout > 0.0) {
 
11032      proc->references = 2;
 
11035      timer_add(conn->phys_ctx,
 
11056   (
void)close(fdin[0]);
 
11057   (
void)close(fdout[1]);
 
11058   (
void)close(fderr[1]);
 
11059   fdin[0] = fdout[1] = fderr[1] = -1;
 
11061   if ((in = fdopen(fdin[1], 
"wb")) == NULL) {
 
11062      status = strerror(
ERRNO);
 
11064                      "Error: CGI program \"%s\": Can not open stdin: %s",
 
11069                         "Error: CGI can not open fdin\nfopen: %s",
 
11074   if ((out = fdopen(fdout[0], 
"rb")) == NULL) {
 
11075      status = strerror(
ERRNO);
 
11077                      "Error: CGI program \"%s\": Can not open stdout: %s",
 
11082                         "Error: CGI can not open fdout\nfopen: %s",
 
11087   if ((err = fdopen(fderr[0], 
"rb")) == NULL) {
 
11088      status = strerror(
ERRNO);
 
11090                      "Error: CGI program \"%s\": Can not open stderr: %s",
 
11095                         "Error: CGI can not open fderr\nfopen: %s",
 
11103   fout.access.fp = out;
 
11105   if ((conn->request_info.content_length != 0) || (conn->is_chunked)) {
 
11107                  (
signed long long)conn->request_info.content_length);
 
11114             "Error: CGI program \"%s\": Forward body data failed",
 
11134                         "Error: Not enough memory for CGI buffer (%u bytes)",
 
11135                         (
unsigned int)buflen);
 
11138          "Error: CGI program \"%s\": Not enough memory for buffer (%u " 
11141          (
unsigned int)buflen);
 
11146   headers_len = 
read_message(out, conn, buf, (
int)buflen, &data_len);
 
11147   DEBUG_TRACE(
"CGI: response: %li", (
signed long)headers_len);
 
11149   if (headers_len <= 0) {
 
11153      i = 
pull_all(err, conn, buf, (
int)buflen);
 
11158                         "Error: CGI program \"%s\" sent error " 
11166                            "Error: CGI program \"%s\" failed.",
 
11172                         "Error: CGI program sent malformed or too big " 
11173                         "(>%u bytes) HTTP headers: [%.*s]",
 
11180                            "Error: CGI program sent malformed or too big " 
11181                            "(>%u bytes) HTTP headers: [%.*s]",
 
11192   buf[headers_len - 1] = 
'\0';
 
11196   status_text = 
"OK";
 
11199      conn->status_code = atoi(status);
 
11200      status_text = status;
 
11201      while (isdigit(*(
const unsigned char *)status_text)
 
11202             || *status_text == 
' ') {
 
11207      conn->status_code = 307;
 
11209      conn->status_code = 200;
 
11214      conn->must_close = 1;
 
11217   DEBUG_TRACE(
"CGI: response %u %s", conn->status_code, status_text);
 
11219   (
void)
mg_printf(conn, 
"HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
 
11231   mg_write(conn, buf + headers_len, (
size_t)(data_len - headers_len));
 
11242   if (pid != (pid_t)-1) {
 
11246   if (fdin[0] != -1) {
 
11249   if (fdout[1] != -1) {
 
11255   } 
else if (fdin[1] != -1) {
 
11261   } 
else if (fdout[0] != -1) {
 
11267   } 
else if (fderr[0] != -1) {
 
11278#if !defined(NO_FILES) 
11280mkcol(
struct mg_connection *conn, 
const char *path)
 
11285   time_t curtime = time(NULL);
 
11287   if (conn == NULL) {
 
11294   memset(&de.file, 0, 
sizeof(de.file));
 
11295   if (!
mg_stat(conn, path, &de.file)) {
 
11297                      "%s: mg_stat(%s) failed: %s",
 
11303   if (de.file.last_modified) {
 
11308          conn, 405, 
"Error: mkcol(%s): %s", path, strerror(
ERRNO));
 
11312   body_len = conn->data_len - conn->request_len;
 
11313   if (body_len > 0) {
 
11315          conn, 415, 
"Error: mkcol(%s): %s", path, strerror(
ERRNO));
 
11322      conn->status_code = 201;
 
11325                "HTTP/1.1 %d Created\r\n" 
11332                "Content-Length: 0\r\n" 
11333                "Connection: %s\r\n\r\n",
 
11336      if (errno == EEXIST) {
 
11338             conn, 405, 
"Error: mkcol(%s): %s", path, strerror(
ERRNO));
 
11339      } 
else if (errno == EACCES) {
 
11341             conn, 403, 
"Error: mkcol(%s): %s", path, strerror(
ERRNO));
 
11342      } 
else if (errno == ENOENT) {
 
11344             conn, 409, 
"Error: mkcol(%s): %s", path, strerror(
ERRNO));
 
11347             conn, 500, 
"fopen(%s): %s", path, strerror(
ERRNO));
 
11361   time_t curtime = time(NULL);
 
11363   if (conn == NULL) {
 
11369      conn->status_code = 200;
 
11371      if (
file.stat.is_directory) {
 
11380#if defined(MG_USE_OPEN_FILE) 
11381         if (
file.access.membuf != NULL) {
 
11385                               "Error: Put not possible\nReplacing %s " 
11386                               "is not supported",
 
11393         if (access(path, W_OK) == 0) {
 
11395            conn->status_code = 200;
 
11401                "Error: Put not possible\nReplacing %s is not allowed",
 
11408      conn->status_code = 201;
 
11416                "HTTP/1.1 %d %s\r\n",
 
11423                "Content-Length: 0\r\n" 
11424                "Connection: %s\r\n\r\n",
 
11437                         "Error: Path too long\nput_dir(%s): %s",
 
11447                         "Error: Can not create directory\nput_dir(%s): %s",
 
11456       || 
file.access.fp == NULL) {
 
11460                         "Error: Can not create file\nfopen(%s): %s",
 
11470      conn->status_code = 206; 
 
11471      fseeko(
file.access.fp, r1, SEEK_SET);
 
11485      conn->status_code = 507;
 
11490             "HTTP/1.1 %d %s\r\n",
 
11497             "Content-Length: 0\r\n" 
11498             "Connection: %s\r\n\r\n",
 
11508   memset(&de.file, 0, 
sizeof(de.file));
 
11509   if (!
mg_stat(conn, path, &de.file)) {
 
11513                         "Error: Cannot delete file\nFile %s not found",
 
11519        if (de.access.membuf != NULL) {
 
11524                    "Error: Delete not possible\nDeleting %s is not supported",
 
11530   if (de.file.is_directory) {
 
11543   if (access(path, W_OK) != 0) {
 
11548          "Error: Delete not possible\nDeleting %s is not allowed",
 
11561                         "Error: Cannot delete file\nremove(%s): %s",
 
11570send_ssi_file(
struct mg_connection *, 
const char *, 
struct mg_file *, 
int);
 
11584   if (conn == NULL) {
 
11591   if (sscanf(tag, 
" virtual=\"%511[^\"]\"", file_name) == 1) {
 
11593      file_name[511] = 0;
 
11602   } 
else if (sscanf(tag, 
" abspath=\"%511[^\"]\"", file_name) == 1) {
 
11605      file_name[511] = 0;
 
11607          mg_snprintf(conn, &truncated, path, 
sizeof(path), 
"%s", file_name);
 
11609   } 
else if ((sscanf(tag, 
" file=\"%511[^\"]\"", file_name) == 1)
 
11610              || (sscanf(tag, 
" \"%511[^\"]\"", file_name) == 1)) {
 
11612      file_name[511] = 0;
 
11616         if ((p = strrchr(path, 
'/')) != NULL) {
 
11619         len = strlen(path);
 
11623                           sizeof(path) - len,
 
11634      mg_cry_internal(conn, 
"SSI #include path length overflow: [%s]", tag);
 
11640                      "Cannot open SSI #include: [%s]: fopen(%s): %s",
 
11659#if !defined(NO_POPEN) 
11663   char cmd[1024] = 
"";
 
11666   if (sscanf(tag, 
" \"%1023[^\"]\"", cmd) != 1) {
 
11670      if ((
file.access.fp = popen(cmd, 
"r")) == NULL) {
 
11672                         "Cannot SSI #exec: [%s]: %s",
 
11677         pclose(
file.access.fp);
 
11689   if (filep == NULL) {
 
11692#if defined(MG_USE_OPEN_FILE) 
11693   if ((filep->access.membuf != NULL) && (offset >= 0)
 
11694       && (((
unsigned int)(offset)) < filep->stat.size)) {
 
11695      return ((
const unsigned char *)filep->access.membuf)[offset];
 
11698       if (filep->access.fp != NULL) {
 
11699      return fgetc(filep->access.fp);
 
11709              struct mg_file *filep,
 
11713   int ch, offset, len, in_tag, in_ssi_tag;
 
11715   if (include_level > 10) {
 
11720   in_tag = in_ssi_tag = len = offset = 0;
 
11723   while ((ch = 
mg_fgetc(filep, offset++)) != EOF) {
 
11736               if ((len > 12) && !memcmp(buf + 5, 
"include", 7)) {
 
11738#if !defined(NO_POPEN) 
11739               } 
else if ((len > 9) && !memcmp(buf + 5, 
"exec", 4)) {
 
11750               in_ssi_tag = in_tag = 0;
 
11762            buf[len++] = (char)(ch & 0xff);
 
11764            if ((len == 5) && !memcmp(buf, 
"<!--#", 5)) {
 
11769            if ((len + 2) > (
int)
sizeof(buf)) {
 
11795            buf[len++] = (char)(ch & 0xff);
 
11797            if (len == (
int)
sizeof(buf)) {
 
11815                        struct mg_file *filep)
 
11818   time_t curtime = time(NULL);
 
11819   const char *cors1, *cors2, *cors3;
 
11821   if ((conn == NULL) || (path == NULL) || (filep == NULL)) {
 
11827      cors1 = 
"Access-Control-Allow-Origin: ";
 
11831      cors1 = cors2 = cors3 = 
"";
 
11839                         "Error: Cannot read file\nfopen(%s): %s",
 
11843      conn->must_close = 1;
 
11846      mg_printf(conn, 
"HTTP/1.1 200 OK\r\n");
 
11852                "Content-Type: text/html\r\n" 
11853                "Connection: %s\r\n\r\n",
 
11865#if !defined(NO_FILES) 
11870   time_t curtime = time(NULL);
 
11876   conn->status_code = 200;
 
11877   conn->must_close = 1;
 
11884             "HTTP/1.1 200 OK\r\n" 
11886             "Connection: %s\r\n" 
11887             "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, " 
11888             "PROPFIND, MKCOL\r\n" 
11901            struct mg_file_stat *filep)
 
11905   if ((conn == NULL) || (uri == NULL) || (filep == NULL)) {
 
11912             "<d:href>%s</d:href>" 
11915             "<d:resourcetype>%s</d:resourcetype>" 
11916             "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>" 
11917             "<d:getlastmodified>%s</d:getlastmodified>" 
11919             "<d:status>HTTP/1.1 200 OK</d:status>" 
11923             filep->is_directory ? 
"<d:collection/>" : 
"",
 
11932   char href[PATH_MAX];
 
11935   struct mg_connection *conn = (
struct mg_connection *)data;
 
11936   if (!de || !conn) {
 
11944               conn->request_info.local_uri,
 
11948      size_t href_encoded_size;
 
11949      char *href_encoded;
 
11951      href_encoded_size = PATH_MAX * 3; 
 
11952      href_encoded = (
char *)
mg_malloc(href_encoded_size);
 
11953      if (href_encoded == NULL) {
 
11968                struct mg_file_stat *filep)
 
11972   time_t curtime = time(NULL);
 
11976   if (!conn || !path || !filep || !conn->dom_ctx) {
 
11980   conn->must_close = 1;
 
11981   conn->status_code = 207;
 
11983             "HTTP/1.1 207 Multi-Status\r\n" 
11989             "Connection: %s\r\n" 
11990             "Content-Type: text/xml; charset=utf-8\r\n\r\n",
 
11994             "<?xml version=\"1.0\" encoding=\"utf-8\"?>" 
11995             "<d:multistatus xmlns:d='DAV:'>\n");
 
11998   print_props(conn, conn->request_info.local_uri, filep);
 
12002   if (filep->is_directory
 
12005       && ((depth == NULL) || (strcmp(depth, 
"0") != 0))) {
 
12009   mg_printf(conn, 
"%s\n", 
"</d:multistatus>");
 
12017      (
void)pthread_mutex_lock(&conn->mutex);
 
12025      (
void)pthread_mutex_unlock(&conn->mutex);
 
12033      (
void)pthread_mutex_lock(&ctx->nonce_mutex);
 
12041      (
void)pthread_mutex_unlock(&ctx->nonce_mutex);
 
12046#if defined(USE_LUA) 
12047#include "mod_lua.inl" 
12050#if defined(USE_DUKTAPE) 
12051#include "mod_duktape.inl" 
12054#if defined(USE_WEBSOCKET) 
12056#if !defined(NO_SSL_DL) 
12057#define SHA_API static 
12062send_websocket_handshake(
struct mg_connection *conn, 
const char *websock_key)
 
12064   static const char *magic = 
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 
12065   char buf[100], sha[20], b64_sha[
sizeof(sha) * 2];
 
12070   mg_snprintf(conn, &truncated, buf, 
sizeof(buf), 
"%s%s", websock_key, magic);
 
12072      conn->must_close = 1;
 
12079   SHA1_Update(&sha_ctx, (
unsigned char *)buf, (uint32_t)strlen(buf));
 
12081   base64_encode((
unsigned char *)sha, 
sizeof(sha), b64_sha);
 
12083             "HTTP/1.1 101 Switching Protocols\r\n" 
12084             "Upgrade: websocket\r\n" 
12085             "Connection: Upgrade\r\n" 
12086             "Sec-WebSocket-Accept: %s\r\n",
 
12088   if (conn->request_info.acceptedWebSocketSubprotocol) {
 
12090                "Sec-WebSocket-Protocol: %s\r\n\r\n",
 
12091                conn->request_info.acceptedWebSocketSubprotocol);
 
12100#if !defined(MG_MAX_UNANSWERED_PING) 
12106#define MG_MAX_UNANSWERED_PING (5) 
12111read_websocket(
struct mg_connection *conn,
 
12113               void *callback_data)
 
12119   unsigned char *buf = (
unsigned char *)conn->buf + conn->request_len;
 
12120   int n, error, exit_by_callback;
 
12127   size_t i, len, mask_len = 0, header_len, body_len;
 
12128   uint64_t data_len = 0;
 
12133   unsigned char mask[4];
 
12138   unsigned char mem[4096];
 
12143   double timeout = -1.0;
 
12144   int enable_ping_pong = 0;
 
12145   int ping_count = 0;
 
12147   if (conn->dom_ctx->config[ENABLE_WEBSOCKET_PING_PONG]) {
 
12149          !
mg_strcasecmp(conn->dom_ctx->config[ENABLE_WEBSOCKET_PING_PONG],
 
12153   if (conn->dom_ctx->config[WEBSOCKET_TIMEOUT]) {
 
12154      timeout = atoi(conn->dom_ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
 
12161   DEBUG_TRACE(
"Websocket connection %s:%u start data processing loop",
 
12162               conn->request_info.remote_addr,
 
12163               conn->request_info.remote_port);
 
12164   conn->in_websocket_handling = 1;
 
12169   while (!conn->phys_ctx->stop_flag && !conn->must_close) {
 
12172      if ((body_len = (
size_t)(conn->data_len - conn->request_len)) >= 2) {
 
12173         len = buf[1] & 127;
 
12174         mask_len = (buf[1] & 128) ? 4 : 0;
 
12175         if ((len < 126) && (body_len >= mask_len)) {
 
12178            header_len = 2 + mask_len;
 
12179         } 
else if ((len == 126) && (body_len >= (4 + mask_len))) {
 
12181            header_len = 4 + mask_len;
 
12182            data_len = ((((size_t)buf[2]) << 8) + buf[3]);
 
12183         } 
else if (body_len >= (10 + mask_len)) {
 
12186            memcpy(&l1, &buf[2], 4); 
 
12187            memcpy(&l2, &buf[6], 4);
 
12188            header_len = 10 + mask_len;
 
12189            data_len = (((uint64_t)ntohl(l1)) << 32) + ntohl(l2);
 
12191            if (data_len > (uint64_t)0x7FFF0000ul) {
 
12196                   "websocket out of memory; closing connection");
 
12202      if ((header_len > 0) && (body_len >= header_len)) {
 
12204         unsigned char *data = mem;
 
12206         if ((
size_t)data_len > (
size_t)
sizeof(mem)) {
 
12209            if (data == NULL) {
 
12215                   "websocket out of memory; closing connection");
 
12221         if (mask_len > 0) {
 
12222            memcpy(mask, buf + header_len - mask_len, 
sizeof(mask));
 
12224            memset(mask, 0, 
sizeof(mask));
 
12230         if (data_len + (uint64_t)header_len > (uint64_t)body_len) {
 
12233            len = body_len - header_len;
 
12234            memcpy(data, buf + header_len, len);
 
12236            while ((uint64_t)len < data_len) {
 
12239                              (
char *)(data + len),
 
12240                              (
int)(data_len - len),
 
12245               } 
else if (
n > 0) {
 
12256                   "Websocket pull failed; closing connection");
 
12263            conn->data_len = conn->request_len;
 
12273            len = (size_t)data_len + header_len;
 
12278            memcpy(data, buf + header_len, (
size_t)data_len);
 
12281            memmove(buf, buf + len, body_len - len);
 
12284            conn->data_len -= (
int)len;
 
12288         if (mask_len > 0) {
 
12289            for (i = 0; i < (size_t)data_len; i++) {
 
12290               data[i] ^= mask[i & 3];
 
12294         exit_by_callback = 0;
 
12298                        conn->request_info.remote_addr,
 
12299                        conn->request_info.remote_port);
 
12302         } 
else if (enable_ping_pong
 
12306                        conn->request_info.remote_addr,
 
12307                        conn->request_info.remote_port);
 
12322            if ((ws_data_handler != NULL)
 
12323                && !ws_data_handler(conn,
 
12328               exit_by_callback = 1;
 
12337         if (exit_by_callback) {
 
12338            DEBUG_TRACE(
"Callback requests to close connection from %s:%u",
 
12339                        conn->request_info.remote_addr,
 
12340                        conn->request_info.remote_port);
 
12345            DEBUG_TRACE(
"Message requests to close connection from %s:%u",
 
12346                        conn->request_info.remote_addr,
 
12347                        conn->request_info.remote_port);
 
12357                        conn->buf + conn->data_len,
 
12358                        conn->buf_size - conn->data_len,
 
12363                        conn->request_info.remote_addr,
 
12364                        conn->request_info.remote_port);
 
12368            conn->data_len += 
n;
 
12372            if (!conn->phys_ctx->stop_flag && !conn->must_close) {
 
12373               if (ping_count > MG_MAX_UNANSWERED_PING) {
 
12375                  DEBUG_TRACE(
"Too many (%i) unanswered ping from %s:%u " 
12376                              "- closing connection",
 
12378                              conn->request_info.remote_addr,
 
12379                              conn->request_info.remote_port);
 
12382               if (enable_ping_pong) {
 
12385                              conn->request_info.remote_addr,
 
12386                              conn->request_info.remote_port);
 
12408   conn->in_websocket_handling = 0;
 
12409   DEBUG_TRACE(
"Websocket connection %s:%u left data processing loop",
 
12410               conn->request_info.remote_addr,
 
12411               conn->request_info.remote_port);
 
12416mg_websocket_write_exec(
struct mg_connection *conn,
 
12420                        uint32_t masking_key)
 
12422   unsigned char header[14];
 
12426#if defined(GCC_DIAGNOSTIC) 
12428#pragma GCC diagnostic push 
12429#pragma GCC diagnostic ignored "-Wconversion" 
12432   header[0] = 0x80u | (
unsigned char)((
unsigned)opcode & 0xf);
 
12434#if defined(GCC_DIAGNOSTIC) 
12435#pragma GCC diagnostic pop 
12439   if (dataLen < 126) {
 
12441      header[1] = (
unsigned char)dataLen;
 
12443   } 
else if (dataLen <= 0xFFFF) {
 
12445      uint16_t len = htons((uint16_t)dataLen);
 
12447      memcpy(header + 2, &len, 2);
 
12451      uint32_t len1 = htonl((uint32_t)((uint64_t)dataLen >> 32));
 
12452      uint32_t len2 = htonl((uint32_t)(dataLen & 0xFFFFFFFFu));
 
12454      memcpy(header + 2, &len1, 4);
 
12455      memcpy(header + 6, &len2, 4);
 
12462      memcpy(header + headerLen, &masking_key, 4);
 
12479   retval = 
mg_write(conn, header, headerLen);
 
12480   if (retval != (
int)headerLen) {
 
12485         retval = 
mg_write(conn, data, dataLen);
 
12502   return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
 
12507mask_data(
const char *in, 
size_t in_len, uint32_t masking_key, 
char *out)
 
12512   if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
 
12514      while (i < (in_len - 3)) {
 
12515         *(uint32_t *)(
void *)(out + i) =
 
12516             *(uint32_t *)(
void *)(in + i) ^ masking_key;
 
12522      while (i < in_len) {
 
12523         *(
uint8_t *)(
void *)(out + i) =
 
12525             ^ *(((
uint8_t *)&masking_key) + (i % 4));
 
12539   char *masked_data =
 
12540       (
char *)
mg_malloc_ctx(((dataLen + 7) / 4) * 4, conn->phys_ctx);
 
12541   uint32_t masking_key = 0;
 
12543   if (masked_data == NULL) {
 
12547                      "Cannot allocate buffer for masked websocket response: " 
12555   } 
while (masking_key == 0);
 
12557   mask_data(data, dataLen, masking_key, masked_data);
 
12559   retval = mg_websocket_write_exec(
 
12560       conn, opcode, masked_data, dataLen, masking_key);
 
12568handle_websocket_request(
struct mg_connection *conn,
 
12570                         int is_callback_resource,
 
12578   const char *websock_key = 
mg_get_header(conn, 
"Sec-WebSocket-Key");
 
12579   const char *version = 
mg_get_header(conn, 
"Sec-WebSocket-Version");
 
12580   ptrdiff_t lua_websock = 0;
 
12582#if !defined(USE_LUA) 
12588   if (!websock_key) {
 
12595      const char *key1 = 
mg_get_header(conn, 
"Sec-WebSocket-Key1");
 
12596      const char *key2 = 
mg_get_header(conn, 
"Sec-WebSocket-Key2");
 
12599      if ((key1 != NULL) && (key2 != NULL)) {
 
12601         conn->content_len = 8;
 
12602         if (8 == 
mg_read(conn, key3, 8)) {
 
12607                               "Protocol upgrade to RFC 6455 required");
 
12618   if ((version == NULL) || (strcmp(version, 
"13") != 0)) {
 
12628   if (is_callback_resource) {
 
12630      const char *protocols[64]; 
 
12631      int nbSubprotocolHeader = get_req_headers(&conn->request_info,
 
12632                                                "Sec-WebSocket-Protocol",
 
12635      if ((nbSubprotocolHeader > 0) && subprotocols) {
 
12639         const char *
sep, *curSubProtocol,
 
12640             *acceptedWebSocketSubprotocol = NULL;
 
12645            const char *protocol = protocols[
cnt];
 
12648               sep = strchr(protocol, 
',');
 
12649               curSubProtocol = protocol;
 
12650               len = 
sep ? (
unsigned long)(sep - protocol)
 
12651                         : (unsigned 
long)strlen(protocol);
 
12652               while (sep && isspace(*++sep))
 
12659                      && (strncmp(curSubProtocol,
 
12663                     acceptedWebSocketSubprotocol =
 
12668            } 
while (sep && !acceptedWebSocketSubprotocol);
 
12669         } 
while (++cnt < nbSubprotocolHeader
 
12670                  && !acceptedWebSocketSubprotocol);
 
12672         conn->request_info.acceptedWebSocketSubprotocol =
 
12673             acceptedWebSocketSubprotocol;
 
12675      } 
else if (nbSubprotocolHeader > 0) {
 
12677         const char *protocol = protocols[0];
 
12682         const char *
sep = strrchr(protocol, 
',');
 
12685            conn->request_info.acceptedWebSocketSubprotocol = protocol;
 
12695            while (isspace(*++sep)) {
 
12698            conn->request_info.acceptedWebSocketSubprotocol = 
sep;
 
12702      if ((ws_connect_handler != NULL)
 
12703          && (ws_connect_handler(conn, cbData) != 0)) {
 
12713#if defined(USE_LUA) 
12717      if (conn->dom_ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
 
12719             conn->dom_ctx->config[LUA_WEBSOCKET_EXTENSIONS],
 
12720             strlen(conn->dom_ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
 
12726         conn->lua_websocket_state = lua_websocket_new(path, conn);
 
12727         if (!conn->lua_websocket_state) {
 
12736   if (!is_callback_resource && !lua_websock) {
 
12746   if (!send_websocket_handshake(conn, websock_key)) {
 
12752   if (is_callback_resource) {
 
12753      if (ws_ready_handler != NULL) {
 
12754         ws_ready_handler(conn, cbData);
 
12756#if defined(USE_LUA) 
12757   } 
else if (lua_websock) {
 
12758      if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
 
12766   if (is_callback_resource) {
 
12767      read_websocket(conn, ws_data_handler, cbData);
 
12768#if defined(USE_LUA) 
12769   } 
else if (lua_websock) {
 
12770      read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
 
12775   if (ws_close_handler) {
 
12776      ws_close_handler(conn, cbData);
 
12784   const char *upgrade, *connection;
 
12793   if (upgrade == NULL) {
 
12803   if (connection == NULL) {
 
12825   return (
n >= 0) && (
n <= 255);
 
12834   if (((sscanf(spec, 
"%d.%d.%d.%d/%d%n", &
a, &
b, &
c, &
d, &
slash, &
n) == 5)
 
12835        || (sscanf(spec, 
"%d.%d.%d.%d%n", &
a, &
b, &
c, &
d, &
n) == 4))
 
12839      *net = ((uint32_t)
a << 24) | ((uint32_t)
b << 16) | ((uint32_t)
c << 8)
 
12841      *mask = 
slash ? (0xffffffffU << (32 - 
slash)) : 0;
 
12852   struct vec vec, val;
 
12853   uint32_t net, mask;
 
12857   while ((spec = 
next_option(spec, &vec, &val)) != NULL) {
 
12859      if ((val.ptr == NULL) || (sscanf(val.ptr, 
"%lf%c", &
v, &mult) < 1)
 
12862              && (mult != 
','))) {
 
12867               : ((
lowercase(&mult) == 
'm') ? 1048576 : 1);
 
12868      if (vec.len == 1 && vec.ptr[0] == 
'*') {
 
12870      } 
else if (
parse_net(vec.ptr, &net, &mask) > 0) {
 
12871         if ((remote_ip & mask) == net) {
 
12889   return ntohl(*(
const uint32_t *)&conn->client.rsa.sin.sin_addr);
 
12897#if defined(MG_LEGACY_INTERFACE) 
12903struct mg_upload_user_data {
 
12904   struct mg_connection *conn;
 
12905   const char *destination_dir;
 
12906   int num_uploaded_files;
 
12912mg_upload_field_found(
const char *key,
 
12913                      const char *filename,
 
12919   struct mg_upload_user_data *fud = (
struct mg_upload_user_data *)user_data;
 
12924      return FORM_FIELD_STORAGE_ABORT;
 
12931               fud->destination_dir,
 
12935      return FORM_FIELD_STORAGE_ABORT;
 
12937   return FORM_FIELD_STORAGE_STORE;
 
12943mg_upload_field_get(
const char *key,
 
12960mg_upload_field_stored(
const char *path, 
long long file_size, 
void *user_data)
 
12962   struct mg_upload_user_data *fud = (
struct mg_upload_user_data *)user_data;
 
12965   fud->num_uploaded_files++;
 
12966   fud->conn->phys_ctx->callbacks.upload(fud->conn, path);
 
12974mg_upload(
struct mg_connection *conn, 
const char *destination_dir)
 
12976   struct mg_upload_user_data fud = {conn, destination_dir, 0};
 
12978                                      mg_upload_field_get,
 
12979                                      mg_upload_field_stored,
 
12987      mg_cry_internal(conn, 
"%s: Error while parsing the request", __func__);
 
12990   return fud.num_uploaded_files;
 
13001      for (i = 0; ((idx == -1) && (i < ctx->num_listening_sockets)); i++) {
 
13002         idx = ctx->listening_sockets[i].is_ssl ? ((
int)(i)) : -1;
 
13015   size_t buflen = 
sizeof(buf);
 
13016   const char *host_header = 
get_header(conn->request_info.http_headers,
 
13017                                        conn->request_info.num_headers,
 
13021   if (host_header != NULL) {
 
13027      buf[buflen - 1] = 
'\0';
 
13029      while (isspace(*host)) {
 
13035      if (*host == 
'[') {
 
13036         pos = strchr(host, 
']');
 
13039            DEBUG_TRACE(
"%s", 
"Host name format error '[' without ']'");
 
13046         pos = strchr(host, 
':');
 
13056         if (sslhost && (conn->dom_ctx != &(conn->phys_ctx->dd))) {
 
13069         struct mg_domain_context *dom = &(conn->phys_ctx->dd);
 
13078               conn->dom_ctx = dom;
 
13104   conn->must_close = 1;
 
13110      int redirect_code = 308;
 
13117          sizeof(target_url),
 
13118          "https://%s:%d%s%s%s",
 
13121#
if defined(USE_IPV6)
 
13122          (conn->phys_ctx->listening_sockets[ssl_index].lsa.sa.sa_family
 
13124              ? (
int)ntohs(conn->phys_ctx->listening_sockets[ssl_index]
 
13125                               .lsa.sin6.sin6_port)
 
13128              (
int)ntohs(conn->phys_ctx->listening_sockets[ssl_index]
 
13129                             .lsa.sin.sin_port),
 
13130          conn->request_info.local_uri,
 
13131          (conn->request_info.query_string == NULL) ? 
"" : 
"?",
 
13132          (conn->request_info.query_string == NULL)
 
13134              : conn->request_info.query_string);
 
13152   pthread_mutex_lock(&handler_info->refcount_mutex);
 
13153   handler_info->refcount++;
 
13154   pthread_mutex_unlock(&handler_info->refcount_mutex);
 
13161   pthread_mutex_lock(&handler_info->refcount_mutex);
 
13162   handler_info->refcount--;
 
13163   pthread_cond_signal(&handler_info->refcount_cond);
 
13164   pthread_mutex_unlock(&handler_info->refcount_mutex);
 
13171   pthread_mutex_lock(&handler_info->refcount_mutex);
 
13172   while (handler_info->refcount) {
 
13173      pthread_cond_wait(&handler_info->refcount_cond,
 
13174                        &handler_info->refcount_mutex);
 
13176   pthread_mutex_unlock(&handler_info->refcount_mutex);
 
13182                    struct mg_domain_context *dom_ctx,
 
13185                    int is_delete_request,
 
13195   struct mg_handler_info *tmp_rh, **lastref;
 
13196   size_t urilen = strlen(uri);
 
13200      DEBUG_ASSERT(is_delete_request || connect_handler != NULL
 
13201                   || ready_handler != NULL || data_handler != NULL
 
13202                   || close_handler != NULL);
 
13205      if (handler != NULL) {
 
13208      if (!is_delete_request && (connect_handler == NULL)
 
13209          && (ready_handler == NULL) && (data_handler == NULL)
 
13210          && (close_handler == NULL)) {
 
13213      if (auth_handler != NULL) {
 
13217      DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL
 
13218                   && data_handler == NULL && close_handler == NULL);
 
13222      if ((connect_handler != NULL) || (ready_handler != NULL)
 
13223          || (data_handler != NULL) || (close_handler != NULL)) {
 
13226      if (!is_delete_request && (handler == NULL)) {
 
13229      if (auth_handler != NULL) {
 
13234      DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL
 
13235                   && data_handler == NULL && close_handler == NULL);
 
13237      if (handler != NULL) {
 
13240      if ((connect_handler != NULL) || (ready_handler != NULL)
 
13241          || (data_handler != NULL) || (close_handler != NULL)) {
 
13244      if (!is_delete_request && (auth_handler == NULL)) {
 
13249   if (!phys_ctx || !dom_ctx) {
 
13256   lastref = &(dom_ctx->handlers);
 
13257   for (tmp_rh = dom_ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
 
13258      if (tmp_rh->handler_type == handler_type) {
 
13259         if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
 
13260            if (!is_delete_request) {
 
13267                  tmp_rh->handler = handler;
 
13269                  tmp_rh->subprotocols = subprotocols;
 
13270                  tmp_rh->connect_handler = connect_handler;
 
13271                  tmp_rh->ready_handler = ready_handler;
 
13272                  tmp_rh->data_handler = data_handler;
 
13273                  tmp_rh->close_handler = close_handler;
 
13275                  tmp_rh->auth_handler = auth_handler;
 
13277               tmp_rh->cbdata = cbdata;
 
13286                  pthread_cond_destroy(&tmp_rh->refcount_cond);
 
13287                  pthread_mutex_destroy(&tmp_rh->refcount_mutex);
 
13289               *lastref = tmp_rh->next;
 
13297      lastref = &(tmp_rh->next);
 
13300   if (is_delete_request) {
 
13308       (
struct mg_handler_info *)
mg_calloc_ctx(
sizeof(
struct mg_handler_info),
 
13311   if (tmp_rh == NULL) {
 
13315                      "Cannot create new request handler struct, OOM");
 
13319   if (!tmp_rh->uri) {
 
13324                      "Cannot create new request handler struct, OOM");
 
13327   tmp_rh->uri_len = urilen;
 
13330      if (0 != pthread_mutex_init(&tmp_rh->refcount_mutex, NULL)) {
 
13336      if (0 != pthread_cond_init(&tmp_rh->refcount_cond, NULL)) {
 
13338         pthread_mutex_destroy(&tmp_rh->refcount_mutex);
 
13343      tmp_rh->refcount = 0;
 
13344      tmp_rh->handler = handler;
 
13346      tmp_rh->subprotocols = subprotocols;
 
13347      tmp_rh->connect_handler = connect_handler;
 
13348      tmp_rh->ready_handler = ready_handler;
 
13349      tmp_rh->data_handler = data_handler;
 
13350      tmp_rh->close_handler = close_handler;
 
13352      tmp_rh->auth_handler = auth_handler;
 
13354   tmp_rh->cbdata = cbdata;
 
13355   tmp_rh->handler_type = handler_type;
 
13356   tmp_rh->next = NULL;
 
13407    struct mg_context *ctx,
 
13416   int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
 
13417                           && (data_handler == NULL)
 
13418                           && (close_handler == NULL);
 
13468                    struct mg_handler_info **handler_info)
 
13471   if (request_info) {
 
13472      const char *uri = request_info->
local_uri;
 
13473      size_t urilen = strlen(uri);
 
13474      struct mg_handler_info *tmp_rh;
 
13476      if (!conn || !conn->phys_ctx || !conn->dom_ctx) {
 
13483      for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
 
13484           tmp_rh = tmp_rh->next) {
 
13485         if (tmp_rh->handler_type == handler_type) {
 
13486            if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
 
13488                  *subprotocols = tmp_rh->subprotocols;
 
13489                  *connect_handler = tmp_rh->connect_handler;
 
13490                  *ready_handler = tmp_rh->ready_handler;
 
13491                  *data_handler = tmp_rh->data_handler;
 
13492                  *close_handler = tmp_rh->close_handler;
 
13494                  *handler = tmp_rh->handler;
 
13497                  *handler_info = tmp_rh;
 
13499                  *auth_handler = tmp_rh->auth_handler;
 
13501               *cbdata = tmp_rh->cbdata;
 
13509      for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
 
13510           tmp_rh = tmp_rh->next) {
 
13511         if (tmp_rh->handler_type == handler_type) {
 
13512            if ((tmp_rh->uri_len < urilen) && (uri[tmp_rh->uri_len] == 
'/')
 
13513                && (memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0)) {
 
13515                  *subprotocols = tmp_rh->subprotocols;
 
13516                  *connect_handler = tmp_rh->connect_handler;
 
13517                  *ready_handler = tmp_rh->ready_handler;
 
13518                  *data_handler = tmp_rh->data_handler;
 
13519                  *close_handler = tmp_rh->close_handler;
 
13521                  *handler = tmp_rh->handler;
 
13524                  *handler_info = tmp_rh;
 
13526                  *auth_handler = tmp_rh->auth_handler;
 
13528               *cbdata = tmp_rh->cbdata;
 
13536      for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
 
13537           tmp_rh = tmp_rh->next) {
 
13538         if (tmp_rh->handler_type == handler_type) {
 
13539            if (
match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
 
13541                  *subprotocols = tmp_rh->subprotocols;
 
13542                  *connect_handler = tmp_rh->connect_handler;
 
13543                  *ready_handler = tmp_rh->ready_handler;
 
13544                  *data_handler = tmp_rh->data_handler;
 
13545                  *close_handler = tmp_rh->close_handler;
 
13547                  *handler = tmp_rh->handler;
 
13550                  *handler_info = tmp_rh;
 
13552                  *auth_handler = tmp_rh->auth_handler;
 
13554               *cbdata = tmp_rh->cbdata;
 
13582#if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE) 
13584deprecated_websocket_connect_wrapper(
const struct mg_connection *conn,
 
13588   if (pcallbacks->websocket_connect) {
 
13589      return pcallbacks->websocket_connect(conn);
 
13597deprecated_websocket_ready_wrapper(
struct mg_connection *conn, 
void *cbdata)
 
13600   if (pcallbacks->websocket_ready) {
 
13601      pcallbacks->websocket_ready(conn);
 
13607deprecated_websocket_data_wrapper(
struct mg_connection *conn,
 
13614   if (pcallbacks->websocket_data) {
 
13615      return pcallbacks->websocket_data(conn, bits, data, len);
 
13631   char path[PATH_MAX];
 
13632   int uri_len, ssl_index;
 
13633   int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
 
13634       is_put_or_delete_request = 0, is_callback_resource = 0;
 
13638   struct mg_handler_info *handler_info = NULL;
 
13644   void *callback_data = NULL;
 
13646   void *auth_callback_data = NULL;
 
13648   time_t curtime = time(NULL);
 
13655   if ((conn->request_info.query_string = strchr(ri->
request_uri, 
'?'))
 
13657      *((
char *)conn->request_info.query_string++) = 
'\0';
 
13661   if (!conn->client.is_ssl && conn->client.ssl_redir) {
 
13663      if (ssl_index >= 0) {
 
13671                            "Error: SSL forward not configured properly");
 
13674                         "Can not redirect to SSL, no SSL port available");
 
13700   if (conn->phys_ctx->callbacks.begin_request != NULL) {
 
13704      i = conn->phys_ctx->callbacks.begin_request(conn);
 
13708         conn->status_code = i;
 
13711      } 
else if (i == 0) {
 
13729      const char *cors_meth_cfg =
 
13731      const char *cors_orig_cfg =
 
13733      const char *cors_origin =
 
13737                                         "Access-Control-Request-Method");
 
13742      if ((cors_meth_cfg != NULL) && (*cors_meth_cfg != 0)
 
13743          && (cors_orig_cfg != NULL) && (*cors_orig_cfg != 0)
 
13744          && (cors_origin != NULL) && (cors_acrm != NULL)) {
 
13748         const char *cors_acrh =
 
13751                        "Access-Control-Request-Headers");
 
13755                   "HTTP/1.1 200 OK\r\n" 
13757                   "Access-Control-Allow-Origin: %s\r\n" 
13758                   "Access-Control-Allow-Methods: %s\r\n" 
13759                   "Content-Length: 0\r\n" 
13760                   "Connection: %s\r\n",
 
13763                   ((cors_meth_cfg[0] == 
'*') ? cors_acrm : cors_meth_cfg),
 
13766         if (cors_acrh != NULL) {
 
13768            const char *cors_hdr_cfg =
 
13771            if ((cors_hdr_cfg != NULL) && (*cors_hdr_cfg != 0)) {
 
13778                         "Access-Control-Allow-Headers: %s\r\n",
 
13779                         ((cors_hdr_cfg[0] == 
'*') ? cors_acrh
 
13783         mg_printf(conn, 
"Access-Control-Max-Age: 60\r\n");
 
13796#if defined(USE_WEBSOCKET) 
13806                           &ws_connect_handler,
 
13817      is_callback_resource = 1;
 
13818      is_script_resource = 1;
 
13821   no_callback_resource:
 
13826      is_callback_resource = 0;
 
13832                    &is_script_resource,
 
13833                    &is_websocket_request,
 
13834                    &is_put_or_delete_request);
 
13848                           &auth_callback_data,
 
13850      if (!auth_handler(conn, auth_callback_data)) {
 
13853   } 
else if (is_put_or_delete_request && !is_script_resource
 
13854              && !is_callback_resource) {
 
13857#if defined(NO_FILES) 
13866                            "%s method not allowed",
 
13867                            conn->request_info.request_method);
 
13871#if !defined(NO_FILES) 
13894   if (is_callback_resource) {
 
13895      if (!is_websocket_request) {
 
13896         i = callback_handler(conn, callback_data);
 
13905            conn->status_code = i;
 
13930                          &is_script_resource,
 
13931                          &is_websocket_request,
 
13932                          &is_put_or_delete_request);
 
13933            callback_handler = NULL;
 
13944            goto no_callback_resource;
 
13947#if defined(USE_WEBSOCKET) 
13948         handle_websocket_request(conn,
 
13950                                  is_callback_resource,
 
13952                                  ws_connect_handler,
 
13963#if defined(USE_WEBSOCKET) 
13964   if (is_websocket_request) {
 
13965      if (is_script_resource) {
 
13969            handle_websocket_request(conn,
 
13977                                     conn->phys_ctx->user_data);
 
13983#if defined(MG_LEGACY_INTERFACE) 
13984         handle_websocket_request(
 
13987             !is_script_resource ,
 
13989             deprecated_websocket_connect_wrapper,
 
13990             deprecated_websocket_ready_wrapper,
 
13991             deprecated_websocket_data_wrapper,
 
13993             conn->phys_ctx->user_data);
 
14002#if defined(NO_FILES) 
14017   if (is_script_resource) {
 
14023   if (is_put_or_delete_request) {
 
14044                         "%s method not allowed",
 
14045                         conn->request_info.request_method);
 
14057   if (
file.stat.is_directory && (uri_len > 0)
 
14058       && (ri->
local_uri[uri_len - 1] != 
'/')) {
 
14061                "HTTP/1.1 301 Moved Permanently\r\n" 
14062                "Location: %s/\r\n" 
14065                "Content-Length: 0\r\n" 
14066                "Connection: %s\r\n",
 
14096                         "%s method not allowed",
 
14097                         conn->request_info.request_method);
 
14102   if (
file.stat.is_directory) {
 
14113                            "Error: Directory listing denied");
 
14127                          struct mg_file *
file)
 
14129   if (!conn || !conn->dom_ctx) {
 
14134#if defined(USE_LUA) 
14136                  conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
 
14137                  strlen(conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
 
14145         handle_lsp_request(conn, path, 
file, NULL);
 
14151   } 
else if (
match_prefix(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS],
 
14153                               conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS]),
 
14161         mg_exec_lua_script(conn, path, NULL);
 
14167#if defined(USE_DUKTAPE) 
14169                  conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
 
14170                  strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
 
14175         mg_exec_duktape_script(conn, path);
 
14181#if !defined(NO_CGI) 
14204#if !defined(NO_CACHING) 
14205   } 
else if ((!conn->in_error_handler)
 
14224   for (i = 0; i < ctx->num_listening_sockets; i++) {
 
14228   mg_free(ctx->listening_sockets);
 
14229   ctx->listening_sockets = NULL;
 
14230   mg_free(ctx->listening_socket_fds);
 
14231   ctx->listening_socket_fds = NULL;
 
14252   unsigned int a, 
b, 
c, 
d, port;
 
14255#if defined(USE_IPV6) 
14256   char buf[100] = {0};
 
14262   memset(so, 0, 
sizeof(*so));
 
14263   so->lsa.sin.sin_family = AF_INET;
 
14271   if (sscanf(vec->ptr, 
"%u.%u.%u.%u:%u%n", &
a, &
b, &
c, &
d, &port, &len)
 
14274      so->lsa.sin.sin_addr.s_addr =
 
14275          htonl((
a << 24) | (
b << 16) | (
c << 8) | 
d);
 
14276      so->lsa.sin.sin_port = htons((uint16_t)port);
 
14279#if defined(USE_IPV6) 
14280   } 
else if (sscanf(vec->ptr, 
"[%49[^]]]:%u%n", buf, &port, &len) == 2
 
14282                     AF_INET6, buf, &so->lsa.sin6, 
sizeof(so->lsa.sin6))) {
 
14286      so->lsa.sin6.sin6_port = htons((uint16_t)port);
 
14290   } 
else if ((vec->ptr[0] == 
'+')
 
14291              && (sscanf(vec->ptr + 1, 
"%u%n", &port, &len) == 1)) {
 
14297#if defined(USE_IPV6) 
14299      so->lsa.sin6.sin6_family = AF_INET6;
 
14300      so->lsa.sin6.sin6_port = htons((uint16_t)port);
 
14301      *ip_version = 4 + 6;
 
14304      so->lsa.sin.sin_port = htons((uint16_t)port);
 
14308   } 
else if (sscanf(vec->ptr, 
"%u%n", &port, &len) == 1) {
 
14310      so->lsa.sin.sin_port = htons((uint16_t)port);
 
14313   } 
else if ((cb = strchr(vec->ptr, 
':')) != NULL) {
 
14323      char hostname[256];
 
14324      size_t hostnlen = (size_t)(cb - vec->ptr);
 
14326      if (hostnlen >= 
sizeof(hostname)) {
 
14332      memcpy(hostname, vec->ptr, hostnlen);
 
14333      hostname[hostnlen] = 0;
 
14336              AF_INET, vec->ptr, &so->lsa.sin, 
sizeof(so->lsa.sin))) {
 
14337         if (sscanf(cb + 1, 
"%u%n", &port, &len) == 1) {
 
14339            so->lsa.sin.sin_family = AF_INET;
 
14340            so->lsa.sin.sin_port = htons((uint16_t)port);
 
14341            len += (
int)(hostnlen + 1);
 
14346#if defined(USE_IPV6) 
14350                              sizeof(so->lsa.sin6))) {
 
14351         if (sscanf(cb + 1, 
"%u%n", &port, &len) == 1) {
 
14353            so->lsa.sin6.sin6_family = AF_INET6;
 
14354            so->lsa.sin.sin_port = htons((uint16_t)port);
 
14355            len += (
int)(hostnlen + 1);
 
14370   if ((len < 0) && ((unsigned)len > (
unsigned)vec->len)) {
 
14374   ch = vec->ptr[len]; 
 
14375   so->is_ssl = (ch == 
's');
 
14376   so->ssl_redir = (ch == 
'r');
 
14380       && ((ch == 
'\0') || (ch == 
's') || (ch == 
'r') || (ch == 
','))) {
 
14430      int portslen = (
int)strlen(ports);
 
14431      char prevIsNumber = 0;
 
14433      for (i = 0; i < portslen; i++) {
 
14434         if (prevIsNumber && (ports[i] == 
's' || ports[i] == 
'r')) {
 
14437         if (ports[i] >= 
'0' && ports[i] <= 
'9') {
 
14453#if defined(USE_IPV6) 
14457   struct socket so, *ptr;
 
14459   struct pollfd *pfd;
 
14464   int portsTotal = 0;
 
14471   memset(&so, 0, 
sizeof(so));
 
14472   memset(&usa, 0, 
sizeof(usa));
 
14476   while ((list = 
next_option(list, &vec, NULL)) != NULL) {
 
14483             "%.*s: invalid port spec (entry %i). Expecting list of: %s",
 
14487             "[IP_ADDRESS:]PORT[s|r]");
 
14491#if !defined(NO_SSL) 
14492      if (so.is_ssl && phys_ctx->dd.ssl_ctx == NULL) {
 
14495                         "Cannot add SSL socket (entry %i)",
 
14501      if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
 
14505                         "cannot create socket (entry %i)",
 
14520      if (setsockopt(so.sock,
 
14522                     SO_EXCLUSIVEADDRUSE,
 
14530             "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
 
14534      if (setsockopt(so.sock,
 
14543                         "cannot set socket option SO_REUSEADDR (entry %i)",
 
14548      if (ip_version > 4) {
 
14550#if defined(USE_IPV6) 
14551         if (ip_version > 6) {
 
14552            if (so.lsa.sa.sa_family == AF_INET6
 
14553                && setsockopt(so.sock,
 
14563                   "cannot set socket option IPV6_V6ONLY=off (entry %i)",
 
14567            if (so.lsa.sa.sa_family == AF_INET6
 
14568                && setsockopt(so.sock,
 
14578                   "cannot set socket option IPV6_V6ONLY=on (entry %i)",
 
14590      if (so.lsa.sa.sa_family == AF_INET) {
 
14592         len = 
sizeof(so.lsa.sin);
 
14593         if (bind(so.sock, &so.lsa.sa, len) != 0) {
 
14595                            "cannot bind to %.*s: %d (%s)",
 
14605#if defined(USE_IPV6) 
14606      else if (so.lsa.sa.sa_family == AF_INET6) {
 
14608         len = 
sizeof(so.lsa.sin6);
 
14609         if (bind(so.sock, &so.lsa.sa, len) != 0) {
 
14611                            "cannot bind to IPv6 %.*s: %d (%s)",
 
14625             "cannot bind: address family not supported (entry %i)",
 
14635                         "cannot listen to %.*s: %d (%s)",
 
14645      if ((getsockname(so.sock, &(usa.sa), &len) != 0)
 
14646          || (usa.sa.sa_family != so.lsa.sa.sa_family)) {
 
14650                         "call to getsockname failed %.*s: %d (%s)",
 
14661#if defined(USE_IPV6) 
14662      if (so.lsa.sa.sa_family == AF_INET6) {
 
14663         so.lsa.sin6.sin6_port = usa.sin6.sin6_port;
 
14667         so.lsa.sin.sin_port = usa.sin.sin_port;
 
14670      if ((ptr = (
struct socket *)
 
14672                              (phys_ctx->num_listening_sockets + 1)
 
14673                                  * 
sizeof(phys_ctx->listening_sockets[0]),
 
14683      if ((pfd = (
struct pollfd *)
 
14685                              (phys_ctx->num_listening_sockets + 1)
 
14686                                  * 
sizeof(phys_ctx->listening_socket_fds[0]),
 
14698      phys_ctx->listening_sockets = ptr;
 
14699      phys_ctx->listening_sockets[phys_ctx->num_listening_sockets] = so;
 
14700      phys_ctx->listening_socket_fds = pfd;
 
14701      phys_ctx->num_listening_sockets++;
 
14705   if (portsOk != portsTotal) {
 
14717   const char *header_value;
 
14719   if ((header_value = 
mg_get_header(conn, header)) == NULL) {
 
14722      return header_value;
 
14727#if defined(MG_EXTERNAL_FUNCTION_log_access) 
14728static void log_access(
const struct mg_connection *conn);
 
14729#include "external_log_access.inl" 
14740   const char *referer;
 
14741   const char *user_agent;
 
14745   if (!conn || !conn->dom_ctx) {
 
14755         fi.access.fp = NULL;
 
14758      fi.access.fp = NULL;
 
14763   if ((fi.access.fp == NULL)
 
14764       && (conn->phys_ctx->callbacks.log_access == NULL)) {
 
14768   tm = localtime(&conn->conn_birth_time);
 
14770      strftime(date, 
sizeof(date), 
"%d/%b/%Y:%H:%M:%S %z", tm);
 
14772      mg_strlcpy(date, 
"01/Jan/1970:00:00:00 +0000", 
sizeof(date));
 
14773      date[
sizeof(date) - 1] = 
'\0';
 
14776   ri = &conn->request_info;
 
14780   user_agent = 
header_val(conn, 
"User-Agent");
 
14786               "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
 
14796               conn->num_bytes_sent,
 
14800   if (conn->phys_ctx->callbacks.log_access) {
 
14801      conn->phys_ctx->callbacks.log_access(conn, buf);
 
14804   if (fi.access.fp) {
 
14806      flockfile(fi.access.fp);
 
14807      if (fprintf(fi.access.fp, 
"%s\n", buf) < 1) {
 
14810      if (fflush(fi.access.fp) != 0) {
 
14813      funlockfile(fi.access.fp);
 
14819                         "Error writing log file %s",
 
14835   uint32_t net, mask;
 
14842      allowed = (list == NULL) ? 
'+' : 
'-';
 
14844      while ((list = 
next_option(list, &vec, NULL)) != NULL) {
 
14846         if ((flag != 
'+' && flag != 
'-')
 
14847             || (
parse_net(&vec.ptr[1], &net, &mask) == 0)) {
 
14849                            "%s: subnet must be [+|-]x.x.x.x[/x]",
 
14854         if (net == (remote_ip & mask)) {
 
14859      return allowed == 
'+';
 
14865#if !defined(_WIN32) 
14873      const uid_t curr_uid = getuid();
 
14875      const char *run_as_user = phys_ctx->dd.config[
RUN_AS_USER];
 
14876      const struct passwd *to_pw = NULL;
 
14878      if (run_as_user != NULL && (to_pw = getpwnam(run_as_user)) == NULL) {
 
14882                         "%s: unknown user [%s]",
 
14885      } 
else if (run_as_user == NULL || curr_uid == to_pw->
pw_uid) {
 
14892         if (setgid(to_pw->
pw_gid) == -1) {
 
14894                            "%s: setgid(%s): %s",
 
14898         } 
else if (setgroups(0, NULL) == -1) {
 
14900                            "%s: setgroups(): %s",
 
14903         } 
else if (setuid(to_pw->
pw_uid) == -1) {
 
14905                            "%s: setuid(%s): %s",
 
14923   struct mg_workerTLS *tls = (
struct mg_workerTLS *)key;
 
14927      if (tls->is_master == 2) {
 
14928         tls->is_master = -3; 
 
14932   pthread_setspecific(
sTlsKey, NULL);
 
14936#if !defined(NO_SSL) 
14939                            struct mg_domain_context *dom_ctx,
 
14941                            const char *chain);
 
14948   static int reload_lock = 0;
 
14949   static long int data_check = 0;
 
14950   volatile int *p_reload_lock = (
volatile int *)&reload_lock;
 
14952   struct stat cert_buf;
 
14956   int should_verify_peer;
 
14964   if (chain == NULL) {
 
14973   if (stat(pem, &cert_buf) != -1) {
 
14974      t = (
long int)cert_buf.st_mtime;
 
14977   if (data_check != t) {
 
14980      should_verify_peer = 0;
 
14984            should_verify_peer = 1;
 
14988            should_verify_peer = 1;
 
14992      if (should_verify_peer) {
 
14993         char *ca_path = conn->dom_ctx->config[
SSL_CA_PATH];
 
14994         char *ca_file = conn->dom_ctx->config[
SSL_CA_FILE];
 
15000                fc(conn->phys_ctx),
 
15001                "SSL_CTX_load_verify_locations error: %s " 
15002                "ssl_verify_peer requires setting " 
15003                "either ssl_ca_path or ssl_ca_file. Is any of them " 
15016         *p_reload_lock = 0;
 
15020   while (*p_reload_lock) {
 
15027#if defined(OPENSSL_API_1_1) 
15035       int (*func)(
SSL *),
 
15036       volatile int *stop_server,
 
15059   if (conn->ssl == NULL) {
 
15064   ret = 
SSL_set_fd(conn->ssl, conn->client.sock);
 
15074   if (client_options) {
 
15083   for (i = 16; i <= 1024; i *= 2) {
 
15084      ret = func(conn->ssl);
 
15094            if (*stop_server) {
 
15143   const char hexdigit[] = 
"0123456789abcdef";
 
15145   if ((memlen <= 0) || (buflen <= 0)) {
 
15148   if (buflen < (3 * memlen)) {
 
15152   for (i = 0; i < memlen; i++) {
 
15154         buf[3 * i - 1] = 
' ';
 
15156      buf[3 * i] = hexdigit[(((
uint8_t *)mem)[i] >> 4) & 0xF];
 
15157      buf[3 * i + 1] = hexdigit[((
uint8_t *)mem)[i] & 0xF];
 
15159   buf[3 * memlen - 1] = 0;
 
15170      char str_subject[1024];
 
15171      char str_issuer[1024];
 
15172      char str_finger[1024];
 
15173      unsigned char buf[256];
 
15174      char *str_serial = NULL;
 
15177      unsigned char *tmp_buf;
 
15178      unsigned char *tmp_p;
 
15205      tmp_buf = (ilen > 0)
 
15213                 tmp_buf, (
unsigned)ilen, buf, &ulen, digest, NULL)) {
 
15220              buf, (
int)ulen, str_finger, (
int)
sizeof(str_finger))) {
 
15226      if (conn->request_info.client_cert) {
 
15227         conn->request_info.client_cert->peer_cert = (
void *)cert;
 
15228         conn->request_info.client_cert->subject =
 
15230         conn->request_info.client_cert->issuer =
 
15232         conn->request_info.client_cert->serial =
 
15234         conn->request_info.client_cert->finger =
 
15239                         "Out of memory: Cannot allocate memory for client " 
15250#if defined(OPENSSL_API_1_1) 
15268#if !defined(NO_SSL_DL) 
15270load_dll(
char *ebuf, 
size_t ebuf_len, 
const char *dll_name, 
struct ssl_func *sw)
 
15277   struct ssl_func *fp;
 
15281   if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
 
15286                  "%s: cannot load %s",
 
15293   for (fp = sw; fp->name != NULL; fp++) {
 
15296      u.fp = (
void (*)(
void))dlsym(dll_handle, fp->name);
 
15301      u.p = dlsym(dll_handle, fp->name);
 
15303      if (u.fp == NULL) {
 
15309                        "%s: %s: cannot find %s",
 
15315            size_t cur_len = strlen(ebuf);
 
15320                           ebuf_len - cur_len - 3,
 
15325                  strcat(ebuf, 
"...");
 
15337      (
void)dlclose(dll_handle);
 
15351#if defined(SSL_ALREADY_INITIALIZED) 
15361#if defined(OPENSSL_API_1_1) 
15362   if (ebuf_len > 0) {
 
15366#if !defined(NO_SSL_DL) 
15374                     "%s: error loading library %s",
 
15391   if (ebuf_len > 0) {
 
15395#if !defined(NO_SSL_DL) 
15403                     "%s: error loading library %s",
 
15420   if (num_locks < 0) {
 
15423   size = 
sizeof(pthread_mutex_t) * ((
size_t)(num_locks));
 
15426   if (num_locks == 0) {
 
15439                     "%s: cannot allocate mutexes: %s",
 
15447      for (i = 0; i < num_locks; i++) {
 
15453                        "%s: error initializing mutex %i of %i",
 
15468#if !defined(NO_SSL_DL) 
15472#if !defined(OPENSSL_API_1_1) 
15481#if defined(OPENSSL_API_1_1) 
15483   OPENSSL_init_ssl(0, NULL);
 
15499                 struct mg_domain_context *dom_ctx,
 
15505                      "%s: cannot open certificate file %s: %s",
 
15515                      "%s: cannot open private key file %s: %s",
 
15524                      "%s: certificate and private key do not match: %s",
 
15541                         "%s: cannot use certificate chain file %s: %s",
 
15552#if defined(OPENSSL_API_1_1) 
15553static unsigned long 
15556   long unsigned ret = (
long unsigned)
SSL_OP_ALL;
 
15557   if (version_id > 0)
 
15559   if (version_id > 1)
 
15561   if (version_id > 2)
 
15563   if (version_id > 3)
 
15572   if (version_id > 0)
 
15574   if (version_id > 1)
 
15576   if (version_id > 2)
 
15578   if (version_id > 3)
 
15614   struct mg_context *ctx = (
struct mg_context *)arg;
 
15615   struct mg_domain_context *dom =
 
15616       (
struct mg_domain_context *)ctx ? &(ctx->dd) : NULL;
 
15618#if defined(GCC_DIAGNOSTIC) 
15619#pragma GCC diagnostic push 
15620#pragma GCC diagnostic ignored "-Wcast-align" 
15624   struct mg_connection *conn = (
struct mg_connection *)
SSL_get_app_data(ssl);
 
15626#if defined(GCC_DIAGNOSTIC) 
15627#pragma GCC diagnostic pop 
15634   if ((ctx == NULL) || (conn->phys_ctx == ctx)) {
 
15635      DEBUG_TRACE(
"%s", 
"internal error - assertion failed");
 
15645   if ((servername == NULL) || (*servername == 0)) {
 
15646      DEBUG_TRACE(
"%s", 
"SSL connection not supporting SNI");
 
15647      conn->dom_ctx = &(ctx->dd);
 
15652   DEBUG_TRACE(
"TLS connection to host %s", servername);
 
15661         conn->dom_ctx = dom;
 
15670   conn->dom_ctx = &(ctx->dd);
 
15679                  struct mg_domain_context *dom_ctx,
 
15684   int should_verify_peer;
 
15685   int peer_certificate_optional;
 
15686   const char *ca_path;
 
15687   const char *ca_file;
 
15688   int use_default_verify_paths;
 
15690   struct timespec now_mt;
 
15695#if defined(OPENSSL_API_1_1) 
15696   if ((dom_ctx->ssl_ctx = 
SSL_CTX_new(TLS_server_method())) == NULL) {
 
15698                      "SSL_CTX_new (server) error: %s",
 
15705                      "SSL_CTX_new (server) error: %s",
 
15721#if !defined(NO_SSL_DL) 
15745   callback_ret = (phys_ctx->callbacks.init_ssl == NULL)
 
15747                      : (phys_ctx->callbacks.init_ssl(dom_ctx->ssl_ctx,
 
15748                                                      phys_ctx->user_data));
 
15753   if (callback_ret < 0) {
 
15755                      "SSL callback returned error: %i",
 
15759   if (callback_ret > 0) {
 
15767   clock_gettime(CLOCK_MONOTONIC, &now_mt);
 
15780                                  (
unsigned char *)ssl_context_id,
 
15781                                  sizeof(ssl_context_id));
 
15791   should_verify_peer = 0;
 
15792   peer_certificate_optional = 0;
 
15796         should_verify_peer = 1;
 
15797         peer_certificate_optional = 0;
 
15802         should_verify_peer = 1;
 
15803         peer_certificate_optional = 1;
 
15807   use_default_verify_paths =
 
15812   if (should_verify_peer) {
 
15818                         "SSL_CTX_load_verify_locations error: %s " 
15819                         "ssl_verify_peer requires setting " 
15820                         "either ssl_ca_path or ssl_ca_file. " 
15821                         "Is any of them present in the " 
15827      if (peer_certificate_optional) {
 
15836      if (use_default_verify_paths
 
15839                         "SSL_CTX_set_default_verify_paths error: %s",
 
15855                         "SSL_CTX_set_cipher_list error: %s",
 
15881      dom_ctx = &(phys_ctx->dd);
 
15891       (phys_ctx->callbacks.external_ssl_ctx == NULL)
 
15893           : (phys_ctx->callbacks.external_ssl_ctx(&ssl_ctx,
 
15894                                                   phys_ctx->user_data));
 
15896   if (callback_ret < 0) {
 
15898                      "external_ssl_ctx callback returned error: %i",
 
15901   } 
else if (callback_ret > 0) {
 
15902      dom_ctx->ssl_ctx = (
SSL_CTX *)ssl_ctx;
 
15915       && (phys_ctx->callbacks.init_ssl == NULL)) {
 
15920                      "Initializing SSL failed: -%s is not set",
 
15926   if (chain == NULL) {
 
15929   if ((chain != NULL) && (*chain == 0)) {
 
15945#if defined(OPENSSL_API_1_1) 
15990         dom_ctx = &(phys_ctx->dd);
 
15993      if ((path != NULL) && !
mg_stat(
fc(phys_ctx), path, &
file.stat)) {
 
15995                         "Cannot open %s: %s",
 
16009   return check_acl(phys_ctx, (uint32_t)0x7f000001UL) != -1;
 
16019   conn->connection_type =
 
16022   conn->num_bytes_sent = conn->consumed_content = 0;
 
16024   conn->path_info = NULL;
 
16025   conn->status_code = -1;
 
16026   conn->content_len = -1;
 
16027   conn->is_chunked = 0;
 
16028   conn->must_close = 0;
 
16029   conn->request_len = 0;
 
16030   conn->throttle = 0;
 
16031   conn->data_len = 0;
 
16032   conn->chunk_remainder = 0;
 
16033   conn->accept_gzip = 0;
 
16035   conn->response_info.content_length = conn->request_info.content_length = -1;
 
16036   conn->response_info.http_version = conn->request_info.http_version = NULL;
 
16037   conn->response_info.num_headers = conn->request_info.num_headers = 0;
 
16038   conn->response_info.status_text = NULL;
 
16039   conn->response_info.status_code = 0;
 
16041   conn->request_info.remote_user = NULL;
 
16042   conn->request_info.request_method = NULL;
 
16043   conn->request_info.request_uri = NULL;
 
16044   conn->request_info.local_uri = NULL;
 
16046#if defined(MG_LEGACY_INTERFACE) 
16048   conn->request_info.uri = NULL;
 
16060set_sock_timeout(
SOCKET sock, 
int milliseconds)
 
16062        int r0 = 0, r1, r2;
 
16067        DWORD tv = (DWORD)milliseconds;
 
16081#if defined(TCP_USER_TIMEOUT) 
16082        unsigned int uto = (
unsigned int)milliseconds;
 
16083        r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (
const void *)&uto, 
sizeof(uto));
 
16086        memset(&tv, 0, 
sizeof(tv));
 
16087        tv.tv_sec = milliseconds / 1000;
 
16088        tv.tv_usec = (milliseconds * 1000) % 1000000;
 
16093            sock, SOL_SOCKET, SO_RCVTIMEO, (
SOCK_OPT_TYPE)&tv, 
sizeof(tv));
 
16095            sock, SOL_SOCKET, SO_SNDTIMEO, (
SOCK_OPT_TYPE)&tv, 
sizeof(tv));
 
16097        return r0 || r1 || r2;
 
16105   if (setsockopt(sock,
 
16109                  sizeof(nodelay_on))
 
16126   struct linger linger;
 
16127   int error_code = 0;
 
16128   int linger_timeout = -2;
 
16129   socklen_t opt_len = 
sizeof(error_code);
 
16152      n = 
pull_inner(NULL, conn, buf, 
sizeof(buf),  1.0);
 
16161   if (linger_timeout >= 0) {
 
16164      linger.l_onoff = 1;
 
16166#if defined(_MSC_VER) 
16167#pragma warning(push) 
16168#pragma warning(disable : 4244) 
16170#if defined(GCC_DIAGNOSTIC) 
16171#pragma GCC diagnostic push 
16172#pragma GCC diagnostic ignored "-Wconversion" 
16178      linger.l_linger = (linger_timeout + 999) / 1000;
 
16180#if defined(GCC_DIAGNOSTIC) 
16181#pragma GCC diagnostic pop 
16183#if defined(_MSC_VER) 
16184#pragma warning(pop) 
16188      linger.l_onoff = 0;
 
16189      linger.l_linger = 0;
 
16192   if (linger_timeout < -1) {
 
16194   } 
else if (getsockopt(conn->client.sock,
 
16198                         (
char *)&error_code,
 
16208                      "%s: getsockopt(SOL_SOCKET SO_ERROR) failed: %s",
 
16211   } 
else if (error_code == ECONNRESET) {
 
16217      if (setsockopt(conn->client.sock,
 
16225             "%s: setsockopt(SOL_SOCKET SO_LINGER(%i,%i)) failed: %s",
 
16242#if defined(USE_SERVER_STATS) 
16243   conn->conn_state = 6; 
 
16246#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
16247   if (conn->lua_websocket_state) {
 
16248      lua_websocket_close(conn, conn->lua_websocket_state);
 
16249      conn->lua_websocket_state = NULL;
 
16256   conn->must_close = 1;
 
16259   if (conn->phys_ctx->callbacks.connection_close != NULL) {
 
16261         conn->phys_ctx->callbacks.connection_close(conn);
 
16271#if defined(USE_SERVER_STATS) 
16272   conn->conn_state = 7; 
 
16275#if !defined(NO_SSL) 
16276   if (conn->ssl != NULL) {
 
16297#if defined(USE_SERVER_STATS) 
16298   conn->conn_state = 8; 
 
16306#if defined(USE_WEBSOCKET) 
16307   struct mg_context *client_ctx = NULL;
 
16310   if ((conn == NULL) || (conn->phys_ctx == NULL)) {
 
16314#if defined(USE_WEBSOCKET) 
16316      if (conn->in_websocket_handling) {
 
16318         conn->must_close = 1;
 
16327      client_ctx = conn->phys_ctx;
 
16330      client_ctx->stop_flag = 1;
 
16331      conn->must_close = 1;
 
16339      for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
 
16340         if (client_ctx->worker_threadids[i] != 0) {
 
16349#if !defined(NO_SSL) 
16350   if (conn->client_ssl_ctx != NULL) {
 
16355#if defined(USE_WEBSOCKET) 
16356   if (client_ctx != NULL) {
 
16358      mg_free(client_ctx->worker_threadids);
 
16360      (
void)pthread_mutex_destroy(&conn->mutex);
 
16377static struct mg_connection *
 
16383   struct mg_connection *conn = NULL;
 
16386   struct sockaddr *psa;
 
16389   unsigned max_req_size =
 
16393   size_t conn_size = ((
sizeof(
struct mg_connection) + 7) >> 3) << 3;
 
16394   size_t ctx_size = ((
sizeof(
struct mg_context) + 7) >> 3) << 3;
 
16399   if (conn == NULL) {
 
16409#if defined(GCC_DIAGNOSTIC) 
16410#pragma GCC diagnostic push 
16411#pragma GCC diagnostic ignored "-Wcast-align" 
16415   conn->phys_ctx = (
struct mg_context *)(((
char *)conn) + conn_size);
 
16417#if defined(GCC_DIAGNOSTIC) 
16418#pragma GCC diagnostic pop 
16421   conn->buf = (((
char *)conn) + conn_size + ctx_size);
 
16422   conn->buf_size = (
int)max_req_size;
 
16424   conn->dom_ctx = &(conn->phys_ctx->dd);
 
16427                       client_options->
host,
 
16428                       client_options->
port,
 
16440#if !defined(NO_SSL) 
16441#if defined(OPENSSL_API_1_1) 
16443       && (conn->client_ssl_ctx = 
SSL_CTX_new(TLS_client_method())) == NULL) {
 
16448                  "SSL_CTX_new error");
 
16461                  "SSL_CTX_new error");
 
16470#if defined(USE_IPV6) 
16471   len = (sa.sa.sa_family == AF_INET) ? 
sizeof(conn->client.rsa.sin)
 
16472                                      : 
sizeof(conn->client.rsa.sin6);
 
16473   psa = (sa.sa.sa_family == AF_INET)
 
16474             ? (
struct sockaddr *)&(conn->client.rsa.sin)
 
16475             : (
struct sockaddr *)&(conn->client.rsa.sin6);
 
16477   len = 
sizeof(conn->client.rsa.sin);
 
16478   psa = (
struct sockaddr *)&(conn->client.rsa.sin);
 
16481   conn->client.sock = sock;
 
16482   conn->client.lsa = sa;
 
16484   if (getsockname(sock, psa, &len) != 0) {
 
16486                      "%s: getsockname() failed: %s",
 
16491   conn->client.is_ssl = use_ssl ? 1 : 0;
 
16497                  "Can not create mutex");
 
16498#if !defined(NO_SSL) 
16507#if !defined(NO_SSL) 
16527                        "Can not use SSL client certificate");
 
16545                  conn->client_ssl_ctx,
 
16547                  &(conn->phys_ctx->stop_flag),
 
16553                     "SSL connection error");
 
16564                      "Cannot set non-blocking mode for client %s:%i",
 
16565                      client_options->
host,
 
16566                      client_options->
port);
 
16575                         char *error_buffer,
 
16576                         size_t error_buffer_size)
 
16581                                 error_buffer_size);
 
16585struct mg_connection *
 
16589                  char *error_buffer,
 
16590                  size_t error_buffer_size)
 
16593   memset(&opts, 0, 
sizeof(opts));
 
16599                                 error_buffer_size);
 
16603static const struct {
 
16608                         {
"https://", 8, 443},
 
16610                         {
"wss://", 6, 443},
 
16624   const char *hostend, *portbegin;
 
16626   unsigned long port;
 
16632   if ((uri[0] == 
'*') && (uri[1] == 
'\0')) {
 
16643   for (i = 0; uri[i] != 0; i++) {
 
16648      if (uri[i] > 126) {
 
16671   if (uri[0] == 
'/') {
 
16695         port = strtoul(portbegin + 1, &portend, 10);
 
16696         if ((portend != hostend) || (port <= 0) || !
is_valid_port(port)) {
 
16712   const char *server_domain;
 
16713   size_t server_domain_len;
 
16714   size_t request_domain_len = 0;
 
16715   unsigned long port = 0;
 
16716   int i, auth_domain_check_enabled;
 
16717   const char *hostbegin = NULL;
 
16718   const char *hostend = NULL;
 
16719   const char *portbegin;
 
16722   auth_domain_check_enabled =
 
16734         hostend = strchr(hostbegin, 
'/');
 
16738         portbegin = strchr(hostbegin, 
':');
 
16739         if ((!portbegin) || (portbegin > hostend)) {
 
16741            request_domain_len = (size_t)(hostend - hostbegin);
 
16743            port = strtoul(portbegin + 1, &portend, 10);
 
16744            if ((portend != hostend) || (port <= 0)
 
16748            request_domain_len = (size_t)(portbegin - hostbegin);
 
16762#if defined(USE_IPV6) 
16763   if (conn->client.lsa.sa.sa_family == AF_INET6) {
 
16764      if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
 
16771      if (ntohs(conn->client.lsa.sin.sin_port) != port) {
 
16785   if (auth_domain_check_enabled) {
 
16787      server_domain_len = strlen(server_domain);
 
16788      if ((server_domain_len == 0) || (hostbegin == NULL)) {
 
16791      if ((request_domain_len == server_domain_len)
 
16792          && (!memcmp(server_domain, hostbegin, server_domain_len))) {
 
16795         if (request_domain_len < (server_domain_len + 2)) {
 
16802         if (hostbegin[request_domain_len - server_domain_len - 1] != 
'.') {
 
16809             != memcmp(server_domain,
 
16810                       hostbegin + request_domain_len - server_domain_len,
 
16811                       server_domain_len)) {
 
16824get_message(
struct mg_connection *conn, 
char *ebuf, 
size_t ebuf_len, 
int *err)
 
16826   if (ebuf_len > 0) {
 
16845   clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
 
16847   conn->request_len =
 
16848       read_message(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
 
16849   DEBUG_ASSERT(conn->request_len < 0 || conn->data_len >= conn->request_len);
 
16850   if ((conn->request_len >= 0) && (conn->data_len < conn->request_len)) {
 
16856                  "Invalid message size");
 
16861   if ((conn->request_len == 0) && (conn->data_len == conn->buf_size)) {
 
16867                  "Message too large");
 
16872   if (conn->request_len <= 0) {
 
16873      if (conn->data_len > 0) {
 
16879                     "Malformed message");
 
16883         conn->must_close = 1;
 
16889                     "No data received");
 
16899get_request(
struct mg_connection *conn, 
char *ebuf, 
size_t ebuf_len, 
int *err)
 
16928                  "Bad request: Host mismatch");
 
16934   if ((cl = 
get_header(conn->request_info.http_headers,
 
16935                        conn->request_info.num_headers,
 
16939      char *endptr = NULL;
 
16940      conn->content_len = strtoll(cl, &endptr, 10);
 
16941      if (endptr == cl) {
 
16952      conn->request_info.content_length = conn->content_len;
 
16953   } 
else if ((cl = 
get_header(conn->request_info.http_headers,
 
16954                               conn->request_info.num_headers,
 
16955                               "Transfer-Encoding"))
 
16958      conn->is_chunked = 1;
 
16959      conn->content_len = -1; 
 
16961      const struct mg_http_method_info *meth =
 
16974      if (meth->request_has_body) {
 
16976         conn->content_len = -1; 
 
16979         conn->content_len = 0; 
 
17012   if ((cl = 
get_header(conn->response_info.http_headers,
 
17013                        conn->response_info.num_headers,
 
17017      char *endptr = NULL;
 
17018      conn->content_len = strtoll(cl, &endptr, 10);
 
17019      if (endptr == cl) {
 
17030      conn->response_info.content_length = conn->content_len;
 
17033      conn->request_info.content_length = conn->content_len;
 
17035   } 
else if ((cl = 
get_header(conn->response_info.http_headers,
 
17036                               conn->response_info.num_headers,
 
17037                               "Transfer-Encoding"))
 
17040      conn->is_chunked = 1;
 
17041      conn->content_len = -1; 
 
17043      conn->content_len = -1; 
 
17059   char *save_timeout;
 
17062   if (ebuf_len > 0) {
 
17072                  "Parameter error");
 
17079   if (timeout >= 0) {
 
17080      mg_snprintf(conn, NULL, txt, 
sizeof(txt), 
"%i", timeout);
 
17086      new_timeout = NULL;
 
17093#if defined(MG_LEGACY_INTERFACE) 
17096   conn->request_info.uri = conn->request_info.request_uri;
 
17098   conn->request_info.local_uri = conn->request_info.request_uri;
 
17102   return (ret == 0) ? -1 : +1;
 
17106struct mg_connection *
 
17115   struct mg_connection *conn;
 
17120   if (ebuf_len > 0) {
 
17129   if (conn != NULL) {
 
17137                     "Error sending request");
 
17141#if defined(MG_LEGACY_INTERFACE) 
17144         conn->request_info.uri = conn->request_info.request_uri;
 
17146         conn->request_info.local_uri = conn->request_info.request_uri;
 
17151   if ((ebuf[0] != 
'\0') && (conn != NULL)) {
 
17161struct websocket_client_thread_data {
 
17162   struct mg_connection *conn;
 
17165   void *callback_data;
 
17169#if defined(USE_WEBSOCKET) 
17171static unsigned __stdcall websocket_client_thread(
void *data)
 
17174websocket_client_thread(
void *data)
 
17177   struct websocket_client_thread_data *cdata =
 
17178       (
struct websocket_client_thread_data *)data;
 
17180#if !defined(_WIN32) 
17181   struct sigaction sa;
 
17184   memset(&sa, 0, 
sizeof(sa));
 
17185   sa.sa_handler = SIG_IGN;
 
17186   sigaction(SIGPIPE, &sa, NULL);
 
17191   if (cdata->conn->phys_ctx) {
 
17192      if (cdata->conn->phys_ctx->callbacks.init_thread) {
 
17195         cdata->conn->phys_ctx->callbacks.init_thread(cdata->conn->phys_ctx,
 
17200   read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
 
17202   DEBUG_TRACE(
"%s", 
"Websocket client thread exited\n");
 
17204   if (cdata->close_handler != NULL) {
 
17205      cdata->close_handler(cdata->conn, cdata->callback_data);
 
17210   cdata->conn->phys_ctx->stop_flag = 2;
 
17223struct mg_connection *
 
17227                            char *error_buffer,
 
17228                            size_t error_buffer_size,
 
17230                            const char *origin,
 
17235   struct mg_connection *conn = NULL;
 
17237#if defined(USE_WEBSOCKET) 
17238   struct mg_context *newctx = NULL;
 
17239   struct websocket_client_thread_data *thread_data;
 
17240   static const char *magic = 
"x3JJHMbDL1EzLkh9GBhXDw==";
 
17241   static const char *handshake_req;
 
17243   if (origin != NULL) {
 
17244      handshake_req = 
"GET %s HTTP/1.1\r\n" 
17246                      "Upgrade: websocket\r\n" 
17247                      "Connection: Upgrade\r\n" 
17248                      "Sec-WebSocket-Key: %s\r\n" 
17249                      "Sec-WebSocket-Version: 13\r\n" 
17253      handshake_req = 
"GET %s HTTP/1.1\r\n" 
17255                      "Upgrade: websocket\r\n" 
17256                      "Connection: Upgrade\r\n" 
17257                      "Sec-WebSocket-Key: %s\r\n" 
17258                      "Sec-WebSocket-Version: 13\r\n" 
17262#if defined(__clang__) 
17263#pragma clang diagnostic push 
17264#pragma clang diagnostic ignored "-Wformat-nonliteral" 
17279#if defined(__clang__) 
17280#pragma clang diagnostic pop 
17284   if (conn == NULL) {
 
17285      if (!*error_buffer) {
 
17291                     "Unexpected error");
 
17296   if (conn->response_info.status_code != 101) {
 
17301      if (!*error_buffer) {
 
17307                     "Unexpected server reply");
 
17310      DEBUG_TRACE(
"Websocket client connect error: %s\r\n", error_buffer);
 
17317   newctx = (
struct mg_context *)
mg_malloc(
sizeof(
struct mg_context));
 
17324   memcpy(newctx, conn->phys_ctx, 
sizeof(
struct mg_context));
 
17325   newctx->user_data = user_data;
 
17327   newctx->cfg_worker_threads = 1; 
 
17328   newctx->worker_threadids =
 
17333   conn->phys_ctx = newctx;
 
17334   conn->dom_ctx = &(newctx->dd);
 
17336   thread_data = (
struct websocket_client_thread_data *)
 
17337       mg_calloc_ctx(
sizeof(
struct websocket_client_thread_data), 1, newctx);
 
17338   if (!thread_data) {
 
17345   thread_data->conn = conn;
 
17346   thread_data->data_handler = data_func;
 
17347   thread_data->close_handler = close_func;
 
17348   thread_data->callback_data = user_data;
 
17354                               (
void *)thread_data,
 
17355                               newctx->worker_threadids)
 
17357      mg_free((
void *)thread_data);
 
17358      mg_free((
void *)newctx->worker_threadids);
 
17363                  "Websocket client connect thread could not be started\r\n");
 
17371   (
void)error_buffer;
 
17372   (
void)error_buffer_size;
 
17389   int keep_alive_enabled =
 
17392   if (!keep_alive_enabled) {
 
17393      conn->must_close = 1;
 
17398   conn->data_len = 0;
 
17399   conn->handled_requests = 0;
 
17402#if defined(USE_SERVER_STATS) 
17403   conn->conn_state = 2; 
 
17407   if (conn->phys_ctx->callbacks.init_connection != NULL) {
 
17409         void *conn_data = NULL;
 
17410         conn->phys_ctx->callbacks.init_connection(conn, &conn_data);
 
17426   int keep_alive, discard_len;
 
17428   const char *hostend;
 
17429   int reqerr, uri_type;
 
17431#if defined(USE_SERVER_STATS) 
17432   int mcon = 
mg_atomic_inc(&(conn->phys_ctx->active_connections));
 
17433   mg_atomic_add(&(conn->phys_ctx->total_connections), 1);
 
17434   if (mcon > (conn->phys_ctx->max_connections)) {
 
17437      conn->phys_ctx->max_connections = mcon;
 
17443   DEBUG_TRACE(
"Start processing connection from %s",
 
17444               conn->request_info.remote_addr);
 
17450      DEBUG_TRACE(
"calling get_request (%i times for this connection)",
 
17451                  conn->handled_requests + 1);
 
17453#if defined(USE_SERVER_STATS) 
17454      conn->conn_state = 3; 
 
17457      if (!
get_request(conn, ebuf, 
sizeof(ebuf), &reqerr)) {
 
17471                     "Bad HTTP version: [%s]",
 
17476      if (ebuf[0] == 
'\0') {
 
17477         uri_type = 
get_uri_type(conn->request_info.request_uri);
 
17478         switch (uri_type) {
 
17481            conn->request_info.local_uri = NULL;
 
17485            conn->request_info.local_uri = conn->request_info.request_uri;
 
17491                conn->request_info.request_uri, conn);
 
17493               conn->request_info.local_uri = hostend;
 
17495               conn->request_info.local_uri = NULL;
 
17505            conn->request_info.local_uri = NULL;
 
17509#if defined(MG_LEGACY_INTERFACE) 
17511         conn->request_info.uri = conn->request_info.local_uri;
 
17517                  (ebuf[0] ? ebuf : 
"none"));
 
17519      if (ebuf[0] == 
'\0') {
 
17520         if (conn->request_info.local_uri) {
 
17523#if defined(USE_SERVER_STATS) 
17524            conn->conn_state = 4; 
 
17528#if defined(USE_SERVER_STATS) 
17529            conn->conn_state = 5; 
 
17531            mg_atomic_add(&(conn->phys_ctx->total_data_read),
 
17532                          conn->consumed_content);
 
17533            mg_atomic_add(&(conn->phys_ctx->total_data_written),
 
17534                          conn->num_bytes_sent);
 
17539            if (conn->phys_ctx->callbacks.end_request != NULL) {
 
17540               conn->phys_ctx->callbacks.end_request(conn,
 
17541                                                     conn->status_code);
 
17547            conn->must_close = 1;
 
17550         conn->must_close = 1;
 
17566                   && (conn->content_len >= 0);
 
17570      discard_len = ((conn->content_len >= 0) && (conn->request_len > 0)
 
17571                     && ((conn->request_len + conn->content_len)
 
17572                         < (int64_t)conn->data_len))
 
17573                        ? (
int)(conn->request_len + conn->content_len)
 
17576      if (discard_len < 0) {
 
17578                     (
long int)discard_len);
 
17581      conn->data_len -= discard_len;
 
17582      if (conn->data_len > 0) {
 
17583         DEBUG_TRACE(
"discard_len = %lu", (
long unsigned)discard_len);
 
17584         memmove(conn->buf, conn->buf + discard_len, (
size_t)conn->data_len);
 
17590      if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
 
17591         DEBUG_TRACE(
"internal error: data_len = %li, buf_size = %li",
 
17592                     (
long int)conn->data_len,
 
17593                     (
long int)conn->buf_size);
 
17597      conn->handled_requests++;
 
17599   } 
while (keep_alive);
 
17601   DEBUG_TRACE(
"Done processing connection from %s (%f sec)",
 
17602               conn->request_info.remote_addr,
 
17603               difftime(time(NULL), conn->conn_birth_time));
 
17607#if defined(USE_SERVER_STATS) 
17608   mg_atomic_add(&(conn->phys_ctx->total_requests), conn->handled_requests);
 
17614#if defined(ALTERNATIVE_QUEUE) 
17621   while (!ctx->stop_flag) {
 
17622      for (i = 0; i < ctx->cfg_worker_threads; i++) {
 
17624         if (ctx->client_socks[i].in_use == 0) {
 
17625            ctx->client_socks[i] = *sp;
 
17626            ctx->client_socks[i].in_use = 1;
 
17641   ctx->client_socks[thread_index].in_use = 0;
 
17642   event_wait(ctx->client_wait_events[thread_index]);
 
17643   *sp = ctx->client_socks[thread_index];
 
17644   DEBUG_TRACE(
"grabbed socket %d, going busy", sp ? sp->sock : -1);
 
17646   return !ctx->stop_flag;
 
17653consume_socket(
struct mg_context *ctx, 
struct socket *sp, 
int thread_index)
 
17655#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue))) 
17657   (
void)thread_index;
 
17659   (
void)pthread_mutex_lock(&ctx->thread_mutex);
 
17663   while ((ctx->sq_head == ctx->sq_tail) && (ctx->stop_flag == 0)) {
 
17664      pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
 
17668   if (ctx->sq_head > ctx->sq_tail) {
 
17670      *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
 
17673      DEBUG_TRACE(
"grabbed socket %d, going busy", sp ? sp->sock : -1);
 
17676      while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
 
17677         ctx->sq_tail -= QUEUE_SIZE(ctx);
 
17678         ctx->sq_head -= QUEUE_SIZE(ctx);
 
17682   (
void)pthread_cond_signal(&ctx->sq_empty);
 
17683   (
void)pthread_mutex_unlock(&ctx->thread_mutex);
 
17685   return !ctx->stop_flag;
 
17694#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue))) 
17698   (
void)pthread_mutex_lock(&ctx->thread_mutex);
 
17701   while ((ctx->stop_flag == 0)
 
17702          && (ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx))) {
 
17703      (
void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
 
17706   if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
 
17708      ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
 
17710      DEBUG_TRACE(
"queued socket %d", sp ? sp->sock : -1);
 
17713   (
void)pthread_cond_signal(&ctx->sq_full);
 
17714   (
void)pthread_mutex_unlock(&ctx->thread_mutex);
 
17720struct worker_thread_args {
 
17721   struct mg_context *ctx;
 
17729   struct mg_context *ctx = thread_args->ctx;
 
17730   struct mg_connection *conn;
 
17731   struct mg_workerTLS tls;
 
17732#if defined(MG_LEGACY_INTERFACE) 
17741   tls.pthread_cond_helper_mutex = CreateEvent(NULL, 
FALSE, 
FALSE, NULL);
 
17745   pthread_setspecific(
sTlsKey, &tls);
 
17747   if (ctx->callbacks.init_thread) {
 
17749      ctx->callbacks.init_thread(ctx, 1);
 
17753   if (((
int)thread_args->index < 0)
 
17754       || ((
unsigned)thread_args->index
 
17755           >= (
unsigned)ctx->cfg_worker_threads)) {
 
17757                      "Internal error: Invalid worker index %i",
 
17758                      (
int)thread_args->index);
 
17761   conn = ctx->worker_connections + thread_args->index;
 
17766   conn->buf = (
char *)
mg_malloc_ctx(ctx->max_request_size, conn->phys_ctx);
 
17767   if (conn->buf == NULL) {
 
17769                      "Out of memory: Cannot allocate buffer for worker %i",
 
17770                      (
int)thread_args->index);
 
17773   conn->buf_size = (
int)ctx->max_request_size;
 
17775   conn->phys_ctx = ctx;
 
17776   conn->dom_ctx = &(ctx->dd); 
 
17779   conn->thread_index = thread_args->index;
 
17780   conn->request_info.user_data = ctx->user_data;
 
17790#if defined(USE_SERVER_STATS) 
17791   conn->conn_state = 1; 
 
17794#if defined(ALTERNATIVE_QUEUE) 
17795   while ((ctx->stop_flag == 0)
 
17801   while (
consume_socket(ctx, &conn->client, conn->thread_index)) {
 
17804      conn->conn_birth_time = time(NULL);
 
17810#if defined(USE_IPV6) 
17811      if (conn->client.rsa.sa.sa_family == AF_INET6) {
 
17812         conn->request_info.remote_port =
 
17813             ntohs(conn->client.rsa.sin6.sin6_port);
 
17817         conn->request_info.remote_port =
 
17818             ntohs(conn->client.rsa.sin.sin_port);
 
17822                         sizeof(conn->request_info.remote_addr),
 
17823                         &conn->client.rsa);
 
17825      DEBUG_TRACE(
"Start processing connection from %s",
 
17826                  conn->request_info.remote_addr);
 
17828      conn->request_info.is_ssl = conn->client.is_ssl;
 
17830      if (conn->client.is_ssl) {
 
17831#if !defined(NO_SSL) 
17834                    conn->dom_ctx->ssl_ctx,
 
17836                    &(conn->phys_ctx->stop_flag),
 
17847            if (conn->request_info.client_cert) {
 
17848               mg_free((
void *)(conn->request_info.client_cert->subject));
 
17849               mg_free((
void *)(conn->request_info.client_cert->issuer));
 
17850               mg_free((
void *)(conn->request_info.client_cert->serial));
 
17851               mg_free((
void *)(conn->request_info.client_cert->finger));
 
17854                   (
X509 *)conn->request_info.client_cert->peer_cert);
 
17855               conn->request_info.client_cert->peer_cert = 0;
 
17856               conn->request_info.client_cert->subject = 0;
 
17857               conn->request_info.client_cert->issuer = 0;
 
17858               conn->request_info.client_cert->serial = 0;
 
17859               conn->request_info.client_cert->finger = 0;
 
17860               mg_free(conn->request_info.client_cert);
 
17861               conn->request_info.client_cert = 0;
 
17877   pthread_setspecific(
sTlsKey, NULL);
 
17879   CloseHandle(tls.pthread_cond_helper_mutex);
 
17881   pthread_mutex_destroy(&conn->mutex);
 
17884   conn->buf_size = 0;
 
17888#if defined(USE_SERVER_STATS) 
17889   conn->conn_state = 9; 
 
17899static unsigned __stdcall 
worker_thread(
void *thread_func_param)
 
17901   struct worker_thread_args *pwta =
 
17902       (
struct worker_thread_args *)thread_func_param;
 
17911   struct worker_thread_args *pwta =
 
17912       (
struct worker_thread_args *)thread_func_param;
 
17913   struct sigaction sa;
 
17916   memset(&sa, 0, 
sizeof(sa));
 
17917   sa.sa_handler = SIG_IGN;
 
17918   sigaction(SIGPIPE, &sa, NULL);
 
17934   socklen_t len = 
sizeof(so.rsa);
 
17937   if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
 
17939   } 
else if (!
check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
 
17942                      "%s: %s is not allowed to connect",
 
17950      so.is_ssl = listener->is_ssl;
 
17951      so.ssl_redir = listener->ssl_redir;
 
17952      if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
 
17954                         "%s: getsockname() failed: %s",
 
17966      if (setsockopt(so.sock,
 
17974             "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
 
17991                "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
 
18015   struct mg_context *ctx = (
struct mg_context *)thread_func_param;
 
18016   struct mg_workerTLS tls;
 
18017   struct pollfd *pfd;
 
18019   unsigned int workerthreadcount;
 
18029   SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
 
18030#elif defined(USE_MASTER_THREAD_PRIORITY) 
18031   int min_prio = sched_get_priority_min(SCHED_RR);
 
18032   int max_prio = sched_get_priority_max(SCHED_RR);
 
18033   if ((min_prio >= 0) && (max_prio >= 0)
 
18034       && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
 
18035       && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
 
18036      struct sched_param sched_param = {0};
 
18037      sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
 
18038      pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
 
18044   tls.pthread_cond_helper_mutex = CreateEvent(NULL, 
FALSE, 
FALSE, NULL);
 
18047   pthread_setspecific(
sTlsKey, &tls);
 
18049   if (ctx->callbacks.init_thread) {
 
18051      ctx->callbacks.init_thread(ctx, 0);
 
18055   ctx->start_time = time(NULL);
 
18058   pfd = ctx->listening_socket_fds;
 
18059   while (ctx->stop_flag == 0) {
 
18060      for (i = 0; i < ctx->num_listening_sockets; i++) {
 
18061         pfd[i].fd = ctx->listening_sockets[i].sock;
 
18062         pfd[i].events = POLLIN;
 
18065      if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
 
18066         for (i = 0; i < ctx->num_listening_sockets; i++) {
 
18072            if ((ctx->stop_flag == 0) && (pfd[i].revents & POLLIN)) {
 
18086   (
void)pthread_mutex_lock(&ctx->thread_mutex);
 
18087#if defined(ALTERNATIVE_QUEUE) 
18088   for (i = 0; i < ctx->cfg_worker_threads; i++) {
 
18092      if (ctx->client_socks[i].in_use) {
 
18097   pthread_cond_broadcast(&ctx->sq_full);
 
18099   (
void)pthread_mutex_unlock(&ctx->thread_mutex);
 
18102   workerthreadcount = ctx->cfg_worker_threads;
 
18103   for (i = 0; i < workerthreadcount; i++) {
 
18104      if (ctx->worker_threadids[i] != 0) {
 
18109#if defined(USE_LUA) 
18111   if (ctx->lua_background_state) {
 
18112      lua_State *lstate = (lua_State *)ctx->lua_background_state;
 
18113      lua_getglobal(lstate, LUABACKGROUNDPARAMS);
 
18114      if (lua_istable(lstate, -1)) {
 
18115         reg_boolean(lstate, 
"shutdown", 1);
 
18116         lua_pop(lstate, 1);
 
18120      ctx->lua_background_state = 0;
 
18127   CloseHandle(tls.pthread_cond_helper_mutex);
 
18129   pthread_setspecific(
sTlsKey, NULL);
 
18134   ctx->stop_flag = 2;
 
18140static unsigned __stdcall 
master_thread(
void *thread_func_param)
 
18149   struct sigaction sa;
 
18152   memset(&sa, 0, 
sizeof(sa));
 
18153   sa.sa_handler = SIG_IGN;
 
18154   sigaction(SIGPIPE, &sa, NULL);
 
18166   struct mg_handler_info *tmp_rh;
 
18172   if (ctx->callbacks.exit_context) {
 
18173      ctx->callbacks.exit_context(ctx);
 
18179   (
void)pthread_mutex_destroy(&ctx->thread_mutex);
 
18180#if defined(ALTERNATIVE_QUEUE) 
18182   for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
 
18185   mg_free(ctx->client_wait_events);
 
18187   (
void)pthread_cond_destroy(&ctx->sq_empty);
 
18188   (
void)pthread_cond_destroy(&ctx->sq_full);
 
18192   (
void)pthread_mutex_destroy(&ctx->nonce_mutex);
 
18194#if defined(USE_TIMERS) 
18200      if (ctx->dd.config[i] != NULL) {
 
18201#if defined(_MSC_VER) 
18202#pragma warning(suppress : 6001) 
18209   while (ctx->dd.handlers) {
 
18210      tmp_rh = ctx->dd.handlers;
 
18211      ctx->dd.handlers = tmp_rh->next;
 
18213         pthread_cond_destroy(&tmp_rh->refcount_cond);
 
18214         pthread_mutex_destroy(&tmp_rh->refcount_mutex);
 
18220#if !defined(NO_SSL) 
18222   if (ctx->dd.ssl_ctx != NULL) {
 
18223      void *ssl_ctx = (
void *)ctx->dd.ssl_ctx;
 
18225          (ctx->callbacks.external_ssl_ctx == NULL)
 
18227              : (ctx->callbacks.external_ssl_ctx(&ssl_ctx, ctx->user_data));
 
18229      if (callback_ret == 0) {
 
18238   if (ctx->worker_threadids != NULL) {
 
18239      mg_free(ctx->worker_threadids);
 
18243   if (ctx->worker_connections != NULL) {
 
18244      mg_free(ctx->worker_connections);
 
18265   mt = ctx->masterthreadid;
 
18270   ctx->masterthreadid = 0;
 
18273   ctx->stop_flag = 1;
 
18276   while (ctx->stop_flag != 2) {
 
18284   (
void)WSACleanup();
 
18293#if !defined(__SYMBIAN32__) 
18294#if defined(_WIN32_WCE) 
18298   DWORD dwVersion = 0;
 
18299   DWORD dwMajorVersion = 0;
 
18300   DWORD dwMinorVersion = 0;
 
18302   BOOL wowRet, isWoW = 
FALSE;
 
18304#if defined(_MSC_VER) 
18305#pragma warning(push) 
18307#pragma warning(disable : 4996) 
18309   dwVersion = GetVersion();
 
18310#if defined(_MSC_VER) 
18311#pragma warning(pop) 
18314   dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
 
18315   dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
 
18316   dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
 
18319   wowRet = IsWow64Process(GetCurrentProcess(), &isWoW);
 
18323           (
unsigned)dwMajorVersion,
 
18324           (
unsigned)dwMinorVersion,
 
18325           (wowRet ? (isWoW ? 
" (WoW64)" : 
"") : 
" (?)"));
 
18333   struct utsname 
name;
 
18344         const char **options)
 
18346   struct mg_context *ctx;
 
18347   const char *
name, *value, *default_value;
 
18348   int idx, ok, workerthreadcount;
 
18351   void (*exit_callback)(
const struct mg_context *ctx) = 0;
 
18353   struct mg_workerTLS tls;
 
18357   WSAStartup(MAKEWORD(2, 2), &data);
 
18361   if ((ctx = (
struct mg_context *)
mg_calloc(1, 
sizeof(*ctx))) == NULL) {
 
18366   ctx->dd.auth_nonce_mask =
 
18367       (uint64_t)
get_random() ^ (uint64_t)(ptrdiff_t)(options);
 
18372      const char *ports_option =
 
18376         const char **run_options = options;
 
18380         while (*run_options) {
 
18381            if (!strcmp(*run_options, optname)) {
 
18382               ports_option = run_options[1];
 
18397   tls.is_master = -1;
 
18400   tls.pthread_cond_helper_mutex = NULL;
 
18402   pthread_setspecific(
sTlsKey, &tls);
 
18405#if !defined(ALTERNATIVE_QUEUE) 
18406   ok &= (0 == pthread_cond_init(&ctx->sq_empty, NULL));
 
18407   ok &= (0 == pthread_cond_init(&ctx->sq_full, NULL));
 
18415                      "Cannot initialize thread synchronization objects");
 
18417      pthread_setspecific(
sTlsKey, NULL);
 
18422      ctx->callbacks = *callbacks;
 
18424      ctx->callbacks.exit_context = 0;
 
18426   ctx->user_data = user_data;
 
18427   ctx->dd.handlers = NULL;
 
18428   ctx->dd.next = NULL;
 
18430#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
18431   ctx->dd.shared_lua_websockets = NULL;
 
18435   while (options && (
name = *options++) != NULL) {
 
18439         pthread_setspecific(
sTlsKey, NULL);
 
18441      } 
else if ((value = *options++) == NULL) {
 
18444         pthread_setspecific(
sTlsKey, NULL);
 
18447      if (ctx->dd.config[idx] != NULL) {
 
18449         mg_free(ctx->dd.config[idx]);
 
18458      if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) {
 
18468      pthread_setspecific(
sTlsKey, NULL);
 
18471   ctx->max_request_size = (unsigned)itmp;
 
18474   workerthreadcount = atoi(ctx->dd.config[
NUM_THREADS]);
 
18479      pthread_setspecific(
sTlsKey, NULL);
 
18483   if (workerthreadcount <= 0) {
 
18486      pthread_setspecific(
sTlsKey, NULL);
 
18491#if defined(NO_FILES) 
18495      pthread_setspecific(
sTlsKey, NULL);
 
18502#if defined(USE_LUA) 
18504   if (ctx->dd.config[LUA_BACKGROUND_SCRIPT] != NULL) {
 
18506      struct vec opt_vec;
 
18508      const char *sparams;
 
18509      lua_State *state = mg_prepare_lua_context_script(
 
18510          ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, 
sizeof(ebuf));
 
18514         pthread_setspecific(
sTlsKey, NULL);
 
18517      ctx->lua_background_state = (
void *)state;
 
18519      lua_newtable(state);
 
18520      reg_boolean(state, 
"shutdown", 0);
 
18522      sparams = ctx->dd.config[LUA_BACKGROUND_SCRIPT_PARAMS];
 
18524      while ((sparams = 
next_option(sparams, &opt_vec, &eq_vec)) != NULL) {
 
18526             state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len);
 
18530      lua_setglobal(state, LUABACKGROUNDPARAMS);
 
18533      ctx->lua_background_state = 0;
 
18540#
if !defined(NO_SSL)
 
18544#
if !defined(_WIN32)
 
18549      pthread_setspecific(
sTlsKey, NULL);
 
18553   ctx->cfg_worker_threads = ((
unsigned int)(workerthreadcount));
 
18554   ctx->worker_threadids = (pthread_t *)
mg_calloc_ctx(ctx->cfg_worker_threads,
 
18558   if (ctx->worker_threadids == NULL) {
 
18561                      "Not enough memory for worker thread ID array");
 
18563      pthread_setspecific(
sTlsKey, NULL);
 
18566   ctx->worker_connections =
 
18567       (
struct mg_connection *)
mg_calloc_ctx(ctx->cfg_worker_threads,
 
18568                                             sizeof(
struct mg_connection),
 
18570   if (ctx->worker_connections == NULL) {
 
18573                      "Not enough memory for worker thread connection array");
 
18575      pthread_setspecific(
sTlsKey, NULL);
 
18580#if defined(ALTERNATIVE_QUEUE) 
18581   ctx->client_wait_events =
 
18583                              ctx->cfg_worker_threads,
 
18585   if (ctx->client_wait_events == NULL) {
 
18588                      "Not enough memory for worker event array");
 
18589      mg_free(ctx->worker_threadids);
 
18591      pthread_setspecific(
sTlsKey, NULL);
 
18595   ctx->client_socks =
 
18596       (
struct socket *)
mg_calloc_ctx(
sizeof(ctx->client_socks[0]),
 
18597                                      ctx->cfg_worker_threads,
 
18599   if (ctx->client_socks == NULL) {
 
18602                      "Not enough memory for worker socket array");
 
18603      mg_free(ctx->client_wait_events);
 
18604      mg_free(ctx->worker_threadids);
 
18606      pthread_setspecific(
sTlsKey, NULL);
 
18610   for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
 
18612      if (ctx->client_wait_events[i] == 0) {
 
18619         mg_free(ctx->client_wait_events);
 
18620         mg_free(ctx->worker_threadids);
 
18622         pthread_setspecific(
sTlsKey, NULL);
 
18629#if defined(USE_TIMERS) 
18630   if (timers_init(ctx) != 0) {
 
18633      pthread_setspecific(
sTlsKey, NULL);
 
18639   if (ctx->callbacks.init_context) {
 
18640      ctx->callbacks.init_context(ctx);
 
18642   ctx->callbacks.exit_context = exit_callback;
 
18649   for (i = 0; i < ctx->cfg_worker_threads; i++) {
 
18650      struct worker_thread_args *wta = (
struct worker_thread_args *)
 
18654         wta->index = (
int)i;
 
18660                                      &ctx->worker_threadids[i])
 
18670                            "Cannot start worker thread %i: error %ld",
 
18675                            "Cannot create threads: error %ld",
 
18678            pthread_setspecific(
sTlsKey, NULL);
 
18685   pthread_setspecific(
sTlsKey, NULL);
 
18690#if defined(MG_EXPERIMENTAL_INTERFACES) 
18693mg_start_domain(
struct mg_context *ctx, 
const char **options)
 
18697   const char *default_value;
 
18698   struct mg_domain_context *new_dom;
 
18699   struct mg_domain_context *dom;
 
18702   if ((ctx == NULL) || (ctx->stop_flag != 0) || (options == NULL)) {
 
18706   new_dom = (
struct mg_domain_context *)
 
18715   while (options && (
name = *options++) != NULL) {
 
18720      } 
else if ((value = *options++) == NULL) {
 
18725      if (new_dom->config[idx] != NULL) {
 
18727         mg_free(new_dom->config[idx]);
 
18744      default_value = ctx->dd.config[i];
 
18745      if ((new_dom->config[i] == NULL) && (default_value != NULL)) {
 
18750   new_dom->handlers = NULL;
 
18751   new_dom->next = NULL;
 
18752   new_dom->nonce_count = 0;
 
18753   new_dom->auth_nonce_mask =
 
18756#if defined(USE_LUA) && defined(USE_WEBSOCKET) 
18757   new_dom->shared_lua_websockets = NULL;
 
18776                         "domain %s already in use",
 
18785      if (dom->next == NULL) {
 
18786         dom->next = new_dom;
 
18804   static const unsigned feature_set = 0
 
18808#if !defined(NO_FILES) 
18811#if !defined(NO_SSL) 
18814#if !defined(NO_CGI) 
18817#if defined(USE_IPV6) 
18820#if defined(USE_WEBSOCKET) 
18823#if defined(USE_LUA) 
18826#if defined(USE_DUKTAPE) 
18829#if !defined(NO_CACHING) 
18832#if defined(USE_SERVER_STATS) 
18835#if defined(USE_ZLIB) 
18841#if defined(MG_LEGACY_INTERFACE) 
18844#if defined(MG_EXPERIMENTAL_INTERFACES) 
18847#if defined(MEMORY_DEBUGGING) 
18850#if defined(USE_TIMERS) 
18853#if !defined(NO_NONCE_CHECK) 
18856#if !defined(NO_POPEN) 
18860   return (feature & feature_set);
 
18865#define strcat0(a, b)                                                          \ 
18867      if ((a != NULL) && (b != NULL)) {                                      \ 
18879   int system_info_length = 0;
 
18882   const char *eol = 
"\r\n";
 
18884   const char *eol = 
"\n";
 
18887   const char *eoobj = 
"}";
 
18888   int reserved_len = (
int)strlen(eoobj) + (
int)strlen(eol);
 
18890   if ((buffer == NULL) || (buflen < 1)) {
 
18896   mg_snprintf(NULL, NULL, block, 
sizeof(block), 
"{%s", eol);
 
18897   system_info_length += (
int)strlen(block);
 
18898   if (system_info_length < buflen) {
 
18909                  "\"version\" : \"%s\",%s",
 
18912      system_info_length += (
int)strlen(block);
 
18913      if (system_info_length < buflen) {
 
18921      DWORD dwVersion = 0;
 
18922      DWORD dwMajorVersion = 0;
 
18923      DWORD dwMinorVersion = 0;
 
18926      GetSystemInfo(&si);
 
18928#if defined(_MSC_VER) 
18929#pragma warning(push) 
18931#pragma warning(disable : 4996) 
18933      dwVersion = GetVersion();
 
18934#if defined(_MSC_VER) 
18935#pragma warning(pop) 
18938      dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
 
18939      dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
 
18945                  "\"os\" : \"Windows %u.%u\",%s",
 
18946                  (
unsigned)dwMajorVersion,
 
18947                  (
unsigned)dwMinorVersion,
 
18949      system_info_length += (
int)strlen(block);
 
18950      if (system_info_length < buflen) {
 
18958                  "\"cpu\" : \"type %u, cores %u, mask %x\",%s",
 
18959                  (
unsigned)si.wProcessorArchitecture,
 
18960                  (
unsigned)si.dwNumberOfProcessors,
 
18961                  (
unsigned)si.dwActiveProcessorMask,
 
18963      system_info_length += (
int)strlen(block);
 
18964      if (system_info_length < buflen) {
 
18968      struct utsname 
name;
 
18976                  "\"os\" : \"%s %s (%s) - %s\",%s",
 
18982      system_info_length += (
int)strlen(block);
 
18983      if (system_info_length < buflen) {
 
18995                  "\"features\" : %lu,%s" 
18996                  "\"feature_list\" : \"Server:%s%s%s%s%s%s%s%s%s\",%s",
 
19010      system_info_length += (
int)strlen(block);
 
19011      if (system_info_length < buflen) {
 
19015#if defined(USE_LUA) 
19020                  "\"lua_version\" : \"%u (%s)\",%s",
 
19021                  (
unsigned)LUA_VERSION_NUM,
 
19024      system_info_length += (
int)strlen(block);
 
19025      if (system_info_length < buflen) {
 
19029#if defined(USE_DUKTAPE) 
19034                  "\"javascript\" : \"Duktape %u.%u.%u\",%s",
 
19035                  (
unsigned)DUK_VERSION / 10000,
 
19036                  ((
unsigned)DUK_VERSION / 100) % 100,
 
19037                  (
unsigned)DUK_VERSION % 100,
 
19039      system_info_length += (
int)strlen(block);
 
19040      if (system_info_length < buflen) {
 
19048#if defined(GCC_DIAGNOSTIC) 
19049#if GCC_VERSION >= 50000 
19050#pragma GCC diagnostic push 
19052#pragma GCC diagnostic ignored "-Wdate-time" 
19059                  "\"build\" : \"%s\",%s",
 
19063#if defined(GCC_DIAGNOSTIC) 
19064#if GCC_VERSION >= 50000 
19065#pragma GCC diagnostic pop 
19069      system_info_length += (
int)strlen(block);
 
19070      if (system_info_length < buflen) {
 
19079#if defined(_MSC_VER) 
19084                  "\"compiler\" : \"MSC: %u (%u)\",%s",
 
19085                  (
unsigned)_MSC_VER,
 
19086                  (
unsigned)_MSC_FULL_VER,
 
19088      system_info_length += (
int)strlen(block);
 
19089      if (system_info_length < buflen) {
 
19092#elif defined(__MINGW64__) 
19097                  "\"compiler\" : \"MinGW64: %u.%u\",%s",
 
19098                  (
unsigned)__MINGW64_VERSION_MAJOR,
 
19099                  (
unsigned)__MINGW64_VERSION_MINOR,
 
19101      system_info_length += (
int)strlen(block);
 
19102      if (system_info_length < buflen) {
 
19109                  "\"compiler\" : \"MinGW32: %u.%u\",%s",
 
19110                  (
unsigned)__MINGW32_MAJOR_VERSION,
 
19111                  (
unsigned)__MINGW32_MINOR_VERSION,
 
19113      system_info_length += (
int)strlen(block);
 
19114      if (system_info_length < buflen) {
 
19117#elif defined(__MINGW32__) 
19122                  "\"compiler\" : \"MinGW32: %u.%u\",%s",
 
19123                  (
unsigned)__MINGW32_MAJOR_VERSION,
 
19124                  (
unsigned)__MINGW32_MINOR_VERSION,
 
19126      system_info_length += (
int)strlen(block);
 
19127      if (system_info_length < buflen) {
 
19130#elif defined(__clang__) 
19135                  "\"compiler\" : \"clang: %u.%u.%u (%s)\",%s",
 
19138                  __clang_patchlevel__,
 
19141      system_info_length += (
int)strlen(block);
 
19142      if (system_info_length < buflen) {
 
19145#elif defined(__GNUC__) 
19150                  "\"compiler\" : \"gcc: %u.%u.%u\",%s",
 
19151                  (
unsigned)__GNUC__,
 
19152                  (
unsigned)__GNUC_MINOR__,
 
19153                  (
unsigned)__GNUC_PATCHLEVEL__,
 
19155      system_info_length += (
int)strlen(block);
 
19156      if (system_info_length < buflen) {
 
19159#elif defined(__INTEL_COMPILER) 
19164                  "\"compiler\" : \"Intel C/C++: %u\",%s",
 
19165                  (
unsigned)__INTEL_COMPILER,
 
19167      system_info_length += (
int)strlen(block);
 
19168      if (system_info_length < buflen) {
 
19171#elif defined(__BORLANDC__) 
19176                  "\"compiler\" : \"Borland C: 0x%x\",%s",
 
19177                  (
unsigned)__BORLANDC__,
 
19179      system_info_length += (
int)strlen(block);
 
19180      if (system_info_length < buflen) {
 
19183#elif defined(__SUNPRO_C) 
19188                  "\"compiler\" : \"Solaris: 0x%x\",%s",
 
19189                  (
unsigned)__SUNPRO_C,
 
19191      system_info_length += (
int)strlen(block);
 
19192      if (system_info_length < buflen) {
 
19200                  "\"compiler\" : \"other\",%s",
 
19202      system_info_length += (
int)strlen(block);
 
19203      if (system_info_length < buflen) {
 
19216                  "\"data_model\" : \"int:%u/%u/%u/%u, float:%u/%u/%u, " 
19218                  "ptr:%u, size:%u, time:%u\"%s",
 
19219                  (
unsigned)
sizeof(
short),
 
19220                  (
unsigned)
sizeof(
int),
 
19221                  (
unsigned)
sizeof(
long),
 
19222                  (
unsigned)
sizeof(
long long),
 
19223                  (
unsigned)
sizeof(
float),
 
19224                  (
unsigned)
sizeof(
double),
 
19225                  (
unsigned)
sizeof(
long double),
 
19226                  (
unsigned)
sizeof(
char),
 
19227                  (
unsigned)
sizeof(
wchar_t),
 
19228                  (
unsigned)
sizeof(
void *),
 
19229                  (
unsigned)
sizeof(
size_t),
 
19230                  (
unsigned)
sizeof(time_t),
 
19232      system_info_length += (
int)strlen(block);
 
19233      if (system_info_length < buflen) {
 
19239   if ((buflen > 0) && buffer && buffer[0]) {
 
19240      if (system_info_length < buflen) {
 
19245   system_info_length += reserved_len;
 
19247   return system_info_length;
 
19251#if defined(USE_SERVER_STATS) 
19255mg_get_context_info_impl(
const struct mg_context *ctx, 
char *buffer, 
int buflen)
 
19259   int context_info_length = 0;
 
19262   const char *eol = 
"\r\n";
 
19264   const char *eol = 
"\n";
 
19266   struct mg_memory_stat *ms = get_memory_stat((
struct mg_context *)ctx);
 
19268   const char *eoobj = 
"}";
 
19269   int reserved_len = (
int)strlen(eoobj) + (
int)strlen(eol);
 
19271   if ((buffer == NULL) || (buflen < 1)) {
 
19277   mg_snprintf(NULL, NULL, block, 
sizeof(block), 
"{%s", eol);
 
19278   context_info_length += (
int)strlen(block);
 
19279   if (context_info_length < buflen) {
 
19290                  "\"blocks\" : %i,%s" 
19304      context_info_length += (
int)strlen(block);
 
19305      if (context_info_length + reserved_len < buflen) {
 
19313      char start_time_str[64] = {0};
 
19314      char now_str[64] = {0};
 
19315      time_t start_time = ctx->start_time;
 
19316      time_t now = time(NULL);
 
19323                  "\"connections\" : {%s" 
19324                  "\"active\" : %i,%s" 
19325                  "\"maxActive\" : %i,%s" 
19329                  ctx->active_connections,
 
19331                  ctx->max_connections,
 
19333                  ctx->total_connections,
 
19337      context_info_length += (
int)strlen(block);
 
19338      if (context_info_length + reserved_len < buflen) {
 
19347                  "\"requests\" : {%s" 
19351                  ctx->total_requests,
 
19355      context_info_length += (
int)strlen(block);
 
19356      if (context_info_length + reserved_len < buflen) {
 
19370                  ctx->total_data_read,
 
19372                  ctx->total_data_written,
 
19376      context_info_length += (
int)strlen(block);
 
19377      if (context_info_length + reserved_len < buflen) {
 
19383                      sizeof(start_time_str) - 1,
 
19392                  "\"uptime\" : %.0f,%s" 
19393                  "\"start\" : \"%s\",%s" 
19394                  "\"now\" : \"%s\"%s" 
19397                  difftime(now, start_time),
 
19405      context_info_length += (
int)strlen(block);
 
19406      if (context_info_length + reserved_len < buflen) {
 
19412   if ((buflen > 0) && buffer && buffer[0]) {
 
19413      if (context_info_length < buflen) {
 
19418   context_info_length += reserved_len;
 
19420   return context_info_length;
 
19425#if defined(MG_EXPERIMENTAL_INTERFACES) 
19429mg_get_connection_info_impl(
const struct mg_context *ctx,
 
19434   const struct mg_connection *conn;
 
19437   int connection_info_length = 0;
 
19439   const char *state_str = 
"unknown";
 
19442   const char *eol = 
"\r\n";
 
19444   const char *eol = 
"\n";
 
19447   const char *eoobj = 
"}";
 
19448   int reserved_len = (
int)strlen(eoobj) + (
int)strlen(eol);
 
19450   if ((buffer == NULL) || (buflen < 1)) {
 
19456   if ((ctx == NULL) || (idx < 0)) {
 
19461   if ((
unsigned)idx >= ctx->cfg_worker_threads) {
 
19468   conn = (ctx->worker_connections) + idx;
 
19471   mg_snprintf(NULL, NULL, block, 
sizeof(block), 
"{%s", eol);
 
19472   connection_info_length += (
int)strlen(block);
 
19473   if (connection_info_length < buflen) {
 
19478   ri = &(conn->request_info);
 
19480#if defined(USE_SERVER_STATS) 
19481   state = conn->conn_state;
 
19486      state_str = 
"undefined";
 
19489      state_str = 
"not used";
 
19492      state_str = 
"init";
 
19495      state_str = 
"ready";
 
19498      state_str = 
"processing";
 
19501      state_str = 
"processed";
 
19504      state_str = 
"to close";
 
19507      state_str = 
"closing";
 
19510      state_str = 
"closed";
 
19513      state_str = 
"done";
 
19519   if ((state >= 3) && (state < 9)) {
 
19524                  "\"connection\" : {%s" 
19526                  "\"protocol\" : \"%s\",%s" 
19527                  "\"addr\" : \"%s\",%s" 
19530                  "\"handled_requests\" : %u%s" 
19541                  conn->handled_requests,
 
19545      connection_info_length += (
int)strlen(block);
 
19546      if (connection_info_length + reserved_len < buflen) {
 
19552   if ((state >= 4) && (state < 6)) {
 
19557                  "\"request_info\" : {%s" 
19558                  "\"method\" : \"%s\",%s" 
19559                  "\"uri\" : \"%s\",%s" 
19560                  "\"query\" : %s%s%s%s" 
19573      connection_info_length += (
int)strlen(block);
 
19574      if (connection_info_length + reserved_len < buflen) {
 
19580   if ((state >= 2) && (state < 9)) {
 
19581      char start_time_str[64] = {0};
 
19582      char now_str[64] = {0};
 
19583      time_t start_time = conn->conn_birth_time;
 
19584      time_t now = time(NULL);
 
19587                      sizeof(start_time_str) - 1,
 
19596                  "\"uptime\" : %.0f,%s" 
19597                  "\"start\" : \"%s\",%s" 
19598                  "\"now\" : \"%s\"%s" 
19601                  difftime(now, start_time),
 
19609      connection_info_length += (
int)strlen(block);
 
19610      if (connection_info_length + reserved_len < buflen) {
 
19622                  "\"name\" : \"%s\",%s" 
19629      connection_info_length += (
int)strlen(block);
 
19630      if (connection_info_length + reserved_len < buflen) {
 
19646                  conn->consumed_content,
 
19648                  conn->num_bytes_sent,
 
19652      connection_info_length += (
int)strlen(block);
 
19653      if (connection_info_length + reserved_len < buflen) {
 
19663               "\"state\" : \"%s\"%s",
 
19667   connection_info_length += (
int)strlen(block);
 
19668   if (connection_info_length + reserved_len < buflen) {
 
19673   if ((buflen > 0) && buffer && buffer[0]) {
 
19674      if (connection_info_length < buflen) {
 
19679   connection_info_length += reserved_len;
 
19681   return connection_info_length;
 
19691   if ((buffer == NULL) || (buflen < 1)) {
 
19706#if defined(USE_SERVER_STATS) 
19707   if ((buffer == NULL) || (buflen < 1)) {
 
19708      return mg_get_context_info_impl(ctx, NULL, 0);
 
19712      return mg_get_context_info_impl(ctx, buffer, buflen);
 
19716   if ((buffer != NULL) && (buflen > 0)) {
 
19724#if defined(MG_EXPERIMENTAL_INTERFACES) 
19726mg_get_connection_info(
const struct mg_context *ctx,
 
19731   if ((buffer == NULL) || (buflen < 1)) {
 
19732      return mg_get_connection_info_impl(ctx, idx, NULL, 0);
 
19736      return mg_get_connection_info_impl(ctx, idx, buffer, buflen);
 
19747#if !defined(NO_SSL) 
19752   unsigned features_inited = features_to_init;
 
19772      InitializeCriticalSection(&global_log_file_lock);
 
19774#if !defined(_WIN32) 
19779#if defined(USE_LUA) 
19780      lua_init_optional_libraries();
 
19786#if !defined(NO_SSL) 
19793            DEBUG_TRACE(
"Initializing SSL failed: %s", ebuf);
 
19807      WSAStartup(MAKEWORD(2, 2), &data);
 
19815   return features_inited;
 
19832      (
void)WSACleanup();
 
19834#if !defined(NO_SSL) 
19842      (
void)DeleteCriticalSection(&global_log_file_lock);
 
19844#if !defined(_WIN32) 
19850#if defined(USE_LUA) 
19851      lua_exit_optional_libraries();
 
static const double x2[5]
 
static const double x1[5]
 
static unsigned int total
 
#define INVALID_HANDLE_VALUE
 
R__EXTERN C unsigned int sleep(unsigned int seconds)
 
typedef void((*Func_t)())
 
static void process_new_connection(struct mg_connection *conn)
 
static int set_tcp_nodelay(SOCKET sock, int nodelay_on)
 
#define SSL_CTX_use_certificate_file
 
static int is_authorized_for_put(struct mg_connection *conn)
 
static int consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
 
static int parse_http_request(char *buf, int len, struct mg_request_info *ri)
 
void mg_send_mime_file2(struct mg_connection *conn, const char *path, const char *mime_type, const char *additional_headers)
 
static pthread_key_t sTlsKey
 
static void sockaddr_to_string(char *buf, size_t len, const union usa *usa)
 
static void open_auth_file(struct mg_connection *conn, const char *path, struct mg_file *filep)
 
char static_assert_replacement[1]
 
int mg_strncasecmp(const char *s1, const char *s2, size_t len)
 
#define SSL_CTX_check_private_key
 
static const struct @139 abs_uri_protocols[]
 
static int check_authorization(struct mg_connection *conn, const char *path)
 
#define mg_malloc_ctx(a, c)
 
static int mg_fgetc(struct mg_file *filep, int offset)
 
struct asn1_integer ASN1_INTEGER
 
#define X509_NAME_oneline
 
static char mg_getc(struct mg_connection *conn)
 
static int mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
 
void mg_unlock_connection(struct mg_connection *conn)
 
static void mkcol(struct mg_connection *conn, const char *path)
 
static void remove_bad_file(const struct mg_connection *conn, const char *path)
 
const struct mg_option * mg_get_valid_options(void)
 
#define SSL_set_tlsext_host_name(ctx, arg)
 
int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server_ports *ports)
 
static int set_non_blocking_mode(SOCKET sock)
 
static void ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
 
int mg_send_http_error(struct mg_connection *conn, int status, const char *fmt,...)
 
static const char * get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
 
static void mg_cry_internal_impl(const struct mg_connection *conn, const char *func, unsigned line, const char *fmt, va_list ap)
 
void mg_lock_context(struct mg_context *ctx)
 
#define SSL_OP_CIPHER_SERVER_PREFERENCE
 
#define MAX_WORKER_THREADS
 
static int send_additional_header(struct mg_connection *conn)
 
#define SSL_load_error_strings
 
static void put_file(struct mg_connection *conn, const char *path)
 
struct ssl_ctx_st SSL_CTX
 
static void do_ssi_exec(struct mg_connection *conn, char *tag)
 
static void tls_dtor(void *key)
 
static void mg_strlcpy(register char *dst, register const char *src, size_t n)
 
const void * SOCK_OPT_TYPE
 
static int header_has_option(const char *header, const char *option)
 
int mg_send_http_redirect(struct mg_connection *conn, const char *target_url, int redirect_code)
 
int mg_get_cookie(const char *cookie_header, const char *var_name, char *dst, size_t dst_size)
 
#define SSL_set_app_data(s, arg)
 
#define SSL_get_peer_certificate
 
#define mg_opendir(conn, x)
 
static FUNCTION_MAY_BE_UNUSED uint64_t mg_get_current_time_ns(void)
 
static char * mg_strndup_ctx(const char *ptr, size_t len, struct mg_context *ctx)
 
#define is_websocket_protocol(conn)
 
static int put_dir(struct mg_connection *conn, const char *path)
 
static void * realloc2(void *ptr, size_t size)
 
#define SSL_OP_SINGLE_DH_USE
 
static int print_dav_dir_entry(struct de *de, void *data)
 
static void delete_file(struct mg_connection *conn, const char *path)
 
static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
 
#define mg_calloc_ctx(a, b, c)
 
static FUNCTION_MAY_BE_UNUSED int mg_atomic_inc(volatile int *addr)
 
int mg_printf(struct mg_connection *conn, const char *fmt,...)
 
static int WINCDECL compare_dir_entries(const void *p1, const void *p2)
 
static int should_keep_alive(const struct mg_connection *conn)
 
static __inline void * mg_malloc(size_t a)
 
#define SSL_get_app_data(s)
 
static int mg_fopen(const struct mg_connection *conn, const char *path, int mode, struct mg_file *filep)
 
#define OPENSSL_REMOVE_THREAD_STATE()
 
static int send_no_cache_header(struct mg_connection *conn)
 
static void handle_static_file_request(struct mg_connection *conn, const char *path, struct mg_file *filep, const char *mime_type, const char *additional_headers)
 
static int ssl_use_pem_file(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *pem, const char *chain)
 
static void mg_cry_internal_wrap(const struct mg_connection *conn, const char *func, unsigned line, const char *fmt,...) PRINTF_ARGS(4
 
static const char * ssl_error(void)
 
static int must_hide_file(struct mg_connection *conn, const char *path)
 
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT
 
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
 
#define CONF_modules_unload
 
#define mg_remove(conn, x)
 
int mg_send_http_ok(struct mg_connection *conn, const char *mime_type, long long content_length)
 
static void close_all_listening_sockets(struct mg_context *ctx)
 
void mg_send_file(struct mg_connection *conn, const char *path)
 
#define SSL_TLSEXT_ERR_OK
 
static void send_authorization_request(struct mg_connection *conn, const char *realm)
 
static int check_password(const char *method, const char *ha1, const char *uri, const char *nonce, const char *nc, const char *cnonce, const char *qop, const char *response)
 
#define X509_get_subject_name
 
#define SSL_TLSEXT_ERR_NOACK
 
static const struct mg_option config_options[]
 
#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS
 
static FUNCTION_MAY_BE_UNUSED unsigned long mg_current_thread_id(void)
 
static const struct mg_http_method_info * get_http_method_info(const char *method)
 
static const char * mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p)
 
const char * mg_get_response_code_text(const struct mg_connection *conn, int response_code)
 
static int get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
 
static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS])
 
static int set_uid_option(struct mg_context *phys_ctx)
 
static void remove_double_dots_and_double_slashes(char *s)
 
static void reset_per_request_attributes(struct mg_connection *conn)
 
static void handle_file_based_request(struct mg_connection *conn, const char *path, struct mg_file *filep)
 
static pid_t spawn_process(struct mg_connection *conn, const char *prog, char *envblk, char *envp[], int fdin[2], int fdout[2], int fderr[2], const char *dir)
 
#define SSL_CTX_set_ecdh_auto(ctx, onoff)
 
#define FUNCTION_MAY_BE_UNUSED
 
static pthread_mutex_t * ssl_mutexes
 
void mg_set_user_connection_data(struct mg_connection *conn, void *data)
 
#define SSLv23_client_method
 
static int get_option_index(const char *name)
 
static int abort_process(void *data)
 
static char * mg_strdup(const char *str)
 
static void addenv(struct cgi_environment *env, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
 
const struct mg_response_info * mg_get_response_info(const struct mg_connection *conn)
 
static int initialize_ssl(char *ebuf, size_t ebuf_len)
 
static __inline void * mg_realloc(void *a, size_t b)
 
static void accept_new_connection(const struct socket *listener, struct mg_context *ctx)
 
static int get_message(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
 
static pthread_mutex_t global_lock_mutex
 
#define CGI_ENVIRONMENT_SIZE
 
static long ssl_get_protocol(int version_id)
 
static int mg_init_library_called
 
long long mg_store_body(struct mg_connection *conn, const char *path)
 
struct mg_connection * mg_download(const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt,...)
 
#define DEBUG_ASSERT(cond)
 
static int pull_inner(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
 
static int mg_poll(struct pollfd *pfd, unsigned int n, int milliseconds, volatile int *stop_server)
 
int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout)
 
#define MG_FILE_COMPRESSION_SIZE_LIMIT
 
static struct mg_connection * mg_connect_client_impl(const struct mg_client_options *client_options, int use_ssl, char *ebuf, size_t ebuf_len)
 
unsigned mg_check_feature(unsigned feature)
 
static int mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
 
static int mg_send_http_error_impl(struct mg_connection *conn, int status, const char *fmt, va_list args)
 
struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options)
 
#define SSL_CTX_clear_options(ctx, op)
 
#define MG_FOPEN_MODE_READ
 
static int open_file_in_memory(const struct mg_connection *conn, const char *path, struct mg_file *filep, int mode)
 
#define SSL_OP_NO_COMPRESSION
 
static int extention_matches_script(struct mg_connection *conn, const char *filename)
 
void mg_set_websocket_handler(struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
 
static const char * alloc_get_host(struct mg_connection *conn)
 
static pthread_mutexattr_t pthread_mutex_attr
 
#define SSL_ERROR_SYSCALL
 
#define SSL_CTX_load_verify_locations
 
void mg_unlock_context(struct mg_context *ctx)
 
#define SSL_ERROR_WANT_READ
 
static int ssl_servername_callback(SSL *ssl, int *ad, void *arg)
 
int mg_modify_passwords_file(const char *fname, const char *domain, const char *user, const char *pass)
 
static char * skip_quoted(char **buf, const char *delimiters, const char *whitespace, char quotechar)
 
static void fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn)
 
int mg_start_thread(mg_thread_func_t func, void *param)
 
static void * load_dll(char *ebuf, size_t ebuf_len, const char *dll_name, struct ssl_func *sw)
 
static const char * get_header(const struct mg_header *hdr, int num_hdr, const char *name)
 
static struct mg_http_method_info http_methods[]
 
static int event_signal(void *eventhdl)
 
static int init_ssl_ctx_impl(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *pem, const char *chain)
 
static int connect_socket(struct mg_context *ctx, const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, SOCKET *sock, union usa *sa)
 
unsigned mg_init_library(unsigned features)
 
struct mg_connection * mg_connect_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size)
 
static int forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
 
static void master_thread_run(void *thread_func_param)
 
static int set_gpass_option(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
 
static int skip_to_end_of_word_and_terminate(char **ppw, int eol)
 
static int get_request(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
 
int mg_get_var(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len)
 
#define ARRAY_SIZE(array)
 
static int parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
 
static int get_first_ssl_listener_index(const struct mg_context *ctx)
 
#define SSL_CTX_use_PrivateKey_file
 
struct ssl_method_st SSL_METHOD
 
void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type)
 
const char * mg_get_header(const struct mg_connection *conn, const char *name)
 
#define mg_mkdir(conn, path, mode)
 
static uint32_t get_remote_ip(const struct mg_connection *conn)
 
static int hexdump2string(void *mem, int memlen, char *buf, int buflen)
 
static void handle_directory_request(struct mg_connection *conn, const char *dir)
 
static int set_ports_option(struct mg_context *phys_ctx)
 
static int read_auth_file(struct mg_file *filep, struct read_auth_file_struct *workdata, int depth)
 
static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr)
 
unsigned mg_exit_library(void)
 
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb)
 
static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
 
int mg_send_digest_access_authentication_request(struct mg_connection *conn, const char *realm)
 
static void print_props(struct mg_connection *conn, const char *uri, struct mg_file_stat *filep)
 
static const char * mg_strcasestr(const char *big_str, const char *small_str)
 
struct mg_connection * mg_connect_websocket_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
 
static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
 
static void handle_ssi_file_request(struct mg_connection *conn, const char *path, struct mg_file *filep)
 
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
 
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
 
static void ssl_info_callback(const SSL *ssl, int what, int ret)
 
#define ASN1_INTEGER_to_BN
 
#define SSL_ERROR_WANT_ACCEPT
 
static void bin2str(char *to, const unsigned char *p, size_t len)
 
const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn)
 
#define SSL_ERROR_WANT_X509_LOOKUP
 
#define MG_FOPEN_MODE_APPEND
 
char * mg_md5(char buf[33],...)
 
static const struct @138 builtin_mime_types[]
 
static const char * next_option(const char *list, struct vec *val, struct vec *eq_val)
 
#define SSL_CB_HANDSHAKE_START
 
static const char * suggest_connection_header(const struct mg_connection *conn)
 
static int alloc_vprintf(char **out_buf, char *prealloc_buf, size_t prealloc_size, const char *fmt, va_list ap)
 
static time_t parse_date_string(const char *datetime)
 
static void do_ssi_include(struct mg_connection *conn, const char *ssi, char *tag, int include_level)
 
int mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
 
static int prepare_cgi_environment(struct mg_connection *conn, const char *prog, struct cgi_environment *env)
 
static void interpret_uri(struct mg_connection *conn, char *filename, size_t filename_buf_len, struct mg_file_stat *filestat, int *is_found, int *is_script_resource, int *is_websocket_request, int *is_put_or_delete_request)
 
#define SSL_ERROR_WANT_CONNECT
 
static void send_options(struct mg_connection *conn)
 
static int lowercase(const char *s)
 
static int parse_range_header(const char *header, int64_t *a, int64_t *b)
 
static void event_destroy(void *eventhdl)
 
static int mg_stat(const struct mg_connection *conn, const char *path, struct mg_file_stat *filep)
 
static int get_uri_type(const char *uri)
 
#define X509_get_serialNumber
 
#define DEBUG_TRACE(fmt,...)
 
static void get_system_name(char **sysName)
 
@ ENABLE_DIRECTORY_LISTING
 
@ ACCESS_CONTROL_ALLOW_ORIGIN
 
@ ALLOW_INDEX_SCRIPT_SUB_RES
 
@ ACCESS_CONTROL_ALLOW_HEADERS
 
@ SSL_DEFAULT_VERIFY_PATHS
 
@ ACCESS_CONTROL_ALLOW_METHODS
 
@ PUT_DELETE_PASSWORDS_FILE
 
@ ENABLE_AUTH_DOMAIN_CHECK
 
int mg_url_encode(const char *src, char *dst, size_t dst_len)
 
static void handler_info_wait_unused(struct mg_handler_info *handler_info)
 
static const char * header_val(const struct mg_connection *conn, const char *header)
 
#define CRYPTO_set_locking_callback
 
struct ossl_init_settings_st OPENSSL_INIT_SETTINGS
 
#define mg_cry_internal(conn, fmt,...)
 
static int set_acl_option(struct mg_context *phys_ctx)
 
static void mg_set_thread_name(const char *name)
 
static void get_mime_type(struct mg_connection *conn, const char *path, struct vec *vec)
 
static int set_blocking_mode(SOCKET sock)
 
#define CRYPTO_cleanup_all_ex_data
 
CIVETWEB_API struct mg_connection * mg_connect_client_secure(const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size)
 
static void send_file_data(struct mg_connection *conn, struct mg_file *filep, int64_t offset, int64_t len)
 
#define MAX_CGI_ENVIR_VARS
 
static int sslize(struct mg_connection *conn, SSL_CTX *s, int(*func)(SSL *), volatile int *stop_server, const struct mg_client_options *client_options)
 
static char * mg_strdup_ctx(const char *str, struct mg_context *ctx)
 
static void set_close_on_exec(SOCKET fd, struct mg_connection *conn)
 
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
 
static int parse_auth_header(struct mg_connection *conn, char *buf, size_t buf_size, struct ah *ah)
 
#define SSL_CTX_set_cipher_list
 
int mg_get_var2(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len, size_t occurrence)
 
static int is_not_modified(const struct mg_connection *conn, const struct mg_file_stat *filestat)
 
static const char * get_proto_name(const struct mg_connection *conn)
 
static void * master_thread(void *thread_func_param)
 
#define SSL_CTX_set_verify_depth
 
static void mg_set_handler_type(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *uri, int handler_type, int is_delete_request, mg_request_handler handler, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, mg_authorization_handler auth_handler, void *cbdata)
 
static int is_file_opened(const struct mg_file_access *fileacc)
 
static int get_http_header_len(const char *buf, int buflen)
 
#define SSL_CTX_set_info_callback
 
static void handler_info_release(struct mg_handler_info *handler_info)
 
void mg_close_connection(struct mg_connection *conn)
 
static int is_valid_port(unsigned long port)
 
static void handle_propfind(struct mg_connection *conn, const char *path, struct mg_file_stat *filep)
 
static int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
 
#define SSL_get_servername
 
#define mg_realloc_ctx(a, b, c)
 
#define SSL_CTX_use_certificate_chain_file
 
struct x509_name X509_NAME
 
static int is_put_or_delete_method(const struct mg_connection *conn)
 
static int read_message(FILE *fp, struct mg_connection *conn, char *buf, int bufsiz, int *nread)
 
#define SSL_CTX_set_default_verify_paths
 
static int print_dir_entry(struct de *de)
 
#define MG_FOPEN_MODE_WRITE
 
void * mg_get_user_connection_data(const struct mg_connection *conn)
 
static int authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm)
 
static void send_ssi_file(struct mg_connection *, const char *, struct mg_file *, int)
 
#define mg_static_assert(cond, txt)
 
#define SOCKET_TIMEOUT_QUANTUM
 
static void produce_socket(struct mg_context *ctx, const struct socket *sp)
 
static ptrdiff_t match_prefix(const char *pattern, size_t pattern_len, const char *str)
 
int mg_send_chunk(struct mg_connection *conn, const char *chunk, unsigned int chunk_len)
 
#define EVP_get_digestbyname
 
static int get_request_handler(struct mg_connection *conn, int handler_type, mg_request_handler *handler, struct mg_websocket_subprotocols **subprotocols, mg_websocket_connect_handler *connect_handler, mg_websocket_ready_handler *ready_handler, mg_websocket_data_handler *data_handler, mg_websocket_close_handler *close_handler, mg_authorization_handler *auth_handler, void **cbdata, struct mg_handler_info **handler_info)
 
static void ssl_get_client_cert_info(struct mg_connection *conn)
 
static int alloc_vprintf2(char **buf, const char *fmt, va_list ap)
 
static int is_in_script_path(const struct mg_connection *conn, const char *path)
 
static double mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
 
static void free_context(struct mg_context *ctx)
 
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
 
static void construct_etag(char *buf, size_t buf_len, const struct mg_file_stat *filestat)
 
int mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
 
static int thread_idx_max
 
static int cryptolib_users
 
static int64_t push_all(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t len)
 
static const char * month_names[]
 
static int refresh_trust(struct mg_connection *conn)
 
static struct ssl_func ssl_sw[]
 
static void mg_vsnprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, va_list ap)
 
static int event_wait(void *eventhdl)
 
static int should_decode_url(const struct mg_connection *conn)
 
static void uninitialize_ssl(void)
 
#define TLSEXT_NAMETYPE_host_name
 
#define SSL_CTX_set_options(ctx, op)
 
static void handle_request(struct mg_connection *conn)
 
static int mg_get_system_info_impl(char *buffer, int buflen)
 
static void * worker_thread_run(struct worker_thread_args *thread_args)
 
#define SSL_CTX_set_verify
 
static int remove_directory(struct mg_connection *conn, const char *dir)
 
static const char * get_http_version(const struct mg_connection *conn)
 
static __inline void * mg_calloc(size_t a, size_t b)
 
static void handle_cgi_request(struct mg_connection *conn, const char *prog)
 
static void handler_info_acquire(struct mg_handler_info *handler_info)
 
static int parse_http_response(char *buf, int len, struct mg_response_info *ri)
 
static void * cryptolib_dll_handle
 
#define MG_FOPEN_MODE_NONE
 
#define CRYPTO_set_id_callback
 
const char * mg_get_builtin_mime_type(const char *path)
 
int mg_read(struct mg_connection *conn, void *buf, size_t len)
 
#define IGNORE_UNUSED_RESULT(a)
 
static FUNCTION_MAY_BE_UNUSED int mg_atomic_dec(volatile int *addr)
 
#define X509_get_issuer_name
 
static void discard_unread_request_data(struct mg_connection *conn)
 
int mg_strcasecmp(const char *s1, const char *s2)
 
static int mg_fclose(struct mg_file_access *fileacc)
 
static struct mg_connection * fc(struct mg_context *ctx)
 
void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
 
static int send_static_cache_header(struct mg_connection *conn)
 
#define SSL_CTX_set_session_id_context
 
static struct mg_context common_client_context
 
static void * worker_thread(void *thread_func_param)
 
#define SSL_CB_HANDSHAKE_DONE
 
static __inline void mg_free(void *a)
 
int mg_check_digest_access_authentication(struct mg_connection *conn, const char *realm, const char *filename)
 
static int mg_join_thread(pthread_t threadid)
 
int mg_get_system_info(char *buffer, int buflen)
 
static void handle_not_modified_static_file_request(struct mg_connection *conn, struct mg_file *filep)
 
static int init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
 
static void close_socket_gracefully(struct mg_connection *conn)
 
struct mg_context * mg_get_context(const struct mg_connection *conn)
 
static int is_ssl_port_used(const char *ports)
 
static void init_connection(struct mg_connection *conn)
 
struct x509_store_ctx_st X509_STORE_CTX
 
static struct ssl_func crypto_sw[]
 
static int dir_scan_callback(struct de *de, void *data)
 
static int get_month_index(const char *s)
 
void mg_set_websocket_handler_with_subprotocols(struct mg_context *ctx, const char *uri, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
 
static int mg_ssl_initialized
 
static void * ssllib_dll_handle
 
#define OPENSSL_INIT_LOAD_SSL_STRINGS
 
#define PASSWORDS_FILE_NAME
 
static void log_access(const struct mg_connection *conn)
 
#define SSLv23_server_method
 
static void close_connection(struct mg_connection *conn)
 
@ CONNECTION_TYPE_RESPONSE
 
@ CONNECTION_TYPE_INVALID
 
@ CONNECTION_TYPE_REQUEST
 
#define SSL_OP_NO_TLSv1_1
 
static int substitute_index_file(struct mg_connection *conn, char *path, size_t path_len, struct mg_file_stat *filestat)
 
static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
 
void mg_stop(struct mg_context *ctx)
 
#define STRUCT_FILE_INITIALIZER
 
#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)
 
static FUNCTION_MAY_BE_UNUSED void mg_global_unlock(void)
 
void * mg_get_user_data(const struct mg_context *ctx)
 
static FUNCTION_MAY_BE_UNUSED void mg_global_lock(void)
 
static int scan_directory(struct mg_connection *conn, const char *dir, void *data, int(*cb)(struct de *, void *))
 
static int push_inner(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len, double timeout)
 
static int check_acl(struct mg_context *phys_ctx, uint32_t remote_ip)
 
const char * mg_version(void)
 
void mg_set_auth_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
 
static uint64_t get_random(void)
 
void mg_lock_connection(struct mg_connection *conn)
 
int mg_send_file_body(struct mg_connection *conn, const char *path)
 
static void * event_create(void)
 
static int is_valid_http_method(const char *method)
 
#define SSL_ERROR_WANT_WRITE
 
static int is_file_in_memory(const struct mg_connection *conn, const char *path)
 
@ MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE
 
@ MG_WEBSOCKET_OPCODE_PONG
 
@ MG_WEBSOCKET_OPCODE_PING
 
CIVETWEB_API int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
 
void *(* mg_thread_func_t)(void *)
 
@ MG_CONFIG_TYPE_DIRECTORY
 
@ MG_CONFIG_TYPE_EXT_PATTERN
 
@ MG_CONFIG_TYPE_STRING_MULTILINE
 
@ MG_CONFIG_TYPE_STRING_LIST
 
@ MG_CONFIG_TYPE_YES_NO_OPTIONAL
 
#define PRINTF_FORMAT_STRING(s)
 
int(* mg_authorization_handler)(struct mg_connection *conn, void *cbdata)
 
CIVETWEB_API int mg_websocket_client_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
 
void(* mg_websocket_ready_handler)(struct mg_connection *, void *)
 
CIVETWEB_API int mg_handle_form_request(struct mg_connection *conn, struct mg_form_data_handler *fdh)
 
#define PRINTF_ARGS(x, y)
 
int(* mg_websocket_data_handler)(struct mg_connection *, int, char *, size_t, void *)
 
int(* mg_request_handler)(struct mg_connection *conn, void *cbdata)
 
void(* mg_websocket_close_handler)(const struct mg_connection *, void *)
 
int(* mg_websocket_connect_handler)(const struct mg_connection *, void *)
 
@ MG_FEATURES_COMPRESSION
 
struct md5_state_s md5_state_t
 
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
 
MD5_STATIC void md5_init(md5_state_t *pms)
 
MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes)
 
RooArgList L(const RooAbsArg &v1)
 
SHA_API void SHA1_Init(SHA_CTX *context)
 
SHA_API void SHA1_Update(SHA_CTX *context, const uint8_t *data, const uint32_t len)
 
SHA_API void SHA1_Final(unsigned char *digest, SHA_CTX *context)
 
void(* exit_context)(const struct mg_context *ctx)
 
const char * default_value
 
struct mg_header http_headers[MG_MAX_HEADERS]
 
const char * request_method
 
const char * query_string
 
const char * http_version
 
const char * http_version
 
struct mg_header http_headers[MG_MAX_HEADERS]
 
static void output(int code)