mirror of
https://git.swurl.xyz/swirl/pacebin.git
synced 2024-11-25 06:19:19 +02:00
738 lines
23 KiB
C
738 lines
23 KiB
C
|
// Copyright (c) 2004-2013 Sergey Lyubka
|
||
|
// Copyright (c) 2013-2021 Cesanta Software Limited
|
||
|
// All rights reserved
|
||
|
//
|
||
|
// This software is dual-licensed: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU General Public License version 2 as
|
||
|
// published by the Free Software Foundation. For the terms of this
|
||
|
// license, see <http://www.gnu.org/licenses/>.
|
||
|
//
|
||
|
// You are free to use this software under the terms of the GNU General
|
||
|
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
// See the GNU General Public License for more details.
|
||
|
//
|
||
|
// Alternatively, you can license this software under a commercial
|
||
|
// license, as set out in <https://www.cesanta.com/license>.
|
||
|
|
||
|
#ifndef MONGOOSE_H
|
||
|
#define MONGOOSE_H
|
||
|
|
||
|
#define MG_VERSION "7.4"
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_ENABLE_SOCKET
|
||
|
#define MG_ENABLE_SOCKET 1
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_ENABLE_IPV6
|
||
|
#define MG_ENABLE_IPV6 0
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_ENABLE_LOG
|
||
|
#define MG_ENABLE_LOG 1
|
||
|
#endif
|
||
|
|
||
|
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
|
||
|
#ifndef MG_ENABLE_WINSOCK
|
||
|
#define MG_ENABLE_WINSOCK 1
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_ENABLE_DIRLIST
|
||
|
#define MG_ENABLE_DIRLIST 0
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_ENABLE_CUSTOM_RANDOM
|
||
|
#define MG_ENABLE_CUSTOM_RANDOM 0
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_ENABLE_PACKED_FS
|
||
|
#define MG_ENABLE_PACKED_FS 0
|
||
|
#endif
|
||
|
|
||
|
// Granularity of the send/recv IO buffer growth
|
||
|
#ifndef MG_IO_SIZE
|
||
|
#define MG_IO_SIZE 2048
|
||
|
#endif
|
||
|
|
||
|
// Maximum size of the recv IO buffer
|
||
|
#ifndef MG_MAX_RECV_BUF_SIZE
|
||
|
#define MG_MAX_RECV_BUF_SIZE (3 * 1024 * 1024)
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_MAX_HTTP_HEADERS
|
||
|
#define MG_MAX_HTTP_HEADERS 40
|
||
|
#endif
|
||
|
|
||
|
#ifndef MG_PATH_MAX
|
||
|
#define MG_PATH_MAX PATH_MAX
|
||
|
#endif
|
||
|
|
||
|
#define MG_ARCH_CUSTOM 0
|
||
|
#define MG_ARCH_UNIX 1
|
||
|
#define MG_ARCH_WIN32 2
|
||
|
#define MG_ARCH_ESP32 3
|
||
|
#define MG_ARCH_ESP8266 4
|
||
|
#define MG_ARCH_FREERTOS_TCP 5
|
||
|
#define MG_ARCH_FREERTOS_LWIP 6
|
||
|
|
||
|
#if !defined(MG_ARCH)
|
||
|
#if defined(__unix__) || defined(__APPLE__)
|
||
|
#define MG_ARCH MG_ARCH_UNIX
|
||
|
#elif defined(_WIN32)
|
||
|
#define MG_ARCH MG_ARCH_WIN32
|
||
|
#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
|
||
|
#define MG_ARCH MG_ARCH_ESP8266
|
||
|
#elif defined(ESP_PLATFORM)
|
||
|
#define MG_ARCH MG_ARCH_ESP32
|
||
|
#elif defined(FREERTOS_IP_H)
|
||
|
#define MG_ARCH MG_ARCH_FREERTOS_TCP
|
||
|
#endif
|
||
|
|
||
|
#if !defined(MG_ARCH)
|
||
|
#error "MG_ARCH is not specified and we couldn't guess it."
|
||
|
#endif
|
||
|
#endif // !defined(MG_ARCH)
|
||
|
|
||
|
#if !defined(PRINTF_LIKE)
|
||
|
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||
|
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||
|
#else
|
||
|
#define PRINTF_LIKE(f, a)
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_CUSTOM
|
||
|
#include <mongoose_custom.h>
|
||
|
#endif
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_ESP32
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <dirent.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <limits.h>
|
||
|
#include <netdb.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#define MG_DIRSEP '/'
|
||
|
#define MG_INT64_FMT "%lld"
|
||
|
#ifndef MG_PATH_MAX
|
||
|
#define MG_PATH_MAX 128
|
||
|
#endif
|
||
|
#undef MG_ENABLE_DIRLIST
|
||
|
#define MG_ENABLE_DIRLIST 1
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_ESP8266
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <dirent.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <limits.h>
|
||
|
#include <netdb.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#include <esp_system.h>
|
||
|
|
||
|
#define MG_DIRSEP '/'
|
||
|
#define MG_INT64_FMT "%lld"
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#if defined(__GNUC__)
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/time.h>
|
||
|
#else
|
||
|
typedef long suseconds_t;
|
||
|
struct timeval {
|
||
|
time_t tv_sec;
|
||
|
suseconds_t tv_usec;
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
#include <FreeRTOS.h>
|
||
|
#include <task.h>
|
||
|
|
||
|
#include <lwip/sockets.h>
|
||
|
|
||
|
#if LWIP_SOCKET != 1
|
||
|
// Sockets support disabled in LWIP by default
|
||
|
#error Set LWIP_SOCKET variable to 1 (in lwipopts.h)
|
||
|
#endif
|
||
|
|
||
|
#if LWIP_POSIX_SOCKETS_IO_NAMES != 0
|
||
|
// LWIP_POSIX_SOCKETS_IO_NAMES must be disabled in posix-compatible OS
|
||
|
// enviroment (freertos mimics to one) otherwise names like `read` and `write`
|
||
|
// conflict
|
||
|
#error LWIP_POSIX_SOCKETS_IO_NAMES must be set to 0 (in lwipopts.h) for FreeRTOS
|
||
|
#endif
|
||
|
|
||
|
#define MG_INT64_FMT "%lld"
|
||
|
#define MG_DIRSEP '/'
|
||
|
|
||
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||
|
static inline void *mg_calloc(int cnt, size_t size) {
|
||
|
void *p = pvPortMalloc(cnt * size);
|
||
|
if (p != NULL) memset(p, 0, size);
|
||
|
return p;
|
||
|
}
|
||
|
#define calloc(a, b) mg_calloc((a), (b))
|
||
|
#define free(a) vPortFree(a)
|
||
|
#define malloc(a) pvPortMalloc(a)
|
||
|
|
||
|
#define gmtime_r(a, b) gmtime(a)
|
||
|
|
||
|
#endif // MG_ARCH == MG_ARCH_FREERTOS_LWIP
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <errno.h>
|
||
|
#include <limits.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#include <FreeRTOS.h>
|
||
|
#include <FreeRTOS_IP.h>
|
||
|
#include <FreeRTOS_Sockets.h>
|
||
|
#include <task.h>
|
||
|
|
||
|
#define MG_INT64_FMT "%lld"
|
||
|
#define MG_DIRSEP '/'
|
||
|
|
||
|
// Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing
|
||
|
// with FreeRTOS_ prefix, is beyond me
|
||
|
#define IPPROTO_TCP FREERTOS_IPPROTO_TCP
|
||
|
#define IPPROTO_UDP FREERTOS_IPPROTO_UDP
|
||
|
#define AF_INET FREERTOS_AF_INET
|
||
|
#define SOCK_STREAM FREERTOS_SOCK_STREAM
|
||
|
#define SOCK_DGRAM FREERTOS_SOCK_DGRAM
|
||
|
#define SO_BROADCAST 0
|
||
|
#define SO_ERROR 0
|
||
|
#define SOL_SOCKET 0
|
||
|
#define SO_REUSEADDR 0
|
||
|
#define sockaddr_in freertos_sockaddr
|
||
|
#define sockaddr freertos_sockaddr
|
||
|
#define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
|
||
|
#define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
|
||
|
#define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
|
||
|
#define listen(a, b) FreeRTOS_listen((a), (b))
|
||
|
#define socket(a, b, c) FreeRTOS_socket((a), (b), (c))
|
||
|
#define send(a, b, c, d) FreeRTOS_send((a), (b), (c), (d))
|
||
|
#define recv(a, b, c, d) FreeRTOS_recv((a), (b), (c), (d))
|
||
|
#define setsockopt(a, b, c, d, e) FreeRTOS_setsockopt((a), (b), (c), (d), (e))
|
||
|
#define sendto(a, b, c, d, e, f) FreeRTOS_sendto((a), (b), (c), (d), (e), (f))
|
||
|
#define recvfrom(a, b, c, d, e, f) \
|
||
|
FreeRTOS_recvfrom((a), (b), (c), (d), (e), (f))
|
||
|
#define closesocket(x) FreeRTOS_closesocket(x)
|
||
|
#define gethostbyname(x) FreeRTOS_gethostbyname(x)
|
||
|
#define getsockname(a, b, c) (-1)
|
||
|
|
||
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||
|
static inline void *mg_calloc(int cnt, size_t size) {
|
||
|
void *p = pvPortMalloc(cnt * size);
|
||
|
if (p != NULL) memset(p, 0, size);
|
||
|
return p;
|
||
|
}
|
||
|
#define calloc(a, b) mg_calloc((a), (b))
|
||
|
#define free(a) vPortFree(a)
|
||
|
#define malloc(a) pvPortMalloc(a)
|
||
|
|
||
|
#define gmtime_r(a, b) gmtime(a)
|
||
|
|
||
|
#if !defined(__GNUC__)
|
||
|
// copied from GCC on ARM; for some reason useconds are signed
|
||
|
typedef long suseconds_t;
|
||
|
struct timeval {
|
||
|
time_t tv_sec;
|
||
|
suseconds_t tv_usec;
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
#ifndef EINPROGRESS
|
||
|
#define EINPROGRESS pdFREERTOS_ERRNO_EINPROGRESS
|
||
|
#endif
|
||
|
#ifndef EWOULDBLOCK
|
||
|
#define EWOULDBLOCK pdFREERTOS_ERRNO_EWOULDBLOCK
|
||
|
#endif
|
||
|
#ifndef EAGAIN
|
||
|
#define EAGAIN pdFREERTOS_ERRNO_EAGAIN
|
||
|
#endif
|
||
|
#ifndef EINTR
|
||
|
#define EINTR pdFREERTOS_ERRNO_EINTR
|
||
|
#endif
|
||
|
|
||
|
#endif // MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_UNIX
|
||
|
|
||
|
#define _DARWIN_UNLIMITED_SELECT 1 // No limit on file descriptors
|
||
|
|
||
|
#include <arpa/inet.h>
|
||
|
#include <ctype.h>
|
||
|
#include <dirent.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <inttypes.h>
|
||
|
#include <limits.h>
|
||
|
#include <netdb.h>
|
||
|
#include <netinet/tcp.h>
|
||
|
#include <signal.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/select.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <time.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#define MG_DIRSEP '/'
|
||
|
#define MG_INT64_FMT "%" PRId64
|
||
|
#undef MG_ENABLE_DIRLIST
|
||
|
#define MG_ENABLE_DIRLIST 1
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if MG_ARCH == MG_ARCH_WIN32
|
||
|
|
||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#endif
|
||
|
|
||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||
|
#define _CRT_SECURE_NO_WARNINGS
|
||
|
#endif
|
||
|
|
||
|
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
|
||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||
|
#endif
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <limits.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||
|
#define __func__ ""
|
||
|
typedef __int64 int64_t;
|
||
|
typedef unsigned __int64 uint64_t;
|
||
|
typedef unsigned char uint8_t;
|
||
|
typedef char int8_t;
|
||
|
typedef unsigned short uint16_t;
|
||
|
typedef short int16_t;
|
||
|
typedef unsigned int uint32_t;
|
||
|
typedef int int32_t;
|
||
|
typedef enum { false = 0, true = 1 } bool;
|
||
|
#else
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <ws2tcpip.h>
|
||
|
#endif
|
||
|
|
||
|
#include <winsock2.h>
|
||
|
|
||
|
// Protect from calls like std::snprintf in app code
|
||
|
// See https://github.com/cesanta/mongoose/issues/1047
|
||
|
#ifndef __cplusplus
|
||
|
#define snprintf _snprintf
|
||
|
#define vsnprintf _vsnprintf
|
||
|
#define strdup(x) _strdup(x)
|
||
|
#endif
|
||
|
|
||
|
typedef unsigned suseconds_t;
|
||
|
typedef int socklen_t;
|
||
|
#define MG_DIRSEP '\\'
|
||
|
#ifndef PATH_MAX
|
||
|
#define PATH_MAX MAX_PATH
|
||
|
#endif
|
||
|
#ifndef EINPROGRESS
|
||
|
#define EINPROGRESS WSAEINPROGRESS
|
||
|
#endif
|
||
|
#ifndef EWOULDBLOCK
|
||
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||
|
#endif
|
||
|
|
||
|
#ifndef va_copy
|
||
|
#ifdef __va_copy
|
||
|
#define va_copy __va_copy
|
||
|
#else
|
||
|
#define va_copy(x, y) (x) = (y)
|
||
|
#endif
|
||
|
#endif
|
||
|
#ifndef S_ISDIR
|
||
|
#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
|
||
|
#endif
|
||
|
|
||
|
#define MG_INT64_FMT "%I64d"
|
||
|
|
||
|
#undef MG_ENABLE_DIRLIST
|
||
|
#define MG_ENABLE_DIRLIST 1
|
||
|
|
||
|
// https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
|
||
|
static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
|
||
|
(void) tm;
|
||
|
return gmtime(t);
|
||
|
}
|
||
|
|
||
|
static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
|
||
|
(void) tm;
|
||
|
return localtime(t);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
struct mg_str {
|
||
|
const char *ptr; // Pointer to string data
|
||
|
size_t len; // String len
|
||
|
};
|
||
|
|
||
|
#define MG_NULL_STR \
|
||
|
{ NULL, 0 }
|
||
|
|
||
|
// Using macro to avoid shadowing C++ struct constructor, see #1298
|
||
|
#define mg_str(s) mg_str_s(s)
|
||
|
|
||
|
struct mg_str mg_str(const char *s);
|
||
|
struct mg_str mg_str_n(const char *s, size_t n);
|
||
|
int mg_lower(const char *s);
|
||
|
int mg_ncasecmp(const char *s1, const char *s2, size_t len);
|
||
|
int mg_casecmp(const char *s1, const char *s2);
|
||
|
int mg_vcmp(const struct mg_str *s1, const char *s2);
|
||
|
int mg_vcasecmp(const struct mg_str *str1, const char *str2);
|
||
|
int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
|
||
|
struct mg_str mg_strstrip(struct mg_str s);
|
||
|
struct mg_str mg_strdup(const struct mg_str s);
|
||
|
const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
|
||
|
|
||
|
#if MG_ENABLE_LOG
|
||
|
#define LOG(level, args) \
|
||
|
do { \
|
||
|
if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \
|
||
|
} while (0)
|
||
|
enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG };
|
||
|
bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
|
||
|
void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||
|
void mg_log_set(const char *spec);
|
||
|
void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
|
||
|
#else
|
||
|
#define LOG(level, args) (void) 0
|
||
|
#define mg_log_set(x) (void) (x)
|
||
|
#endif
|
||
|
|
||
|
struct mg_timer {
|
||
|
unsigned long period_ms; // Timer period in milliseconds
|
||
|
unsigned flags; // Possible flags values below
|
||
|
void (*fn)(void *); // Function to call
|
||
|
void *arg; // Function argument
|
||
|
unsigned long expire; // Expiration timestamp in milliseconds
|
||
|
struct mg_timer *next; // Linkage in g_timers list
|
||
|
};
|
||
|
|
||
|
#define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
|
||
|
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
||
|
|
||
|
extern struct mg_timer *g_timers; // Global list of timers
|
||
|
|
||
|
void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
|
||
|
void (*fn)(void *), void *);
|
||
|
void mg_timer_free(struct mg_timer *);
|
||
|
void mg_timer_poll(unsigned long uptime_ms);
|
||
|
|
||
|
char *mg_file_read(const char *path, size_t *size);
|
||
|
bool mg_file_write(const char *path, const void *buf, size_t len);
|
||
|
bool mg_file_printf(const char *path, const char *fmt, ...);
|
||
|
void mg_random(void *buf, size_t len);
|
||
|
bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
|
||
|
bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
|
||
|
uint16_t mg_ntohs(uint16_t net);
|
||
|
uint32_t mg_ntohl(uint32_t net);
|
||
|
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
||
|
char *mg_hexdump(const void *buf, size_t len);
|
||
|
char *mg_hex(const void *buf, size_t len, char *dst);
|
||
|
void mg_unhex(const char *buf, size_t len, unsigned char *to);
|
||
|
unsigned long mg_unhexn(const char *s, size_t len);
|
||
|
int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
|
||
|
int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||
|
int64_t mg_to64(struct mg_str str);
|
||
|
int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
||
|
double mg_time(void);
|
||
|
unsigned long mg_millis(void);
|
||
|
void mg_usleep(unsigned long usecs);
|
||
|
|
||
|
#define mg_htons(x) mg_ntohs(x)
|
||
|
#define mg_htonl(x) mg_ntohl(x)
|
||
|
|
||
|
// Expands to a string representation of its argument: e.g.
|
||
|
// MG_STRINGIFY_LITERAL(5) expands to "5"
|
||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||
|
#define MG_STRINGIFY_LITERAL(...) #__VA_ARGS__
|
||
|
#else
|
||
|
#define MG_STRINGIFY_LITERAL(x) #x
|
||
|
#endif
|
||
|
// Expands to a string representation of its argument, which can be a macro:
|
||
|
// #define FOO 123
|
||
|
// MG_STRINGIFY_MACRO(FOO) // Expands to 123
|
||
|
#define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
|
||
|
|
||
|
// Linked list management macros
|
||
|
#define LIST_ADD_HEAD(type_, head_, elem_) \
|
||
|
do { \
|
||
|
(elem_)->next = (*head_); \
|
||
|
*(head_) = (elem_); \
|
||
|
} while (0)
|
||
|
|
||
|
#define LIST_ADD_TAIL(type_, head_, elem_) \
|
||
|
do { \
|
||
|
type_ **h = head_; \
|
||
|
while (*h != NULL) h = &(*h)->next; \
|
||
|
*h = (elem_); \
|
||
|
} while (0)
|
||
|
|
||
|
#define LIST_DELETE(type_, head_, elem_) \
|
||
|
do { \
|
||
|
type_ **h = head_; \
|
||
|
while (*h != (elem_)) h = &(*h)->next; \
|
||
|
*h = (elem_)->next; \
|
||
|
} while (0)
|
||
|
|
||
|
enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
|
||
|
|
||
|
// Filesystem API functions
|
||
|
// stat() returns MG_FS_* flags and populates file size and modification time
|
||
|
// list() calls fn() for every directory entry, allowing to list a directory
|
||
|
struct mg_fs {
|
||
|
int (*stat)(const char *path, size_t *size, time_t *mtime);
|
||
|
void (*list)(const char *path, void (*fn)(const char *, void *), void *);
|
||
|
struct mg_fd *(*open)(const char *path, int flags); // Open file
|
||
|
void (*close)(struct mg_fd *fd); // Close file
|
||
|
size_t (*read)(void *fd, void *buf, size_t len); // Read file
|
||
|
size_t (*write)(void *fd, const void *buf, size_t len); // Write file
|
||
|
size_t (*seek)(void *fd, size_t offset); // Set file position
|
||
|
};
|
||
|
|
||
|
// File descriptor
|
||
|
struct mg_fd {
|
||
|
void *fd;
|
||
|
struct mg_fs *fs;
|
||
|
};
|
||
|
|
||
|
extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
|
||
|
extern struct mg_fs mg_fs_packed; // Packed FS, see examples/complete
|
||
|
|
||
|
unsigned short mg_url_port(const char *url);
|
||
|
int mg_url_is_ssl(const char *url);
|
||
|
struct mg_str mg_url_host(const char *url);
|
||
|
struct mg_str mg_url_user(const char *url);
|
||
|
struct mg_str mg_url_pass(const char *url);
|
||
|
const char *mg_url_uri(const char *url);
|
||
|
|
||
|
#include <stddef.h>
|
||
|
|
||
|
struct mg_iobuf {
|
||
|
unsigned char *buf; // Pointer to stored data
|
||
|
size_t size; // Total size available
|
||
|
size_t len; // Current number of bytes
|
||
|
};
|
||
|
|
||
|
int mg_iobuf_init(struct mg_iobuf *, size_t);
|
||
|
int mg_iobuf_resize(struct mg_iobuf *, size_t);
|
||
|
void mg_iobuf_free(struct mg_iobuf *);
|
||
|
size_t mg_iobuf_add(struct mg_iobuf *, size_t, const void *, size_t, size_t);
|
||
|
size_t mg_iobuf_del(struct mg_iobuf *, size_t ofs, size_t len);
|
||
|
|
||
|
struct mg_connection;
|
||
|
typedef void (*mg_event_handler_t)(struct mg_connection *, int ev,
|
||
|
void *ev_data, void *fn_data);
|
||
|
void mg_call(struct mg_connection *c, int ev, void *ev_data);
|
||
|
void mg_error(struct mg_connection *c, const char *fmt, ...);
|
||
|
|
||
|
enum {
|
||
|
MG_EV_ERROR, // Error char *error_message
|
||
|
MG_EV_POLL, // mg_mgr_poll iteration unsigned long *millis
|
||
|
MG_EV_RESOLVE, // Host name is resolved NULL
|
||
|
MG_EV_CONNECT, // Connection established NULL
|
||
|
MG_EV_ACCEPT, // Connection accepted NULL
|
||
|
MG_EV_READ, // Data received from socket struct mg_str *
|
||
|
MG_EV_WRITE, // Data written to socket long *bytes_written
|
||
|
MG_EV_CLOSE, // Connection closed NULL
|
||
|
MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
|
||
|
MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
|
||
|
MG_EV_USER, // Starting ID for user events
|
||
|
};
|
||
|
|
||
|
struct mg_addr {
|
||
|
uint16_t port; // TCP or UDP port in network byte order
|
||
|
uint32_t ip; // IP address in network byte order
|
||
|
uint8_t ip6[16]; // IPv6 address
|
||
|
bool is_ip6; // True when address is IPv6 address
|
||
|
};
|
||
|
|
||
|
struct mg_mgr {
|
||
|
struct mg_connection *conns; // List of active connections
|
||
|
unsigned long nextid; // Next connection ID
|
||
|
void *userdata; // Arbitrary user data pointer
|
||
|
#if MG_ARCH == MG_ARCH_FREERTOS_TCP
|
||
|
SocketSet_t ss; // NOTE(lsm): referenced from socket struct
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
struct mg_connection {
|
||
|
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
||
|
struct mg_mgr *mgr; // Our container
|
||
|
struct mg_addr peer; // Remote address. For listeners, local address
|
||
|
void *fd; // Connected socket, or LWIP data
|
||
|
unsigned long id; // Auto-incrementing unique connection ID
|
||
|
struct mg_iobuf recv; // Incoming data
|
||
|
struct mg_iobuf send; // Outgoing data
|
||
|
mg_event_handler_t fn; // User-specified event handler function
|
||
|
void *fn_data; // User-specified function parameter
|
||
|
mg_event_handler_t pfn; // Protocol-specific handler function
|
||
|
void *pfn_data; // Protocol-specific function parameter
|
||
|
char label[50]; // Arbitrary label
|
||
|
void *tls; // TLS specific data
|
||
|
unsigned is_listening : 1; // Listening connection
|
||
|
unsigned is_client : 1; // Outbound (client) connection
|
||
|
unsigned is_accepted : 1; // Accepted (server) connection
|
||
|
unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
|
||
|
unsigned is_connecting : 1; // Non-blocking connect is in progress
|
||
|
unsigned is_tls : 1; // TLS-enabled connection
|
||
|
unsigned is_tls_hs : 1; // TLS handshake is in progress
|
||
|
unsigned is_udp : 1; // UDP connection
|
||
|
unsigned is_websocket : 1; // WebSocket connection
|
||
|
unsigned is_hexdumping : 1; // Hexdump in/out traffic
|
||
|
unsigned is_draining : 1; // Send remaining data, then close and free
|
||
|
unsigned is_closing : 1; // Close and free the connection immediately
|
||
|
unsigned is_readable : 1; // Connection is ready to read
|
||
|
unsigned is_writable : 1; // Connection is ready to write
|
||
|
};
|
||
|
|
||
|
void mg_mgr_poll(struct mg_mgr *, int ms);
|
||
|
void mg_mgr_init(struct mg_mgr *);
|
||
|
void mg_mgr_free(struct mg_mgr *);
|
||
|
|
||
|
struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
|
||
|
mg_event_handler_t fn, void *fn_data);
|
||
|
struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
|
||
|
mg_event_handler_t fn, void *fn_data);
|
||
|
bool mg_send(struct mg_connection *, const void *, size_t);
|
||
|
int mg_printf(struct mg_connection *, const char *fmt, ...);
|
||
|
int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
|
||
|
char *mg_straddr(struct mg_connection *, char *, size_t);
|
||
|
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
||
|
char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
|
||
|
|
||
|
struct mg_connection *mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *);
|
||
|
void mg_mgr_wakeup(struct mg_connection *pipe);
|
||
|
|
||
|
struct mg_http_header {
|
||
|
struct mg_str name; // Header name
|
||
|
struct mg_str value; // Header value
|
||
|
};
|
||
|
|
||
|
struct mg_http_message {
|
||
|
struct mg_str method, uri, query, proto; // Request/response line
|
||
|
struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
|
||
|
struct mg_str body; // Body
|
||
|
struct mg_str head; // Request + headers
|
||
|
struct mg_str chunk; // Chunk for chunked encoding, or partial body
|
||
|
struct mg_str message; // Request + headers + body
|
||
|
};
|
||
|
|
||
|
// Parameter for mg_http_serve_dir()
|
||
|
struct mg_http_serve_opts {
|
||
|
const char *root_dir; // Web root directory, must be non-NULL
|
||
|
const char *extra_headers; // Extra HTTP headers to add in responses
|
||
|
const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
|
||
|
struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
|
||
|
};
|
||
|
|
||
|
// Parameter for mg_http_next_multipart
|
||
|
struct mg_http_part {
|
||
|
struct mg_str name; // Form field name
|
||
|
struct mg_str filename; // Filename for file uploads
|
||
|
struct mg_str body; // Part contents
|
||
|
};
|
||
|
|
||
|
int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
|
||
|
int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
|
||
|
void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...);
|
||
|
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
|
||
|
void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
|
||
|
struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url,
|
||
|
mg_event_handler_t fn, void *fn_data);
|
||
|
struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
|
||
|
mg_event_handler_t fn, void *fn_data);
|
||
|
void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
|
||
|
struct mg_http_serve_opts *opts);
|
||
|
void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
|
||
|
const char *path, struct mg_http_serve_opts *opts);
|
||
|
void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
|
||
|
const char *body_fmt, ...);
|
||
|
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
||
|
int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
|
||
|
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
||
|
size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
||
|
bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
|
||
|
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
|
||
|
size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
#endif // MONGOOSE_H
|
||
|
|