2020-12-05 19:26:32 +08:00
|
|
|
// Copyright (c) 2004-2013 Sergey Lyubka
|
2022-02-23 02:13:06 +08:00
|
|
|
// Copyright (c) 2013-2022 Cesanta Software Limited
|
2020-12-05 19:26:32 +08:00
|
|
|
// 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
|
2021-10-20 17:04:49 +08:00
|
|
|
// license, see http://www.gnu.org/licenses/
|
2020-12-05 19:26:32 +08:00
|
|
|
//
|
|
|
|
// 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
|
2021-10-20 17:04:49 +08:00
|
|
|
// license, as set out in https://www.mongoose.ws/licensing/
|
2022-02-23 02:13:06 +08:00
|
|
|
//
|
2022-09-30 03:18:05 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only or commercial
|
2021-07-20 18:33:38 +08:00
|
|
|
|
2021-07-19 16:04:18 +08:00
|
|
|
#ifndef MONGOOSE_H
|
|
|
|
#define MONGOOSE_H
|
|
|
|
|
2023-01-25 00:30:45 +08:00
|
|
|
#define MG_VERSION "7.9"
|
2020-12-05 19:26:32 +08:00
|
|
|
|
2021-07-13 13:58:34 +08:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#define MG_ARCH_CUSTOM 0 // User creates its own mongoose_custom.h
|
|
|
|
#define MG_ARCH_UNIX 1 // Linux, BSD, Mac, ...
|
|
|
|
#define MG_ARCH_WIN32 2 // Windows
|
|
|
|
#define MG_ARCH_ESP32 3 // ESP32
|
|
|
|
#define MG_ARCH_ESP8266 4 // ESP8266
|
|
|
|
#define MG_ARCH_FREERTOS 5 // FreeRTOS
|
|
|
|
#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
|
|
|
|
#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
|
|
|
|
#define MG_ARCH_NEWLIB 8 // Bare metal ARM
|
|
|
|
#define MG_ARCH_RTX 9 // Keil MDK RTX
|
|
|
|
#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
|
|
|
|
#define MG_ARCH_RP2040 11 // Raspberry Pi RP2040
|
2020-12-05 19:26:32 +08:00
|
|
|
|
|
|
|
#if !defined(MG_ARCH)
|
2021-05-11 16:12:06 +08:00
|
|
|
#if defined(__unix__) || defined(__APPLE__)
|
2020-12-05 19:26:32 +08:00
|
|
|
#define MG_ARCH MG_ARCH_UNIX
|
2016-03-30 00:27:55 +08:00
|
|
|
#elif defined(_WIN32)
|
2020-12-05 19:26:32 +08:00
|
|
|
#define MG_ARCH MG_ARCH_WIN32
|
|
|
|
#elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
|
|
|
|
#define MG_ARCH MG_ARCH_ESP8266
|
2022-10-21 22:39:45 +08:00
|
|
|
#elif defined(__ZEPHYR__)
|
|
|
|
#define MG_ARCH MG_ARCH_ZEPHYR
|
2020-12-27 09:29:42 +08:00
|
|
|
#elif defined(ESP_PLATFORM)
|
|
|
|
#define MG_ARCH MG_ARCH_ESP32
|
2021-05-18 00:36:57 +08:00
|
|
|
#elif defined(FREERTOS_IP_H)
|
2022-11-06 09:03:33 +08:00
|
|
|
#define MG_ARCH MG_ARCH_FREERTOS
|
|
|
|
#define MG_ENABLE_FREERTOS_TCP 1
|
2021-09-14 14:28:28 +08:00
|
|
|
#elif defined(AZURE_RTOS_THREADX)
|
|
|
|
#define MG_ARCH MG_ARCH_AZURERTOS
|
2022-07-04 06:00:15 +08:00
|
|
|
#elif defined(PICO_TARGET_NAME)
|
|
|
|
#define MG_ARCH MG_ARCH_RP2040
|
2016-03-30 00:27:55 +08:00
|
|
|
#endif
|
2022-11-03 20:59:55 +08:00
|
|
|
#endif // !defined(MG_ARCH)
|
2016-03-30 00:27:55 +08:00
|
|
|
|
2022-11-02 08:01:33 +08:00
|
|
|
#if !defined(MG_ARCH) || (MG_ARCH == MG_ARCH_CUSTOM)
|
2022-09-01 01:20:34 +08:00
|
|
|
#include "mongoose_custom.h" // keep this include
|
2016-10-17 17:03:59 +08:00
|
|
|
#endif
|
|
|
|
|
2022-08-21 01:26:29 +08:00
|
|
|
#if !defined(MG_ARCH)
|
|
|
|
#error "MG_ARCH is not specified and we couldn't guess it. Set -D MG_ARCH=..."
|
2017-10-17 03:00:16 +08:00
|
|
|
#endif
|
|
|
|
|
2022-09-28 19:42:20 +08:00
|
|
|
// http://esr.ibiblio.org/?p=5095
|
2022-11-06 09:03:33 +08:00
|
|
|
#define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
|
|
|
|
|
|
|
|
|
2022-09-28 19:42:20 +08:00
|
|
|
|
Change from using #ifdef to #if for features tests
"#if FOO" still works with simple -DFOO, but gives more flexibility.
Specifically, if user expressed no preference (FOO is not defined),
we can apply reasonable defaults (this is the legitimate use of ifdef).
In short, from now on, please use
#if MG_ENABLE_FOO
instead of
#ifdef MG_ENABLE_FOO
Since we are all used to #ifdef, this change also adds a precommit check
to police this. Specifically, in *.h and *.c files that are Copyright Cesanta,
"ifdef" and "if defined()" are not allowed to be used with macros that contain
ENABLE or DISABLE, unless the like also contains "ifdef-ok".
Hence, if you are sure you want to use ifdef, use this:
#ifdef MG_ENABLE_FOO /* ifdef-ok */
PUBLISHED_FROM=9be829448f53cff575d6cae8b9945fb12531c15a
2016-10-14 01:55:08 +08:00
|
|
|
|
|
|
|
|
2016-10-18 03:08:11 +08:00
|
|
|
|
2016-10-14 18:15:11 +08:00
|
|
|
|
2016-10-18 02:13:21 +08:00
|
|
|
|
2016-11-14 05:20:15 +08:00
|
|
|
|
2016-10-14 18:15:11 +08:00
|
|
|
|
2021-05-29 06:49:26 +08:00
|
|
|
|
2022-03-30 14:56:44 +08:00
|
|
|
|
2022-05-01 20:47:33 +08:00
|
|
|
|
2022-05-12 15:07:51 +08:00
|
|
|
|
|
|
|
|
2021-09-14 14:28:28 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_AZURERTOS
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
2022-01-12 03:15:38 +08:00
|
|
|
#include <stdint.h>
|
2021-09-14 14:28:28 +08:00
|
|
|
#include <stdio.h>
|
2022-01-12 03:15:38 +08:00
|
|
|
#include <time.h>
|
|
|
|
|
2021-09-14 14:28:28 +08:00
|
|
|
#include <fx_api.h>
|
2022-01-12 03:15:38 +08:00
|
|
|
#include <tx_api.h>
|
2021-09-14 14:28:28 +08:00
|
|
|
|
|
|
|
#include <nx_api.h>
|
|
|
|
#include <nx_bsd.h>
|
2022-01-12 03:15:38 +08:00
|
|
|
#include <nx_port.h>
|
|
|
|
#include <tx_port.h>
|
2021-09-14 14:28:28 +08:00
|
|
|
|
|
|
|
#define PATH_MAX FX_MAXIMUM_PATH
|
|
|
|
#define MG_DIRSEP '\\'
|
|
|
|
|
|
|
|
#define socklen_t int
|
|
|
|
#define closesocket(x) soc_close(x)
|
|
|
|
|
|
|
|
#undef FOPEN_MAX
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_ESP32
|
2016-10-14 04:48:45 +08:00
|
|
|
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <ctype.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <dirent.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <netdb.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2021-02-03 10:13:05 +08:00
|
|
|
#include <sys/stat.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2022-05-16 18:54:26 +08:00
|
|
|
#include <esp_timer.h>
|
|
|
|
|
2021-02-03 10:13:05 +08:00
|
|
|
#define MG_PATH_MAX 128
|
2016-10-26 22:41:54 +08:00
|
|
|
|
2016-11-24 17:46:40 +08:00
|
|
|
#endif
|
|
|
|
|
2016-11-29 19:17:57 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_ESP8266
|
|
|
|
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <ctype.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <dirent.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
2020-12-27 09:29:42 +08:00
|
|
|
#include <netdb.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <stdarg.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <stdbool.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <sys/time.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include <esp_system.h>
|
|
|
|
|
2021-10-31 02:34:53 +08:00
|
|
|
#define MG_PATH_MAX 128
|
2017-03-15 08:37:45 +08:00
|
|
|
|
2016-11-09 06:29:07 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_FREERTOS
|
2021-05-29 06:49:26 +08:00
|
|
|
|
2022-02-08 21:36:04 +08:00
|
|
|
#include <ctype.h>
|
2022-11-06 09:03:33 +08:00
|
|
|
// #include <errno.h> // Cannot include errno - might conflict with lwip!
|
2021-05-29 06:49:26 +08:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
2022-08-15 06:46:33 +08:00
|
|
|
#include <stddef.h>
|
2021-05-29 06:49:26 +08:00
|
|
|
#include <stdint.h>
|
2021-09-29 17:13:02 +08:00
|
|
|
#include <stdio.h>
|
2022-11-24 21:15:03 +08:00
|
|
|
#include <stdlib.h> // rand(), strtol(), atoi()
|
2022-01-14 20:33:06 +08:00
|
|
|
#include <string.h>
|
2023-01-21 05:09:21 +08:00
|
|
|
#include <sys/stat.h>
|
2021-05-29 16:44:07 +08:00
|
|
|
|
2021-05-29 06:49:26 +08:00
|
|
|
#include <FreeRTOS.h>
|
|
|
|
#include <task.h>
|
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#ifndef MG_IO_SIZE
|
|
|
|
#define MG_IO_SIZE 512
|
2021-08-11 14:56:46 +08:00
|
|
|
#endif
|
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#define calloc(a, b) mg_calloc(a, b)
|
2021-05-29 06:49:26 +08:00
|
|
|
#define free(a) vPortFree(a)
|
|
|
|
#define malloc(a) pvPortMalloc(a)
|
2022-08-20 07:03:15 +08:00
|
|
|
#define strdup(s) ((char *) mg_strdup(mg_str(s)).ptr)
|
2020-12-05 19:26:32 +08:00
|
|
|
|
2021-05-18 00:36:57 +08:00
|
|
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
2022-11-06 09:03:33 +08:00
|
|
|
static inline void *mg_calloc(size_t cnt, size_t size) {
|
2021-05-18 00:36:57 +08:00
|
|
|
void *p = pvPortMalloc(cnt * size);
|
2022-06-21 19:07:00 +08:00
|
|
|
if (p != NULL) memset(p, 0, size * cnt);
|
2021-05-18 00:36:57 +08:00
|
|
|
return p;
|
|
|
|
}
|
2021-05-19 07:00:32 +08:00
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#define mkdir(a, b) mg_mkdir(a, b)
|
|
|
|
static inline int mg_mkdir(const char *path, mode_t mode) {
|
|
|
|
(void) path, (void) mode;
|
|
|
|
return -1;
|
|
|
|
}
|
2022-10-10 20:41:07 +08:00
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#endif // MG_ARCH == MG_ARCH_FREERTOS
|
2020-12-05 19:26:32 +08:00
|
|
|
|
|
|
|
|
2022-05-01 20:47:33 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_NEWLIB
|
|
|
|
#define _POSIX_TIMERS
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.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 <unistd.h>
|
|
|
|
|
|
|
|
#define MG_PATH_MAX 100
|
|
|
|
#define MG_ENABLE_SOCKET 0
|
|
|
|
#define MG_ENABLE_DIRLIST 0
|
2023-02-08 23:00:04 +08:00
|
|
|
#define MG_ENABLE_ATOMIC 1
|
2022-05-01 20:47:33 +08:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2022-07-04 06:00:15 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_RP2040
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2022-07-04 18:10:08 +08:00
|
|
|
|
|
|
|
#include <pico/stdlib.h>
|
|
|
|
int mkdir(const char *, mode_t);
|
2023-02-08 23:00:04 +08:00
|
|
|
#define MG_ENABLE_ATOMIC 1
|
2022-07-04 06:00:15 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2022-05-12 15:07:51 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_RTX
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#if !defined MG_ENABLE_RL && (!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP)
|
|
|
|
#define MG_ENABLE_RL 1
|
2022-02-18 16:07:10 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
|
2022-05-16 00:18:18 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_TIRTOS
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2022-10-29 05:55:10 +08:00
|
|
|
#include <serrno.h>
|
2022-05-16 00:18:18 +08:00
|
|
|
#include <sys/socket.h>
|
|
|
|
|
2022-10-24 22:48:54 +08:00
|
|
|
#include <ti/sysbios/knl/Clock.h>
|
|
|
|
|
2022-05-16 00:18:18 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_UNIX
|
|
|
|
|
2021-07-24 17:35:48 +08:00
|
|
|
#define _DARWIN_UNLIMITED_SELECT 1 // No limit on file descriptors
|
2016-11-09 06:29:07 +08:00
|
|
|
|
2022-07-02 00:28:06 +08:00
|
|
|
#if defined(__APPLE__)
|
|
|
|
#include <mach/mach_time.h>
|
|
|
|
#endif
|
|
|
|
|
2022-08-03 22:07:16 +08:00
|
|
|
#if !defined(MG_ENABLE_EPOLL) && defined(__linux__)
|
|
|
|
#define MG_ENABLE_EPOLL 1
|
|
|
|
#elif !defined(MG_ENABLE_POLL)
|
2022-05-26 15:55:28 +08:00
|
|
|
#define MG_ENABLE_POLL 1
|
|
|
|
#endif
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <arpa/inet.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <ctype.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <dirent.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2021-01-27 01:43:31 +08:00
|
|
|
#include <inttypes.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <limits.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <netdb.h>
|
2022-01-24 10:20:45 +08:00
|
|
|
#include <netinet/in.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <signal.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <stdarg.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <stdbool.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <stddef.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <stdint.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2022-08-03 22:07:16 +08:00
|
|
|
|
|
|
|
#if defined(MG_ENABLE_EPOLL) && MG_ENABLE_EPOLL
|
|
|
|
#include <sys/epoll.h>
|
|
|
|
#elif defined(MG_ENABLE_POLL) && MG_ENABLE_POLL
|
2022-05-25 05:43:22 +08:00
|
|
|
#include <poll.h>
|
|
|
|
#else
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <sys/select.h>
|
2022-05-25 05:43:22 +08:00
|
|
|
#endif
|
2022-08-03 22:07:16 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <sys/socket.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <sys/stat.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <sys/time.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <unistd.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
|
2022-02-14 19:32:01 +08:00
|
|
|
#ifndef MG_ENABLE_DIRLIST
|
|
|
|
#define MG_ENABLE_DIRLIST 1
|
|
|
|
#endif
|
|
|
|
|
2022-08-07 05:19:55 +08:00
|
|
|
#ifndef MG_PATH_MAX
|
|
|
|
#define MG_PATH_MAX FILENAME_MAX
|
|
|
|
#endif
|
|
|
|
|
2016-11-12 04:34:00 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_WIN32
|
2016-11-12 04:34:00 +08:00
|
|
|
|
2021-07-13 14:13:06 +08:00
|
|
|
#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
|
|
|
|
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <ctype.h>
|
2022-01-21 20:35:28 +08:00
|
|
|
#include <direct.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
2022-02-13 00:43:08 +08:00
|
|
|
#include <signal.h>
|
2021-03-13 20:34:26 +08:00
|
|
|
#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>
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
|
|
|
#define __func__ ""
|
|
|
|
typedef __int64 int64_t;
|
|
|
|
typedef unsigned __int64 uint64_t;
|
|
|
|
typedef unsigned char uint8_t;
|
2021-01-25 18:08:15 +08:00
|
|
|
typedef char int8_t;
|
2020-12-05 19:26:32 +08:00
|
|
|
typedef unsigned short uint16_t;
|
2021-01-25 18:08:15 +08:00
|
|
|
typedef short int16_t;
|
2020-12-05 19:26:32 +08:00
|
|
|
typedef unsigned int uint32_t;
|
2021-01-25 18:08:15 +08:00
|
|
|
typedef int int32_t;
|
2021-01-26 20:16:58 +08:00
|
|
|
typedef enum { false = 0, true = 1 } bool;
|
2020-12-05 19:26:32 +08:00
|
|
|
#else
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
2020-12-22 17:44:59 +08:00
|
|
|
#include <ws2tcpip.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#endif
|
2016-11-12 04:34:00 +08:00
|
|
|
|
2022-02-13 00:43:08 +08:00
|
|
|
#include <process.h>
|
2022-03-15 18:10:08 +08:00
|
|
|
#include <winerror.h>
|
2020-12-05 19:26:32 +08:00
|
|
|
#include <winsock2.h>
|
2020-12-24 05:05:46 +08:00
|
|
|
|
2020-12-24 05:20:48 +08:00
|
|
|
// Protect from calls like std::snprintf in app code
|
2020-12-24 05:05:46 +08:00
|
|
|
// See https://github.com/cesanta/mongoose/issues/1047
|
|
|
|
#ifndef __cplusplus
|
2020-12-05 19:26:32 +08:00
|
|
|
#define snprintf _snprintf
|
|
|
|
#define vsnprintf _vsnprintf
|
2021-09-27 20:52:39 +08:00
|
|
|
#ifndef strdup // For MSVC with _DEBUG, see #1359
|
2020-12-05 19:26:32 +08:00
|
|
|
#define strdup(x) _strdup(x)
|
2020-12-24 05:05:46 +08:00
|
|
|
#endif
|
2021-09-27 20:52:39 +08:00
|
|
|
#endif
|
2020-12-24 05:05:46 +08:00
|
|
|
|
2022-11-05 18:07:31 +08:00
|
|
|
#define MG_INVALID_SOCKET INVALID_SOCKET
|
|
|
|
#define MG_SOCKET_TYPE SOCKET
|
|
|
|
typedef unsigned long nfds_t;
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
#pragma comment(lib, "ws2_32.lib")
|
2022-10-31 18:40:34 +08:00
|
|
|
#ifndef alloca
|
2022-11-05 18:07:31 +08:00
|
|
|
#define alloca(a) _alloca(a)
|
|
|
|
#endif
|
2022-10-31 18:40:34 +08:00
|
|
|
#endif
|
2022-11-05 18:07:31 +08:00
|
|
|
#define poll(a, b, c) WSAPoll((a), (b), (c))
|
|
|
|
#define closesocket(x) closesocket(x)
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
typedef int socklen_t;
|
|
|
|
#define MG_DIRSEP '\\'
|
2022-08-07 05:19:55 +08:00
|
|
|
|
|
|
|
#ifndef MG_PATH_MAX
|
|
|
|
#define MG_PATH_MAX FILENAME_MAX
|
2020-12-24 15:26:50 +08:00
|
|
|
#endif
|
2022-08-07 05:19:55 +08:00
|
|
|
|
2023-02-01 20:25:30 +08:00
|
|
|
#ifndef SO_EXCLUSIVEADDRUSE
|
|
|
|
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
|
2015-12-06 00:46:53 +08:00
|
|
|
#endif
|
2021-07-24 17:35:48 +08:00
|
|
|
|
2023-02-01 20:25:30 +08:00
|
|
|
#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? WSAGetLastError() : 0)
|
|
|
|
|
|
|
|
#define MG_SOCK_PENDING(errcode) \
|
|
|
|
(((errcode) < 0) && \
|
|
|
|
(WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || \
|
|
|
|
WSAGetLastError() == WSAEWOULDBLOCK))
|
|
|
|
|
|
|
|
#define MG_SOCK_RESET(errcode) \
|
|
|
|
(((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
|
|
|
|
|
2021-12-23 02:04:36 +08:00
|
|
|
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
|
|
|
#define sleep(x) Sleep(x)
|
2022-01-21 20:35:28 +08:00
|
|
|
#define mkdir(a, b) _mkdir(a)
|
2021-12-23 02:04:36 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#ifndef S_ISDIR
|
|
|
|
#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
|
|
|
|
#endif
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2022-02-14 19:32:01 +08:00
|
|
|
#ifndef MG_ENABLE_DIRLIST
|
|
|
|
#define MG_ENABLE_DIRLIST 1
|
|
|
|
#endif
|
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
#endif
|
|
|
|
|
2016-03-19 17:48:50 +08:00
|
|
|
|
2022-03-30 14:56:44 +08:00
|
|
|
#if MG_ARCH == MG_ARCH_ZEPHYR
|
|
|
|
|
2022-10-01 06:30:26 +08:00
|
|
|
#include <zephyr/kernel.h>
|
2022-03-30 14:56:44 +08:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2022-10-01 06:30:26 +08:00
|
|
|
#include <zephyr/net/socket.h>
|
2022-03-30 14:56:44 +08:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
2022-05-20 16:45:17 +08:00
|
|
|
#define MG_PUTCHAR(x) printk("%c", x)
|
2022-10-01 06:30:26 +08:00
|
|
|
#ifndef strdup
|
|
|
|
#define strdup(s) ((char *) mg_strdup(mg_str(s)).ptr)
|
|
|
|
#endif
|
2022-03-30 14:56:44 +08:00
|
|
|
#define strerror(x) zsock_gai_strerror(x)
|
|
|
|
#define FD_CLOEXEC 0
|
|
|
|
#define F_SETFD 0
|
2022-04-01 23:42:41 +08:00
|
|
|
#define MG_ENABLE_SSI 0
|
2022-03-30 14:56:44 +08:00
|
|
|
|
|
|
|
int rand(void);
|
|
|
|
int sscanf(const char *, const char *, ...);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#if defined(MG_ENABLE_FREERTOS_TCP) && MG_ENABLE_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 <list.h>
|
|
|
|
#include <task.h>
|
|
|
|
|
|
|
|
#include <FreeRTOS_IP.h>
|
|
|
|
#include <FreeRTOS_Sockets.h>
|
|
|
|
|
|
|
|
#define MG_SOCKET_TYPE Socket_t
|
|
|
|
#define MG_INVALID_SOCKET FREERTOS_INVALID_SOCKET
|
|
|
|
|
|
|
|
// 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) mg_getsockname((a), (b), (c))
|
|
|
|
#define getpeername(a, b, c) mg_getpeername((a), (b), (c))
|
|
|
|
|
|
|
|
static inline int mg_getsockname(MG_SOCKET_TYPE fd, void *buf, socklen_t *len) {
|
|
|
|
(void) fd, (void) buf, (void) len;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int mg_getpeername(MG_SOCKET_TYPE fd, void *buf, socklen_t *len) {
|
|
|
|
(void) fd, (void) buf, (void) len;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(MG_ENABLE_LWIP) && MG_ENABLE_LWIP
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#else
|
|
|
|
struct timeval {
|
|
|
|
time_t tv_sec;
|
|
|
|
long tv_usec;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#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
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(MG_ENABLE_RL) && MG_ENABLE_RL
|
|
|
|
#include <rl_net.h>
|
|
|
|
|
|
|
|
#define MG_ENABLE_CUSTOM_MILLIS 1
|
|
|
|
#define closesocket(x) closesocket(x)
|
|
|
|
#define mkdir(a, b) (-1)
|
2023-02-01 20:25:30 +08:00
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#define TCP_NODELAY SO_KEEPALIVE
|
2023-02-01 20:25:30 +08:00
|
|
|
|
|
|
|
#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0)
|
|
|
|
|
|
|
|
#define MG_SOCK_PENDING(errcode) \
|
|
|
|
((errcode) == BSD_EWOULDBLOCK || (errcode) == BSD_EALREADY || \
|
|
|
|
(errcode) == BSD_EINPROGRESS)
|
|
|
|
|
|
|
|
#define MG_SOCK_RESET(errcode) \
|
|
|
|
((errcode) == BSD_ECONNABORTED || (errcode) == BSD_ECONNRESET)
|
|
|
|
|
|
|
|
#define MG_SOCK_INTR(fd) 0
|
|
|
|
|
|
|
|
#define socklen_t int
|
2022-11-06 09:03:33 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2022-06-19 16:04:22 +08:00
|
|
|
#ifndef MG_ENABLE_LOG
|
|
|
|
#define MG_ENABLE_LOG 1
|
|
|
|
#endif
|
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
#ifndef MG_ENABLE_TCPIP
|
|
|
|
#define MG_ENABLE_TCPIP 0 // Mongoose built-in network stack
|
2022-11-06 09:03:33 +08:00
|
|
|
#endif
|
|
|
|
|
2023-02-08 23:00:04 +08:00
|
|
|
#ifndef MG_ENABLE_ATOMIC
|
|
|
|
#define MG_ENABLE_ATOMIC 0 // Required by mg_queue
|
|
|
|
#endif
|
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
#ifndef MG_ENABLE_LWIP
|
|
|
|
#define MG_ENABLE_LWIP 0 // lWIP network stack
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_FREERTOS_TCP
|
|
|
|
#define MG_ENABLE_FREERTOS_TCP 0 // Amazon FreeRTOS-TCP network stack
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_RL
|
|
|
|
#define MG_ENABLE_RL 0 // ARM MDK network stack
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_SOCKET
|
2023-02-08 05:16:42 +08:00
|
|
|
#define MG_ENABLE_SOCKET !MG_ENABLE_TCPIP
|
2022-05-19 04:19:21 +08:00
|
|
|
#endif
|
|
|
|
|
2022-05-25 05:43:22 +08:00
|
|
|
#ifndef MG_ENABLE_POLL
|
|
|
|
#define MG_ENABLE_POLL 0
|
|
|
|
#endif
|
|
|
|
|
2022-08-03 22:07:16 +08:00
|
|
|
#ifndef MG_ENABLE_EPOLL
|
|
|
|
#define MG_ENABLE_EPOLL 0
|
|
|
|
#endif
|
|
|
|
|
2022-01-18 15:44:30 +08:00
|
|
|
#ifndef MG_ENABLE_FATFS
|
|
|
|
#define MG_ENABLE_FATFS 0
|
|
|
|
#endif
|
|
|
|
|
2021-12-22 01:39:55 +08:00
|
|
|
#ifndef MG_ENABLE_MBEDTLS
|
|
|
|
#define MG_ENABLE_MBEDTLS 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_OPENSSL
|
|
|
|
#define MG_ENABLE_OPENSSL 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_CUSTOM_TLS
|
|
|
|
#define MG_ENABLE_CUSTOM_TLS 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_SSI
|
2022-05-09 04:54:15 +08:00
|
|
|
#define MG_ENABLE_SSI 0
|
2021-12-22 01:39:55 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_IPV6
|
|
|
|
#define MG_ENABLE_IPV6 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_MD5
|
2022-09-28 19:42:20 +08:00
|
|
|
#define MG_ENABLE_MD5 1
|
2021-12-22 01:39:55 +08:00
|
|
|
#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
|
2022-02-14 19:32:01 +08:00
|
|
|
#define MG_ENABLE_DIRLIST 0
|
2021-12-22 01:39:55 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_CUSTOM_RANDOM
|
|
|
|
#define MG_ENABLE_CUSTOM_RANDOM 0
|
|
|
|
#endif
|
|
|
|
|
2022-04-05 01:14:59 +08:00
|
|
|
#ifndef MG_ENABLE_CUSTOM_MILLIS
|
|
|
|
#define MG_ENABLE_CUSTOM_MILLIS 0
|
|
|
|
#endif
|
|
|
|
|
2021-12-22 01:39:55 +08:00
|
|
|
#ifndef MG_ENABLE_PACKED_FS
|
|
|
|
#define MG_ENABLE_PACKED_FS 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_IO_SIZE
|
2023-01-09 18:58:07 +08:00
|
|
|
#define MG_IO_SIZE 2048 // Granularity of the send/recv IO buffer growth
|
2021-12-22 01:39:55 +08:00
|
|
|
#endif
|
|
|
|
|
2022-06-02 20:50:44 +08:00
|
|
|
#ifndef MG_MAX_RECV_SIZE
|
2023-01-09 18:58:07 +08:00
|
|
|
#define MG_MAX_RECV_SIZE (3 * 1024 * 1024) // Maximum recv IO buffer size
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_DATA_SIZE
|
|
|
|
#define MG_DATA_SIZE 32 // struct mg_connection :: data size
|
2021-12-22 01:39:55 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_MAX_HTTP_HEADERS
|
2022-08-27 19:31:43 +08:00
|
|
|
#define MG_MAX_HTTP_HEADERS 30
|
2021-12-22 01:39:55 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_HTTP_INDEX
|
|
|
|
#define MG_HTTP_INDEX "index.html"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_PATH_MAX
|
|
|
|
#ifdef PATH_MAX
|
|
|
|
#define MG_PATH_MAX PATH_MAX
|
|
|
|
#else
|
|
|
|
#define MG_PATH_MAX 128
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
|
2022-05-12 22:07:02 +08:00
|
|
|
#define MG_SOCK_LISTEN_BACKLOG_SIZE 3
|
2021-12-22 01:39:55 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_DIRSEP
|
|
|
|
#define MG_DIRSEP '/'
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_ENABLE_FILE
|
|
|
|
#if defined(FOPEN_MAX)
|
|
|
|
#define MG_ENABLE_FILE 1
|
|
|
|
#else
|
|
|
|
#define MG_ENABLE_FILE 0
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2022-11-05 18:07:31 +08:00
|
|
|
#ifndef MG_INVALID_SOCKET
|
|
|
|
#define MG_INVALID_SOCKET (-1)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_SOCKET_TYPE
|
|
|
|
#define MG_SOCKET_TYPE int
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MG_SOCKET_ERRNO
|
|
|
|
#define MG_SOCKET_ERRNO errno
|
|
|
|
#endif
|
|
|
|
|
2022-08-03 22:07:16 +08:00
|
|
|
#if MG_ENABLE_EPOLL
|
|
|
|
#define MG_EPOLL_ADD(c) \
|
|
|
|
do { \
|
|
|
|
struct epoll_event ev = {EPOLLIN | EPOLLERR | EPOLLHUP, {c}}; \
|
|
|
|
epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_ADD, (int) (size_t) c->fd, &ev); \
|
|
|
|
} while (0)
|
|
|
|
#define MG_EPOLL_MOD(c, wr) \
|
|
|
|
do { \
|
|
|
|
struct epoll_event ev = {EPOLLIN | EPOLLERR | EPOLLHUP, {c}}; \
|
|
|
|
if (wr) ev.events |= EPOLLOUT; \
|
|
|
|
epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_MOD, (int) (size_t) c->fd, &ev); \
|
|
|
|
} while (0)
|
|
|
|
#else
|
|
|
|
#define MG_EPOLL_ADD(c)
|
|
|
|
#define MG_EPOLL_MOD(c, wr)
|
|
|
|
#endif
|
|
|
|
|
2021-12-22 01:39:55 +08:00
|
|
|
|
2022-01-11 01:30:51 +08:00
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_str {
|
2021-09-15 14:43:48 +08:00
|
|
|
const char *ptr; // Pointer to string data
|
|
|
|
size_t len; // String len
|
2015-09-08 19:49:03 +08:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#define MG_NULL_STR \
|
|
|
|
{ NULL, 0 }
|
2020-05-25 00:32:33 +08:00
|
|
|
|
2022-01-23 14:10:14 +08:00
|
|
|
#define MG_C_STR(a) \
|
|
|
|
{ (a), sizeof(a) - 1 }
|
|
|
|
|
2021-07-15 09:18:32 +08:00
|
|
|
// Using macro to avoid shadowing C++ struct constructor, see #1298
|
|
|
|
#define mg_str(s) mg_str_s(s)
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_str mg_str(const char *s);
|
2020-12-07 11:47:37 +08:00
|
|
|
struct mg_str mg_str_n(const char *s, size_t n);
|
2020-12-05 19:26:32 +08:00
|
|
|
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);
|
2022-01-29 19:03:54 +08:00
|
|
|
bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);
|
|
|
|
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);
|
2022-05-31 17:41:14 +08:00
|
|
|
bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char delim);
|
2022-02-10 19:56:55 +08:00
|
|
|
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_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
|
|
|
|
int64_t mg_to64(struct mg_str str);
|
2022-04-12 17:20:43 +08:00
|
|
|
uint64_t mg_tou64(struct mg_str str);
|
2022-07-01 03:27:43 +08:00
|
|
|
char *mg_remove_double_dots(char *s);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2022-07-28 17:18:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-02-08 23:00:04 +08:00
|
|
|
#if MG_ENABLE_ATOMIC
|
|
|
|
#include <stdatomic.h>
|
|
|
|
#elif !defined(_Atomic)
|
|
|
|
#define _Atomic
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Single producer, single consumer non-blocking queue
|
|
|
|
//
|
|
|
|
// Producer:
|
|
|
|
// void *buf;
|
|
|
|
// while (mg_queue_space(q, &buf) < len) WAIT(); // Wait for free space
|
|
|
|
// memcpy(buf, data, len); // Copy data to the queue
|
|
|
|
// mg_queue_add(q, len); // Advance q->head
|
|
|
|
//
|
|
|
|
// Consumer:
|
|
|
|
// void *buf;
|
|
|
|
// while ((len = mg_queue_next(q, &buf)) == MG_QUEUE_EMPTY) WAIT();
|
|
|
|
// mg_hexdump(buf, len); // Handle message
|
|
|
|
// mg_queue_del(q); // Delete message
|
|
|
|
//
|
|
|
|
struct mg_queue {
|
|
|
|
char *buf;
|
|
|
|
size_t len;
|
|
|
|
volatile _Atomic size_t tail;
|
|
|
|
volatile _Atomic size_t head;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MG_QUEUE_EMPTY ((size_t) ~0ul) // Next message size when queue is empty
|
|
|
|
|
|
|
|
void mg_queue_add(struct mg_queue *, size_t len); // Advance head
|
|
|
|
void mg_queue_del(struct mg_queue *); // Advance tail
|
|
|
|
size_t mg_queue_space(struct mg_queue *, char **); // Get free space
|
|
|
|
size_t mg_queue_next(struct mg_queue *, char **); // Get next message size
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-02-10 23:29:25 +08:00
|
|
|
typedef void (*mg_pfn_t)(char, void *); // Output function
|
2022-07-27 07:46:05 +08:00
|
|
|
typedef size_t (*mg_pm_t)(mg_pfn_t, void *, va_list *); // %M printer
|
2022-06-28 07:45:52 +08:00
|
|
|
|
2022-08-14 03:34:20 +08:00
|
|
|
size_t mg_vxprintf(void (*)(char, void *), void *, const char *fmt, va_list *);
|
|
|
|
size_t mg_xprintf(void (*fn)(char, void *), void *, const char *fmt, ...);
|
2023-02-10 23:29:25 +08:00
|
|
|
|
|
|
|
// Convenience wrappers around mg_xprintf
|
2022-06-28 07:45:52 +08:00
|
|
|
size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap);
|
|
|
|
size_t mg_snprintf(char *, size_t, const char *fmt, ...);
|
2022-08-13 22:37:55 +08:00
|
|
|
char *mg_vmprintf(const char *fmt, va_list *ap);
|
2022-06-28 07:45:52 +08:00
|
|
|
char *mg_mprintf(const char *fmt, ...);
|
2023-02-08 23:00:04 +08:00
|
|
|
size_t mg_queue_vprintf(struct mg_queue *, const char *fmt, va_list *);
|
|
|
|
size_t mg_queue_printf(struct mg_queue *, const char *fmt, ...);
|
2022-08-13 22:37:55 +08:00
|
|
|
|
2023-02-10 23:29:25 +08:00
|
|
|
// %M print helper functions
|
|
|
|
size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap);
|
|
|
|
size_t mg_print_ip_port(void (*out)(char, void *), void *arg, va_list *ap);
|
|
|
|
size_t mg_print_ip4(void (*out)(char, void *), void *arg, va_list *ap);
|
|
|
|
size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap);
|
|
|
|
size_t mg_print_mac(void (*out)(char, void *), void *arg, va_list *ap);
|
|
|
|
|
|
|
|
// Various output functions
|
|
|
|
void mg_pfn_iobuf(char ch, void *param); // param: struct mg_iobuf *
|
|
|
|
void mg_pfn_stdout(char c, void *param); // param: ignored
|
|
|
|
|
2022-06-28 07:45:52 +08:00
|
|
|
|
2016-02-26 08:12:32 +08:00
|
|
|
|
2016-10-05 07:38:27 +08:00
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
|
2022-02-13 02:17:25 +08:00
|
|
|
enum { MG_LL_NONE, MG_LL_ERROR, MG_LL_INFO, MG_LL_DEBUG, MG_LL_VERBOSE };
|
2022-06-09 05:09:11 +08:00
|
|
|
void mg_log(const char *fmt, ...);
|
2022-01-23 14:10:14 +08:00
|
|
|
bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
|
2022-08-01 18:19:32 +08:00
|
|
|
void mg_log_set(int log_level);
|
2022-05-07 04:09:13 +08:00
|
|
|
void mg_hexdump(const void *buf, size_t len);
|
2022-08-13 22:37:55 +08:00
|
|
|
void mg_log_set_fn(mg_pfn_t fn, void *param);
|
2022-01-24 10:20:45 +08:00
|
|
|
|
2022-06-19 16:04:22 +08:00
|
|
|
#if MG_ENABLE_LOG
|
2022-02-13 02:17:25 +08:00
|
|
|
#define MG_LOG(level, args) \
|
2020-12-05 19:26:32 +08:00
|
|
|
do { \
|
|
|
|
if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \
|
|
|
|
} while (0)
|
2022-06-19 16:04:22 +08:00
|
|
|
#else
|
|
|
|
#define MG_LOG(level, args) \
|
|
|
|
do { \
|
|
|
|
if (0) mg_log args; \
|
|
|
|
} while (0)
|
|
|
|
#endif
|
2022-01-24 10:20:45 +08:00
|
|
|
|
2022-02-13 02:17:25 +08:00
|
|
|
#define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
|
|
|
|
#define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
|
|
|
|
#define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
|
|
|
|
#define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
|
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2021-12-22 05:50:18 +08:00
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_timer {
|
2022-07-17 19:52:18 +08:00
|
|
|
unsigned long id; // Timer ID
|
2022-04-07 20:50:25 +08:00
|
|
|
uint64_t period_ms; // Timer period in milliseconds
|
|
|
|
uint64_t expire; // Expiration timestamp in milliseconds
|
2021-05-29 01:30:42 +08:00
|
|
|
unsigned flags; // Possible flags values below
|
2022-05-15 21:29:34 +08:00
|
|
|
#define MG_TIMER_ONCE 0 // Call function once
|
|
|
|
#define MG_TIMER_REPEAT 1 // Call function periodically
|
2021-11-06 19:29:56 +08:00
|
|
|
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
|
2020-12-05 19:26:32 +08:00
|
|
|
void (*fn)(void *); // Function to call
|
2021-03-11 21:15:53 +08:00
|
|
|
void *arg; // Function argument
|
2022-05-15 21:29:34 +08:00
|
|
|
struct mg_timer *next; // Linkage
|
2020-12-05 19:26:32 +08:00
|
|
|
};
|
2016-10-15 00:58:14 +08:00
|
|
|
|
2022-04-12 21:14:55 +08:00
|
|
|
void mg_timer_init(struct mg_timer **head, struct mg_timer *timer,
|
|
|
|
uint64_t milliseconds, unsigned flags, void (*fn)(void *),
|
|
|
|
void *arg);
|
|
|
|
void mg_timer_free(struct mg_timer **head, struct mg_timer *);
|
|
|
|
void mg_timer_poll(struct mg_timer **head, uint64_t new_ms);
|
2022-09-03 16:41:17 +08:00
|
|
|
bool mg_timer_expired(uint64_t *expiration, uint64_t period, uint64_t now);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
2015-10-20 17:31:23 +08:00
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
2022-01-19 01:11:02 +08:00
|
|
|
enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
|
|
|
|
|
|
|
|
// Filesystem API functions
|
2022-02-08 21:36:04 +08:00
|
|
|
// st() returns MG_FS_* flags and populates file size and modification time
|
|
|
|
// ls() calls fn() for every directory entry, allowing to list a directory
|
|
|
|
//
|
|
|
|
// NOTE: UNIX-style shorthand names for the API functions are deliberately
|
|
|
|
// chosen to avoid conflicts with some libraries that make macros for e.g.
|
|
|
|
// stat(), write(), read() calls.
|
2022-01-19 01:11:02 +08:00
|
|
|
struct mg_fs {
|
2022-02-08 21:36:04 +08:00
|
|
|
int (*st)(const char *path, size_t *size, time_t *mtime); // stat file
|
|
|
|
void (*ls)(const char *path, void (*fn)(const char *, void *), void *);
|
|
|
|
void *(*op)(const char *path, int flags); // Open file
|
|
|
|
void (*cl)(void *fd); // Close file
|
|
|
|
size_t (*rd)(void *fd, void *buf, size_t len); // Read file
|
|
|
|
size_t (*wr)(void *fd, const void *buf, size_t len); // Write file
|
|
|
|
size_t (*sk)(void *fd, size_t offset); // Set file position
|
|
|
|
bool (*mv)(const char *from, const char *to); // Rename file
|
|
|
|
bool (*rm)(const char *path); // Delete file
|
|
|
|
bool (*mkd)(const char *path); // Create directory
|
2022-01-19 01:11:02 +08:00
|
|
|
};
|
|
|
|
|
2022-01-19 17:25:01 +08:00
|
|
|
extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
|
2022-05-25 20:28:25 +08:00
|
|
|
extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard
|
2022-01-19 17:25:01 +08:00
|
|
|
extern struct mg_fs mg_fs_fat; // FAT FS
|
|
|
|
|
2022-01-19 01:11:02 +08:00
|
|
|
// File descriptor
|
|
|
|
struct mg_fd {
|
|
|
|
void *fd;
|
|
|
|
struct mg_fs *fs;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags);
|
|
|
|
void mg_fs_close(struct mg_fd *fd);
|
|
|
|
char *mg_file_read(struct mg_fs *fs, const char *path, size_t *size);
|
|
|
|
bool mg_file_write(struct mg_fs *fs, const char *path, const void *, size_t);
|
|
|
|
bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-22 02:16:12 +08:00
|
|
|
|
2023-01-31 22:56:46 +08:00
|
|
|
|
|
|
|
|
2021-07-30 20:19:20 +08:00
|
|
|
void mg_random(void *buf, size_t len);
|
2022-07-04 18:00:06 +08:00
|
|
|
char *mg_random_str(char *buf, size_t len);
|
2020-12-05 19:26:32 +08:00
|
|
|
uint16_t mg_ntohs(uint16_t net);
|
|
|
|
uint32_t mg_ntohl(uint32_t net);
|
2021-03-08 23:41:16 +08:00
|
|
|
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
2022-04-07 20:50:25 +08:00
|
|
|
uint64_t mg_millis(void);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#define mg_htons(x) mg_ntohs(x)
|
|
|
|
#define mg_htonl(x) mg_ntohl(x)
|
2015-11-18 15:39:51 +08:00
|
|
|
|
2023-01-29 22:30:06 +08:00
|
|
|
#define MG_U32(a, b, c, d) \
|
2022-12-19 19:43:25 +08:00
|
|
|
(((uint32_t) ((a) &255) << 24) | ((uint32_t) ((b) &255) << 16) | \
|
|
|
|
((uint32_t) ((c) &255) << 8) | (uint32_t) ((d) &255))
|
|
|
|
|
2023-01-29 22:30:06 +08:00
|
|
|
// For printing IPv4 addresses: printf("%d.%d.%d.%d\n", MG_IPADDR_PARTS(&ip))
|
|
|
|
#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
|
|
|
|
#define MG_IPADDR_PARTS(ADDR) \
|
|
|
|
MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3]
|
|
|
|
|
2021-04-09 23:55:12 +08:00
|
|
|
// Linked list management macros
|
2020-12-05 19:26:32 +08:00
|
|
|
#define LIST_ADD_HEAD(type_, head_, elem_) \
|
|
|
|
do { \
|
|
|
|
(elem_)->next = (*head_); \
|
|
|
|
*(head_) = (elem_); \
|
|
|
|
} while (0)
|
2016-10-15 00:58:14 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#define LIST_ADD_TAIL(type_, head_, elem_) \
|
|
|
|
do { \
|
|
|
|
type_ **h = head_; \
|
|
|
|
while (*h != NULL) h = &(*h)->next; \
|
|
|
|
*h = (elem_); \
|
|
|
|
} while (0)
|
2016-10-15 00:58:14 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#define LIST_DELETE(type_, head_, elem_) \
|
|
|
|
do { \
|
|
|
|
type_ **h = head_; \
|
|
|
|
while (*h != (elem_)) h = &(*h)->next; \
|
|
|
|
*h = (elem_)->next; \
|
|
|
|
} while (0)
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
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);
|
2016-10-28 01:43:56 +08:00
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2022-07-02 00:28:06 +08:00
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_iobuf {
|
2021-08-30 20:06:45 +08:00
|
|
|
unsigned char *buf; // Pointer to stored data
|
2021-08-28 15:08:54 +08:00
|
|
|
size_t size; // Total size available
|
|
|
|
size_t len; // Current number of bytes
|
2022-08-01 19:53:25 +08:00
|
|
|
size_t align; // Alignment during allocation
|
2015-09-08 19:49:03 +08:00
|
|
|
};
|
|
|
|
|
2022-08-01 19:53:25 +08:00
|
|
|
int mg_iobuf_init(struct mg_iobuf *, size_t, size_t);
|
2021-01-29 20:32:34 +08:00
|
|
|
int mg_iobuf_resize(struct mg_iobuf *, size_t);
|
2020-12-05 19:26:32 +08:00
|
|
|
void mg_iobuf_free(struct mg_iobuf *);
|
2022-08-01 19:53:25 +08:00
|
|
|
size_t mg_iobuf_add(struct mg_iobuf *, size_t, const void *, size_t);
|
2021-08-27 17:25:24 +08:00
|
|
|
size_t mg_iobuf_del(struct mg_iobuf *, size_t ofs, size_t len);
|
2016-11-09 17:52:59 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
int mg_base64_update(unsigned char p, char *to, int len);
|
|
|
|
int mg_base64_final(char *to, int len);
|
|
|
|
int mg_base64_encode(const unsigned char *p, int n, char *to);
|
|
|
|
int mg_base64_decode(const char *src, int n, char *dst);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
typedef struct {
|
|
|
|
uint32_t buf[4];
|
|
|
|
uint32_t bits[2];
|
|
|
|
unsigned char in[64];
|
|
|
|
} mg_md5_ctx;
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
void mg_md5_init(mg_md5_ctx *c);
|
|
|
|
void mg_md5_update(mg_md5_ctx *c, const unsigned char *data, size_t len);
|
|
|
|
void mg_md5_final(mg_md5_ctx *c, unsigned char[16]);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
typedef struct {
|
|
|
|
uint32_t state[5];
|
|
|
|
uint32_t count[2];
|
|
|
|
unsigned char buffer[64];
|
|
|
|
} mg_sha1_ctx;
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
void mg_sha1_init(mg_sha1_ctx *);
|
|
|
|
void mg_sha1_update(mg_sha1_ctx *, const unsigned char *data, size_t len);
|
|
|
|
void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
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 {
|
2021-03-08 23:41:16 +08:00
|
|
|
MG_EV_ERROR, // Error char *error_message
|
2021-11-02 00:20:00 +08:00
|
|
|
MG_EV_OPEN, // Connection created NULL
|
2022-09-10 00:09:18 +08:00
|
|
|
MG_EV_POLL, // mg_mgr_poll iteration uint64_t *uptime_millis
|
2021-03-08 23:41:16 +08:00
|
|
|
MG_EV_RESOLVE, // Host name is resolved NULL
|
|
|
|
MG_EV_CONNECT, // Connection established NULL
|
|
|
|
MG_EV_ACCEPT, // Connection accepted NULL
|
2022-09-20 18:34:22 +08:00
|
|
|
MG_EV_TLS_HS, // TLS handshake succeeded NULL
|
2022-09-10 00:09:18 +08:00
|
|
|
MG_EV_READ, // Data received from socket long *bytes_read
|
2021-05-29 01:30:42 +08:00
|
|
|
MG_EV_WRITE, // Data written to socket long *bytes_written
|
2021-03-08 23:41:16 +08:00
|
|
|
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_WS_OPEN, // Websocket handshake done struct mg_http_message *
|
|
|
|
MG_EV_WS_MSG, // Websocket msg, text or bin struct mg_ws_message *
|
|
|
|
MG_EV_WS_CTL, // Websocket control msg struct mg_ws_message *
|
|
|
|
MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
|
|
|
|
MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
|
|
|
|
MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
|
2022-09-10 00:09:18 +08:00
|
|
|
MG_EV_SNTP_TIME, // SNTP time received uint64_t *epoch_millis
|
2022-09-19 20:28:07 +08:00
|
|
|
MG_EV_USER // Starting ID for user events
|
2015-09-08 19:49:03 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-23 18:15:09 +08:00
|
|
|
|
2022-04-12 21:14:55 +08:00
|
|
|
|
2022-11-06 09:03:33 +08:00
|
|
|
|
2020-12-22 17:44:59 +08:00
|
|
|
struct mg_dns {
|
|
|
|
const char *url; // DNS server URL
|
|
|
|
struct mg_connection *c; // DNS server connection
|
2015-09-08 19:49:03 +08:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_addr {
|
2020-12-21 00:55:33 +08:00
|
|
|
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
|
2020-12-05 19:26:32 +08:00
|
|
|
};
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2020-12-22 17:44:59 +08:00
|
|
|
struct mg_mgr {
|
|
|
|
struct mg_connection *conns; // List of active connections
|
|
|
|
struct mg_dns dns4; // DNS for IPv4
|
|
|
|
struct mg_dns dns6; // DNS for IPv6
|
|
|
|
int dnstimeout; // DNS resolve timeout in milliseconds
|
2022-04-23 03:44:53 +08:00
|
|
|
bool use_dns6; // Use DNS6 server by default, see #1532
|
2020-12-22 17:44:59 +08:00
|
|
|
unsigned long nextid; // Next connection ID
|
2022-07-17 19:52:18 +08:00
|
|
|
unsigned long timerid; // Next timer ID
|
2021-03-01 00:40:27 +08:00
|
|
|
void *userdata; // Arbitrary user data pointer
|
2022-04-12 21:14:55 +08:00
|
|
|
uint16_t mqtt_id; // MQTT IDs for pub/sub
|
|
|
|
void *active_dns_requests; // DNS requests in progress
|
|
|
|
struct mg_timer *timers; // Active timers
|
2022-08-03 22:07:16 +08:00
|
|
|
int epoll_fd; // Used when MG_EPOLL_ENABLE=1
|
2022-07-17 19:52:18 +08:00
|
|
|
void *priv; // Used by the MIP stack
|
|
|
|
size_t extraconnsize; // Used by the MIP stack
|
2022-11-06 09:03:33 +08:00
|
|
|
#if MG_ENABLE_FREERTOS_TCP
|
2020-12-22 17:44:59 +08:00
|
|
|
SocketSet_t ss; // NOTE(lsm): referenced from socket struct
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_connection {
|
|
|
|
struct mg_connection *next; // Linkage in struct mg_mgr :: connections
|
|
|
|
struct mg_mgr *mgr; // Our container
|
2022-02-23 06:00:55 +08:00
|
|
|
struct mg_addr loc; // Local address
|
|
|
|
struct mg_addr rem; // Remote address
|
2020-12-05 19:26:32 +08:00
|
|
|
void *fd; // Connected socket, or LWIP data
|
2020-12-21 20:26:44 +08:00
|
|
|
unsigned long id; // Auto-incrementing unique connection ID
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_iobuf recv; // Incoming data
|
|
|
|
struct mg_iobuf send; // Outgoing data
|
|
|
|
mg_event_handler_t fn; // User-specified event handler function
|
2021-03-11 21:15:53 +08:00
|
|
|
void *fn_data; // User-specified function parameter
|
2020-12-05 19:26:32 +08:00
|
|
|
mg_event_handler_t pfn; // Protocol-specific handler function
|
|
|
|
void *pfn_data; // Protocol-specific function parameter
|
2023-01-09 18:58:07 +08:00
|
|
|
char data[MG_DATA_SIZE]; // Arbitrary connection data
|
2020-12-05 19:26:32 +08:00
|
|
|
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
|
2021-03-11 21:15:53 +08:00
|
|
|
unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
|
2023-02-07 10:10:30 +08:00
|
|
|
unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress
|
2020-12-05 19:26:32 +08:00
|
|
|
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
|
2022-07-05 00:47:17 +08:00
|
|
|
unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator
|
2020-12-05 19:26:32 +08:00
|
|
|
unsigned is_hexdumping : 1; // Hexdump in/out traffic
|
2020-12-07 05:12:05 +08:00
|
|
|
unsigned is_draining : 1; // Send remaining data, then close and free
|
|
|
|
unsigned is_closing : 1; // Close and free the connection immediately
|
2022-06-03 18:37:35 +08:00
|
|
|
unsigned is_full : 1; // Stop reads, until cleared
|
2022-08-06 02:18:06 +08:00
|
|
|
unsigned is_resp : 1; // Response is still being generated
|
2020-12-05 19:26:32 +08:00
|
|
|
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);
|
2022-04-22 21:42:07 +08:00
|
|
|
struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
|
|
|
|
mg_event_handler_t fn, void *fn_data);
|
2021-10-22 21:00:31 +08:00
|
|
|
void mg_connect_resolved(struct mg_connection *);
|
2021-05-29 01:30:42 +08:00
|
|
|
bool mg_send(struct mg_connection *, const void *, size_t);
|
2022-02-11 01:11:03 +08:00
|
|
|
size_t mg_printf(struct mg_connection *, const char *fmt, ...);
|
2022-09-23 15:59:02 +08:00
|
|
|
size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
|
2020-12-21 00:55:33 +08:00
|
|
|
bool mg_aton(struct mg_str str, struct mg_addr *addr);
|
2022-06-01 01:23:32 +08:00
|
|
|
int mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *, bool udp);
|
2021-08-08 00:22:47 +08:00
|
|
|
|
2022-02-23 05:14:29 +08:00
|
|
|
// These functions are used to integrate with custom network stacks
|
2022-02-23 18:51:01 +08:00
|
|
|
struct mg_connection *mg_alloc_conn(struct mg_mgr *);
|
2022-02-23 11:06:02 +08:00
|
|
|
void mg_close_conn(struct mg_connection *c);
|
|
|
|
bool mg_open_listener(struct mg_connection *c, const char *url);
|
2023-01-29 22:30:06 +08:00
|
|
|
|
|
|
|
// Utility functions
|
2022-04-12 21:14:55 +08:00
|
|
|
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
|
|
|
|
unsigned flags, void (*fn)(void *), void *arg);
|
2022-02-23 05:14:29 +08:00
|
|
|
|
2022-09-09 18:11:53 +08:00
|
|
|
// Low-level IO primives used by TLS layer
|
|
|
|
enum { MG_IO_ERR = -1, MG_IO_WAIT = -2, MG_IO_RESET = -3 };
|
|
|
|
long mg_io_send(struct mg_connection *c, const void *buf, size_t len);
|
|
|
|
long mg_io_recv(struct mg_connection *c, void *buf, size_t len);
|
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-08 20:25:44 +08:00
|
|
|
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2021-07-29 04:11:07 +08:00
|
|
|
|
2021-12-22 02:16:12 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_http_header {
|
2021-09-15 14:43:48 +08:00
|
|
|
struct mg_str name; // Header name
|
|
|
|
struct mg_str value; // Header value
|
2015-09-08 19:49:03 +08:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_http_message {
|
2020-12-25 23:04:43 +08:00
|
|
|
struct mg_str method, uri, query, proto; // Request/response line
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
|
2020-12-25 23:04:43 +08:00
|
|
|
struct mg_str body; // Body
|
2021-02-09 21:27:17 +08:00
|
|
|
struct mg_str head; // Request + headers
|
2021-03-07 19:56:20 +08:00
|
|
|
struct mg_str chunk; // Chunk for chunked encoding, or partial body
|
2021-02-09 21:27:17 +08:00
|
|
|
struct mg_str message; // Request + headers + body
|
2020-12-05 19:26:32 +08:00
|
|
|
};
|
|
|
|
|
2021-01-02 20:30:09 +08:00
|
|
|
// Parameter for mg_http_serve_dir()
|
|
|
|
struct mg_http_serve_opts {
|
2021-07-24 09:44:25 +08:00
|
|
|
const char *root_dir; // Web root directory, must be non-NULL
|
|
|
|
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
|
|
|
|
const char *extra_headers; // Extra HTTP headers to add in responses
|
2021-07-29 04:11:07 +08:00
|
|
|
const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
|
2022-06-01 06:44:03 +08:00
|
|
|
const char *page404; // Path to the 404 page, or NULL by default
|
2021-07-29 04:11:07 +08:00
|
|
|
struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
|
2021-01-02 20:30:09 +08:00
|
|
|
};
|
|
|
|
|
2021-03-15 21:20:53 +08:00
|
|
|
// 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
|
2021-03-17 15:43:29 +08:00
|
|
|
struct mg_str body; // Part contents
|
2021-03-15 21:20:53 +08:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
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);
|
2021-03-08 23:41:16 +08:00
|
|
|
void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
|
2020-12-05 19:26:32 +08:00
|
|
|
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,
|
2022-04-12 17:04:55 +08:00
|
|
|
const struct mg_http_serve_opts *);
|
2021-07-29 04:11:07 +08:00
|
|
|
void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
|
2022-04-12 17:04:55 +08:00
|
|
|
const char *path, const struct mg_http_serve_opts *);
|
2020-12-18 06:45:22 +08:00
|
|
|
void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
|
|
|
|
const char *body_fmt, ...);
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
2022-06-18 11:23:56 +08:00
|
|
|
struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
|
2021-05-29 01:30:42 +08:00
|
|
|
int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
|
2020-12-05 19:26:32 +08:00
|
|
|
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
2021-05-29 01:30:42 +08:00
|
|
|
size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
|
|
|
void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
|
2020-12-05 19:26:32 +08:00
|
|
|
bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
|
2022-07-01 04:54:50 +08:00
|
|
|
long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
|
|
|
|
struct mg_fs *fs, const char *path, size_t max_size);
|
2020-12-05 19:26:32 +08:00
|
|
|
void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
2021-03-17 15:43:29 +08:00
|
|
|
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 *);
|
2022-02-13 00:51:37 +08:00
|
|
|
int mg_http_status(const struct mg_http_message *hm);
|
2022-10-28 22:35:40 +08:00
|
|
|
void mg_hello(const char *url);
|
2020-12-05 19:26:32 +08:00
|
|
|
|
|
|
|
|
2021-01-03 01:57:51 +08:00
|
|
|
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
|
|
|
|
const char *fullpath);
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
|
2021-12-14 20:42:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_tls_opts {
|
2021-01-30 21:03:11 +08:00
|
|
|
const char *ca; // CA certificate file. For both listeners and clients
|
2021-10-14 23:32:48 +08:00
|
|
|
const char *crl; // Certificate Revocation List. For clients
|
2021-01-30 21:03:11 +08:00
|
|
|
const char *cert; // Certificate
|
|
|
|
const char *certkey; // Certificate key
|
|
|
|
const char *ciphers; // Cipher list
|
|
|
|
struct mg_str srvname; // If not empty, enables server name verification
|
2022-01-19 01:11:02 +08:00
|
|
|
struct mg_fs *fs; // FS API for reading certificate files
|
2020-12-05 19:26:32 +08:00
|
|
|
};
|
|
|
|
|
2022-04-12 17:04:55 +08:00
|
|
|
void mg_tls_init(struct mg_connection *, const struct mg_tls_opts *);
|
2021-05-29 01:30:42 +08:00
|
|
|
void mg_tls_free(struct mg_connection *);
|
|
|
|
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
|
|
|
|
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
|
2022-04-12 16:38:25 +08:00
|
|
|
size_t mg_tls_pending(struct mg_connection *);
|
2021-05-29 01:30:42 +08:00
|
|
|
void mg_tls_handshake(struct mg_connection *);
|
2015-09-08 19:49:03 +08:00
|
|
|
|
|
|
|
|
2021-12-14 20:42:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-01-24 10:20:45 +08:00
|
|
|
|
|
|
|
#if MG_ENABLE_MBEDTLS
|
2021-12-14 20:42:41 +08:00
|
|
|
#include <mbedtls/debug.h>
|
2022-01-19 01:11:02 +08:00
|
|
|
#include <mbedtls/net_sockets.h>
|
2021-12-14 20:42:41 +08:00
|
|
|
#include <mbedtls/ssl.h>
|
|
|
|
|
|
|
|
struct mg_tls {
|
|
|
|
char *cafile; // CA certificate path
|
|
|
|
mbedtls_x509_crt ca; // Parsed CA certificate
|
|
|
|
mbedtls_x509_crt cert; // Parsed certificate
|
|
|
|
mbedtls_ssl_context ssl; // SSL/TLS context
|
|
|
|
mbedtls_ssl_config conf; // SSL-TLS config
|
|
|
|
mbedtls_pk_context pk; // Private key context
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if MG_ENABLE_OPENSSL
|
|
|
|
|
|
|
|
#include <openssl/err.h>
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
|
|
|
struct mg_tls {
|
|
|
|
SSL_CTX *ctx;
|
|
|
|
SSL *ssl;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
#define WEBSOCKET_OP_CONTINUE 0
|
|
|
|
#define WEBSOCKET_OP_TEXT 1
|
|
|
|
#define WEBSOCKET_OP_BINARY 2
|
|
|
|
#define WEBSOCKET_OP_CLOSE 8
|
|
|
|
#define WEBSOCKET_OP_PING 9
|
|
|
|
#define WEBSOCKET_OP_PONG 10
|
2015-09-08 19:49:03 +08:00
|
|
|
|
2016-11-24 17:46:40 +08:00
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_ws_message {
|
2021-09-15 14:43:48 +08:00
|
|
|
struct mg_str data; // Websocket message data
|
|
|
|
uint8_t flags; // Websocket message flags
|
2020-12-05 19:26:32 +08:00
|
|
|
};
|
2016-11-24 17:46:40 +08:00
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url,
|
|
|
|
mg_event_handler_t fn, void *fn_data,
|
|
|
|
const char *fmt, ...);
|
2021-01-17 06:48:43 +08:00
|
|
|
void mg_ws_upgrade(struct mg_connection *, struct mg_http_message *,
|
|
|
|
const char *fmt, ...);
|
2022-08-11 19:11:12 +08:00
|
|
|
size_t mg_ws_send(struct mg_connection *, const void *buf, size_t len, int op);
|
2021-08-01 21:10:21 +08:00
|
|
|
size_t mg_ws_wrap(struct mg_connection *, size_t len, int op);
|
2022-06-05 21:59:50 +08:00
|
|
|
size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...);
|
2022-08-13 18:16:13 +08:00
|
|
|
size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt,
|
|
|
|
va_list *);
|
2016-11-24 17:46:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
|
|
|
|
mg_event_handler_t fn, void *fn_data);
|
2022-05-16 01:41:01 +08:00
|
|
|
void mg_sntp_request(struct mg_connection *c);
|
2021-12-22 05:50:18 +08:00
|
|
|
int64_t mg_sntp_parse(const unsigned char *buf, size_t len);
|
2016-11-24 17:46:40 +08:00
|
|
|
|
2017-10-17 03:00:16 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-10-19 15:38:33 +08:00
|
|
|
|
2020-12-16 04:29:47 +08:00
|
|
|
#define MQTT_CMD_CONNECT 1
|
|
|
|
#define MQTT_CMD_CONNACK 2
|
|
|
|
#define MQTT_CMD_PUBLISH 3
|
|
|
|
#define MQTT_CMD_PUBACK 4
|
|
|
|
#define MQTT_CMD_PUBREC 5
|
|
|
|
#define MQTT_CMD_PUBREL 6
|
|
|
|
#define MQTT_CMD_PUBCOMP 7
|
|
|
|
#define MQTT_CMD_SUBSCRIBE 8
|
|
|
|
#define MQTT_CMD_SUBACK 9
|
|
|
|
#define MQTT_CMD_UNSUBSCRIBE 10
|
|
|
|
#define MQTT_CMD_UNSUBACK 11
|
|
|
|
#define MQTT_CMD_PINGREQ 12
|
|
|
|
#define MQTT_CMD_PINGRESP 13
|
|
|
|
#define MQTT_CMD_DISCONNECT 14
|
2022-06-28 18:31:13 +08:00
|
|
|
#define MQTT_CMD_AUTH 15
|
2020-12-16 04:29:47 +08:00
|
|
|
|
2022-07-02 02:15:38 +08:00
|
|
|
enum { MQTT_OK, MQTT_INCOMPLETE, MQTT_MALFORMED };
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_mqtt_opts {
|
2021-10-31 20:48:32 +08:00
|
|
|
struct mg_str user; // Username, can be empty
|
|
|
|
struct mg_str pass; // Password, can be empty
|
2021-09-15 14:43:48 +08:00
|
|
|
struct mg_str client_id; // Client ID
|
|
|
|
struct mg_str will_topic; // Will topic
|
|
|
|
struct mg_str will_message; // Will message
|
2021-12-23 19:00:18 +08:00
|
|
|
uint8_t will_qos; // Will message quality of service
|
2022-06-28 18:31:13 +08:00
|
|
|
uint8_t version; // Can be 4 (3.1.1), or 5. If 0, assume 4.
|
|
|
|
uint16_t keepalive; // Keep-alive timer in seconds
|
2021-09-15 14:43:48 +08:00
|
|
|
bool will_retain; // Retain last will
|
|
|
|
bool clean; // Use clean session, 0 or 1
|
2017-10-17 03:00:16 +08:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_mqtt_message {
|
2021-06-11 02:15:50 +08:00
|
|
|
struct mg_str topic; // Parsed topic
|
|
|
|
struct mg_str data; // Parsed message
|
|
|
|
struct mg_str dgram; // Whole MQTT datagram, including headers
|
2020-12-16 04:29:47 +08:00
|
|
|
uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
|
|
|
|
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
|
|
|
|
uint8_t qos; // Quality of service
|
|
|
|
uint8_t ack; // Connack return code. 0 - success
|
2017-10-17 03:00:16 +08:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url,
|
2022-04-12 17:04:55 +08:00
|
|
|
const struct mg_mqtt_opts *opts,
|
2020-12-05 19:26:32 +08:00
|
|
|
mg_event_handler_t fn, void *fn_data);
|
2020-12-16 04:29:47 +08:00
|
|
|
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
|
|
|
|
mg_event_handler_t fn, void *fn_data);
|
2022-04-12 17:04:55 +08:00
|
|
|
void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts);
|
2022-01-19 17:57:27 +08:00
|
|
|
void mg_mqtt_pub(struct mg_connection *c, struct mg_str topic,
|
|
|
|
struct mg_str data, int qos, bool retain);
|
|
|
|
void mg_mqtt_sub(struct mg_connection *, struct mg_str topic, int qos);
|
2022-06-28 18:31:13 +08:00
|
|
|
int mg_mqtt_parse(const uint8_t *, size_t, uint8_t, struct mg_mqtt_message *);
|
2020-12-16 04:29:47 +08:00
|
|
|
void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
|
|
|
|
uint32_t len);
|
2021-03-07 20:21:59 +08:00
|
|
|
void mg_mqtt_ping(struct mg_connection *);
|
|
|
|
void mg_mqtt_pong(struct mg_connection *);
|
|
|
|
void mg_mqtt_disconnect(struct mg_connection *);
|
2017-10-17 03:00:16 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-22 17:44:59 +08:00
|
|
|
// Mongoose sends DNS queries that contain only one question:
|
|
|
|
// either A (IPv4) or AAAA (IPv6) address lookup.
|
|
|
|
// Therefore, we expect zero or one answer.
|
|
|
|
// If `resolved` is true, then `addr` contains resolved IPv4 or IPV6 address.
|
2020-12-05 19:26:32 +08:00
|
|
|
struct mg_dns_message {
|
2020-12-22 17:44:59 +08:00
|
|
|
uint16_t txnid; // Transaction ID
|
|
|
|
bool resolved; // Resolve successful, addr is set
|
|
|
|
struct mg_addr addr; // Resolved address
|
|
|
|
char name[256]; // Host name
|
2020-12-05 19:26:32 +08:00
|
|
|
};
|
2017-10-17 03:00:16 +08:00
|
|
|
|
2020-12-28 13:25:29 +08:00
|
|
|
struct mg_dns_header {
|
|
|
|
uint16_t txnid; // Transaction ID
|
|
|
|
uint16_t flags;
|
|
|
|
uint16_t num_questions;
|
|
|
|
uint16_t num_answers;
|
|
|
|
uint16_t num_authority_prs;
|
|
|
|
uint16_t num_other_prs;
|
|
|
|
};
|
|
|
|
|
|
|
|
// DNS resource record
|
|
|
|
struct mg_dns_rr {
|
|
|
|
uint16_t nlen; // Name or pointer length
|
|
|
|
uint16_t atype; // Address type
|
|
|
|
uint16_t aclass; // Address class
|
|
|
|
uint16_t alen; // Address length
|
|
|
|
};
|
|
|
|
|
2022-01-07 23:00:10 +08:00
|
|
|
void mg_resolve(struct mg_connection *, const char *url);
|
2020-12-22 17:44:59 +08:00
|
|
|
void mg_resolve_cancel(struct mg_connection *);
|
2020-12-21 00:55:33 +08:00
|
|
|
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
2020-12-28 13:25:29 +08:00
|
|
|
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
|
|
|
bool is_question, struct mg_dns_rr *);
|
2021-07-13 13:58:34 +08:00
|
|
|
|
2022-05-19 04:19:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-12 00:29:45 +08:00
|
|
|
#ifndef MG_JSON_MAX_DEPTH
|
|
|
|
#define MG_JSON_MAX_DEPTH 30
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Error return values - negative. Successful returns are >= 0
|
|
|
|
enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
|
2022-07-30 14:55:26 +08:00
|
|
|
int mg_json_get(struct mg_str json, const char *path, int *toklen);
|
2022-06-12 00:29:45 +08:00
|
|
|
|
|
|
|
bool mg_json_get_num(struct mg_str json, const char *path, double *v);
|
|
|
|
bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
|
2022-07-01 03:03:02 +08:00
|
|
|
long mg_json_get_long(struct mg_str json, const char *path, long dflt);
|
2022-06-12 00:29:45 +08:00
|
|
|
char *mg_json_get_str(struct mg_str json, const char *path);
|
2022-06-22 23:28:22 +08:00
|
|
|
char *mg_json_get_hex(struct mg_str json, const char *path, int *len);
|
|
|
|
char *mg_json_get_b64(struct mg_str json, const char *path, int *len);
|
2022-06-12 00:29:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2022-07-28 17:18:17 +08:00
|
|
|
|
2022-07-27 07:46:05 +08:00
|
|
|
// JSON-RPC request descriptor
|
|
|
|
struct mg_rpc_req {
|
2022-08-01 05:51:59 +08:00
|
|
|
struct mg_rpc **head; // RPC handlers list head
|
|
|
|
struct mg_rpc *rpc; // RPC handler being called
|
|
|
|
mg_pfn_t pfn; // Response printing function
|
|
|
|
void *pfn_data; // Response printing function data
|
|
|
|
void *req_data; // Arbitrary request data
|
|
|
|
struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
|
2022-07-27 07:46:05 +08:00
|
|
|
};
|
|
|
|
|
2022-08-01 05:51:59 +08:00
|
|
|
// JSON-RPC method handler
|
|
|
|
struct mg_rpc {
|
|
|
|
struct mg_rpc *next; // Next in list
|
|
|
|
struct mg_str method; // Method pattern
|
|
|
|
void (*fn)(struct mg_rpc_req *); // Handler function
|
|
|
|
void *fn_data; // Handler function argument
|
|
|
|
};
|
|
|
|
|
|
|
|
void mg_rpc_add(struct mg_rpc **head, struct mg_str method_pattern,
|
2022-07-27 07:46:05 +08:00
|
|
|
void (*handler)(struct mg_rpc_req *), void *handler_data);
|
2022-08-01 05:51:59 +08:00
|
|
|
void mg_rpc_del(struct mg_rpc **head, void (*handler)(struct mg_rpc_req *));
|
2022-07-30 14:55:26 +08:00
|
|
|
void mg_rpc_process(struct mg_rpc_req *);
|
2022-07-27 07:46:05 +08:00
|
|
|
|
|
|
|
// Helper functions to print result or error frame
|
|
|
|
void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
|
|
|
|
void mg_rpc_vok(struct mg_rpc_req *, const char *fmt, va_list *ap);
|
|
|
|
void mg_rpc_err(struct mg_rpc_req *, int code, const char *fmt, ...);
|
|
|
|
void mg_rpc_verr(struct mg_rpc_req *, int code, const char *fmt, va_list *);
|
|
|
|
void mg_rpc_list(struct mg_rpc_req *r);
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-12 00:29:45 +08:00
|
|
|
|
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_if; // MIP network interface
|
2022-12-19 19:43:25 +08:00
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_driver {
|
|
|
|
bool (*init)(struct mg_tcpip_if *); // Init driver
|
|
|
|
size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame
|
|
|
|
size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame
|
|
|
|
bool (*up)(struct mg_tcpip_if *); // Up/down status
|
2022-05-19 04:19:21 +08:00
|
|
|
};
|
|
|
|
|
2022-11-09 21:11:22 +08:00
|
|
|
// Receive queue - single producer, single consumer queue. Interrupt-based
|
2023-02-08 05:16:42 +08:00
|
|
|
// drivers copy received frames to the queue in interrupt context.
|
|
|
|
// mg_tcpip_poll() function runs in event loop context, reads from the queue
|
2022-11-09 21:11:22 +08:00
|
|
|
struct queue {
|
|
|
|
uint8_t *buf;
|
|
|
|
size_t len;
|
|
|
|
volatile size_t tail, head;
|
2022-05-19 04:19:21 +08:00
|
|
|
};
|
|
|
|
|
2022-11-09 21:11:22 +08:00
|
|
|
// Network interface
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_if {
|
|
|
|
uint8_t mac[6]; // MAC address. Must be set to a valid MAC
|
|
|
|
uint32_t ip, mask, gw; // IP address, mask, default gateway
|
|
|
|
struct mg_str rx; // Output (TX) buffer
|
|
|
|
struct mg_str tx; // Input (RX) buffer
|
|
|
|
bool enable_dhcp_client; // Enable DCHP client
|
|
|
|
bool enable_dhcp_server; // Enable DCHP server
|
|
|
|
struct mg_tcpip_driver *driver; // Low level driver
|
|
|
|
void *driver_data; // Driver-specific data
|
|
|
|
struct mg_mgr *mgr; // Mongoose event manager
|
|
|
|
struct queue queue; // Set queue.len for interrupt based drivers
|
2022-11-09 21:11:22 +08:00
|
|
|
|
|
|
|
// Internal state, user can use it but should not change it
|
2023-02-07 10:10:30 +08:00
|
|
|
uint8_t gwmac[6]; // Router's MAC
|
|
|
|
uint64_t now; // Current time
|
|
|
|
uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
|
|
|
|
uint64_t lease_expire; // Lease expiration time
|
|
|
|
uint16_t eport; // Next ephemeral port
|
|
|
|
volatile uint32_t ndrop; // Number of received, but dropped frames
|
|
|
|
volatile uint32_t nrecv; // Number of received frames
|
|
|
|
volatile uint32_t nsent; // Number of transmitted frames
|
|
|
|
volatile uint32_t nerr; // Number of driver errors
|
|
|
|
uint8_t state; // Current state
|
|
|
|
#define MIP_STATE_DOWN 0 // Interface is down
|
|
|
|
#define MIP_STATE_UP 1 // Interface is up
|
|
|
|
#define MIP_STATE_READY 2 // Interface is up and has IP
|
2022-11-09 21:11:22 +08:00
|
|
|
};
|
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
|
|
|
|
void mg_tcpip_free(struct mg_tcpip_if *);
|
|
|
|
void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
|
|
|
|
size_t mg_tcpip_qread(void *buf, struct mg_tcpip_if *ifp);
|
2023-01-04 06:33:26 +08:00
|
|
|
// conveniency rx function for IRQ-driven drivers
|
2023-02-08 05:16:42 +08:00
|
|
|
size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp);
|
2022-05-19 04:19:21 +08:00
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
extern struct mg_tcpip_driver mg_tcpip_driver_stm32;
|
|
|
|
extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
|
|
|
|
extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
|
|
|
|
extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
|
2023-02-09 22:57:44 +08:00
|
|
|
extern struct mg_tcpip_driver mg_tcpip_driver_imxrt1020;
|
2022-08-31 15:34:38 +08:00
|
|
|
|
|
|
|
// Drivers that require SPI, can use this SPI abstraction
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_spi {
|
2022-08-31 15:34:38 +08:00
|
|
|
void *spi; // Opaque SPI bus descriptor
|
|
|
|
void (*begin)(void *); // SPI begin: slave select low
|
|
|
|
void (*end)(void *); // SPI end: slave select high
|
2022-09-02 19:58:43 +08:00
|
|
|
uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
|
2022-08-31 15:34:38 +08:00
|
|
|
};
|
2022-06-09 19:39:48 +08:00
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
#if MG_ENABLE_TCPIP
|
2023-02-04 03:32:38 +08:00
|
|
|
#if !defined(MG_ENABLE_DRIVER_STM32H) && !defined(MG_ENABLE_DRIVER_TM4C)
|
|
|
|
#define MG_ENABLE_DRIVER_STM32 1
|
2023-02-07 03:22:43 +08:00
|
|
|
#else
|
2023-02-04 03:32:38 +08:00
|
|
|
#define MG_ENABLE_DRIVER_STM32 0
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2022-09-11 19:19:01 +08:00
|
|
|
|
2023-02-09 22:57:44 +08:00
|
|
|
struct mg_tcpip_driver_imxrt1020_data {
|
|
|
|
// MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
|
|
|
|
// must not exceed 2.5MHz. Configuration for clock range 2.36~2.50 MHz
|
|
|
|
// ipg_clk MSCR mdc_cr VALUE
|
|
|
|
// -------------------------------------
|
|
|
|
// -1 <-- tell driver to guess the value
|
|
|
|
// 25 MHz 0x04 0
|
|
|
|
// 33 MHz 0x06 1
|
|
|
|
// 40 MHz 0x07 2
|
|
|
|
// 50 MHz 0x09 3
|
|
|
|
// 66 MHz 0x0D 4 <-- value for iMXRT1020-EVK at max freq.
|
|
|
|
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_driver_stm32_data {
|
2022-09-11 19:19:01 +08:00
|
|
|
// MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
|
|
|
|
// HCLK range DIVIDER mdc_cr VALUE
|
|
|
|
// -------------------------------------
|
|
|
|
// -1 <-- tell driver to guess the value
|
|
|
|
// 60-100 MHz HCLK/42 0
|
|
|
|
// 100-150 MHz HCLK/62 1
|
|
|
|
// 20-35 MHz HCLK/16 2
|
|
|
|
// 35-60 MHz HCLK/26 3
|
|
|
|
// 150-216 MHz HCLK/102 4 <-- value for Nucleo-F* on max speed
|
|
|
|
// 216-310 MHz HCLK/124 5
|
|
|
|
// 110, 111 Reserved
|
|
|
|
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
|
|
|
|
};
|
|
|
|
|
2022-11-11 22:01:17 +08:00
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_driver_stm32h_data {
|
2023-02-04 03:32:38 +08:00
|
|
|
// MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
|
|
|
|
// HCLK range DIVIDER mdc_cr VALUE
|
|
|
|
// -------------------------------------
|
|
|
|
// -1 <-- tell driver to guess the value
|
|
|
|
// 60-100 MHz HCLK/42 0
|
|
|
|
// 100-150 MHz HCLK/62 1
|
|
|
|
// 20-35 MHz HCLK/16 2
|
|
|
|
// 35-60 MHz HCLK/26 3
|
|
|
|
// 150-250 MHz HCLK/102 4 <-- value for Nucleo-H* on max speed driven by HSI
|
|
|
|
// 250-300 MHz HCLK/124 5 <-- value for Nucleo-H* on max speed driven by CSI
|
|
|
|
// 110, 111 Reserved
|
|
|
|
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-02-08 05:16:42 +08:00
|
|
|
struct mg_tcpip_driver_tm4c_data {
|
2022-11-11 22:01:17 +08:00
|
|
|
// MDC clock divider. MDC clock is derived from SYSCLK, must not exceed 2.5MHz
|
|
|
|
// SYSCLK range DIVIDER mdc_cr VALUE
|
|
|
|
// -------------------------------------
|
|
|
|
// -1 <-- tell driver to guess the value
|
|
|
|
// 60-100 MHz SYSCLK/42 0
|
|
|
|
// 100-150 MHz SYSCLK/62 1 <-- value for EK-TM4C129* on max speed
|
|
|
|
// 20-35 MHz SYSCLK/16 2
|
|
|
|
// 35-60 MHz SYSCLK/26 3
|
|
|
|
// 0x4-0xF Reserved
|
|
|
|
int mdc_cr; // Valid values: -1, 0, 1, 2, 3
|
|
|
|
};
|
|
|
|
|
2021-07-13 13:58:34 +08:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
2021-07-19 16:04:18 +08:00
|
|
|
#endif // MONGOOSE_H
|