Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
civetweb.c
Go to the documentation of this file.
1/* Copyright (c) 2013-2018 the Civetweb developers
2 * Copyright (c) 2004-2013 Sergey Lyubka
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#if defined(__GNUC__) || defined(__MINGW32__)
24#define GCC_VERSION \
25 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
26#if GCC_VERSION >= 40500
27/* gcc diagnostic pragmas available */
28#define GCC_DIAGNOSTIC
29#endif
30#endif
31
32#if defined(GCC_DIAGNOSTIC)
33/* Disable unused macros warnings - not all defines are required
34 * for all systems and all compilers. */
35#pragma GCC diagnostic ignored "-Wunused-macros"
36/* A padding warning is just plain useless */
37#pragma GCC diagnostic ignored "-Wpadded"
38#endif
39
40#if defined(__clang__) /* GCC does not (yet) support this pragma */
41/* We must set some flags for the headers we include. These flags
42 * are reserved ids according to C99, so we need to disable a
43 * warning for that. */
44#pragma GCC diagnostic push
45#pragma GCC diagnostic ignored "-Wreserved-id-macro"
46#endif
47
48#if defined(_WIN32)
49#if !defined(_CRT_SECURE_NO_WARNINGS)
50#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
51#endif
52#if !defined(_WIN32_WINNT) /* defined for tdm-gcc so we can use getnameinfo */
53#define _WIN32_WINNT 0x0501
54#endif
55#else
56#if !defined(_GNU_SOURCE)
57#define _GNU_SOURCE /* for setgroups(), pthread_setname_np() */
58#endif
59#if defined(__linux__) && !defined(_XOPEN_SOURCE)
60#define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
61#endif
62#if !defined(_LARGEFILE_SOURCE)
63#define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
64#endif
65#if !defined(_FILE_OFFSET_BITS)
66#define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
67#endif
68#if !defined(__STDC_FORMAT_MACROS)
69#define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
70#endif
71#if !defined(__STDC_LIMIT_MACROS)
72#define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
73#endif
74#if !defined(_DARWIN_UNLIMITED_SELECT)
75#define _DARWIN_UNLIMITED_SELECT
76#endif
77#if defined(__sun)
78#define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
79#define __inline inline /* not recognized on older compiler versions */
80#endif
81#endif
82
83#if defined(__clang__)
84/* Enable reserved-id-macro warning again. */
85#pragma GCC diagnostic pop
86#endif
87
88
89#if defined(USE_LUA)
90#define USE_TIMERS
91#endif
92
93#if defined(_MSC_VER)
94/* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
95#pragma warning(disable : 4306)
96/* conditional expression is constant: introduced by FD_SET(..) */
97#pragma warning(disable : 4127)
98/* non-constant aggregate initializer: issued due to missing C99 support */
99#pragma warning(disable : 4204)
100/* padding added after data member */
101#pragma warning(disable : 4820)
102/* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
103#pragma warning(disable : 4668)
104/* no function prototype given: converting '()' to '(void)' */
105#pragma warning(disable : 4255)
106/* function has been selected for automatic inline expansion */
107#pragma warning(disable : 4711)
108#endif
109
110
111/* This code uses static_assert to check some conditions.
112 * Unfortunately some compilers still do not support it, so we have a
113 * replacement function here. */
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
118#else
120#define mg_static_assert(cond, txt) \
121 extern char static_assert_replacement[(cond) ? 1 : -1]
122#endif
123
124mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
125 "int data type size check");
126mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
127 "pointer data type size check");
128mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
129
130
131/* Alternative queue is well tested and should be the new default */
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"
135#endif
136#else
137#define ALTERNATIVE_QUEUE
138#endif
139
140
141/* DTL -- including winsock2.h works better if lean and mean */
142#if !defined(WIN32_LEAN_AND_MEAN)
143#define WIN32_LEAN_AND_MEAN
144#endif
145
146#if defined(__SYMBIAN32__)
147/* According to https://en.wikipedia.org/wiki/Symbian#History,
148 * Symbian is no longer maintained since 2014-01-01.
149 * Recent versions of CivetWeb are no longer tested for Symbian.
150 * It makes no sense, to support an abandoned operating system.
151 */
152#error "Symbian is no longer maintained. CivetWeb no longer supports Symbian."
153#define NO_SSL /* SSL is not supported */
154#define NO_CGI /* CGI is not supported */
155#define PATH_MAX FILENAME_MAX
156#endif /* __SYMBIAN32__ */
157
158
159#if !defined(CIVETWEB_HEADER_INCLUDED)
160/* Include the header file here, so the CivetWeb interface is defined for the
161 * entire implementation, including the following forward definitions. */
162#include "civetweb.h"
163#endif
164
165#if !defined(DEBUG_TRACE)
166#if defined(DEBUG)
167static void DEBUG_TRACE_FUNC(const char *func,
168 unsigned line,
169 PRINTF_FORMAT_STRING(const char *fmt),
170 ...) PRINTF_ARGS(3, 4);
171
172#define DEBUG_TRACE(fmt, ...) \
173 DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
174
175#define NEED_DEBUG_TRACE_FUNC
176
177#else
178#define DEBUG_TRACE(fmt, ...) \
179 do { \
180 } while (0)
181#endif /* DEBUG */
182#endif /* DEBUG_TRACE */
183
184
185#if !defined(DEBUG_ASSERT)
186#if defined(DEBUG)
187#define DEBUG_ASSERT(cond) \
188 do { \
189 if (!(cond)) { \
190 DEBUG_TRACE("ASSERTION FAILED: %s", #cond); \
191 exit(2); /* Exit with error */ \
192 } \
193 } while (0)
194#else
195#define DEBUG_ASSERT(cond)
196#endif /* DEBUG */
197#endif
198
199
200#if defined(__GNUC__) && defined(GCC_INSTRUMENTATION)
201void __cyg_profile_func_enter(void *this_fn, void *call_site)
202 __attribute__((no_instrument_function));
203
204void __cyg_profile_func_exit(void *this_fn, void *call_site)
205 __attribute__((no_instrument_function));
206
207void
208__cyg_profile_func_enter(void *this_fn, void *call_site)
209{
210 if ((void *)this_fn != (void *)printf) {
211 printf("E %p %p\n", this_fn, call_site);
212 }
213}
214
215void
216__cyg_profile_func_exit(void *this_fn, void *call_site)
217{
218 if ((void *)this_fn != (void *)printf) {
219 printf("X %p %p\n", this_fn, call_site);
220 }
221}
222#endif
223
224
225#if !defined(IGNORE_UNUSED_RESULT)
226#define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
227#endif
228
229
230#if defined(__GNUC__) || defined(__MINGW32__)
231
232/* GCC unused function attribute seems fundamentally broken.
233 * Several attempts to tell the compiler "THIS FUNCTION MAY BE USED
234 * OR UNUSED" for individual functions failed.
235 * Either the compiler creates an "unused-function" warning if a
236 * function is not marked with __attribute__((unused)).
237 * On the other hand, if the function is marked with this attribute,
238 * but is used, the compiler raises a completely idiotic
239 * "used-but-marked-unused" warning - and
240 * #pragma GCC diagnostic ignored "-Wused-but-marked-unused"
241 * raises error: unknown option after "#pragma GCC diagnostic".
242 * Disable this warning completely, until the GCC guys sober up
243 * again.
244 */
245
246#pragma GCC diagnostic ignored "-Wunused-function"
247
248#define FUNCTION_MAY_BE_UNUSED /* __attribute__((unused)) */
249
250#else
251#define FUNCTION_MAY_BE_UNUSED
252#endif
253
254
255/* Some ANSI #includes are not available on Windows CE */
256#if !defined(_WIN32_WCE)
257#include <errno.h>
258#include <fcntl.h>
259#include <signal.h>
260#include <sys/stat.h>
261#include <sys/types.h>
262#endif /* !_WIN32_WCE */
263
264
265#if defined(__clang__)
266/* When using -Weverything, clang does not accept it's own headers
267 * in a release build configuration. Disable what is too much in
268 * -Weverything. */
269#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
270#endif
271
272#if defined(__GNUC__) || defined(__MINGW32__)
273/* Who on earth came to the conclusion, using __DATE__ should rise
274 * an "expansion of date or time macro is not reproducible"
275 * warning. That's exactly what was intended by using this macro.
276 * Just disable this nonsense warning. */
277
278/* And disabling them does not work either:
279 * #pragma clang diagnostic ignored "-Wno-error=date-time"
280 * #pragma clang diagnostic ignored "-Wdate-time"
281 * So we just have to disable ALL warnings for some lines
282 * of code.
283 * This seems to be a known GCC bug, not resolved since 2012:
284 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
285 */
286#endif
287
288
289#if defined(__MACH__) /* Apple OSX section */
290
291#if defined(__clang__)
292#if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8))
293/* Avoid warnings for Xcode 7. It seems it does no longer exist in Xcode 8 */
294#pragma clang diagnostic ignored "-Wno-reserved-id-macro"
295#pragma clang diagnostic ignored "-Wno-keyword-macro"
296#endif
297#endif
298
299#define CLOCK_MONOTONIC (1)
300#define CLOCK_REALTIME (2)
301
302#include <mach/clock.h>
303#include <mach/mach.h>
304#include <mach/mach_time.h>
305#include <sys/errno.h>
306#include <sys/time.h>
307
308/* clock_gettime is not implemented on OSX prior to 10.12 */
309static int
310_civet_clock_gettime(int clk_id, struct timespec *t)
311{
312 memset(t, 0, sizeof(*t));
313 if (clk_id == CLOCK_REALTIME) {
314 struct timeval now;
315 int rv = gettimeofday(&now, NULL);
316 if (rv) {
317 return rv;
318 }
319 t->tv_sec = now.tv_sec;
320 t->tv_nsec = now.tv_usec * 1000;
321 return 0;
322
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};
326
327 uint64_t now = mach_absolute_time();
328
329 if (clock_start_time == 0) {
330 kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
331 DEBUG_ASSERT(mach_status == KERN_SUCCESS);
332
333 /* appease "unused variable" warning for release builds */
334 (void)mach_status;
335
336 clock_start_time = now;
337 }
338
339 now = (uint64_t)((double)(now - clock_start_time)
340 * (double)timebase_ifo.numer
341 / (double)timebase_ifo.denom);
342
343 t->tv_sec = now / 1000000000;
344 t->tv_nsec = now % 1000000000;
345 return 0;
346 }
347 return -1; /* EINVAL - Clock ID is unknown */
348}
349
350/* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
351#if defined(__CLOCK_AVAILABILITY)
352/* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be
353 * declared but it may be NULL at runtime. So we need to check before using
354 * it. */
355static int
356_civet_safe_clock_gettime(int clk_id, struct timespec *t)
357{
358 if (clock_gettime) {
359 return clock_gettime(clk_id, t);
360 }
361 return _civet_clock_gettime(clk_id, t);
362}
363#define clock_gettime _civet_safe_clock_gettime
364#else
365#define clock_gettime _civet_clock_gettime
366#endif
367
368#endif
369
370
371#include <ctype.h>
372#include <limits.h>
373#include <stdarg.h>
374#include <stddef.h>
375#include <stdint.h>
376#include <stdio.h>
377#include <stdlib.h>
378#include <string.h>
379#include <time.h>
380
381/********************************************************************/
382/* CivetWeb configuration defines */
383/********************************************************************/
384
385/* Maximum number of threads that can be configured.
386 * The number of threads actually created depends on the "num_threads"
387 * configuration parameter, but this is the upper limit. */
388#if !defined(MAX_WORKER_THREADS)
389#define MAX_WORKER_THREADS (1024 * 64) /* in threads (count) */
390#endif
391
392/* Timeout interval for select/poll calls.
393 * The timeouts depend on "*_timeout_ms" configuration values, but long
394 * timeouts are split into timouts as small as SOCKET_TIMEOUT_QUANTUM.
395 * This reduces the time required to stop the server. */
396#if !defined(SOCKET_TIMEOUT_QUANTUM)
397#define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */
398#endif
399
400/* Do not try to compress files smaller than this limit. */
401#if !defined(MG_FILE_COMPRESSION_SIZE_LIMIT)
402#define MG_FILE_COMPRESSION_SIZE_LIMIT (1024) /* in bytes */
403#endif
404
405#if !defined(PASSWORDS_FILE_NAME)
406#define PASSWORDS_FILE_NAME ".htpasswd"
407#endif
408
409/* Initial buffer size for all CGI environment variables. In case there is
410 * not enough space, another block is allocated. */
411#if !defined(CGI_ENVIRONMENT_SIZE)
412#define CGI_ENVIRONMENT_SIZE (4096) /* in bytes */
413#endif
414
415/* Maximum number of environment variables. */
416#if !defined(MAX_CGI_ENVIR_VARS)
417#define MAX_CGI_ENVIR_VARS (256) /* in variables (count) */
418#endif
419
420/* General purpose buffer size. */
421#if !defined(MG_BUF_LEN) /* in bytes */
422#define MG_BUF_LEN (1024 * 8)
423#endif
424
425/* Size of the accepted socket queue (in case the old queue implementation
426 * is used). */
427#if !defined(MGSQLEN)
428#define MGSQLEN (20) /* count */
429#endif
430
431
432/********************************************************************/
433
434/* Helper makros */
435#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
436
437/* Standard defines */
438#if !defined(INT64_MAX)
439#define INT64_MAX (9223372036854775807)
440#endif
441
442#define SHUTDOWN_RD (0)
443#define SHUTDOWN_WR (1)
444#define SHUTDOWN_BOTH (2)
445
447 "worker threads must be a positive number");
448
449mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8,
450 "size_t data type size check");
451
452#if defined(_WIN32) /* WINDOWS include block */
453#include <windows.h>
454#include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
455#include <ws2tcpip.h>
456
457typedef const char *SOCK_OPT_TYPE;
458
459#if !defined(PATH_MAX)
460#define W_PATH_MAX (MAX_PATH)
461/* at most three UTF-8 chars per wchar_t */
462#define PATH_MAX (W_PATH_MAX * 3)
463#else
464#define W_PATH_MAX ((PATH_MAX + 2) / 3)
465#endif
466
467mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
468
469#if !defined(_IN_PORT_T)
470#if !defined(in_port_t)
471#define in_port_t u_short
472#endif
473#endif
474
475#if !defined(_WIN32_WCE)
476#include <direct.h>
477#include <io.h>
478#include <process.h>
479#else /* _WIN32_WCE */
480#define NO_CGI /* WinCE has no pipes */
481#define NO_POPEN /* WinCE has no popen */
482
483typedef long off_t;
484
485#define errno ((int)(GetLastError()))
486#define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
487#endif /* _WIN32_WCE */
488
489#define MAKEUQUAD(lo, hi) \
490 ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
491#define RATE_DIFF (10000000) /* 100 nsecs */
492#define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
493#define SYS2UNIX_TIME(lo, hi) \
494 ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
495
496/* Visual Studio 6 does not know __func__ or __FUNCTION__
497 * The rest of MS compilers use __FUNCTION__, not C99 __func__
498 * Also use _strtoui64 on modern M$ compilers */
499#if defined(_MSC_VER)
500#if (_MSC_VER < 1300)
501#define STRX(x) #x
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))
506#else
507#define __func__ __FUNCTION__
508#define strtoull(x, y, z) (_strtoui64(x, y, z))
509#define strtoll(x, y, z) (_strtoi64(x, y, z))
510#endif
511#endif /* _MSC_VER */
512
513#define ERRNO ((int)(GetLastError()))
514#define NO_SOCKLEN_T
515
516#if defined(_WIN64) || defined(__MINGW64__)
517#if !defined(SSL_LIB)
518#define SSL_LIB "ssleay64.dll"
519#endif
520#if !defined(CRYPTO_LIB)
521#define CRYPTO_LIB "libeay64.dll"
522#endif
523#else
524#if !defined(SSL_LIB)
525#define SSL_LIB "ssleay32.dll"
526#endif
527#if !defined(CRYPTO_LIB)
528#define CRYPTO_LIB "libeay32.dll"
529#endif
530#endif
531
532#define O_NONBLOCK (0)
533#if !defined(W_OK)
534#define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
535#endif
536#if !defined(EWOULDBLOCK)
537#define EWOULDBLOCK WSAEWOULDBLOCK
538#endif /* !EWOULDBLOCK */
539#define _POSIX_
540#define INT64_FMT "I64d"
541#define UINT64_FMT "I64u"
542
543#define WINCDECL __cdecl
544#define vsnprintf_impl _vsnprintf
545#define access _access
546#define mg_sleep(x) (Sleep(x))
547
548#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
549#if !defined(popen)
550#define popen(x, y) (_popen(x, y))
551#endif
552#if !defined(pclose)
553#define pclose(x) (_pclose(x))
554#endif
555#define close(x) (_close(x))
556#define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
557#define RTLD_LAZY (0)
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__)
567/* Only MinGW 32 bit is missing this function */
568#define timegm(x) (_mkgmtime(x))
569#else
570time_t timegm(struct tm *tm);
571#define NEED_TIMEGM
572#endif
573
574
575#if !defined(fileno)
576#define fileno(x) (_fileno(x))
577#endif /* !fileno MINGW #defines fileno */
578
579typedef HANDLE pthread_mutex_t;
580typedef DWORD pthread_key_t;
581typedef HANDLE pthread_t;
582typedef struct {
583 CRITICAL_SECTION threadIdSec;
584 struct mg_workerTLS *waiting_thread; /* The chain of threads */
586
587#if !defined(__clockid_t_defined)
588typedef DWORD clockid_t;
589#endif
590#if !defined(CLOCK_MONOTONIC)
591#define CLOCK_MONOTONIC (1)
592#endif
593#if !defined(CLOCK_REALTIME)
594#define CLOCK_REALTIME (2)
595#endif
596#if !defined(CLOCK_THREAD)
597#define CLOCK_THREAD (3)
598#endif
599#if !defined(CLOCK_PROCESS)
600#define CLOCK_PROCESS (4)
601#endif
602
603
604#if defined(_MSC_VER) && (_MSC_VER >= 1900)
605#define _TIMESPEC_DEFINED
606#endif
607#if !defined(_TIMESPEC_DEFINED)
608struct timespec {
609 time_t tv_sec; /* seconds */
610 long tv_nsec; /* nanoseconds */
611};
612#endif
613
614#if !defined(WIN_PTHREADS_TIME_H)
615#define MUST_IMPLEMENT_CLOCK_GETTIME
616#endif
617
618#if defined(MUST_IMPLEMENT_CLOCK_GETTIME)
619#define clock_gettime mg_clock_gettime
620static int
621clock_gettime(clockid_t clk_id, struct timespec *tp)
622{
623 FILETIME ft;
624 ULARGE_INTEGER li, li2;
625 BOOL ok = FALSE;
626 double d;
627 static double perfcnt_per_sec = 0.0;
628 static BOOL initialized = FALSE;
629
630 if (!initialized) {
631 QueryPerformanceFrequency((LARGE_INTEGER *)&li);
632 perfcnt_per_sec = 1.0 / li.QuadPart;
633 initialized = TRUE;
634 }
635
636 if (tp) {
637 memset(tp, 0, sizeof(*tp));
638
639 if (clk_id == CLOCK_REALTIME) {
640
641 /* BEGIN: CLOCK_REALTIME = wall clock (date and time) */
642 GetSystemTimeAsFileTime(&ft);
643 li.LowPart = ft.dwLowDateTime;
644 li.HighPart = ft.dwHighDateTime;
645 li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
646 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
647 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
648 ok = TRUE;
649 /* END: CLOCK_REALTIME */
650
651 } else if (clk_id == CLOCK_MONOTONIC) {
652
653 /* BEGIN: CLOCK_MONOTONIC = stopwatch (time differences) */
654 QueryPerformanceCounter((LARGE_INTEGER *)&li);
655 d = li.QuadPart * perfcnt_per_sec;
656 tp->tv_sec = (time_t)d;
657 d -= (double)tp->tv_sec;
658 tp->tv_nsec = (long)(d * 1.0E9);
659 ok = TRUE;
660 /* END: CLOCK_MONOTONIC */
661
662 } else if (clk_id == CLOCK_THREAD) {
663
664 /* BEGIN: CLOCK_THREAD = CPU usage of thread */
665 FILETIME t_create, t_exit, t_kernel, t_user;
666 if (GetThreadTimes(GetCurrentThread(),
667 &t_create,
668 &t_exit,
669 &t_kernel,
670 &t_user)) {
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;
678 ok = TRUE;
679 }
680 /* END: CLOCK_THREAD */
681
682 } else if (clk_id == CLOCK_PROCESS) {
683
684 /* BEGIN: CLOCK_PROCESS = CPU usage of process */
685 FILETIME t_create, t_exit, t_kernel, t_user;
686 if (GetProcessTimes(GetCurrentProcess(),
687 &t_create,
688 &t_exit,
689 &t_kernel,
690 &t_user)) {
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;
698 ok = TRUE;
699 }
700 /* END: CLOCK_PROCESS */
701
702 } else {
703
704 /* BEGIN: unknown clock */
705 /* ok = FALSE; already set by init */
706 /* END: unknown clock */
707 }
708 }
709
710 return ok ? 0 : -1;
711}
712#endif
713
714
715#define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
716
717static int pthread_mutex_lock(pthread_mutex_t *);
718static int pthread_mutex_unlock(pthread_mutex_t *);
719static void path_to_unicode(const struct mg_connection *conn,
720 const char *path,
721 wchar_t *wbuf,
722 size_t wbuf_len);
723
724/* All file operations need to be rewritten to solve #246. */
725
726struct mg_file;
727
728static const char *
729mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p);
730
731
732/* POSIX dirent interface */
733struct dirent {
734 char d_name[PATH_MAX];
735};
736
737typedef struct DIR {
738 HANDLE handle;
739 WIN32_FIND_DATAW info;
740 struct dirent result;
741} DIR;
742
743#if defined(_WIN32)
744#if !defined(HAVE_POLL)
745struct pollfd {
746 SOCKET fd;
747 short events;
748 short revents;
749};
750#endif
751#endif
752
753/* Mark required libraries */
754#if defined(_MSC_VER)
755#pragma comment(lib, "Ws2_32.lib")
756#endif
757
758#else /* defined(_WIN32) - WINDOWS vs UNIX include block */
759
760#include <arpa/inet.h>
761#include <inttypes.h>
762#include <netdb.h>
763#include <netinet/in.h>
764#include <netinet/tcp.h>
765#include <stdint.h>
766#include <sys/poll.h>
767#include <sys/socket.h>
768#include <sys/time.h>
769#include <sys/utsname.h>
770#include <sys/wait.h>
771typedef const void *SOCK_OPT_TYPE;
772
773#if defined(ANDROID)
774typedef unsigned short int in_port_t;
775#endif
776
777#include <dirent.h>
778#include <grp.h>
779#include <pwd.h>
780#include <unistd.h>
781#define vsnprintf_impl vsnprintf
782
783#if !defined(NO_SSL_DL) && !defined(NO_SSL)
784#include <dlfcn.h>
785#endif
786#include <pthread.h>
787#if defined(__MACH__)
788#define SSL_LIB "libssl.dylib"
789#define CRYPTO_LIB "libcrypto.dylib"
790#else
791#if !defined(SSL_LIB)
792#define SSL_LIB "libssl.so"
793#endif
794#if !defined(CRYPTO_LIB)
795#define CRYPTO_LIB "libcrypto.so"
796#endif
797#endif
798#if !defined(O_BINARY)
799#define O_BINARY (0)
800#endif /* 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))
808#define ERRNO (errno)
809#define INVALID_SOCKET (-1)
810#define INT64_FMT PRId64
811#define UINT64_FMT PRIu64
812typedef int SOCKET;
813#define WINCDECL
814
815#if defined(__hpux)
816/* HPUX 11 does not have monotonic, fall back to realtime */
817#if !defined(CLOCK_MONOTONIC)
818#define CLOCK_MONOTONIC CLOCK_REALTIME
819#endif
820
821/* HPUX defines socklen_t incorrectly as size_t which is 64bit on
822 * Itanium. Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
823 * the prototypes use int* rather than socklen_t* which matches the
824 * actual library expectation. When called with the wrong size arg
825 * accept() returns a zero client inet addr and check_acl() always
826 * fails. Since socklen_t is widely used below, just force replace
827 * their typedef with int. - DTL
828 */
829#define socklen_t int
830#endif /* hpux */
831
832#endif /* defined(_WIN32) - WINDOWS vs UNIX include block */
833
834/* Maximum queue length for pending connections. This value is passed as
835 * parameter to the "listen" socket call. */
836#if !defined(SOMAXCONN)
837/* This symbol may be defined in winsock2.h so this must after that include */
838#define SOMAXCONN (100) /* in pending connections (count) */
839#endif
840
841/* In case our C library is missing "timegm", provide an implementation */
842#if defined(NEED_TIMEGM)
843static inline int
844is_leap(int y)
845{
846 return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
847}
848
849static inline int
850count_leap(int y)
851{
852 return (y - 1969) / 4 - (y - 1901) / 100 + (y - 1601) / 400;
853}
854
855time_t
856timegm(struct tm *tm)
857{
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;
866
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)
871 return -1;
872
873 time_t res = year - 1970;
874 res *= 365;
875 res += mday;
876 res += ydays[mon] + (mon > 1 && is_leap(year) ? 1 : 0);
877 res += count_leap(year);
878
879 res *= 24;
880 res += hour;
881 res *= 60;
882 res += min;
883 res *= 60;
884 res += sec;
885 return res;
886}
887#endif /* NEED_TIMEGM */
888
889
890/* va_copy should always be a macro, C99 and C++11 - DTL */
891#if !defined(va_copy)
892#define va_copy(x, y) ((x) = (y))
893#endif
894
895
896#if defined(_WIN32)
897/* Create substitutes for POSIX functions in Win32. */
898
899#if defined(GCC_DIAGNOSTIC)
900/* Show no warning in case system functions are not used. */
901#pragma GCC diagnostic push
902#pragma GCC diagnostic ignored "-Wunused-function"
903#endif
904
905
906static CRITICAL_SECTION global_log_file_lock;
907
909static DWORD
910pthread_self(void)
911{
912 return GetCurrentThreadId();
913}
914
915
917static int
918pthread_key_create(
919 pthread_key_t *key,
920 void (*_ignored)(void *) /* destructor not supported for Windows */
921)
922{
923 (void)_ignored;
924
925 if ((key != 0)) {
926 *key = TlsAlloc();
927 return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
928 }
929 return -2;
930}
931
932
934static int
935pthread_key_delete(pthread_key_t key)
936{
937 return TlsFree(key) ? 0 : 1;
938}
939
940
942static int
943pthread_setspecific(pthread_key_t key, void *value)
944{
945 return TlsSetValue(key, value) ? 0 : 1;
946}
947
948
950static void *
951pthread_getspecific(pthread_key_t key)
952{
953 return TlsGetValue(key);
954}
955
956#if defined(GCC_DIAGNOSTIC)
957/* Enable unused function warning again */
958#pragma GCC diagnostic pop
959#endif
960
961static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
962#else
963static pthread_mutexattr_t pthread_mutex_attr;
964#endif /* _WIN32 */
965
966
967#if defined(_WIN32_WCE)
968/* Create substitutes for POSIX functions in Win32. */
969
970#if defined(GCC_DIAGNOSTIC)
971/* Show no warning in case system functions are not used. */
972#pragma GCC diagnostic push
973#pragma GCC diagnostic ignored "-Wunused-function"
974#endif
975
976
978static time_t
979time(time_t *ptime)
980{
981 time_t t;
982 SYSTEMTIME st;
983 FILETIME ft;
984
985 GetSystemTime(&st);
986 SystemTimeToFileTime(&st, &ft);
987 t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
988
989 if (ptime != NULL) {
990 *ptime = t;
991 }
992
993 return t;
994}
995
996
998static struct tm *
999localtime_s(const time_t *ptime, struct tm *ptm)
1000{
1001 int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
1002 FILETIME ft, lft;
1003 SYSTEMTIME st;
1004 TIME_ZONE_INFORMATION tzinfo;
1005
1006 if (ptm == NULL) {
1007 return NULL;
1008 }
1009
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;
1020 ptm->tm_yday = 0; /* hope nobody uses this */
1021 ptm->tm_isdst =
1022 (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
1023
1024 return ptm;
1025}
1026
1027
1029static struct tm *
1030gmtime_s(const time_t *ptime, struct tm *ptm)
1031{
1032 /* FIXME(lsm): fix this. */
1033 return localtime_s(ptime, ptm);
1034}
1035
1036
1037static int mg_atomic_inc(volatile int *addr);
1038static struct tm tm_array[MAX_WORKER_THREADS];
1039static int tm_index = 0;
1040
1041
1043static struct tm *
1044localtime(const time_t *ptime)
1045{
1046 int i = mg_atomic_inc(&tm_index) % (sizeof(tm_array) / sizeof(tm_array[0]));
1047 return localtime_s(ptime, tm_array + i);
1048}
1049
1050
1052static struct tm *
1053gmtime(const time_t *ptime)
1054{
1055 int i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array);
1056 return gmtime_s(ptime, tm_array + i);
1057}
1058
1059
1061static size_t
1062strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
1063{
1064 /* TODO: (void)mg_snprintf(NULL, dst, dst_size, "implement strftime()
1065 * for WinCE"); */
1066 return 0;
1067}
1068
1069#define _beginthreadex(psec, stack, func, prm, flags, ptid) \
1070 (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid)
1071
1072#define remove(f) mg_remove(NULL, f)
1073
1074
1076static int
1077rename(const char *a, const char *b)
1078{
1079 wchar_t wa[W_PATH_MAX];
1080 wchar_t wb[W_PATH_MAX];
1081 path_to_unicode(NULL, a, wa, ARRAY_SIZE(wa));
1082 path_to_unicode(NULL, b, wb, ARRAY_SIZE(wb));
1083
1084 return MoveFileW(wa, wb) ? 0 : -1;
1085}
1086
1087
1088struct stat {
1089 int64_t st_size;
1090 time_t st_mtime;
1091};
1092
1093
1095static int
1096stat(const char *name, struct stat *st)
1097{
1098 wchar_t wbuf[W_PATH_MAX];
1099 WIN32_FILE_ATTRIBUTE_DATA attr;
1100 time_t creation_time, write_time;
1101
1102 path_to_unicode(NULL, name, wbuf, ARRAY_SIZE(wbuf));
1103 memset(&attr, 0, sizeof(attr));
1104
1105 GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
1106 st->st_size =
1107 (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
1108
1109 write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
1110 attr.ftLastWriteTime.dwHighDateTime);
1111 creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
1112 attr.ftCreationTime.dwHighDateTime);
1113
1114 if (creation_time > write_time) {
1115 st->st_mtime = creation_time;
1116 } else {
1117 st->st_mtime = write_time;
1118 }
1119 return 0;
1120}
1121
1122#define access(x, a) 1 /* not required anyway */
1123
1124/* WinCE-TODO: define stat, remove, rename, _rmdir, _lseeki64 */
1125/* Values from errno.h in Windows SDK (Visual Studio). */
1126#define EEXIST 17
1127#define EACCES 13
1128#define ENOENT 2
1129
1130#if defined(GCC_DIAGNOSTIC)
1131/* Enable unused function warning again */
1132#pragma GCC diagnostic pop
1133#endif
1134
1135#endif /* defined(_WIN32_WCE) */
1136
1137
1138#if defined(GCC_DIAGNOSTIC)
1139/* Show no warning in case system functions are not used. */
1140#pragma GCC diagnostic push
1141#pragma GCC diagnostic ignored "-Wunused-function"
1142#endif /* defined(GCC_DIAGNOSTIC) */
1143#if defined(__clang__)
1144/* Show no warning in case system functions are not used. */
1145#pragma clang diagnostic push
1146#pragma clang diagnostic ignored "-Wunused-function"
1147#endif
1148
1149static pthread_mutex_t global_lock_mutex;
1150
1151
1152#if defined(_WIN32)
1153/* Forward declaration for Windows */
1155static int pthread_mutex_lock(pthread_mutex_t *mutex);
1156
1158static int pthread_mutex_unlock(pthread_mutex_t *mutex);
1159#endif
1160
1161
1163static void
1165{
1166 (void)pthread_mutex_lock(&global_lock_mutex);
1167}
1168
1169
1171static void
1173{
1174 (void)pthread_mutex_unlock(&global_lock_mutex);
1175}
1176
1177
1179static int
1180mg_atomic_inc(volatile int *addr)
1181{
1182 int ret;
1183#if defined(_WIN32) && !defined(NO_ATOMICS)
1184 /* Depending on the SDK, this function uses either
1185 * (volatile unsigned int *) or (volatile LONG *),
1186 * so whatever you use, the other SDK is likely to raise a warning. */
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);
1192#else
1194 ret = (++(*addr));
1196#endif
1197 return ret;
1198}
1199
1200
1202static int
1203mg_atomic_dec(volatile int *addr)
1204{
1205 int ret;
1206#if defined(_WIN32) && !defined(NO_ATOMICS)
1207 /* Depending on the SDK, this function uses either
1208 * (volatile unsigned int *) or (volatile LONG *),
1209 * so whatever you use, the other SDK is likely to raise a warning. */
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);
1215#else
1217 ret = (--(*addr));
1219#endif
1220 return ret;
1221}
1222
1223
1224#if defined(USE_SERVER_STATS)
1225static int64_t
1226mg_atomic_add(volatile int64_t *addr, int64_t value)
1227{
1228 int64_t ret;
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);
1235#else
1237 *addr += value;
1238 ret = (*addr);
1240#endif
1241 return ret;
1242}
1243#endif
1244
1245
1246#if defined(GCC_DIAGNOSTIC)
1247/* Show no warning in case system functions are not used. */
1248#pragma GCC diagnostic pop
1249#endif /* defined(GCC_DIAGNOSTIC) */
1250#if defined(__clang__)
1251/* Show no warning in case system functions are not used. */
1252#pragma clang diagnostic pop
1253#endif
1254
1255
1256#if defined(USE_SERVER_STATS)
1257
1258struct mg_memory_stat {
1259 volatile int64_t totalMemUsed;
1260 volatile int64_t maxMemUsed;
1261 volatile int blockCount;
1262};
1263
1264
1265static struct mg_memory_stat *get_memory_stat(struct mg_context *ctx);
1266
1267
1268static void *
1269mg_malloc_ex(size_t size,
1270 struct mg_context *ctx,
1271 const char *file,
1272 unsigned line)
1273{
1274 void *data = malloc(size + 2 * sizeof(uintptr_t));
1275 void *memory = 0;
1276 struct mg_memory_stat *mstat = get_memory_stat(ctx);
1277
1278#if defined(MEMORY_DEBUGGING)
1279 char mallocStr[256];
1280#else
1281 (void)file;
1282 (void)line;
1283#endif
1284
1285 if (data) {
1286 int64_t mmem = mg_atomic_add(&mstat->totalMemUsed, (int64_t)size);
1287 if (mmem > mstat->maxMemUsed) {
1288 /* could use atomic compare exchange, but this
1289 * seems overkill for statistics data */
1290 mstat->maxMemUsed = mmem;
1291 }
1292
1293 mg_atomic_inc(&mstat->blockCount);
1294 ((uintptr_t *)data)[0] = size;
1295 ((uintptr_t *)data)[1] = (uintptr_t)mstat;
1296 memory = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1297 }
1298
1299#if defined(MEMORY_DEBUGGING)
1300 sprintf(mallocStr,
1301 "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n",
1302 memory,
1303 (unsigned long)size,
1304 (unsigned long)mstat->totalMemUsed,
1305 (unsigned long)mstat->blockCount,
1306 file,
1307 line);
1308#if defined(_WIN32)
1309 OutputDebugStringA(mallocStr);
1310#else
1311 DEBUG_TRACE("%s", mallocStr);
1312#endif
1313#endif
1314
1315 return memory;
1316}
1317
1318
1319static void *
1320mg_calloc_ex(size_t count,
1321 size_t size,
1322 struct mg_context *ctx,
1323 const char *file,
1324 unsigned line)
1325{
1326 void *data = mg_malloc_ex(size * count, ctx, file, line);
1327
1328 if (data) {
1329 memset(data, 0, size * count);
1330 }
1331 return data;
1332}
1333
1334
1335static void
1336mg_free_ex(void *memory, const char *file, unsigned line)
1337{
1338 void *data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1339
1340
1341#if defined(MEMORY_DEBUGGING)
1342 char mallocStr[256];
1343#else
1344 (void)file;
1345 (void)line;
1346#endif
1347
1348 if (memory) {
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);
1353 mg_atomic_dec(&mstat->blockCount);
1354#if defined(MEMORY_DEBUGGING)
1355 sprintf(mallocStr,
1356 "MEM: %p %5lu free %7lu %4lu --- %s:%u\n",
1357 memory,
1358 (unsigned long)size,
1359 (unsigned long)mstat->totalMemUsed,
1360 (unsigned long)mstat->blockCount,
1361 file,
1362 line);
1363#if defined(_WIN32)
1364 OutputDebugStringA(mallocStr);
1365#else
1366 DEBUG_TRACE("%s", mallocStr);
1367#endif
1368#endif
1369 free(data);
1370 }
1371}
1372
1373
1374static void *
1375mg_realloc_ex(void *memory,
1376 size_t newsize,
1377 struct mg_context *ctx,
1378 const char *file,
1379 unsigned line)
1380{
1381 void *data;
1382 void *_realloc;
1383 uintptr_t oldsize;
1384
1385#if defined(MEMORY_DEBUGGING)
1386 char mallocStr[256];
1387#else
1388 (void)file;
1389 (void)line;
1390#endif
1391
1392 if (newsize) {
1393 if (memory) {
1394 /* Reallocate existing block */
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));
1400 if (_realloc) {
1401 data = _realloc;
1402 mg_atomic_add(&mstat->totalMemUsed, -(int64_t)oldsize);
1403#if defined(MEMORY_DEBUGGING)
1404 sprintf(mallocStr,
1405 "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n",
1406 memory,
1407 (unsigned long)oldsize,
1408 (unsigned long)mstat->totalMemUsed,
1409 (unsigned long)mstat->blockCount,
1410 file,
1411 line);
1412#if defined(_WIN32)
1413 OutputDebugStringA(mallocStr);
1414#else
1415 DEBUG_TRACE("%s", mallocStr);
1416#endif
1417#endif
1418 mg_atomic_add(&mstat->totalMemUsed, (int64_t)newsize);
1419#if defined(MEMORY_DEBUGGING)
1420 sprintf(mallocStr,
1421 "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
1422 memory,
1423 (unsigned long)newsize,
1424 (unsigned long)mstat->totalMemUsed,
1425 (unsigned long)mstat->blockCount,
1426 file,
1427 line);
1428#if defined(_WIN32)
1429 OutputDebugStringA(mallocStr);
1430#else
1431 DEBUG_TRACE("%s", mallocStr);
1432#endif
1433#endif
1434 *(uintptr_t *)data = newsize;
1435 data = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1436 } else {
1437#if defined(MEMORY_DEBUGGING)
1438#if defined(_WIN32)
1439 OutputDebugStringA("MEM: realloc failed\n");
1440#else
1441 DEBUG_TRACE("%s", "MEM: realloc failed\n");
1442#endif
1443#endif
1444 return _realloc;
1445 }
1446 } else {
1447 /* Allocate new block */
1448 data = mg_malloc_ex(newsize, ctx, file, line);
1449 }
1450 } else {
1451 /* Free existing block */
1452 data = 0;
1453 mg_free_ex(memory, file, line);
1454 }
1455
1456 return data;
1457}
1458
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__)
1463
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__)
1467
1468#else /* USE_SERVER_STATS */
1469
1470static __inline void *
1472{
1473 return malloc(a);
1474}
1475
1476static __inline void *
1477mg_calloc(size_t a, size_t b)
1478{
1479 return calloc(a, b);
1480}
1481
1482static __inline void *
1483mg_realloc(void *a, size_t b)
1484{
1485 return realloc(a, b);
1486}
1487
1488static __inline void
1490{
1491 free(a);
1492}
1493
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)
1498
1499#endif /* USE_SERVER_STATS */
1500
1501
1502static void mg_vsnprintf(const struct mg_connection *conn,
1503 int *truncated,
1504 char *buf,
1505 size_t buflen,
1506 const char *fmt,
1507 va_list ap);
1508
1509static void mg_snprintf(const struct mg_connection *conn,
1510 int *truncated,
1511 char *buf,
1512 size_t buflen,
1513 PRINTF_FORMAT_STRING(const char *fmt),
1514 ...) PRINTF_ARGS(5, 6);
1515
1516/* This following lines are just meant as a reminder to use the mg-functions
1517 * for memory management */
1518#if defined(malloc)
1519#undef malloc
1520#endif
1521#if defined(calloc)
1522#undef calloc
1523#endif
1524#if defined(realloc)
1525#undef realloc
1526#endif
1527#if defined(free)
1528#undef free
1529#endif
1530#if defined(snprintf)
1531#undef snprintf
1532#endif
1533#if defined(vsnprintf)
1534#undef vsnprintf
1535#endif
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
1541#if defined(_WIN32)
1542/* vsnprintf must not be used in any system,
1543 * but this define only works well for Windows. */
1544#define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
1545#endif
1546
1547
1548/* mg_init_library counter */
1550
1551#if !defined(NO_SSL)
1552static int mg_ssl_initialized = 0;
1553#endif
1554
1555static pthread_key_t sTlsKey; /* Thread local storage index */
1556static int thread_idx_max = 0;
1557
1558#if defined(MG_LEGACY_INTERFACE)
1559#define MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE
1560#endif
1561
1562struct mg_workerTLS {
1563 int is_master;
1564 unsigned long thread_idx;
1565#if defined(_WIN32)
1566 HANDLE pthread_cond_helper_mutex;
1567 struct mg_workerTLS *next_waiting_thread;
1568#endif
1569#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
1570 char txtbuf[4];
1571#endif
1572};
1573
1574
1575#if defined(GCC_DIAGNOSTIC)
1576/* Show no warning in case system functions are not used. */
1577#pragma GCC diagnostic push
1578#pragma GCC diagnostic ignored "-Wunused-function"
1579#endif /* defined(GCC_DIAGNOSTIC) */
1580#if defined(__clang__)
1581/* Show no warning in case system functions are not used. */
1582#pragma clang diagnostic push
1583#pragma clang diagnostic ignored "-Wunused-function"
1584#endif
1585
1586
1587/* Get a unique thread ID as unsigned long, independent from the data type
1588 * of thread IDs defined by the operating system API.
1589 * If two calls to mg_current_thread_id return the same value, they calls
1590 * are done from the same thread. If they return different values, they are
1591 * done from different threads. (Provided this function is used in the same
1592 * process context and threads are not repeatedly created and deleted, but
1593 * CivetWeb does not do that).
1594 * This function must match the signature required for SSL id callbacks:
1595 * CRYPTO_set_id_callback
1596 */
1598static unsigned long
1600{
1601#if defined(_WIN32)
1602 return GetCurrentThreadId();
1603#else
1604
1605#if defined(__clang__)
1606#pragma clang diagnostic push
1607#pragma clang diagnostic ignored "-Wunreachable-code"
1608/* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
1609 * or not, so one of the two conditions will be unreachable by construction.
1610 * Unfortunately the C standard does not define a way to check this at
1611 * compile time, since the #if preprocessor conditions can not use the sizeof
1612 * operator as an argument. */
1613#endif
1614
1615 if (sizeof(pthread_t) > sizeof(unsigned long)) {
1616 /* This is the problematic case for CRYPTO_set_id_callback:
1617 * The OS pthread_t can not be cast to unsigned long. */
1618 struct mg_workerTLS *tls =
1619 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
1620 if (tls == NULL) {
1621 /* SSL called from an unknown thread: Create some thread index.
1622 */
1623 tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
1624 tls->is_master = -2; /* -2 means "3rd party thread" */
1625 tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
1626 pthread_setspecific(sTlsKey, tls);
1627 }
1628 return tls->thread_idx;
1629 } else {
1630 /* pthread_t may be any data type, so a simple cast to unsigned long
1631 * can rise a warning/error, depending on the platform.
1632 * Here memcpy is used as an anything-to-anything cast. */
1633 unsigned long ret = 0;
1634 pthread_t t = pthread_self();
1635 memcpy(&ret, &t, sizeof(pthread_t));
1636 return ret;
1637 }
1638
1639#if defined(__clang__)
1640#pragma clang diagnostic pop
1641#endif
1642
1643#endif
1644}
1645
1646
1648static uint64_t
1650{
1651 struct timespec tsnow;
1652 clock_gettime(CLOCK_REALTIME, &tsnow);
1653 return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
1654}
1655
1656
1657#if defined(GCC_DIAGNOSTIC)
1658/* Show no warning in case system functions are not used. */
1659#pragma GCC diagnostic pop
1660#endif /* defined(GCC_DIAGNOSTIC) */
1661#if defined(__clang__)
1662/* Show no warning in case system functions are not used. */
1663#pragma clang diagnostic pop
1664#endif
1665
1666
1667#if defined(NEED_DEBUG_TRACE_FUNC)
1668static void
1669DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
1670{
1671 va_list args;
1672 uint64_t nsnow;
1673 static uint64_t nslast;
1674 struct timespec tsnow;
1675
1676 /* Get some operating system independent thread id */
1677 unsigned long thread_id = mg_current_thread_id();
1678
1679 clock_gettime(CLOCK_REALTIME, &tsnow);
1680 nsnow = ((uint64_t)tsnow.tv_sec) * ((uint64_t)1000000000)
1681 + ((uint64_t)tsnow.tv_nsec);
1682
1683 if (!nslast) {
1684 nslast = nsnow;
1685 }
1686
1687 flockfile(stdout);
1688 printf("*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ",
1689 (unsigned long)tsnow.tv_sec,
1690 (unsigned long)tsnow.tv_nsec,
1691 nsnow - nslast,
1692 thread_id,
1693 func,
1694 line);
1695 va_start(args, fmt);
1696 vprintf(fmt, args);
1697 va_end(args);
1698 putchar('\n');
1699 fflush(stdout);
1700 funlockfile(stdout);
1701 nslast = nsnow;
1702}
1703#endif /* NEED_DEBUG_TRACE_FUNC */
1704
1705
1706#define MD5_STATIC static
1707#include "md5.inl"
1708
1709/* Darwin prior to 7.0 and Win32 do not have socklen_t */
1710#if defined(NO_SOCKLEN_T)
1711typedef int socklen_t;
1712#endif /* NO_SOCKLEN_T */
1713
1714#define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
1715
1716#if !defined(MSG_NOSIGNAL)
1717#define MSG_NOSIGNAL (0)
1718#endif
1719
1720
1721#if defined(NO_SSL)
1722typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
1723typedef struct SSL_CTX SSL_CTX;
1724#else
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>
1737
1738#if defined(WOLFSSL_VERSION)
1739/* Additional defines for WolfSSL, see
1740 * https://github.com/civetweb/civetweb/issues/583 */
1741#include "wolfssl_extras.inl"
1742#endif
1743
1744#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1745/* If OpenSSL headers are included, automatically select the API version */
1746#if !defined(OPENSSL_API_1_1)
1747#define OPENSSL_API_1_1
1748#endif
1749#define OPENSSL_REMOVE_THREAD_STATE()
1750#else
1751#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL)
1752#endif
1753
1754#else
1755
1756/* SSL loaded dynamically from DLL.
1757 * I put the prototypes here to be independent from OpenSSL source
1758 * installation. */
1759
1760typedef struct ssl_st SSL;
1761typedef struct ssl_method_st SSL_METHOD;
1762typedef struct ssl_ctx_st SSL_CTX;
1763typedef struct x509_store_ctx_st X509_STORE_CTX;
1764typedef struct x509_name X509_NAME;
1765typedef struct asn1_integer ASN1_INTEGER;
1766typedef struct bignum BIGNUM;
1767typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
1768typedef struct evp_md EVP_MD;
1769typedef struct x509 X509;
1770
1771
1772#define SSL_CTRL_OPTIONS (32)
1773#define SSL_CTRL_CLEAR_OPTIONS (77)
1774#define SSL_CTRL_SET_ECDH_AUTO (94)
1775
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
1779
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)
1794
1795#define SSL_CB_HANDSHAKE_START (0x10)
1796#define SSL_CB_HANDSHAKE_DONE (0x20)
1797
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) /* see errno */
1804#define SSL_ERROR_ZERO_RETURN (6)
1805#define SSL_ERROR_WANT_CONNECT (7)
1806#define SSL_ERROR_WANT_ACCEPT (8)
1807
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)
1814
1815struct ssl_func {
1816 const char *name; /* SSL function name */
1817 void (*ptr)(void); /* Function pointer */
1818};
1819
1820
1821#if defined(OPENSSL_API_1_1)
1822
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] \
1836 .ptr)
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 *, \
1850 int, \
1851 int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18] \
1852 .ptr)
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))) \
1873 ssl_sw[32] \
1874 .ptr)
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)
1883
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)
1888
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, \
1895 (void (*)(void))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)
1900
1901#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
1902#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
1903
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))
1906
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)
1918#define EVP_Digest \
1919 (*(int (*)( \
1920 const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
1921 crypto_sw[9] \
1922 .ptr)
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)
1929
1930#define OPENSSL_free(a) CRYPTO_free(a)
1931
1932#define OPENSSL_REMOVE_THREAD_STATE()
1933
1934/* init_ssl_ctx() function updates this array.
1935 * It loads SSL library dynamically and changes NULLs to the actual addresses
1936 * of respective functions. The macros above (like SSL_connect()) are really
1937 * just calling these functions indirectly via the pointer. */
1938static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
1939 {"SSL_accept", NULL},
1940 {"SSL_connect", NULL},
1941 {"SSL_read", NULL},
1942 {"SSL_write", NULL},
1943 {"SSL_get_error", NULL},
1944 {"SSL_set_fd", NULL},
1945 {"SSL_new", 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},
1976 {"SSL_ctrl", NULL},
1977 {NULL, NULL}};
1978
1979
1980/* Similar array as ssl_sw. These functions could be located in different
1981 * lib. */
1982static struct ssl_func crypto_sw[] = {{"ERR_get_error", NULL},
1983 {"ERR_error_string", NULL},
1984 {"CONF_modules_unload", NULL},
1985 {"X509_free", NULL},
1986 {"X509_get_subject_name", NULL},
1987 {"X509_get_issuer_name", NULL},
1988 {"X509_NAME_oneline", NULL},
1989 {"X509_get_serialNumber", NULL},
1990 {"EVP_get_digestbyname", NULL},
1991 {"EVP_Digest", NULL},
1992 {"i2d_X509", NULL},
1993 {"BN_bn2hex", NULL},
1994 {"ASN1_INTEGER_to_BN", NULL},
1995 {"BN_free", NULL},
1996 {"CRYPTO_free", NULL},
1997 {NULL, NULL}};
1998#else
1999
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 *, \
2025 int, \
2026 int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19] \
2027 .ptr)
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] \
2046 .ptr)
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)
2055
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)
2062
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, \
2069 (void (*)(void))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)
2074
2075#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
2076#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
2077
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))
2080
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)
2104#define EVP_Digest \
2105 (*(int (*)( \
2106 const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
2107 crypto_sw[18] \
2108 .ptr)
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)
2115
2116#define OPENSSL_free(a) CRYPTO_free(a)
2117
2118/* use here ERR_remove_state,
2119 * while on some platforms function is not included into library due to
2120 * deprication */
2121#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_state(0)
2122
2123/* init_ssl_ctx() function updates this array.
2124 * It loads SSL library dynamically and changes NULLs to the actual addresses
2125 * of respective functions. The macros above (like SSL_connect()) are really
2126 * just calling these functions indirectly via the pointer. */
2127static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
2128 {"SSL_accept", NULL},
2129 {"SSL_connect", NULL},
2130 {"SSL_read", NULL},
2131 {"SSL_write", NULL},
2132 {"SSL_get_error", NULL},
2133 {"SSL_set_fd", NULL},
2134 {"SSL_new", 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},
2165 {"SSL_ctrl", NULL},
2166 {NULL, NULL}};
2167
2168
2169/* Similar array as ssl_sw. These functions could be located in different
2170 * lib. */
2171static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
2172 {"CRYPTO_set_locking_callback", NULL},
2173 {"CRYPTO_set_id_callback", NULL},
2174 {"ERR_get_error", NULL},
2175 {"ERR_error_string", NULL},
2176 {"ERR_remove_state", NULL},
2177 {"ERR_free_strings", NULL},
2178 {"ENGINE_cleanup", NULL},
2179 {"CONF_modules_unload", NULL},
2180 {"CRYPTO_cleanup_all_ex_data", NULL},
2181 {"EVP_cleanup", NULL},
2182 {"X509_free", NULL},
2183 {"X509_get_subject_name", NULL},
2184 {"X509_get_issuer_name", NULL},
2185 {"X509_NAME_oneline", NULL},
2186 {"X509_get_serialNumber", NULL},
2187 {"i2c_ASN1_INTEGER", NULL},
2188 {"EVP_get_digestbyname", NULL},
2189 {"EVP_Digest", NULL},
2190 {"i2d_X509", NULL},
2191 {"BN_bn2hex", NULL},
2192 {"ASN1_INTEGER_to_BN", NULL},
2193 {"BN_free", NULL},
2194 {"CRYPTO_free", NULL},
2195 {NULL, NULL}};
2196#endif /* OPENSSL_API_1_1 */
2197#endif /* NO_SSL_DL */
2198#endif /* NO_SSL */
2199
2200
2201#if !defined(NO_CACHING)
2202static const char *month_names[] = {"Jan",
2203 "Feb",
2204 "Mar",
2205 "Apr",
2206 "May",
2207 "Jun",
2208 "Jul",
2209 "Aug",
2210 "Sep",
2211 "Oct",
2212 "Nov",
2213 "Dec"};
2214#endif /* !NO_CACHING */
2215
2216/* Unified socket address. For IPv6 support, add IPv6 address structure in
2217 * the
2218 * union u. */
2219union usa {
2220 struct sockaddr sa;
2221 struct sockaddr_in sin;
2222#if defined(USE_IPV6)
2223 struct sockaddr_in6 sin6;
2224#endif
2225};
2226
2227/* Describes a string (chunk of memory). */
2228struct vec {
2229 const char *ptr;
2230 size_t len;
2231};
2232
2233struct mg_file_stat {
2234 /* File properties filled by mg_stat: */
2235 uint64_t size;
2236 time_t last_modified;
2237 int is_directory; /* Set to 1 if mg_stat is called for a directory */
2238 int is_gzipped; /* Set to 1 if the content is gzipped, in which
2239 * case we need a "Content-Eencoding: gzip" header */
2240 int location; /* 0 = nowhere, 1 = on disk, 2 = in memory */
2241};
2242
2243struct mg_file_in_memory {
2244 char *p;
2245 uint32_t pos;
2246 char mode;
2247};
2248
2249struct mg_file_access {
2250 /* File properties filled by mg_fopen: */
2251 FILE *fp;
2252#if defined(MG_USE_OPEN_FILE)
2253 /* TODO (low): Remove obsolete "file in memory" implementation.
2254 * In an "early 2017" discussion at Google groups
2255 * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
2256 * we decided to get rid of this feature (after some fade-out
2257 * phase). */
2258 const char *membuf;
2259#endif
2260};
2261
2262struct mg_file {
2263 struct mg_file_stat stat;
2264 struct mg_file_access access;
2265};
2266
2267#if defined(MG_USE_OPEN_FILE)
2268
2269#define STRUCT_FILE_INITIALIZER \
2270 { \
2271 {(uint64_t)0, (time_t)0, 0, 0, 0}, \
2272 { \
2273 (FILE *)NULL, (const char *)NULL \
2274 } \
2275 }
2276
2277#else
2278
2279#define STRUCT_FILE_INITIALIZER \
2280 { \
2281 {(uint64_t)0, (time_t)0, 0, 0, 0}, \
2282 { \
2283 (FILE *)NULL \
2284 } \
2285 }
2286
2287#endif
2288
2289
2290/* Describes listening socket, or socket which was accept()-ed by the master
2291 * thread and queued for future handling by the worker thread. */
2292struct socket {
2293 SOCKET sock; /* Listening socket */
2294 union usa lsa; /* Local socket address */
2295 union usa rsa; /* Remote socket address */
2296 unsigned char is_ssl; /* Is port SSL-ed */
2297 unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
2298 * port */
2299 unsigned char in_use; /* Is valid */
2300};
2301
2302
2303/* Enum const for all options must be in sync with
2304 * static struct mg_option config_options[]
2305 * This is tested in the unit test (test/private.c)
2306 * "Private Config Options"
2307 */
2308enum {
2309 /* Once for each server */
2313 CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
2314 * socket option typedef TCP_NODELAY. */
2317#if defined(__linux__)
2318 ALLOW_SENDFILE_CALL,
2319#endif
2320#if defined(_WIN32)
2321 CASE_SENSITIVE_FILES,
2322#endif
2329#if defined(USE_WEBSOCKET)
2330 WEBSOCKET_TIMEOUT,
2331 ENABLE_WEBSOCKET_PING_PONG,
2332#endif
2334#if defined(USE_LUA)
2335 LUA_BACKGROUND_SCRIPT,
2336 LUA_BACKGROUND_SCRIPT_PARAMS,
2337#endif
2338#if defined(USE_TIMERS)
2339 CGI_TIMEOUT,
2340#endif
2341
2342 /* Once for each domain */
2369
2370#if defined(USE_LUA)
2371 LUA_PRELOAD_FILE,
2372 LUA_SCRIPT_EXTENSIONS,
2373 LUA_SERVER_PAGE_EXTENSIONS,
2374#if defined(MG_EXPERIMENTAL_INTERFACES)
2375 LUA_DEBUG_PARAMS,
2376#endif
2377#endif
2378#if defined(USE_DUKTAPE)
2379 DUKTAPE_SCRIPT_EXTENSIONS,
2380#endif
2381
2382#if defined(USE_WEBSOCKET)
2383 WEBSOCKET_ROOT,
2384#endif
2385#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2386 LUA_WEBSOCKET_EXTENSIONS,
2387#endif
2388
2393#if !defined(NO_CACHING)
2395#endif
2396#if !defined(NO_SSL)
2398#endif
2401
2404
2405
2406/* Config option name, config types, default value.
2407 * Must be in the same order as the enum const above.
2408 */
2409static const struct mg_option config_options[] = {
2410
2411 /* Once for each server */
2412 {"listening_ports", MG_CONFIG_TYPE_STRING_LIST, "8080"},
2413 {"num_threads", MG_CONFIG_TYPE_NUMBER, "50"},
2414 {"run_as_user", MG_CONFIG_TYPE_STRING, NULL},
2415 {"tcp_nodelay", MG_CONFIG_TYPE_NUMBER, "0"},
2416 {"max_request_size", MG_CONFIG_TYPE_NUMBER, "16384"},
2417 {"linger_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2418#if defined(__linux__)
2419 {"allow_sendfile_call", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2420#endif
2421#if defined(_WIN32)
2422 {"case_sensitive", MG_CONFIG_TYPE_BOOLEAN, "no"},
2423#endif
2424 {"throttle", MG_CONFIG_TYPE_STRING_LIST, NULL},
2425 {"access_log_file", MG_CONFIG_TYPE_FILE, NULL},
2426 {"error_log_file", MG_CONFIG_TYPE_FILE, NULL},
2427 {"enable_keep_alive", MG_CONFIG_TYPE_BOOLEAN, "no"},
2428 {"request_timeout_ms", MG_CONFIG_TYPE_NUMBER, "30000"},
2429 {"keep_alive_timeout_ms", MG_CONFIG_TYPE_NUMBER, "500"},
2430#if defined(USE_WEBSOCKET)
2431 {"websocket_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2432 {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
2433#endif
2434 {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2435#if defined(USE_LUA)
2436 {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL},
2437 {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL},
2438#endif
2439#if defined(USE_TIMERS)
2440 {"cgi_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2441#endif
2442
2443 /* Once for each domain */
2444 {"document_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
2445 {"cgi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
2446 {"cgi_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
2447 {"put_delete_auth_file", MG_CONFIG_TYPE_FILE, NULL},
2448 {"cgi_interpreter", MG_CONFIG_TYPE_FILE, NULL},
2449 {"protect_uri", MG_CONFIG_TYPE_STRING_LIST, NULL},
2450 {"authentication_domain", MG_CONFIG_TYPE_STRING, "mydomain.com"},
2451 {"enable_auth_domain_check", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2452 {"ssi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
2453 {"enable_directory_listing", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2454 {"global_auth_file", MG_CONFIG_TYPE_FILE, NULL},
2455 {"index_files",
2457#if defined(USE_LUA)
2458 "index.xhtml,index.html,index.htm,"
2459 "index.lp,index.lsp,index.lua,index.cgi,"
2460 "index.shtml,index.php"},
2461#else
2462 "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
2463#endif
2464 {"access_control_list", MG_CONFIG_TYPE_STRING_LIST, NULL},
2465 {"extra_mime_types", MG_CONFIG_TYPE_STRING_LIST, NULL},
2466 {"ssl_certificate", MG_CONFIG_TYPE_FILE, NULL},
2467 {"ssl_certificate_chain", MG_CONFIG_TYPE_FILE, NULL},
2468 {"url_rewrite_patterns", MG_CONFIG_TYPE_STRING_LIST, NULL},
2469 {"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
2470
2471 {"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"},
2472
2473 {"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL},
2474 {"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL},
2475 {"ssl_verify_depth", MG_CONFIG_TYPE_NUMBER, "9"},
2476 {"ssl_default_verify_paths", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2477 {"ssl_cipher_list", MG_CONFIG_TYPE_STRING, NULL},
2478 {"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "0"},
2479 {"ssl_short_trust", MG_CONFIG_TYPE_BOOLEAN, "no"},
2480
2481#if defined(USE_LUA)
2482 {"lua_preload_file", MG_CONFIG_TYPE_FILE, NULL},
2483 {"lua_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2484 {"lua_server_page_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
2485#if defined(MG_EXPERIMENTAL_INTERFACES)
2486 {"lua_debug", MG_CONFIG_TYPE_STRING, NULL},
2487#endif
2488#endif
2489#if defined(USE_DUKTAPE)
2490 /* The support for duktape is still in alpha version state.
2491 * The name of this config option might change. */
2492 {"duktape_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
2493#endif
2494
2495#if defined(USE_WEBSOCKET)
2496 {"websocket_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
2497#endif
2498#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2499 {"lua_websocket_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2500#endif
2501 {"access_control_allow_origin", MG_CONFIG_TYPE_STRING, "*"},
2502 {"access_control_allow_methods", MG_CONFIG_TYPE_STRING, "*"},
2503 {"access_control_allow_headers", MG_CONFIG_TYPE_STRING, "*"},
2504 {"error_pages", MG_CONFIG_TYPE_DIRECTORY, NULL},
2505#if !defined(NO_CACHING)
2506 {"static_file_max_age", MG_CONFIG_TYPE_NUMBER, "3600"},
2507#endif
2508#if !defined(NO_SSL)
2509 {"strict_transport_security_max_age", MG_CONFIG_TYPE_NUMBER, NULL},
2510#endif
2511 {"additional_header", MG_CONFIG_TYPE_STRING_MULTILINE, NULL},
2512 {"allow_index_script_resource", MG_CONFIG_TYPE_BOOLEAN, "no"},
2513
2514 {NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}};
2515
2516
2517/* Check if the config_options and the corresponding enum have compatible
2518 * sizes. */
2520 == (NUM_OPTIONS + 1),
2521 "config_options and enum not sync");
2522
2523
2525
2526
2527struct mg_handler_info {
2528 /* Name/Pattern of the URI. */
2529 char *uri;
2530 size_t uri_len;
2531
2532 /* handler type */
2533 int handler_type;
2534
2535 /* Handler for http/https or authorization requests. */
2536 mg_request_handler handler;
2537 unsigned int refcount;
2538 pthread_mutex_t refcount_mutex; /* Protects refcount */
2540 refcount_cond; /* Signaled when handler refcount is decremented */
2541
2542 /* Handler for ws/wss (websocket) requests. */
2543 mg_websocket_connect_handler connect_handler;
2544 mg_websocket_ready_handler ready_handler;
2545 mg_websocket_data_handler data_handler;
2546 mg_websocket_close_handler close_handler;
2547
2548 /* accepted subprotocols for ws/wss requests. */
2549 struct mg_websocket_subprotocols *subprotocols;
2550
2551 /* Handler for authorization requests */
2552 mg_authorization_handler auth_handler;
2553
2554 /* User supplied argument for the handler function. */
2555 void *cbdata;
2556
2557 /* next handler in a linked list */
2558 struct mg_handler_info *next;
2559};
2560
2561
2562enum {
2568
2569
2570struct mg_domain_context {
2571 SSL_CTX *ssl_ctx; /* SSL context */
2572 char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
2573 struct mg_handler_info *handlers; /* linked list of uri handlers */
2574
2575 /* Server nonce */
2576 uint64_t auth_nonce_mask; /* Mask for all nonce values */
2577 unsigned long nonce_count; /* Used nonces, used for authentication */
2578
2579#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2580 /* linked list of shared lua websockets */
2581 struct mg_shared_lua_websocket_list *shared_lua_websockets;
2582#endif
2583
2584 /* Linked list of domains */
2585 struct mg_domain_context *next;
2586};
2587
2588
2589struct mg_context {
2590
2591 /* Part 1 - Physical context:
2592 * This holds threads, ports, timeouts, ...
2593 * set for the entire server, independent from the
2594 * addressed hostname.
2595 */
2596
2597 /* Connection related */
2598 int context_type; /* See CONTEXT_* above */
2599
2600 struct socket *listening_sockets;
2601 struct pollfd *listening_socket_fds;
2602 unsigned int num_listening_sockets;
2603
2604 struct mg_connection *worker_connections; /* The connection struct, pre-
2605 * allocated for each worker */
2606
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;
2614#endif
2615
2616 /* Thread related */
2617 volatile int stop_flag; /* Should we stop event loop */
2618 pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
2619
2620 pthread_t masterthreadid; /* The master thread ID */
2621 unsigned int
2622 cfg_worker_threads; /* The number of configured worker threads. */
2623 pthread_t *worker_threadids; /* The worker thread IDs */
2624
2625/* Connection to thread dispatching */
2626#if defined(ALTERNATIVE_QUEUE)
2627 struct socket *client_socks;
2628 void **client_wait_events;
2629#else
2630 struct socket queue[MGSQLEN]; /* Accepted sockets */
2631 volatile int sq_head; /* Head of the socket queue */
2632 volatile int sq_tail; /* Tail of the socket queue */
2633 pthread_cond_t sq_full; /* Signaled when socket is produced */
2634 pthread_cond_t sq_empty; /* Signaled when socket is consumed */
2635#endif
2636
2637 /* Memory related */
2638 unsigned int max_request_size; /* The max request size */
2639
2640#if defined(USE_SERVER_STATS)
2641 struct mg_memory_stat ctx_memory;
2642#endif
2643
2644 /* Operating system related */
2645 char *systemName; /* What operating system is running */
2646 time_t start_time; /* Server start time, used for authentication
2647 * and for diagnstics. */
2648
2649#if defined(USE_TIMERS)
2650 struct ttimers *timers;
2651#endif
2652
2653/* Lua specific: Background operations and shared websockets */
2654#if defined(USE_LUA)
2655 void *lua_background_state;
2656#endif
2657
2658 /* Server nonce */
2659 pthread_mutex_t nonce_mutex; /* Protects nonce_count */
2660
2661 /* Server callbacks */
2662 struct mg_callbacks callbacks; /* User-defined callback function */
2663 void *user_data; /* User-defined data */
2664
2665 /* Part 2 - Logical domain:
2666 * This holds hostname, TLS certificate, document root, ...
2667 * set for a domain hosted at the server.
2668 * There may be multiple domains hosted at one physical server.
2669 * The default domain "dd" is the first element of a list of
2670 * domains.
2671 */
2672 struct mg_domain_context dd; /* default domain */
2673};
2674
2675
2676#if defined(USE_SERVER_STATS)
2677static struct mg_memory_stat mg_common_memory = {0, 0, 0};
2678
2679static struct mg_memory_stat *
2680get_memory_stat(struct mg_context *ctx)
2681{
2682 if (ctx) {
2683 return &(ctx->ctx_memory);
2684 }
2685 return &mg_common_memory;
2686}
2687#endif
2688
2689enum {
2694
2695struct mg_connection {
2696 int connection_type; /* see CONNECTION_TYPE_* above */
2697
2698 struct mg_request_info request_info;
2699 struct mg_response_info response_info;
2700
2701 struct mg_context *phys_ctx;
2702 struct mg_domain_context *dom_ctx;
2703
2704#if defined(USE_SERVER_STATS)
2705 int conn_state; /* 0 = undef, numerical value may change in different
2706 * versions. For the current definition, see
2707 * mg_get_connection_info_impl */
2708#endif
2709
2710 const char *host; /* Host (HTTP/1.1 header or SNI) */
2711 SSL *ssl; /* SSL descriptor */
2712 SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
2713 struct socket client; /* Connected client */
2714 time_t conn_birth_time; /* Time (wall clock) when connection was
2715 * established */
2716 struct timespec req_time; /* Time (since system start) when the request
2717 * was received */
2718 int64_t num_bytes_sent; /* Total bytes sent to client */
2719 int64_t content_len; /* Content-Length header value */
2720 int64_t consumed_content; /* How many bytes of content have been read */
2721 int is_chunked; /* Transfer-Encoding is chunked:
2722 * 0 = not chunked,
2723 * 1 = chunked, do data read yet,
2724 * 2 = chunked, some data read,
2725 * 3 = chunked, all data read
2726 */
2727 size_t chunk_remainder; /* Unread data from the last chunk */
2728 char *buf; /* Buffer for received data */
2729 char *path_info; /* PATH_INFO part of the URL */
2730
2731 int must_close; /* 1 if connection must be closed */
2732 int accept_gzip; /* 1 if gzip encoding is accepted */
2733 int in_error_handler; /* 1 if in handler for user defined error
2734 * pages */
2735#if defined(USE_WEBSOCKET)
2736 int in_websocket_handling; /* 1 if in read_websocket */
2737#endif
2738 int handled_requests; /* Number of requests handled by this connection
2739 */
2740 int buf_size; /* Buffer size */
2741 int request_len; /* Size of the request + headers in a buffer */
2742 int data_len; /* Total size of data in a buffer */
2743 int status_code; /* HTTP reply status code, e.g. 200 */
2744 int throttle; /* Throttling, bytes/sec. <= 0 means no
2745 * throttle */
2746
2747 time_t last_throttle_time; /* Last time throttled data was sent */
2748 int64_t last_throttle_bytes; /* Bytes sent this second */
2749 pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure
2750 * atomic transmissions for websockets */
2751#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2752 void *lua_websocket_state; /* Lua_State for a websocket connection */
2753#endif
2754
2755 int thread_index; /* Thread index within ctx */
2756};
2757
2758
2759/* Directory entry */
2760struct de {
2761 struct mg_connection *conn;
2762 char *file_name;
2763 struct mg_file_stat file;
2764};
2765
2766
2767#if defined(USE_WEBSOCKET)
2768static int is_websocket_protocol(const struct mg_connection *conn);
2769#else
2770#define is_websocket_protocol(conn) (0)
2771#endif
2772
2773
2774#define mg_cry_internal(conn, fmt, ...) \
2775 mg_cry_internal_wrap(conn, __func__, __LINE__, fmt, __VA_ARGS__)
2776
2777static void mg_cry_internal_wrap(const struct mg_connection *conn,
2778 const char *func,
2779 unsigned line,
2780 const char *fmt,
2781 ...) PRINTF_ARGS(4, 5);
2782
2783
2784#if !defined(NO_THREAD_NAME)
2785#if defined(_WIN32) && defined(_MSC_VER)
2786/* Set the thread name for debugging purposes in Visual Studio
2787 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
2788 */
2789#pragma pack(push, 8)
2790typedef struct tagTHREADNAME_INFO {
2791 DWORD dwType; /* Must be 0x1000. */
2792 LPCSTR szName; /* Pointer to name (in user addr space). */
2793 DWORD dwThreadID; /* Thread ID (-1=caller thread). */
2794 DWORD dwFlags; /* Reserved for future use, must be zero. */
2795} THREADNAME_INFO;
2796#pragma pack(pop)
2797
2798#elif defined(__linux__)
2799
2800#include <sys/prctl.h>
2801#include <sys/sendfile.h>
2802#if defined(ALTERNATIVE_QUEUE)
2803#include <sys/eventfd.h>
2804#endif /* ALTERNATIVE_QUEUE */
2805
2806
2807#if defined(ALTERNATIVE_QUEUE)
2808
2809static void *
2810event_create(void)
2811{
2812 int evhdl = eventfd(0, EFD_CLOEXEC);
2813 int *ret;
2814
2815 if (evhdl == -1) {
2816 /* Linux uses -1 on error, Windows NULL. */
2817 /* However, Linux does not return 0 on success either. */
2818 return 0;
2819 }
2820
2821 ret = (int *)mg_malloc(sizeof(int));
2822 if (ret) {
2823 *ret = evhdl;
2824 } else {
2825 (void)close(evhdl);
2826 }
2827
2828 return (void *)ret;
2829}
2830
2831
2832static int
2833event_wait(void *eventhdl)
2834{
2835 uint64_t u;
2836 int evhdl, s;
2837
2838 if (!eventhdl) {
2839 /* error */
2840 return 0;
2841 }
2842 evhdl = *(int *)eventhdl;
2843
2844 s = (int)read(evhdl, &u, sizeof(u));
2845 if (s != sizeof(u)) {
2846 /* error */
2847 return 0;
2848 }
2849 (void)u; /* the value is not required */
2850 return 1;
2851}
2852
2853
2854static int
2855event_signal(void *eventhdl)
2856{
2857 uint64_t u = 1;
2858 int evhdl, s;
2859
2860 if (!eventhdl) {
2861 /* error */
2862 return 0;
2863 }
2864 evhdl = *(int *)eventhdl;
2865
2866 s = (int)write(evhdl, &u, sizeof(u));
2867 if (s != sizeof(u)) {
2868 /* error */
2869 return 0;
2870 }
2871 return 1;
2872}
2873
2874
2875static void
2876event_destroy(void *eventhdl)
2877{
2878 int evhdl;
2879
2880 if (!eventhdl) {
2881 /* error */
2882 return;
2883 }
2884 evhdl = *(int *)eventhdl;
2885
2886 close(evhdl);
2887 mg_free(eventhdl);
2888}
2889
2890
2891#endif
2892
2893#endif
2894
2895
2896#if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE)
2897
2898struct posix_event {
2899 pthread_mutex_t mutex;
2900 pthread_cond_t cond;
2901};
2902
2903
2904static void *
2906{
2907 struct posix_event *ret = mg_malloc(sizeof(struct posix_event));
2908 if (ret == 0) {
2909 /* out of memory */
2910 return 0;
2911 }
2912 if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
2913 /* pthread mutex not available */
2914 mg_free(ret);
2915 return 0;
2916 }
2917 if (0 != pthread_cond_init(&(ret->cond), NULL)) {
2918 /* pthread cond not available */
2919 pthread_mutex_destroy(&(ret->mutex));
2920 mg_free(ret);
2921 return 0;
2922 }
2923 return (void *)ret;
2924}
2925
2926
2927static int
2928event_wait(void *eventhdl)
2929{
2930 struct posix_event *ev = (struct posix_event *)eventhdl;
2931 pthread_mutex_lock(&(ev->mutex));
2932 pthread_cond_wait(&(ev->cond), &(ev->mutex));
2933 pthread_mutex_unlock(&(ev->mutex));
2934 return 1;
2935}
2936
2937
2938static int
2939event_signal(void *eventhdl)
2940{
2941 struct posix_event *ev = (struct posix_event *)eventhdl;
2942 pthread_mutex_lock(&(ev->mutex));
2943 pthread_cond_signal(&(ev->cond));
2944 pthread_mutex_unlock(&(ev->mutex));
2945 return 1;
2946}
2947
2948
2949static void
2950event_destroy(void *eventhdl)
2951{
2952 struct posix_event *ev = (struct posix_event *)eventhdl;
2953 pthread_cond_destroy(&(ev->cond));
2954 pthread_mutex_destroy(&(ev->mutex));
2955 mg_free(ev);
2956}
2957#endif
2958
2959
2960static void
2962{
2963 char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
2964
2966 NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
2967
2968#if defined(_WIN32)
2969#if defined(_MSC_VER)
2970 /* Windows and Visual Studio Compiler */
2971 __try {
2972 THREADNAME_INFO info;
2973 info.dwType = 0x1000;
2974 info.szName = threadName;
2975 info.dwThreadID = ~0U;
2976 info.dwFlags = 0;
2977
2978 RaiseException(0x406D1388,
2979 0,
2980 sizeof(info) / sizeof(ULONG_PTR),
2981 (ULONG_PTR *)&info);
2982 } __except (EXCEPTION_EXECUTE_HANDLER) {
2983 }
2984#elif defined(__MINGW32__)
2985/* No option known to set thread name for MinGW */
2986#endif
2987#elif defined(_GNU_SOURCE) && defined(__GLIBC__) \
2988 && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
2989/* pthread_setname_np first appeared in glibc in version 2.12*/
2990#if defined(__MACH__)
2991 /* OS X only current thread name can be changed */
2992 (void)pthread_setname_np(threadName);
2993#else
2994 (void)pthread_setname_np(pthread_self(), threadName);
2995#endif
2996#elif defined(__linux__)
2997 /* on linux we can use the old prctl function */
2998 (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
2999#endif
3000}
3001#else /* !defined(NO_THREAD_NAME) */
3002void
3003mg_set_thread_name(const char *threadName)
3004{
3005}
3006#endif
3007
3008
3009#if defined(MG_LEGACY_INTERFACE)
3010const char **
3011mg_get_valid_option_names(void)
3012{
3013 /* This function is deprecated. Use mg_get_valid_options instead. */
3014 static const char
3015 *data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
3016 int i;
3017
3018 for (i = 0; config_options[i].name != NULL; i++) {
3019 data[i * 2] = config_options[i].name;
3020 data[i * 2 + 1] = config_options[i].default_value;
3021 }
3022
3023 return data;
3024}
3025#endif
3026
3027
3028const struct mg_option *
3030{
3031 return config_options;
3032}
3033
3034
3035/* Do not open file (used in is_file_in_memory) */
3036#define MG_FOPEN_MODE_NONE (0)
3037
3038/* Open file for read only access */
3039#define MG_FOPEN_MODE_READ (1)
3040
3041/* Open file for writing, create and overwrite */
3042#define MG_FOPEN_MODE_WRITE (2)
3043
3044/* Open file for writing, create and append */
3045#define MG_FOPEN_MODE_APPEND (4)
3046
3047
3048/* If a file is in memory, set all "stat" members and the membuf pointer of
3049 * output filep and return 1, otherwise return 0 and don't modify anything.
3050 */
3051static int
3052open_file_in_memory(const struct mg_connection *conn,
3053 const char *path,
3054 struct mg_file *filep,
3055 int mode)
3056{
3057#if defined(MG_USE_OPEN_FILE)
3058
3059 size_t size = 0;
3060 const char *buf = NULL;
3061 if (!conn) {
3062 return 0;
3063 }
3064
3065 if ((mode != MG_FOPEN_MODE_NONE) && (mode != MG_FOPEN_MODE_READ)) {
3066 return 0;
3067 }
3068
3069 if (conn->phys_ctx->callbacks.open_file) {
3070 buf = conn->phys_ctx->callbacks.open_file(conn, path, &size);
3071 if (buf != NULL) {
3072 if (filep == NULL) {
3073 /* This is a file in memory, but we cannot store the
3074 * properties
3075 * now.
3076 * Called from "is_file_in_memory" function. */
3077 return 1;
3078 }
3079
3080 /* NOTE: override filep->size only on success. Otherwise, it
3081 * might
3082 * break constructs like if (!mg_stat() || !mg_fopen()) ... */
3083 filep->access.membuf = buf;
3084 filep->access.fp = NULL;
3085
3086 /* Size was set by the callback */
3087 filep->stat.size = size;
3088
3089 /* Assume the data may change during runtime by setting
3090 * last_modified = now */
3091 filep->stat.last_modified = time(NULL);
3092
3093 filep->stat.is_directory = 0;
3094 filep->stat.is_gzipped = 0;
3095 }
3096 }
3097
3098 return (buf != NULL);
3099
3100#else
3101 (void)conn;
3102 (void)path;
3103 (void)filep;
3104 (void)mode;
3105
3106 return 0;
3107
3108#endif
3109}
3110
3111
3112static int
3113is_file_in_memory(const struct mg_connection *conn, const char *path)
3114{
3115 return open_file_in_memory(conn, path, NULL, MG_FOPEN_MODE_NONE);
3116}
3117
3118
3119static int
3120is_file_opened(const struct mg_file_access *fileacc)
3121{
3122 if (!fileacc) {
3123 return 0;
3124 }
3125
3126#if defined(MG_USE_OPEN_FILE)
3127 return (fileacc->membuf != NULL) || (fileacc->fp != NULL);
3128#else
3129 return (fileacc->fp != NULL);
3130#endif
3131}
3132
3133
3134static int mg_stat(const struct mg_connection *conn,
3135 const char *path,
3136 struct mg_file_stat *filep);
3137
3138
3139/* mg_fopen will open a file either in memory or on the disk.
3140 * The input parameter path is a string in UTF-8 encoding.
3141 * The input parameter mode is MG_FOPEN_MODE_*
3142 * On success, either fp or membuf will be set in the output
3143 * struct file. All status members will also be set.
3144 * The function returns 1 on success, 0 on error. */
3145static int
3146mg_fopen(const struct mg_connection *conn,
3147 const char *path,
3148 int mode,
3149 struct mg_file *filep)
3150{
3151 int found;
3152
3153 if (!filep) {
3154 return 0;
3155 }
3156 filep->access.fp = NULL;
3157#if defined(MG_USE_OPEN_FILE)
3158 filep->access.membuf = NULL;
3159#endif
3160
3161 if (!is_file_in_memory(conn, path)) {
3162
3163 /* filep is initialized in mg_stat: all fields with memset to,
3164 * some fields like size and modification date with values */
3165 found = mg_stat(conn, path, &(filep->stat));
3166
3167 if ((mode == MG_FOPEN_MODE_READ) && (!found)) {
3168 /* file does not exist and will not be created */
3169 return 0;
3170 }
3171
3172#if defined(_WIN32)
3173 {
3174 wchar_t wbuf[W_PATH_MAX];
3175 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3176 switch (mode) {
3177 case MG_FOPEN_MODE_READ:
3178 filep->access.fp = _wfopen(wbuf, L"rb");
3179 break;
3181 filep->access.fp = _wfopen(wbuf, L"wb");
3182 break;
3184 filep->access.fp = _wfopen(wbuf, L"ab");
3185 break;
3186 }
3187 }
3188#else
3189 /* Linux et al already use unicode. No need to convert. */
3190 switch (mode) {
3191 case MG_FOPEN_MODE_READ:
3192 filep->access.fp = fopen(path, "r");
3193 break;
3195 filep->access.fp = fopen(path, "w");
3196 break;
3198 filep->access.fp = fopen(path, "a");
3199 break;
3200 }
3201
3202#endif
3203 if (!found) {
3204 /* File did not exist before fopen was called.
3205 * Maybe it has been created now. Get stat info
3206 * like creation time now. */
3207 found = mg_stat(conn, path, &(filep->stat));
3208 (void)found;
3209 }
3210
3211 /* file is on disk */
3212 return (filep->access.fp != NULL);
3213
3214 } else {
3215#if defined(MG_USE_OPEN_FILE)
3216 /* is_file_in_memory returned true */
3217 if (open_file_in_memory(conn, path, filep, mode)) {
3218 /* file is in memory */
3219 return (filep->access.membuf != NULL);
3220 }
3221#endif
3222 }
3223
3224 /* Open failed */
3225 return 0;
3226}
3227
3228
3229/* return 0 on success, just like fclose */
3230static int
3231mg_fclose(struct mg_file_access *fileacc)
3232{
3233 int ret = -1;
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) {
3239 ret = 0;
3240#endif
3241 }
3242 /* reset all members of fileacc */
3243 memset(fileacc, 0, sizeof(*fileacc));
3244 }
3245 return ret;
3246}
3247
3248
3249static void
3250mg_strlcpy(register char *dst, register const char *src, size_t n)
3251{
3252 for (; *src != '\0' && n > 1; n--) {
3253 *dst++ = *src++;
3254 }
3255 *dst = '\0';
3256}
3257
3258
3259static int
3260lowercase(const char *s)
3261{
3262 return tolower(*(const unsigned char *)s);
3263}
3264
3265
3266int
3267mg_strncasecmp(const char *s1, const char *s2, size_t len)
3268{
3269 int diff = 0;
3270
3271 if (len > 0) {
3272 do {
3273 diff = lowercase(s1++) - lowercase(s2++);
3274 } while (diff == 0 && s1[-1] != '\0' && --len > 0);
3275 }
3276
3277 return diff;
3278}
3279
3280
3281int
3282mg_strcasecmp(const char *s1, const char *s2)
3283{
3284 int diff;
3285
3286 do {
3287 diff = lowercase(s1++) - lowercase(s2++);
3288 } while (diff == 0 && s1[-1] != '\0');
3289
3290 return diff;
3291}
3292
3293
3294static char *
3295mg_strndup_ctx(const char *ptr, size_t len, struct mg_context *ctx)
3296{
3297 char *p;
3298 (void)ctx; /* Avoid Visual Studio warning if USE_SERVER_STATS is not
3299 * defined */
3300
3301 if ((p = (char *)mg_malloc_ctx(len + 1, ctx)) != NULL) {
3302 mg_strlcpy(p, ptr, len + 1);
3303 }
3304
3305 return p;
3306}
3307
3308
3309static char *
3310mg_strdup_ctx(const char *str, struct mg_context *ctx)
3311{
3312 return mg_strndup_ctx(str, strlen(str), ctx);
3313}
3314
3315static char *
3316mg_strdup(const char *str)
3317{
3318 return mg_strndup_ctx(str, strlen(str), NULL);
3319}
3320
3321
3322static const char *
3323mg_strcasestr(const char *big_str, const char *small_str)
3324{
3325 size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
3326
3327 if (big_len >= small_len) {
3328 for (i = 0; i <= (big_len - small_len); i++) {
3329 if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
3330 return big_str + i;
3331 }
3332 }
3333 }
3334
3335 return NULL;
3336}
3337
3338
3339/* Return null terminated string of given maximum length.
3340 * Report errors if length is exceeded. */
3341static void
3342mg_vsnprintf(const struct mg_connection *conn,
3343 int *truncated,
3344 char *buf,
3345 size_t buflen,
3346 const char *fmt,
3347 va_list ap)
3348{
3349 int n, ok;
3350
3351 if (buflen == 0) {
3352 if (truncated) {
3353 *truncated = 1;
3354 }
3355 return;
3356 }
3357
3358#if defined(__clang__)
3359#pragma clang diagnostic push
3360#pragma clang diagnostic ignored "-Wformat-nonliteral"
3361/* Using fmt as a non-literal is intended here, since it is mostly called
3362 * indirectly by mg_snprintf */
3363#endif
3364
3365 n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
3366 ok = (n >= 0) && ((size_t)n < buflen);
3367
3368#if defined(__clang__)
3369#pragma clang diagnostic pop
3370#endif
3371
3372 if (ok) {
3373 if (truncated) {
3374 *truncated = 0;
3375 }
3376 } else {
3377 if (truncated) {
3378 *truncated = 1;
3379 }
3380 mg_cry_internal(conn,
3381 "truncating vsnprintf buffer: [%.*s]",
3382 (int)((buflen > 200) ? 200 : (buflen - 1)),
3383 buf);
3384 n = (int)buflen - 1;
3385 }
3386 buf[n] = '\0';
3387}
3388
3389
3390static void
3391mg_snprintf(const struct mg_connection *conn,
3392 int *truncated,
3393 char *buf,
3394 size_t buflen,
3395 const char *fmt,
3396 ...)
3397{
3398 va_list ap;
3399
3400 va_start(ap, fmt);
3401 mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
3402 va_end(ap);
3403}
3404
3405
3406static int
3408{
3409 int i;
3410
3411 for (i = 0; config_options[i].name != NULL; i++) {
3412 if (strcmp(config_options[i].name, name) == 0) {
3413 return i;
3414 }
3415 }
3416 return -1;
3417}
3418
3419
3420const char *
3421mg_get_option(const struct mg_context *ctx, const char *name)
3422{
3423 int i;
3424 if ((i = get_option_index(name)) == -1) {
3425 return NULL;
3426 } else if (!ctx || ctx->dd.config[i] == NULL) {
3427 return "";
3428 } else {
3429 return ctx->dd.config[i];
3430 }
3431}
3432
3433#define mg_get_option DO_NOT_USE_THIS_FUNCTION_INTERNALLY__access_directly
3434
3435struct mg_context *
3436mg_get_context(const struct mg_connection *conn)
3437{
3438 return (conn == NULL) ? (struct mg_context *)NULL : (conn->phys_ctx);
3439}
3440
3441
3442void *
3443mg_get_user_data(const struct mg_context *ctx)
3444{
3445 return (ctx == NULL) ? NULL : ctx->user_data;
3446}
3447
3448
3449void
3450mg_set_user_connection_data(struct mg_connection *conn, void *data)
3451{
3452 if (conn != NULL) {
3453 conn->request_info.conn_data = data;
3454 }
3455}
3456
3457
3458void *
3459mg_get_user_connection_data(const struct mg_connection *conn)
3460{
3461 if (conn != NULL) {
3462 return conn->request_info.conn_data;
3463 }
3464 return NULL;
3465}
3466
3467
3468#if defined(MG_LEGACY_INTERFACE)
3469/* Deprecated: Use mg_get_server_ports instead. */
3470size_t
3471mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
3472{
3473 size_t i;
3474 if (!ctx) {
3475 return 0;
3476 }
3477 for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
3478 ssl[i] = ctx->listening_sockets[i].is_ssl;
3479 ports[i] =
3480#if defined(USE_IPV6)
3481 (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3482 ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3483 :
3484#endif
3485 ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3486 }
3487 return i;
3488}
3489#endif
3490
3491
3492int
3493mg_get_server_ports(const struct mg_context *ctx,
3494 int size,
3495 struct mg_server_ports *ports)
3496{
3497 int i, cnt = 0;
3498
3499 if (size <= 0) {
3500 return -1;
3501 }
3502 memset(ports, 0, sizeof(*ports) * (size_t)size);
3503 if (!ctx) {
3504 return -1;
3505 }
3506 if (!ctx->listening_sockets) {
3507 return -1;
3508 }
3509
3510 for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
3511
3512 ports[cnt].port =
3513#if defined(USE_IPV6)
3514 (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3515 ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3516 :
3517#endif
3518 ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3519 ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
3520 ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
3521
3522 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
3523 /* IPv4 */
3524 ports[cnt].protocol = 1;
3525 cnt++;
3526 } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
3527 /* IPv6 */
3528 ports[cnt].protocol = 3;
3529 cnt++;
3530 }
3531 }
3532
3533 return cnt;
3534}
3535
3536
3537static void
3538sockaddr_to_string(char *buf, size_t len, const union usa *usa)
3539{
3540 buf[0] = '\0';
3541
3542 if (!usa) {
3543 return;
3544 }
3545
3546 if (usa->sa.sa_family == AF_INET) {
3547 getnameinfo(&usa->sa,
3548 sizeof(usa->sin),
3549 buf,
3550 (unsigned)len,
3551 NULL,
3552 0,
3553 NI_NUMERICHOST);
3554 }
3555#if defined(USE_IPV6)
3556 else if (usa->sa.sa_family == AF_INET6) {
3557 getnameinfo(&usa->sa,
3558 sizeof(usa->sin6),
3559 buf,
3560 (unsigned)len,
3561 NULL,
3562 0,
3563 NI_NUMERICHOST);
3564 }
3565#endif
3566}
3567
3568
3569/* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
3570 * included in all responses other than 100, 101, 5xx. */
3571static void
3572gmt_time_string(char *buf, size_t buf_len, time_t *t)
3573{
3574#if !defined(REENTRANT_TIME)
3575 struct tm *tm;
3576
3577 tm = ((t != NULL) ? gmtime(t) : NULL);
3578 if (tm != NULL) {
3579#else
3580 struct tm _tm;
3581 struct tm *tm = &_tm;
3582
3583 if (t != NULL) {
3584 gmtime_r(t, tm);
3585#endif
3586 strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
3587 } else {
3588 mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
3589 buf[buf_len - 1] = '\0';
3590 }
3591}
3592
3593
3594/* difftime for struct timespec. Return value is in seconds. */
3595static double
3596mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
3597{
3598 return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
3599 + (double)(ts_now->tv_sec - ts_before->tv_sec);
3600}
3601
3602
3603#if defined(MG_EXTERNAL_FUNCTION_mg_cry_internal_impl)
3604static void mg_cry_internal_impl(const struct mg_connection *conn,
3605 const char *func,
3606 unsigned line,
3607 const char *fmt,
3608 va_list ap);
3609#include "external_mg_cry_internal_impl.inl"
3610#else
3611
3612/* Print error message to the opened error log stream. */
3613static void
3614mg_cry_internal_impl(const struct mg_connection *conn,
3615 const char *func,
3616 unsigned line,
3617 const char *fmt,
3618 va_list ap)
3619{
3620 char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
3621 struct mg_file fi;
3622 time_t timestamp;
3623
3624 /* Unused, in the RELEASE build */
3625 (void)func;
3626 (void)line;
3627
3628#if defined(GCC_DIAGNOSTIC)
3629#pragma GCC diagnostic push
3630#pragma GCC diagnostic ignored "-Wformat-nonliteral"
3631#endif
3632
3633 IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
3634
3635#if defined(GCC_DIAGNOSTIC)
3636#pragma GCC diagnostic pop
3637#endif
3638
3639 buf[sizeof(buf) - 1] = 0;
3640
3641 DEBUG_TRACE("mg_cry called from %s:%u: %s", func, line, buf);
3642
3643 if (!conn) {
3644 puts(buf);
3645 return;
3646 }
3647
3648 /* Do not lock when getting the callback value, here and below.
3649 * I suppose this is fine, since function cannot disappear in the
3650 * same way string option can. */
3651 if ((conn->phys_ctx->callbacks.log_message == NULL)
3652 || (conn->phys_ctx->callbacks.log_message(conn, buf) == 0)) {
3653
3654 if (conn->dom_ctx->config[ERROR_LOG_FILE] != NULL) {
3655 if (mg_fopen(conn,
3656 conn->dom_ctx->config[ERROR_LOG_FILE],
3658 &fi)
3659 == 0) {
3660 fi.access.fp = NULL;
3661 }
3662 } else {
3663 fi.access.fp = NULL;
3664 }
3665
3666 if (fi.access.fp != NULL) {
3667 flockfile(fi.access.fp);
3668 timestamp = time(NULL);
3669
3670 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
3671 fprintf(fi.access.fp,
3672 "[%010lu] [error] [client %s] ",
3673 (unsigned long)timestamp,
3674 src_addr);
3675
3676 if (conn->request_info.request_method != NULL) {
3677 fprintf(fi.access.fp,
3678 "%s %s: ",
3679 conn->request_info.request_method,
3680 conn->request_info.request_uri
3681 ? conn->request_info.request_uri
3682 : "");
3683 }
3684
3685 fprintf(fi.access.fp, "%s", buf);
3686 fputc('\n', fi.access.fp);
3687 fflush(fi.access.fp);
3688 funlockfile(fi.access.fp);
3689 (void)mg_fclose(&fi.access); /* Ignore errors. We can't call
3690 * mg_cry here anyway ;-) */
3691 }
3692 }
3693}
3694
3695#endif /* Externally provided function */
3696
3697
3698static void
3699mg_cry_internal_wrap(const struct mg_connection *conn,
3700 const char *func,
3701 unsigned line,
3702 const char *fmt,
3703 ...)
3704{
3705 va_list ap;
3706 va_start(ap, fmt);
3707 mg_cry_internal_impl(conn, func, line, fmt, ap);
3708 va_end(ap);
3709}
3710
3711
3712void
3713mg_cry(const struct mg_connection *conn, const char *fmt, ...)
3714{
3715 va_list ap;
3716 va_start(ap, fmt);
3717 mg_cry_internal_impl(conn, "user", 0, fmt, ap);
3718 va_end(ap);
3719}
3720
3721
3722#define mg_cry DO_NOT_USE_THIS_FUNCTION__USE_mg_cry_internal
3723
3724
3725/* Return fake connection structure. Used for logging, if connection
3726 * is not applicable at the moment of logging. */
3727static struct mg_connection *
3728fc(struct mg_context *ctx)
3729{
3730 static struct mg_connection fake_connection;
3731 fake_connection.phys_ctx = ctx;
3732 fake_connection.dom_ctx = &(ctx->dd);
3733 return &fake_connection;
3734}
3735
3736
3737const char *
3739{
3740 return CIVETWEB_VERSION;
3741}
3742
3743
3744const struct mg_request_info *
3745mg_get_request_info(const struct mg_connection *conn)
3746{
3747 if (!conn) {
3748 return NULL;
3749 }
3750#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
3751 if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
3752 char txt[16];
3753 struct mg_workerTLS *tls =
3754 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3755
3756 sprintf(txt, "%03i", conn->response_info.status_code);
3757 if (strlen(txt) == 3) {
3758 memcpy(tls->txtbuf, txt, 4);
3759 } else {
3760 strcpy(tls->txtbuf, "ERR");
3761 }
3762
3763 ((struct mg_connection *)conn)->request_info.local_uri =
3764 ((struct mg_connection *)conn)->request_info.request_uri =
3765 tls->txtbuf; /* use thread safe buffer */
3766
3767 ((struct mg_connection *)conn)->request_info.num_headers =
3768 conn->response_info.num_headers;
3769 memcpy(((struct mg_connection *)conn)->request_info.http_headers,
3770 conn->response_info.http_headers,
3771 sizeof(conn->response_info.http_headers));
3772 } else
3773#endif
3774 if (conn->connection_type != CONNECTION_TYPE_REQUEST) {
3775 return NULL;
3776 }
3777 return &conn->request_info;
3778}
3779
3780
3781const struct mg_response_info *
3782mg_get_response_info(const struct mg_connection *conn)
3783{
3784 if (!conn) {
3785 return NULL;
3786 }
3787 if (conn->connection_type != CONNECTION_TYPE_RESPONSE) {
3788 return NULL;
3789 }
3790 return &conn->response_info;
3791}
3792
3793
3794static const char *
3795get_proto_name(const struct mg_connection *conn)
3796{
3797#if defined(__clang__)
3798#pragma clang diagnostic push
3799#pragma clang diagnostic ignored "-Wunreachable-code"
3800/* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be
3801 * not supported. Clang raises an "unreachable code" warning for parts of ?:
3802 * unreachable, but splitting into four different #ifdef clauses here is more
3803 * complicated.
3804 */
3805#endif
3806
3807 const struct mg_request_info *ri = &conn->request_info;
3808
3809 const char *proto =
3810 (is_websocket_protocol(conn) ? (ri->is_ssl ? "wss" : "ws")
3811 : (ri->is_ssl ? "https" : "http"));
3812
3813 return proto;
3814
3815#if defined(__clang__)
3816#pragma clang diagnostic pop
3817#endif
3818}
3819
3820
3821int
3822mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
3823{
3824 if ((buflen < 1) || (buf == 0) || (conn == 0)) {
3825 return -1;
3826 } else {
3827
3828 int truncated = 0;
3829 const struct mg_request_info *ri = &conn->request_info;
3830
3831 const char *proto = get_proto_name(conn);
3832
3833 if (ri->local_uri == NULL) {
3834 return -1;
3835 }
3836
3837 if ((ri->request_uri != NULL)
3838 && (0 != strcmp(ri->local_uri, ri->request_uri))) {
3839 /* The request uri is different from the local uri.
3840 * This is usually if an absolute URI, including server
3841 * name has been provided. */
3842 mg_snprintf(conn,
3843 &truncated,
3844 buf,
3845 buflen,
3846 "%s://%s",
3847 proto,
3848 ri->request_uri);
3849 if (truncated) {
3850 return -1;
3851 }
3852 return 0;
3853
3854 } else {
3855
3856 /* The common case is a relative URI, so we have to
3857 * construct an absolute URI from server name and port */
3858
3859#if defined(USE_IPV6)
3860 int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
3861 int port = is_ipv6 ? htons(conn->client.lsa.sin6.sin6_port)
3862 : htons(conn->client.lsa.sin.sin_port);
3863#else
3864 int port = htons(conn->client.lsa.sin.sin_port);
3865#endif
3866 int def_port = ri->is_ssl ? 443 : 80;
3867 int auth_domain_check_enabled =
3868 conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK]
3869 && (!mg_strcasecmp(
3870 conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes"));
3871 const char *server_domain =
3872 conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
3873
3874 char portstr[16];
3875 char server_ip[48];
3876
3877 if (port != def_port) {
3878 sprintf(portstr, ":%u", (unsigned)port);
3879 } else {
3880 portstr[0] = 0;
3881 }
3882
3883 if (!auth_domain_check_enabled || !server_domain) {
3884
3885 sockaddr_to_string(server_ip,
3886 sizeof(server_ip),
3887 &conn->client.lsa);
3888
3889 server_domain = server_ip;
3890 }
3891
3892 mg_snprintf(conn,
3893 &truncated,
3894 buf,
3895 buflen,
3896 "%s://%s%s%s",
3897 proto,
3898 server_domain,
3899 portstr,
3900 ri->local_uri);
3901 if (truncated) {
3902 return -1;
3903 }
3904 return 0;
3905 }
3906 }
3907}
3908
3909/* Skip the characters until one of the delimiters characters found.
3910 * 0-terminate resulting word. Skip the delimiter and following whitespaces.
3911 * Advance pointer to buffer to the next word. Return found 0-terminated
3912 * word.
3913 * Delimiters can be quoted with quotechar. */
3914static char *
3915skip_quoted(char **buf,
3916 const char *delimiters,
3917 const char *whitespace,
3918 char quotechar)
3919{
3920 char *p, *begin_word, *end_word, *end_whitespace;
3921
3922 begin_word = *buf;
3923 end_word = begin_word + strcspn(begin_word, delimiters);
3924
3925 /* Check for quotechar */
3926 if (end_word > begin_word) {
3927 p = end_word - 1;
3928 while (*p == quotechar) {
3929 /* While the delimiter is quoted, look for the next delimiter.
3930 */
3931 /* This happens, e.g., in calls from parse_auth_header,
3932 * if the user name contains a " character. */
3933
3934 /* If there is anything beyond end_word, copy it. */
3935 if (*end_word != '\0') {
3936 size_t end_off = strcspn(end_word + 1, delimiters);
3937 memmove(p, end_word, end_off + 1);
3938 p += end_off; /* p must correspond to end_word - 1 */
3939 end_word += end_off + 1;
3940 } else {
3941 *p = '\0';
3942 break;
3943 }
3944 }
3945 for (p++; p < end_word; p++) {
3946 *p = '\0';
3947 }
3948 }
3949
3950 if (*end_word == '\0') {
3951 *buf = end_word;
3952 } else {
3953
3954#if defined(GCC_DIAGNOSTIC)
3955/* Disable spurious conversion warning for GCC */
3956#pragma GCC diagnostic push
3957#pragma GCC diagnostic ignored "-Wsign-conversion"
3958#endif /* defined(GCC_DIAGNOSTIC) */
3959
3960 end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
3961
3962#if defined(GCC_DIAGNOSTIC)
3963#pragma GCC diagnostic pop
3964#endif /* defined(GCC_DIAGNOSTIC) */
3965
3966 for (p = end_word; p < end_whitespace; p++) {
3967 *p = '\0';
3968 }
3969
3970 *buf = end_whitespace;
3971 }
3972
3973 return begin_word;
3974}
3975
3976
3977/* Return HTTP header value, or NULL if not found. */
3978static const char *
3979get_header(const struct mg_header *hdr, int num_hdr, const char *name)
3980{
3981 int i;
3982 for (i = 0; i < num_hdr; i++) {
3983 if (!mg_strcasecmp(name, hdr[i].name)) {
3984 return hdr[i].value;
3985 }
3986 }
3987
3988 return NULL;
3989}
3990
3991
3992#if defined(USE_WEBSOCKET)
3993/* Retrieve requested HTTP header multiple values, and return the number of
3994 * found occurrences */
3995static int
3996get_req_headers(const struct mg_request_info *ri,
3997 const char *name,
3998 const char **output,
3999 int output_max_size)
4000{
4001 int i;
4002 int cnt = 0;
4003 if (ri) {
4004 for (i = 0; i < ri->num_headers && cnt < output_max_size; i++) {
4005 if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
4006 output[cnt++] = ri->http_headers[i].value;
4007 }
4008 }
4009 }
4010 return cnt;
4011}
4012#endif
4013
4014
4015const char *
4016mg_get_header(const struct mg_connection *conn, const char *name)
4017{
4018 if (!conn) {
4019 return NULL;
4020 }
4021
4022 if (conn->connection_type == CONNECTION_TYPE_REQUEST) {
4023 return get_header(conn->request_info.http_headers,
4024 conn->request_info.num_headers,
4025 name);
4026 }
4027 if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
4028 return get_header(conn->response_info.http_headers,
4029 conn->response_info.num_headers,
4030 name);
4031 }
4032 return NULL;
4033}
4034
4035
4036static const char *
4037get_http_version(const struct mg_connection *conn)
4038{
4039 if (!conn) {
4040 return NULL;
4041 }
4042
4043 if (conn->connection_type == CONNECTION_TYPE_REQUEST) {
4044 return conn->request_info.http_version;
4045 }
4046 if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
4047 return conn->response_info.http_version;
4048 }
4049 return NULL;
4050}
4051
4052
4053/* A helper function for traversing a comma separated list of values.
4054 * It returns a list pointer shifted to the next value, or NULL if the end
4055 * of the list found.
4056 * Value is stored in val vector. If value has form "x=y", then eq_val
4057 * vector is initialized to point to the "y" part, and val vector length
4058 * is adjusted to point only to "x". */
4059static const char *
4060next_option(const char *list, struct vec *val, struct vec *eq_val)
4061{
4062 int end;
4063
4064reparse:
4065 if (val == NULL || list == NULL || *list == '\0') {
4066 /* End of the list */
4067 return NULL;
4068 }
4069
4070 /* Skip over leading LWS */
4071 while (*list == ' ' || *list == '\t')
4072 list++;
4073
4074 val->ptr = list;
4075 if ((list = strchr(val->ptr, ',')) != NULL) {
4076 /* Comma found. Store length and shift the list ptr */
4077 val->len = ((size_t)(list - val->ptr));
4078 list++;
4079 } else {
4080 /* This value is the last one */
4081 list = val->ptr + strlen(val->ptr);
4082 val->len = ((size_t)(list - val->ptr));
4083 }
4084
4085 /* Adjust length for trailing LWS */
4086 end = (int)val->len - 1;
4087 while (end >= 0 && ((val->ptr[end] == ' ') || (val->ptr[end] == '\t')))
4088 end--;
4089 val->len = (size_t)(end + 1);
4090
4091 if (val->len == 0) {
4092 /* Ignore any empty entries. */
4093 goto reparse;
4094 }
4095
4096 if (eq_val != NULL) {
4097 /* Value has form "x=y", adjust pointers and lengths
4098 * so that val points to "x", and eq_val points to "y". */
4099 eq_val->len = 0;
4100 eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
4101 if (eq_val->ptr != NULL) {
4102 eq_val->ptr++; /* Skip over '=' character */
4103 eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
4104 val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
4105 }
4106 }
4107
4108 return list;
4109}
4110
4111
4112/* A helper function for checking if a comma separated list of values
4113 * contains
4114 * the given option (case insensitvely).
4115 * 'header' can be NULL, in which case false is returned. */
4116static int
4117header_has_option(const char *header, const char *option)
4118{
4119 struct vec opt_vec;
4120 struct vec eq_vec;
4121
4122 DEBUG_ASSERT(option != NULL);
4123 DEBUG_ASSERT(option[0] != '\0');
4124
4125 while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
4126 if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
4127 return 1;
4128 }
4129
4130 return 0;
4131}
4132
4133
4134/* Perform case-insensitive match of string against pattern */
4135static ptrdiff_t
4136match_prefix(const char *pattern, size_t pattern_len, const char *str)
4137{
4138 const char *or_str;
4139 ptrdiff_t i, j, len, res;
4140
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
4144 : match_prefix(or_str + 1,
4145 (size_t)((pattern + pattern_len)
4146 - (or_str + 1)),
4147 str);
4148 }
4149
4150 for (i = 0, j = 0; (i < (ptrdiff_t)pattern_len); i++, j++) {
4151 if ((pattern[i] == '?') && (str[j] != '\0')) {
4152 continue;
4153 } else if (pattern[i] == '$') {
4154 return (str[j] == '\0') ? j : -1;
4155 } else if (pattern[i] == '*') {
4156 i++;
4157 if (pattern[i] == '*') {
4158 i++;
4159 len = strlen(str + j);
4160 } else {
4161 len = strcspn(str + j, "/");
4162 }
4163 if (i == (ptrdiff_t)pattern_len) {
4164 return j + len;
4165 }
4166 do {
4167 res = match_prefix(pattern + i, pattern_len - i, str + j + len);
4168 } while (res == -1 && len-- > 0);
4169 return (res == -1) ? -1 : j + res + len;
4170 } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
4171 return -1;
4172 }
4173 }
4174 return (ptrdiff_t)j;
4175}
4176
4177
4178/* HTTP 1.1 assumes keep alive if "Connection:" header is not set
4179 * This function must tolerate situations when connection info is not
4180 * set up, for example if request parsing failed. */
4181static int
4182should_keep_alive(const struct mg_connection *conn)
4183{
4184 const char *http_version;
4185 const char *header;
4186
4187 /* First satisfy needs of the server */
4188 if ((conn == NULL) || conn->must_close) {
4189 /* Close, if civetweb framework needs to close */
4190 return 0;
4191 }
4192
4193 if (mg_strcasecmp(conn->dom_ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0) {
4194 /* Close, if keep alive is not enabled */
4195 return 0;
4196 }
4197
4198 /* Check explicit wish of the client */
4199 header = mg_get_header(conn, "Connection");
4200 if (header) {
4201 /* If there is a connection header from the client, obey */
4202 if (header_has_option(header, "keep-alive")) {
4203 return 1;
4204 }
4205 return 0;
4206 }
4207
4208 /* Use default of the standard */
4209 http_version = get_http_version(conn);
4210 if (http_version && (0 == strcmp(http_version, "1.1"))) {
4211 /* HTTP 1.1 default is keep alive */
4212 return 1;
4213 }
4214
4215 /* HTTP 1.0 (and earlier) default is to close the connection */
4216 return 0;
4217}
4218
4219
4220static int
4221should_decode_url(const struct mg_connection *conn)
4222{
4223 if (!conn || !conn->dom_ctx) {
4224 return 0;
4225 }
4226
4227 return (mg_strcasecmp(conn->dom_ctx->config[DECODE_URL], "yes") == 0);
4228}
4229
4230
4231static const char *
4232suggest_connection_header(const struct mg_connection *conn)
4233{
4234 return should_keep_alive(conn) ? "keep-alive" : "close";
4235}
4236
4237
4238static int
4239send_no_cache_header(struct mg_connection *conn)
4240{
4241 /* Send all current and obsolete cache opt-out directives. */
4242 return mg_printf(conn,
4243 "Cache-Control: no-cache, no-store, "
4244 "must-revalidate, private, max-age=0\r\n"
4245 "Pragma: no-cache\r\n"
4246 "Expires: 0\r\n");
4247}
4248
4249
4250static int
4251send_static_cache_header(struct mg_connection *conn)
4252{
4253#if !defined(NO_CACHING)
4254 /* Read the server config to check how long a file may be cached.
4255 * The configuration is in seconds. */
4256 int max_age = atoi(conn->dom_ctx->config[STATIC_FILE_MAX_AGE]);
4257 if (max_age <= 0) {
4258 /* 0 means "do not cache". All values <0 are reserved
4259 * and may be used differently in the future. */
4260 /* If a file should not be cached, do not only send
4261 * max-age=0, but also pragmas and Expires headers. */
4262 return send_no_cache_header(conn);
4263 }
4264
4265 /* Use "Cache-Control: max-age" instead of "Expires" header.
4266 * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
4267 /* See also https://www.mnot.net/cache_docs/ */
4268 /* According to RFC 2616, Section 14.21, caching times should not exceed
4269 * one year. A year with 365 days corresponds to 31536000 seconds, a
4270 * leap
4271 * year to 31622400 seconds. For the moment, we just send whatever has
4272 * been configured, still the behavior for >1 year should be considered
4273 * as undefined. */
4274 return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
4275#else /* NO_CACHING */
4276 return send_no_cache_header(conn);
4277#endif /* !NO_CACHING */
4278}
4279
4280
4281static int
4282send_additional_header(struct mg_connection *conn)
4283{
4284 int i = 0;
4285 const char *header = conn->dom_ctx->config[ADDITIONAL_HEADER];
4286
4287#if !defined(NO_SSL)
4288 if (conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]) {
4289 int max_age = atoi(conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]);
4290 if (max_age >= 0) {
4291 i += mg_printf(conn,
4292 "Strict-Transport-Security: max-age=%u\r\n",
4293 (unsigned)max_age);
4294 }
4295 }
4296#endif
4297
4298 if (header && header[0]) {
4299 i += mg_printf(conn, "%s\r\n", header);
4300 }
4301
4302 return i;
4303}
4304
4305
4306static void handle_file_based_request(struct mg_connection *conn,
4307 const char *path,
4308 struct mg_file *filep);
4309
4310
4311const char *
4312mg_get_response_code_text(const struct mg_connection *conn, int response_code)
4313{
4314 /* See IANA HTTP status code assignment:
4315 * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
4316 */
4317
4318 switch (response_code) {
4319 /* RFC2616 Section 10.1 - Informational 1xx */
4320 case 100:
4321 return "Continue"; /* RFC2616 Section 10.1.1 */
4322 case 101:
4323 return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
4324 case 102:
4325 return "Processing"; /* RFC2518 Section 10.1 */
4326
4327 /* RFC2616 Section 10.2 - Successful 2xx */
4328 case 200:
4329 return "OK"; /* RFC2616 Section 10.2.1 */
4330 case 201:
4331 return "Created"; /* RFC2616 Section 10.2.2 */
4332 case 202:
4333 return "Accepted"; /* RFC2616 Section 10.2.3 */
4334 case 203:
4335 return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
4336 case 204:
4337 return "No Content"; /* RFC2616 Section 10.2.5 */
4338 case 205:
4339 return "Reset Content"; /* RFC2616 Section 10.2.6 */
4340 case 206:
4341 return "Partial Content"; /* RFC2616 Section 10.2.7 */
4342 case 207:
4343 return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1
4344 */
4345 case 208:
4346 return "Already Reported"; /* RFC5842 Section 7.1 */
4347
4348 case 226:
4349 return "IM used"; /* RFC3229 Section 10.4.1 */
4350
4351 /* RFC2616 Section 10.3 - Redirection 3xx */
4352 case 300:
4353 return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
4354 case 301:
4355 return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
4356 case 302:
4357 return "Found"; /* RFC2616 Section 10.3.3 */
4358 case 303:
4359 return "See Other"; /* RFC2616 Section 10.3.4 */
4360 case 304:
4361 return "Not Modified"; /* RFC2616 Section 10.3.5 */
4362 case 305:
4363 return "Use Proxy"; /* RFC2616 Section 10.3.6 */
4364 case 307:
4365 return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
4366 case 308:
4367 return "Permanent Redirect"; /* RFC7238 Section 3 */
4368
4369 /* RFC2616 Section 10.4 - Client Error 4xx */
4370 case 400:
4371 return "Bad Request"; /* RFC2616 Section 10.4.1 */
4372 case 401:
4373 return "Unauthorized"; /* RFC2616 Section 10.4.2 */
4374 case 402:
4375 return "Payment Required"; /* RFC2616 Section 10.4.3 */
4376 case 403:
4377 return "Forbidden"; /* RFC2616 Section 10.4.4 */
4378 case 404:
4379 return "Not Found"; /* RFC2616 Section 10.4.5 */
4380 case 405:
4381 return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
4382 case 406:
4383 return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
4384 case 407:
4385 return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
4386 case 408:
4387 return "Request Time-out"; /* RFC2616 Section 10.4.9 */
4388 case 409:
4389 return "Conflict"; /* RFC2616 Section 10.4.10 */
4390 case 410:
4391 return "Gone"; /* RFC2616 Section 10.4.11 */
4392 case 411:
4393 return "Length Required"; /* RFC2616 Section 10.4.12 */
4394 case 412:
4395 return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
4396 case 413:
4397 return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
4398 case 414:
4399 return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
4400 case 415:
4401 return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
4402 case 416:
4403 return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17
4404 */
4405 case 417:
4406 return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
4407
4408 case 421:
4409 return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
4410 case 422:
4411 return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
4412 * Section 11.2 */
4413 case 423:
4414 return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
4415 case 424:
4416 return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
4417 * Section 11.4 */
4418
4419 case 426:
4420 return "Upgrade Required"; /* RFC 2817 Section 4 */
4421
4422 case 428:
4423 return "Precondition Required"; /* RFC 6585, Section 3 */
4424 case 429:
4425 return "Too Many Requests"; /* RFC 6585, Section 4 */
4426
4427 case 431:
4428 return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
4429
4430 case 451:
4431 return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
4432 * Section 3 */
4433
4434 /* RFC2616 Section 10.5 - Server Error 5xx */
4435 case 500:
4436 return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
4437 case 501:
4438 return "Not Implemented"; /* RFC2616 Section 10.5.2 */
4439 case 502:
4440 return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
4441 case 503:
4442 return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
4443 case 504:
4444 return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
4445 case 505:
4446 return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
4447 case 506:
4448 return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
4449 case 507:
4450 return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
4451 * Section 11.5 */
4452 case 508:
4453 return "Loop Detected"; /* RFC5842 Section 7.1 */
4454
4455 case 510:
4456 return "Not Extended"; /* RFC 2774, Section 7 */
4457 case 511:
4458 return "Network Authentication Required"; /* RFC 6585, Section 6 */
4459
4460 /* Other status codes, not shown in the IANA HTTP status code
4461 * assignment.
4462 * E.g., "de facto" standards due to common use, ... */
4463 case 418:
4464 return "I am a teapot"; /* RFC2324 Section 2.3.2 */
4465 case 419:
4466 return "Authentication Timeout"; /* common use */
4467 case 420:
4468 return "Enhance Your Calm"; /* common use */
4469 case 440:
4470 return "Login Timeout"; /* common use */
4471 case 509:
4472 return "Bandwidth Limit Exceeded"; /* common use */
4473
4474 default:
4475 /* This error code is unknown. This should not happen. */
4476 if (conn) {
4477 mg_cry_internal(conn,
4478 "Unknown HTTP response code: %u",
4479 response_code);
4480 }
4481
4482 /* Return at least a category according to RFC 2616 Section 10. */
4483 if (response_code >= 100 && response_code < 200) {
4484 /* Unknown informational status code */
4485 return "Information";
4486 }
4487 if (response_code >= 200 && response_code < 300) {
4488 /* Unknown success code */
4489 return "Success";
4490 }
4491 if (response_code >= 300 && response_code < 400) {
4492 /* Unknown redirection code */
4493 return "Redirection";
4494 }
4495 if (response_code >= 400 && response_code < 500) {
4496 /* Unknown request error code */
4497 return "Client Error";
4498 }
4499 if (response_code >= 500 && response_code < 600) {
4500 /* Unknown server error code */
4501 return "Server Error";
4502 }
4503
4504 /* Response code not even within reasonable range */
4505 return "";
4506 }
4507}
4508
4509
4510static int
4511mg_send_http_error_impl(struct mg_connection *conn,
4512 int status,
4513 const char *fmt,
4514 va_list args)
4515{
4516 char errmsg_buf[MG_BUF_LEN];
4517 char path_buf[PATH_MAX];
4518 va_list ap;
4519 int len, i, page_handler_found, scope, truncated, has_body;
4520 char date[64];
4521 time_t curtime = time(NULL);
4522 const char *error_handler = NULL;
4523 struct mg_file error_page_file = STRUCT_FILE_INITIALIZER;
4524 const char *error_page_file_ext, *tstr;
4525 int handled_by_callback = 0;
4526
4527 const char *status_text = mg_get_response_code_text(conn, status);
4528
4529 if ((conn == NULL) || (fmt == NULL)) {
4530 return -2;
4531 }
4532
4533 /* Set status (for log) */
4534 conn->status_code = status;
4535
4536 /* Errors 1xx, 204 and 304 MUST NOT send a body */
4537 has_body = ((status > 199) && (status != 204) && (status != 304));
4538
4539 /* Prepare message in buf, if required */
4540 if (has_body
4541 || (!conn->in_error_handler
4542 && (conn->phys_ctx->callbacks.http_error != NULL))) {
4543 /* Store error message in errmsg_buf */
4544 va_copy(ap, args);
4545 mg_vsnprintf(conn, NULL, errmsg_buf, sizeof(errmsg_buf), fmt, ap);
4546 va_end(ap);
4547 /* In a debug build, print all html errors */
4548 DEBUG_TRACE("Error %i - [%s]", status, errmsg_buf);
4549 }
4550
4551 /* If there is a http_error callback, call it.
4552 * But don't do it recursively, if callback calls mg_send_http_error again.
4553 */
4554 if (!conn->in_error_handler
4555 && (conn->phys_ctx->callbacks.http_error != NULL)) {
4556 /* Mark in_error_handler to avoid recursion and call user callback. */
4557 conn->in_error_handler = 1;
4558 handled_by_callback =
4559 (conn->phys_ctx->callbacks.http_error(conn, status, errmsg_buf)
4560 == 0);
4561 conn->in_error_handler = 0;
4562 }
4563
4564 if (!handled_by_callback) {
4565 /* Check for recursion */
4566 if (conn->in_error_handler) {
4568 "Recursion when handling error %u - fall back to default",
4569 status);
4570 } else {
4571 /* Send user defined error pages, if defined */
4572 error_handler = conn->dom_ctx->config[ERROR_PAGES];
4573 error_page_file_ext = conn->dom_ctx->config[INDEX_FILES];
4574 page_handler_found = 0;
4575
4576 if (error_handler != NULL) {
4577 for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
4578 switch (scope) {
4579 case 1: /* Handler for specific error, e.g. 404 error */
4580 mg_snprintf(conn,
4581 &truncated,
4582 path_buf,
4583 sizeof(path_buf) - 32,
4584 "%serror%03u.",
4585 error_handler,
4586 status);
4587 break;
4588 case 2: /* Handler for error group, e.g., 5xx error
4589 * handler
4590 * for all server errors (500-599) */
4591 mg_snprintf(conn,
4592 &truncated,
4593 path_buf,
4594 sizeof(path_buf) - 32,
4595 "%serror%01uxx.",
4596 error_handler,
4597 status / 100);
4598 break;
4599 default: /* Handler for all errors */
4600 mg_snprintf(conn,
4601 &truncated,
4602 path_buf,
4603 sizeof(path_buf) - 32,
4604 "%serror.",
4605 error_handler);
4606 break;
4607 }
4608
4609 /* String truncation in buf may only occur if
4610 * error_handler is too long. This string is
4611 * from the config, not from a client. */
4612 (void)truncated;
4613
4614 len = (int)strlen(path_buf);
4615
4616 tstr = strchr(error_page_file_ext, '.');
4617
4618 while (tstr) {
4619 for (i = 1;
4620 (i < 32) && (tstr[i] != 0) && (tstr[i] != ',');
4621 i++) {
4622 /* buffer overrun is not possible here, since
4623 * (i < 32) && (len < sizeof(path_buf) - 32)
4624 * ==> (i + len) < sizeof(path_buf) */
4625 path_buf[len + i - 1] = tstr[i];
4626 }
4627 /* buffer overrun is not possible here, since
4628 * (i <= 32) && (len < sizeof(path_buf) - 32)
4629 * ==> (i + len) <= sizeof(path_buf) */
4630 path_buf[len + i - 1] = 0;
4631
4632 if (mg_stat(conn, path_buf, &error_page_file.stat)) {
4633 DEBUG_TRACE("Check error page %s - found",
4634 path_buf);
4635 page_handler_found = 1;
4636 break;
4637 }
4638 DEBUG_TRACE("Check error page %s - not found",
4639 path_buf);
4640
4641 tstr = strchr(tstr + i, '.');
4642 }
4643 }
4644 }
4645
4646 if (page_handler_found) {
4647 conn->in_error_handler = 1;
4648 handle_file_based_request(conn, path_buf, &error_page_file);
4649 conn->in_error_handler = 0;
4650 return 0;
4651 }
4652 }
4653
4654 /* No custom error page. Send default error page. */
4655 gmt_time_string(date, sizeof(date), &curtime);
4656
4657 conn->must_close = 1;
4658 mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
4661 if (has_body) {
4662 mg_printf(conn,
4663 "%s",
4664 "Content-Type: text/plain; charset=utf-8\r\n");
4665 }
4666 mg_printf(conn,
4667 "Date: %s\r\n"
4668 "Connection: close\r\n\r\n",
4669 date);
4670
4671 /* HTTP responses 1xx, 204 and 304 MUST NOT send a body */
4672 if (has_body) {
4673 /* For other errors, send a generic error message. */
4674 mg_printf(conn, "Error %d: %s\n", status, status_text);
4675 mg_write(conn, errmsg_buf, strlen(errmsg_buf));
4676
4677 } else {
4678 /* No body allowed. Close the connection. */
4679 DEBUG_TRACE("Error %i", status);
4680 }
4681 }
4682 return 0;
4683}
4684
4685
4686int
4687mg_send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
4688{
4689 va_list ap;
4690 int ret;
4691
4692 va_start(ap, fmt);
4693 ret = mg_send_http_error_impl(conn, status, fmt, ap);
4694 va_end(ap);
4695
4696 return ret;
4697}
4698
4699
4700int
4701mg_send_http_ok(struct mg_connection *conn,
4702 const char *mime_type,
4703 long long content_length)
4704{
4705 char date[64];
4706 time_t curtime = time(NULL);
4707
4708 if ((mime_type == NULL) || (*mime_type == 0)) {
4709 /* Parameter error */
4710 return -2;
4711 }
4712
4713 gmt_time_string(date, sizeof(date), &curtime);
4714
4715 mg_printf(conn,
4716 "HTTP/1.1 200 OK\r\n"
4717 "Content-Type: %s\r\n"
4718 "Date: %s\r\n"
4719 "Connection: %s\r\n",
4720 mime_type,
4721 date,
4723
4726 if (content_length < 0) {
4727 mg_printf(conn, "Transfer-Encoding: chunked\r\n\r\n");
4728 } else {
4729 mg_printf(conn,
4730 "Content-Length: %" UINT64_FMT "\r\n\r\n",
4731 (uint64_t)content_length);
4732 }
4733
4734 return 0;
4735}
4736
4737
4738int
4739mg_send_http_redirect(struct mg_connection *conn,
4740 const char *target_url,
4741 int redirect_code)
4742{
4743 /* Send a 30x redirect response.
4744 *
4745 * Redirect types (status codes):
4746 *
4747 * Status | Perm/Temp | Method | Version
4748 * 301 | permanent | POST->GET undefined | HTTP/1.0
4749 * 302 | temporary | POST->GET undefined | HTTP/1.0
4750 * 303 | temporary | always use GET | HTTP/1.1
4751 * 307 | temporary | always keep method | HTTP/1.1
4752 * 308 | permanent | always keep method | HTTP/1.1
4753 */
4754 const char *redirect_text;
4755 int ret;
4756 size_t content_len = 0;
4757 char reply[MG_BUF_LEN];
4758
4759 /* In case redirect_code=0, use 307. */
4760 if (redirect_code == 0) {
4761 redirect_code = 307;
4762 }
4763
4764 /* In case redirect_code is none of the above, return error. */
4765 if ((redirect_code != 301) && (redirect_code != 302)
4766 && (redirect_code != 303) && (redirect_code != 307)
4767 && (redirect_code != 308)) {
4768 /* Parameter error */
4769 return -2;
4770 }
4771
4772 /* Get proper text for response code */
4773 redirect_text = mg_get_response_code_text(conn, redirect_code);
4774
4775 /* If target_url is not defined, redirect to "/". */
4776 if ((target_url == NULL) || (*target_url == 0)) {
4777 target_url = "/";
4778 }
4779
4780#if defined(MG_SEND_REDIRECT_BODY)
4781 /* TODO: condition name? */
4782
4783 /* Prepare a response body with a hyperlink.
4784 *
4785 * According to RFC2616 (and RFC1945 before):
4786 * Unless the request method was HEAD, the entity of the
4787 * response SHOULD contain a short hypertext note with a hyperlink to
4788 * the new URI(s).
4789 *
4790 * However, this response body is not useful in M2M communication.
4791 * Probably the original reason in the RFC was, clients not supporting
4792 * a 30x HTTP redirect could still show the HTML page and let the user
4793 * press the link. Since current browsers support 30x HTTP, the additional
4794 * HTML body does not seem to make sense anymore.
4795 *
4796 * The new RFC7231 (Section 6.4) does no longer recommend it ("SHOULD"),
4797 * but it only notes:
4798 * The server's response payload usually contains a short
4799 * hypertext note with a hyperlink to the new URI(s).
4800 *
4801 * Deactivated by default. If you need the 30x body, set the define.
4802 */
4804 conn,
4805 NULL /* ignore truncation */,
4806 reply,
4807 sizeof(reply),
4808 "<html><head>%s</head><body><a href=\"%s\">%s</a></body></html>",
4809 redirect_text,
4810 target_url,
4811 target_url);
4812 content_len = strlen(reply);
4813#else
4814 reply[0] = 0;
4815#endif
4816
4817 /* Do not send any additional header. For all other options,
4818 * including caching, there are suitable defaults. */
4819 ret = mg_printf(conn,
4820 "HTTP/1.1 %i %s\r\n"
4821 "Location: %s\r\n"
4822 "Content-Length: %u\r\n"
4823 "Connection: %s\r\n\r\n",
4824 redirect_code,
4825 redirect_text,
4826 target_url,
4827 (unsigned int)content_len,
4829
4830 /* Send response body */
4831 if (ret > 0) {
4832 /* ... unless it is a HEAD request */
4833 if (0 != strcmp(conn->request_info.request_method, "HEAD")) {
4834 ret = mg_write(conn, reply, content_len);
4835 }
4836 }
4837
4838 return (ret > 0) ? ret : -1;
4839}
4840
4841
4842#if defined(_WIN32)
4843/* Create substitutes for POSIX functions in Win32. */
4844
4845#if defined(GCC_DIAGNOSTIC)
4846/* Show no warning in case system functions are not used. */
4847#pragma GCC diagnostic push
4848#pragma GCC diagnostic ignored "-Wunused-function"
4849#endif
4850
4851
4853static int
4854pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
4855{
4856 (void)unused;
4857 *mutex = CreateMutex(NULL, FALSE, NULL);
4858 return (*mutex == NULL) ? -1 : 0;
4859}
4860
4862static int
4863pthread_mutex_destroy(pthread_mutex_t *mutex)
4864{
4865 return (CloseHandle(*mutex) == 0) ? -1 : 0;
4866}
4867
4868
4870static int
4871pthread_mutex_lock(pthread_mutex_t *mutex)
4872{
4873 return (WaitForSingleObject(*mutex, (DWORD)INFINITE) == WAIT_OBJECT_0) ? 0
4874 : -1;
4875}
4876
4877
4878#if defined(ENABLE_UNUSED_PTHREAD_FUNCTIONS)
4880static int
4881pthread_mutex_trylock(pthread_mutex_t *mutex)
4882{
4883 switch (WaitForSingleObject(*mutex, 0)) {
4884 case WAIT_OBJECT_0:
4885 return 0;
4886 case WAIT_TIMEOUT:
4887 return -2; /* EBUSY */
4888 }
4889 return -1;
4890}
4891#endif
4892
4893
4895static int
4896pthread_mutex_unlock(pthread_mutex_t *mutex)
4897{
4898 return (ReleaseMutex(*mutex) == 0) ? -1 : 0;
4899}
4900
4901
4903static int
4904pthread_cond_init(pthread_cond_t *cv, const void *unused)
4905{
4906 (void)unused;
4907 InitializeCriticalSection(&cv->threadIdSec);
4908 cv->waiting_thread = NULL;
4909 return 0;
4910}
4911
4912
4914static int
4915pthread_cond_timedwait(pthread_cond_t *cv,
4916 pthread_mutex_t *mutex,
4917 FUNCTION_MAY_BE_UNUSED const struct timespec *abstime)
4918{
4919 struct mg_workerTLS **ptls,
4920 *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
4921 int ok;
4922 int64_t nsnow, nswaitabs, nswaitrel;
4923 DWORD mswaitrel;
4924
4925 EnterCriticalSection(&cv->threadIdSec);
4926 /* Add this thread to cv's waiting list */
4927 ptls = &cv->waiting_thread;
4928 for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
4929 ;
4930 tls->next_waiting_thread = NULL;
4931 *ptls = tls;
4932 LeaveCriticalSection(&cv->threadIdSec);
4933
4934 if (abstime) {
4935 nsnow = mg_get_current_time_ns();
4936 nswaitabs =
4937 (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
4938 nswaitrel = nswaitabs - nsnow;
4939 if (nswaitrel < 0) {
4940 nswaitrel = 0;
4941 }
4942 mswaitrel = (DWORD)(nswaitrel / 1000000);
4943 } else {
4944 mswaitrel = (DWORD)INFINITE;
4945 }
4946
4947 pthread_mutex_unlock(mutex);
4948 ok = (WAIT_OBJECT_0
4949 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
4950 if (!ok) {
4951 ok = 1;
4952 EnterCriticalSection(&cv->threadIdSec);
4953 ptls = &cv->waiting_thread;
4954 for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
4955 if (*ptls == tls) {
4956 *ptls = tls->next_waiting_thread;
4957 ok = 0;
4958 break;
4959 }
4960 }
4961 LeaveCriticalSection(&cv->threadIdSec);
4962 if (ok) {
4963 WaitForSingleObject(tls->pthread_cond_helper_mutex,
4964 (DWORD)INFINITE);
4965 }
4966 }
4967 /* This thread has been removed from cv's waiting list */
4968 pthread_mutex_lock(mutex);
4969
4970 return ok ? 0 : -1;
4971}
4972
4973
4975static int
4976pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
4977{
4978 return pthread_cond_timedwait(cv, mutex, NULL);
4979}
4980
4981
4983static int
4984pthread_cond_signal(pthread_cond_t *cv)
4985{
4986 HANDLE wkup = NULL;
4987 BOOL ok = FALSE;
4988
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;
4993
4994 ok = SetEvent(wkup);
4995 DEBUG_ASSERT(ok);
4996 }
4997 LeaveCriticalSection(&cv->threadIdSec);
4998
4999 return ok ? 0 : 1;
5000}
5001
5002
5004static int
5005pthread_cond_broadcast(pthread_cond_t *cv)
5006{
5007 EnterCriticalSection(&cv->threadIdSec);
5008 while (cv->waiting_thread) {
5009 pthread_cond_signal(cv);
5010 }
5011 LeaveCriticalSection(&cv->threadIdSec);
5012
5013 return 0;
5014}
5015
5016
5018static int
5019pthread_cond_destroy(pthread_cond_t *cv)
5020{
5021 EnterCriticalSection(&cv->threadIdSec);
5022 DEBUG_ASSERT(cv->waiting_thread == NULL);
5023 LeaveCriticalSection(&cv->threadIdSec);
5024 DeleteCriticalSection(&cv->threadIdSec);
5025
5026 return 0;
5027}
5028
5029
5030#if defined(ALTERNATIVE_QUEUE)
5032static void *
5033event_create(void)
5034{
5035 return (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
5036}
5037
5038
5040static int
5041event_wait(void *eventhdl)
5042{
5043 int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE);
5044 return (res == WAIT_OBJECT_0);
5045}
5046
5047
5049static int
5050event_signal(void *eventhdl)
5051{
5052 return (int)SetEvent((HANDLE)eventhdl);
5053}
5054
5055
5057static void
5058event_destroy(void *eventhdl)
5059{
5060 CloseHandle((HANDLE)eventhdl);
5061}
5062#endif
5063
5064
5065#if defined(GCC_DIAGNOSTIC)
5066/* Enable unused function warning again */
5067#pragma GCC diagnostic pop
5068#endif
5069
5070
5071/* For Windows, change all slashes to backslashes in path names. */
5072static void
5073change_slashes_to_backslashes(char *path)
5074{
5075 int i;
5076
5077 for (i = 0; path[i] != '\0'; i++) {
5078 if (path[i] == '/') {
5079 path[i] = '\\';
5080 }
5081
5082 /* remove double backslash (check i > 0 to preserve UNC paths,
5083 * like \\server\file.txt) */
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));
5087 }
5088 }
5089 }
5090}
5091
5092
5093static int
5094mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
5095{
5096 int diff;
5097
5098 do {
5099 diff = tolower(*s1) - tolower(*s2);
5100 s1++;
5101 s2++;
5102 } while ((diff == 0) && (s1[-1] != '\0'));
5103
5104 return diff;
5105}
5106
5107
5108/* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
5109 * wbuf and wbuf_len is a target buffer and its length. */
5110static void
5111path_to_unicode(const struct mg_connection *conn,
5112 const char *path,
5113 wchar_t *wbuf,
5114 size_t wbuf_len)
5115{
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;
5120
5121 mg_strlcpy(buf, path, sizeof(buf));
5122 change_slashes_to_backslashes(buf);
5123
5124 /* Convert to Unicode and back. If doubly-converted string does not
5125 * match the original, something is fishy, reject. */
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) {
5131 wbuf[0] = L'\0';
5132 }
5133
5134 /* Windows file systems are not case sensitive, but you can still use
5135 * uppercase and lowercase letters (on all modern file systems).
5136 * The server can check if the URI uses the same upper/lowercase
5137 * letters an the file system, effectively making Windows servers
5138 * case sensitive (like Linux servers are). It is still not possible
5139 * to use two files with the same name in different cases on Windows
5140 * (like /a and /A) - this would be possible in Linux.
5141 * As a default, Windows is not case sensitive, but the case sensitive
5142 * file name check can be activated by an additional configuration. */
5143 if (conn) {
5144 if (conn->dom_ctx->config[CASE_SENSITIVE_FILES]
5145 && !mg_strcasecmp(conn->dom_ctx->config[CASE_SENSITIVE_FILES],
5146 "yes")) {
5147 /* Use case sensitive compare function */
5148 fcompare = wcscmp;
5149 }
5150 }
5151 (void)conn; /* conn is currently unused */
5152
5153#if !defined(_WIN32_WCE)
5154 /* Only accept a full file path, not a Windows short (8.3) path. */
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) {
5160 /* File does not exist. This is not always a problem here. */
5161 return;
5162 }
5163 }
5164 if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
5165 /* Short name is used. */
5166 wbuf[0] = L'\0';
5167 }
5168#else
5169 (void)long_len;
5170 (void)wbuf2;
5171 (void)err;
5172
5173 if (strchr(path, '~')) {
5174 wbuf[0] = L'\0';
5175 }
5176#endif
5177}
5178
5179
5180/* Windows happily opens files with some garbage at the end of file name.
5181 * For example, fopen("a.cgi ", "r") on Windows successfully opens
5182 * "a.cgi", despite one would expect an error back.
5183 * This function returns non-0 if path ends with some garbage. */
5184static int
5185path_cannot_disclose_cgi(const char *path)
5186{
5187 static const char *allowed_last_characters = "_-";
5188 int last = path[strlen(path) - 1];
5189 return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
5190}
5191
5192
5193static int
5194mg_stat(const struct mg_connection *conn,
5195 const char *path,
5196 struct mg_file_stat *filep)
5197{
5198 wchar_t wbuf[W_PATH_MAX];
5199 WIN32_FILE_ATTRIBUTE_DATA info;
5200 time_t creation_time;
5201
5202 if (!filep) {
5203 return 0;
5204 }
5205 memset(filep, 0, sizeof(*filep));
5206
5207 if (conn && is_file_in_memory(conn, path)) {
5208 /* filep->is_directory = 0; filep->gzipped = 0; .. already done by
5209 * memset */
5210
5211 /* Quick fix (for 1.9.x): */
5212 /* mg_stat must fill all fields, also for files in memory */
5213 struct mg_file tmp_file = STRUCT_FILE_INITIALIZER;
5214 open_file_in_memory(conn, path, &tmp_file, MG_FOPEN_MODE_NONE);
5215 filep->size = tmp_file.stat.size;
5216 filep->location = 2;
5217 /* TODO: for 1.10: restructure how files in memory are handled */
5218
5219 /* The "file in memory" feature is a candidate for deletion.
5220 * Please join the discussion at
5221 * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
5222 */
5223
5224 filep->last_modified = time(NULL); /* TODO */
5225 /* last_modified = now ... assumes the file may change during
5226 * runtime,
5227 * so every mg_fopen call may return different data */
5228 /* last_modified = conn->phys_ctx.start_time;
5229 * May be used it the data does not change during runtime. This
5230 * allows
5231 * browser caching. Since we do not know, we have to assume the file
5232 * in memory may change. */
5233 return 1;
5234 }
5235
5236 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5237 if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
5238 filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
5239 filep->last_modified =
5240 SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
5241 info.ftLastWriteTime.dwHighDateTime);
5242
5243 /* On Windows, the file creation time can be higher than the
5244 * modification time, e.g. when a file is copied.
5245 * Since the Last-Modified timestamp is used for caching
5246 * it should be based on the most recent timestamp. */
5247 creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
5248 info.ftCreationTime.dwHighDateTime);
5249 if (creation_time > filep->last_modified) {
5250 filep->last_modified = creation_time;
5251 }
5252
5253 filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5254 /* If file name is fishy, reset the file structure and return
5255 * error.
5256 * Note it is important to reset, not just return the error, cause
5257 * functions like is_file_opened() check the struct. */
5258 if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
5259 memset(filep, 0, sizeof(*filep));
5260 return 0;
5261 }
5262
5263 return 1;
5264 }
5265
5266 return 0;
5267}
5268
5269
5270static int
5271mg_remove(const struct mg_connection *conn, const char *path)
5272{
5273 wchar_t wbuf[W_PATH_MAX];
5274 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5275 return DeleteFileW(wbuf) ? 0 : -1;
5276}
5277
5278
5279static int
5280mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
5281{
5282 wchar_t wbuf[W_PATH_MAX];
5283 (void)mode;
5284 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5285 return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
5286}
5287
5288
5289/* Create substitutes for POSIX functions in Win32. */
5290
5291#if defined(GCC_DIAGNOSTIC)
5292/* Show no warning in case system functions are not used. */
5293#pragma GCC diagnostic push
5294#pragma GCC diagnostic ignored "-Wunused-function"
5295#endif
5296
5297
5298/* Implementation of POSIX opendir/closedir/readdir for Windows. */
5300static DIR *
5301mg_opendir(const struct mg_connection *conn, const char *name)
5302{
5303 DIR *dir = NULL;
5304 wchar_t wpath[W_PATH_MAX];
5305 DWORD attrs;
5306
5307 if (name == NULL) {
5308 SetLastError(ERROR_BAD_ARGUMENTS);
5309 } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
5310 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5311 } else {
5312 path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
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';
5319 } else {
5320 mg_free(dir);
5321 dir = NULL;
5322 }
5323 }
5324
5325 return dir;
5326}
5327
5328
5330static int
5331mg_closedir(DIR *dir)
5332{
5333 int result = 0;
5334
5335 if (dir != NULL) {
5336 if (dir->handle != INVALID_HANDLE_VALUE)
5337 result = FindClose(dir->handle) ? 0 : -1;
5338
5339 mg_free(dir);
5340 } else {
5341 result = -1;
5342 SetLastError(ERROR_BAD_ARGUMENTS);
5343 }
5344
5345 return result;
5346}
5347
5348
5350static struct dirent *
5351mg_readdir(DIR *dir)
5352{
5353 struct dirent *result = 0;
5354
5355 if (dir) {
5356 if (dir->handle != INVALID_HANDLE_VALUE) {
5357 result = &dir->result;
5358 (void)WideCharToMultiByte(CP_UTF8,
5359 0,
5360 dir->info.cFileName,
5361 -1,
5362 result->d_name,
5363 sizeof(result->d_name),
5364 NULL,
5365 NULL);
5366
5367 if (!FindNextFileW(dir->handle, &dir->info)) {
5368 (void)FindClose(dir->handle);
5369 dir->handle = INVALID_HANDLE_VALUE;
5370 }
5371
5372 } else {
5373 SetLastError(ERROR_FILE_NOT_FOUND);
5374 }
5375 } else {
5376 SetLastError(ERROR_BAD_ARGUMENTS);
5377 }
5378
5379 return result;
5380}
5381
5382
5383#if !defined(HAVE_POLL)
5384#define POLLIN (1) /* Data ready - read will not block. */
5385#define POLLPRI (2) /* Priority data ready. */
5386#define POLLOUT (4) /* Send queue not full - write will not block. */
5387
5389static int
5390poll(struct pollfd *pfd, unsigned int n, int milliseconds)
5391{
5392 struct timeval tv;
5393 fd_set rset;
5394 fd_set wset;
5395 unsigned int i;
5396 int result;
5397 SOCKET maxfd = 0;
5398
5399 memset(&tv, 0, sizeof(tv));
5400 tv.tv_sec = milliseconds / 1000;
5401 tv.tv_usec = (milliseconds % 1000) * 1000;
5402 FD_ZERO(&rset);
5403 FD_ZERO(&wset);
5404
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);
5410 }
5411 pfd[i].revents = 0;
5412
5413 if (pfd[i].fd > maxfd) {
5414 maxfd = pfd[i].fd;
5415 }
5416 }
5417
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;
5422 }
5423 if (FD_ISSET(pfd[i].fd, &wset)) {
5424 pfd[i].revents |= POLLOUT;
5425 }
5426 }
5427 }
5428
5429 /* We should subtract the time used in select from remaining
5430 * "milliseconds", in particular if called from mg_poll with a
5431 * timeout quantum.
5432 * Unfortunately, the remaining time is not stored in "tv" in all
5433 * implementations, so the result in "tv" must be considered undefined.
5434 * See http://man7.org/linux/man-pages/man2/select.2.html */
5435
5436 return result;
5437}
5438#endif /* HAVE_POLL */
5439
5440
5441#if defined(GCC_DIAGNOSTIC)
5442/* Enable unused function warning again */
5443#pragma GCC diagnostic pop
5444#endif
5445
5446
5447static void
5448set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
5449{
5450 (void)conn; /* Unused. */
5451#if defined(_WIN32_WCE)
5452 (void)sock;
5453#else
5454 (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
5455#endif
5456}
5457
5458
5459int
5461{
5462#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5463 /* Compile-time option to control stack size, e.g.
5464 * -DUSE_STACK_SIZE=16384
5465 */
5466 return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
5467 == ((uintptr_t)(-1L)))
5468 ? -1
5469 : 0);
5470#else
5471 return (
5472 (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
5473 ? -1
5474 : 0);
5475#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5476}
5477
5478
5479/* Start a thread storing the thread context. */
5480static int
5481mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
5482 void *p,
5483 pthread_t *threadidptr)
5484{
5485 uintptr_t uip;
5486 HANDLE threadhandle;
5487 int result = -1;
5488
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;
5493 result = 0;
5494 }
5495
5496 return result;
5497}
5498
5499
5500/* Wait for a thread to finish. */
5501static int
5502mg_join_thread(pthread_t threadid)
5503{
5504 int result;
5505 DWORD dwevent;
5506
5507 result = -1;
5508 dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE);
5509 if (dwevent == WAIT_FAILED) {
5510 DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
5511 } else {
5512 if (dwevent == WAIT_OBJECT_0) {
5513 CloseHandle(threadid);
5514 result = 0;
5515 }
5516 }
5517
5518 return result;
5519}
5520
5521#if !defined(NO_SSL_DL) && !defined(NO_SSL)
5522/* If SSL is loaded dynamically, dlopen/dlclose is required. */
5523/* Create substitutes for POSIX functions in Win32. */
5524
5525#if defined(GCC_DIAGNOSTIC)
5526/* Show no warning in case system functions are not used. */
5527#pragma GCC diagnostic push
5528#pragma GCC diagnostic ignored "-Wunused-function"
5529#endif
5530
5531
5533static HANDLE
5534dlopen(const char *dll_name, int flags)
5535{
5536 wchar_t wbuf[W_PATH_MAX];
5537 (void)flags;
5538 path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
5539 return LoadLibraryW(wbuf);
5540}
5541
5542
5544static int
5545dlclose(void *handle)
5546{
5547 int result;
5548
5549 if (FreeLibrary((HMODULE)handle) != 0) {
5550 result = 0;
5551 } else {
5552 result = -1;
5553 }
5554
5555 return result;
5556}
5557
5558
5559#if defined(GCC_DIAGNOSTIC)
5560/* Enable unused function warning again */
5561#pragma GCC diagnostic pop
5562#endif
5563
5564#endif
5565
5566
5567#if !defined(NO_CGI)
5568#define SIGKILL (0)
5569
5570
5571static int
5572kill(pid_t pid, int sig_num)
5573{
5574 (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
5575 (void)CloseHandle((HANDLE)pid);
5576 return 0;
5577}
5578
5579
5580#if !defined(WNOHANG)
5581#define WNOHANG (1)
5582#endif
5583
5584
5585static pid_t
5586waitpid(pid_t pid, int *status, int flags)
5587{
5588 DWORD timeout = INFINITE;
5589 DWORD waitres;
5590
5591 (void)status; /* Currently not used by any client here */
5592
5593 if ((flags | WNOHANG) == WNOHANG) {
5594 timeout = 0;
5595 }
5596
5597 waitres = WaitForSingleObject((HANDLE)pid, timeout);
5598 if (waitres == WAIT_OBJECT_0) {
5599 return pid;
5600 }
5601 if (waitres == WAIT_TIMEOUT) {
5602 return 0;
5603 }
5604 return (pid_t)-1;
5605}
5606
5607
5608static void
5609trim_trailing_whitespaces(char *s)
5610{
5611 char *e = s + strlen(s) - 1;
5612 while ((e > s) && isspace(*(unsigned char *)e)) {
5613 *e-- = '\0';
5614 }
5615}
5616
5617
5618static pid_t
5619spawn_process(struct mg_connection *conn,
5620 const char *prog,
5621 char *envblk,
5622 char *envp[],
5623 int fdin[2],
5624 int fdout[2],
5625 int fderr[2],
5626 const char *dir)
5627{
5628 HANDLE me;
5629 char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
5630 cmdline[PATH_MAX], buf[PATH_MAX];
5631 int truncated;
5632 struct mg_file file = STRUCT_FILE_INITIALIZER;
5633 STARTUPINFOA si;
5634 PROCESS_INFORMATION pi = {0};
5635
5636 (void)envp;
5637
5638 memset(&si, 0, sizeof(si));
5639 si.cb = sizeof(si);
5640
5641 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
5642 si.wShowWindow = SW_HIDE;
5643
5644 me = GetCurrentProcess();
5645 DuplicateHandle(me,
5646 (HANDLE)_get_osfhandle(fdin[0]),
5647 me,
5648 &si.hStdInput,
5649 0,
5650 TRUE,
5651 DUPLICATE_SAME_ACCESS);
5652 DuplicateHandle(me,
5653 (HANDLE)_get_osfhandle(fdout[1]),
5654 me,
5655 &si.hStdOutput,
5656 0,
5657 TRUE,
5658 DUPLICATE_SAME_ACCESS);
5659 DuplicateHandle(me,
5660 (HANDLE)_get_osfhandle(fderr[1]),
5661 me,
5662 &si.hStdError,
5663 0,
5664 TRUE,
5665 DUPLICATE_SAME_ACCESS);
5666
5667 /* Mark handles that should not be inherited. See
5668 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
5669 */
5670 SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
5671 HANDLE_FLAG_INHERIT,
5672 0);
5673 SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
5674 HANDLE_FLAG_INHERIT,
5675 0);
5676 SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
5677 HANDLE_FLAG_INHERIT,
5678 0);
5679
5680 /* If CGI file is a script, try to read the interpreter line */
5681 interp = conn->dom_ctx->config[CGI_INTERPRETER];
5682 if (interp == NULL) {
5683 buf[0] = buf[1] = '\0';
5684
5685 /* Read the first line of the script into the buffer */
5687 conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
5688
5689 if (truncated) {
5690 pi.hProcess = (pid_t)-1;
5691 goto spawn_cleanup;
5692 }
5693
5694 if (mg_fopen(conn, cmdline, MG_FOPEN_MODE_READ, &file)) {
5695#if defined(MG_USE_OPEN_FILE)
5696 p = (char *)file.access.membuf;
5697#else
5698 p = (char *)NULL;
5699#endif
5700 mg_fgets(buf, sizeof(buf), &file, &p);
5701 (void)mg_fclose(&file.access); /* ignore error on read only file */
5702 buf[sizeof(buf) - 1] = '\0';
5703 }
5704
5705 if ((buf[0] == '#') && (buf[1] == '!')) {
5706 trim_trailing_whitespaces(buf + 2);
5707 } else {
5708 buf[2] = '\0';
5709 }
5710 interp = buf + 2;
5711 }
5712
5713 if (interp[0] != '\0') {
5714 GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
5715 interp = full_interp;
5716 }
5717 GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
5718
5719 if (interp[0] != '\0') {
5720 mg_snprintf(conn,
5721 &truncated,
5722 cmdline,
5723 sizeof(cmdline),
5724 "\"%s\" \"%s\\%s\"",
5725 interp,
5726 full_dir,
5727 prog);
5728 } else {
5729 mg_snprintf(conn,
5730 &truncated,
5731 cmdline,
5732 sizeof(cmdline),
5733 "\"%s\\%s\"",
5734 full_dir,
5735 prog);
5736 }
5737
5738 if (truncated) {
5739 pi.hProcess = (pid_t)-1;
5740 goto spawn_cleanup;
5741 }
5742
5743 DEBUG_TRACE("Running [%s]", cmdline);
5744 if (CreateProcessA(NULL,
5745 cmdline,
5746 NULL,
5747 NULL,
5748 TRUE,
5749 CREATE_NEW_PROCESS_GROUP,
5750 envblk,
5751 NULL,
5752 &si,
5753 &pi)
5754 == 0) {
5756 conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
5757 pi.hProcess = (pid_t)-1;
5758 /* goto spawn_cleanup; */
5759 }
5760
5761spawn_cleanup:
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);
5767 }
5768
5769 return (pid_t)pi.hProcess;
5770}
5771#endif /* !NO_CGI */
5772
5773
5774static int
5776{
5777 unsigned long non_blocking = 0;
5778 return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5779}
5780
5781static int
5783{
5784 unsigned long non_blocking = 1;
5785 return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5786}
5787
5788#else
5789
5790static int
5791mg_stat(const struct mg_connection *conn,
5792 const char *path,
5793 struct mg_file_stat *filep)
5794{
5795 struct stat st;
5796 if (!filep) {
5797 return 0;
5798 }
5799 memset(filep, 0, sizeof(*filep));
5800
5801 if (conn && is_file_in_memory(conn, path)) {
5802
5803 /* Quick fix (for 1.9.x): */
5804 /* mg_stat must fill all fields, also for files in memory */
5805 struct mg_file tmp_file = STRUCT_FILE_INITIALIZER;
5806 open_file_in_memory(conn, path, &tmp_file, MG_FOPEN_MODE_NONE);
5807 filep->size = tmp_file.stat.size;
5808 filep->last_modified = time(NULL);
5809 filep->location = 2;
5810 /* TODO: remove legacy "files in memory" feature */
5811
5812 return 1;
5813 }
5814
5815 if (0 == stat(path, &st)) {
5816 filep->size = (uint64_t)(st.st_size);
5817 filep->last_modified = st.st_mtime;
5818 filep->is_directory = S_ISDIR(st.st_mode);
5819 return 1;
5820 }
5821
5822 return 0;
5823}
5824
5825
5826static void
5827set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
5828{
5829 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
5830 if (conn) {
5831 mg_cry_internal(conn,
5832 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
5833 __func__,
5834 strerror(ERRNO));
5835 }
5836 }
5837}
5838
5839
5840int
5842{
5843 pthread_t thread_id;
5844 pthread_attr_t attr;
5845 int result;
5846
5847 (void)pthread_attr_init(&attr);
5848 (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5849
5850#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5851 /* Compile-time option to control stack size,
5852 * e.g. -DUSE_STACK_SIZE=16384 */
5853 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5854#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5855
5856 result = pthread_create(&thread_id, &attr, func, param);
5857 pthread_attr_destroy(&attr);
5858
5859 return result;
5860}
5861
5862
5863/* Start a thread storing the thread context. */
5864static int
5866 void *param,
5867 pthread_t *threadidptr)
5868{
5869 pthread_t thread_id;
5870 pthread_attr_t attr;
5871 int result;
5872
5873 (void)pthread_attr_init(&attr);
5874
5875#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5876 /* Compile-time option to control stack size,
5877 * e.g. -DUSE_STACK_SIZE=16384 */
5878 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5879#endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
5880
5881 result = pthread_create(&thread_id, &attr, func, param);
5882 pthread_attr_destroy(&attr);
5883 if ((result == 0) && (threadidptr != NULL)) {
5884 *threadidptr = thread_id;
5885 }
5886 return result;
5887}
5888
5889
5890/* Wait for a thread to finish. */
5891static int
5892mg_join_thread(pthread_t threadid)
5893{
5894 int result;
5895
5896 result = pthread_join(threadid, NULL);
5897 return result;
5898}
5899
5900
5901#if !defined(NO_CGI)
5902static pid_t
5903spawn_process(struct mg_connection *conn,
5904 const char *prog,
5905 char *envblk,
5906 char *envp[],
5907 int fdin[2],
5908 int fdout[2],
5909 int fderr[2],
5910 const char *dir)
5911{
5912 pid_t pid;
5913 const char *interp;
5914
5915 (void)envblk;
5916
5917 if (conn == NULL) {
5918 return 0;
5919 }
5920
5921 if ((pid = fork()) == -1) {
5922 /* Parent */
5923 mg_send_http_error(conn,
5924 500,
5925 "Error: Creating CGI process\nfork(): %s",
5926 strerror(ERRNO));
5927 } else if (pid == 0) {
5928 /* Child */
5929 if (chdir(dir) != 0) {
5931 conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
5932 } else if (dup2(fdin[0], 0) == -1) {
5933 mg_cry_internal(conn,
5934 "%s: dup2(%d, 0): %s",
5935 __func__,
5936 fdin[0],
5937 strerror(ERRNO));
5938 } else if (dup2(fdout[1], 1) == -1) {
5939 mg_cry_internal(conn,
5940 "%s: dup2(%d, 1): %s",
5941 __func__,
5942 fdout[1],
5943 strerror(ERRNO));
5944 } else if (dup2(fderr[1], 2) == -1) {
5945 mg_cry_internal(conn,
5946 "%s: dup2(%d, 2): %s",
5947 __func__,
5948 fderr[1],
5949 strerror(ERRNO));
5950 } else {
5951 /* Keep stderr and stdout in two different pipes.
5952 * Stdout will be sent back to the client,
5953 * stderr should go into a server error log. */
5954 (void)close(fdin[0]);
5955 (void)close(fdout[1]);
5956 (void)close(fderr[1]);
5957
5958 /* Close write end fdin and read end fdout and fderr */
5959 (void)close(fdin[1]);
5960 (void)close(fdout[0]);
5961 (void)close(fderr[0]);
5962
5963 /* After exec, all signal handlers are restored to their default
5964 * values, with one exception of SIGCHLD. According to
5965 * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler
5966 * will leave unchanged after exec if it was set to be ignored.
5967 * Restore it to default action. */
5968 signal(SIGCHLD, SIG_DFL);
5969
5970 interp = conn->dom_ctx->config[CGI_INTERPRETER];
5971 if (interp == NULL) {
5972 (void)execle(prog, prog, NULL, envp);
5973 mg_cry_internal(conn,
5974 "%s: execle(%s): %s",
5975 __func__,
5976 prog,
5977 strerror(ERRNO));
5978 } else {
5979 (void)execle(interp, interp, prog, NULL, envp);
5980 mg_cry_internal(conn,
5981 "%s: execle(%s %s): %s",
5982 __func__,
5983 interp,
5984 prog,
5985 strerror(ERRNO));
5986 }
5987 }
5988 exit(EXIT_FAILURE);
5989 }
5990
5991 return pid;
5992}
5993#endif /* !NO_CGI */
5994
5995
5996static int
5998{
5999 int flags = fcntl(sock, F_GETFL, 0);
6000 if (flags < 0) {
6001 return -1;
6002 }
6003
6004 if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) {
6005 return -1;
6006 }
6007 return 0;
6008}
6009
6010static int
6012{
6013 int flags = fcntl(sock, F_GETFL, 0);
6014 if (flags < 0) {
6015 return -1;
6016 }
6017
6018 if (fcntl(sock, F_SETFL, flags & (~(int)(O_NONBLOCK))) < 0) {
6019 return -1;
6020 }
6021 return 0;
6022}
6023#endif /* _WIN32 / else */
6024
6025/* End of initial operating system specific define block. */
6026
6027
6028/* Get a random number (independent of C rand function) */
6029static uint64_t
6031{
6032 static uint64_t lfsr = 0; /* Linear feedback shift register */
6033 static uint64_t lcg = 0; /* Linear congruential generator */
6034 uint64_t now = mg_get_current_time_ns();
6035
6036 if (lfsr == 0) {
6037 /* lfsr will be only 0 if has not been initialized,
6038 * so this code is called only once. */
6039 lfsr = mg_get_current_time_ns();
6040 lcg = mg_get_current_time_ns();
6041 } else {
6042 /* Get the next step of both random number generators. */
6043 lfsr = (lfsr >> 1)
6044 | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
6045 << 63);
6046 lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
6047 }
6048
6049 /* Combining two pseudo-random number generators and a high resolution
6050 * part
6051 * of the current server time will make it hard (impossible?) to guess
6052 * the
6053 * next number. */
6054 return (lfsr ^ lcg ^ now);
6055}
6056
6057
6058static int
6059mg_poll(struct pollfd *pfd,
6060 unsigned int n,
6061 int milliseconds,
6062 volatile int *stop_server)
6063{
6064 /* Call poll, but only for a maximum time of a few seconds.
6065 * This will allow to stop the server after some seconds, instead
6066 * of having to wait for a long socket timeout. */
6067 int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
6068
6069 do {
6070 int result;
6071
6072 if (*stop_server) {
6073 /* Shut down signal */
6074 return -2;
6075 }
6076
6077 if ((milliseconds >= 0) && (milliseconds < ms_now)) {
6078 ms_now = milliseconds;
6079 }
6080
6081 result = poll(pfd, n, ms_now);
6082 if (result != 0) {
6083 /* Poll returned either success (1) or error (-1).
6084 * Forward both to the caller. */
6085 return result;
6086 }
6087
6088 /* Poll returned timeout (0). */
6089 if (milliseconds > 0) {
6090 milliseconds -= ms_now;
6091 }
6092
6093 } while (milliseconds != 0);
6094
6095 /* timeout: return 0 */
6096 return 0;
6097}
6098
6099
6100/* Write data to the IO channel - opened file descriptor, socket or SSL
6101 * descriptor.
6102 * Return value:
6103 * >=0 .. number of bytes successfully written
6104 * -1 .. timeout
6105 * -2 .. error
6106 */
6107static int
6108push_inner(struct mg_context *ctx,
6109 FILE *fp,
6110 SOCKET sock,
6111 SSL *ssl,
6112 const char *buf,
6113 int len,
6114 double timeout)
6115{
6116 uint64_t start = 0, now = 0, timeout_ns = 0;
6117 int n, err;
6118 unsigned ms_wait = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
6119
6120#if defined(_WIN32)
6121 typedef int len_t;
6122#else
6123 typedef size_t len_t;
6124#endif
6125
6126 if (timeout > 0) {
6127 now = mg_get_current_time_ns();
6128 start = now;
6129 timeout_ns = (uint64_t)(timeout * 1.0E9);
6130 }
6131
6132 if (ctx == NULL) {
6133 return -2;
6134 }
6135
6136#if defined(NO_SSL)
6137 if (ssl) {
6138 return -2;
6139 }
6140#endif
6141
6142 /* Try to read until it succeeds, fails, times out, or the server
6143 * shuts down. */
6144 for (;;) {
6145
6146#if !defined(NO_SSL)
6147 if (ssl != NULL) {
6148 n = SSL_write(ssl, buf, len);
6149 if (n <= 0) {
6150 err = SSL_get_error(ssl, n);
6151 if ((err == SSL_ERROR_SYSCALL) && (n == -1)) {
6152 err = ERRNO;
6153 } else if ((err == SSL_ERROR_WANT_READ)
6154 || (err == SSL_ERROR_WANT_WRITE)) {
6155 n = 0;
6156 } else {
6157 DEBUG_TRACE("SSL_write() failed, error %d", err);
6158 return -2;
6159 }
6160 } else {
6161 err = 0;
6162 }
6163 } else
6164#endif
6165 if (fp != NULL) {
6166 n = (int)fwrite(buf, 1, (size_t)len, fp);
6167 if (ferror(fp)) {
6168 n = -1;
6169 err = ERRNO;
6170 } else {
6171 err = 0;
6172 }
6173 } else {
6174 n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
6175 err = (n < 0) ? ERRNO : 0;
6176#if defined(_WIN32)
6177 if (err == WSAEWOULDBLOCK) {
6178 err = 0;
6179 n = 0;
6180 }
6181#else
6182 if (err == EWOULDBLOCK) {
6183 err = 0;
6184 n = 0;
6185 }
6186#endif
6187 if (n < 0) {
6188 /* shutdown of the socket at client side */
6189 return -2;
6190 }
6191 }
6192
6193 if (ctx->stop_flag) {
6194 return -2;
6195 }
6196
6197 if ((n > 0) || ((n == 0) && (len == 0))) {
6198 /* some data has been read, or no data was requested */
6199 return n;
6200 }
6201 if (n < 0) {
6202 /* socket error - check errno */
6203 DEBUG_TRACE("send() failed, error %d", err);
6204
6205 /* TODO (mid): error handling depending on the error code.
6206 * These codes are different between Windows and Linux.
6207 * Currently there is no problem with failing send calls,
6208 * if there is a reproducible situation, it should be
6209 * investigated in detail.
6210 */
6211 return -2;
6212 }
6213
6214 /* Only in case n=0 (timeout), repeat calling the write function */
6215
6216 /* If send failed, wait before retry */
6217 if (fp != NULL) {
6218 /* For files, just wait a fixed time.
6219 * Maybe it helps, maybe not. */
6220 mg_sleep(5);
6221 } else {
6222 /* For sockets, wait for the socket using poll */
6223 struct pollfd pfd[1];
6224 int pollres;
6225
6226 pfd[0].fd = sock;
6227 pfd[0].events = POLLOUT;
6228 pollres = mg_poll(pfd, 1, (int)(ms_wait), &(ctx->stop_flag));
6229 if (ctx->stop_flag) {
6230 return -2;
6231 }
6232 if (pollres > 0) {
6233 continue;
6234 }
6235 }
6236
6237 if (timeout > 0) {
6238 now = mg_get_current_time_ns();
6239 if ((now - start) > timeout_ns) {
6240 /* Timeout */
6241 break;
6242 }
6243 }
6244 }
6245
6246 (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
6247 used */
6248
6249 return -1;
6250}
6251
6252
6253static int64_t
6254push_all(struct mg_context *ctx,
6255 FILE *fp,
6256 SOCKET sock,
6257 SSL *ssl,
6258 const char *buf,
6259 int64_t len)
6260{
6261 double timeout = -1.0;
6262 int64_t n, nwritten = 0;
6263
6264 if (ctx == NULL) {
6265 return -1;
6266 }
6267
6268 if (ctx->dd.config[REQUEST_TIMEOUT]) {
6269 timeout = atoi(ctx->dd.config[REQUEST_TIMEOUT]) / 1000.0;
6270 }
6271
6272 while ((len > 0) && (ctx->stop_flag == 0)) {
6273 n = push_inner(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
6274 if (n < 0) {
6275 if (nwritten == 0) {
6276 nwritten = n; /* Propagate the error */
6277 }
6278 break;
6279 } else if (n == 0) {
6280 break; /* No more data to write */
6281 } else {
6282 nwritten += n;
6283 len -= n;
6284 }
6285 }
6286
6287 return nwritten;
6288}
6289
6290
6291/* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
6292 * Return value:
6293 * >=0 .. number of bytes successfully read
6294 * -1 .. timeout
6295 * -2 .. error
6296 */
6297static int
6298pull_inner(FILE *fp,
6299 struct mg_connection *conn,
6300 char *buf,
6301 int len,
6302 double timeout)
6303{
6304 int nread, err = 0;
6305
6306#if defined(_WIN32)
6307 typedef int len_t;
6308#else
6309 typedef size_t len_t;
6310#endif
6311#if !defined(NO_SSL)
6312 int ssl_pending;
6313#endif
6314
6315 /* We need an additional wait loop around this, because in some cases
6316 * with TLSwe may get data from the socket but not from SSL_read.
6317 * In this case we need to repeat at least once.
6318 */
6319
6320 if (fp != NULL) {
6321#if !defined(_WIN32_WCE)
6322 /* Use read() instead of fread(), because if we're reading from the
6323 * CGI pipe, fread() may block until IO buffer is filled up. We
6324 * cannot afford to block and must pass all read bytes immediately
6325 * to the client. */
6326 nread = (int)read(fileno(fp), buf, (size_t)len);
6327#else
6328 /* WinCE does not support CGI pipes */
6329 nread = (int)fread(buf, 1, (size_t)len, fp);
6330#endif
6331 err = (nread < 0) ? ERRNO : 0;
6332 if ((nread == 0) && (len > 0)) {
6333 /* Should get data, but got EOL */
6334 return -2;
6335 }
6336
6337#if !defined(NO_SSL)
6338 } else if ((conn->ssl != NULL)
6339 && ((ssl_pending = SSL_pending(conn->ssl)) > 0)) {
6340 /* We already know there is no more data buffered in conn->buf
6341 * but there is more available in the SSL layer. So don't poll
6342 * conn->client.sock yet. */
6343 if (ssl_pending > len) {
6344 ssl_pending = len;
6345 }
6346 nread = SSL_read(conn->ssl, buf, ssl_pending);
6347 if (nread <= 0) {
6348 err = SSL_get_error(conn->ssl, nread);
6349 if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
6350 err = ERRNO;
6351 } else if ((err == SSL_ERROR_WANT_READ)
6352 || (err == SSL_ERROR_WANT_WRITE)) {
6353 nread = 0;
6354 } else {
6355 DEBUG_TRACE("SSL_read() failed, error %d", err);
6356 return -1;
6357 }
6358 } else {
6359 err = 0;
6360 }
6361
6362 } else if (conn->ssl != NULL) {
6363
6364 struct pollfd pfd[1];
6365 int pollres;
6366
6367 pfd[0].fd = conn->client.sock;
6368 pfd[0].events = POLLIN;
6369 pollres = mg_poll(pfd,
6370 1,
6371 (int)(timeout * 1000.0),
6372 &(conn->phys_ctx->stop_flag));
6373 if (conn->phys_ctx->stop_flag) {
6374 return -2;
6375 }
6376 if (pollres > 0) {
6377 nread = SSL_read(conn->ssl, buf, len);
6378 if (nread <= 0) {
6379 err = SSL_get_error(conn->ssl, nread);
6380 if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {