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;
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;
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 *);
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,
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,
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,
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)
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
1566 HANDLE pthread_cond_helper_mutex;
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)) {
1626 pthread_setspecific(
sTlsKey, tls);
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()
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},
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)
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},
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)
2222#if defined(USE_IPV6)
2223 struct sockaddr_in6 sin6;
2252#if defined(MG_USE_OPEN_FILE)
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}, \
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");
2579#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2581 struct mg_shared_lua_websocket_list *shared_lua_websockets;
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;
2626#if defined(ALTERNATIVE_QUEUE)
2631 volatile int sq_head;
2632 volatile int sq_tail;
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;
2676#if defined(USE_SERVER_STATS)
2677static struct mg_memory_stat mg_common_memory = {0, 0, 0};
2679static struct mg_memory_stat *
2683 return &(ctx->ctx_memory);
2685 return &mg_common_memory;
2704#if defined(USE_SERVER_STATS)
2735#if defined(USE_WEBSOCKET)
2736 int in_websocket_handling;
2751#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2752 void *lua_websocket_state;
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)
2912 if (0 != pthread_mutex_init(&(ret->
mutex), NULL)) {
2917 if (0 != pthread_cond_init(&(ret->
cond), NULL)) {
2919 pthread_mutex_destroy(&(ret->
mutex));
2931 pthread_mutex_lock(&(ev->
mutex));
2932 pthread_cond_wait(&(ev->
cond), &(ev->
mutex));
2933 pthread_mutex_unlock(&(ev->
mutex));
2942 pthread_mutex_lock(&(ev->
mutex));
2943 pthread_cond_signal(&(ev->
cond));
2944 pthread_mutex_unlock(&(ev->
mutex));
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)
3057#if defined(MG_USE_OPEN_FILE)
3060 const char *buf = NULL;
3072 if (filep == NULL) {
3083 filep->
access.membuf = buf;
3098 return (buf != NULL);
3126#if defined(MG_USE_OPEN_FILE)
3127 return (fileacc->membuf != NULL) || (fileacc->
fp != NULL);
3129 return (fileacc->
fp != NULL);
3157#if defined(MG_USE_OPEN_FILE)
3158 filep->
access.membuf = NULL;
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");
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) {
3433#define mg_get_option DO_NOT_USE_THIS_FUNCTION_INTERNALLY__access_directly
3445 return (ctx == NULL) ? NULL : ctx->
user_data;
3468#if defined(MG_LEGACY_INTERFACE)
3471mg_get_ports(
const struct mg_context *ctx,
size_t size,
int *ports,
int *ssl)
3480#if defined(USE_IPV6)
3502 memset(ports, 0,
sizeof(*ports) * (
size_t)
size);
3513#if defined(USE_IPV6)
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;
3668 timestamp = time(NULL);
3672 "[%010lu] [error] [client %s] ",
3673 (
unsigned long)timestamp,
3722#define mg_cry DO_NOT_USE_THIS_FUNCTION__USE_mg_cry_internal
3733 return &fake_connection;
3750#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
3757 if (strlen(txt) == 3) {
3758 memcpy(tls->txtbuf, txt, 4);
3760 strcpy(tls->txtbuf,
"ERR");
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)
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)
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));
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) {
4168 }
while (res == -1 &&
len-- > 0);
4169 return (res == -1) ? -1 : j + res +
len;
4174 return (ptrdiff_t)j;
4184 const char *http_version;
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]) {
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)) {
4537 has_body = ((status > 199) && (status != 204) && (status != 304));
4545 mg_vsnprintf(conn, NULL, errmsg_buf,
sizeof(errmsg_buf), fmt, ap);
4548 DEBUG_TRACE(
"Error %i - [%s]", status, errmsg_buf);
4558 handled_by_callback =
4564 if (!handled_by_callback) {
4568 "Recursion when handling error %u - fall back to default",
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) {
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,
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,
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'));
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) {
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;
5198 wchar_t wbuf[W_PATH_MAX];
5199 WIN32_FILE_ATTRIBUTE_DATA info;
5200 time_t creation_time;
5205 memset(filep, 0,
sizeof(*filep));
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);
5240 SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
5241 info.ftLastWriteTime.dwHighDateTime);
5247 creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
5248 info.ftCreationTime.dwHighDateTime);
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));
5273 wchar_t wbuf[W_PATH_MAX];
5274 path_to_unicode(conn, path, wbuf,
ARRAY_SIZE(wbuf));
5275 return DeleteFileW(wbuf) ? 0 : -1;
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);
5799 memset(filep, 0,
sizeof(*filep));
5815 if (0 ==
stat(path, &st)) {
5816 filep->
size = (uint64_t)(st.st_size);
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",