24 #if !defined(_CRT_SECURE_NO_WARNINGS) 25 #define _CRT_SECURE_NO_WARNINGS 28 #define _WIN32_WINNT 0x0501 31 #if !defined(_GNU_SOURCE) 34 #if defined(__linux__) && !defined(_XOPEN_SOURCE) 35 #define _XOPEN_SOURCE 600 37 #ifndef _LARGEFILE_SOURCE 38 #define _LARGEFILE_SOURCE 40 #ifndef _FILE_OFFSET_BITS 41 #define _FILE_OFFSET_BITS 64 43 #ifndef __STDC_FORMAT_MACROS 44 #define __STDC_FORMAT_MACROS 46 #ifndef __STDC_LIMIT_MACROS 47 #define __STDC_LIMIT_MACROS 50 #define __EXTENSIONS__ 51 #define __inline inline 61 #pragma warning(disable : 4306) 63 #pragma warning(disable : 4127) 65 #pragma warning(disable : 4204) 67 #pragma warning(disable : 4820) 69 #pragma warning(disable : 4668) 71 #pragma warning(disable : 4255) 73 #pragma warning(disable : 4711) 80 #if defined(_MSC_VER) && (_MSC_VER >= 1600) 81 #define mg_static_assert static_assert 82 #elif defined(__cplusplus) && (__cplusplus >= 201103L) 83 #define mg_static_assert static_assert 84 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) 85 #define mg_static_assert _Static_assert 88 #define mg_static_assert(cond, txt) \ 89 extern char static_assert_replacement[(cond) ? 1 : -1] 93 "int data type size check");
95 "pointer data type size check");
100 #ifdef NO_ALTERNATIVE_QUEUE 101 #ifdef ALTERNATIVE_QUEUE 102 #error "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE or none, but not both" 105 #define ALTERNATIVE_QUEUE 110 #ifndef WIN32_LEAN_AND_MEAN 111 #define WIN32_LEAN_AND_MEAN 114 #if defined(__SYMBIAN32__) 123 "Symbian is no longer maintained. CivetWeb will drop Symbian support." 126 #define PATH_MAX FILENAME_MAX 130 #ifndef CIVETWEB_HEADER_INCLUDED 137 #ifndef IGNORE_UNUSED_RESULT 138 #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1)) 142 #if defined(__GNUC__) || defined(__MINGW32__) 158 #pragma GCC diagnostic ignored "-Wunused-function" 160 #define FUNCTION_MAY_BE_UNUSED 163 #define FUNCTION_MAY_BE_UNUSED 168 #include <sys/types.h> 169 #include <sys/stat.h> 180 #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" 183 #if defined(__GNUC__) || defined(__MINGW32__) 201 #if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8)) 203 #pragma clang diagnostic ignored "-Wno-reserved-id-macro" 204 #pragma clang diagnostic ignored "-Wno-keyword-macro" 208 #define CLOCK_MONOTONIC (1) 209 #define CLOCK_REALTIME (2) 211 #include <sys/errno.h> 212 #include <sys/time.h> 213 #include <mach/clock.h> 214 #include <mach/mach.h> 215 #include <mach/mach_time.h> 220 _civet_clock_gettime(
int clk_id,
struct timespec *t)
222 memset(t, 0,
sizeof(*t));
223 if (clk_id == CLOCK_REALTIME) {
225 int rv = gettimeofday(&now, NULL);
229 t->tv_sec = now.tv_sec;
230 t->tv_nsec = now.tv_usec * 1000;
233 }
else if (clk_id == CLOCK_MONOTONIC) {
234 static uint64_t clock_start_time = 0;
235 static mach_timebase_info_data_t timebase_ifo = {0, 0};
237 uint64_t now = mach_absolute_time();
239 if (clock_start_time == 0) {
240 kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
242 assert(mach_status == KERN_SUCCESS);
247 clock_start_time = now;
250 now = (uint64_t)((
double)(now - clock_start_time)
251 * (
double)timebase_ifo.numer
252 / (double)timebase_ifo.denom);
254 t->tv_sec = now / 1000000000;
255 t->tv_nsec = now % 1000000000;
262 #ifdef __CLOCK_AVAILABILITY 267 _civet_safe_clock_gettime(
int clk_id,
struct timespec *t)
270 return clock_gettime(clk_id, t);
272 return _civet_clock_gettime(clk_id, t);
274 #define clock_gettime _civet_safe_clock_gettime 276 #define clock_gettime _civet_clock_gettime 294 #define INT64_MAX (9223372036854775807) 298 #ifndef MAX_WORKER_THREADS 299 #define MAX_WORKER_THREADS (1024 * 64) 302 #ifndef SOCKET_TIMEOUT_QUANTUM 303 #define SOCKET_TIMEOUT_QUANTUM (2000) 306 #define SHUTDOWN_RD (0) 307 #define SHUTDOWN_WR (1) 308 #define SHUTDOWN_BOTH (2) 311 "worker threads must be a positive number");
314 "size_t data type size check");
316 #if defined(_WIN32) \ 317 && !defined(__SYMBIAN32__) 319 #include <winsock2.h> 320 #include <ws2tcpip.h> 324 #if !defined(PATH_MAX) 325 #define PATH_MAX (MAX_PATH) 328 #if !defined(PATH_MAX) 329 #define PATH_MAX (4096) 336 #define in_port_t u_short 350 #define errno ((int)(GetLastError())) 351 #define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10)) 354 #define MAKEUQUAD(lo, hi) \ 355 ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32)) 356 #define RATE_DIFF (10000000) 357 #define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de)) 358 #define SYS2UNIX_TIME(lo, hi) \ 359 ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)) 364 #if defined(_MSC_VER) 365 #if (_MSC_VER < 1300) 367 #define STR(x) STRX(x) 368 #define __func__ __FILE__ ":" STR(__LINE__) 369 #define strtoull(x, y, z) ((unsigned __int64)_atoi64(x)) 370 #define strtoll(x, y, z) (_atoi64(x)) 372 #define __func__ __FUNCTION__ 373 #define strtoull(x, y, z) (_strtoui64(x, y, z)) 374 #define strtoll(x, y, z) (_strtoi64(x, y, z)) 378 #define ERRNO ((int)(GetLastError())) 381 #if defined(_WIN64) || defined(__MINGW64__) 382 #define SSL_LIB "ssleay64.dll" 383 #define CRYPTO_LIB "libeay64.dll" 385 #define SSL_LIB "ssleay32.dll" 386 #define CRYPTO_LIB "libeay32.dll" 389 #define O_NONBLOCK (0) 393 #if !defined(EWOULDBLOCK) 394 #define EWOULDBLOCK WSAEWOULDBLOCK 397 #define INT64_FMT "I64d" 398 #define UINT64_FMT "I64u" 400 #define WINCDECL __cdecl 401 #define vsnprintf_impl _vsnprintf 402 #define access _access 403 #define mg_sleep(x) (Sleep(x)) 405 #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY) 407 #define popen(x, y) (_popen(x, y)) 410 #define pclose(x) (_pclose(x)) 412 #define close(x) (_close(x)) 413 #define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y))) 414 #define RTLD_LAZY (0) 415 #define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0) 416 #define fdopen(x, y) (_fdopen((x), (y))) 417 #define write(x, y, z) (_write((x), (y), (unsigned)z)) 418 #define read(x, y, z) (_read((x), (y), (unsigned)z)) 419 #define flockfile(x) (EnterCriticalSection(&global_log_file_lock)) 420 #define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock)) 421 #define sleep(x) (Sleep((x)*1000)) 422 #define rmdir(x) (_rmdir(x)) 423 #define timegm(x) (_mkgmtime(x)) 426 #define fileno(x) (_fileno(x)) 429 typedef HANDLE pthread_mutex_t;
430 typedef DWORD pthread_key_t;
431 typedef HANDLE pthread_t;
433 CRITICAL_SECTION threadIdSec;
434 struct mg_workerTLS *waiting_thread;
437 #ifndef __clockid_t_defined 438 typedef DWORD clockid_t;
440 #ifndef CLOCK_MONOTONIC 441 #define CLOCK_MONOTONIC (1) 443 #ifndef CLOCK_REALTIME 444 #define CLOCK_REALTIME (2) 447 #define CLOCK_THREAD (3) 449 #ifndef CLOCK_PROCESS 450 #define CLOCK_PROCESS (4) 454 #if defined(_MSC_VER) && (_MSC_VER >= 1900) 455 #define _TIMESPEC_DEFINED 457 #ifndef _TIMESPEC_DEFINED 464 #if !defined(WIN_PTHREADS_TIME_H) 465 #define MUST_IMPLEMENT_CLOCK_GETTIME 468 #ifdef MUST_IMPLEMENT_CLOCK_GETTIME 469 #define clock_gettime mg_clock_gettime 471 clock_gettime(clockid_t clk_id,
struct timespec *tp)
474 ULARGE_INTEGER li, li2;
477 static double perfcnt_per_sec = 0.0;
480 memset(tp, 0,
sizeof(*tp));
482 if (clk_id == CLOCK_REALTIME) {
485 GetSystemTimeAsFileTime(&ft);
486 li.LowPart = ft.dwLowDateTime;
487 li.HighPart = ft.dwHighDateTime;
488 li.QuadPart -= 116444736000000000;
489 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
490 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
494 }
else if (clk_id == CLOCK_MONOTONIC) {
497 if (perfcnt_per_sec == 0.0) {
498 QueryPerformanceFrequency((LARGE_INTEGER *)&li);
499 perfcnt_per_sec = 1.0 / li.QuadPart;
501 if (perfcnt_per_sec != 0.0) {
502 QueryPerformanceCounter((LARGE_INTEGER *)&li);
503 d = li.QuadPart * perfcnt_per_sec;
504 tp->tv_sec = (time_t)d;
506 tp->tv_nsec = (long)(d * 1.0E9);
511 }
else if (clk_id == CLOCK_THREAD) {
514 FILETIME t_create, t_exit, t_kernel, t_user;
515 if (GetThreadTimes(GetCurrentThread(),
520 li.LowPart = t_user.dwLowDateTime;
521 li.HighPart = t_user.dwHighDateTime;
522 li2.LowPart = t_kernel.dwLowDateTime;
523 li2.HighPart = t_kernel.dwHighDateTime;
524 li.QuadPart += li2.QuadPart;
525 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
526 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
531 }
else if (clk_id == CLOCK_PROCESS) {
534 FILETIME t_create, t_exit, t_kernel, t_user;
535 if (GetProcessTimes(GetCurrentProcess(),
540 li.LowPart = t_user.dwLowDateTime;
541 li.HighPart = t_user.dwHighDateTime;
542 li2.LowPart = t_kernel.dwLowDateTime;
543 li2.HighPart = t_kernel.dwHighDateTime;
544 li.QuadPart += li2.QuadPart;
545 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
546 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
566 static int pthread_mutex_lock(pthread_mutex_t *);
567 static int pthread_mutex_unlock(pthread_mutex_t *);
568 static void path_to_unicode(
const struct mg_connection *conn,
580 mg_fgets(
char *buf,
size_t size,
struct mg_file *filep,
char **p);
585 char d_name[PATH_MAX];
590 WIN32_FIND_DATAW info;
591 struct dirent result;
594 #if defined(_WIN32) && !defined(POLLIN) 601 #define POLLIN (0x0300) 606 #if defined(_MSC_VER) 607 #pragma comment(lib, "Ws2_32.lib") 613 #include <sys/wait.h> 614 #include <sys/socket.h> 615 #include <sys/poll.h> 616 #include <netinet/in.h> 617 #include <arpa/inet.h> 618 #include <sys/time.h> 619 #include <sys/utsname.h> 621 #include <inttypes.h> 623 #include <netinet/tcp.h> 627 typedef unsigned short int in_port_t;
634 #define vsnprintf_impl vsnprintf 636 #if !defined(NO_SSL_DL) && !defined(NO_SSL) 640 #if defined(__MACH__) 641 #define SSL_LIB "libssl.dylib" 642 #define CRYPTO_LIB "libcrypto.dylib" 644 #if !defined(SSL_LIB) 645 #define SSL_LIB "libssl.so" 647 #if !defined(CRYPTO_LIB) 648 #define CRYPTO_LIB "libcrypto.so" 654 #define closesocket(a) (close(a)) 655 #define mg_mkdir(conn, path, mode) (mkdir(path, mode)) 656 #define mg_remove(conn, x) (remove(x)) 657 #define mg_sleep(x) (usleep((x)*1000)) 658 #define mg_opendir(conn, x) (opendir(x)) 659 #define mg_closedir(x) (closedir(x)) 660 #define mg_readdir(x) (readdir(x)) 661 #define ERRNO (errno) 662 #define INVALID_SOCKET (-1) 663 #define INT64_FMT PRId64 664 #define UINT64_FMT PRIu64 670 #ifndef CLOCK_MONOTONIC 671 #define CLOCK_MONOTONIC CLOCK_REALTIME 682 #define socklen_t int 690 #define va_copy(x, y) ((x) = (y)) 696 #if defined(__MINGW32__) 698 #pragma GCC diagnostic push 699 #pragma GCC diagnostic ignored "-Wunused-function" 703 static CRITICAL_SECTION global_log_file_lock;
709 return GetCurrentThreadId();
717 void (*_ignored)(
void *)
724 return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
732 pthread_key_delete(pthread_key_t key)
734 return TlsFree(key) ? 0 : 1;
740 pthread_setspecific(pthread_key_t key,
void *value)
742 return TlsSetValue(key, value) ? 0 : 1;
748 pthread_getspecific(pthread_key_t key)
750 return TlsGetValue(key);
753 #if defined(__MINGW32__) 755 #pragma GCC diagnostic pop 764 #define PASSWORDS_FILE_NAME ".htpasswd" 765 #define CGI_ENVIRONMENT_SIZE (4096) 766 #define MAX_CGI_ENVIR_VARS (256) 767 #define MG_BUF_LEN (8192) 769 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 772 #if defined(_WIN32_WCE) 775 #if defined(__MINGW32__) 777 #pragma GCC diagnostic push 778 #pragma GCC diagnostic ignored "-Wunused-function" 791 SystemTimeToFileTime(&st, &ft);
792 t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
804 localtime_s(
const time_t *ptime,
struct tm *ptm)
806 int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
809 TIME_ZONE_INFORMATION tzinfo;
816 FileTimeToLocalFileTime(&ft, &lft);
817 FileTimeToSystemTime(&lft, &st);
818 ptm->tm_year = st.wYear - 1900;
819 ptm->tm_mon = st.wMonth - 1;
820 ptm->tm_wday = st.wDayOfWeek;
821 ptm->tm_mday = st.wDay;
822 ptm->tm_hour = st.wHour;
823 ptm->tm_min = st.wMinute;
824 ptm->tm_sec = st.wSecond;
827 (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
835 gmtime_s(
const time_t *ptime,
struct tm *ptm)
838 return localtime_s(ptime, ptm);
843 static struct tm tm_array[MAX_WORKER_THREADS];
844 static int tm_index = 0;
849 localtime(
const time_t *ptime)
851 int i =
mg_atomic_inc(&tm_index) % (
sizeof(tm_array) /
sizeof(tm_array[0]));
852 return localtime_s(ptime, tm_array + i);
858 gmtime(
const time_t *ptime)
861 return gmtime_s(ptime, tm_array + i);
867 strftime(
char *dst,
size_t dst_size,
const char *fmt,
const struct tm *tm)
874 #define _beginthreadex(psec, stack, func, prm, flags, ptid) \ 875 (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid) 877 #define remove(f) mg_remove(NULL, f) 882 rename(
const char *
a,
const char *
b)
884 wchar_t wa[PATH_MAX];
885 wchar_t wb[PATH_MAX];
889 return MoveFileW(wa, wb) ? 0 : -1;
901 stat(
const char *
name,
struct stat *st)
903 wchar_t wbuf[PATH_MAX];
904 WIN32_FILE_ATTRIBUTE_DATA attr;
905 time_t creation_time, write_time;
907 path_to_unicode(NULL, name, wbuf,
ARRAY_SIZE(wbuf));
908 memset(&attr, 0,
sizeof(attr));
910 GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
912 (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
914 write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
915 attr.ftLastWriteTime.dwHighDateTime);
916 creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
917 attr.ftCreationTime.dwHighDateTime);
919 if (creation_time > write_time) {
920 st->st_mtime = creation_time;
922 st->st_mtime = write_time;
927 #define access(x, a) 1 935 #if defined(__MINGW32__) 937 #pragma GCC diagnostic pop 943 #if defined(__GNUC__) || defined(__MINGW32__) 945 #define GCC_VERSION \ 946 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 947 #if GCC_VERSION >= 40500 948 #pragma GCC diagnostic push 949 #pragma GCC diagnostic ignored "-Wunused-function" 952 #if defined(__clang__) 954 #pragma clang diagnostic push 955 #pragma clang diagnostic ignored "-Wunused-function" 961 #if defined(_WIN32) && !defined(__SYMBIAN32__) 964 static int pthread_mutex_lock(pthread_mutex_t *mutex);
967 static int pthread_mutex_unlock(pthread_mutex_t *mutex);
975 (
void)pthread_mutex_lock(&global_lock_mutex);
983 (
void)pthread_mutex_unlock(&global_lock_mutex);
992 #if defined(_WIN32) && !defined(__SYMBIAN32__) && !defined(NO_ATOMICS) 996 ret = InterlockedIncrement((
volatile long *)addr);
997 #elif defined(__GNUC__) \ 998 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ 999 && !defined(NO_ATOMICS) 1000 ret = __sync_add_and_fetch(addr, 1);
1015 #if defined(_WIN32) && !defined(__SYMBIAN32__) && !defined(NO_ATOMICS) 1019 ret = InterlockedDecrement((
volatile long *)addr);
1020 #elif defined(__GNUC__) \ 1021 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ 1022 && !defined(NO_ATOMICS) 1023 ret = __sync_sub_and_fetch(addr, 1);
1033 #if defined(USE_SERVER_STATS) 1035 mg_atomic_add(
volatile int64_t *addr, int64_t value)
1038 #if defined(_WIN64) && !defined(__SYMBIAN32__) && !defined(NO_ATOMICS) 1039 ret = InterlockedAdd64(addr, value);
1040 #elif defined(__GNUC__) \ 1041 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ 1042 && !defined(NO_ATOMICS) 1043 ret = __sync_add_and_fetch(addr, value);
1055 #if defined(__GNUC__) 1057 #if GCC_VERSION >= 40500 1058 #pragma GCC diagnostic pop 1061 #if defined(__clang__) 1063 #pragma clang diagnostic pop 1067 #if defined(USE_SERVER_STATS) 1069 struct mg_memory_stat {
1070 volatile int64_t totalMemUsed;
1071 volatile int64_t maxMemUsed;
1072 volatile int blockCount;
1076 static struct mg_memory_stat *get_memory_stat(
struct mg_context *ctx);
1080 mg_malloc_ex(
size_t size,
1081 struct mg_context *ctx,
1085 void *
data =
malloc(size + 2 *
sizeof(uintptr_t));
1087 struct mg_memory_stat *mstat = get_memory_stat(ctx);
1089 #if defined(MEMORY_DEBUGGING) 1090 char mallocStr[256];
1097 int64_t mmem = mg_atomic_add(&mstat->totalMemUsed, (int64_t)size);
1098 if (mmem > mstat->maxMemUsed) {
1101 mstat->maxMemUsed = mmem;
1105 ((uintptr_t *)data)[0] = size;
1106 ((uintptr_t *)data)[1] = (uintptr_t)mstat;
1107 memory = (
void *)(((
char *)
data) + 2 *
sizeof(uintptr_t));
1110 #if defined(MEMORY_DEBUGGING) 1112 "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n",
1114 (
unsigned long)size,
1115 (
unsigned long)mstat->totalMemUsed,
1116 (
unsigned long)mstat->blockCount,
1120 OutputDebugStringA(mallocStr);
1131 mg_calloc_ex(
size_t count,
1133 struct mg_context *ctx,
1137 void *
data = mg_malloc_ex(size * count, ctx, file, line);
1140 memset(data, 0, size * count);
1147 mg_free_ex(
void *memory,
const char *file,
unsigned line)
1149 void *
data = (
void *)(((
char *)memory) - 2 *
sizeof(uintptr_t));
1152 #if defined(MEMORY_DEBUGGING) 1153 char mallocStr[256];
1160 uintptr_t size = ((uintptr_t *)data)[0];
1161 struct mg_memory_stat *mstat =
1162 (
struct mg_memory_stat *)(((uintptr_t *)
data)[1]);
1163 mg_atomic_add(&mstat->totalMemUsed, -(int64_t)size);
1165 #if defined(MEMORY_DEBUGGING) 1167 "MEM: %p %5lu free %7lu %4lu --- %s:%u\n",
1169 (
unsigned long)size,
1170 (
unsigned long)mstat->totalMemUsed,
1171 (
unsigned long)mstat->blockCount,
1175 OutputDebugStringA(mallocStr);
1186 mg_realloc_ex(
void *memory,
1188 struct mg_context *ctx,
1196 #if defined(MEMORY_DEBUGGING) 1197 char mallocStr[256];
1206 struct mg_memory_stat *mstat;
1207 data = (
void *)(((
char *)memory) - 2 *
sizeof(uintptr_t));
1208 oldsize = ((uintptr_t *)data)[0];
1209 mstat = (
struct mg_memory_stat *)((uintptr_t *)
data)[1];
1210 _realloc =
realloc(data, newsize + 2 *
sizeof(uintptr_t));
1213 mg_atomic_add(&mstat->totalMemUsed, -(int64_t)oldsize);
1214 #if defined(MEMORY_DEBUGGING) 1216 "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n",
1218 (
unsigned long)oldsize,
1219 (
unsigned long)mstat->totalMemUsed,
1220 (
unsigned long)mstat->blockCount,
1224 OutputDebugStringA(mallocStr);
1229 mg_atomic_add(&mstat->totalMemUsed, (int64_t)newsize);
1230 #if defined(MEMORY_DEBUGGING) 1232 "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
1234 (
unsigned long)newsize,
1235 (
unsigned long)mstat->totalMemUsed,
1236 (
unsigned long)mstat->blockCount,
1240 OutputDebugStringA(mallocStr);
1245 *(uintptr_t *)data = newsize;
1246 data = (
void *)(((
char *)
data) + 2 *
sizeof(uintptr_t));
1248 #if defined(MEMORY_DEBUGGING) 1250 OutputDebugStringA(
"MEM: realloc failed\n");
1259 data = mg_malloc_ex(newsize, ctx, file, line);
1264 mg_free_ex(memory, file, line);
1270 #define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__) 1271 #define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__) 1272 #define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__) 1273 #define mg_free(a) mg_free_ex(a, __FILE__, __LINE__) 1275 #define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__) 1276 #define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__) 1277 #define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__) 1281 static __inline
void *
1287 static __inline
void *
1293 static __inline
void *
1299 static __inline
void 1305 #define mg_malloc_ctx(a, c) mg_malloc(a) 1306 #define mg_calloc_ctx(a, b, c) mg_calloc(a, b) 1307 #define mg_realloc_ctx(a, b, c) mg_realloc(a, b) 1308 #define mg_free_ctx(a, c) mg_free(a) 1313 static void mg_vsnprintf(
const struct mg_connection *conn,
1320 static void mg_snprintf(
const struct mg_connection *conn,
1347 #define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc 1348 #define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc 1349 #define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc 1350 #define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free 1351 #define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf 1354 #define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf 1361 #if !defined(NO_SSL) 1369 struct mg_workerTLS {
1371 unsigned long thread_idx;
1372 #if defined(_WIN32) && !defined(__SYMBIAN32__) 1373 HANDLE pthread_cond_helper_mutex;
1374 struct mg_workerTLS *next_waiting_thread;
1379 #if defined(__GNUC__) || defined(__MINGW32__) 1381 #if GCC_VERSION >= 40500 1382 #pragma GCC diagnostic push 1383 #pragma GCC diagnostic ignored "-Wunused-function" 1386 #if defined(__clang__) 1388 #pragma clang diagnostic push 1389 #pragma clang diagnostic ignored "-Wunused-function" 1404 static unsigned long 1408 return GetCurrentThreadId();
1412 #pragma clang diagnostic push 1413 #pragma clang diagnostic ignored "-Wunreachable-code" 1421 if (
sizeof(pthread_t) >
sizeof(
unsigned long)) {
1424 struct mg_workerTLS *tls =
1425 (
struct mg_workerTLS *)pthread_getspecific(sTlsKey);
1429 tls = (
struct mg_workerTLS *)
mg_malloc(
sizeof(
struct mg_workerTLS));
1430 tls->is_master = -2;
1432 pthread_setspecific(sTlsKey, tls);
1434 return tls->thread_idx;
1439 unsigned long ret = 0;
1440 pthread_t t = pthread_self();
1441 memcpy(&ret, &t,
sizeof(pthread_t));
1446 #pragma clang diagnostic pop 1457 struct timespec tsnow;
1458 clock_gettime(CLOCK_REALTIME, &tsnow);
1459 return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
1463 #if defined(__GNUC__) 1465 #if GCC_VERSION >= 40500 1466 #pragma GCC diagnostic pop 1469 #if defined(__clang__) 1471 #pragma clang diagnostic pop 1475 #if !defined(DEBUG_TRACE) 1477 static void DEBUG_TRACE_FUNC(
const char *func,
1483 DEBUG_TRACE_FUNC(const
char *func,
unsigned line, const
char *fmt, ...)
1487 static uint64_t nslast;
1488 struct timespec tsnow;
1493 clock_gettime(CLOCK_REALTIME, &tsnow);
1494 nsnow = ((uint64_t)tsnow.tv_sec) * ((uint64_t)1000000000)
1495 + ((uint64_t)tsnow.tv_nsec);
1502 printf(
"*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ",
1503 (
unsigned long)tsnow.tv_sec,
1504 (
unsigned long)tsnow.tv_nsec,
1509 va_start(args, fmt);
1514 funlockfile(stdout);
1518 #define DEBUG_TRACE(fmt, ...) \ 1519 DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__) 1522 #define DEBUG_TRACE(fmt, ...) \ 1529 #define MD5_STATIC static 1534 typedef int socklen_t;
1536 #define _DARWIN_UNLIMITED_SELECT 1538 #define IP_ADDR_STR_LEN (50) 1540 #if !defined(MSG_NOSIGNAL) 1541 #define MSG_NOSIGNAL (0) 1544 #if !defined(SOMAXCONN) 1545 #define SOMAXCONN (100) 1549 #if !defined(MGSQLEN) 1550 #define MGSQLEN (20) 1558 #if defined(NO_SSL_DL) 1559 #include <openssl/ssl.h> 1560 #include <openssl/err.h> 1561 #include <openssl/crypto.h> 1562 #include <openssl/x509.h> 1563 #include <openssl/pem.h> 1564 #include <openssl/engine.h> 1565 #include <openssl/conf.h> 1566 #include <openssl/dh.h> 1567 #include <openssl/bn.h> 1568 #include <openssl/opensslv.h> 1587 #define SSL_CTRL_OPTIONS (32) 1588 #define SSL_CTRL_CLEAR_OPTIONS (77) 1589 #define SSL_CTRL_SET_ECDH_AUTO (94) 1591 #define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L 1592 #define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L 1593 #define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L 1595 #define SSL_VERIFY_NONE (0) 1596 #define SSL_VERIFY_PEER (1) 1597 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2) 1598 #define SSL_VERIFY_CLIENT_ONCE (4) 1599 #define SSL_OP_ALL ((long)(0x80000BFFUL)) 1600 #define SSL_OP_NO_SSLv2 (0x01000000L) 1601 #define SSL_OP_NO_SSLv3 (0x02000000L) 1602 #define SSL_OP_NO_TLSv1 (0x04000000L) 1603 #define SSL_OP_NO_TLSv1_2 (0x08000000L) 1604 #define SSL_OP_NO_TLSv1_1 (0x10000000L) 1605 #define SSL_OP_SINGLE_DH_USE (0x00100000L) 1606 #define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L) 1607 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000L) 1608 #define SSL_OP_NO_COMPRESSION (0x00020000L) 1610 #define SSL_CB_HANDSHAKE_START (0x10) 1611 #define SSL_CB_HANDSHAKE_DONE (0x20) 1613 #define SSL_ERROR_NONE (0) 1614 #define SSL_ERROR_SSL (1) 1615 #define SSL_ERROR_WANT_READ (2) 1616 #define SSL_ERROR_WANT_WRITE (3) 1617 #define SSL_ERROR_WANT_X509_LOOKUP (4) 1618 #define SSL_ERROR_SYSCALL (5) 1619 #define SSL_ERROR_ZERO_RETURN (6) 1620 #define SSL_ERROR_WANT_CONNECT (7) 1621 #define SSL_ERROR_WANT_ACCEPT (8) 1630 #ifdef OPENSSL_API_1_1 1632 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) 1633 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) 1634 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) 1635 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) 1636 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) 1637 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) 1638 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) 1639 #define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr) 1640 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr) 1641 #define TLS_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr) 1642 #define OPENSSL_init_ssl \ 1643 (*(int (*)(uint64_t opts, \ 1644 const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10].ptr) 1645 #define SSL_CTX_use_PrivateKey_file \ 1646 (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) 1647 #define SSL_CTX_use_certificate_file \ 1648 (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) 1649 #define SSL_CTX_set_default_passwd_cb \ 1650 (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) 1651 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) 1652 #define SSL_CTX_use_certificate_chain_file \ 1653 (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr) 1654 #define TLS_client_method (*(SSL_METHOD * (*)(void))ssl_sw[16].ptr) 1655 #define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr) 1656 #define SSL_CTX_set_verify \ 1657 (*(void (*)(SSL_CTX *, \ 1659 int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18].ptr) 1660 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr) 1661 #define SSL_CTX_load_verify_locations \ 1662 (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr) 1663 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr) 1664 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr) 1665 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[23].ptr) 1666 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr) 1667 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[25].ptr) 1668 #define SSL_CIPHER_get_name \ 1669 (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr) 1670 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr) 1671 #define SSL_CTX_set_session_id_context \ 1672 (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr) 1673 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr) 1674 #define SSL_CTX_set_cipher_list \ 1675 (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr) 1676 #define SSL_CTX_set_options \ 1677 (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr) 1678 #define SSL_CTX_set_info_callback \ 1679 (*(void (*)(SSL_CTX * ctx, \ 1680 void (*callback)(const SSL * s, int, int)))ssl_sw[32].ptr) 1681 #define SSL_get_ex_data (*(char *(*)(SSL *, int))ssl_sw[33].ptr) 1682 #define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) 1684 #define SSL_CTX_clear_options(ctx, op) \ 1685 SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) 1686 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \ 1687 SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) 1689 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) 1690 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) 1692 #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) 1693 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) 1695 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr) 1696 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr) 1697 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[2].ptr) 1698 #define CONF_modules_unload (*(void (*)(int))crypto_sw[3].ptr) 1699 #define X509_free (*(void (*)(X509 *))crypto_sw[4].ptr) 1700 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[5].ptr) 1701 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[6].ptr) 1702 #define X509_NAME_oneline \ 1703 (*(char *(*)(X509_NAME *, char *, int))crypto_sw[7].ptr) 1704 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[8].ptr) 1705 #define EVP_get_digestbyname \ 1706 (*(const EVP_MD *(*)(const char *))crypto_sw[9].ptr) 1707 #define EVP_Digest \ 1709 const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ 1711 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[11].ptr) 1712 #define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[12].ptr) 1713 #define ASN1_INTEGER_to_BN \ 1714 (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn))crypto_sw[13].ptr) 1715 #define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[14].ptr) 1716 #define CRYPTO_free (*(void (*)(void *addr))crypto_sw[15].ptr) 1718 #define OPENSSL_free(a) CRYPTO_free(a) 1725 static struct ssl_func ssl_sw[] = {{
"SSL_free", NULL},
1726 {
"SSL_accept", NULL},
1727 {
"SSL_connect", NULL},
1729 {
"SSL_write", NULL},
1730 {
"SSL_get_error", NULL},
1731 {
"SSL_set_fd", NULL},
1733 {
"SSL_CTX_new", NULL},
1734 {
"TLS_server_method", NULL},
1735 {
"OPENSSL_init_ssl", NULL},
1736 {
"SSL_CTX_use_PrivateKey_file", NULL},
1737 {
"SSL_CTX_use_certificate_file", NULL},
1738 {
"SSL_CTX_set_default_passwd_cb", NULL},
1739 {
"SSL_CTX_free", NULL},
1740 {
"SSL_CTX_use_certificate_chain_file", NULL},
1741 {
"TLS_client_method", NULL},
1742 {
"SSL_pending", NULL},
1743 {
"SSL_CTX_set_verify", NULL},
1744 {
"SSL_shutdown", NULL},
1745 {
"SSL_CTX_load_verify_locations", NULL},
1746 {
"SSL_CTX_set_default_verify_paths", NULL},
1747 {
"SSL_CTX_set_verify_depth", NULL},
1748 {
"SSL_get_peer_certificate", NULL},
1749 {
"SSL_get_version", NULL},
1750 {
"SSL_get_current_cipher", NULL},
1751 {
"SSL_CIPHER_get_name", NULL},
1752 {
"SSL_CTX_check_private_key", NULL},
1753 {
"SSL_CTX_set_session_id_context", NULL},
1754 {
"SSL_CTX_ctrl", NULL},
1755 {
"SSL_CTX_set_cipher_list", NULL},
1756 {
"SSL_CTX_set_options", NULL},
1757 {
"SSL_CTX_set_info_callback", NULL},
1758 {
"SSL_get_ex_data", NULL},
1759 {
"SSL_set_ex_data", NULL},
1765 static struct ssl_func crypto_sw[] = {{
"ERR_get_error", NULL},
1766 {
"ERR_error_string", NULL},
1767 {
"ERR_remove_state", NULL},
1768 {
"CONF_modules_unload", NULL},
1769 {
"X509_free", NULL},
1770 {
"X509_get_subject_name", NULL},
1771 {
"X509_get_issuer_name", NULL},
1772 {
"X509_NAME_oneline", NULL},
1773 {
"X509_get_serialNumber", NULL},
1774 {
"EVP_get_digestbyname", NULL},
1775 {
"EVP_Digest", NULL},
1777 {
"BN_bn2hex", NULL},
1778 {
"ASN1_INTEGER_to_BN", NULL},
1780 {
"CRYPTO_free", NULL},
1784 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) 1785 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) 1786 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) 1787 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) 1788 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) 1789 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) 1790 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) 1791 #define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr) 1792 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr) 1793 #define SSLv23_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr) 1794 #define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr) 1795 #define SSL_CTX_use_PrivateKey_file \ 1796 (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) 1797 #define SSL_CTX_use_certificate_file \ 1798 (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) 1799 #define SSL_CTX_set_default_passwd_cb \ 1800 (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) 1801 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) 1802 #define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr) 1803 #define SSL_CTX_use_certificate_chain_file \ 1804 (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr) 1805 #define SSLv23_client_method (*(SSL_METHOD * (*)(void))ssl_sw[17].ptr) 1806 #define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr) 1807 #define SSL_CTX_set_verify \ 1808 (*(void (*)(SSL_CTX *, \ 1810 int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19].ptr) 1811 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr) 1812 #define SSL_CTX_load_verify_locations \ 1813 (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr) 1814 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr) 1815 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr) 1816 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[24].ptr) 1817 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr) 1818 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[26].ptr) 1819 #define SSL_CIPHER_get_name \ 1820 (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr) 1821 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr) 1822 #define SSL_CTX_set_session_id_context \ 1823 (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr) 1824 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr) 1825 #define SSL_CTX_set_cipher_list \ 1826 (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr) 1827 #define SSL_CTX_set_info_callback \ 1828 (*(void (*)(SSL_CTX * ctx, \ 1829 void (*callback)(const SSL * s, int, int)))ssl_sw[32].ptr) 1830 #define SSL_get_ex_data (*(char *(*)(SSL *, int))ssl_sw[33].ptr) 1831 #define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) 1833 #define SSL_CTX_set_options(ctx, op) \ 1834 SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL) 1835 #define SSL_CTX_clear_options(ctx, op) \ 1836 SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) 1837 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \ 1838 SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) 1841 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) 1842 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) 1844 #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) 1845 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) 1847 #define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr) 1848 #define CRYPTO_set_locking_callback \ 1849 (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr) 1850 #define CRYPTO_set_id_callback \ 1851 (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr) 1852 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr) 1853 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr) 1854 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr) 1855 #define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr) 1856 #define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr) 1857 #define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr) 1858 #define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr) 1859 #define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr) 1860 #define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr) 1861 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[12].ptr) 1862 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[13].ptr) 1863 #define X509_NAME_oneline \ 1864 (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr) 1865 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[15].ptr) 1866 #define i2c_ASN1_INTEGER \ 1867 (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr) 1868 #define EVP_get_digestbyname \ 1869 (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr) 1870 #define EVP_Digest \ 1872 const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ 1874 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr) 1875 #define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr) 1876 #define ASN1_INTEGER_to_BN \ 1877 (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn))crypto_sw[21].ptr) 1878 #define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr) 1879 #define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr) 1881 #define OPENSSL_free(a) CRYPTO_free(a) 1887 static struct ssl_func ssl_sw[] = {{
"SSL_free", NULL},
1888 {
"SSL_accept", NULL},
1889 {
"SSL_connect", NULL},
1891 {
"SSL_write", NULL},
1892 {
"SSL_get_error", NULL},
1893 {
"SSL_set_fd", NULL},
1895 {
"SSL_CTX_new", NULL},
1896 {
"SSLv23_server_method", NULL},
1897 {
"SSL_library_init", NULL},
1898 {
"SSL_CTX_use_PrivateKey_file", NULL},
1899 {
"SSL_CTX_use_certificate_file", NULL},
1900 {
"SSL_CTX_set_default_passwd_cb", NULL},
1901 {
"SSL_CTX_free", NULL},
1902 {
"SSL_load_error_strings", NULL},
1903 {
"SSL_CTX_use_certificate_chain_file", NULL},
1904 {
"SSLv23_client_method", NULL},
1905 {
"SSL_pending", NULL},
1906 {
"SSL_CTX_set_verify", NULL},
1907 {
"SSL_shutdown", NULL},
1908 {
"SSL_CTX_load_verify_locations", NULL},
1909 {
"SSL_CTX_set_default_verify_paths", NULL},
1910 {
"SSL_CTX_set_verify_depth", NULL},
1911 {
"SSL_get_peer_certificate", NULL},
1912 {
"SSL_get_version", NULL},
1913 {
"SSL_get_current_cipher", NULL},
1914 {
"SSL_CIPHER_get_name", NULL},
1915 {
"SSL_CTX_check_private_key", NULL},
1916 {
"SSL_CTX_set_session_id_context", NULL},
1917 {
"SSL_CTX_ctrl", NULL},
1918 {
"SSL_CTX_set_cipher_list", NULL},
1919 {
"SSL_CTX_set_info_callback", NULL},
1920 {
"SSL_get_ex_data", NULL},
1921 {
"SSL_set_ex_data", NULL},
1927 static struct ssl_func crypto_sw[] = {{
"CRYPTO_num_locks", NULL},
1928 {
"CRYPTO_set_locking_callback", NULL},
1929 {
"CRYPTO_set_id_callback", NULL},
1930 {
"ERR_get_error", NULL},
1931 {
"ERR_error_string", NULL},
1932 {
"ERR_remove_state", NULL},
1933 {
"ERR_free_strings", NULL},
1934 {
"ENGINE_cleanup", NULL},
1935 {
"CONF_modules_unload", NULL},
1936 {
"CRYPTO_cleanup_all_ex_data", NULL},
1937 {
"EVP_cleanup", NULL},
1938 {
"X509_free", NULL},
1939 {
"X509_get_subject_name", NULL},
1940 {
"X509_get_issuer_name", NULL},
1941 {
"X509_NAME_oneline", NULL},
1942 {
"X509_get_serialNumber", NULL},
1943 {
"i2c_ASN1_INTEGER", NULL},
1944 {
"EVP_get_digestbyname", NULL},
1945 {
"EVP_Digest", NULL},
1947 {
"BN_bn2hex", NULL},
1948 {
"ASN1_INTEGER_to_BN", NULL},
1950 {
"CRYPTO_free", NULL},
1957 #if !defined(NO_CACHING) 1977 struct sockaddr_in sin;
1978 #if defined(USE_IPV6) 1979 struct sockaddr_in6 sin6;
1989 struct mg_file_stat {
1992 time_t last_modified;
1999 struct mg_file_in_memory {
2005 struct mg_file_access {
2015 struct mg_file_stat stat;
2016 struct mg_file_access access;
2019 #define STRUCT_FILE_INITIALIZER \ 2022 (uint64_t)0, (time_t)0, 0, 0, 0 \ 2026 (FILE *) NULL, (const char *)NULL \ 2036 unsigned char is_ssl;
2037 unsigned char ssl_redir;
2039 unsigned char in_use;
2081 #if defined(USE_WEBSOCKET) 2087 #if defined(USE_LUA) 2089 LUA_SCRIPT_EXTENSIONS,
2090 LUA_SERVER_PAGE_EXTENSIONS,
2092 #if defined(USE_DUKTAPE) 2093 DUKTAPE_SCRIPT_EXTENSIONS,
2096 #if defined(USE_WEBSOCKET) 2099 #if defined(USE_LUA) && defined(USE_WEBSOCKET) 2100 LUA_WEBSOCKET_EXTENSIONS,
2109 #if !defined(NO_CACHING) 2112 #if !defined(NO_SSL) 2115 #if defined(__linux__) 2116 ALLOW_SENDFILE_CALL,
2119 CASE_SENSITIVE_FILES,
2121 #if defined(USE_LUA) 2122 LUA_BACKGROUND_SCRIPT,
2123 LUA_BACKGROUND_SCRIPT_PARAMS,
2151 "index.xhtml,index.html,index.htm," 2152 "index.lp,index.lsp,index.lua,index.cgi," 2153 "index.shtml,index.php"},
2155 "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
2182 #if defined(USE_WEBSOCKET) 2187 #if defined(USE_LUA) 2192 #if defined(USE_DUKTAPE) 2198 #if defined(USE_WEBSOCKET) 2201 #if defined(USE_LUA) && defined(USE_WEBSOCKET) 2209 #if !defined(NO_CACHING) 2212 #if !defined(NO_SSL) 2215 #if defined(__linux__) 2221 #if defined(USE_LUA) 2236 "config_options and enum not sync");
2242 struct mg_handler_info {
2269 struct mg_handler_info *next;
2282 volatile int stop_flag;
2289 struct socket *listening_sockets;
2290 struct pollfd *listening_socket_fds;
2291 unsigned int num_listening_sockets;
2293 pthread_mutex_t thread_mutex;
2295 #ifdef ALTERNATIVE_QUEUE 2296 struct socket *client_socks;
2297 void **client_wait_events;
2299 struct socket queue[MGSQLEN];
2300 volatile int sq_head;
2301 volatile int sq_tail;
2306 unsigned int max_request_size;
2308 pthread_t masterthreadid;
2311 pthread_t *worker_threadids;
2312 struct mg_connection *worker_connections;
2318 uint64_t auth_nonce_mask;
2319 pthread_mutex_t nonce_mutex;
2320 unsigned long nonce_count;
2325 struct mg_handler_info *handlers;
2327 #if defined(USE_LUA) && defined(USE_WEBSOCKET) 2329 struct mg_shared_lua_websocket_list *shared_lua_websockets;
2332 #if defined(USE_TIMERS) 2333 struct ttimers *timers;
2336 #if defined(USE_LUA) 2337 void *lua_background_state;
2340 #if defined(USE_SERVER_STATS) 2341 int active_connections;
2342 int max_connections;
2343 int64_t total_connections;
2344 int64_t total_requests;
2345 struct mg_memory_stat ctx_memory;
2346 int64_t total_data_read;
2347 int64_t total_data_written;
2352 #if defined(USE_SERVER_STATS) 2353 static struct mg_memory_stat mg_common_memory = {0, 0, 0};
2355 static struct mg_memory_stat *
2356 get_memory_stat(
struct mg_context *ctx)
2359 return &(ctx->ctx_memory);
2361 return &mg_common_memory;
2371 struct mg_connection {
2372 int connection_type;
2377 struct mg_context *ctx;
2379 #if defined(USE_SERVER_STATS) 2387 struct socket client;
2388 time_t conn_birth_time;
2390 struct timespec req_time;
2392 int64_t num_bytes_sent;
2393 int64_t content_len;
2394 int64_t consumed_content;
2401 size_t chunk_remainder;
2407 int in_error_handler;
2409 #if defined(USE_WEBSOCKET) 2410 int in_websocket_handling;
2412 int handled_requests;
2421 time_t last_throttle_time;
2422 int64_t last_throttle_bytes;
2423 pthread_mutex_t mutex;
2425 #if defined(USE_LUA) && defined(USE_WEBSOCKET) 2426 void *lua_websocket_state;
2435 struct mg_connection *conn;
2437 struct mg_file_stat file;
2441 #if defined(USE_WEBSOCKET) 2444 #define is_websocket_protocol(conn) (0) 2448 #if !defined(NO_THREAD_NAME) 2449 #if defined(_WIN32) && defined(_MSC_VER) 2453 #pragma pack(push, 8) 2454 typedef struct tagTHREADNAME_INFO {
2462 #elif defined(__linux__) 2464 #include <sys/prctl.h> 2465 #include <sys/sendfile.h> 2466 #ifdef ALTERNATIVE_QUEUE 2467 #include <sys/eventfd.h> 2471 #if defined(ALTERNATIVE_QUEUE) 2475 #pragma clang diagnostic push 2476 #pragma clang diagnostic ignored "-Wunreachable-code" 2484 #if defined(__GNUC__) || defined(__MINGW32__) 2488 #pragma GCC diagnostic push 2489 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" 2490 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast" 2497 int evhdl = eventfd(0, EFD_CLOEXEC);
2505 if (
sizeof(
int) ==
sizeof(
void *)) {
2506 ret = (
void *)evhdl;
2526 if (
sizeof(
int) ==
sizeof(
void *)) {
2527 evhdl = (int)eventhdl;
2533 evhdl = *(
int *)eventhdl;
2536 s = (int)read(evhdl, &u,
sizeof(u));
2537 if (s !=
sizeof(uint64_t)) {
2552 if (
sizeof(
int) ==
sizeof(
void *)) {
2553 evhdl = (int)eventhdl;
2559 evhdl = *(
int *)eventhdl;
2562 s = (int)write(evhdl, &u,
sizeof(u));
2563 if (s !=
sizeof(uint64_t)) {
2576 if (
sizeof(
int) ==
sizeof(
void *)) {
2577 evhdl = (int)eventhdl;
2584 evhdl = *(
int *)eventhdl;
2591 #if defined(__GNUC__) || defined(__MINGW32__) 2592 #pragma GCC diagnostic pop 2596 #pragma clang diagnostic pop 2604 #if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE) 2606 struct posix_event {
2607 pthread_mutex_t mutex;
2615 struct posix_event *ret =
mg_malloc(
sizeof(
struct posix_event));
2620 if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
2625 if (0 != pthread_cond_init(&(ret->cond), NULL)) {
2627 pthread_mutex_destroy(&(ret->mutex));
2638 struct posix_event *ev = (
struct posix_event *)eventhdl;
2639 pthread_mutex_lock(&(ev->mutex));
2640 pthread_cond_wait(&(ev->cond), &(ev->mutex));
2641 pthread_mutex_unlock(&(ev->mutex));
2649 struct posix_event *ev = (
struct posix_event *)eventhdl;
2650 pthread_mutex_lock(&(ev->mutex));
2651 pthread_cond_signal(&(ev->cond));
2652 pthread_mutex_unlock(&(ev->mutex));
2660 struct posix_event *ev = (
struct posix_event *)eventhdl;
2661 pthread_cond_destroy(&(ev->cond));
2662 pthread_mutex_destroy(&(ev->mutex));
2671 char threadName[16 + 1];
2674 NULL, NULL, threadName,
sizeof(threadName),
"civetweb-%s", name);
2677 #if defined(_MSC_VER) 2681 THREADNAME_INFO info;
2682 info.dwType = 0x1000;
2683 info.szName = threadName;
2684 info.dwThreadID = ~0U;
2687 RaiseException(0x406D1388,
2689 sizeof(info) /
sizeof(ULONG_PTR),
2690 (ULONG_PTR *)&info);
2692 __except(EXCEPTION_EXECUTE_HANDLER)
2695 #elif defined(__MINGW32__) 2698 #elif defined(_GNU_SOURCE) && defined(__GLIBC__) \ 2699 && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12))) 2701 (
void)pthread_setname_np(pthread_self(), threadName);
2702 #elif defined(__linux__) 2704 (
void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
2715 #if defined(MG_LEGACY_INTERFACE) 2717 mg_get_valid_option_names(
void)
2742 #define MG_FOPEN_MODE_NONE (0) 2745 #define MG_FOPEN_MODE_READ (1) 2748 #define MG_FOPEN_MODE_WRITE (2) 2751 #define MG_FOPEN_MODE_APPEND (4) 2760 struct mg_file *filep,
2763 #if defined(MG_USE_OPEN_FILE) 2766 const char *buf = NULL;
2775 if (conn->ctx->callbacks.open_file) {
2776 buf = conn->ctx->callbacks.open_file(conn, path, &size);
2778 if (filep == NULL) {
2789 filep->access.membuf = buf;
2790 filep->access.fp = NULL;
2793 filep->stat.size = size;
2797 filep->stat.last_modified = time(NULL);
2799 filep->stat.is_directory = 0;
2800 filep->stat.is_gzipped = 0;
2804 return (buf != NULL);
2831 return (fileacc->membuf != NULL) || (fileacc->fp != NULL);
2835 static int mg_stat(
const struct mg_connection *conn,
2837 struct mg_file_stat *filep);
2850 struct mg_file *filep)
2857 filep->access.fp = NULL;
2858 filep->access.membuf = NULL;
2864 found =
mg_stat(conn, path, &(filep->stat));
2873 wchar_t wbuf[PATH_MAX];
2874 path_to_unicode(conn, path, wbuf,
ARRAY_SIZE(wbuf));
2877 filep->access.fp = _wfopen(wbuf,
L"rb");
2880 filep->access.fp = _wfopen(wbuf,
L"wb");
2883 filep->access.fp = _wfopen(wbuf,
L"ab");
2891 filep->access.fp = fopen(path,
"r");
2894 filep->access.fp = fopen(path,
"w");
2897 filep->access.fp = fopen(path,
"a");
2906 found =
mg_stat(conn, path, &(filep->stat));
2911 return (filep->access.fp != NULL);
2917 return (filep->access.membuf != NULL);
2931 if (fileacc != NULL) {
2932 if (fileacc->fp != NULL) {
2933 ret = fclose(fileacc->fp);
2934 }
else if (fileacc->membuf != NULL) {
2938 memset(fileacc, 0,
sizeof(*fileacc));
2947 for (; *src !=
'\0' && n > 1; n--) {
2957 return tolower(*(
const unsigned char *)s);
2969 }
while (diff == 0 && s1[-1] !=
'\0' && --len > 0);
2983 }
while (diff == 0 && s1[-1] !=
'\0');
2994 if ((p = (
char *)
mg_malloc(len + 1)) != NULL) {
3012 size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
3014 if (big_len >= small_len) {
3015 for (i = 0; i <= (big_len - small_len); i++) {
3046 #pragma clang diagnostic push 3047 #pragma clang diagnostic ignored "-Wformat-nonliteral" 3053 ok = (n >= 0) && ((
size_t)n < buflen);
3056 #pragma clang diagnostic pop 3068 "truncating vsnprintf buffer: [%.*s]",
3069 (
int)((buflen > 200) ? 200 : (buflen - 1)),
3071 n = (int)buflen - 1;
3113 }
else if (!ctx || ctx->config[i] == NULL) {
3116 return ctx->config[i];
3124 return (conn == NULL) ? (
struct mg_context *)NULL : (conn->ctx);
3131 return (ctx == NULL) ? NULL : ctx->user_data;
3139 conn->request_info.conn_data =
data;
3148 return conn->request_info.conn_data;
3154 #if defined(MG_LEGACY_INTERFACE) 3157 mg_get_ports(
const struct mg_context *ctx,
size_t size,
int *ports,
int *ssl)
3163 for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
3164 ssl[i] = ctx->listening_sockets[i].is_ssl;
3166 #if defined(USE_IPV6) 3167 (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3168 ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3171 ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3188 memset(ports, 0,
sizeof(*ports) * (
size_t)size);
3192 if (!ctx->listening_sockets) {
3196 for (i = 0; (i < size) && (i < (
int)ctx->num_listening_sockets); i++) {
3199 #if defined(USE_IPV6) 3200 (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3201 ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3204 ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3205 ports[
cnt].
is_ssl = ctx->listening_sockets[i].is_ssl;
3208 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
3212 }
else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
3232 if (usa->sa.sa_family == AF_INET) {
3233 getnameinfo(&usa->sa,
3241 #if defined(USE_IPV6) 3242 else if (usa->sa.sa_family == AF_INET6) {
3243 getnameinfo(&usa->sa,
3262 tm = ((t != NULL) ? gmtime(t) : NULL);
3264 strftime(buf, buf_len,
"%a, %d %b %Y %H:%M:%S GMT", tm);
3266 mg_strlcpy(buf,
"Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
3267 buf[buf_len - 1] =
'\0';
3276 return (
double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0
E-9
3277 + (
double)(ts_now->tv_sec - ts_before->tv_sec);
3283 mg_cry(
const struct mg_connection *conn,
const char *fmt, ...)
3293 buf[
sizeof(buf) - 1] = 0;
3305 if ((conn->ctx->callbacks.log_message == NULL)
3306 || (conn->ctx->callbacks.log_message(conn, buf) == 0)) {
3313 fi.access.fp = NULL;
3316 fi.access.fp = NULL;
3319 if (fi.access.fp != NULL) {
3320 flockfile(fi.access.fp);
3321 timestamp = time(NULL);
3324 fprintf(fi.access.fp,
3325 "[%010lu] [error] [client %s] ",
3326 (
unsigned long)timestamp,
3329 if (conn->request_info.request_method != NULL) {
3330 fprintf(fi.access.fp,
3332 conn->request_info.request_method,
3333 conn->request_info.request_uri
3334 ? conn->request_info.request_uri
3338 fprintf(fi.access.fp,
"%s", buf);
3339 fputc(
'\n', fi.access.fp);
3340 fflush(fi.access.fp);
3341 funlockfile(fi.access.fp);
3351 static struct mg_connection *
3352 fc(
struct mg_context *ctx)
3354 static struct mg_connection fake_connection;
3355 fake_connection.ctx = ctx;
3356 return &fake_connection;
3375 static char txt[16];
3376 sprintf(txt,
"%03i", conn->response_info.status_code);
3378 ((
struct mg_connection *)conn)->request_info.local_uri =
3379 ((
struct mg_connection *)conn)->request_info.request_uri =
3382 ((
struct mg_connection *)conn)->request_info.num_headers =
3383 conn->response_info.num_headers;
3384 memcpy(((
struct mg_connection *)conn)->request_info.http_headers,
3385 conn->response_info.http_headers,
3386 sizeof(conn->response_info.http_headers));
3392 return &conn->request_info;
3405 return &conn->response_info;
3413 #pragma clang diagnostic push 3414 #pragma clang diagnostic ignored "-Wunreachable-code" 3426 : (ri->
is_ssl ?
"https" :
"http"));
3431 #pragma clang diagnostic pop 3439 if ((buflen < 1) || (buf == 0) || (conn == 0)) {
3467 #if defined(USE_IPV6) 3468 int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
3469 int port = is_ipv6 ? htons(conn->client.lsa.sin6.sin6_port)
3470 : htons(conn->client.lsa.sin.sin_port);
3472 int port = htons(conn->client.lsa.sin.sin_port);
3474 int def_port = ri->
is_ssl ? 443 : 80;
3475 int auth_domain_check_enabled =
3479 const char *server_domain =
3485 if (port != def_port) {
3486 sprintf(portstr,
":%u", (
unsigned)port);
3491 if (!auth_domain_check_enabled || !server_domain) {
3497 server_domain = server_ip;
3524 const char *delimiters,
3525 const char *whitespace,
3528 char *p, *begin_word, *end_word, *end_whitespace;
3531 end_word = begin_word + strcspn(begin_word, delimiters);
3534 if (end_word > begin_word) {
3536 while (*p == quotechar) {
3543 if (*end_word !=
'\0') {
3544 size_t end_off = strcspn(end_word + 1, delimiters);
3545 memmove(p, end_word, end_off + 1);
3547 end_word += end_off + 1;
3553 for (p++; p < end_word; p++) {
3558 if (*end_word ==
'\0') {
3562 #if defined(__GNUC__) || defined(__MINGW32__) 3564 #if GCC_VERSION >= 40500 3565 #pragma GCC diagnostic push 3566 #pragma GCC diagnostic ignored "-Wsign-conversion" 3570 end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
3572 #if defined(__GNUC__) || defined(__MINGW32__) 3573 #if GCC_VERSION >= 40500 3574 #pragma GCC diagnostic pop 3578 for (p = end_word; p < end_whitespace; p++) {
3582 *buf = end_whitespace;
3594 for (i = 0; i < num_hdr; i++) {
3596 return hdr[i].
value;
3604 #if defined(USE_WEBSOCKET) 3611 int output_max_size)
3616 for (i = 0; i < ri->
num_headers && cnt < output_max_size; i++) {
3635 return get_header(conn->request_info.http_headers,
3636 conn->request_info.num_headers,
3640 return get_header(conn->response_info.http_headers,
3641 conn->request_info.num_headers,
3656 return conn->request_info.http_version;
3659 return conn->response_info.http_version;
3677 if (val == NULL || list == NULL || *list ==
'\0') {
3683 while (*list ==
' ' || *list ==
'\t')
3687 if ((list = strchr(val->ptr,
',')) != NULL) {
3689 val->len = ((size_t)(list - val->ptr));
3693 list = val->ptr + strlen(val->ptr);
3694 val->len = ((size_t)(list - val->ptr));
3698 end = (int)val->len - 1;
3699 while (end >= 0 && ((val->ptr[end] ==
' ') || (val->ptr[end] ==
'\t')))
3701 val->len = (size_t)(end + 1);
3703 if (val->len == 0) {
3708 if (eq_val != NULL) {
3712 eq_val->ptr = (
const char *)memchr(val->ptr,
'=', val->len);
3713 if (eq_val->ptr != NULL) {
3715 eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
3716 val->len = ((
size_t)(eq_val->ptr - val->ptr)) - 1;
3739 while ((header =
next_option(header, &opt_vec, &eq_vec)) != NULL) {
3756 if ((or_str = (
const char *)memchr(pattern,
'|', pattern_len)) != NULL) {
3757 res =
match_prefix(pattern, (
size_t)(or_str - pattern), str);
3759 (
size_t)((pattern + pattern_len)
3764 for (i = 0, j = 0; (i < pattern_len); i++, j++) {
3765 if ((pattern[i] ==
'?') && (str[j] !=
'\0')) {
3767 }
else if (pattern[i] ==
'$') {
3768 return (str[j] ==
'\0') ? j : -1;
3769 }
else if (pattern[i] ==
'*') {
3771 if (pattern[i] ==
'*') {
3773 len = (int)strlen(str + j);
3775 len = (int)strcspn(str + j,
"/");
3777 if (i == pattern_len) {
3781 res =
match_prefix(pattern + i, pattern_len - i, str + j + len);
3782 }
while (res == -1 && len-- > 0);
3783 return (res == -1) ? -1 : j + res + len;
3798 const char *http_version;
3802 if ((conn == NULL) || conn->must_close) {
3824 if (http_version && (0 == strcmp(http_version,
"1.1"))) {
3837 if (!conn || !conn->ctx) {
3857 "Cache-Control: no-cache, no-store, " 3858 "must-revalidate, private, max-age=0\r\n" 3859 "Pragma: no-cache\r\n" 3867 #if !defined(NO_CACHING) 3888 return mg_printf(conn,
"Cache-Control: max-age=%u\r\n", (
unsigned)max_age);
3901 #if !defined(NO_SSL) 3906 "Strict-Transport-Security: max-age=%u\r\n",
3912 if (header && header[0]) {
3922 struct mg_file *filep);
3932 switch (response_code) {
3937 return "Switching Protocols";
3939 return "Processing";
3949 return "Non-Authoritative Information";
3951 return "No Content";
3953 return "Reset Content";
3955 return "Partial Content";
3957 return "Multi-Status";
3960 return "Already Reported";
3967 return "Multiple Choices";
3969 return "Moved Permanently";
3975 return "Not Modified";
3979 return "Temporary Redirect";
3981 return "Permanent Redirect";
3985 return "Bad Request";
3987 return "Unauthorized";
3989 return "Payment Required";
3995 return "Method Not Allowed";
3997 return "Not Acceptable";
3999 return "Proxy Authentication Required";
4001 return "Request Time-out";
4007 return "Length Required";
4009 return "Precondition Failed";
4011 return "Request Entity Too Large";
4013 return "Request-URI Too Large";
4015 return "Unsupported Media Type";
4017 return "Requested range not satisfiable";
4020 return "Expectation Failed";
4023 return "Misdirected Request";
4025 return "Unproccessable entity";
4030 return "Failed Dependency";
4034 return "Upgrade Required";
4037 return "Precondition Required";
4039 return "Too Many Requests";
4042 return "Request Header Fields Too Large";
4045 return "Unavailable For Legal Reasons";
4050 return "Internal Server Error";
4052 return "Not Implemented";
4054 return "Bad Gateway";
4056 return "Service Unavailable";
4058 return "Gateway Time-out";
4060 return "HTTP Version not supported";
4062 return "Variant Also Negotiates";
4064 return "Insufficient Storage";
4067 return "Loop Detected";
4070 return "Not Extended";
4072 return "Network Authentication Required";
4078 return "I am a teapot";
4080 return "Authentication Timeout";
4082 return "Enhance Your Calm";
4084 return "Login Timeout";
4086 return "Bandwidth Limit Exceeded";
4091 mg_cry(conn,
"Unknown HTTP response code: %u", response_code);
4095 if (response_code >= 100 && response_code < 200) {
4097 return "Information";
4099 if (response_code >= 200 && response_code < 300) {
4103 if (response_code >= 300 && response_code < 400) {
4105 return "Redirection";
4107 if (response_code >= 400 && response_code < 500) {
4109 return "Client Error";
4111 if (response_code >= 500 && response_code < 600) {
4113 return "Server Error";
4127 int len, i, page_handler_found, scope, truncated, has_body;
4129 time_t curtime = time(NULL);
4130 const char *error_handler = NULL;
4132 const char *error_page_file_ext, *tstr;
4140 conn->status_code = status;
4141 if (conn->in_error_handler || (conn->ctx->callbacks.http_error == NULL)
4142 || conn->ctx->callbacks.http_error(conn, status)) {
4145 if (conn->in_error_handler) {
4147 "Recursion when handling error %u - fall back to default",
4152 error_page_file_ext = conn->ctx->config[
INDEX_FILES];
4153 page_handler_found = 0;
4155 if (error_handler != NULL) {
4156 for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
4193 len = (int)strlen(buf);
4195 tstr = strchr(error_page_file_ext,
'.');
4199 (i < 32) && (tstr[i] != 0) && (tstr[i] !=
',');
4201 buf[len + i - 1] = tstr[i];
4202 buf[len + i - 1] = 0;
4204 if (
mg_stat(conn, buf, &error_page_file.stat)) {
4206 page_handler_found = 1;
4209 DEBUG_TRACE(
"Check error page %s - not found", buf);
4211 tstr = strchr(tstr + i,
'.');
4216 if (page_handler_found) {
4217 conn->in_error_handler = 1;
4219 conn->in_error_handler = 0;
4228 has_body = ((status > 199) && (status != 204) && (status != 304));
4230 conn->must_close = 1;
4231 mg_printf(conn,
"HTTP/1.1 %d %s\r\n", status, status_text);
4237 "Content-Type: text/plain; charset=utf-8\r\n");
4241 "Connection: close\r\n\r\n",
4246 mg_printf(conn,
"Error %d: %s\n", status, status_text);
4263 #if defined(_WIN32) && !defined(__SYMBIAN32__) 4266 #if defined(__MINGW32__) 4268 #pragma GCC diagnostic push 4269 #pragma GCC diagnostic ignored "-Wunused-function" 4275 pthread_mutex_init(pthread_mutex_t *mutex,
void *unused)
4278 *mutex = CreateMutex(NULL,
FALSE, NULL);
4279 return (*mutex == NULL) ? -1 : 0;
4284 pthread_mutex_destroy(pthread_mutex_t *mutex)
4286 return (CloseHandle(*mutex) == 0) ? -1 : 0;
4292 pthread_mutex_lock(pthread_mutex_t *mutex)
4294 return (WaitForSingleObject(*mutex, (DWORD)INFINITE) == WAIT_OBJECT_0) ? 0
4299 #ifdef ENABLE_UNUSED_PTHREAD_FUNCTIONS 4302 pthread_mutex_trylock(pthread_mutex_t *mutex)
4304 switch (WaitForSingleObject(*mutex, 0)) {
4317 pthread_mutex_unlock(pthread_mutex_t *mutex)
4319 return (ReleaseMutex(*mutex) == 0) ? -1 : 0;
4328 InitializeCriticalSection(&cv->threadIdSec);
4329 cv->waiting_thread = NULL;
4337 pthread_mutex_t *mutex,
4338 const struct timespec *abstime)
4340 struct mg_workerTLS **ptls,
4341 *tls = (
struct mg_workerTLS *)pthread_getspecific(sTlsKey);
4343 int64_t nsnow, nswaitabs, nswaitrel;
4346 EnterCriticalSection(&cv->threadIdSec);
4348 ptls = &cv->waiting_thread;
4349 for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
4351 tls->next_waiting_thread = NULL;
4353 LeaveCriticalSection(&cv->threadIdSec);
4358 (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
4359 nswaitrel = nswaitabs - nsnow;
4360 if (nswaitrel < 0) {
4363 mswaitrel = (DWORD)(nswaitrel / 1000000);
4365 mswaitrel = (DWORD)INFINITE;
4368 pthread_mutex_unlock(mutex);
4370 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
4373 EnterCriticalSection(&cv->threadIdSec);
4374 ptls = &cv->waiting_thread;
4375 for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
4377 *ptls = tls->next_waiting_thread;
4382 LeaveCriticalSection(&cv->threadIdSec);
4384 WaitForSingleObject(tls->pthread_cond_helper_mutex,
4389 pthread_mutex_lock(mutex);
4399 return pthread_cond_timedwait(cv, mutex, NULL);
4410 EnterCriticalSection(&cv->threadIdSec);
4411 if (cv->waiting_thread) {
4412 wkup = cv->waiting_thread->pthread_cond_helper_mutex;
4413 cv->waiting_thread = cv->waiting_thread->next_waiting_thread;
4415 ok = SetEvent(wkup);
4418 LeaveCriticalSection(&cv->threadIdSec);
4428 EnterCriticalSection(&cv->threadIdSec);
4429 while (cv->waiting_thread) {
4430 pthread_cond_signal(cv);
4432 LeaveCriticalSection(&cv->threadIdSec);
4442 EnterCriticalSection(&cv->threadIdSec);
4443 assert(cv->waiting_thread == NULL);
4444 LeaveCriticalSection(&cv->threadIdSec);
4445 DeleteCriticalSection(&cv->threadIdSec);
4451 #ifdef ALTERNATIVE_QUEUE 4456 return (
void *)CreateEvent(NULL,
FALSE,
FALSE, NULL);
4464 int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE);
4465 return (res == WAIT_OBJECT_0);
4473 return (
int)SetEvent((HANDLE)eventhdl);
4481 CloseHandle((HANDLE)eventhdl);
4486 #if defined(__MINGW32__) 4488 #pragma GCC diagnostic pop 4494 change_slashes_to_backslashes(
char *path)
4498 for (i = 0; path[i] !=
'\0'; i++) {
4499 if (path[i] ==
'/') {
4505 if ((path[i] ==
'\\') && (i > 0)) {
4506 while ((path[i + 1] ==
'\\') || (path[i + 1] ==
'/')) {
4507 (
void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
4515 mg_wcscasecmp(
const wchar_t *
s1,
const wchar_t *s2)
4520 diff = tolower(*s1) - tolower(*s2);
4523 }
while ((diff == 0) && (s1[-1] !=
'\0'));
4532 path_to_unicode(
const struct mg_connection *conn,
4537 char buf[PATH_MAX], buf2[PATH_MAX];
4538 wchar_t wbuf2[MAX_PATH + 1];
4539 DWORD long_len, err;
4540 int (*fcompare)(
const wchar_t *,
const wchar_t *) = mg_wcscasecmp;
4543 change_slashes_to_backslashes(buf);
4547 memset(wbuf, 0, wbuf_len *
sizeof(
wchar_t));
4548 MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (
int)wbuf_len);
4549 WideCharToMultiByte(
4550 CP_UTF8, 0, wbuf, (
int)wbuf_len, buf2,
sizeof(buf2), NULL, NULL);
4551 if (strcmp(buf, buf2) != 0) {
4565 if (conn->ctx->config[CASE_SENSITIVE_FILES]
4566 && !
mg_strcasecmp(conn->ctx->config[CASE_SENSITIVE_FILES],
"yes")) {
4573 #if !defined(_WIN32_WCE) 4575 memset(wbuf2, 0,
ARRAY_SIZE(wbuf2) *
sizeof(
wchar_t));
4576 long_len = GetLongPathNameW(wbuf, wbuf2,
ARRAY_SIZE(wbuf2) - 1);
4577 if (long_len == 0) {
4578 err = GetLastError();
4579 if (err == ERROR_FILE_NOT_FOUND) {
4584 if ((long_len >=
ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
4593 if (strchr(path,
'~')) {
4605 path_cannot_disclose_cgi(
const char *path)
4607 static const char *allowed_last_characters =
"_-";
4608 int last = path[strlen(path) - 1];
4609 return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
4614 mg_stat(
const struct mg_connection *conn,
4616 struct mg_file_stat *filep)
4618 wchar_t wbuf[PATH_MAX];
4619 WIN32_FILE_ATTRIBUTE_DATA info;
4620 time_t creation_time;
4625 memset(filep, 0,
sizeof(*filep));
4635 filep->size = tmp_file.stat.size;
4636 filep->location = 2;
4644 filep->last_modified = time(NULL);
4656 path_to_unicode(conn, path, wbuf,
ARRAY_SIZE(wbuf));
4657 if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
4658 filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
4659 filep->last_modified =
4660 SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
4661 info.ftLastWriteTime.dwHighDateTime);
4667 creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
4668 info.ftCreationTime.dwHighDateTime);
4669 if (creation_time > filep->last_modified) {
4670 filep->last_modified = creation_time;
4673 filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4678 if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
4679 memset(filep, 0,
sizeof(*filep));
4691 mg_remove(
const struct mg_connection *conn,
const char *path)
4693 wchar_t wbuf[PATH_MAX];
4694 path_to_unicode(conn, path, wbuf,
ARRAY_SIZE(wbuf));
4695 return DeleteFileW(wbuf) ? 0 : -1;
4700 mg_mkdir(
const struct mg_connection *conn,
const char *path,
int mode)
4702 wchar_t wbuf[PATH_MAX];
4704 path_to_unicode(conn, path, wbuf,
ARRAY_SIZE(wbuf));
4705 return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
4711 #if defined(__MINGW32__) 4713 #pragma GCC diagnostic push 4714 #pragma GCC diagnostic ignored "-Wunused-function" 4721 mg_opendir(
const struct mg_connection *conn,
const char *name)
4724 wchar_t wpath[PATH_MAX];
4728 SetLastError(ERROR_BAD_ARGUMENTS);
4729 }
else if ((dir = (DIR *)
mg_malloc(
sizeof(*dir))) == NULL) {
4730 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4732 path_to_unicode(conn, name, wpath,
ARRAY_SIZE(wpath));
4733 attrs = GetFileAttributesW(wpath);
4734 if (attrs != 0xFFFFFFFF && ((attrs & FILE_ATTRIBUTE_DIRECTORY)
4735 == FILE_ATTRIBUTE_DIRECTORY)) {
4736 (
void)wcscat(wpath,
L"\\*");
4737 dir->handle = FindFirstFileW(wpath, &dir->info);
4738 dir->result.d_name[0] =
'\0';
4757 result = FindClose(dir->handle) ? 0 : -1;
4762 SetLastError(ERROR_BAD_ARGUMENTS);
4770 static struct dirent *
4773 struct dirent *result = 0;
4777 result = &dir->result;
4778 (
void)WideCharToMultiByte(CP_UTF8,
4780 dir->info.cFileName,
4783 sizeof(result->d_name),
4787 if (!FindNextFileW(dir->handle, &dir->info)) {
4788 (
void)FindClose(dir->handle);
4793 SetLastError(ERROR_FILE_NOT_FOUND);
4796 SetLastError(ERROR_BAD_ARGUMENTS);
4806 poll(
struct pollfd *pfd,
unsigned int n,
int milliseconds)
4814 memset(&tv, 0,
sizeof(tv));
4815 tv.tv_sec = milliseconds / 1000;
4816 tv.tv_usec = (milliseconds % 1000) * 1000;
4819 for (i = 0; i <
n; i++) {
4820 FD_SET((SOCKET)pfd[i].fd, &
set);
4823 if (pfd[i].fd > maxfd) {
4828 if ((result = select((
int)maxfd + 1, &
set, NULL, NULL, &tv)) > 0) {
4829 for (i = 0; i <
n; i++) {
4830 if (FD_ISSET(pfd[i].fd, &
set)) {
4831 pfd[i].revents = POLLIN;
4848 #if defined(__MINGW32__) 4850 #pragma GCC diagnostic pop 4858 #if defined(_WIN32_WCE) 4861 (
void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
4869 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) 4873 return ((_beginthread((
void(__cdecl *)(
void *))f, USE_STACK_SIZE, p)
4874 == ((uintptr_t)(-1
L)))
4879 (_beginthread((
void(__cdecl *)(
void *))f, 0, p) == ((uintptr_t)(-1
L)))
4890 pthread_t *threadidptr)
4893 HANDLE threadhandle;
4896 uip = _beginthreadex(NULL, 0, (
unsigned(__stdcall *)(
void *))f, p, 0, NULL);
4897 threadhandle = (HANDLE)uip;
4898 if ((uip != (uintptr_t)(-1
L)) && (threadidptr != NULL)) {
4899 *threadidptr = threadhandle;
4915 dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE);
4916 if (dwevent == WAIT_FAILED) {
4919 if (dwevent == WAIT_OBJECT_0) {
4920 CloseHandle(threadid);
4928 #if !defined(NO_SSL_DL) && !defined(NO_SSL) 4932 #if defined(__MINGW32__) 4934 #pragma GCC diagnostic push 4935 #pragma GCC diagnostic ignored "-Wunused-function" 4941 dlopen(
const char *dll_name,
int flags)
4943 wchar_t wbuf[PATH_MAX];
4945 path_to_unicode(NULL, dll_name, wbuf,
ARRAY_SIZE(wbuf));
4946 return LoadLibraryW(wbuf);
4952 dlclose(
void *handle)
4956 if (FreeLibrary((HMODULE)handle) != 0) {
4966 #if defined(__MINGW32__) 4968 #pragma GCC diagnostic pop 4974 #if !defined(NO_CGI) 4978 kill(pid_t pid,
int sig_num)
4980 (
void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
4981 (
void)CloseHandle((HANDLE)pid);
4987 trim_trailing_whitespaces(
char *
s)
4989 char *
e = s + strlen(s) - 1;
4990 while ((e > s) && isspace(*(
unsigned char *)e)) {
5007 char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
5008 cmdline[PATH_MAX], buf[PATH_MAX];
5012 PROCESS_INFORMATION
pi = {0};
5016 memset(&si, 0,
sizeof(si));
5019 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
5020 si.wShowWindow = SW_HIDE;
5022 me = GetCurrentProcess();
5024 (HANDLE)_get_osfhandle(fdin[0]),
5029 DUPLICATE_SAME_ACCESS);
5031 (HANDLE)_get_osfhandle(fdout[1]),
5036 DUPLICATE_SAME_ACCESS);
5038 (HANDLE)_get_osfhandle(fderr[1]),
5043 DUPLICATE_SAME_ACCESS);
5048 SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
5049 HANDLE_FLAG_INHERIT,
5051 SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
5052 HANDLE_FLAG_INHERIT,
5054 SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
5055 HANDLE_FLAG_INHERIT,
5060 if (interp == NULL) {
5061 buf[0] = buf[1] =
'\0';
5065 conn, &truncated, cmdline,
sizeof(cmdline),
"%s/%s", dir, prog);
5068 pi.hProcess = (pid_t)-1;
5073 p = (
char *)file.access.membuf;
5074 mg_fgets(buf,
sizeof(buf), &file, &p);
5076 buf[
sizeof(buf) - 1] =
'\0';
5079 if ((buf[0] ==
'#') && (buf[1] ==
'!')) {
5080 trim_trailing_whitespaces(buf + 2);
5087 if (interp[0] !=
'\0') {
5088 GetFullPathNameA(interp,
sizeof(full_interp), full_interp, NULL);
5089 interp = full_interp;
5091 GetFullPathNameA(dir,
sizeof(full_dir), full_dir, NULL);
5093 if (interp[0] !=
'\0') {
5098 "\"%s\" \"%s\\%s\"",
5113 pi.hProcess = (pid_t)-1;
5118 if (CreateProcessA(NULL,
5123 CREATE_NEW_PROCESS_GROUP,
5129 conn,
"%s: CreateProcess(%s): %ld", __func__, cmdline, (
long)
ERRNO);
5130 pi.hProcess = (pid_t)-1;
5135 (
void)CloseHandle(si.hStdOutput);
5136 (
void)CloseHandle(si.hStdError);
5137 (
void)CloseHandle(si.hStdInput);
5138 if (pi.hThread != NULL) {
5139 (
void)CloseHandle(pi.hThread);
5142 return (pid_t)pi.hProcess;
5150 unsigned long non_blocking = 0;
5151 return ioctlsocket(sock, (
long)FIONBIO, &non_blocking);
5157 unsigned long non_blocking = 1;
5158 return ioctlsocket(sock, (
long)FIONBIO, &non_blocking);
5165 struct mg_file_stat *filep)
5171 memset(filep, 0,
sizeof(*filep));
5179 filep->size = tmp_file.stat.size;
5180 filep->last_modified = time(NULL);
5181 filep->location = 2;
5187 if (0 == stat(path, &st)) {
5188 filep->size = (uint64_t)(st.st_size);
5189 filep->last_modified = st.st_mtime;
5190 filep->is_directory = S_ISDIR(st.st_mode);
5201 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
5204 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
5215 pthread_t thread_id;
5216 pthread_attr_t attr;
5219 (
void)pthread_attr_init(&attr);
5220 (
void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5222 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) 5225 (
void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5228 result = pthread_create(&thread_id, &attr, func, param);
5229 pthread_attr_destroy(&attr);
5239 pthread_t *threadidptr)
5241 pthread_t thread_id;
5242 pthread_attr_t attr;
5245 (
void)pthread_attr_init(&attr);
5247 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) 5250 (
void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5253 result = pthread_create(&thread_id, &attr, func, param);
5254 pthread_attr_destroy(&attr);
5255 if ((result == 0) && (threadidptr != NULL)) {
5256 *threadidptr = thread_id;
5268 result = pthread_join(threadid, NULL);
5293 if ((pid = fork()) == -1) {
5297 "Error: Creating CGI process\nfork(): %s",
5299 }
else if (pid == 0) {
5301 if (chdir(dir) != 0) {
5302 mg_cry(conn,
"%s: chdir(%s): %s", __func__, dir, strerror(
ERRNO));
5303 }
else if (dup2(fdin[0], 0) == -1) {
5305 "%s: dup2(%d, 0): %s",
5309 }
else if (dup2(fdout[1], 1) == -1) {
5311 "%s: dup2(%d, 1): %s",
5315 }
else if (dup2(fderr[1], 2) == -1) {
5317 "%s: dup2(%d, 2): %s",
5339 signal(SIGCHLD, SIG_DFL);
5342 if (interp == NULL) {
5343 (
void)execle(prog, prog, NULL, envp);
5345 "%s: execle(%s): %s",
5350 (
void)execle(interp, interp, prog, NULL, envp);
5352 "%s: execle(%s %s): %s",
5370 int flags = fcntl(sock, F_GETFL, 0);
5375 if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) {
5384 int flags = fcntl(sock, F_GETFL, 0);
5389 if (fcntl(sock, F_SETFL, flags & (~(
int)(O_NONBLOCK))) < 0) {
5403 static uint64_t lfsr = 0;
5404 static uint64_t lcg = 0;
5415 | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
5417 lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
5425 return (lfsr ^ lcg ^ now);
5433 volatile int *stop_server)
5448 if ((milliseconds >= 0) && (milliseconds < ms_now)) {
5449 ms_now = milliseconds;
5452 result = poll(pfd, n, ms_now);
5460 if (milliseconds > 0) {
5461 milliseconds -= ms_now;
5464 }
while (milliseconds != 0);
5487 uint64_t start = 0, now = 0, timeout_ns = 0;
5494 typedef size_t len_t;
5500 timeout_ns = (uint64_t)(timeout * 1.0E9);
5537 n = (int)fwrite(buf, 1, (
size_t)len, fp);
5546 err = (n < 0) ?
ERRNO : 0;
5548 if (err == WSAEWOULDBLOCK) {
5553 if (err == EWOULDBLOCK) {
5564 if (ctx->stop_flag) {
5568 if ((n > 0) || ((n == 0) && (len == 0))) {
5591 mg_sleep(ms_wait > 10 ? 10 : ms_wait);
5598 #if defined(__GNUC__) || defined(__MINGW32__) 5602 #pragma GCC diagnostic push 5603 #pragma GCC diagnostic ignored "-Wsign-conversion" 5607 FD_SET(sock, &wfds);
5608 tv.tv_sec = (time_t)(ms_wait / 1000);
5609 tv.tv_usec = (long)((ms_wait % 1000) * 1000);
5611 sret = select((
int)sock + 1, NULL, &wfds, NULL, &tv);
5613 #if defined(__GNUC__) || defined(__MINGW32__) 5614 #pragma GCC diagnostic pop 5626 if ((now - start) > timeout_ns) {
5648 double timeout = -1.0;
5649 int64_t
n, nwritten = 0;
5659 while ((len > 0) && (ctx->stop_flag == 0)) {
5660 n =
push_inner(ctx, fp, sock, ssl, buf + nwritten, (
int)len, timeout);
5662 if (nwritten == 0) {
5666 }
else if (n == 0) {
5686 struct mg_connection *conn,
5696 typedef size_t len_t;
5708 #if !defined(_WIN32_WCE) 5713 nread = (int)read(fileno(fp), buf, (size_t)len);
5716 nread = (int)fread(buf, 1, (
size_t)len, fp);
5718 err = (nread < 0) ?
ERRNO : 0;
5719 if ((nread == 0) && (len > 0)) {
5725 }
else if ((conn->ssl != NULL)
5726 && ((ssl_pending =
SSL_pending(conn->ssl)) > 0)) {
5730 if (ssl_pending > len) {
5733 nread =
SSL_read(conn->ssl, buf, ssl_pending);
5749 }
else if (conn->ssl != NULL) {
5751 struct pollfd pfd[1];
5754 pfd[0].fd = conn->client.sock;
5755 pfd[0].events = POLLIN;
5757 mg_poll(pfd, 1, (
int)(timeout * 1000.0), &(conn->ctx->stop_flag));
5758 if (conn->ctx->stop_flag) {
5762 nread =
SSL_read(conn->ssl, buf, len);
5778 }
else if (pollres < 0) {
5788 struct pollfd pfd[1];
5791 pfd[0].fd = conn->client.sock;
5792 pfd[0].events = POLLIN;
5794 mg_poll(pfd, 1, (
int)(timeout * 1000.0), &(conn->ctx->stop_flag));
5795 if (conn->ctx->stop_flag) {
5799 nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
5800 err = (nread < 0) ?
ERRNO : 0;
5805 }
else if (pollres < 0) {
5814 if (conn->ctx->stop_flag) {
5818 if ((nread > 0) || ((nread == 0) && (len == 0))) {
5826 if (err == WSAEWOULDBLOCK) {
5830 }
else if (err == WSAETIMEDOUT) {
5834 }
else if (err == WSAECONNABORTED) {
5847 if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == EINTR)) {
5872 pull_all(FILE *fp,
struct mg_connection *conn,
char *buf,
int len)
5875 double timeout = -1.0;
5876 uint64_t start_time = 0, now = 0, timeout_ns = 0;
5881 if (timeout >= 0.0) {
5883 timeout_ns = (uint64_t)(timeout * 1.0E9);
5886 while ((len > 0) && (conn->ctx->stop_flag == 0)) {
5887 n =
pull_inner(fp, conn, buf + nread, len, timeout);
5893 }
else if (n == -1) {
5895 if (timeout >= 0.0) {
5897 if ((now - start_time) <= timeout_ns) {
5902 }
else if (n == 0) {
5905 conn->consumed_content +=
n;
5926 to_read =
sizeof(buf);
5928 if (conn->is_chunked) {
5931 while (conn->is_chunked != 3) {
5932 nread =
mg_read(conn, buf, to_read);
5940 while (conn->consumed_content < conn->content_len) {
5942 > (
size_t)(conn->content_len - conn->consumed_content)) {
5943 to_read = (size_t)(conn->content_len - conn->consumed_content);
5946 nread =
mg_read(conn, buf, to_read);
5958 int64_t
n, buffered_len, nread;
5960 (int64_t)((len > INT_MAX) ? INT_MAX : len);
5972 if (conn->consumed_content == 0) {
5973 if (conn->is_chunked == 1) {
5974 conn->content_len = len64;
5975 conn->is_chunked = 2;
5976 }
else if (conn->content_len == -1) {
5980 conn->must_close = 1;
5985 if (conn->consumed_content < conn->content_len) {
5987 int64_t left_to_read = conn->content_len - conn->consumed_content;
5988 if (left_to_read < len64) {
5992 len64 = left_to_read;
5996 buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
5997 - conn->consumed_content;
5998 if (buffered_len > 0) {
5999 if (len64 < buffered_len) {
6000 buffered_len = len64;
6002 body = conn->buf + conn->request_len + conn->consumed_content;
6003 memcpy(buf, body, (
size_t)buffered_len);
6004 len64 -= buffered_len;
6005 conn->consumed_content += buffered_len;
6006 nread += buffered_len;
6007 buf = (
char *)buf + buffered_len;
6013 if ((n =
pull_all(NULL, conn, (
char *)buf, (
int)len64)) >= 0) {
6016 nread = ((nread > 0) ? nread : n);
6038 mg_read(
struct mg_connection *conn,
void *buf,
size_t len)
6040 if (len > INT_MAX) {
6048 if (conn->is_chunked) {
6049 size_t all_read = 0;
6052 if (conn->is_chunked == 3) {
6057 if (conn->chunk_remainder) {
6061 ((conn->chunk_remainder > len) ? (len)
6062 : (conn->chunk_remainder));
6064 conn->content_len += (int)read_now;
6073 all_read += (size_t)read_ret;
6074 conn->chunk_remainder -= (size_t)read_ret;
6075 len -= (size_t)read_ret;
6077 if (conn->chunk_remainder == 0) {
6081 conn->content_len += 2;
6084 if ((x1 !=
'\r') || (x2 !=
'\n')) {
6095 unsigned long chunkSize = 0;
6097 for (i = 0; i < ((int)
sizeof(lenbuf) - 1); i++) {
6098 conn->content_len++;
6100 if ((i > 0) && (lenbuf[i] ==
'\r')
6101 && (lenbuf[i - 1] !=
'\r')) {
6104 if ((i > 1) && (lenbuf[i] ==
'\n')
6105 && (lenbuf[i - 1] ==
'\r')) {
6107 chunkSize = strtoul(lenbuf, &end, 16);
6108 if (chunkSize == 0) {
6110 conn->is_chunked = 3;
6114 if (!isxdigit(lenbuf[i])) {
6119 if ((end == NULL) || (*end !=
'\r')) {
6123 if (chunkSize == 0) {
6127 conn->chunk_remainder = chunkSize;
6131 return (
int)all_read;
6138 mg_write(
struct mg_connection *conn,
const void *buf,
size_t len)
6141 int64_t
n,
total, allowed;
6147 if (conn->throttle > 0) {
6148 if ((now = time(NULL)) != conn->last_throttle_time) {
6149 conn->last_throttle_time = now;
6150 conn->last_throttle_bytes = 0;
6152 allowed = conn->throttle - conn->last_throttle_bytes;
6153 if (allowed > (int64_t)len) {
6154 allowed = (int64_t)len;
6161 (int64_t)allowed)) == allowed) {
6162 buf = (
const char *)buf + total;
6163 conn->last_throttle_bytes +=
total;
6164 while ((total < (int64_t)len) && (conn->ctx->stop_flag == 0)) {
6165 allowed = (conn->throttle > ((int64_t)len - total))
6166 ? (int64_t)len -
total 6173 (int64_t)allowed)) != allowed) {
6177 conn->last_throttle_bytes = allowed;
6178 conn->last_throttle_time = time(NULL);
6179 buf = (
const char *)buf + n;
6192 conn->num_bytes_sent +=
total;
6202 unsigned int chunk_len)
6210 sprintf(lenbuf,
"%x\r\n", chunk_len);
6211 lenbuf_len = strlen(lenbuf);
6214 ret =
mg_write(conn, lenbuf, lenbuf_len);
6215 if (ret != (
int)lenbuf_len) {
6220 ret =
mg_write(conn, chunk, chunk_len);
6221 if (ret != (
int)chunk_len) {
6259 (*buf)[size - 1] = 0;
6273 size_t prealloc_size,
6299 }
else if ((
size_t)(len) >= prealloc_size) {
6302 *out_buf = (
char *)
mg_malloc((
size_t)(len) + 1);
6320 *out_buf = prealloc_buf;
6328 mg_vprintf(
struct mg_connection *conn,
const char *fmt, va_list ap)
6334 if ((len =
alloc_vprintf(&buf, mem,
sizeof(mem), fmt, ap)) > 0) {
6335 len =
mg_write(conn, buf, (
size_t)len);
6337 if ((buf != mem) && (buf != NULL)) {
6364 int is_form_url_encoded)
6367 #define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W')) 6369 for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
6370 if ((i < src_len - 2) && (src[i] ==
'%')
6371 && isxdigit(*(
const unsigned char *)(src + i + 1))
6372 && isxdigit(*(
const unsigned char *)(src + i + 2))) {
6373 a = tolower(*(
const unsigned char *)(src + i + 1));
6374 b = tolower(*(
const unsigned char *)(src + i + 2));
6377 }
else if (is_form_url_encoded && (src[i] ==
'+')) {
6386 return (i >= src_len) ? j : -1;
6397 return mg_get_var2(data, data_len, name, dst, dst_len, 0);
6409 const char *p, *
e, *
s;
6413 if ((dst == NULL) || (dst_len == 0)) {
6415 }
else if ((data == NULL) || (name == NULL) || (data_len == 0)) {
6419 name_len = strlen(name);
6420 e = data + data_len;
6425 for (p = data; p + name_len <
e; p++) {
6426 if (((p == data) || (p[-1] ==
'&')) && (p[name_len] ==
'=')
6432 s = (
const char *)memchr(p,
'&', (
size_t)(e - p));
6461 const char *var_name,
6465 const char *
s, *p, *end;
6466 int name_len, len = -1;
6468 if ((dst == NULL) || (dst_size == 0)) {
6473 if ((var_name == NULL) || ((s = cookie_header) == NULL)) {
6477 name_len = (int)strlen(var_name);
6478 end = s + strlen(s);
6479 for (; (s =
mg_strcasestr(s, var_name)) != NULL; s += name_len) {
6480 if (s[name_len] ==
'=') {
6482 if ((s == cookie_header) || (s[-1] ==
' ')) {
6484 if ((p = strchr(s,
' ')) == NULL) {
6490 if ((*s ==
'"') && (p[-1] ==
'"') && (p > s + 1)) {
6494 if ((
size_t)(p -
s) < dst_size) {
6508 #if defined(USE_WEBSOCKET) || defined(USE_LUA) 6510 base64_encode(
const unsigned char *src,
int src_len,
char *dst)
6512 static const char *b64 =
6513 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6516 for (i = j = 0; i < src_len; i += 3) {
6518 b = ((i + 1) >= src_len) ? 0 : src[i + 1];
6519 c = ((i + 2) >= src_len) ? 0 : src[i + 2];
6521 dst[j++] = b64[a >> 2];
6522 dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
6523 if (i + 1 < src_len) {
6524 dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
6526 if (i + 2 < src_len) {
6527 dst[j++] = b64[c & 63];
6530 while (j % 4 != 0) {
6538 #if defined(USE_LUA) 6539 static unsigned char 6540 b64reverse(
char letter)
6542 if ((letter >=
'A') && (letter <=
'Z')) {
6543 return letter -
'A';
6545 if ((letter >=
'a') && (letter <=
'z')) {
6546 return letter -
'a' + 26;
6548 if ((letter >=
'0') && (letter <=
'9')) {
6549 return letter -
'0' + 52;
6551 if (letter ==
'+') {
6554 if (letter ==
'/') {
6557 if (letter ==
'=') {
6565 base64_decode(
const unsigned char *src,
int src_len,
char *dst,
size_t *dst_len)
6568 unsigned char a,
b,
c,
d;
6572 for (i = 0; i < src_len; i += 4) {
6573 a = b64reverse(src[i]);
6578 b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]);
6583 c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]);
6588 d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]);
6593 dst[(*dst_len)++] = (a << 2) + (b >> 4);
6595 dst[(*dst_len)++] = (b << 4) + (c >> 2);
6597 dst[(*dst_len)++] = (c << 6) + d;
6610 const char *s = conn->request_info.request_method;
6611 return (s != NULL) && (!strcmp(s,
"PUT") || !strcmp(s,
"DELETE")
6612 || !strcmp(s,
"MKCOL") || !strcmp(s,
"PATCH"));
6618 #if !defined(NO_FILES) 6621 struct mg_connection *conn,
6622 const char *filename
6625 #if !defined(NO_CGI) 6632 #if defined(USE_LUA) 6633 if (
match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
6634 strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
6639 #if defined(USE_DUKTAPE) 6640 if (
match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
6641 strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
6662 struct mg_file_stat *filestat)
6664 const char *list = conn->ctx->config[
INDEX_FILES];
6665 struct vec filename_vec;
6666 size_t n = strlen(path);
6672 while ((n > 0) && (path[n - 1] ==
'/')) {
6679 while ((list =
next_option(list, &filename_vec, NULL)) != NULL) {
6681 if (filename_vec.len > (path_len - (n + 2))) {
6686 mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
6689 if (
mg_stat(conn, path, filestat)) {
6709 size_t filename_buf_len,
6710 struct mg_file_stat *filestat,
6712 int *is_script_resource,
6713 int *is_websocket_request,
6714 int *is_put_or_delete_request
6717 char const *accept_encoding;
6719 #if !defined(NO_FILES) 6720 const char *uri = conn->request_info.local_uri;
6722 const char *rewrite;
6725 char gz_path[PATH_MAX];
6727 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) 6729 size_t tmp_str_len, sep_pos;
6730 int allow_substitute_script_subresources;
6733 (
void)filename_buf_len;
6737 memset(filestat, 0,
sizeof(*filestat));
6740 *is_script_resource = 0;
6747 #if defined(USE_WEBSOCKET) 6749 #if !defined(NO_FILES) 6750 if (*is_websocket_request && conn->ctx->config[WEBSOCKET_ROOT]) {
6751 root = conn->ctx->config[WEBSOCKET_ROOT];
6755 *is_websocket_request = 0;
6759 conn->accept_gzip = 0;
6760 if ((accept_encoding =
mg_get_header(conn,
"Accept-Encoding")) != NULL) {
6761 if (strstr(accept_encoding,
"gzip") != NULL) {
6762 conn->accept_gzip = 1;
6766 #if !defined(NO_FILES) 6782 conn, &truncated, filename, filename_buf_len - 1,
"%s%s", root, uri);
6785 goto interpret_cleanup;
6790 while ((rewrite =
next_option(rewrite, &a, &b)) != NULL) {
6791 if ((match_len =
match_prefix(a.ptr, a.len, uri)) > 0) {
6795 filename_buf_len - 1,
6805 goto interpret_cleanup;
6811 if (
mg_stat(conn, filename, filestat)) {
6828 *is_script_resource = (!*is_put_or_delete_request);
6833 if (filestat->is_directory) {
6836 struct mg_file_stat tmp_filestat;
6837 memset(&tmp_filestat, 0,
sizeof(tmp_filestat));
6840 conn, filename, filename_buf_len, &tmp_filestat)) {
6844 *filestat = tmp_filestat;
6848 *is_script_resource = 1;
6851 *is_script_resource = 0;
6852 *is_found = (
mg_stat(conn, filename, filestat) ? 1 : 0);