Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
civetweb.c
Go to the documentation of this file.
1/* Copyright (c) 2013-2021 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 0x0502
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(__LSB_VERSION__) || defined(__sun)
63#define NEED_TIMEGM
64#define NO_THREAD_NAME
65#endif
66#if !defined(_LARGEFILE_SOURCE)
67#define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
68#endif
69#if !defined(_FILE_OFFSET_BITS)
70#define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
71#endif
72#if !defined(__STDC_FORMAT_MACROS)
73#define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
74#endif
75#if !defined(__STDC_LIMIT_MACROS)
76#define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
77#endif
78#if !defined(_DARWIN_UNLIMITED_SELECT)
79#define _DARWIN_UNLIMITED_SELECT
80#endif
81#if defined(__sun)
82#define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
83#define __inline inline /* not recognized on older compiler versions */
84#endif
85#endif
86
87#if defined(__clang__)
88/* Enable reserved-id-macro warning again. */
89#pragma GCC diagnostic pop
90#endif
91
92
93#if defined(USE_LUA)
94#define USE_TIMERS
95#endif
96
97#if defined(_MSC_VER)
98/* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
99#pragma warning(disable : 4306)
100/* conditional expression is constant: introduced by FD_SET(..) */
101#pragma warning(disable : 4127)
102/* non-constant aggregate initializer: issued due to missing C99 support */
103#pragma warning(disable : 4204)
104/* padding added after data member */
105#pragma warning(disable : 4820)
106/* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
107#pragma warning(disable : 4668)
108/* no function prototype given: converting '()' to '(void)' */
109#pragma warning(disable : 4255)
110/* function has been selected for automatic inline expansion */
111#pragma warning(disable : 4711)
112#endif
113
114
115/* This code uses static_assert to check some conditions.
116 * Unfortunately some compilers still do not support it, so we have a
117 * replacement function here. */
118#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201100L
119#define mg_static_assert _Static_assert
120#elif defined(__cplusplus) && __cplusplus >= 201103L
121#define mg_static_assert static_assert
122#else
124#define mg_static_assert(cond, txt) \
125 extern char static_assert_replacement[(cond) ? 1 : -1]
126#endif
127
128mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
129 "int data type size check");
130mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
131 "pointer data type size check");
132mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
133
134
135/* Select queue implementation. Diagnosis features originally only implemented
136 * for the "ALTERNATIVE_QUEUE" have been ported to the previous queue
137 * implementation (NO_ALTERNATIVE_QUEUE) as well. The new configuration value
138 * "CONNECTION_QUEUE_SIZE" is only available for the previous queue
139 * implementation, since the queue length is independent from the number of
140 * worker threads there, while the new queue is one element per worker thread.
141 *
142 */
143#if defined(NO_ALTERNATIVE_QUEUE) && defined(ALTERNATIVE_QUEUE)
144/* The queues are exclusive or - only one can be used. */
145#error \
146 "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE (or none of them), but not both"
147#endif
148#if !defined(NO_ALTERNATIVE_QUEUE) && !defined(ALTERNATIVE_QUEUE)
149/* Use a default implementation */
150#define NO_ALTERNATIVE_QUEUE
151#endif
152
153#if defined(NO_FILESYSTEMS) && !defined(NO_FILES)
154/* File system access:
155 * NO_FILES = do not serve any files from the file system automatically.
156 * However, with NO_FILES CivetWeb may still write log files, read access
157 * control files, default error page files or use API functions like
158 * mg_send_file in callbacks to send files from the server local
159 * file system.
160 * NO_FILES only disables the automatic mapping between URLs and local
161 * file names.
162 * NO_FILESYSTEM = do not access any file at all. Useful for embedded
163 * devices without file system. Logging to files in not available
164 * (use callbacks instead) and API functions like mg_send_file are not
165 * available.
166 * If NO_FILESYSTEM is set, NO_FILES must be set as well.
167 */
168#error "Inconsistent build flags, NO_FILESYSTEMS requires NO_FILES"
169#endif
170
171/* DTL -- including winsock2.h works better if lean and mean */
172#if !defined(WIN32_LEAN_AND_MEAN)
173#define WIN32_LEAN_AND_MEAN
174#endif
175
176#if defined(__SYMBIAN32__)
177/* According to https://en.wikipedia.org/wiki/Symbian#History,
178 * Symbian is no longer maintained since 2014-01-01.
179 * Support for Symbian has been removed from CivetWeb
180 */
181#error "Symbian is no longer maintained. CivetWeb no longer supports Symbian."
182#endif /* __SYMBIAN32__ */
183
184#if defined(__ZEPHYR__)
185#include <time.h>
186
187#include <ctype.h>
188#include <net/socket.h>
189#include <posix/pthread.h>
190#include <posix/time.h>
191#include <stdio.h>
192#include <stdlib.h>
193#include <string.h>
194#include <zephyr.h>
195
196#include <fcntl.h>
197
198#include <libc_extensions.h>
199
200/* Max worker threads is the max of pthreads minus the main application thread
201 * and minus the main civetweb thread, thus -2
202 */
203#define MAX_WORKER_THREADS (CONFIG_MAX_PTHREAD_COUNT - 2)
204
205#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
206#define ZEPHYR_STACK_SIZE USE_STACK_SIZE
207#else
208#define ZEPHYR_STACK_SIZE (1024 * 16)
209#endif
210
211K_THREAD_STACK_DEFINE(civetweb_main_stack, ZEPHYR_STACK_SIZE);
212K_THREAD_STACK_ARRAY_DEFINE(civetweb_worker_stacks,
214 ZEPHYR_STACK_SIZE);
215
216static int zephyr_worker_stack_index;
217
218#endif
219
220#if !defined(CIVETWEB_HEADER_INCLUDED)
221/* Include the header file here, so the CivetWeb interface is defined for the
222 * entire implementation, including the following forward definitions. */
223#include "civetweb.h"
224#endif
225
226#if !defined(DEBUG_TRACE)
227#if defined(DEBUG)
228static void DEBUG_TRACE_FUNC(const char *func,
229 unsigned line,
230 PRINTF_FORMAT_STRING(const char *fmt),
231 ...) PRINTF_ARGS(3, 4);
232
233#define DEBUG_TRACE(fmt, ...) \
234 DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
235
236#define NEED_DEBUG_TRACE_FUNC
237#if !defined(DEBUG_TRACE_STREAM)
238#define DEBUG_TRACE_STREAM stdout
239#endif
240
241#else
242#define DEBUG_TRACE(fmt, ...) \
243 do { \
244 } while (0)
245#endif /* DEBUG */
246#endif /* DEBUG_TRACE */
247
248
249#if !defined(DEBUG_ASSERT)
250#if defined(DEBUG)
251#include <stdlib.h>
252#define DEBUG_ASSERT(cond) \
253 do { \
254 if (!(cond)) { \
255 DEBUG_TRACE("ASSERTION FAILED: %s", #cond); \
256 exit(2); /* Exit with error */ \
257 } \
258 } while (0)
259#else
260#define DEBUG_ASSERT(cond)
261#endif /* DEBUG */
262#endif
263
264
265#if defined(__GNUC__) && defined(GCC_INSTRUMENTATION)
266void __cyg_profile_func_enter(void *this_fn, void *call_site)
267 __attribute__((no_instrument_function));
268
269void __cyg_profile_func_exit(void *this_fn, void *call_site)
270 __attribute__((no_instrument_function));
271
272void
273__cyg_profile_func_enter(void *this_fn, void *call_site)
274{
275 if ((void *)this_fn != (void *)printf) {
276 printf("E %p %p\n", this_fn, call_site);
277 }
278}
279
280void
281__cyg_profile_func_exit(void *this_fn, void *call_site)
282{
283 if ((void *)this_fn != (void *)printf) {
284 printf("X %p %p\n", this_fn, call_site);
285 }
286}
287#endif
288
289
290#if !defined(IGNORE_UNUSED_RESULT)
291#define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
292#endif
293
294
295#if defined(__GNUC__) || defined(__MINGW32__)
296
297/* GCC unused function attribute seems fundamentally broken.
298 * Several attempts to tell the compiler "THIS FUNCTION MAY BE USED
299 * OR UNUSED" for individual functions failed.
300 * Either the compiler creates an "unused-function" warning if a
301 * function is not marked with __attribute__((unused)).
302 * On the other hand, if the function is marked with this attribute,
303 * but is used, the compiler raises a completely idiotic
304 * "used-but-marked-unused" warning - and
305 * #pragma GCC diagnostic ignored "-Wused-but-marked-unused"
306 * raises error: unknown option after "#pragma GCC diagnostic".
307 * Disable this warning completely, until the GCC guys sober up
308 * again.
309 */
310
311#pragma GCC diagnostic ignored "-Wunused-function"
312
313#define FUNCTION_MAY_BE_UNUSED /* __attribute__((unused)) */
314
315#else
316#define FUNCTION_MAY_BE_UNUSED
317#endif
318
319
320/* Some ANSI #includes are not available on Windows CE and Zephyr */
321#if !defined(_WIN32_WCE) && !defined(__ZEPHYR__)
322#include <errno.h>
323#include <fcntl.h>
324#include <signal.h>
325#include <stdlib.h>
326#include <sys/stat.h>
327#include <sys/types.h>
328#endif /* !_WIN32_WCE */
329
330
331#if defined(__clang__)
332/* When using -Weverything, clang does not accept it's own headers
333 * in a release build configuration. Disable what is too much in
334 * -Weverything. */
335#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
336#endif
337
338#if defined(__GNUC__) || defined(__MINGW32__)
339/* Who on earth came to the conclusion, using __DATE__ should rise
340 * an "expansion of date or time macro is not reproducible"
341 * warning. That's exactly what was intended by using this macro.
342 * Just disable this nonsense warning. */
343
344/* And disabling them does not work either:
345 * #pragma clang diagnostic ignored "-Wno-error=date-time"
346 * #pragma clang diagnostic ignored "-Wdate-time"
347 * So we just have to disable ALL warnings for some lines
348 * of code.
349 * This seems to be a known GCC bug, not resolved since 2012:
350 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
351 */
352#endif
353
354
355#if defined(__MACH__) /* Apple OSX section */
356
357#if defined(__clang__)
358#if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8))
359/* Avoid warnings for Xcode 7. It seems it does no longer exist in Xcode 8 */
360#pragma clang diagnostic ignored "-Wno-reserved-id-macro"
361#pragma clang diagnostic ignored "-Wno-keyword-macro"
362#endif
363#endif
364
365#ifndef CLOCK_MONOTONIC
366#define CLOCK_MONOTONIC (1)
367#endif
368#ifndef CLOCK_REALTIME
369#define CLOCK_REALTIME (2)
370#endif
371
372#include <mach/clock.h>
373#include <mach/mach.h>
374#include <mach/mach_time.h>
375#include <sys/errno.h>
376#include <sys/time.h>
377
378/* clock_gettime is not implemented on OSX prior to 10.12 */
379static int
380_civet_clock_gettime(int clk_id, struct timespec *t)
381{
382 memset(t, 0, sizeof(*t));
383 if (clk_id == CLOCK_REALTIME) {
384 struct timeval now;
385 int rv = gettimeofday(&now, NULL);
386 if (rv) {
387 return rv;
388 }
389 t->tv_sec = now.tv_sec;
390 t->tv_nsec = now.tv_usec * 1000;
391 return 0;
392
393 } else if (clk_id == CLOCK_MONOTONIC) {
394 static uint64_t clock_start_time = 0;
395 static mach_timebase_info_data_t timebase_ifo = {0, 0};
396
397 uint64_t now = mach_absolute_time();
398
399 if (clock_start_time == 0) {
400 kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
401 DEBUG_ASSERT(mach_status == KERN_SUCCESS);
402
403 /* appease "unused variable" warning for release builds */
404 (void)mach_status;
405
406 clock_start_time = now;
407 }
408
409 now = (uint64_t)((double)(now - clock_start_time)
410 * (double)timebase_ifo.numer
411 / (double)timebase_ifo.denom);
412
413 t->tv_sec = now / 1000000000;
414 t->tv_nsec = now % 1000000000;
415 return 0;
416 }
417 return -1; /* EINVAL - Clock ID is unknown */
418}
419
420/* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
421#if defined(__CLOCK_AVAILABILITY)
422/* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be
423 * declared but it may be NULL at runtime. So we need to check before using
424 * it. */
425static int
426_civet_safe_clock_gettime(int clk_id, struct timespec *t)
427{
428 if (clock_gettime) {
429 return clock_gettime(clk_id, t);
430 }
431 return _civet_clock_gettime(clk_id, t);
432}
433#define clock_gettime _civet_safe_clock_gettime
434#else
435#define clock_gettime _civet_clock_gettime
436#endif
437
438#endif
439
440
441#if !defined(_WIN32)
442/* Unix might return different error codes indicating to try again.
443 * For Linux EAGAIN==EWOULDBLOCK, maybe EAGAIN!=EWOULDBLOCK is history from
444 * decades ago, but better check both and let the compile optimize it. */
445#define ERROR_TRY_AGAIN(err) \
446 (((err) == EAGAIN) || ((err) == EWOULDBLOCK) || ((err) == EINTR))
447#endif
448
449#if defined(USE_ZLIB)
450#include "zconf.h"
451#include "zlib.h"
452#endif
453
454
455/********************************************************************/
456/* CivetWeb configuration defines */
457/********************************************************************/
458
459/* Maximum number of threads that can be configured.
460 * The number of threads actually created depends on the "num_threads"
461 * configuration parameter, but this is the upper limit. */
462#if !defined(MAX_WORKER_THREADS)
463#define MAX_WORKER_THREADS (1024 * 64) /* in threads (count) */
464#endif
465
466/* Timeout interval for select/poll calls.
467 * The timeouts depend on "*_timeout_ms" configuration values, but long
468 * timeouts are split into timouts as small as SOCKET_TIMEOUT_QUANTUM.
469 * This reduces the time required to stop the server. */
470#if !defined(SOCKET_TIMEOUT_QUANTUM)
471#define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */
472#endif
473
474/* Do not try to compress files smaller than this limit. */
475#if !defined(MG_FILE_COMPRESSION_SIZE_LIMIT)
476#define MG_FILE_COMPRESSION_SIZE_LIMIT (1024) /* in bytes */
477#endif
478
479#if !defined(PASSWORDS_FILE_NAME)
480#define PASSWORDS_FILE_NAME ".htpasswd"
481#endif
482
483/* Initial buffer size for all CGI environment variables. In case there is
484 * not enough space, another block is allocated. */
485#if !defined(CGI_ENVIRONMENT_SIZE)
486#define CGI_ENVIRONMENT_SIZE (4096) /* in bytes */
487#endif
488
489/* Maximum number of environment variables. */
490#if !defined(MAX_CGI_ENVIR_VARS)
491#define MAX_CGI_ENVIR_VARS (256) /* in variables (count) */
492#endif
493
494/* General purpose buffer size. */
495#if !defined(MG_BUF_LEN) /* in bytes */
496#define MG_BUF_LEN (1024 * 8)
497#endif
498
499
500/********************************************************************/
501
502/* Helper makros */
503#if !defined(ARRAY_SIZE)
504#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
505#endif
506
507#include <stdint.h>
508
509/* Standard defines */
510#if !defined(INT64_MAX)
511#define INT64_MAX (9223372036854775807)
512#endif
513
514#define SHUTDOWN_RD (0)
515#define SHUTDOWN_WR (1)
516#define SHUTDOWN_BOTH (2)
517
519 "worker threads must be a positive number");
520
521mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8,
522 "size_t data type size check");
523
524
525#if defined(_WIN32) /* WINDOWS include block */
526#include <malloc.h> /* *alloc( */
527#include <stdlib.h> /* *alloc( */
528#include <time.h> /* struct timespec */
529#include <windows.h>
530#include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
531#include <ws2tcpip.h>
532
533typedef const char *SOCK_OPT_TYPE;
534
535/* For a detailed description of these *_PATH_MAX defines, see
536 * https://github.com/civetweb/civetweb/issues/937. */
537
538/* UTF8_PATH_MAX is a char buffer size for 259 BMP characters in UTF-8 plus
539 * null termination, rounded up to the next 4 bytes boundary */
540#define UTF8_PATH_MAX (3 * 260)
541/* UTF16_PATH_MAX is the 16-bit wchar_t buffer size required for 259 BMP
542 * characters plus termination. (Note: wchar_t is 16 bit on Windows) */
543#define UTF16_PATH_MAX (260)
544
545#if !defined(_IN_PORT_T)
546#if !defined(in_port_t)
547#define in_port_t u_short
548#endif
549#endif
550
551#if defined(_WIN32_WCE)
552#error "WinCE support has ended"
553#endif
554
555#include <direct.h>
556#include <io.h>
557#include <process.h>
558
559
560#define MAKEUQUAD(lo, hi) \
561 ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
562#define RATE_DIFF (10000000) /* 100 nsecs */
563#define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
564#define SYS2UNIX_TIME(lo, hi) \
565 ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
566
567/* Visual Studio 6 does not know __func__ or __FUNCTION__
568 * The rest of MS compilers use __FUNCTION__, not C99 __func__
569 * Also use _strtoui64 on modern M$ compilers */
570#if defined(_MSC_VER)
571#if (_MSC_VER < 1300)
572#define STRX(x) #x
573#define STR(x) STRX(x)
574#define __func__ __FILE__ ":" STR(__LINE__)
575#define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
576#define strtoll(x, y, z) (_atoi64(x))
577#else
578#define __func__ __FUNCTION__
579#define strtoull(x, y, z) (_strtoui64(x, y, z))
580#define strtoll(x, y, z) (_strtoi64(x, y, z))
581#endif
582#endif /* _MSC_VER */
583
584#define ERRNO ((int)(GetLastError()))
585#define NO_SOCKLEN_T
586
587
588#if defined(_WIN64) || defined(__MINGW64__)
589#if !defined(SSL_LIB)
590
591#if defined(OPENSSL_API_3_0)
592#define SSL_LIB "libssl-3-x64.dll"
593#define CRYPTO_LIB "libcrypto-3-x64.dll"
594#endif
595
596#if defined(OPENSSL_API_1_1)
597#define SSL_LIB "libssl-1_1-x64.dll"
598#define CRYPTO_LIB "libcrypto-1_1-x64.dll"
599#endif /* OPENSSL_API_1_1 */
600
601#if defined(OPENSSL_API_1_0)
602#define SSL_LIB "ssleay64.dll"
603#define CRYPTO_LIB "libeay64.dll"
604#endif /* OPENSSL_API_1_0 */
605
606#endif
607#else /* defined(_WIN64) || defined(__MINGW64__) */
608#if !defined(SSL_LIB)
609
610#if defined(OPENSSL_API_3_0)
611#define SSL_LIB "libssl-3.dll"
612#define CRYPTO_LIB "libcrypto-3.dll"
613#endif
614
615#if defined(OPENSSL_API_1_1)
616#define SSL_LIB "libssl-1_1.dll"
617#define CRYPTO_LIB "libcrypto-1_1.dll"
618#endif /* OPENSSL_API_1_1 */
619
620#if defined(OPENSSL_API_1_0)
621#define SSL_LIB "ssleay32.dll"
622#define CRYPTO_LIB "libeay32.dll"
623#endif /* OPENSSL_API_1_0 */
624
625#endif /* SSL_LIB */
626#endif /* defined(_WIN64) || defined(__MINGW64__) */
627
628
629#define O_NONBLOCK (0)
630#if !defined(W_OK)
631#define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
632#endif
633#define _POSIX_
634#define INT64_FMT "I64d"
635#define UINT64_FMT "I64u"
636
637#define WINCDECL __cdecl
638#define vsnprintf_impl _vsnprintf
639#define access _access
640#define mg_sleep(x) (Sleep(x))
641
642#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
643#if !defined(popen)
644#define popen(x, y) (_popen(x, y))
645#endif
646#if !defined(pclose)
647#define pclose(x) (_pclose(x))
648#endif
649#define close(x) (_close(x))
650#define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
651#define RTLD_LAZY (0)
652#define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0)
653#define fdopen(x, y) (_fdopen((x), (y)))
654#define write(x, y, z) (_write((x), (y), (unsigned)z))
655#define read(x, y, z) (_read((x), (y), (unsigned)z))
656#define flockfile(x) ((void)pthread_mutex_lock(&global_log_file_lock))
657#define funlockfile(x) ((void)pthread_mutex_unlock(&global_log_file_lock))
658#define sleep(x) (Sleep((x)*1000))
659#define rmdir(x) (_rmdir(x))
660#if defined(_WIN64) || !defined(__MINGW32__)
661/* Only MinGW 32 bit is missing this function */
662#define timegm(x) (_mkgmtime(x))
663#else
664time_t timegm(struct tm *tm);
665#define NEED_TIMEGM
666#endif
667
668
669#if !defined(fileno)
670#define fileno(x) (_fileno(x))
671#endif /* !fileno MINGW #defines fileno */
672
673typedef struct {
674 CRITICAL_SECTION sec; /* Immovable */
675} pthread_mutex_t;
676typedef DWORD pthread_key_t;
677typedef HANDLE pthread_t;
678typedef struct {
679 pthread_mutex_t threadIdSec;
680 struct mg_workerTLS *waiting_thread; /* The chain of threads */
682
683#if !defined(__clockid_t_defined)
684typedef DWORD clockid_t;
685#endif
686#if !defined(CLOCK_MONOTONIC)
687#define CLOCK_MONOTONIC (1)
688#endif
689#if !defined(CLOCK_REALTIME)
690#define CLOCK_REALTIME (2)
691#endif
692#if !defined(CLOCK_THREAD)
693#define CLOCK_THREAD (3)
694#endif
695#if !defined(CLOCK_PROCESS)
696#define CLOCK_PROCESS (4)
697#endif
698
699
700#if defined(_MSC_VER) && (_MSC_VER >= 1900)
701#define _TIMESPEC_DEFINED
702#endif
703#if !defined(_TIMESPEC_DEFINED)
704struct timespec {
705 time_t tv_sec; /* seconds */
706 long tv_nsec; /* nanoseconds */
707};
708#endif
709
710#if !defined(WIN_PTHREADS_TIME_H)
711#define MUST_IMPLEMENT_CLOCK_GETTIME
712#endif
713
714#if defined(MUST_IMPLEMENT_CLOCK_GETTIME)
715#define clock_gettime mg_clock_gettime
716static int
717clock_gettime(clockid_t clk_id, struct timespec *tp)
718{
719 FILETIME ft;
720 ULARGE_INTEGER li, li2;
721 BOOL ok = FALSE;
722 double d;
723 static double perfcnt_per_sec = 0.0;
724 static BOOL initialized = FALSE;
725
726 if (!initialized) {
727 QueryPerformanceFrequency((LARGE_INTEGER *)&li);
728 perfcnt_per_sec = 1.0 / li.QuadPart;
729 initialized = TRUE;
730 }
731
732 if (tp) {
733 memset(tp, 0, sizeof(*tp));
734
735 if (clk_id == CLOCK_REALTIME) {
736
737 /* BEGIN: CLOCK_REALTIME = wall clock (date and time) */
738 GetSystemTimeAsFileTime(&ft);
739 li.LowPart = ft.dwLowDateTime;
740 li.HighPart = ft.dwHighDateTime;
741 li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
742 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
743 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
744 ok = TRUE;
745 /* END: CLOCK_REALTIME */
746
747 } else if (clk_id == CLOCK_MONOTONIC) {
748
749 /* BEGIN: CLOCK_MONOTONIC = stopwatch (time differences) */
750 QueryPerformanceCounter((LARGE_INTEGER *)&li);
751 d = li.QuadPart * perfcnt_per_sec;
752 tp->tv_sec = (time_t)d;
753 d -= (double)tp->tv_sec;
754 tp->tv_nsec = (long)(d * 1.0E9);
755 ok = TRUE;
756 /* END: CLOCK_MONOTONIC */
757
758 } else if (clk_id == CLOCK_THREAD) {
759
760 /* BEGIN: CLOCK_THREAD = CPU usage of thread */
761 FILETIME t_create, t_exit, t_kernel, t_user;
762 if (GetThreadTimes(GetCurrentThread(),
763 &t_create,
764 &t_exit,
765 &t_kernel,
766 &t_user)) {
767 li.LowPart = t_user.dwLowDateTime;
768 li.HighPart = t_user.dwHighDateTime;
769 li2.LowPart = t_kernel.dwLowDateTime;
770 li2.HighPart = t_kernel.dwHighDateTime;
771 li.QuadPart += li2.QuadPart;
772 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
773 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
774 ok = TRUE;
775 }
776 /* END: CLOCK_THREAD */
777
778 } else if (clk_id == CLOCK_PROCESS) {
779
780 /* BEGIN: CLOCK_PROCESS = CPU usage of process */
781 FILETIME t_create, t_exit, t_kernel, t_user;
782 if (GetProcessTimes(GetCurrentProcess(),
783 &t_create,
784 &t_exit,
785 &t_kernel,
786 &t_user)) {
787 li.LowPart = t_user.dwLowDateTime;
788 li.HighPart = t_user.dwHighDateTime;
789 li2.LowPart = t_kernel.dwLowDateTime;
790 li2.HighPart = t_kernel.dwHighDateTime;
791 li.QuadPart += li2.QuadPart;
792 tp->tv_sec = (time_t)(li.QuadPart / 10000000);
793 tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
794 ok = TRUE;
795 }
796 /* END: CLOCK_PROCESS */
797
798 } else {
799
800 /* BEGIN: unknown clock */
801 /* ok = FALSE; already set by init */
802 /* END: unknown clock */
803 }
804 }
805
806 return ok ? 0 : -1;
807}
808#endif
809
810
811#define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
812
813static int pthread_mutex_lock(pthread_mutex_t *);
814static int pthread_mutex_unlock(pthread_mutex_t *);
815static void path_to_unicode(const struct mg_connection *conn,
816 const char *path,
817 wchar_t *wbuf,
818 size_t wbuf_len);
819
820/* All file operations need to be rewritten to solve #246. */
821
822struct mg_file;
823
824static const char *mg_fgets(char *buf, size_t size, struct mg_file *filep);
825
826
827/* POSIX dirent interface */
828struct dirent {
829 char d_name[UTF8_PATH_MAX];
830};
831
832typedef struct DIR {
833 HANDLE handle;
834 WIN32_FIND_DATAW info;
835 struct dirent result;
836} DIR;
837
838#if defined(HAVE_POLL)
839#define mg_pollfd pollfd
840#else
841struct mg_pollfd {
842 SOCKET fd;
843 short events;
844 short revents;
845};
846#endif
847
848/* Mark required libraries */
849#if defined(_MSC_VER)
850#pragma comment(lib, "Ws2_32.lib")
851#endif
852
853#else /* defined(_WIN32) - WINDOWS vs UNIX include block */
854
855#include <inttypes.h>
856
857/* Linux & co. internally use UTF8 */
858#define UTF8_PATH_MAX (PATH_MAX)
859
860typedef const void *SOCK_OPT_TYPE;
861
862#if defined(ANDROID)
863typedef unsigned short int in_port_t;
864#endif
865
866#if !defined(__ZEPHYR__)
867#include <arpa/inet.h>
868#include <ctype.h>
869#include <dirent.h>
870#include <grp.h>
871#include <limits.h>
872#include <netdb.h>
873#include <netinet/in.h>
874#include <netinet/tcp.h>
875#include <pthread.h>
876#include <pwd.h>
877#include <stdarg.h>
878#include <stddef.h>
879#include <stdio.h>
880#include <stdlib.h>
881#include <string.h>
882#include <sys/poll.h>
883#include <sys/socket.h>
884#include <sys/time.h>
885#include <sys/utsname.h>
886#include <sys/wait.h>
887#include <time.h>
888#include <unistd.h>
889#if defined(USE_X_DOM_SOCKET)
890#include <sys/un.h>
891#endif
892#endif
893
894#define vsnprintf_impl vsnprintf
895
896#if !defined(NO_SSL_DL) && !defined(NO_SSL)
897#include <dlfcn.h>
898#endif
899
900#if defined(__MACH__)
901#define SSL_LIB "libssl.dylib"
902#define CRYPTO_LIB "libcrypto.dylib"
903#else
904#if !defined(SSL_LIB)
905#define SSL_LIB "libssl.so"
906#endif
907#if !defined(CRYPTO_LIB)
908#define CRYPTO_LIB "libcrypto.so"
909#endif
910#endif
911#if !defined(O_BINARY)
912#define O_BINARY (0)
913#endif /* O_BINARY */
914#define closesocket(a) (close(a))
915#define mg_mkdir(conn, path, mode) (mkdir(path, mode))
916#define mg_remove(conn, x) (remove(x))
917#define mg_sleep(x) (usleep((x)*1000))
918#define mg_opendir(conn, x) (opendir(x))
919#define mg_closedir(x) (closedir(x))
920#define mg_readdir(x) (readdir(x))
921#define ERRNO (errno)
922#define INVALID_SOCKET (-1)
923#define INT64_FMT PRId64
924#define UINT64_FMT PRIu64
925typedef int SOCKET;
926#define WINCDECL
927
928#if defined(__hpux)
929/* HPUX 11 does not have monotonic, fall back to realtime */
930#if !defined(CLOCK_MONOTONIC)
931#define CLOCK_MONOTONIC CLOCK_REALTIME
932#endif
933
934/* HPUX defines socklen_t incorrectly as size_t which is 64bit on
935 * Itanium. Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
936 * the prototypes use int* rather than socklen_t* which matches the
937 * actual library expectation. When called with the wrong size arg
938 * accept() returns a zero client inet addr and check_acl() always
939 * fails. Since socklen_t is widely used below, just force replace
940 * their typedef with int. - DTL
941 */
942#define socklen_t int
943#endif /* hpux */
944
945#define mg_pollfd pollfd
946
947#endif /* defined(_WIN32) - WINDOWS vs UNIX include block */
948
949/* In case our C library is missing "timegm", provide an implementation */
950#if defined(NEED_TIMEGM)
951static inline int
952is_leap(int y)
953{
954 return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
955}
956
957static inline int
958count_leap(int y)
959{
960 return (y - 1969) / 4 - (y - 1901) / 100 + (y - 1601) / 400;
961}
962
963time_t
964timegm(struct tm *tm)
965{
966 static const unsigned short ydays[] = {
967 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
968 int year = tm->tm_year + 1900;
969 int mon = tm->tm_mon;
970 int mday = tm->tm_mday - 1;
971 int hour = tm->tm_hour;
972 int min = tm->tm_min;
973 int sec = tm->tm_sec;
974
975 if (year < 1970 || mon < 0 || mon > 11 || mday < 0
976 || (mday >= ydays[mon + 1] - ydays[mon]
977 + (mon == 1 && is_leap(year) ? 1 : 0))
978 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60)
979 return -1;
980
981 time_t res = year - 1970;
982 res *= 365;
983 res += mday;
984 res += ydays[mon] + (mon > 1 && is_leap(year) ? 1 : 0);
985 res += count_leap(year);
986
987 res *= 24;
988 res += hour;
989 res *= 60;
990 res += min;
991 res *= 60;
992 res += sec;
993 return res;
994}
995#endif /* NEED_TIMEGM */
996
997
998/* va_copy should always be a macro, C99 and C++11 - DTL */
999#if !defined(va_copy)
1000#define va_copy(x, y) ((x) = (y))
1001#endif
1002
1003
1004#if defined(_WIN32)
1005/* Create substitutes for POSIX functions in Win32. */
1006
1007#if defined(GCC_DIAGNOSTIC)
1008/* Show no warning in case system functions are not used. */
1009#pragma GCC diagnostic push
1010#pragma GCC diagnostic ignored "-Wunused-function"
1011#endif
1012
1013
1014static pthread_mutex_t global_log_file_lock;
1015
1017static DWORD
1018pthread_self(void)
1019{
1020 return GetCurrentThreadId();
1021}
1022
1023
1025static int
1026pthread_key_create(
1027 pthread_key_t *key,
1028 void (*_ignored)(void *) /* destructor not supported for Windows */
1029)
1030{
1031 (void)_ignored;
1032
1033 if ((key != 0)) {
1034 *key = TlsAlloc();
1035 return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
1036 }
1037 return -2;
1038}
1039
1040
1042static int
1043pthread_key_delete(pthread_key_t key)
1044{
1045 return TlsFree(key) ? 0 : 1;
1046}
1047
1048
1050static int
1051pthread_setspecific(pthread_key_t key, void *value)
1052{
1053 return TlsSetValue(key, value) ? 0 : 1;
1054}
1055
1056
1058static void *
1059pthread_getspecific(pthread_key_t key)
1060{
1061 return TlsGetValue(key);
1062}
1063
1064#if defined(GCC_DIAGNOSTIC)
1065/* Enable unused function warning again */
1066#pragma GCC diagnostic pop
1067#endif
1068
1069static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
1070#else
1071static pthread_mutexattr_t pthread_mutex_attr;
1072#endif /* _WIN32 */
1073
1074
1075#if defined(GCC_DIAGNOSTIC)
1076/* Show no warning in case system functions are not used. */
1077#pragma GCC diagnostic push
1078#pragma GCC diagnostic ignored "-Wunused-function"
1079#endif /* defined(GCC_DIAGNOSTIC) */
1080#if defined(__clang__)
1081/* Show no warning in case system functions are not used. */
1082#pragma clang diagnostic push
1083#pragma clang diagnostic ignored "-Wunused-function"
1084#endif
1085
1086static pthread_mutex_t global_lock_mutex;
1087
1088
1090static void
1092{
1093 (void)pthread_mutex_lock(&global_lock_mutex);
1094}
1095
1096
1098static void
1100{
1101 (void)pthread_mutex_unlock(&global_lock_mutex);
1102}
1103
1104
1105#if defined(_WIN64)
1106mg_static_assert(SIZE_MAX == 0xFFFFFFFFFFFFFFFFu, "Mismatch for atomic types");
1107#elif defined(_WIN32)
1108mg_static_assert(SIZE_MAX == 0xFFFFFFFFu, "Mismatch for atomic types");
1109#endif
1110
1111
1112/* Atomic functions working on ptrdiff_t ("signed size_t").
1113 * Operations: Increment, Decrement, Add, Maximum.
1114 * Up to size_t, they do not an atomic "load" operation.
1115 */
1117static ptrdiff_t
1118mg_atomic_inc(volatile ptrdiff_t *addr)
1119{
1120 ptrdiff_t ret;
1121
1122#if defined(_WIN64) && !defined(NO_ATOMICS)
1123 ret = InterlockedIncrement64(addr);
1124#elif defined(_WIN32) && !defined(NO_ATOMICS)
1125 ret = InterlockedIncrement(addr);
1126#elif defined(__GNUC__) \
1127 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1128 && !defined(NO_ATOMICS)
1129 ret = __sync_add_and_fetch(addr, 1);
1130#else
1132 ret = (++(*addr));
1134#endif
1135 return ret;
1136}
1137
1138
1140static ptrdiff_t
1141mg_atomic_dec(volatile ptrdiff_t *addr)
1142{
1143 ptrdiff_t ret;
1144
1145#if defined(_WIN64) && !defined(NO_ATOMICS)
1146 ret = InterlockedDecrement64(addr);
1147#elif defined(_WIN32) && !defined(NO_ATOMICS)
1148 ret = InterlockedDecrement(addr);
1149#elif defined(__GNUC__) \
1150 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1151 && !defined(NO_ATOMICS)
1152 ret = __sync_sub_and_fetch(addr, 1);
1153#else
1155 ret = (--(*addr));
1157#endif
1158 return ret;
1159}
1160
1161
1162#if defined(USE_SERVER_STATS) || defined(STOP_FLAG_NEEDS_LOCK)
1163static ptrdiff_t
1164mg_atomic_add(volatile ptrdiff_t *addr, ptrdiff_t value)
1165{
1166 ptrdiff_t ret;
1167
1168#if defined(_WIN64) && !defined(NO_ATOMICS)
1169 ret = InterlockedAdd64(addr, value);
1170#elif defined(_WIN32) && !defined(NO_ATOMICS)
1171 ret = InterlockedExchangeAdd(addr, value) + value;
1172#elif defined(__GNUC__) \
1173 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1174 && !defined(NO_ATOMICS)
1175 ret = __sync_add_and_fetch(addr, value);
1176#else
1178 *addr += value;
1179 ret = (*addr);
1181#endif
1182 return ret;
1183}
1184
1185
1187static ptrdiff_t
1188mg_atomic_compare_and_swap(volatile ptrdiff_t *addr,
1189 ptrdiff_t oldval,
1190 ptrdiff_t newval)
1191{
1192 ptrdiff_t ret;
1193
1194#if defined(_WIN64) && !defined(NO_ATOMICS)
1195 ret = InterlockedCompareExchange64(addr, newval, oldval);
1196#elif defined(_WIN32) && !defined(NO_ATOMICS)
1197 ret = InterlockedCompareExchange(addr, newval, oldval);
1198#elif defined(__GNUC__) \
1199 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1200 && !defined(NO_ATOMICS)
1201 ret = __sync_val_compare_and_swap(addr, oldval, newval);
1202#else
1204 ret = *addr;
1205 if ((ret != newval) && (ret == oldval)) {
1206 *addr = newval;
1207 }
1209#endif
1210 return ret;
1211}
1212
1213
1214static void
1215mg_atomic_max(volatile ptrdiff_t *addr, ptrdiff_t value)
1216{
1217 register ptrdiff_t tmp = *addr;
1218
1219#if defined(_WIN64) && !defined(NO_ATOMICS)
1220 while (tmp < value) {
1221 tmp = InterlockedCompareExchange64(addr, value, tmp);
1222 }
1223#elif defined(_WIN32) && !defined(NO_ATOMICS)
1224 while (tmp < value) {
1225 tmp = InterlockedCompareExchange(addr, value, tmp);
1226 }
1227#elif defined(__GNUC__) \
1228 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1229 && !defined(NO_ATOMICS)
1230 while (tmp < value) {
1231 tmp = __sync_val_compare_and_swap(addr, tmp, value);
1232 }
1233#else
1235 if (*addr < value) {
1236 *addr = value;
1237 }
1239#endif
1240}
1241
1242
1243static int64_t
1244mg_atomic_add64(volatile int64_t *addr, int64_t value)
1245{
1246 int64_t ret;
1247
1248#if defined(_WIN64) && !defined(NO_ATOMICS)
1249 ret = InterlockedAdd64(addr, value);
1250#elif defined(_WIN32) && !defined(NO_ATOMICS)
1251 ret = InterlockedExchangeAdd64(addr, value) + value;
1252#elif defined(__GNUC__) \
1253 && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1254 && !defined(NO_ATOMICS)
1255 ret = __sync_add_and_fetch(addr, value);
1256#else
1258 *addr += value;
1259 ret = (*addr);
1261#endif
1262 return ret;
1263}
1264#endif
1265
1266
1267#if defined(GCC_DIAGNOSTIC)
1268/* Show no warning in case system functions are not used. */
1269#pragma GCC diagnostic pop
1270#endif /* defined(GCC_DIAGNOSTIC) */
1271#if defined(__clang__)
1272/* Show no warning in case system functions are not used. */
1273#pragma clang diagnostic pop
1274#endif
1275
1276
1277#if defined(USE_SERVER_STATS)
1278
1279struct mg_memory_stat {
1280 volatile ptrdiff_t totalMemUsed;
1281 volatile ptrdiff_t maxMemUsed;
1282 volatile ptrdiff_t blockCount;
1283};
1284
1285
1286static struct mg_memory_stat *get_memory_stat(struct mg_context *ctx);
1287
1288
1289static void *
1290mg_malloc_ex(size_t size,
1291 struct mg_context *ctx,
1292 const char *file,
1293 unsigned line)
1294{
1295 void *data = malloc(size + 2 * sizeof(uintptr_t));
1296 void *memory = 0;
1297 struct mg_memory_stat *mstat = get_memory_stat(ctx);
1298
1299#if defined(MEMORY_DEBUGGING)
1300 char mallocStr[256];
1301#else
1302 (void)file;
1303 (void)line;
1304#endif
1305
1306 if (data) {
1307 ptrdiff_t mmem = mg_atomic_add(&mstat->totalMemUsed, (ptrdiff_t)size);
1308 mg_atomic_max(&mstat->maxMemUsed, mmem);
1309
1310 mg_atomic_inc(&mstat->blockCount);
1311 ((uintptr_t *)data)[0] = size;
1312 ((uintptr_t *)data)[1] = (uintptr_t)mstat;
1313 memory = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1314 }
1315
1316#if defined(MEMORY_DEBUGGING)
1317 sprintf(mallocStr,
1318 "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n",
1319 memory,
1320 (unsigned long)size,
1321 (unsigned long)mstat->totalMemUsed,
1322 (unsigned long)mstat->blockCount,
1323 file,
1324 line);
1325 DEBUG_TRACE("%s", mallocStr);
1326#endif
1327
1328 return memory;
1329}
1330
1331
1332static void *
1333mg_calloc_ex(size_t count,
1334 size_t size,
1335 struct mg_context *ctx,
1336 const char *file,
1337 unsigned line)
1338{
1339 void *data = mg_malloc_ex(size * count, ctx, file, line);
1340
1341 if (data) {
1342 memset(data, 0, size * count);
1343 }
1344 return data;
1345}
1346
1347
1348static void
1349mg_free_ex(void *memory, const char *file, unsigned line)
1350{
1351#if defined(MEMORY_DEBUGGING)
1352 char mallocStr[256];
1353#else
1354 (void)file;
1355 (void)line;
1356#endif
1357
1358 if (memory) {
1359 void *data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1360 uintptr_t size = ((uintptr_t *)data)[0];
1361 struct mg_memory_stat *mstat =
1362 (struct mg_memory_stat *)(((uintptr_t *)data)[1]);
1363 mg_atomic_add(&mstat->totalMemUsed, -(ptrdiff_t)size);
1364 mg_atomic_dec(&mstat->blockCount);
1365
1366#if defined(MEMORY_DEBUGGING)
1367 sprintf(mallocStr,
1368 "MEM: %p %5lu free %7lu %4lu --- %s:%u\n",
1369 memory,
1370 (unsigned long)size,
1371 (unsigned long)mstat->totalMemUsed,
1372 (unsigned long)mstat->blockCount,
1373 file,
1374 line);
1375 DEBUG_TRACE("%s", mallocStr);
1376#endif
1377 free(data);
1378 }
1379}
1380
1381
1382static void *
1383mg_realloc_ex(void *memory,
1384 size_t newsize,
1385 struct mg_context *ctx,
1386 const char *file,
1387 unsigned line)
1388{
1389 void *data;
1390 void *_realloc;
1391 uintptr_t oldsize;
1392
1393#if defined(MEMORY_DEBUGGING)
1394 char mallocStr[256];
1395#else
1396 (void)file;
1397 (void)line;
1398#endif
1399
1400 if (newsize) {
1401 if (memory) {
1402 /* Reallocate existing block */
1403 struct mg_memory_stat *mstat;
1404 data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1405 oldsize = ((uintptr_t *)data)[0];
1406 mstat = (struct mg_memory_stat *)((uintptr_t *)data)[1];
1407 _realloc = realloc(data, newsize + 2 * sizeof(uintptr_t));
1408 if (_realloc) {
1409 data = _realloc;
1410 mg_atomic_add(&mstat->totalMemUsed, -(ptrdiff_t)oldsize);
1411#if defined(MEMORY_DEBUGGING)
1412 sprintf(mallocStr,
1413 "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n",
1414 memory,
1415 (unsigned long)oldsize,
1416 (unsigned long)mstat->totalMemUsed,
1417 (unsigned long)mstat->blockCount,
1418 file,
1419 line);
1420 DEBUG_TRACE("%s", mallocStr);
1421#endif
1422 mg_atomic_add(&mstat->totalMemUsed, (ptrdiff_t)newsize);
1423
1424#if defined(MEMORY_DEBUGGING)
1425 sprintf(mallocStr,
1426 "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
1427 memory,
1428 (unsigned long)newsize,
1429 (unsigned long)mstat->totalMemUsed,
1430 (unsigned long)mstat->blockCount,
1431 file,
1432 line);
1433 DEBUG_TRACE("%s", mallocStr);
1434#endif
1435 *(uintptr_t *)data = newsize;
1436 data = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1437 } else {
1438#if defined(MEMORY_DEBUGGING)
1439 DEBUG_TRACE("%s", "MEM: realloc failed\n");
1440#endif
1441 return _realloc;
1442 }
1443 } else {
1444 /* Allocate new block */
1445 data = mg_malloc_ex(newsize, ctx, file, line);
1446 }
1447 } else {
1448 /* Free existing block */
1449 data = 0;
1450 mg_free_ex(memory, file, line);
1451 }
1452
1453 return data;
1454}
1455
1456
1457#define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__)
1458#define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__)
1459#define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__)
1460#define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
1461
1462#define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__)
1463#define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__)
1464#define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__)
1465
1466
1467#else /* USE_SERVER_STATS */
1468
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)
1552#if defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \
1553 || defined(OPENSSL_API_3_0)
1554static int mg_openssl_initialized = 0;
1555#endif
1556#if !defined(OPENSSL_API_1_0) && !defined(OPENSSL_API_1_1) \
1557 && !defined(OPENSSL_API_3_0) && !defined(USE_MBEDTLS)
1558#error "Please define OPENSSL_API_1_0 or OPENSSL_API_1_1"
1559#endif
1560#if defined(OPENSSL_API_1_0) && defined(OPENSSL_API_1_1) \
1561 && defined(OPENSSL_API_3_0)
1562#error "Multiple OPENSSL_API versions defined"
1563#endif
1564#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \
1565 || defined(OPENSSL_API_3_0)) \
1566 && defined(USE_MBEDTLS)
1567#error "Multiple SSL libraries defined"
1568#endif
1569#endif
1570
1571
1572static pthread_key_t sTlsKey; /* Thread local storage index */
1573static volatile ptrdiff_t thread_idx_max = 0;
1574
1575#if defined(MG_LEGACY_INTERFACE)
1576#define MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE
1577#endif
1578
1581 unsigned long thread_idx;
1583#if defined(_WIN32)
1584 HANDLE pthread_cond_helper_mutex;
1585 struct mg_workerTLS *next_waiting_thread;
1586#endif
1587 const char *alpn_proto;
1588#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
1589 char txtbuf[4];
1590#endif
1591};
1592
1593
1594#if defined(GCC_DIAGNOSTIC)
1595/* Show no warning in case system functions are not used. */
1596#pragma GCC diagnostic push
1597#pragma GCC diagnostic ignored "-Wunused-function"
1598#endif /* defined(GCC_DIAGNOSTIC) */
1599#if defined(__clang__)
1600/* Show no warning in case system functions are not used. */
1601#pragma clang diagnostic push
1602#pragma clang diagnostic ignored "-Wunused-function"
1603#endif
1604
1605
1606/* Get a unique thread ID as unsigned long, independent from the data type
1607 * of thread IDs defined by the operating system API.
1608 * If two calls to mg_current_thread_id return the same value, they calls
1609 * are done from the same thread. If they return different values, they are
1610 * done from different threads. (Provided this function is used in the same
1611 * process context and threads are not repeatedly created and deleted, but
1612 * CivetWeb does not do that).
1613 * This function must match the signature required for SSL id callbacks:
1614 * CRYPTO_set_id_callback
1615 */
1617static unsigned long
1619{
1620#if defined(_WIN32)
1621 return GetCurrentThreadId();
1622#else
1623
1624#if defined(__clang__)
1625#pragma clang diagnostic push
1626#pragma clang diagnostic ignored "-Wunreachable-code"
1627 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
1628 * or not, so one of the two conditions will be unreachable by construction.
1629 * Unfortunately the C standard does not define a way to check this at
1630 * compile time, since the #if preprocessor conditions can not use the
1631 * sizeof operator as an argument. */
1632#endif
1633
1634 if (sizeof(pthread_t) > sizeof(unsigned long)) {
1635 /* This is the problematic case for CRYPTO_set_id_callback:
1636 * The OS pthread_t can not be cast to unsigned long. */
1637 struct mg_workerTLS *tls =
1638 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
1639 if (tls == NULL) {
1640 /* SSL called from an unknown thread: Create some thread index.
1641 */
1642 tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
1643 tls->is_master = -2; /* -2 means "3rd party thread" */
1644 tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
1645 pthread_setspecific(sTlsKey, tls);
1646 }
1647 return tls->thread_idx;
1648 } else {
1649 /* pthread_t may be any data type, so a simple cast to unsigned long
1650 * can rise a warning/error, depending on the platform.
1651 * Here memcpy is used as an anything-to-anything cast. */
1652 unsigned long ret = 0;
1653 pthread_t t = pthread_self();
1654 memcpy(&ret, &t, sizeof(pthread_t));
1655 return ret;
1656 }
1657
1658#if defined(__clang__)
1659#pragma clang diagnostic pop
1660#endif
1661
1662#endif
1663}
1664
1665
1667static uint64_t
1669{
1670 struct timespec tsnow;
1671 clock_gettime(CLOCK_REALTIME, &tsnow);
1672 return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
1673}
1674
1675
1676#if defined(GCC_DIAGNOSTIC)
1677/* Show no warning in case system functions are not used. */
1678#pragma GCC diagnostic pop
1679#endif /* defined(GCC_DIAGNOSTIC) */
1680#if defined(__clang__)
1681/* Show no warning in case system functions are not used. */
1682#pragma clang diagnostic pop
1683#endif
1684
1685
1686#if defined(NEED_DEBUG_TRACE_FUNC)
1687static void
1688DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
1689{
1690 va_list args;
1691 struct timespec tsnow;
1692
1693 /* Get some operating system independent thread id */
1694 unsigned long thread_id = mg_current_thread_id();
1695
1696 clock_gettime(CLOCK_REALTIME, &tsnow);
1697
1698 flockfile(DEBUG_TRACE_STREAM);
1699 fprintf(DEBUG_TRACE_STREAM,
1700 "*** %lu.%09lu %lu %s:%u: ",
1701 (unsigned long)tsnow.tv_sec,
1702 (unsigned long)tsnow.tv_nsec,
1703 thread_id,
1704 func,
1705 line);
1706 va_start(args, fmt);
1707 vfprintf(DEBUG_TRACE_STREAM, fmt, args);
1708 va_end(args);
1709 putc('\n', DEBUG_TRACE_STREAM);
1710 fflush(DEBUG_TRACE_STREAM);
1711 funlockfile(DEBUG_TRACE_STREAM);
1712}
1713#endif /* NEED_DEBUG_TRACE_FUNC */
1714
1715
1716#define MD5_STATIC static
1717#include "md5.inl"
1718
1719/* Darwin prior to 7.0 and Win32 do not have socklen_t */
1720#if defined(NO_SOCKLEN_T)
1721typedef int socklen_t;
1722#endif /* NO_SOCKLEN_T */
1723
1724#define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
1725
1726#if !defined(MSG_NOSIGNAL)
1727#define MSG_NOSIGNAL (0)
1728#endif
1729
1730
1731/* SSL: mbedTLS vs. no-ssl vs. OpenSSL */
1732#if defined(USE_MBEDTLS)
1733/* mbedTLS */
1734#include "mod_mbedtls.inl"
1735
1736#elif defined(NO_SSL)
1737/* no SSL */
1738typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
1739typedef struct SSL_CTX SSL_CTX;
1740
1741#elif defined(NO_SSL_DL)
1742/* OpenSSL without dynamic loading */
1743#include <openssl/bn.h>
1744#include <openssl/conf.h>
1745#include <openssl/crypto.h>
1746#include <openssl/dh.h>
1747#include <openssl/engine.h>
1748#include <openssl/err.h>
1749#include <openssl/opensslv.h>
1750#include <openssl/pem.h>
1751#include <openssl/ssl.h>
1752#include <openssl/tls1.h>
1753#include <openssl/x509.h>
1754
1755#if defined(WOLFSSL_VERSION)
1756/* Additional defines for WolfSSL, see
1757 * https://github.com/civetweb/civetweb/issues/583 */
1758#include "wolfssl_extras.inl"
1759#endif
1760
1761#if defined(OPENSSL_IS_BORINGSSL)
1762/* From boringssl/src/include/openssl/mem.h:
1763 *
1764 * OpenSSL has, historically, had a complex set of malloc debugging options.
1765 * However, that was written in a time before Valgrind and ASAN. Since we now
1766 * have those tools, the OpenSSL allocation functions are simply macros around
1767 * the standard memory functions.
1768 *
1769 * #define OPENSSL_free free */
1770#define free free
1771// disable for boringssl
1772#define CONF_modules_unload(a) ((void)0)
1773#define ENGINE_cleanup() ((void)0)
1774#endif
1775
1776/* If OpenSSL headers are included, automatically select the API version */
1777#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
1778#if !defined(OPENSSL_API_3_0)
1779#define OPENSSL_API_3_0
1780#endif
1781#define OPENSSL_REMOVE_THREAD_STATE()
1782#else
1783#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1784#if !defined(OPENSSL_API_1_1)
1785#define OPENSSL_API_1_1
1786#endif
1787#define OPENSSL_REMOVE_THREAD_STATE()
1788#else
1789#if !defined(OPENSSL_API_1_0)
1790#define OPENSSL_API_1_0
1791#endif
1792#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL)
1793#endif
1794#endif
1795
1796
1797#else
1798/* SSL loaded dynamically from DLL / shared object */
1799/* Add all prototypes here, to be independent from OpenSSL source
1800 * installation. */
1801#include "openssl_dl.inl"
1802
1803#endif /* Various SSL bindings */
1804
1805
1806#if !defined(NO_CACHING)
1807static const char month_names[][4] = {"Jan",
1808 "Feb",
1809 "Mar",
1810 "Apr",
1811 "May",
1812 "Jun",
1813 "Jul",
1814 "Aug",
1815 "Sep",
1816 "Oct",
1817 "Nov",
1818 "Dec"};
1819#endif /* !NO_CACHING */
1820
1821
1822/* Unified socket address. For IPv6 support, add IPv6 address structure in
1823 * the union u. */
1824union usa {
1825 struct sockaddr sa;
1826 struct sockaddr_in sin;
1827#if defined(USE_IPV6)
1828 struct sockaddr_in6 sin6;
1829#endif
1830#if defined(USE_X_DOM_SOCKET)
1831 struct sockaddr_un sun;
1832#endif
1833};
1834
1835#if defined(USE_X_DOM_SOCKET)
1836static unsigned short
1837USA_IN_PORT_UNSAFE(union usa *s)
1838{
1839 if (s->sa.sa_family == AF_INET)
1840 return s->sin.sin_port;
1841#if defined(USE_IPV6)
1842 if (s->sa.sa_family == AF_INET6)
1843 return s->sin6.sin6_port;
1844#endif
1845 return 0;
1846}
1847#endif
1848#if defined(USE_IPV6)
1849#define USA_IN_PORT_UNSAFE(s) \
1850 (((s)->sa.sa_family == AF_INET6) ? (s)->sin6.sin6_port : (s)->sin.sin_port)
1851#else
1852#define USA_IN_PORT_UNSAFE(s) ((s)->sin.sin_port)
1853#endif
1854
1855/* Describes a string (chunk of memory). */
1856struct vec {
1857 const char *ptr;
1858 size_t len;
1859};
1860
1862 /* File properties filled by mg_stat: */
1863 uint64_t size;
1865 int is_directory; /* Set to 1 if mg_stat is called for a directory */
1866 int is_gzipped; /* Set to 1 if the content is gzipped, in which
1867 * case we need a "Content-Eencoding: gzip" header */
1868 int location; /* 0 = nowhere, 1 = on disk, 2 = in memory */
1869};
1870
1871
1873 /* File properties filled by mg_fopen: */
1874 FILE *fp;
1875};
1876
1877struct mg_file {
1880};
1881
1882
1883#define STRUCT_FILE_INITIALIZER \
1884 { \
1885 {(uint64_t)0, (time_t)0, 0, 0, 0}, \
1886 { \
1887 (FILE *)NULL \
1888 } \
1889 }
1890
1891
1892/* Describes listening socket, or socket which was accept()-ed by the master
1893 * thread and queued for future handling by the worker thread. */
1894struct socket {
1895 SOCKET sock; /* Listening socket */
1896 union usa lsa; /* Local socket address */
1897 union usa rsa; /* Remote socket address */
1898 unsigned char is_ssl; /* Is port SSL-ed */
1899 unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
1900 * port */
1901 unsigned char in_use; /* 0: invalid, 1: valid, 2: free */
1902};
1903
1904
1905/* Enum const for all options must be in sync with
1906 * static struct mg_option config_options[]
1907 * This is tested in the unit test (test/private.c)
1908 * "Private Config Options"
1909 */
1910enum {
1911 /* Once for each server */
1915 CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
1916 * socket option typedef TCP_NODELAY. */
1921#if defined(__linux__)
1922 ALLOW_SENDFILE_CALL,
1923#endif
1924#if defined(_WIN32)
1925 CASE_SENSITIVE_FILES,
1926#endif
1931#if defined(USE_WEBSOCKET)
1932 WEBSOCKET_TIMEOUT,
1933 ENABLE_WEBSOCKET_PING_PONG,
1934#endif
1937#if defined(USE_LUA)
1938 LUA_BACKGROUND_SCRIPT,
1939 LUA_BACKGROUND_SCRIPT_PARAMS,
1940#endif
1941#if defined(USE_HTTP2)
1942 ENABLE_HTTP2,
1943#endif
1944
1945 /* Once for each domain */
1947
1950
1955#if defined(USE_TIMERS)
1956 CGI_TIMEOUT,
1957#endif
1958
1963#if defined(USE_TIMERS)
1964 CGI2_TIMEOUT,
1965#endif
1966
1967#if defined(USE_4_CGI)
1968 CGI3_EXTENSIONS,
1969 CGI3_ENVIRONMENT,
1970 CGI3_INTERPRETER,
1971 CGI3_INTERPRETER_ARGS,
1972#if defined(USE_TIMERS)
1973 CGI3_TIMEOUT,
1974#endif
1975
1976 CGI4_EXTENSIONS,
1977 CGI4_ENVIRONMENT,
1978 CGI4_INTERPRETER,
1979 CGI4_INTERPRETER_ARGS,
1980#if defined(USE_TIMERS)
1981 CGI4_TIMEOUT,
1982#endif
1983#endif
1984
1985 PUT_DELETE_PASSWORDS_FILE, /* must follow CGI_* */
2008
2009#if defined(USE_LUA)
2010 LUA_PRELOAD_FILE,
2011 LUA_SCRIPT_EXTENSIONS,
2012 LUA_SERVER_PAGE_EXTENSIONS,
2013#if defined(MG_EXPERIMENTAL_INTERFACES)
2014 LUA_DEBUG_PARAMS,
2015#endif
2016#endif
2017#if defined(USE_DUKTAPE)
2018 DUKTAPE_SCRIPT_EXTENSIONS,
2019#endif
2020
2021#if defined(USE_WEBSOCKET)
2022 WEBSOCKET_ROOT,
2023#endif
2024#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2025 LUA_WEBSOCKET_EXTENSIONS,
2026#endif
2027
2032#if !defined(NO_CACHING)
2035#endif
2036#if !defined(NO_SSL)
2038#endif
2041
2044
2045
2046/* Config option name, config types, default value.
2047 * Must be in the same order as the enum const above.
2048 */
2049static const struct mg_option config_options[] = {
2050
2051 /* Once for each server */
2052 {"listening_ports", MG_CONFIG_TYPE_STRING_LIST, "8080"},
2053 {"num_threads", MG_CONFIG_TYPE_NUMBER, "50"},
2054 {"run_as_user", MG_CONFIG_TYPE_STRING, NULL},
2055 {"tcp_nodelay", MG_CONFIG_TYPE_NUMBER, "0"},
2056 {"max_request_size", MG_CONFIG_TYPE_NUMBER, "16384"},
2057 {"linger_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2058 {"connection_queue", MG_CONFIG_TYPE_NUMBER, "20"},
2059 {"listen_backlog", MG_CONFIG_TYPE_NUMBER, "200"},
2060#if defined(__linux__)
2061 {"allow_sendfile_call", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2062#endif
2063#if defined(_WIN32)
2064 {"case_sensitive", MG_CONFIG_TYPE_BOOLEAN, "no"},
2065#endif
2066 {"throttle", MG_CONFIG_TYPE_STRING_LIST, NULL},
2067 {"enable_keep_alive", MG_CONFIG_TYPE_BOOLEAN, "no"},
2068 {"request_timeout_ms", MG_CONFIG_TYPE_NUMBER, "30000"},
2069 {"keep_alive_timeout_ms", MG_CONFIG_TYPE_NUMBER, "500"},
2070#if defined(USE_WEBSOCKET)
2071 {"websocket_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2072 {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"},
2073#endif
2074 {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2075 {"decode_query_string", MG_CONFIG_TYPE_BOOLEAN, "no"},
2076#if defined(USE_LUA)
2077 {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL},
2078 {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL},
2079#endif
2080#if defined(USE_HTTP2)
2081 {"enable_http2", MG_CONFIG_TYPE_BOOLEAN, "no"},
2082#endif
2083
2084 /* Once for each domain */
2085 {"document_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
2086
2087 {"access_log_file", MG_CONFIG_TYPE_FILE, NULL},
2088 {"error_log_file", MG_CONFIG_TYPE_FILE, NULL},
2089
2090 {"cgi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
2091 {"cgi_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
2092 {"cgi_interpreter", MG_CONFIG_TYPE_FILE, NULL},
2093 {"cgi_interpreter_args", MG_CONFIG_TYPE_STRING, NULL},
2094#if defined(USE_TIMERS)
2095 {"cgi_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2096#endif
2097
2098 {"cgi2_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
2099 {"cgi2_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
2100 {"cgi2_interpreter", MG_CONFIG_TYPE_FILE, NULL},
2101 {"cgi2_interpreter_args", MG_CONFIG_TYPE_STRING, NULL},
2102#if defined(USE_TIMERS)
2103 {"cgi2_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2104#endif
2105
2106#if defined(USE_4_CGI)
2107 {"cgi3_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
2108 {"cgi3_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
2109 {"cgi3_interpreter", MG_CONFIG_TYPE_FILE, NULL},
2110 {"cgi3_interpreter_args", MG_CONFIG_TYPE_STRING, NULL},
2111#if defined(USE_TIMERS)
2112 {"cgi3_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2113#endif
2114
2115 {"cgi2_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
2116 {"cgi4_environment", MG_CONFIG_TYPE_STRING_LIST, NULL},
2117 {"cgi4_interpreter", MG_CONFIG_TYPE_FILE, NULL},
2118 {"cgi4_interpreter_args", MG_CONFIG_TYPE_STRING, NULL},
2119#if defined(USE_TIMERS)
2120 {"cgi4_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL},
2121#endif
2122#endif
2123
2124 {"put_delete_auth_file", MG_CONFIG_TYPE_FILE, NULL},
2125 {"protect_uri", MG_CONFIG_TYPE_STRING_LIST, NULL},
2126 {"authentication_domain", MG_CONFIG_TYPE_STRING, "mydomain.com"},
2127 {"enable_auth_domain_check", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2128 {"ssi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
2129 {"enable_directory_listing", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2130 {"global_auth_file", MG_CONFIG_TYPE_FILE, NULL},
2131 {"index_files",
2133#if defined(USE_LUA)
2134 "index.xhtml,index.html,index.htm,"
2135 "index.lp,index.lsp,index.lua,index.cgi,"
2136 "index.shtml,index.php"},
2137#else
2138 "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
2139#endif
2140 {"access_control_list", MG_CONFIG_TYPE_STRING_LIST, NULL},
2141 {"extra_mime_types", MG_CONFIG_TYPE_STRING_LIST, NULL},
2142 {"ssl_certificate", MG_CONFIG_TYPE_FILE, NULL},
2143 {"ssl_certificate_chain", MG_CONFIG_TYPE_FILE, NULL},
2144 {"url_rewrite_patterns", MG_CONFIG_TYPE_STRING_LIST, NULL},
2145 {"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL},
2146
2147 {"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"},
2148 {"ssl_cache_timeout", MG_CONFIG_TYPE_NUMBER, "-1"},
2149
2150 {"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL},
2151 {"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL},
2152 {"ssl_verify_depth", MG_CONFIG_TYPE_NUMBER, "9"},
2153 {"ssl_default_verify_paths", MG_CONFIG_TYPE_BOOLEAN, "yes"},
2154 {"ssl_cipher_list", MG_CONFIG_TYPE_STRING, NULL},
2155
2156 /* HTTP2 requires ALPN, and anyway TLS1.2 should be considered
2157 * as a minimum in 2020 */
2158 {"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "4"},
2159
2160 {"ssl_short_trust", MG_CONFIG_TYPE_BOOLEAN, "no"},
2161
2162#if defined(USE_LUA)
2163 {"lua_preload_file", MG_CONFIG_TYPE_FILE, NULL},
2164 {"lua_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2165 {"lua_server_page_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
2166#if defined(MG_EXPERIMENTAL_INTERFACES)
2167 {"lua_debug", MG_CONFIG_TYPE_STRING, NULL},
2168#endif
2169#endif
2170#if defined(USE_DUKTAPE)
2171 /* The support for duktape is still in alpha version state.
2172 * The name of this config option might change. */
2173 {"duktape_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
2174#endif
2175
2176#if defined(USE_WEBSOCKET)
2177 {"websocket_root", MG_CONFIG_TYPE_DIRECTORY, NULL},
2178#endif
2179#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2180 {"lua_websocket_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2181#endif
2182 {"access_control_allow_origin", MG_CONFIG_TYPE_STRING, "*"},
2183 {"access_control_allow_methods", MG_CONFIG_TYPE_STRING, "*"},
2184 {"access_control_allow_headers", MG_CONFIG_TYPE_STRING, "*"},
2185 {"error_pages", MG_CONFIG_TYPE_DIRECTORY, NULL},
2186#if !defined(NO_CACHING)
2187 {"static_file_max_age", MG_CONFIG_TYPE_NUMBER, "3600"},
2188 {"static_file_cache_control", MG_CONFIG_TYPE_STRING, NULL},
2189#endif
2190#if !defined(NO_SSL)
2191 {"strict_transport_security_max_age", MG_CONFIG_TYPE_NUMBER, NULL},
2192#endif
2193 {"additional_header", MG_CONFIG_TYPE_STRING_MULTILINE, NULL},
2194 {"allow_index_script_resource", MG_CONFIG_TYPE_BOOLEAN, "no"},
2195
2196 {NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}};
2197
2198
2199/* Check if the config_options and the corresponding enum have compatible
2200 * sizes. */
2201mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
2202 == (NUM_OPTIONS + 1),
2203 "config_options and enum not sync");
2204
2205
2207
2208
2210 /* Name/Pattern of the URI. */
2211 char *uri;
2212 size_t uri_len;
2213
2214 /* handler type */
2216
2217 /* Handler for http/https or authorization requests. */
2219 unsigned int refcount;
2221
2222 /* Handler for ws/wss (websocket) requests. */
2227
2228 /* accepted subprotocols for ws/wss requests. */
2230
2231 /* Handler for authorization requests */
2233
2234 /* User supplied argument for the handler function. */
2235 void *cbdata;
2236
2237 /* next handler in a linked list */
2239};
2240
2241
2242enum {
2248
2249
2251 SSL_CTX *ssl_ctx; /* SSL context */
2252 char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
2253 struct mg_handler_info *handlers; /* linked list of uri handlers */
2255
2256 /* Server nonce */
2257 uint64_t auth_nonce_mask; /* Mask for all nonce values */
2258 unsigned long nonce_count; /* Used nonces, used for authentication */
2259
2260#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2261 /* linked list of shared lua websockets */
2262 struct mg_shared_lua_websocket_list *shared_lua_websockets;
2263#endif
2264
2265 /* Linked list of domains */
2267};
2268
2269
2270/* Stop flag can be "volatile" or require a lock.
2271 * MSDN uses volatile for "Interlocked" operations, but also explicitly
2272 * states a read operation for int is always atomic. */
2273#if defined(STOP_FLAG_NEEDS_LOCK)
2274
2275typedef ptrdiff_t volatile stop_flag_t;
2276
2277static int
2279{
2280 stop_flag_t sf = mg_atomic_add(f, 0);
2281 return (sf == 0);
2282}
2283
2284static int
2286{
2287 stop_flag_t sf = mg_atomic_add(f, 0);
2288 return (sf == 2);
2289}
2290
2291static void
2293{
2294 stop_flag_t sf;
2295 do {
2296 sf = mg_atomic_compare_and_swap(f, *f, v);
2297 } while (sf != v);
2298}
2299
2300#else /* STOP_FLAG_NEEDS_LOCK */
2301
2302typedef int volatile stop_flag_t;
2303#define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0)
2304#define STOP_FLAG_IS_TWO(f) ((*(f)) == 2)
2305#define STOP_FLAG_ASSIGN(f, v) ((*(f)) = (v))
2306
2307#endif /* STOP_FLAG_NEEDS_LOCK */
2308
2309
2311
2312 /* Part 1 - Physical context:
2313 * This holds threads, ports, timeouts, ...
2314 * set for the entire server, independent from the
2315 * addressed hostname.
2316 */
2317
2318 /* Connection related */
2319 int context_type; /* See CONTEXT_* above */
2320
2324
2325 struct mg_connection *worker_connections; /* The connection struct, pre-
2326 * allocated for each worker */
2327
2328#if defined(USE_SERVER_STATS)
2329 volatile ptrdiff_t active_connections;
2330 volatile ptrdiff_t max_active_connections;
2331 volatile ptrdiff_t total_connections;
2332 volatile ptrdiff_t total_requests;
2333 volatile int64_t total_data_read;
2334 volatile int64_t total_data_written;
2335#endif
2336
2337 /* Thread related */
2338 stop_flag_t stop_flag; /* Should we stop event loop */
2339 pthread_mutex_t thread_mutex; /* Protects client_socks or queue */
2340
2341 pthread_t masterthreadid; /* The master thread ID */
2342 unsigned int
2343 cfg_worker_threads; /* The number of configured worker threads. */
2344 pthread_t *worker_threadids; /* The worker thread IDs */
2345 unsigned long starter_thread_idx; /* thread index which called mg_start */
2346
2347 /* Connection to thread dispatching */
2348#if defined(ALTERNATIVE_QUEUE)
2349 struct socket *client_socks;
2350 void **client_wait_events;
2351#else
2352 struct socket *squeue; /* Socket queue (sq) : accepted sockets waiting for a
2353 worker thread */
2354 volatile int sq_head; /* Head of the socket queue */
2355 volatile int sq_tail; /* Tail of the socket queue */
2356 pthread_cond_t sq_full; /* Signaled when socket is produced */
2357 pthread_cond_t sq_empty; /* Signaled when socket is consumed */
2358 volatile int sq_blocked; /* Status information: sq is full */
2359 int sq_size; /* No of elements in socket queue */
2360#if defined(USE_SERVER_STATS)
2361 int sq_max_fill;
2362#endif /* USE_SERVER_STATS */
2363#endif /* ALTERNATIVE_QUEUE */
2364
2365 /* Memory related */
2366 unsigned int max_request_size; /* The max request size */
2367
2368#if defined(USE_SERVER_STATS)
2369 struct mg_memory_stat ctx_memory;
2370#endif
2371
2372 /* Operating system related */
2373 char *systemName; /* What operating system is running */
2374 time_t start_time; /* Server start time, used for authentication
2375 * and for diagnstics. */
2376
2377#if defined(USE_TIMERS)
2378 struct ttimers *timers;
2379#endif
2380
2381 /* Lua specific: Background operations and shared websockets */
2382#if defined(USE_LUA)
2383 void *lua_background_state; /* lua_State (here as void *) */
2384 pthread_mutex_t lua_bg_mutex; /* Protect background state */
2385 int lua_bg_log_available; /* Use Lua background state for access log */
2386#endif
2387
2388 /* Server nonce */
2389 pthread_mutex_t nonce_mutex; /* Protects ssl_ctx, handlers,
2390 * ssl_cert_last_mtime, nonce_count, and
2391 * next (linked list) */
2392
2393 /* Server callbacks */
2394 struct mg_callbacks callbacks; /* User-defined callback function */
2395 void *user_data; /* User-defined data */
2396
2397 /* Part 2 - Logical domain:
2398 * This holds hostname, TLS certificate, document root, ...
2399 * set for a domain hosted at the server.
2400 * There may be multiple domains hosted at one physical server.
2401 * The default domain "dd" is the first element of a list of
2402 * domains.
2403 */
2404 struct mg_domain_context dd; /* default domain */
2405};
2406
2407
2408#if defined(USE_SERVER_STATS)
2409static struct mg_memory_stat mg_common_memory = {0, 0, 0};
2410
2411static struct mg_memory_stat *
2412get_memory_stat(struct mg_context *ctx)
2413{
2414 if (ctx) {
2415 return &(ctx->ctx_memory);
2416 }
2417 return &mg_common_memory;
2418}
2419#endif
2420
2421enum {
2426
2427enum {
2432
2433
2434#if defined(USE_HTTP2)
2435#if !defined(HTTP2_DYN_TABLE_SIZE)
2436#define HTTP2_DYN_TABLE_SIZE (256)
2437#endif
2438
2439struct mg_http2_connection {
2440 uint32_t stream_id;
2441 uint32_t dyn_table_size;
2442 struct mg_header dyn_table[HTTP2_DYN_TABLE_SIZE];
2443};
2444#endif
2445
2446
2448 int connection_type; /* see CONNECTION_TYPE_* above */
2449 int protocol_type; /* see PROTOCOL_TYPE_*: 0=http/1.x, 1=ws, 2=http/2 */
2450 int request_state; /* 0: nothing sent, 1: header partially sent, 2: header
2451 fully sent */
2452#if defined(USE_HTTP2)
2453 struct mg_http2_connection http2;
2454#endif
2455
2458
2461
2462#if defined(USE_SERVER_STATS)
2463 int conn_state; /* 0 = undef, numerical value may change in different
2464 * versions. For the current definition, see
2465 * mg_get_connection_info_impl */
2466#endif
2467
2468 SSL *ssl; /* SSL descriptor */
2469 struct socket client; /* Connected client */
2470 time_t conn_birth_time; /* Time (wall clock) when connection was
2471 * established */
2472#if defined(USE_SERVER_STATS)
2473 time_t conn_close_time; /* Time (wall clock) when connection was
2474 * closed (or 0 if still open) */
2475 double processing_time; /* Procesing time for one request. */
2476#endif
2477 struct timespec req_time; /* Time (since system start) when the request
2478 * was received */
2479 int64_t num_bytes_sent; /* Total bytes sent to client */
2480 int64_t content_len; /* How many bytes of content can be read
2481 * !is_chunked: Content-Length header value
2482 * or -1 (until connection closed,
2483 * not allowed for a request)
2484 * is_chunked: >= 0, appended gradually
2485 */
2486 int64_t consumed_content; /* How many bytes of content have been read */
2487 int is_chunked; /* Transfer-Encoding is chunked:
2488 * 0 = not chunked,
2489 * 1 = chunked, not yet, or some data read,
2490 * 2 = chunked, has error,
2491 * 3 = chunked, all data read except trailer,
2492 * 4 = chunked, all data read
2493 */
2494 char *buf; /* Buffer for received data */
2495 char *path_info; /* PATH_INFO part of the URL */
2496
2497 int must_close; /* 1 if connection must be closed */
2498 int accept_gzip; /* 1 if gzip encoding is accepted */
2499 int in_error_handler; /* 1 if in handler for user defined error
2500 * pages */
2501#if defined(USE_WEBSOCKET)
2502 int in_websocket_handling; /* 1 if in read_websocket */
2503#endif
2504#if defined(USE_ZLIB) && defined(USE_WEBSOCKET) \
2505 && defined(MG_EXPERIMENTAL_INTERFACES)
2506 /* Parameters for websocket data compression according to rfc7692 */
2507 int websocket_deflate_server_max_windows_bits;
2508 int websocket_deflate_client_max_windows_bits;
2509 int websocket_deflate_server_no_context_takeover;
2510 int websocket_deflate_client_no_context_takeover;
2511 int websocket_deflate_initialized;
2512 int websocket_deflate_flush;
2513 z_stream websocket_deflate_state;
2514 z_stream websocket_inflate_state;
2515#endif
2516 int handled_requests; /* Number of requests handled by this connection
2517 */
2518 int buf_size; /* Buffer size */
2519 int request_len; /* Size of the request + headers in a buffer */
2520 int data_len; /* Total size of data in a buffer */
2521 int status_code; /* HTTP reply status code, e.g. 200 */
2522 int throttle; /* Throttling, bytes/sec. <= 0 means no
2523 * throttle */
2524
2525 time_t last_throttle_time; /* Last time throttled data was sent */
2526 int last_throttle_bytes; /* Bytes sent this second */
2527 pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure
2528 * atomic transmissions for websockets */
2529#if defined(USE_LUA) && defined(USE_WEBSOCKET)
2530 void *lua_websocket_state; /* Lua_State for a websocket connection */
2531#endif
2532
2533 void *tls_user_ptr; /* User defined pointer in thread local storage,
2534 * for quick access */
2535};
2536
2537
2538/* Directory entry */
2539struct de {
2543};
2544
2545
2546#define mg_cry_internal(conn, fmt, ...) \
2547 mg_cry_internal_wrap(conn, NULL, __func__, __LINE__, fmt, __VA_ARGS__)
2548
2549#define mg_cry_ctx_internal(ctx, fmt, ...) \
2550 mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__)
2551
2552static void mg_cry_internal_wrap(const struct mg_connection *conn,
2553 struct mg_context *ctx,
2554 const char *func,
2555 unsigned line,
2556 const char *fmt,
2557 ...) PRINTF_ARGS(5, 6);
2558
2559
2560#if !defined(NO_THREAD_NAME)
2561#if defined(_WIN32) && defined(_MSC_VER)
2562/* Set the thread name for debugging purposes in Visual Studio
2563 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
2564 */
2565#pragma pack(push, 8)
2566typedef struct tagTHREADNAME_INFO {
2567 DWORD dwType; /* Must be 0x1000. */
2568 LPCSTR szName; /* Pointer to name (in user addr space). */
2569 DWORD dwThreadID; /* Thread ID (-1=caller thread). */
2570 DWORD dwFlags; /* Reserved for future use, must be zero. */
2571} THREADNAME_INFO;
2572#pragma pack(pop)
2573
2574#elif defined(__linux__)
2575
2576#include <sys/prctl.h>
2577#include <sys/sendfile.h>
2578#if defined(ALTERNATIVE_QUEUE)
2579#include <sys/eventfd.h>
2580#endif /* ALTERNATIVE_QUEUE */
2581
2582
2583#if defined(ALTERNATIVE_QUEUE)
2584
2585static void *
2586event_create(void)
2587{
2588 int evhdl = eventfd(0, EFD_CLOEXEC);
2589 int *ret;
2590
2591 if (evhdl == -1) {
2592 /* Linux uses -1 on error, Windows NULL. */
2593 /* However, Linux does not return 0 on success either. */
2594 return 0;
2595 }
2596
2597 ret = (int *)mg_malloc(sizeof(int));
2598 if (ret) {
2599 *ret = evhdl;
2600 } else {
2601 (void)close(evhdl);
2602 }
2603
2604 return (void *)ret;
2605}
2606
2607
2608static int
2609event_wait(void *eventhdl)
2610{
2611 uint64_t u;
2612 int evhdl, s;
2613
2614 if (!eventhdl) {
2615 /* error */
2616 return 0;
2617 }
2618 evhdl = *(int *)eventhdl;
2619
2620 s = (int)read(evhdl, &u, sizeof(u));
2621 if (s != sizeof(u)) {
2622 /* error */
2623 return 0;
2624 }
2625 (void)u; /* the value is not required */
2626 return 1;
2627}
2628
2629
2630static int
2631event_signal(void *eventhdl)
2632{
2633 uint64_t u = 1;
2634 int evhdl, s;
2635
2636 if (!eventhdl) {
2637 /* error */
2638 return 0;
2639 }
2640 evhdl = *(int *)eventhdl;
2641
2642 s = (int)write(evhdl, &u, sizeof(u));
2643 if (s != sizeof(u)) {
2644 /* error */
2645 return 0;
2646 }
2647 return 1;
2648}
2649
2650
2651static void
2652event_destroy(void *eventhdl)
2653{
2654 int evhdl;
2655
2656 if (!eventhdl) {
2657 /* error */
2658 return;
2659 }
2660 evhdl = *(int *)eventhdl;
2661
2662 close(evhdl);
2663 mg_free(eventhdl);
2664}
2665
2666
2667#endif
2668
2669#endif
2670
2671
2672#if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE)
2673
2674struct posix_event {
2675 pthread_mutex_t mutex;
2676 pthread_cond_t cond;
2677 int signaled;
2678};
2679
2680
2681static void *
2682event_create(void)
2683{
2684 struct posix_event *ret = mg_malloc(sizeof(struct posix_event));
2685 if (ret == 0) {
2686 /* out of memory */
2687 return 0;
2688 }
2689 if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
2690 /* pthread mutex not available */
2691 mg_free(ret);
2692 return 0;
2693 }
2694 if (0 != pthread_cond_init(&(ret->cond), NULL)) {
2695 /* pthread cond not available */
2696 pthread_mutex_destroy(&(ret->mutex));
2697 mg_free(ret);
2698 return 0;
2699 }
2700 ret->signaled = 0;
2701 return (void *)ret;
2702}
2703
2704
2705static int
2706event_wait(void *eventhdl)
2707{
2708 struct posix_event *ev = (struct posix_event *)eventhdl;
2709 pthread_mutex_lock(&(ev->mutex));
2710 while (!ev->signaled) {
2711 pthread_cond_wait(&(ev->cond), &(ev->mutex));
2712 }
2713 ev->signaled = 0;
2714 pthread_mutex_unlock(&(ev->mutex));
2715 return 1;
2716}
2717
2718
2719static int
2720event_signal(void *eventhdl)
2721{
2722 struct posix_event *ev = (struct posix_event *)eventhdl;
2723 pthread_mutex_lock(&(ev->mutex));
2724 pthread_cond_signal(&(ev->cond));
2725 ev->signaled = 1;
2726 pthread_mutex_unlock(&(ev->mutex));
2727 return 1;
2728}
2729
2730
2731static void
2732event_destroy(void *eventhdl)
2733{
2734 struct posix_event *ev = (struct posix_event *)eventhdl;
2735 pthread_cond_destroy(&(ev->cond));
2736 pthread_mutex_destroy(&(ev->mutex));
2737 mg_free(ev);
2738}
2739#endif
2740
2741
2742static void
2744{
2745 char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
2746
2748 NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
2749
2750#if defined(_WIN32)
2751#if defined(_MSC_VER)
2752 /* Windows and Visual Studio Compiler */
2753 __try {
2754 THREADNAME_INFO info;
2755 info.dwType = 0x1000;
2756 info.szName = threadName;
2757 info.dwThreadID = ~0U;
2758 info.dwFlags = 0;
2759
2760 RaiseException(0x406D1388,
2761 0,
2762 sizeof(info) / sizeof(ULONG_PTR),
2763 (ULONG_PTR *)&info);
2764 } __except (EXCEPTION_EXECUTE_HANDLER) {
2765 }
2766#elif defined(__MINGW32__)
2767 /* No option known to set thread name for MinGW known */
2768#endif
2769#elif defined(_GNU_SOURCE) && defined(__GLIBC__) \
2770 && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
2771 /* pthread_setname_np first appeared in glibc in version 2.12 */
2772#if defined(__MACH__)
2773 /* OS X only current thread name can be changed */
2774 (void)pthread_setname_np(threadName);
2775#else
2776 (void)pthread_setname_np(pthread_self(), threadName);
2777#endif
2778#elif defined(__linux__)
2779 /* On Linux we can use the prctl function.
2780 * When building for Linux Standard Base (LSB) use
2781 * NO_THREAD_NAME. However, thread names are a big
2782 * help for debugging, so the stadard is to set them.
2783 */
2784 (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
2785#endif
2786}
2787#else /* !defined(NO_THREAD_NAME) */
2788void
2789mg_set_thread_name(const char *threadName)
2790{
2791}
2792#endif
2793
2794
2795const struct mg_option *
2797{
2798 return config_options;
2799}
2800
2801
2802/* Do not open file (unused) */
2803#define MG_FOPEN_MODE_NONE (0)
2804
2805/* Open file for read only access */
2806#define MG_FOPEN_MODE_READ (1)
2807
2808/* Open file for writing, create and overwrite */
2809#define MG_FOPEN_MODE_WRITE (2)
2810
2811/* Open file for writing, create and append */
2812#define MG_FOPEN_MODE_APPEND (4)
2813
2814
2815static int
2816is_file_opened(const struct mg_file_access *fileacc)
2817{
2818 if (!fileacc) {
2819 return 0;
2820 }
2821
2822 return (fileacc->fp != NULL);
2823}
2824
2825
2826#if !defined(NO_FILESYSTEMS)
2827static int mg_stat(const struct mg_connection *conn,
2828 const char *path,
2829 struct mg_file_stat *filep);
2830
2831
2832/* Reject files with special characters (for Windows) */
2833static int
2834mg_path_suspicious(const struct mg_connection *conn, const char *path)
2835{
2836 const uint8_t *c = (const uint8_t *)path;
2837 (void)conn; /* not used */
2838
2839 if ((c == NULL) || (c[0] == 0)) {
2840 /* Null pointer or empty path --> suspicious */
2841 return 1;
2842 }
2843
2844#if defined(_WIN32)
2845 while (*c) {
2846 if (*c < 32) {
2847 /* Control character */
2848 return 1;
2849 }
2850 if ((*c == '>') || (*c == '<') || (*c == '|')) {
2851 /* stdin/stdout redirection character */
2852 return 1;
2853 }
2854 if ((*c == '*') || (*c == '?')) {
2855 /* Wildcard character */
2856 return 1;
2857 }
2858 if (*c == '"') {
2859 /* Windows quotation */
2860 return 1;
2861 }
2862 c++;
2863 }
2864#endif
2865
2866 /* Nothing suspicious found */
2867 return 0;
2868}
2869
2870
2871/* mg_fopen will open a file either in memory or on the disk.
2872 * The input parameter path is a string in UTF-8 encoding.
2873 * The input parameter mode is MG_FOPEN_MODE_*
2874 * On success, fp will be set in the output struct mg_file.
2875 * All status members will also be set.
2876 * The function returns 1 on success, 0 on error. */
2877static int
2878mg_fopen(const struct mg_connection *conn,
2879 const char *path,
2880 int mode,
2881 struct mg_file *filep)
2882{
2883 int found;
2884
2885 if (!filep) {
2886 return 0;
2887 }
2888 filep->access.fp = NULL;
2889
2890 if (mg_path_suspicious(conn, path)) {
2891 return 0;
2892 }
2893
2894 /* filep is initialized in mg_stat: all fields with memset to,
2895 * some fields like size and modification date with values */
2896 found = mg_stat(conn, path, &(filep->stat));
2897
2898 if ((mode == MG_FOPEN_MODE_READ) && (!found)) {
2899 /* file does not exist and will not be created */
2900 return 0;
2901 }
2902
2903#if defined(_WIN32)
2904 {
2905 wchar_t wbuf[UTF16_PATH_MAX];
2906 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
2907 switch (mode) {
2908 case MG_FOPEN_MODE_READ:
2909 filep->access.fp = _wfopen(wbuf, L"rb");
2910 break;
2912 filep->access.fp = _wfopen(wbuf, L"wb");
2913 break;
2915 filep->access.fp = _wfopen(wbuf, L"ab");
2916 break;
2917 }
2918 }
2919#else
2920 /* Linux et al already use unicode. No need to convert. */
2921 switch (mode) {
2922 case MG_FOPEN_MODE_READ:
2923 filep->access.fp = fopen(path, "r");
2924 break;
2926 filep->access.fp = fopen(path, "w");
2927 break;
2929 filep->access.fp = fopen(path, "a");
2930 break;
2931 }
2932
2933#endif
2934 if (!found) {
2935 /* File did not exist before fopen was called.
2936 * Maybe it has been created now. Get stat info
2937 * like creation time now. */
2938 found = mg_stat(conn, path, &(filep->stat));
2939 (void)found;
2940 }
2941
2942 /* return OK if file is opened */
2943 return (filep->access.fp != NULL);
2944}
2945
2946
2947/* return 0 on success, just like fclose */
2948static int
2950{
2951 int ret = -1;
2952 if (fileacc != NULL) {
2953 if (fileacc->fp != NULL) {
2954 ret = fclose(fileacc->fp);
2955 }
2956 /* reset all members of fileacc */
2957 memset(fileacc, 0, sizeof(*fileacc));
2958 }
2959 return ret;
2960}
2961#endif /* NO_FILESYSTEMS */
2962
2963
2964static void
2965mg_strlcpy(char *dst, const char *src, size_t n)
2966{
2967 for (; *src != '\0' && n > 1; n--) {
2968 *dst++ = *src++;
2969 }
2970 *dst = '\0';
2971}
2972
2973
2974static int
2975lowercase(const char *s)
2976{
2977 return tolower((unsigned char)*s);
2978}
2979
2980
2981int
2982mg_strncasecmp(const char *s1, const char *s2, size_t len)
2983{
2984 int diff = 0;
2985
2986 if (len > 0) {
2987 do {
2988 diff = lowercase(s1++) - lowercase(s2++);
2989 } while (diff == 0 && s1[-1] != '\0' && --len > 0);
2990 }
2991
2992 return diff;
2993}
2994
2995
2996int
2997mg_strcasecmp(const char *s1, const char *s2)
2998{
2999 int diff;
3000
3001 do {
3002 diff = lowercase(s1++) - lowercase(s2++);
3003 } while (diff == 0 && s1[-1] != '\0');
3004
3005 return diff;
3006}
3007
3008
3009static char *
3010mg_strndup_ctx(const char *ptr, size_t len, struct mg_context *ctx)
3011{
3012 char *p;
3013 (void)ctx; /* Avoid Visual Studio warning if USE_SERVER_STATS is not
3014 * defined */
3015
3016 if ((p = (char *)mg_malloc_ctx(len + 1, ctx)) != NULL) {
3017 mg_strlcpy(p, ptr, len + 1);
3018 }
3019
3020 return p;
3021}
3022
3023
3024static char *
3025mg_strdup_ctx(const char *str, struct mg_context *ctx)
3026{
3027 return mg_strndup_ctx(str, strlen(str), ctx);
3028}
3029
3030static char *
3031mg_strdup(const char *str)
3032{
3033 return mg_strndup_ctx(str, strlen(str), NULL);
3034}
3035
3036
3037static const char *
3038mg_strcasestr(const char *big_str, const char *small_str)
3039{
3040 size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
3041
3042 if (big_len >= small_len) {
3043 for (i = 0; i <= (big_len - small_len); i++) {
3044 if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
3045 return big_str + i;
3046 }
3047 }
3048 }
3049
3050 return NULL;
3051}
3052
3053
3054/* Return null terminated string of given maximum length.
3055 * Report errors if length is exceeded. */
3056static void
3057mg_vsnprintf(const struct mg_connection *conn,
3058 int *truncated,
3059 char *buf,
3060 size_t buflen,
3061 const char *fmt,
3062 va_list ap)
3063{
3064 int n, ok;
3065
3066 if (buflen == 0) {
3067 if (truncated) {
3068 *truncated = 1;
3069 }
3070 return;
3071 }
3072
3073#if defined(__clang__)
3074#pragma clang diagnostic push
3075#pragma clang diagnostic ignored "-Wformat-nonliteral"
3076 /* Using fmt as a non-literal is intended here, since it is mostly called
3077 * indirectly by mg_snprintf */
3078#endif
3079
3080 n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
3081 ok = (n >= 0) && ((size_t)n < buflen);
3082
3083#if defined(__clang__)
3084#pragma clang diagnostic pop
3085#endif
3086
3087 if (ok) {
3088 if (truncated) {
3089 *truncated = 0;
3090 }
3091 } else {
3092 if (truncated) {
3093 *truncated = 1;
3094 }
3095 mg_cry_internal(conn,
3096 "truncating vsnprintf buffer: [%.*s]",
3097 (int)((buflen > 200) ? 200 : (buflen - 1)),
3098 buf);
3099 n = (int)buflen - 1;
3100 }
3101 buf[n] = '\0';
3102}
3103
3104
3105static void
3106mg_snprintf(const struct mg_connection *conn,
3107 int *truncated,
3108 char *buf,
3109 size_t buflen,
3110 const char *fmt,
3111 ...)
3112{
3113 va_list ap;
3114
3115 va_start(ap, fmt);
3116 mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
3117 va_end(ap);
3118}
3119
3120
3121static int
3123{
3124 int i;
3125
3126 for (i = 0; config_options[i].name != NULL; i++) {
3127 if (strcmp(config_options[i].name, name) == 0) {
3128 return i;
3129 }
3130 }
3131 return -1;
3132}
3133
3134
3135const char *
3136mg_get_option(const struct mg_context *ctx, const char *name)
3137{
3138 int i;
3139 if ((i = get_option_index(name)) == -1) {
3140 return NULL;
3141 } else if (!ctx || ctx->dd.config[i] == NULL) {
3142 return "";
3143 } else {
3144 return ctx->dd.config[i];
3145 }
3146}
3147
3148#define mg_get_option DO_NOT_USE_THIS_FUNCTION_INTERNALLY__access_directly
3149
3150struct mg_context *
3152{
3153 return (conn == NULL) ? (struct mg_context *)NULL : (conn->phys_ctx);
3154}
3155
3156
3157void *
3159{
3160 return (ctx == NULL) ? NULL : ctx->user_data;
3161}
3162
3163
3164void *
3166{
3167 return mg_get_user_data(mg_get_context(conn));
3168}
3169
3170
3171void *
3173{
3174 /* both methods should return the same pointer */
3175 if (conn) {
3176 /* quick access, in case conn is known */
3177 return conn->tls_user_ptr;
3178 } else {
3179 /* otherwise get pointer from thread local storage (TLS) */
3180 struct mg_workerTLS *tls =
3181 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3182 return tls->user_ptr;
3183 }
3184}
3185
3186
3187void
3188mg_set_user_connection_data(const struct mg_connection *const_conn, void *data)
3189{
3190 if (const_conn != NULL) {
3191 /* Const cast, since "const struct mg_connection *" does not mean
3192 * the connection object is not modified. Here "const" is used,
3193 * to indicate mg_read/mg_write/mg_send/.. must not be called. */
3194 struct mg_connection *conn = (struct mg_connection *)const_conn;
3195 conn->request_info.conn_data = data;
3196 }
3197}
3198
3199
3200void *
3202{
3203 if (conn != NULL) {
3204 return conn->request_info.conn_data;
3205 }
3206 return NULL;
3207}
3208
3209
3210int
3212 int size,
3213 struct mg_server_port *ports)
3214{
3215 int i, cnt = 0;
3216
3217 if (size <= 0) {
3218 return -1;
3219 }
3220 memset(ports, 0, sizeof(*ports) * (size_t)size);
3221 if (!ctx) {
3222 return -1;
3223 }
3224 if (!ctx->listening_sockets) {
3225 return -1;
3226 }
3227
3228 for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
3229
3230 ports[cnt].port =
3231 ntohs(USA_IN_PORT_UNSAFE(&(ctx->listening_sockets[i].lsa)));
3232 ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
3233 ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
3234
3235 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
3236 /* IPv4 */
3237 ports[cnt].protocol = 1;
3238 cnt++;
3239 } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
3240 /* IPv6 */
3241 ports[cnt].protocol = 3;
3242 cnt++;
3243 }
3244 }
3245
3246 return cnt;
3247}
3248
3249
3250#if defined(USE_X_DOM_SOCKET) && !defined(UNIX_DOMAIN_SOCKET_SERVER_NAME)
3251#define UNIX_DOMAIN_SOCKET_SERVER_NAME "*"
3252#endif
3253
3254static void
3255sockaddr_to_string(char *buf, size_t len, const union usa *usa)
3256{
3257 buf[0] = '\0';
3258
3259 if (!usa) {
3260 return;
3261 }
3262
3263 if (usa->sa.sa_family == AF_INET) {
3264 getnameinfo(&usa->sa,
3265 sizeof(usa->sin),
3266 buf,
3267 (unsigned)len,
3268 NULL,
3269 0,
3270 NI_NUMERICHOST);
3271 }
3272#if defined(USE_IPV6)
3273 else if (usa->sa.sa_family == AF_INET6) {
3274 getnameinfo(&usa->sa,
3275 sizeof(usa->sin6),
3276 buf,
3277 (unsigned)len,
3278 NULL,
3279 0,
3280 NI_NUMERICHOST);
3281 }
3282#endif
3283#if defined(USE_X_DOM_SOCKET)
3284 else if (usa->sa.sa_family == AF_UNIX) {
3285 /* TODO: Define a remote address for unix domain sockets.
3286 * This code will always return "localhost", identical to http+tcp:
3287 getnameinfo(&usa->sa,
3288 sizeof(usa->sun),
3289 buf,
3290 (unsigned)len,
3291 NULL,
3292 0,
3293 NI_NUMERICHOST);
3294 */
3295 strncpy(buf, UNIX_DOMAIN_SOCKET_SERVER_NAME, len);
3296 buf[len-1] = 0;
3297 }
3298#endif
3299}
3300
3301
3302/* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
3303 * included in all responses other than 100, 101, 5xx. */
3304static void
3305gmt_time_string(char *buf, size_t buf_len, time_t *t)
3306{
3307#if !defined(REENTRANT_TIME)
3308 struct tm *tm;
3309
3310 tm = ((t != NULL) ? gmtime(t) : NULL);
3311 if (tm != NULL) {
3312#else
3313 struct tm _tm;
3314 struct tm *tm = &_tm;
3315
3316 if (t != NULL) {
3317 gmtime_r(t, tm);
3318#endif
3319 strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
3320 } else {
3321 mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
3322 buf[buf_len - 1] = '\0';
3323 }
3324}
3325
3326
3327/* difftime for struct timespec. Return value is in seconds. */
3328static double
3329mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
3330{
3331 return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
3332 + (double)(ts_now->tv_sec - ts_before->tv_sec);
3333}
3334
3335
3336#if defined(MG_EXTERNAL_FUNCTION_mg_cry_internal_impl)
3337static void mg_cry_internal_impl(const struct mg_connection *conn,
3338 const char *func,
3339 unsigned line,
3340 const char *fmt,
3341 va_list ap);
3342#include "external_mg_cry_internal_impl.inl"
3343#elif !defined(NO_FILESYSTEMS)
3344
3345/* Print error message to the opened error log stream. */
3346static void
3348 const char *func,
3349 unsigned line,
3350 const char *fmt,
3351 va_list ap)
3352{
3353 char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
3354 struct mg_file fi;
3355 time_t timestamp;
3356
3357 /* Unused, in the RELEASE build */
3358 (void)func;
3359 (void)line;
3360
3361#if defined(GCC_DIAGNOSTIC)
3362#pragma GCC diagnostic push
3363#pragma GCC diagnostic ignored "-Wformat-nonliteral"
3364#endif
3365
3366 IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
3367
3368#if defined(GCC_DIAGNOSTIC)
3369#pragma GCC diagnostic pop
3370#endif
3371
3372 buf[sizeof(buf) - 1] = 0;
3373
3374 DEBUG_TRACE("mg_cry called from %s:%u: %s", func, line, buf);
3375
3376 if (!conn) {
3377 puts(buf);
3378 return;
3379 }
3380
3381 /* Do not lock when getting the callback value, here and below.
3382 * I suppose this is fine, since function cannot disappear in the
3383 * same way string option can. */
3384 if ((conn->phys_ctx->callbacks.log_message == NULL)
3385 || (conn->phys_ctx->callbacks.log_message(conn, buf) == 0)) {
3386
3387 if (conn->dom_ctx->config[ERROR_LOG_FILE] != NULL) {
3388 if (mg_fopen(conn,
3391 &fi)
3392 == 0) {
3393 fi.access.fp = NULL;
3394 }
3395 } else {
3396 fi.access.fp = NULL;
3397 }
3398
3399 if (fi.access.fp != NULL) {
3400 flockfile(fi.access.fp);
3401 timestamp = time(NULL);
3402
3403 sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
3404 fprintf(fi.access.fp,
3405 "[%010lu] [error] [client %s] ",
3406 (unsigned long)timestamp,
3407 src_addr);
3408
3409 if (conn->request_info.request_method != NULL) {
3410 fprintf(fi.access.fp,
3411 "%s %s: ",
3415 : "");
3416 }
3417
3418 fprintf(fi.access.fp, "%s", buf);
3419 fputc('\n', fi.access.fp);
3420 fflush(fi.access.fp);
3421 funlockfile(fi.access.fp);
3422 (void)mg_fclose(&fi.access); /* Ignore errors. We can't call
3423 * mg_cry here anyway ;-) */
3424 }
3425 }
3426}
3427#else
3428#error Must either enable filesystems or provide a custom mg_cry_internal_impl implementation
3429#endif /* Externally provided function */
3430
3431
3432/* Construct fake connection structure. Used for logging, if connection
3433 * is not applicable at the moment of logging. */
3434static struct mg_connection *
3436{
3437 static const struct mg_connection conn_zero = {0};
3438 *fc = conn_zero;
3439 fc->phys_ctx = ctx;
3440 fc->dom_ctx = &(ctx->dd);
3441 return fc;
3442}
3443
3444
3445static void
3447 struct mg_context *ctx,
3448 const char *func,
3449 unsigned line,
3450 const char *fmt,
3451 ...)
3452{
3453 va_list ap;
3454 va_start(ap, fmt);
3455 if (!conn && ctx) {
3456 struct mg_connection fc;
3457 mg_cry_internal_impl(fake_connection(&fc, ctx), func, line, fmt, ap);
3458 } else {
3459 mg_cry_internal_impl(conn, func, line, fmt, ap);
3460 }
3461 va_end(ap);
3462}
3463
3464
3465void
3466mg_cry(const struct mg_connection *conn, const char *fmt, ...)
3467{
3468 va_list ap;
3469 va_start(ap, fmt);
3470 mg_cry_internal_impl(conn, "user", 0, fmt, ap);
3471 va_end(ap);
3472}
3473
3474
3475#define mg_cry DO_NOT_USE_THIS_FUNCTION__USE_mg_cry_internal
3476
3477
3478const char *
3480{
3481 return CIVETWEB_VERSION;
3482}
3483
3484
3485const struct mg_request_info *
3487{
3488 if (!conn) {
3489 return NULL;
3490 }
3491#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
3493 char txt[16];
3494 struct mg_workerTLS *tls =
3495 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3496
3497 sprintf(txt, "%03i", conn->response_info.status_code);
3498 if (strlen(txt) == 3) {
3499 memcpy(tls->txtbuf, txt, 4);
3500 } else {
3501 strcpy(tls->txtbuf, "ERR");
3502 }
3503
3504 ((struct mg_connection *)conn)->request_info.local_uri =
3505 tls->txtbuf; /* use thread safe buffer */
3506 ((struct mg_connection *)conn)->request_info.local_uri_raw =
3507 tls->txtbuf; /* use the same thread safe buffer */
3508 ((struct mg_connection *)conn)->request_info.request_uri =
3509 tls->txtbuf; /* use the same thread safe buffer */
3510
3511 ((struct mg_connection *)conn)->request_info.num_headers =
3513 memcpy(((struct mg_connection *)conn)->request_info.http_headers,
3515 sizeof(conn->response_info.http_headers));
3516 } else
3517#endif
3519 return NULL;
3520 }
3521 return &conn->request_info;
3522}
3523
3524
3525const struct mg_response_info *
3527{
3528 if (!conn) {
3529 return NULL;
3530 }
3532 return NULL;
3533 }
3534 return &conn->response_info;
3535}
3536
3537
3538static const char *
3540{
3541#if defined(__clang__)
3542#pragma clang diagnostic push
3543#pragma clang diagnostic ignored "-Wunreachable-code"
3544 /* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be
3545 * not supported. Clang raises an "unreachable code" warning for parts of ?:
3546 * unreachable, but splitting into four different #ifdef clauses here is
3547 * more complicated.
3548 */
3549#endif
3550
3551 const struct mg_request_info *ri = &conn->request_info;
3552
3553 const char *proto = ((conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)
3554 ? (ri->is_ssl ? "wss" : "ws")
3555 : (ri->is_ssl ? "https" : "http"));
3556
3557 return proto;
3558
3559#if defined(__clang__)
3560#pragma clang diagnostic pop
3561#endif
3562}
3563
3564
3565static int
3567 char *buf,
3568 size_t buflen,
3569 const char *define_proto,
3570 int define_port,
3571 const char *define_uri)
3572{
3573 if ((buflen < 1) || (buf == 0) || (conn == 0)) {
3574 return -1;
3575 } else {
3576 int truncated = 0;
3577 const struct mg_request_info *ri = &conn->request_info;
3578
3579 const char *proto =
3580 (define_proto != NULL) ? define_proto : get_proto_name(conn);
3581 const char *uri =
3582 (define_uri != NULL)
3583 ? define_uri
3584 : ((ri->request_uri != NULL) ? ri->request_uri : ri->local_uri);
3585 int port = (define_port > 0) ? define_port : ri->server_port;
3586 int default_port = 80;
3587
3588 if (uri == NULL) {
3589 return -1;
3590 }
3591
3592#if defined(USE_X_DOM_SOCKET)
3593 if (conn->client.lsa.sa.sa_family == AF_UNIX) {
3594 /* TODO: Define and document a link for UNIX domain sockets. */
3595 /* There seems to be no official standard for this.
3596 * Common uses seem to be "httpunix://", "http.unix://" or
3597 * "http+unix://" as a protocol definition string, followed by
3598 * "localhost" or "127.0.0.1" or "/tmp/unix/path" or
3599 * "%2Ftmp%2Funix%2Fpath" (url % encoded) or
3600 * "localhost:%2Ftmp%2Funix%2Fpath" (domain socket path as port) or
3601 * "" (completely skipping the server name part). In any case, the
3602 * last part is the server local path. */
3603 const char *server_name = UNIX_DOMAIN_SOCKET_SERVER_NAME;
3604 mg_snprintf(conn,
3605 &truncated,
3606 buf,
3607 buflen,
3608 "%s.unix://%s%s",
3609 proto,
3610 server_name,
3611 ri->local_uri);
3612 default_port = 0;
3613 return 0;
3614 }
3615#endif
3616
3617 if (define_proto) {
3618 /* If we got a protocol name, use the default port accordingly. */
3619 if ((0 == strcmp(define_proto, "https"))
3620 || (0 == strcmp(define_proto, "wss"))) {
3621 default_port = 443;
3622 }
3623 } else if (ri->is_ssl) {
3624 /* If we did not get a protocol name, use TLS as default if it is
3625 * already used. */
3626 default_port = 443;
3627 }
3628
3629 {
3630#if defined(USE_IPV6)
3631 int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
3632#endif
3633 int auth_domain_check_enabled =
3635 && (!mg_strcasecmp(
3636 conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes"));
3637
3638 const char *server_domain =
3640
3641 char portstr[16];
3642 char server_ip[48];
3643
3644 if (port != default_port) {
3645 sprintf(portstr, ":%u", (unsigned)port);
3646 } else {
3647 portstr[0] = 0;
3648 }
3649
3650 if (!auth_domain_check_enabled || !server_domain) {
3651
3652 sockaddr_to_string(server_ip,
3653 sizeof(server_ip),
3654 &conn->client.lsa);
3655
3656 server_domain = server_ip;
3657 }
3658
3659 mg_snprintf(conn,
3660 &truncated,
3661 buf,
3662 buflen,
3663#if defined(USE_IPV6)
3664 "%s://%s%s%s%s%s",
3665 proto,
3666 (is_ipv6 && (server_domain == server_ip)) ? "[" : "",
3667 server_domain,
3668 (is_ipv6 && (server_domain == server_ip)) ? "]" : "",
3669#else
3670 "%s://%s%s%s",
3671 proto,
3672 server_domain,
3673#endif
3674 portstr,
3675 ri->local_uri);
3676
3677 if (truncated) {
3678 return -1;
3679 }
3680 return 0;
3681 }
3682 }
3683}
3684
3685
3686int
3687mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
3688{
3689 return mg_construct_local_link(conn, buf, buflen, NULL, -1, NULL);
3690}
3691
3692
3693/* Skip the characters until one of the delimiters characters found.
3694 * 0-terminate resulting word. Skip the delimiter and following whitespaces.
3695 * Advance pointer to buffer to the next word. Return found 0-terminated
3696 * word.
3697 * Delimiters can be quoted with quotechar. */
3698static char *
3699skip_quoted(char **buf,
3700 const char *delimiters,
3701 const char *whitespace,
3702 char quotechar)
3703{
3704 char *p, *begin_word, *end_word, *end_whitespace;
3705
3706 begin_word = *buf;
3707 end_word = begin_word + strcspn(begin_word, delimiters);
3708
3709 /* Check for quotechar */
3710 if (end_word > begin_word) {
3711 p = end_word - 1;
3712 while (*p == quotechar) {
3713 /* While the delimiter is quoted, look for the next delimiter.
3714 */
3715 /* This happens, e.g., in calls from parse_auth_header,
3716 * if the user name contains a " character. */
3717
3718 /* If there is anything beyond end_word, copy it. */
3719 if (*end_word != '\0') {
3720 size_t end_off = strcspn(end_word + 1, delimiters);
3721 memmove(p, end_word, end_off + 1);
3722 p += end_off; /* p must correspond to end_word - 1 */
3723 end_word += end_off + 1;
3724 } else {
3725 *p = '\0';
3726 break;
3727 }
3728 }
3729 for (p++; p < end_word; p++) {
3730 *p = '\0';
3731 }
3732 }
3733
3734 if (*end_word == '\0') {
3735 *buf = end_word;
3736 } else {
3737
3738#if defined(GCC_DIAGNOSTIC)
3739 /* Disable spurious conversion warning for GCC */
3740#pragma GCC diagnostic push
3741#pragma GCC diagnostic ignored "-Wsign-conversion"
3742#endif /* defined(GCC_DIAGNOSTIC) */
3743
3744 end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
3745
3746#if defined(GCC_DIAGNOSTIC)
3747#pragma GCC diagnostic pop
3748#endif /* defined(GCC_DIAGNOSTIC) */
3749
3750 for (p = end_word; p < end_whitespace; p++) {
3751 *p = '\0';
3752 }
3753
3754 *buf = end_whitespace;
3755 }
3756
3757 return begin_word;
3758}
3759
3760
3761/* Return HTTP header value, or NULL if not found. */
3762static const char *
3763get_header(const struct mg_header *hdr, int num_hdr, const char *name)
3764{
3765 int i;
3766 for (i = 0; i < num_hdr; i++) {
3767 if (!mg_strcasecmp(name, hdr[i].name)) {
3768 return hdr[i].value;
3769 }
3770 }
3771
3772 return NULL;
3773}
3774
3775
3776#if defined(USE_WEBSOCKET)
3777/* Retrieve requested HTTP header multiple values, and return the number of
3778 * found occurrences */
3779static int
3780get_req_headers(const struct mg_request_info *ri,
3781 const char *name,
3782 const char **output,
3783 int output_max_size)
3784{
3785 int i;
3786 int cnt = 0;
3787 if (ri) {
3788 for (i = 0; i < ri->num_headers && cnt < output_max_size; i++) {
3789 if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
3790 output[cnt++] = ri->http_headers[i].value;
3791 }
3792 }
3793 }
3794 return cnt;
3795}
3796#endif
3797
3798
3799const char *
3800mg_get_header(const struct mg_connection *conn, const char *name)
3801{
3802 if (!conn) {
3803 return NULL;
3804 }
3805
3809 name);
3810 }
3814 name);
3815 }
3816 return NULL;
3817}
3818
3819
3820static const char *
3822{
3823 if (!conn) {
3824 return NULL;
3825 }
3826
3828 return conn->request_info.http_version;
3829 }
3831 return conn->response_info.http_version;
3832 }
3833 return NULL;
3834}
3835
3836
3837/* A helper function for traversing a comma separated list of values.
3838 * It returns a list pointer shifted to the next value, or NULL if the end
3839 * of the list found.
3840 * Value is stored in val vector. If value has form "x=y", then eq_val
3841 * vector is initialized to point to the "y" part, and val vector length
3842 * is adjusted to point only to "x". */
3843static const char *
3844next_option(const char *list, struct vec *val, struct vec *eq_val)
3845{
3846 int end;
3847
3848reparse:
3849 if (val == NULL || list == NULL || *list == '\0') {
3850 /* End of the list */
3851 return NULL;
3852 }
3853
3854 /* Skip over leading LWS */
3855 while (*list == ' ' || *list == '\t')
3856 list++;
3857
3858 val->ptr = list;
3859 if ((list = strchr(val->ptr, ',')) != NULL) {
3860 /* Comma found. Store length and shift the list ptr */
3861 val->len = ((size_t)(list - val->ptr));
3862 list++;
3863 } else {
3864 /* This value is the last one */
3865 list = val->ptr + strlen(val->ptr);
3866 val->len = ((size_t)(list - val->ptr));
3867 }
3868
3869 /* Adjust length for trailing LWS */
3870 end = (int)val->len - 1;
3871 while (end >= 0 && ((val->ptr[end] == ' ') || (val->ptr[end] == '\t')))
3872 end--;
3873 val->len = (size_t)(end) + (size_t)(1);
3874
3875 if (val->len == 0) {
3876 /* Ignore any empty entries. */
3877 goto reparse;
3878 }
3879
3880 if (eq_val != NULL) {
3881 /* Value has form "x=y", adjust pointers and lengths
3882 * so that val points to "x", and eq_val points to "y". */
3883 eq_val->len = 0;
3884 eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
3885 if (eq_val->ptr != NULL) {
3886 eq_val->ptr++; /* Skip over '=' character */
3887 eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
3888 val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
3889 }
3890 }
3891
3892 return list;
3893}
3894
3895
3896/* A helper function for checking if a comma separated list of values
3897 * contains
3898 * the given option (case insensitvely).
3899 * 'header' can be NULL, in which case false is returned. */
3900static int
3901header_has_option(const char *header, const char *option)
3902{
3903 struct vec opt_vec;
3904 struct vec eq_vec;
3905
3906 DEBUG_ASSERT(option != NULL);
3907 DEBUG_ASSERT(option[0] != '\0');
3908
3909 while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
3910 if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
3911 return 1;
3912 }
3913
3914 return 0;
3915}
3916
3917
3918/* Perform case-insensitive match of string against pattern */
3919static ptrdiff_t
3920match_prefix(const char *pattern, size_t pattern_len, const char *str)
3921{
3922 const char *or_str;
3923 ptrdiff_t i, j, len, res;
3924
3925 if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
3926 res = match_prefix(pattern, (size_t)(or_str - pattern), str);
3927 return (res > 0) ? res
3928 : match_prefix(or_str + 1,
3929 (size_t)((pattern + pattern_len)
3930 - (or_str + 1)),
3931 str);
3932 }
3933
3934 for (i = 0, j = 0; (i < (ptrdiff_t)pattern_len); i++, j++) {
3935 if ((pattern[i] == '?') && (str[j] != '\0')) {
3936 continue;
3937 } else if (pattern[i] == '$') {
3938 return (str[j] == '\0') ? j : -1;
3939 } else if (pattern[i] == '*') {
3940 i++;
3941 if (pattern[i] == '*') {
3942 i++;
3943 len = (ptrdiff_t)strlen(str + j);
3944 } else {
3945 len = (ptrdiff_t)strcspn(str + j, "/");
3946 }
3947 if (i == (ptrdiff_t)pattern_len) {
3948 return j + len;
3949 }
3950 do {
3951 res = match_prefix(pattern + i,
3952 (pattern_len - (size_t)i),
3953 str + j + len);
3954 } while (res == -1 && len-- > 0);
3955 return (res == -1) ? -1 : j + res + len;
3956 } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
3957 return -1;
3958 }
3959 }
3960 return (ptrdiff_t)j;
3961}
3962
3963
3964static ptrdiff_t
3965match_prefix_strlen(const char *pattern, const char *str)
3966{
3967 if (pattern == NULL) {
3968 return -1;
3969 }
3970 return match_prefix(pattern, strlen(pattern), str);
3971}
3972
3973
3974/* HTTP 1.1 assumes keep alive if "Connection:" header is not set
3975 * This function must tolerate situations when connection info is not
3976 * set up, for example if request parsing failed. */
3977static int
3979{
3980 const char *http_version;
3981 const char *header;
3982
3983 /* First satisfy needs of the server */
3984 if ((conn == NULL) || conn->must_close) {
3985 /* Close, if civetweb framework needs to close */
3986 return 0;
3987 }
3988
3989 if (mg_strcasecmp(conn->dom_ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0) {
3990 /* Close, if keep alive is not enabled */
3991 return 0;
3992 }
3993
3994 /* Check explicit wish of the client */
3995 header = mg_get_header(conn, "Connection");
3996 if (header) {
3997 /* If there is a connection header from the client, obey */
3998 if (header_has_option(header, "keep-alive")) {
3999 return 1;
4000 }
4001 return 0;
4002 }
4003
4004 /* Use default of the standard */
4005 http_version = get_http_version(conn);
4006 if (http_version && (0 == strcmp(http_version, "1.1"))) {
4007 /* HTTP 1.1 default is keep alive */
4008 return 1;
4009 }
4010
4011 /* HTTP 1.0 (and earlier) default is to close the connection */
4012 return 0;
4013}
4014
4015
4016static int
4018{
4019 if (!conn || !conn->dom_ctx) {
4020 return 0;
4021 }
4022
4023 return (mg_strcasecmp(conn->dom_ctx->config[DECODE_URL], "yes") == 0);
4024}
4025
4026
4027static int
4029{
4030 if (!conn || !conn->dom_ctx) {
4031 return 0;
4032 }
4033
4034 return (mg_strcasecmp(conn->dom_ctx->config[DECODE_QUERY_STRING], "yes")
4035 == 0);
4036}
4037
4038
4039static const char *
4041{
4042 return should_keep_alive(conn) ? "keep-alive" : "close";
4043}
4044
4045
4046#include "response.inl"
4047
4048
4049static void
4051{
4052 /* Send all current and obsolete cache opt-out directives. */
4054 "Cache-Control",
4055 "no-cache, no-store, "
4056 "must-revalidate, private, max-age=0",
4057 -1);
4058 mg_response_header_add(conn, "Expires", "0", -1);
4059
4060 if (conn->protocol_type == PROTOCOL_TYPE_HTTP1) {
4061 /* Obsolete, but still send it for HTTP/1.0 */
4062 mg_response_header_add(conn, "Pragma", "no-cache", -1);
4063 }
4064}
4065
4066
4067static void
4069{
4070#if !defined(NO_CACHING)
4071 int max_age;
4072 char val[64];
4073
4074 const char *cache_control =
4076
4077 /* If there is a full cache-control option configured,0 use it */
4078 if (cache_control != NULL) {
4079 mg_response_header_add(conn, "Cache-Control", cache_control, -1);
4080 return;
4081 }
4082
4083 /* Read the server config to check how long a file may be cached.
4084 * The configuration is in seconds. */
4085 max_age = atoi(conn->dom_ctx->config[STATIC_FILE_MAX_AGE]);
4086 if (max_age <= 0) {
4087 /* 0 means "do not cache". All values <0 are reserved
4088 * and may be used differently in the future. */
4089 /* If a file should not be cached, do not only send
4090 * max-age=0, but also pragmas and Expires headers. */
4092 return;
4093 }
4094
4095 /* Use "Cache-Control: max-age" instead of "Expires" header.
4096 * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
4097 /* See also https://www.mnot.net/cache_docs/ */
4098 /* According to RFC 2616, Section 14.21, caching times should not exceed
4099 * one year. A year with 365 days corresponds to 31536000 seconds, a
4100 * leap
4101 * year to 31622400 seconds. For the moment, we just send whatever has
4102 * been configured, still the behavior for >1 year should be considered
4103 * as undefined. */
4105 conn, NULL, val, sizeof(val), "max-age=%lu", (unsigned long)max_age);
4106 mg_response_header_add(conn, "Cache-Control", val, -1);
4107
4108#else /* NO_CACHING */
4109
4111#endif /* !NO_CACHING */
4112}
4113
4114
4115static void
4117{
4118 const char *header = conn->dom_ctx->config[ADDITIONAL_HEADER];
4119
4120#if !defined(NO_SSL)
4121 if (conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]) {
4122 long max_age = atol(conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]);
4123 if (max_age >= 0) {
4124 char val[64];
4125 mg_snprintf(conn,
4126 NULL,
4127 val,
4128 sizeof(val),
4129 "max-age=%lu",
4130 (unsigned long)max_age);
4131 mg_response_header_add(conn, "Strict-Transport-Security", val, -1);
4132 }
4133 }
4134#endif
4135
4136 if (header && header[0]) {
4137 mg_response_header_add_lines(conn, header);
4138 }
4139}
4140
4141
4142#if !defined(NO_FILESYSTEMS)
4143static void handle_file_based_request(struct mg_connection *conn,
4144 const char *path,
4145 struct mg_file *filep);
4146#endif /* NO_FILESYSTEMS */
4147
4148
4149const char *
4150mg_get_response_code_text(const struct mg_connection *conn, int response_code)
4151{
4152 /* See IANA HTTP status code assignment:
4153 * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
4154 */
4155
4156 switch (response_code) {
4157 /* RFC2616 Section 10.1 - Informational 1xx */
4158 case 100:
4159 return "Continue"; /* RFC2616 Section 10.1.1 */
4160 case 101:
4161 return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
4162 case 102:
4163 return "Processing"; /* RFC2518 Section 10.1 */
4164
4165 /* RFC2616 Section 10.2 - Successful 2xx */
4166 case 200:
4167 return "OK"; /* RFC2616 Section 10.2.1 */
4168 case 201:
4169 return "Created"; /* RFC2616 Section 10.2.2 */
4170 case 202:
4171 return "Accepted"; /* RFC2616 Section 10.2.3 */
4172 case 203:
4173 return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
4174 case 204:
4175 return "No Content"; /* RFC2616 Section 10.2.5 */
4176 case 205:
4177 return "Reset Content"; /* RFC2616 Section 10.2.6 */
4178 case 206:
4179 return "Partial Content"; /* RFC2616 Section 10.2.7 */
4180 case 207:
4181 return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1
4182 */
4183 case 208:
4184 return "Already Reported"; /* RFC5842 Section 7.1 */
4185
4186 case 226:
4187 return "IM used"; /* RFC3229 Section 10.4.1 */
4188
4189 /* RFC2616 Section 10.3 - Redirection 3xx */
4190 case 300:
4191 return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
4192 case 301:
4193 return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
4194 case 302:
4195 return "Found"; /* RFC2616 Section 10.3.3 */
4196 case 303:
4197 return "See Other"; /* RFC2616 Section 10.3.4 */
4198 case 304:
4199 return "Not Modified"; /* RFC2616 Section 10.3.5 */
4200 case 305:
4201 return "Use Proxy"; /* RFC2616 Section 10.3.6 */
4202 case 307:
4203 return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
4204 case 308:
4205 return "Permanent Redirect"; /* RFC7238 Section 3 */
4206
4207 /* RFC2616 Section 10.4 - Client Error 4xx */
4208 case 400:
4209 return "Bad Request"; /* RFC2616 Section 10.4.1 */
4210 case 401:
4211 return "Unauthorized"; /* RFC2616 Section 10.4.2 */
4212 case 402:
4213 return "Payment Required"; /* RFC2616 Section 10.4.3 */
4214 case 403:
4215 return "Forbidden"; /* RFC2616 Section 10.4.4 */
4216 case 404:
4217 return "Not Found"; /* RFC2616 Section 10.4.5 */
4218 case 405:
4219 return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
4220 case 406:
4221 return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
4222 case 407:
4223 return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
4224 case 408:
4225 return "Request Time-out"; /* RFC2616 Section 10.4.9 */
4226 case 409:
4227 return "Conflict"; /* RFC2616 Section 10.4.10 */
4228 case 410:
4229 return "Gone"; /* RFC2616 Section 10.4.11 */
4230 case 411:
4231 return "Length Required"; /* RFC2616 Section 10.4.12 */
4232 case 412:
4233 return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
4234 case 413:
4235 return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
4236 case 414:
4237 return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
4238 case 415:
4239 return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
4240 case 416:
4241 return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17
4242 */
4243 case 417:
4244 return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
4245
4246 case 421:
4247 return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
4248 case 422:
4249 return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
4250 * Section 11.2 */
4251 case 423:
4252 return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
4253 case 424:
4254 return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
4255 * Section 11.4 */
4256
4257 case 426:
4258 return "Upgrade Required"; /* RFC 2817 Section 4 */
4259
4260 case 428:
4261 return "Precondition Required"; /* RFC 6585, Section 3 */
4262 case 429:
4263 return "Too Many Requests"; /* RFC 6585, Section 4 */
4264
4265 case 431:
4266 return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
4267
4268 case 451:
4269 return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
4270 * Section 3 */
4271
4272 /* RFC2616 Section 10.5 - Server Error 5xx */
4273 case 500:
4274 return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
4275 case 501:
4276 return "Not Implemented"; /* RFC2616 Section 10.5.2 */
4277 case 502:
4278 return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
4279 case 503:
4280 return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
4281 case 504:
4282 return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
4283 case 505:
4284 return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
4285 case 506:
4286 return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
4287 case 507:
4288 return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
4289 * Section 11.5 */
4290 case 508:
4291 return "Loop Detected"; /* RFC5842 Section 7.1 */
4292
4293 case 510:
4294 return "Not Extended"; /* RFC 2774, Section 7 */
4295 case 511:
4296 return "Network Authentication Required"; /* RFC 6585, Section 6 */
4297
4298 /* Other status codes, not shown in the IANA HTTP status code
4299 * assignment.
4300 * E.g., "de facto" standards due to common use, ... */
4301 case 418:
4302 return "I am a teapot"; /* RFC2324 Section 2.3.2 */
4303 case 419:
4304 return "Authentication Timeout"; /* common use */
4305 case 420:
4306 return "Enhance Your Calm"; /* common use */
4307 case 440:
4308 return "Login Timeout"; /* common use */
4309 case 509:
4310 return "Bandwidth Limit Exceeded"; /* common use */
4311
4312 default:
4313 /* This error code is unknown. This should not happen. */
4314 if (conn) {
4315 mg_cry_internal(conn,
4316 "Unknown HTTP response code: %u",
4317 response_code);
4318 }
4319
4320 /* Return at least a category according to RFC 2616 Section 10. */
4321 if (response_code >= 100 && response_code < 200) {
4322 /* Unknown informational status code */
4323 return "Information";
4324 }
4325 if (response_code >= 200 && response_code < 300) {
4326 /* Unknown success code */
4327 return "Success";
4328 }
4329 if (response_code >= 300 && response_code < 400) {
4330 /* Unknown redirection code */
4331 return "Redirection";
4332 }
4333 if (response_code >= 400 && response_code < 500) {
4334 /* Unknown request error code */
4335 return "Client Error";
4336 }
4337 if (response_code >= 500 && response_code < 600) {
4338 /* Unknown server error code */
4339 return "Server Error";
4340 }
4341
4342 /* Response code not even within reasonable range */
4343 return "";
4344 }
4345}
4346
4347
4348static int
4350 int status,
4351 const char *fmt,
4352 va_list args)
4353{
4354 char errmsg_buf[MG_BUF_LEN];
4355 va_list ap;
4356 int has_body;
4357
4358#if !defined(NO_FILESYSTEMS)
4359 char path_buf[UTF8_PATH_MAX];
4360 int len, i, page_handler_found, scope, truncated;
4361 const char *error_handler = NULL;
4362 struct mg_file error_page_file = STRUCT_FILE_INITIALIZER;
4363 const char *error_page_file_ext, *tstr;
4364#endif /* NO_FILESYSTEMS */
4365 int handled_by_callback = 0;
4366
4367 if ((conn == NULL) || (fmt == NULL)) {
4368 return -2;
4369 }
4370
4371 /* Set status (for log) */
4372 conn->status_code = status;
4373
4374 /* Errors 1xx, 204 and 304 MUST NOT send a body */
4375 has_body = ((status > 199) && (status != 204) && (status != 304));
4376
4377 /* Prepare message in buf, if required */
4378 if (has_body
4379 || (!conn->in_error_handler
4380 && (conn->phys_ctx->callbacks.http_error != NULL))) {
4381 /* Store error message in errmsg_buf */
4382 va_copy(ap, args);
4383 mg_vsnprintf(conn, NULL, errmsg_buf, sizeof(errmsg_buf), fmt, ap);
4384 va_end(ap);
4385 /* In a debug build, print all html errors */
4386 DEBUG_TRACE("Error %i - [%s]", status, errmsg_buf);
4387 }
4388
4389 /* If there is a http_error callback, call it.
4390 * But don't do it recursively, if callback calls mg_send_http_error again.
4391 */
4392 if (!conn->in_error_handler
4393 && (conn->phys_ctx->callbacks.http_error != NULL)) {
4394 /* Mark in_error_handler to avoid recursion and call user callback. */
4395 conn->in_error_handler = 1;
4396 handled_by_callback =
4397 (conn->phys_ctx->callbacks.http_error(conn, status, errmsg_buf)
4398 == 0);
4399 conn->in_error_handler = 0;
4400 }
4401
4402 if (!handled_by_callback) {
4403 /* Check for recursion */
4404 if (conn->in_error_handler) {
4406 "Recursion when handling error %u - fall back to default",
4407 status);
4408#if !defined(NO_FILESYSTEMS)
4409 } else {
4410 /* Send user defined error pages, if defined */
4411 error_handler = conn->dom_ctx->config[ERROR_PAGES];
4412 error_page_file_ext = conn->dom_ctx->config[INDEX_FILES];
4413 page_handler_found = 0;
4414
4415 if (error_handler != NULL) {
4416 for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
4417 switch (scope) {
4418 case 1: /* Handler for specific error, e.g. 404 error */
4419 mg_snprintf(conn,
4420 &truncated,
4421 path_buf,
4422 sizeof(path_buf) - 32,
4423 "%serror%03u.",
4424 error_handler,
4425 status);
4426 break;
4427 case 2: /* Handler for error group, e.g., 5xx error
4428 * handler
4429 * for all server errors (500-599) */
4430 mg_snprintf(conn,
4431 &truncated,
4432 path_buf,
4433 sizeof(path_buf) - 32,
4434 "%serror%01uxx.",
4435 error_handler,
4436 status / 100);
4437 break;
4438 default: /* Handler for all errors */
4439 mg_snprintf(conn,
4440 &truncated,
4441 path_buf,
4442 sizeof(path_buf) - 32,
4443 "%serror.",
4444 error_handler);
4445 break;
4446 }
4447
4448 /* String truncation in buf may only occur if
4449 * error_handler is too long. This string is
4450 * from the config, not from a client. */
4451 (void)truncated;
4452
4453 /* The following code is redundant, but it should avoid
4454 * false positives in static source code analyzers and
4455 * vulnerability scanners.
4456 */
4457 path_buf[sizeof(path_buf) - 32] = 0;
4458 len = (int)strlen(path_buf);
4459 if (len > (int)sizeof(path_buf) - 32) {
4460 len = (int)sizeof(path_buf) - 32;
4461 }
4462
4463 /* Start with the file extenstion from the configuration. */
4464 tstr = strchr(error_page_file_ext, '.');
4465
4466 while (tstr) {
4467 for (i = 1;
4468 (i < 32) && (tstr[i] != 0) && (tstr[i] != ',');
4469 i++) {
4470 /* buffer overrun is not possible here, since
4471 * (i < 32) && (len < sizeof(path_buf) - 32)
4472 * ==> (i + len) < sizeof(path_buf) */
4473 path_buf[len + i - 1] = tstr[i];
4474 }
4475 /* buffer overrun is not possible here, since
4476 * (i <= 32) && (len < sizeof(path_buf) - 32)
4477 * ==> (i + len) <= sizeof(path_buf) */
4478 path_buf[len + i - 1] = 0;
4479
4480 if (mg_stat(conn, path_buf, &error_page_file.stat)) {
4481 DEBUG_TRACE("Check error page %s - found",
4482 path_buf);
4483 page_handler_found = 1;
4484 break;
4485 }
4486 DEBUG_TRACE("Check error page %s - not found",
4487 path_buf);
4488
4489 /* Continue with the next file extenstion from the
4490 * configuration (if there is a next one). */
4491 tstr = strchr(tstr + i, '.');
4492 }
4493 }
4494 }
4495
4496 if (page_handler_found) {
4497 conn->in_error_handler = 1;
4498 handle_file_based_request(conn, path_buf, &error_page_file);
4499 conn->in_error_handler = 0;
4500 return 0;
4501 }
4502#endif /* NO_FILESYSTEMS */
4503 }
4504
4505 /* No custom error page. Send default error page. */
4506 conn->must_close = 1;
4507 mg_response_header_start(conn, status);
4510 if (has_body) {
4512 "Content-Type",
4513 "text/plain; charset=utf-8",
4514 -1);
4515 }
4517
4518 /* HTTP responses 1xx, 204 and 304 MUST NOT send a body */
4519 if (has_body) {
4520 /* For other errors, send a generic error message. */
4521 const char *status_text = mg_get_response_code_text(conn, status);
4522 mg_printf(conn, "Error %d: %s\n", status, status_text);
4523 mg_write(conn, errmsg_buf, strlen(errmsg_buf));
4524
4525 } else {
4526 /* No body allowed. Close the connection. */
4527 DEBUG_TRACE("Error %i", status);
4528 }
4529 }
4530 return 0;
4531}
4532
4533
4534int
4535mg_send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
4536{
4537 va_list ap;
4538 int ret;
4539
4540 va_start(ap, fmt);
4541 ret = mg_send_http_error_impl(conn, status, fmt, ap);
4542 va_end(ap);
4543
4544 return ret;
4545}
4546
4547
4548int
4550 const char *mime_type,
4551 long long content_length)
4552{
4553 if ((mime_type == NULL) || (*mime_type == 0)) {
4554 /* No content type defined: default to text/html */
4555 mime_type = "text/html";
4556 }
4557
4558 mg_response_header_start(conn, 200);
4561 mg_response_header_add(conn, "Content-Type", mime_type, -1);
4562 if (content_length < 0) {
4563 /* Size not known. Use chunked encoding (HTTP/1.x) */
4564 if (conn->protocol_type == PROTOCOL_TYPE_HTTP1) {
4565 /* Only HTTP/1.x defines "chunked" encoding, HTTP/2 does not*/
4566 mg_response_header_add(conn, "Transfer-Encoding", "chunked", -1);
4567 }
4568 } else {
4569 char len[32];
4570 int trunc = 0;
4571 mg_snprintf(conn,
4572 &trunc,
4573 len,
4574 sizeof(len),
4575 "%" UINT64_FMT,
4576 (uint64_t)content_length);
4577 if (!trunc) {
4578 /* Since 32 bytes is enough to hold any 64 bit decimal number,
4579 * !trunc is always true */
4580 mg_response_header_add(conn, "Content-Length", len, -1);
4581 }
4582 }
4584
4585 return 0;
4586}
4587
4588
4589int
4591 const char *target_url,
4592 int redirect_code)
4593{
4594 /* Send a 30x redirect response.
4595 *
4596 * Redirect types (status codes):
4597 *
4598 * Status | Perm/Temp | Method | Version
4599 * 301 | permanent | POST->GET undefined | HTTP/1.0
4600 * 302 | temporary | POST->GET undefined | HTTP/1.0
4601 * 303 | temporary | always use GET | HTTP/1.1
4602 * 307 | temporary | always keep method | HTTP/1.1
4603 * 308 | permanent | always keep method | HTTP/1.1
4604 */
4605 const char *redirect_text;
4606 int ret;
4607 size_t content_len = 0;
4608#if defined(MG_SEND_REDIRECT_BODY)
4609 char reply[MG_BUF_LEN];
4610#endif
4611
4612 /* In case redirect_code=0, use 307. */
4613 if (redirect_code == 0) {
4614 redirect_code = 307;
4615 }
4616
4617 /* In case redirect_code is none of the above, return error. */
4618 if ((redirect_code != 301) && (redirect_code != 302)
4619 && (redirect_code != 303) && (redirect_code != 307)
4620 && (redirect_code != 308)) {
4621 /* Parameter error */
4622 return -2;
4623 }
4624
4625 /* Get proper text for response code */
4626 redirect_text = mg_get_response_code_text(conn, redirect_code);
4627
4628 /* If target_url is not defined, redirect to "/". */
4629 if ((target_url == NULL) || (*target_url == 0)) {
4630 target_url = "/";
4631 }
4632
4633#if defined(MG_SEND_REDIRECT_BODY)
4634 /* TODO: condition name? */
4635
4636 /* Prepare a response body with a hyperlink.
4637 *
4638 * According to RFC2616 (and RFC1945 before):
4639 * Unless the request method was HEAD, the entity of the
4640 * response SHOULD contain a short hypertext note with a hyperlink to
4641 * the new URI(s).
4642 *
4643 * However, this response body is not useful in M2M communication.
4644 * Probably the original reason in the RFC was, clients not supporting
4645 * a 30x HTTP redirect could still show the HTML page and let the user
4646 * press the link. Since current browsers support 30x HTTP, the additional
4647 * HTML body does not seem to make sense anymore.
4648 *
4649 * The new RFC7231 (Section 6.4) does no longer recommend it ("SHOULD"),
4650 * but it only notes:
4651 * The server's response payload usually contains a short
4652 * hypertext note with a hyperlink to the new URI(s).
4653 *
4654 * Deactivated by default. If you need the 30x body, set the define.
4655 */
4657 conn,
4658 NULL /* ignore truncation */,
4659 reply,
4660 sizeof(reply),
4661 "<html><head>%s</head><body><a href=\"%s\">%s</a></body></html>",
4662 redirect_text,
4663 target_url,
4664 target_url);
4665 content_len = strlen(reply);
4666#endif
4667
4668 /* Do not send any additional header. For all other options,
4669 * including caching, there are suitable defaults. */
4670 ret = mg_printf(conn,
4671 "HTTP/1.1 %i %s\r\n"
4672 "Location: %s\r\n"
4673 "Content-Length: %u\r\n"
4674 "Connection: %s\r\n\r\n",
4675 redirect_code,
4676 redirect_text,
4677 target_url,
4678 (unsigned int)content_len,
4680
4681#if defined(MG_SEND_REDIRECT_BODY)
4682 /* Send response body */
4683 if (ret > 0) {
4684 /* ... unless it is a HEAD request */
4685 if (0 != strcmp(conn->request_info.request_method, "HEAD")) {
4686 ret = mg_write(conn, reply, content_len);
4687 }
4688 }
4689#endif
4690
4691 return (ret > 0) ? ret : -1;
4692}
4693
4694
4695#if defined(_WIN32)
4696/* Create substitutes for POSIX functions in Win32. */
4697
4698#if defined(GCC_DIAGNOSTIC)
4699/* Show no warning in case system functions are not used. */
4700#pragma GCC diagnostic push
4701#pragma GCC diagnostic ignored "-Wunused-function"
4702#endif
4703
4704
4705static int
4706pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
4707{
4708 (void)unused;
4709 /* Always initialize as PTHREAD_MUTEX_RECURSIVE */
4710 InitializeCriticalSection(&mutex->sec);
4711 return 0;
4712}
4713
4714
4715static int
4716pthread_mutex_destroy(pthread_mutex_t *mutex)
4717{
4718 DeleteCriticalSection(&mutex->sec);
4719 return 0;
4720}
4721
4722
4723static int
4724pthread_mutex_lock(pthread_mutex_t *mutex)
4725{
4726 EnterCriticalSection(&mutex->sec);
4727 return 0;
4728}
4729
4730
4731static int
4732pthread_mutex_unlock(pthread_mutex_t *mutex)
4733{
4734 LeaveCriticalSection(&mutex->sec);
4735 return 0;
4736}
4737
4738
4740static int
4741pthread_cond_init(pthread_cond_t *cv, const void *unused)
4742{
4743 (void)unused;
4744 (void)pthread_mutex_init(&cv->threadIdSec, &pthread_mutex_attr);
4745 cv->waiting_thread = NULL;
4746 return 0;
4747}
4748
4749
4751static int
4752pthread_cond_timedwait(pthread_cond_t *cv,
4753 pthread_mutex_t *mutex,
4754 FUNCTION_MAY_BE_UNUSED const struct timespec *abstime)
4755{
4756 struct mg_workerTLS **ptls,
4757 *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
4758 int ok;
4759 uint64_t nsnow, nswaitabs;
4760 int64_t nswaitrel;
4761 DWORD mswaitrel;
4762
4763 pthread_mutex_lock(&cv->threadIdSec);
4764 /* Add this thread to cv's waiting list */
4765 ptls = &cv->waiting_thread;
4766 for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
4767 ;
4768 tls->next_waiting_thread = NULL;
4769 *ptls = tls;
4770 pthread_mutex_unlock(&cv->threadIdSec);
4771
4772 if (abstime) {
4773 nsnow = mg_get_current_time_ns();
4774 nswaitabs =
4775 (((uint64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
4776 nswaitrel = nswaitabs - nsnow;
4777 if (nswaitrel < 0) {
4778 nswaitrel = 0;
4779 }
4780 mswaitrel = (DWORD)(nswaitrel / 1000000);
4781 } else {
4782 mswaitrel = (DWORD)INFINITE;
4783 }
4784
4785 pthread_mutex_unlock(mutex);
4786 ok = (WAIT_OBJECT_0
4787 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
4788 if (!ok) {
4789 ok = 1;
4790 pthread_mutex_lock(&cv->threadIdSec);
4791 ptls = &cv->waiting_thread;
4792 for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
4793 if (*ptls == tls) {
4794 *ptls = tls->next_waiting_thread;
4795 ok = 0;
4796 break;
4797 }
4798 }
4799 pthread_mutex_unlock(&cv->threadIdSec);
4800 if (ok) {
4801 WaitForSingleObject(tls->pthread_cond_helper_mutex,
4802 (DWORD)INFINITE);
4803 }
4804 }
4805 /* This thread has been removed from cv's waiting list */
4806 pthread_mutex_lock(mutex);
4807
4808 return ok ? 0 : -1;
4809}
4810
4811
4813static int
4814pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
4815{
4816 return pthread_cond_timedwait(cv, mutex, NULL);
4817}
4818
4819
4821static int
4822pthread_cond_signal(pthread_cond_t *cv)
4823{
4824 HANDLE wkup = NULL;
4825 BOOL ok = FALSE;
4826
4827 pthread_mutex_lock(&cv->threadIdSec);
4828 if (cv->waiting_thread) {
4829 wkup = cv->waiting_thread->pthread_cond_helper_mutex;
4830 cv->waiting_thread = cv->waiting_thread->next_waiting_thread;
4831
4832 ok = SetEvent(wkup);
4833 DEBUG_ASSERT(ok);
4834 }
4835 pthread_mutex_unlock(&cv->threadIdSec);
4836
4837 return ok ? 0 : 1;
4838}
4839
4840
4842static int
4843pthread_cond_broadcast(pthread_cond_t *cv)
4844{
4845 pthread_mutex_lock(&cv->threadIdSec);
4846 while (cv->waiting_thread) {
4847 pthread_cond_signal(cv);
4848 }
4849 pthread_mutex_unlock(&cv->threadIdSec);
4850
4851 return 0;
4852}
4853
4854
4856static int
4857pthread_cond_destroy(pthread_cond_t *cv)
4858{
4859 pthread_mutex_lock(&cv->threadIdSec);
4860 DEBUG_ASSERT(cv->waiting_thread == NULL);
4861 pthread_mutex_unlock(&cv->threadIdSec);
4862 pthread_mutex_destroy(&cv->threadIdSec);
4863
4864 return 0;
4865}
4866
4867
4868#if defined(ALTERNATIVE_QUEUE)
4870static void *
4871event_create(void)
4872{
4873 return (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
4874}
4875
4876
4878static int
4879event_wait(void *eventhdl)
4880{
4881 int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE);
4882 return (res == WAIT_OBJECT_0);
4883}
4884
4885
4887static int
4888event_signal(void *eventhdl)
4889{
4890 return (int)SetEvent((HANDLE)eventhdl);
4891}
4892
4893
4895static void
4896event_destroy(void *eventhdl)
4897{
4898 CloseHandle((HANDLE)eventhdl);
4899}
4900#endif
4901
4902
4903#if defined(GCC_DIAGNOSTIC)
4904/* Enable unused function warning again */
4905#pragma GCC diagnostic pop
4906#endif
4907
4908
4909/* For Windows, change all slashes to backslashes in path names. */
4910static void
4911change_slashes_to_backslashes(char *path)
4912{
4913 int i;
4914
4915 for (i = 0; path[i] != '\0'; i++) {
4916 if (path[i] == '/') {
4917 path[i] = '\\';
4918 }
4919
4920 /* remove double backslash (check i > 0 to preserve UNC paths,
4921 * like \\server\file.txt) */
4922 if ((i > 0) && (path[i] == '\\')) {
4923 while ((path[i + 1] == '\\') || (path[i + 1] == '/')) {
4924 (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
4925 }
4926 }
4927 }
4928}
4929
4930
4931static int
4932mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
4933{
4934 int diff;
4935
4936 do {
4937 diff = ((*s1 >= L'A') && (*s1 <= L'Z') ? (*s1 - L'A' + L'a') : *s1)
4938 - ((*s2 >= L'A') && (*s2 <= L'Z') ? (*s2 - L'A' + L'a') : *s2);
4939 s1++;
4940 s2++;
4941 } while ((diff == 0) && (s1[-1] != L'\0'));
4942
4943 return diff;
4944}
4945
4946
4947/* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
4948 * wbuf and wbuf_len is a target buffer and its length. */
4949static void
4950path_to_unicode(const struct mg_connection *conn,
4951 const char *path,
4952 wchar_t *wbuf,
4953 size_t wbuf_len)
4954{
4955 char buf[UTF8_PATH_MAX], buf2[UTF8_PATH_MAX];
4956 wchar_t wbuf2[UTF16_PATH_MAX + 1];
4957 DWORD long_len, err;
4958 int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
4959
4960 mg_strlcpy(buf, path, sizeof(buf));
4961 change_slashes_to_backslashes(buf);
4962
4963 /* Convert to Unicode and back. If doubly-converted string does not
4964 * match the original, something is fishy, reject. */
4965 memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
4966 MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
4967 WideCharToMultiByte(
4968 CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
4969 if (strcmp(buf, buf2) != 0) {
4970 wbuf[0] = L'\0';
4971 }
4972
4973 /* Windows file systems are not case sensitive, but you can still use
4974 * uppercase and lowercase letters (on all modern file systems).
4975 * The server can check if the URI uses the same upper/lowercase
4976 * letters an the file system, effectively making Windows servers
4977 * case sensitive (like Linux servers are). It is still not possible
4978 * to use two files with the same name in different cases on Windows
4979 * (like /a and /A) - this would be possible in Linux.
4980 * As a default, Windows is not case sensitive, but the case sensitive
4981 * file name check can be activated by an additional configuration. */
4982 if (conn) {
4983 if (conn->dom_ctx->config[CASE_SENSITIVE_FILES]
4984 && !mg_strcasecmp(conn->dom_ctx->config[CASE_SENSITIVE_FILES],
4985 "yes")) {
4986 /* Use case sensitive compare function */
4987 fcompare = wcscmp;
4988 }
4989 }
4990 (void)conn; /* conn is currently unused */
4991
4992 /* Only accept a full file path, not a Windows short (8.3) path. */
4993 memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
4994 long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
4995 if (long_len == 0) {
4996 err = GetLastError();
4997 if (err == ERROR_FILE_NOT_FOUND) {
4998 /* File does not exist. This is not always a problem here. */
4999 return;
5000 }
5001 }
5002 if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
5003 /* Short name is used. */
5004 wbuf[0] = L'\0';
5005 }
5006}
5007
5008
5009#if !defined(NO_FILESYSTEMS)
5010/* Get file information, return 1 if file exists, 0 if not */
5011static int
5012mg_stat(const struct mg_connection *conn,
5013 const char *path,
5014 struct mg_file_stat *filep)
5015{
5016 wchar_t wbuf[UTF16_PATH_MAX];
5017 WIN32_FILE_ATTRIBUTE_DATA info;
5018 time_t creation_time;
5019 size_t len;
5020
5021 if (!filep) {
5022 return 0;
5023 }
5024 memset(filep, 0, sizeof(*filep));
5025
5026 if (mg_path_suspicious(conn, path)) {
5027 return 0;
5028 }
5029
5030 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5031 /* Windows happily opens files with some garbage at the end of file name.
5032 * For example, fopen("a.cgi ", "r") on Windows successfully opens
5033 * "a.cgi", despite one would expect an error back. */
5034 len = strlen(path);
5035 if ((len > 0) && (path[len - 1] != ' ') && (path[len - 1] != '.')
5036 && (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0)) {
5037 filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
5038 filep->last_modified =
5039 SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
5040 info.ftLastWriteTime.dwHighDateTime);
5041
5042 /* On Windows, the file creation time can be higher than the
5043 * modification time, e.g. when a file is copied.
5044 * Since the Last-Modified timestamp is used for caching
5045 * it should be based on the most recent timestamp. */
5046 creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
5047 info.ftCreationTime.dwHighDateTime);
5048 if (creation_time > filep->last_modified) {
5049 filep->last_modified = creation_time;
5050 }
5051
5052 filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5053 return 1;
5054 }
5055
5056 return 0;
5057}
5058#endif
5059
5060
5061static int
5062mg_remove(const struct mg_connection *conn, const char *path)
5063{
5064 wchar_t wbuf[UTF16_PATH_MAX];
5065 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5066 return DeleteFileW(wbuf) ? 0 : -1;
5067}
5068
5069
5070static int
5071mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
5072{
5073 wchar_t wbuf[UTF16_PATH_MAX];
5074 (void)mode;
5075 path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
5076 return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
5077}
5078
5079
5080/* Create substitutes for POSIX functions in Win32. */
5081
5082#if defined(GCC_DIAGNOSTIC)
5083/* Show no warning in case system functions are not used. */
5084#pragma GCC diagnostic push
5085#pragma GCC diagnostic ignored "-Wunused-function"
5086#endif
5087
5088
5089/* Implementation of POSIX opendir/closedir/readdir for Windows. */
5091static DIR *
5092mg_opendir(const struct mg_connection *conn, const char *name)
5093{
5094 DIR *dir = NULL;
5095 wchar_t wpath[UTF16_PATH_MAX];
5096 DWORD attrs;
5097
5098 if (name == NULL) {
5099 SetLastError(ERROR_BAD_ARGUMENTS);
5100 } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
5101 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5102 } else {
5103 path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
5104 attrs = GetFileAttributesW(wpath);
5105 if ((wcslen(wpath) + 2 < ARRAY_SIZE(wpath)) && (attrs != 0xFFFFFFFF)
5106 && ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
5107 (void)wcscat(wpath, L"\\*");
5108 dir->handle = FindFirstFileW(wpath, &dir->info);
5109 dir->result.d_name[0] = '\0';
5110 } else {
5111 mg_free(dir);
5112 dir = NULL;
5113 }
5114 }
5115
5116 return dir;
5117}
5118
5119
5121static int
5122mg_closedir(DIR *dir)
5123{
5124 int result = 0;
5125
5126 if (dir != NULL) {
5127 if (dir->handle != INVALID_HANDLE_VALUE)
5128 result = FindClose(dir->handle) ? 0 : -1;
5129
5130 mg_free(dir);
5131 } else {
5132 result = -1;
5133 SetLastError(ERROR_BAD_ARGUMENTS);
5134 }
5135
5136 return result;
5137}
5138
5139
5141static struct dirent *
5142mg_readdir(DIR *dir)
5143{
5144 struct dirent *result = 0;
5145
5146 if (dir) {
5147 if (dir->handle != INVALID_HANDLE_VALUE) {
5148 result = &dir->result;
5149 (void)WideCharToMultiByte(CP_UTF8,
5150 0,
5151 dir->info.cFileName,
5152 -1,
5153 result->d_name,
5154 sizeof(result->d_name),
5155 NULL,
5156 NULL);
5157
5158 if (!FindNextFileW(dir->handle, &dir->info)) {
5159 (void)FindClose(dir->handle);
5160 dir->handle = INVALID_HANDLE_VALUE;
5161 }
5162
5163 } else {
5164 SetLastError(ERROR_FILE_NOT_FOUND);
5165 }
5166 } else {
5167 SetLastError(ERROR_BAD_ARGUMENTS);
5168 }
5169
5170 return result;
5171}
5172
5173
5174#if !defined(HAVE_POLL)
5175#undef POLLIN
5176#undef POLLPRI
5177#undef POLLOUT
5178#undef POLLERR
5179#define POLLIN (1) /* Data ready - read will not block. */
5180#define POLLPRI (2) /* Priority data ready. */
5181#define POLLOUT (4) /* Send queue not full - write will not block. */
5182#define POLLERR (8) /* Error event */
5183
5185static int
5186poll(struct mg_pollfd *pfd, unsigned int n, int milliseconds)
5187{
5188 struct timeval tv;
5189 fd_set rset;
5190 fd_set wset;
5191 fd_set eset;
5192 unsigned int i;
5193 int result;
5194 SOCKET maxfd = 0;
5195
5196 memset(&tv, 0, sizeof(tv));
5197 tv.tv_sec = milliseconds / 1000;
5198 tv.tv_usec = (milliseconds % 1000) * 1000;
5199 FD_ZERO(&rset);
5200 FD_ZERO(&wset);
5201 FD_ZERO(&eset);
5202
5203 for (i = 0; i < n; i++) {
5204 if (pfd[i].events & (POLLIN | POLLOUT | POLLERR)) {
5205 if (pfd[i].events & POLLIN) {
5206 FD_SET(pfd[i].fd, &rset);
5207 }
5208 if (pfd[i].events & POLLOUT) {
5209 FD_SET(pfd[i].fd, &wset);
5210 }
5211 /* Check for errors for any FD in the set */
5212 FD_SET(pfd[i].fd, &eset);
5213 }
5214 pfd[i].revents = 0;
5215
5216 if (pfd[i].fd > maxfd) {
5217 maxfd = pfd[i].fd;
5218 }
5219 }
5220
5221 if ((result = select((int)maxfd + 1, &rset, &wset, &eset, &tv)) > 0) {
5222 for (i = 0; i < n; i++) {
5223 if (FD_ISSET(pfd[i].fd, &rset)) {
5224 pfd[i].revents |= POLLIN;
5225 }
5226 if (FD_ISSET(pfd[i].fd, &wset)) {
5227 pfd[i].revents |= POLLOUT;
5228 }
5229 if (FD_ISSET(pfd[i].fd, &eset)) {
5230 pfd[i].revents |= POLLERR;
5231 }
5232 }
5233 }
5234
5235 /* We should subtract the time used in select from remaining
5236 * "milliseconds", in particular if called from mg_poll with a
5237 * timeout quantum.
5238 * Unfortunately, the remaining time is not stored in "tv" in all
5239 * implementations, so the result in "tv" must be considered undefined.
5240 * See http://man7.org/linux/man-pages/man2/select.2.html */
5241
5242 return result;
5243}
5244#endif /* HAVE_POLL */
5245
5246
5247#if defined(GCC_DIAGNOSTIC)
5248/* Enable unused function warning again */
5249#pragma GCC diagnostic pop
5250#endif
5251
5252
5253static void
5255 const struct mg_connection *conn /* may be null */,
5256 struct mg_context *ctx /* may be null */)
5257{
5258 (void)conn; /* Unused. */
5259 (void)ctx;
5260
5261 (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
5262}
5263
5264
5265int
5267{
5268#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5269 /* Compile-time option to control stack size, e.g.
5270 * -DUSE_STACK_SIZE=16384
5271 */
5272 return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
5273 == ((uintptr_t)(-1L)))
5274 ? -1
5275 : 0);
5276#else
5277 return (
5278 (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
5279 ? -1
5280 : 0);
5281#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5282}
5283
5284
5285/* Start a thread storing the thread context. */
5286static int
5287mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
5288 void *p,
5289 pthread_t *threadidptr)
5290{
5291 uintptr_t uip;
5292 HANDLE threadhandle;
5293 int result = -1;
5294
5295 uip = _beginthreadex(NULL, 0, f, p, 0, NULL);
5296 threadhandle = (HANDLE)uip;
5297 if ((uip != 0) && (threadidptr != NULL)) {
5298 *threadidptr = threadhandle;
5299 result = 0;
5300 }
5301
5302 return result;
5303}
5304
5305
5306/* Wait for a thread to finish. */
5307static int
5308mg_join_thread(pthread_t threadid)
5309{
5310 int result;
5311 DWORD dwevent;
5312
5313 result = -1;
5314 dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE);
5315 if (dwevent == WAIT_FAILED) {
5316 DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
5317 } else {
5318 if (dwevent == WAIT_OBJECT_0) {
5319 CloseHandle(threadid);
5320 result = 0;
5321 }
5322 }
5323
5324 return result;
5325}
5326
5327#if !defined(NO_SSL_DL) && !defined(NO_SSL)
5328/* If SSL is loaded dynamically, dlopen/dlclose is required. */
5329/* Create substitutes for POSIX functions in Win32. */
5330
5331#if defined(GCC_DIAGNOSTIC)
5332/* Show no warning in case system functions are not used. */
5333#pragma GCC diagnostic push
5334#pragma GCC diagnostic ignored "-Wunused-function"
5335#endif
5336
5337
5339static HANDLE
5340dlopen(const char *dll_name, int flags)
5341{
5342 wchar_t wbuf[UTF16_PATH_MAX];
5343 (void)flags;
5344 path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
5345 return LoadLibraryW(wbuf);
5346}
5347
5348
5350static int
5351dlclose(void *handle)
5352{
5353 int result;
5354
5355 if (FreeLibrary((HMODULE)handle) != 0) {
5356 result = 0;
5357 } else {
5358 result = -1;
5359 }
5360
5361 return result;
5362}
5363
5364
5365#if defined(GCC_DIAGNOSTIC)
5366/* Enable unused function warning again */
5367#pragma GCC diagnostic pop
5368#endif
5369
5370#endif
5371
5372
5373#if !defined(NO_CGI)
5374#define SIGKILL (0)
5375
5376
5377static int
5378kill(pid_t pid, int sig_num)
5379{
5380 (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
5381 (void)CloseHandle((HANDLE)pid);
5382 return 0;
5383}
5384
5385
5386#if !defined(WNOHANG)
5387#define WNOHANG (1)
5388#endif
5389
5390
5391static pid_t
5392waitpid(pid_t pid, int *status, int flags)
5393{
5394 DWORD timeout = INFINITE;
5395 DWORD waitres;
5396
5397 (void)status; /* Currently not used by any client here */
5398
5399 if ((flags | WNOHANG) == WNOHANG) {
5400 timeout = 0;
5401 }
5402
5403 waitres = WaitForSingleObject((HANDLE)pid, timeout);
5404 if (waitres == WAIT_OBJECT_0) {
5405 return pid;
5406 }
5407 if (waitres == WAIT_TIMEOUT) {
5408 return 0;
5409 }
5410 return (pid_t)-1;
5411}
5412
5413
5414static void
5415trim_trailing_whitespaces(char *s)
5416{
5417 char *e = s + strlen(s);
5418 while ((e > s) && isspace((unsigned char)e[-1])) {
5419 *(--e) = '\0';
5420 }
5421}
5422
5423
5424static pid_t
5425spawn_process(struct mg_connection *conn,
5426 const char *prog,
5427 char *envblk,
5428 char *envp[],
5429 int fdin[2],
5430 int fdout[2],
5431 int fderr[2],
5432 const char *dir,
5433 unsigned char cgi_config_idx)
5434{
5435 HANDLE me;
5436 char *interp;
5437 char *interp_arg = 0;
5438 char full_dir[UTF8_PATH_MAX], cmdline[UTF8_PATH_MAX], buf[UTF8_PATH_MAX];
5439 int truncated;
5441 STARTUPINFOA si;
5442 PROCESS_INFORMATION pi = {0};
5443
5444 (void)envp;
5445
5446 memset(&si, 0, sizeof(si));
5447 si.cb = sizeof(si);
5448
5449 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
5450 si.wShowWindow = SW_HIDE;
5451
5452 me = GetCurrentProcess();
5453 DuplicateHandle(me,
5454 (HANDLE)_get_osfhandle(fdin[0]),
5455 me,
5456 &si.hStdInput,
5457 0,
5458 TRUE,
5459 DUPLICATE_SAME_ACCESS);
5460 DuplicateHandle(me,
5461 (HANDLE)_get_osfhandle(fdout[1]),
5462 me,
5463 &si.hStdOutput,
5464 0,
5465 TRUE,
5466 DUPLICATE_SAME_ACCESS);
5467 DuplicateHandle(me,
5468 (HANDLE)_get_osfhandle(fderr[1]),
5469 me,
5470 &si.hStdError,
5471 0,
5472 TRUE,
5473 DUPLICATE_SAME_ACCESS);
5474
5475 /* Mark handles that should not be inherited. See
5476 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
5477 */
5478 SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
5479 HANDLE_FLAG_INHERIT,
5480 0);
5481 SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
5482 HANDLE_FLAG_INHERIT,
5483 0);
5484 SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
5485 HANDLE_FLAG_INHERIT,
5486 0);
5487
5488 /* First check, if there is a CGI interpreter configured for all CGI
5489 * scripts. */
5490 interp = conn->dom_ctx->config[CGI_INTERPRETER + cgi_config_idx];
5491 if (interp != NULL) {
5492 /* If there is a configured interpreter, check for additional arguments
5493 */
5494 interp_arg =
5495 conn->dom_ctx->config[CGI_INTERPRETER_ARGS + cgi_config_idx];
5496 } else {
5497 /* Otherwise, the interpreter must be stated in the first line of the
5498 * CGI script file, after a #! (shebang) mark. */
5499 buf[0] = buf[1] = '\0';
5500
5501 /* Get the full script path */
5503 conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
5504
5505 if (truncated) {
5506 pi.hProcess = (pid_t)-1;
5507 goto spawn_cleanup;
5508 }
5509
5510 /* Open the script file, to read the first line */
5511 if (mg_fopen(conn, cmdline, MG_FOPEN_MODE_READ, &file)) {
5512
5513 /* Read the first line of the script into the buffer */
5514 mg_fgets(buf, sizeof(buf), &file);
5515 (void)mg_fclose(&file.access); /* ignore error on read only file */
5516 buf[sizeof(buf) - 1] = '\0';
5517 }
5518
5519 if ((buf[0] == '#') && (buf[1] == '!')) {
5520 trim_trailing_whitespaces(buf + 2);
5521 } else {
5522 buf[2] = '\0';
5523 }
5524 interp = buf + 2;
5525 }
5526
5527 GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
5528
5529 if (interp[0] != '\0') {
5530 /* This is an interpreted script file. We must call the interpreter. */
5531 if ((interp_arg != 0) && (interp_arg[0] != 0)) {
5532 mg_snprintf(conn,
5533 &truncated,
5534 cmdline,
5535 sizeof(cmdline),
5536 "\"%s\" %s \"%s\\%s\"",
5537 interp,
5538 interp_arg,
5539 full_dir,
5540 prog);
5541 } else {
5542 mg_snprintf(conn,
5543 &truncated,
5544 cmdline,
5545 sizeof(cmdline),
5546 "\"%s\" \"%s\\%s\"",
5547 interp,
5548 full_dir,
5549 prog);
5550 }
5551 } else {
5552 /* This is (probably) a compiled program. We call it directly. */
5553 mg_snprintf(conn,
5554 &truncated,
5555 cmdline,
5556 sizeof(cmdline),
5557 "\"%s\\%s\"",
5558 full_dir,
5559 prog);
5560 }
5561
5562 if (truncated) {
5563 pi.hProcess = (pid_t)-1;
5564 goto spawn_cleanup;
5565 }
5566
5567 DEBUG_TRACE("Running [%s]", cmdline);
5568 if (CreateProcessA(NULL,
5569 cmdline,
5570 NULL,
5571 NULL,
5572 TRUE,
5573 CREATE_NEW_PROCESS_GROUP,
5574 envblk,
5575 NULL,
5576 &si,
5577 &pi)
5578 == 0) {
5580 conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
5581 pi.hProcess = (pid_t)-1;
5582 /* goto spawn_cleanup; */
5583 }
5584
5585spawn_cleanup:
5586 (void)CloseHandle(si.hStdOutput);
5587 (void)CloseHandle(si.hStdError);
5588 (void)CloseHandle(si.hStdInput);
5589 if (pi.hThread != NULL) {
5590 (void)CloseHandle(pi.hThread);
5591 }
5592
5593 return (pid_t)pi.hProcess;
5594}
5595#endif /* !NO_CGI */
5596
5597
5598static int
5600{
5601 unsigned long non_blocking = 0;
5602 return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5603}
5604
5605
5606static int
5608{
5609 unsigned long non_blocking = 1;
5610 return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5611}
5612
5613
5614#else
5615
5616
5617#if !defined(NO_FILESYSTEMS)
5618static int
5619mg_stat(const struct mg_connection *conn,
5620 const char *path,
5621 struct mg_file_stat *filep)
5622{
5623 struct stat st;
5624 if (!filep) {
5625 return 0;
5626 }
5627 memset(filep, 0, sizeof(*filep));
5628
5629 if (mg_path_suspicious(conn, path)) {
5630 return 0;
5631 }
5632
5633 if (0 == stat(path, &st)) {
5634 filep->size = (uint64_t)(st.st_size);
5635 filep->last_modified = st.st_mtime;
5636 filep->is_directory = S_ISDIR(st.st_mode);
5637 return 1;
5638 }
5639
5640 return 0;
5641}
5642#endif /* NO_FILESYSTEMS */
5643
5644
5645static void
5647 const struct mg_connection *conn /* may be null */,
5648 struct mg_context *ctx /* may be null */)
5649{
5650#if defined(__ZEPHYR__)
5651 (void)fd;
5652 (void)conn;
5653 (void)ctx;
5654#else
5655 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
5656 if (conn || ctx) {
5657 struct mg_connection fc;
5658 mg_cry_internal((conn ? conn : fake_connection(&fc, ctx)),
5659 "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
5660 __func__,
5661 strerror(ERRNO));
5662 }
5663 }
5664#endif
5665}
5666
5667
5668int
5670{
5671 pthread_t thread_id;
5672 pthread_attr_t attr;
5673 int result;
5674
5675 (void)pthread_attr_init(&attr);
5676 (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5677
5678#if defined(__ZEPHYR__)
5679 pthread_attr_setstack(&attr, &civetweb_main_stack, ZEPHYR_STACK_SIZE);
5680#elif defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5681 /* Compile-time option to control stack size,
5682 * e.g. -DUSE_STACK_SIZE=16384 */
5683 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5684#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5685
5686 result = pthread_create(&thread_id, &attr, func, param);
5687 pthread_attr_destroy(&attr);
5688
5689 return result;
5690}
5691
5692
5693/* Start a thread storing the thread context. */
5694static int
5696 void *param,
5697 pthread_t *threadidptr)
5698{
5699 pthread_t thread_id;
5700 pthread_attr_t attr;
5701 int result;
5702
5703 (void)pthread_attr_init(&attr);
5704
5705#if defined(__ZEPHYR__)
5706 pthread_attr_setstack(&attr,
5707 &civetweb_worker_stacks[zephyr_worker_stack_index++],
5708 ZEPHYR_STACK_SIZE);
5709#elif defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5710 /* Compile-time option to control stack size,
5711 * e.g. -DUSE_STACK_SIZE=16384 */
5712 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5713#endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
5714
5715 result = pthread_create(&thread_id, &attr, func, param);
5716 pthread_attr_destroy(&attr);
5717 if ((result == 0) && (threadidptr != NULL)) {
5718 *threadidptr = thread_id;
5719 }
5720 return result;
5721}
5722
5723
5724/* Wait for a thread to finish. */
5725static int
5726mg_join_thread(pthread_t threadid)
5727{
5728 int result;
5729
5730 result = pthread_join(threadid, NULL);
5731 return result;
5732}
5733
5734
5735#if !defined(NO_CGI)
5736static pid_t
5738 const char *prog,
5739 char *envblk,
5740 char *envp[],
5741 int fdin[2],
5742 int fdout[2],
5743 int fderr[2],
5744 const char *dir,
5745 unsigned char cgi_config_idx)
5746{
5747 pid_t pid;
5748 const char *interp;
5749
5750 (void)envblk;
5751
5752 if ((pid = fork()) == -1) {
5753 /* Parent */
5754 mg_cry_internal(conn, "%s: fork(): %s", __func__, strerror(ERRNO));
5755 } else if (pid != 0) {
5756 /* Make sure children close parent-side descriptors.
5757 * The caller will close the child-side immediately. */
5758 set_close_on_exec(fdin[1], conn, NULL); /* stdin write */
5759 set_close_on_exec(fdout[0], conn, NULL); /* stdout read */
5760 set_close_on_exec(fderr[0], conn, NULL); /* stderr read */
5761 } else {
5762 /* Child */
5763 if (chdir(dir) != 0) {
5765 conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
5766 } else if (dup2(fdin[0], 0) == -1) {
5767 mg_cry_internal(conn,
5768 "%s: dup2(%d, 0): %s",
5769 __func__,
5770 fdin[0],
5771 strerror(ERRNO));
5772 } else if (dup2(fdout[1], 1) == -1) {
5773 mg_cry_internal(conn,
5774 "%s: dup2(%d, 1): %s",
5775 __func__,
5776 fdout[1],
5777 strerror(ERRNO));
5778 } else if (dup2(fderr[1], 2) == -1) {
5779 mg_cry_internal(conn,
5780 "%s: dup2(%d, 2): %s",
5781 __func__,
5782 fderr[1],
5783 strerror(ERRNO));
5784 } else {
5785 struct sigaction sa;
5786
5787 /* Keep stderr and stdout in two different pipes.
5788 * Stdout will be sent back to the client,
5789 * stderr should go into a server error log. */
5790 (void)close(fdin[0]);
5791 (void)close(fdout[1]);
5792 (void)close(fderr[1]);
5793
5794 /* Close write end fdin and read end fdout and fderr */
5795 (void)close(fdin[1]);
5796 (void)close(fdout[0]);
5797 (void)close(fderr[0]);
5798
5799 /* After exec, all signal handlers are restored to their default
5800 * values, with one exception of SIGCHLD. According to
5801 * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler
5802 * will leave unchanged after exec if it was set to be ignored.
5803 * Restore it to default action. */
5804 memset(&sa, 0, sizeof(sa));
5805 sa.sa_handler = SIG_DFL;
5806 sigaction(SIGCHLD, &sa, NULL);
5807
5808 interp = conn->dom_ctx->config[CGI_INTERPRETER + cgi_config_idx];
5809 if (interp == NULL) {
5810 /* no interpreter configured, call the programm directly */
5811 (void)execle(prog, prog, NULL, envp);
5812 mg_cry_internal(conn,
5813 "%s: execle(%s): %s",
5814 __func__,
5815 prog,
5816 strerror(ERRNO));
5817 } else {
5818 /* call the configured interpreter */
5819 const char *interp_args =
5820 conn->dom_ctx
5821 ->config[CGI_INTERPRETER_ARGS + cgi_config_idx];
5822
5823 if ((interp_args != NULL) && (interp_args[0] != 0)) {
5824 (void)execle(interp, interp, interp_args, prog, NULL, envp);
5825 } else {
5826 (void)execle(interp, interp, prog, NULL, envp);
5827 }
5828 mg_cry_internal(conn,
5829 "%s: execle(%s %s): %s",
5830 __func__,
5831 interp,
5832 prog,
5833 strerror(ERRNO));
5834 }
5835 }
5836 exit(EXIT_FAILURE);
5837 }
5838
5839 return pid;
5840}
5841#endif /* !NO_CGI */
5842
5843
5844static int
5846{
5847 int flags = fcntl(sock, F_GETFL, 0);
5848 if (flags < 0) {
5849 return -1;
5850 }
5851
5852 if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) {
5853 return -1;
5854 }
5855 return 0;
5856}
5857
5858static int
5860{
5861 int flags = fcntl(sock, F_GETFL, 0);
5862 if (flags < 0) {
5863 return -1;
5864 }
5865
5866 if (fcntl(sock, F_SETFL, flags & (~(int)(O_NONBLOCK))) < 0) {
5867 return -1;
5868 }
5869 return 0;
5870}
5871#endif /* _WIN32 / else */
5872
5873/* End of initial operating system specific define block. */
5874
5875
5876/* Get a random number (independent of C rand function) */
5877static uint64_t
5879{
5880 static uint64_t lfsr = 0; /* Linear feedback shift register */
5881 static uint64_t lcg = 0; /* Linear congruential generator */
5882 uint64_t now = mg_get_current_time_ns();
5883
5884 if (lfsr == 0) {
5885 /* lfsr will be only 0 if has not been initialized,
5886 * so this code is called only once. */
5887 lfsr = mg_get_current_time_ns();
5888 lcg = mg_get_current_time_ns();
5889 } else {
5890 /* Get the next step of both random number generators. */
5891 lfsr = (lfsr >> 1)
5892 | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
5893 << 63);
5894 lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
5895 }
5896
5897 /* Combining two pseudo-random number generators and a high resolution
5898 * part
5899 * of the current server time will make it hard (impossible?) to guess
5900 * the
5901 * next number. */
5902 return (lfsr ^ lcg ^ now);
5903}
5904
5905
5906static int
5907mg_poll(struct mg_pollfd *pfd,
5908 unsigned int n,
5909 int milliseconds,
5910 const stop_flag_t *stop_flag)
5911{
5912 /* Call poll, but only for a maximum time of a few seconds.
5913 * This will allow to stop the server after some seconds, instead
5914 * of having to wait for a long socket timeout. */
5915 int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
5916
5917 int check_pollerr = 0;
5918 if ((n == 1) && ((pfd[0].events & POLLERR) == 0)) {
5919 /* If we wait for only one file descriptor, wait on error as well */
5920 pfd[0].events |= POLLERR;
5921 check_pollerr = 1;
5922 }
5923
5924 do {
5925 int result;
5926
5927 if (!STOP_FLAG_IS_ZERO(&*stop_flag)) {
5928 /* Shut down signal */
5929 return -2;
5930 }
5931
5932 if ((milliseconds >= 0) && (milliseconds < ms_now)) {
5933 ms_now = milliseconds;
5934 }
5935
5936 result = poll(pfd, n, ms_now);
5937 if (result != 0) {
5938 /* Poll returned either success (1) or error (-1).
5939 * Forward both to the caller. */
5940 if ((check_pollerr)
5941 && ((pfd[0].revents & (POLLIN | POLLOUT | POLLERR))
5942 == POLLERR)) {
5943 /* One and only file descriptor returned error */
5944 return -1;
5945 }
5946 return result;
5947 }
5948
5949 /* Poll returned timeout (0). */
5950 if (milliseconds > 0) {
5951 milliseconds -= ms_now;
5952 }
5953
5954 } while (milliseconds > 0);
5955
5956 /* timeout: return 0 */
5957 return 0;
5958}
5959
5960
5961/* Write data to the IO channel - opened file descriptor, socket or SSL
5962 * descriptor.
5963 * Return value:
5964 * >=0 .. number of bytes successfully written
5965 * -1 .. timeout
5966 * -2 .. error
5967 */
5968static int
5970 FILE *fp,
5971 SOCKET sock,
5972 SSL *ssl,
5973 const char *buf,
5974 int len,
5975 double timeout)
5976{
5977 uint64_t start = 0, now = 0, timeout_ns = 0;
5978 int n, err;
5979 unsigned ms_wait = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
5980
5981#if defined(_WIN32)
5982 typedef int len_t;
5983#else
5984 typedef size_t len_t;
5985#endif
5986
5987 if (timeout > 0) {
5988 now = mg_get_current_time_ns();
5989 start = now;
5990 timeout_ns = (uint64_t)(timeout * 1.0E9);
5991 }
5992
5993 if (ctx == NULL) {
5994 return -2;
5995 }
5996
5997#if defined(NO_SSL) && !defined(USE_MBEDTLS)
5998 if (ssl) {
5999 return -2;
6000 }
6001#endif
6002
6003 /* Try to read until it succeeds, fails, times out, or the server
6004 * shuts down. */
6005 for (;;) {
6006
6007#if defined(USE_MBEDTLS)
6008 if (ssl != NULL) {
6009 n = mbed_ssl_write(ssl, (const unsigned char *)buf, len);
6010 if (n <= 0) {
6011 if ((n == MBEDTLS_ERR_SSL_WANT_READ)
6012 || (n == MBEDTLS_ERR_SSL_WANT_WRITE)
6013 ||