1 // Copyright (c) 2004-2013 Sergey Lyubka
2 // Copyright (c) 2013-2022 Cesanta Software Limited
5 // This software is dual-licensed: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation. For the terms of this
8 // license, see http://www.gnu.org/licenses/
10 // You are free to use this software under the terms of the GNU General
11 // Public License, but WITHOUT ANY WARRANTY; without even the implied
12 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU General Public License for more details.
15 // Alternatively, you can license this software under a commercial
16 // license, as set out in https://www.mongoose.ws/licensing/
18 // SPDX-License-Identifier: GPL-2.0-only or commercial
23 #define MG_VERSION "7.11"
30 #define MG_ARCH_CUSTOM 0 // User creates its own mongoose_custom.h
31 #define MG_ARCH_UNIX 1 // Linux, BSD, Mac, ...
32 #define MG_ARCH_WIN32 2 // Windows
33 #define MG_ARCH_ESP32 3 // ESP32
34 #define MG_ARCH_ESP8266 4 // ESP8266
35 #define MG_ARCH_FREERTOS 5 // FreeRTOS
36 #define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
37 #define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
38 #define MG_ARCH_NEWLIB 8 // Bare metal ARM
39 #define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
40 #define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
41 #define MG_ARCH_RP2040 11 // Raspberry Pi RP2040
42 #define MG_ARCH_ARMCC 12 // Keil MDK-Core with Configuration Wizard
43 #define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS)
44 #define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS
47 #if defined(__unix__) || defined(__APPLE__)
48 #define MG_ARCH MG_ARCH_UNIX
50 #define MG_ARCH MG_ARCH_WIN32
51 #elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
52 #define MG_ARCH MG_ARCH_ESP8266
53 #elif defined(__ZEPHYR__)
54 #define MG_ARCH MG_ARCH_ZEPHYR
55 #elif defined(ESP_PLATFORM)
56 #define MG_ARCH MG_ARCH_ESP32
57 #elif defined(FREERTOS_IP_H)
58 #define MG_ARCH MG_ARCH_FREERTOS
59 #define MG_ENABLE_FREERTOS_TCP 1
60 #elif defined(AZURE_RTOS_THREADX)
61 #define MG_ARCH MG_ARCH_AZURERTOS
62 #elif defined(PICO_TARGET_NAME)
63 #define MG_ARCH MG_ARCH_RP2040
64 #elif defined(__ARMCC_VERSION)
65 #define MG_ARCH MG_ARCH_ARMCC
66 #elif defined(__RTTHREAD__)
67 #define MG_ARCH MG_ARCH_RTTHREAD
69 #endif // !defined(MG_ARCH)
71 // if the user did not specify an MG_ARCH, or specified a custom one, OR
72 // we guessed a known IDE, pull the customized config (Configuration Wizard)
73 #if !defined(MG_ARCH) || (MG_ARCH == MG_ARCH_CUSTOM) || MG_ARCH == MG_ARCH_ARMCC
74 #include "mongoose_custom.h" // keep this include
78 #error "MG_ARCH is not specified and we couldn't guess it. Set -D MG_ARCH=..."
81 // http://esr.ibiblio.org/?p=5095
82 #define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
98 #if MG_ARCH == MG_ARCH_AZURERTOS
114 #define PATH_MAX FX_MAXIMUM_PATH
115 #define MG_DIRSEP '\\'
117 #define socklen_t int
118 #define closesocket(x) soc_close(x)
125 #if MG_ARCH == MG_ARCH_ESP32
138 #include <sys/stat.h>
139 #include <sys/types.h>
142 #include <esp_timer.h>
144 #define MG_PATH_MAX 128
149 #if MG_ARCH == MG_ARCH_ESP8266
163 #include <sys/stat.h>
164 #include <sys/time.h>
165 #include <sys/types.h>
168 #include <esp_system.h>
170 #define MG_PATH_MAX 128
175 #if MG_ARCH == MG_ARCH_FREERTOS
178 #if !defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP
186 #include <stdlib.h> // rand(), strtol(), atoi()
188 #if defined(__ARMCC_VERSION)
189 #define mode_t size_t
192 #include <sys/stat.h>
195 #include <FreeRTOS.h>
199 #define MG_IO_SIZE 512
202 #define calloc(a, b) mg_calloc(a, b)
203 #define free(a) vPortFree(a)
204 #define malloc(a) pvPortMalloc(a)
205 #define strdup(s) ((char *) mg_strdup(mg_str(s)).ptr)
207 // Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
208 static inline void *mg_calloc(size_t cnt, size_t size) {
209 void *p = pvPortMalloc(cnt * size);
210 if (p != NULL) memset(p, 0, size * cnt);
214 #define mkdir(a, b) mg_mkdir(a, b)
215 static inline int mg_mkdir(const char *path, mode_t mode) {
216 (void) path, (void) mode;
220 #endif // MG_ARCH == MG_ARCH_FREERTOS
223 #if MG_ARCH == MG_ARCH_NEWLIB
224 #define _POSIX_TIMERS
233 #include <sys/stat.h>
234 #include <sys/time.h>
235 #include <sys/types.h>
239 #define MG_PATH_MAX 100
240 #define MG_ENABLE_SOCKET 0
241 #define MG_ENABLE_DIRLIST 0
246 #if MG_ARCH == MG_ARCH_RP2040
256 #include <pico/stdlib.h>
257 int mkdir(const char *, mode_t);
261 #if MG_ARCH == MG_ARCH_RTTHREAD
\r
263 #include <rtthread.h>
\r
267 #include <sys/socket.h>
\r
268 #include <sys/select.h>
\r
269 #include <stdarg.h>
\r
270 #include <stdbool.h>
\r
271 #include <stdint.h>
\r
273 #include <stdlib.h>
\r
274 #include <string.h>
\r
275 #include <sys/types.h>
\r
279 #define MG_IO_SIZE 1460
\r
282 #endif // MG_ARCH == MG_ARCH_RTTHREAD
\r
285 #if MG_ARCH == MG_ARCH_ARMCC || MG_ARCH == MG_ARCH_CMSIS_RTOS1 || \
286 MG_ARCH == MG_ARCH_CMSIS_RTOS2
298 #if MG_ARCH == MG_ARCH_CMSIS_RTOS1
299 #include "cmsis_os.h" // keep this include
300 // https://developer.arm.com/documentation/ka003821/latest
301 extern uint32_t rt_time_get(void);
302 #elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
303 #include "cmsis_os2.h" // keep this include
306 #define strdup(s) ((char *) mg_strdup(mg_str(s)).ptr)
308 #if defined(__ARMCC_VERSION)
309 #define mode_t size_t
310 #define mkdir(a, b) mg_mkdir(a, b)
311 static inline int mg_mkdir(const char *path, mode_t mode) {
312 (void) path, (void) mode;
317 #if (MG_ARCH == MG_ARCH_CMSIS_RTOS1 || MG_ARCH == MG_ARCH_CMSIS_RTOS2) && \
318 !defined MG_ENABLE_RL && (!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && \
319 (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP)
320 #define MG_ENABLE_RL 1
326 #if MG_ARCH == MG_ARCH_TIRTOS
338 #include <sys/socket.h>
340 #include <ti/sysbios/knl/Clock.h>
345 #if MG_ARCH == MG_ARCH_UNIX
347 #define _DARWIN_UNLIMITED_SELECT 1 // No limit on file descriptors
349 #if defined(__APPLE__)
350 #include <mach/mach_time.h>
353 #if !defined(MG_ENABLE_EPOLL) && defined(__linux__)
354 #define MG_ENABLE_EPOLL 1
355 #elif !defined(MG_ENABLE_POLL)
356 #define MG_ENABLE_POLL 1
359 #include <arpa/inet.h>
364 #include <inttypes.h>
367 #include <netinet/in.h>
368 #include <netinet/tcp.h>
378 #if defined(MG_ENABLE_EPOLL) && MG_ENABLE_EPOLL
379 #include <sys/epoll.h>
380 #elif defined(MG_ENABLE_POLL) && MG_ENABLE_POLL
383 #include <sys/select.h>
386 #include <sys/socket.h>
387 #include <sys/stat.h>
388 #include <sys/time.h>
389 #include <sys/types.h>
393 #ifndef MG_ENABLE_DIRLIST
394 #define MG_ENABLE_DIRLIST 1
398 #define MG_PATH_MAX FILENAME_MAX
404 #if MG_ARCH == MG_ARCH_WIN32
406 #ifndef WIN32_LEAN_AND_MEAN
407 #define WIN32_LEAN_AND_MEAN
410 #ifndef _CRT_SECURE_NO_WARNINGS
411 #define _CRT_SECURE_NO_WARNINGS
414 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
415 #define _WINSOCK_DEPRECATED_NO_WARNINGS
429 #include <sys/stat.h>
430 #include <sys/types.h>
433 #if defined(_MSC_VER) && _MSC_VER < 1700
435 typedef __int64 int64_t;
436 typedef unsigned __int64 uint64_t;
437 typedef unsigned char uint8_t;
439 typedef unsigned short uint16_t;
440 typedef short int16_t;
441 typedef unsigned int uint32_t;
443 typedef enum { false = 0, true = 1 } bool;
447 #include <ws2tcpip.h>
451 #include <winerror.h>
452 #include <winsock2.h>
454 // Protect from calls like std::snprintf in app code
455 // See https://github.com/cesanta/mongoose/issues/1047
457 #define snprintf _snprintf
458 #define vsnprintf _vsnprintf
459 #ifndef strdup // For MSVC with _DEBUG, see #1359
460 #define strdup(x) _strdup(x)
464 #define MG_INVALID_SOCKET INVALID_SOCKET
465 #define MG_SOCKET_TYPE SOCKET
466 typedef unsigned long nfds_t;
467 #if defined(_MSC_VER)
468 #pragma comment(lib, "ws2_32.lib")
470 #define alloca(a) _alloca(a)
473 #define poll(a, b, c) WSAPoll((a), (b), (c))
474 #define closesocket(x) closesocket(x)
476 typedef int socklen_t;
477 #define MG_DIRSEP '\\'
480 #define MG_PATH_MAX FILENAME_MAX
483 #ifndef SO_EXCLUSIVEADDRUSE
484 #define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
487 #define MG_SOCK_ERR(errcode) ((errcode) < 0 ? WSAGetLastError() : 0)
489 #define MG_SOCK_PENDING(errcode) \
490 (((errcode) < 0) && \
491 (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || \
492 WSAGetLastError() == WSAEWOULDBLOCK))
494 #define MG_SOCK_RESET(errcode) \
495 (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
497 #define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
498 #define sleep(x) Sleep((x) *1000)
499 #define mkdir(a, b) _mkdir(a)
502 #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
505 #ifndef MG_ENABLE_DIRLIST
506 #define MG_ENABLE_DIRLIST 1
516 #if MG_ARCH == MG_ARCH_ZEPHYR
518 #include <zephyr/kernel.h>
523 #include <zephyr/net/socket.h>
530 #include <sys/types.h>
533 #define MG_PUTCHAR(x) printk("%c", x)
535 #define strdup(s) ((char *) mg_strdup(mg_str(s)).ptr)
537 #define strerror(x) zsock_gai_strerror(x)
540 #define MG_ENABLE_SSI 0
543 int sscanf(const char *, const char *, ...);
548 #if defined(MG_ENABLE_FREERTOS_TCP) && MG_ENABLE_FREERTOS_TCP
553 #include <FreeRTOS_IP.h>
554 #include <FreeRTOS_Sockets.h>
555 #include <FreeRTOS_errno_TCP.h> // contents to be moved and file removed, some day
557 #define MG_SOCKET_TYPE Socket_t
558 #define MG_INVALID_SOCKET FREERTOS_INVALID_SOCKET
560 // Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing
561 // with FreeRTOS_ prefix, is beyond me
562 #define IPPROTO_TCP FREERTOS_IPPROTO_TCP
563 #define IPPROTO_UDP FREERTOS_IPPROTO_UDP
564 #define AF_INET FREERTOS_AF_INET
565 #define SOCK_STREAM FREERTOS_SOCK_STREAM
566 #define SOCK_DGRAM FREERTOS_SOCK_DGRAM
567 #define SO_BROADCAST 0
570 #define SO_REUSEADDR 0
572 #define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0)
574 #define MG_SOCK_PENDING(errcode) \
575 ((errcode) == -pdFREERTOS_ERRNO_EWOULDBLOCK || \
576 (errcode) == -pdFREERTOS_ERRNO_EISCONN || \
577 (errcode) == -pdFREERTOS_ERRNO_EINPROGRESS || \
578 (errcode) == -pdFREERTOS_ERRNO_EAGAIN)
580 #define MG_SOCK_RESET(errcode) ((errcode) == -pdFREERTOS_ERRNO_ENOTCONN)
582 // actually only if optional timeout is enabled
583 #define MG_SOCK_INTR(fd) (fd == NULL)
585 #define sockaddr_in freertos_sockaddr
586 #define sockaddr freertos_sockaddr
587 #define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
588 #define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
589 #define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
590 #define listen(a, b) FreeRTOS_listen((a), (b))
591 #define socket(a, b, c) FreeRTOS_socket((a), (b), (c))
592 #define send(a, b, c, d) FreeRTOS_send((a), (b), (c), (d))
593 #define recv(a, b, c, d) FreeRTOS_recv((a), (b), (c), (d))
594 #define setsockopt(a, b, c, d, e) FreeRTOS_setsockopt((a), (b), (c), (d), (e))
595 #define sendto(a, b, c, d, e, f) FreeRTOS_sendto((a), (b), (c), (d), (e), (f))
596 #define recvfrom(a, b, c, d, e, f) \
597 FreeRTOS_recvfrom((a), (b), (c), (d), (e), (f))
598 #define closesocket(x) FreeRTOS_closesocket(x)
599 #define gethostbyname(x) FreeRTOS_gethostbyname(x)
600 #define getsockname(a, b, c) mg_getsockname((a), (b), (c))
601 #define getpeername(a, b, c) mg_getpeername((a), (b), (c))
603 static inline int mg_getsockname(MG_SOCKET_TYPE fd, void *buf, socklen_t *len) {
604 (void) fd, (void) buf, (void) len;
608 static inline int mg_getpeername(MG_SOCKET_TYPE fd, void *buf, socklen_t *len) {
609 (void) fd, (void) buf, (void) len;
615 #if defined(MG_ENABLE_LWIP) && MG_ENABLE_LWIP
617 #if defined(__GNUC__) && !defined(__ARMCC_VERSION)
618 #include <sys/stat.h>
623 #include <lwip/sockets.h>
625 #if !LWIP_TIMEVAL_PRIVATE
626 #if defined(__GNUC__) && !defined(__ARMCC_VERSION) // armclang sets both
627 #include <sys/time.h>
637 // Sockets support disabled in LWIP by default
638 #error Set LWIP_SOCKET variable to 1 (in lwipopts.h)
643 #if defined(MG_ENABLE_RL) && MG_ENABLE_RL
646 #define closesocket(x) closesocket(x)
648 #define TCP_NODELAY SO_KEEPALIVE
650 #define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0)
652 #define MG_SOCK_PENDING(errcode) \
653 ((errcode) == BSD_EWOULDBLOCK || (errcode) == BSD_EALREADY || \
654 (errcode) == BSD_EINPROGRESS)
656 #define MG_SOCK_RESET(errcode) \
657 ((errcode) == BSD_ECONNABORTED || (errcode) == BSD_ECONNRESET)
659 // In blocking mode, which is enabled by default, accept() waits for a
660 // connection request. In non blocking mode, you must call accept()
661 // again if the error code BSD_EWOULDBLOCK is returned.
662 #define MG_SOCK_INTR(fd) (fd == BSD_EWOULDBLOCK)
664 #define socklen_t int
668 #ifndef MG_ENABLE_LOG
669 #define MG_ENABLE_LOG 1
672 #ifndef MG_ENABLE_TCPIP
673 #define MG_ENABLE_TCPIP 0 // Mongoose built-in network stack
676 #ifndef MG_ENABLE_LWIP
677 #define MG_ENABLE_LWIP 0 // lWIP network stack
680 #ifndef MG_ENABLE_FREERTOS_TCP
681 #define MG_ENABLE_FREERTOS_TCP 0 // Amazon FreeRTOS-TCP network stack
685 #define MG_ENABLE_RL 0 // ARM MDK network stack
688 #ifndef MG_ENABLE_SOCKET
689 #define MG_ENABLE_SOCKET !MG_ENABLE_TCPIP
692 #ifndef MG_ENABLE_POLL
693 #define MG_ENABLE_POLL 0
696 #ifndef MG_ENABLE_EPOLL
697 #define MG_ENABLE_EPOLL 0
700 #ifndef MG_ENABLE_FATFS
701 #define MG_ENABLE_FATFS 0
704 #ifndef MG_ENABLE_SSI
705 #define MG_ENABLE_SSI 0
708 #ifndef MG_ENABLE_IPV6
709 #define MG_ENABLE_IPV6 0
712 #ifndef MG_ENABLE_MD5
713 #define MG_ENABLE_MD5 1
716 // Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
717 #ifndef MG_ENABLE_WINSOCK
718 #define MG_ENABLE_WINSOCK 1
721 #ifndef MG_ENABLE_DIRLIST
722 #define MG_ENABLE_DIRLIST 0
725 #ifndef MG_ENABLE_CUSTOM_RANDOM
726 #define MG_ENABLE_CUSTOM_RANDOM 0
729 #ifndef MG_ENABLE_CUSTOM_MILLIS
730 #define MG_ENABLE_CUSTOM_MILLIS 0
733 #ifndef MG_ENABLE_PACKED_FS
734 #define MG_ENABLE_PACKED_FS 0
737 #ifndef MG_ENABLE_ASSERT
738 #define MG_ENABLE_ASSERT 0
742 #define MG_IO_SIZE 2048 // Granularity of the send/recv IO buffer growth
745 #ifndef MG_MAX_RECV_SIZE
746 #define MG_MAX_RECV_SIZE (3UL * 1024UL * 1024UL) // Maximum recv IO buffer size
750 #define MG_DATA_SIZE 32 // struct mg_connection :: data size
753 #ifndef MG_MAX_HTTP_HEADERS
754 #define MG_MAX_HTTP_HEADERS 30
757 #ifndef MG_HTTP_INDEX
758 #define MG_HTTP_INDEX "index.html"
763 #define MG_PATH_MAX PATH_MAX
765 #define MG_PATH_MAX 128
769 #ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
770 #define MG_SOCK_LISTEN_BACKLOG_SIZE 3
774 #define MG_DIRSEP '/'
777 #ifndef MG_ENABLE_FILE
778 #if defined(FOPEN_MAX)
779 #define MG_ENABLE_FILE 1
781 #define MG_ENABLE_FILE 0
785 #ifndef MG_INVALID_SOCKET
786 #define MG_INVALID_SOCKET (-1)
789 #ifndef MG_SOCKET_TYPE
790 #define MG_SOCKET_TYPE int
793 #ifndef MG_SOCKET_ERRNO
794 #define MG_SOCKET_ERRNO errno
798 #define MG_EPOLL_ADD(c) \
800 struct epoll_event ev = {EPOLLIN | EPOLLERR | EPOLLHUP, {c}}; \
801 epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_ADD, (int) (size_t) c->fd, &ev); \
803 #define MG_EPOLL_MOD(c, wr) \
805 struct epoll_event ev = {EPOLLIN | EPOLLERR | EPOLLHUP, {c}}; \
806 if (wr) ev.events |= EPOLLOUT; \
807 epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_MOD, (int) (size_t) c->fd, &ev); \
810 #define MG_EPOLL_ADD(c)
811 #define MG_EPOLL_MOD(c, wr)
818 const char *ptr; // Pointer to string data
819 size_t len; // String len
822 #define MG_NULL_STR \
825 #define MG_C_STR(a) \
826 { (a), sizeof(a) - 1 }
828 // Using macro to avoid shadowing C++ struct constructor, see #1298
829 #define mg_str(s) mg_str_s(s)
831 struct mg_str mg_str(const char *s);
832 struct mg_str mg_str_n(const char *s, size_t n);
833 int mg_lower(const char *s);
834 int mg_ncasecmp(const char *s1, const char *s2, size_t len);
835 int mg_casecmp(const char *s1, const char *s2);
836 int mg_vcmp(const struct mg_str *s1, const char *s2);
837 int mg_vcasecmp(const struct mg_str *str1, const char *str2);
838 int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
839 struct mg_str mg_strstrip(struct mg_str s);
840 struct mg_str mg_strdup(const struct mg_str s);
841 const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
842 bool mg_match(struct mg_str str, struct mg_str pattern, struct mg_str *caps);
843 bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
844 bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
845 bool mg_split(struct mg_str *s, struct mg_str *k, struct mg_str *v, char delim);
846 char *mg_hex(const void *buf, size_t len, char *dst);
847 void mg_unhex(const char *buf, size_t len, unsigned char *to);
848 unsigned long mg_unhexn(const char *s, size_t len);
849 bool mg_path_is_sane(const char *path);
854 // Single producer, single consumer non-blocking queue
859 volatile size_t tail;
860 volatile size_t head;
863 void mg_queue_init(struct mg_queue *, char *, size_t); // Init queue
864 size_t mg_queue_book(struct mg_queue *, char **buf, size_t); // Reserve space
865 void mg_queue_add(struct mg_queue *, size_t); // Add new message
866 size_t mg_queue_next(struct mg_queue *, char **); // Get oldest message
867 void mg_queue_del(struct mg_queue *, size_t); // Delete oldest message
872 typedef void (*mg_pfn_t)(char, void *); // Output function
873 typedef size_t (*mg_pm_t)(mg_pfn_t, void *, va_list *); // %M printer
875 size_t mg_vxprintf(void (*)(char, void *), void *, const char *fmt, va_list *);
876 size_t mg_xprintf(void (*fn)(char, void *), void *, const char *fmt, ...);
883 // Convenience wrappers around mg_xprintf
884 size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap);
885 size_t mg_snprintf(char *, size_t, const char *fmt, ...);
886 char *mg_vmprintf(const char *fmt, va_list *ap);
887 char *mg_mprintf(const char *fmt, ...);
888 size_t mg_queue_vprintf(struct mg_queue *, const char *fmt, va_list *);
889 size_t mg_queue_printf(struct mg_queue *, const char *fmt, ...);
891 // %M print helper functions
892 size_t mg_print_base64(void (*out)(char, void *), void *arg, va_list *ap);
893 size_t mg_print_esc(void (*out)(char, void *), void *arg, va_list *ap);
894 size_t mg_print_hex(void (*out)(char, void *), void *arg, va_list *ap);
895 size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap);
896 size_t mg_print_ip_port(void (*out)(char, void *), void *arg, va_list *ap);
897 size_t mg_print_ip4(void (*out)(char, void *), void *arg, va_list *ap);
898 size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap);
899 size_t mg_print_mac(void (*out)(char, void *), void *arg, va_list *ap);
901 // Various output functions
902 void mg_pfn_iobuf(char ch, void *param); // param: struct mg_iobuf *
903 void mg_pfn_stdout(char c, void *param); // param: ignored
905 // A helper macro for printing JSON: mg_snprintf(buf, len, "%m", MG_ESC("hi"))
906 #define MG_ESC(str) mg_print_esc, 0, (str)
913 enum { MG_LL_NONE, MG_LL_ERROR, MG_LL_INFO, MG_LL_DEBUG, MG_LL_VERBOSE };
914 void mg_log(const char *fmt, ...);
915 bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
916 void mg_log_set(int log_level);
917 void mg_hexdump(const void *buf, size_t len);
918 void mg_log_set_fn(mg_pfn_t fn, void *param);
921 #define MG_LOG(level, args) \
923 if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \
926 #define MG_LOG(level, args) \
928 if (0) mg_log args; \
932 #define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args)
933 #define MG_INFO(args) MG_LOG(MG_LL_INFO, args)
934 #define MG_DEBUG(args) MG_LOG(MG_LL_DEBUG, args)
935 #define MG_VERBOSE(args) MG_LOG(MG_LL_VERBOSE, args)
941 unsigned long id; // Timer ID
942 uint64_t period_ms; // Timer period in milliseconds
943 uint64_t expire; // Expiration timestamp in milliseconds
944 unsigned flags; // Possible flags values below
945 #define MG_TIMER_ONCE 0 // Call function once
946 #define MG_TIMER_REPEAT 1 // Call function periodically
947 #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
948 void (*fn)(void *); // Function to call
949 void *arg; // Function argument
950 struct mg_timer *next; // Linkage
953 void mg_timer_init(struct mg_timer **head, struct mg_timer *timer,
954 uint64_t milliseconds, unsigned flags, void (*fn)(void *),
956 void mg_timer_free(struct mg_timer **head, struct mg_timer *);
957 void mg_timer_poll(struct mg_timer **head, uint64_t new_ms);
958 bool mg_timer_expired(uint64_t *expiration, uint64_t period, uint64_t now);
964 enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
966 // Filesystem API functions
967 // st() returns MG_FS_* flags and populates file size and modification time
968 // ls() calls fn() for every directory entry, allowing to list a directory
970 // NOTE: UNIX-style shorthand names for the API functions are deliberately
971 // chosen to avoid conflicts with some libraries that make macros for e.g.
972 // stat(), write(), read() calls.
974 int (*st)(const char *path, size_t *size, time_t *mtime); // stat file
975 void (*ls)(const char *path, void (*fn)(const char *, void *), void *);
976 void *(*op)(const char *path, int flags); // Open file
977 void (*cl)(void *fd); // Close file
978 size_t (*rd)(void *fd, void *buf, size_t len); // Read file
979 size_t (*wr)(void *fd, const void *buf, size_t len); // Write file
980 size_t (*sk)(void *fd, size_t offset); // Set file position
981 bool (*mv)(const char *from, const char *to); // Rename file
982 bool (*rm)(const char *path); // Delete file
983 bool (*mkd)(const char *path); // Create directory
986 extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
987 extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard
988 extern struct mg_fs mg_fs_fat; // FAT FS
996 struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags);
997 void mg_fs_close(struct mg_fd *fd);
998 char *mg_file_read(struct mg_fs *fs, const char *path, size_t *size);
999 bool mg_file_write(struct mg_fs *fs, const char *path, const void *, size_t);
1000 bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...);
1008 #if MG_ENABLE_ASSERT
1010 #elif !defined(assert)
1014 void mg_random(void *buf, size_t len);
1015 char *mg_random_str(char *buf, size_t len);
1016 uint16_t mg_ntohs(uint16_t net);
1017 uint32_t mg_ntohl(uint32_t net);
1018 uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
1019 uint64_t mg_millis(void);
1021 #define mg_htons(x) mg_ntohs(x)
1022 #define mg_htonl(x) mg_ntohl(x)
1024 #define MG_U32(a, b, c, d) \
1025 (((uint32_t) ((a) &255) << 24) | ((uint32_t) ((b) &255) << 16) | \
1026 ((uint32_t) ((c) &255) << 8) | (uint32_t) ((d) &255))
1028 // For printing IPv4 addresses: printf("%d.%d.%d.%d\n", MG_IPADDR_PARTS(&ip))
1029 #define MG_U8P(ADDR) ((uint8_t *) (ADDR))
1030 #define MG_IPADDR_PARTS(ADDR) \
1031 MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3]
1034 int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip);
1036 // Linked list management macros
1037 #define LIST_ADD_HEAD(type_, head_, elem_) \
1039 (elem_)->next = (*head_); \
1040 *(head_) = (elem_); \
1043 #define LIST_ADD_TAIL(type_, head_, elem_) \
1045 type_ **h = head_; \
1046 while (*h != NULL) h = &(*h)->next; \
1050 #define LIST_DELETE(type_, head_, elem_) \
1052 type_ **h = head_; \
1053 while (*h != (elem_)) h = &(*h)->next; \
1054 *h = (elem_)->next; \
1059 unsigned short mg_url_port(const char *url);
1060 int mg_url_is_ssl(const char *url);
1061 struct mg_str mg_url_host(const char *url);
1062 struct mg_str mg_url_user(const char *url);
1063 struct mg_str mg_url_pass(const char *url);
1064 const char *mg_url_uri(const char *url);
1070 unsigned char *buf; // Pointer to stored data
1071 size_t size; // Total size available
1072 size_t len; // Current number of bytes
1073 size_t align; // Alignment during allocation
1076 int mg_iobuf_init(struct mg_iobuf *, size_t, size_t);
1077 int mg_iobuf_resize(struct mg_iobuf *, size_t);
1078 void mg_iobuf_free(struct mg_iobuf *);
1079 size_t mg_iobuf_add(struct mg_iobuf *, size_t, const void *, size_t);
1080 size_t mg_iobuf_del(struct mg_iobuf *, size_t ofs, size_t len);
1082 int mg_base64_update(unsigned char p, char *to, int len);
1083 int mg_base64_final(char *to, int len);
1084 int mg_base64_encode(const unsigned char *p, int n, char *to);
1085 int mg_base64_decode(const char *src, int n, char *dst);
1093 unsigned char in[64];
1096 void mg_md5_init(mg_md5_ctx *c);
1097 void mg_md5_update(mg_md5_ctx *c, const unsigned char *data, size_t len);
1098 void mg_md5_final(mg_md5_ctx *c, unsigned char[16]);
1106 unsigned char buffer[64];
1109 void mg_sha1_init(mg_sha1_ctx *);
1110 void mg_sha1_update(mg_sha1_ctx *, const unsigned char *data, size_t len);
1111 void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *);
1114 struct mg_connection;
1115 typedef void (*mg_event_handler_t)(struct mg_connection *, int ev,
1116 void *ev_data, void *fn_data);
1117 void mg_call(struct mg_connection *c, int ev, void *ev_data);
1118 void mg_error(struct mg_connection *c, const char *fmt, ...);
1121 MG_EV_ERROR, // Error char *error_message
1122 MG_EV_OPEN, // Connection created NULL
1123 MG_EV_POLL, // mg_mgr_poll iteration uint64_t *uptime_millis
1124 MG_EV_RESOLVE, // Host name is resolved NULL
1125 MG_EV_CONNECT, // Connection established NULL
1126 MG_EV_ACCEPT, // Connection accepted NULL
1127 MG_EV_TLS_HS, // TLS handshake succeeded NULL
1128 MG_EV_READ, // Data received from socket long *bytes_read
1129 MG_EV_WRITE, // Data written to socket long *bytes_written
1130 MG_EV_CLOSE, // Connection closed NULL
1131 MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
1132 MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
1133 MG_EV_WS_OPEN, // Websocket handshake done struct mg_http_message *
1134 MG_EV_WS_MSG, // Websocket msg, text or bin struct mg_ws_message *
1135 MG_EV_WS_CTL, // Websocket control msg struct mg_ws_message *
1136 MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
1137 MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
1138 MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
1139 MG_EV_SNTP_TIME, // SNTP time received uint64_t *epoch_millis
1140 MG_EV_USER // Starting ID for user events
1152 const char *url; // DNS server URL
1153 struct mg_connection *c; // DNS server connection
1157 uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
1158 uint16_t port; // TCP or UDP port in network byte order
1159 bool is_ip6; // True when address is IPv6 address
1163 struct mg_connection *conns; // List of active connections
1164 struct mg_dns dns4; // DNS for IPv4
1165 struct mg_dns dns6; // DNS for IPv6
1166 int dnstimeout; // DNS resolve timeout in milliseconds
1167 bool use_dns6; // Use DNS6 server by default, see #1532
1168 unsigned long nextid; // Next connection ID
1169 unsigned long timerid; // Next timer ID
1170 void *userdata; // Arbitrary user data pointer
1171 void *tls_ctx; // TLS context shared by all TLS sessions
1172 uint16_t mqtt_id; // MQTT IDs for pub/sub
1173 void *active_dns_requests; // DNS requests in progress
1174 struct mg_timer *timers; // Active timers
1175 int epoll_fd; // Used when MG_EPOLL_ENABLE=1
1176 void *priv; // Used by the MIP stack
1177 size_t extraconnsize; // Used by the MIP stack
1178 #if MG_ENABLE_FREERTOS_TCP
1179 SocketSet_t ss; // NOTE(lsm): referenced from socket struct
1183 struct mg_connection {
1184 struct mg_connection *next; // Linkage in struct mg_mgr :: connections
1185 struct mg_mgr *mgr; // Our container
1186 struct mg_addr loc; // Local address
1187 struct mg_addr rem; // Remote address
1188 void *fd; // Connected socket, or LWIP data
1189 unsigned long id; // Auto-incrementing unique connection ID
1190 struct mg_iobuf recv; // Incoming data
1191 struct mg_iobuf send; // Outgoing data
1192 mg_event_handler_t fn; // User-specified event handler function
1193 void *fn_data; // User-specified function parameter
1194 mg_event_handler_t pfn; // Protocol-specific handler function
1195 void *pfn_data; // Protocol-specific function parameter
1196 char data[MG_DATA_SIZE]; // Arbitrary connection data
1197 void *tls; // TLS specific data
1198 unsigned is_listening : 1; // Listening connection
1199 unsigned is_client : 1; // Outbound (client) connection
1200 unsigned is_accepted : 1; // Accepted (server) connection
1201 unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
1202 unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress
1203 unsigned is_connecting : 1; // Non-blocking connect is in progress
1204 unsigned is_tls : 1; // TLS-enabled connection
1205 unsigned is_tls_hs : 1; // TLS handshake is in progress
1206 unsigned is_udp : 1; // UDP connection
1207 unsigned is_websocket : 1; // WebSocket connection
1208 unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator
1209 unsigned is_hexdumping : 1; // Hexdump in/out traffic
1210 unsigned is_draining : 1; // Send remaining data, then close and free
1211 unsigned is_closing : 1; // Close and free the connection immediately
1212 unsigned is_full : 1; // Stop reads, until cleared
1213 unsigned is_resp : 1; // Response is still being generated
1214 unsigned is_readable : 1; // Connection is ready to read
1215 unsigned is_writable : 1; // Connection is ready to write
1218 void mg_mgr_poll(struct mg_mgr *, int ms);
1219 void mg_mgr_init(struct mg_mgr *);
1220 void mg_mgr_free(struct mg_mgr *);
1222 struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
1223 mg_event_handler_t fn, void *fn_data);
1224 struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
1225 mg_event_handler_t fn, void *fn_data);
1226 struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
1227 mg_event_handler_t fn, void *fn_data);
1228 void mg_connect_resolved(struct mg_connection *);
1229 bool mg_send(struct mg_connection *, const void *, size_t);
1230 size_t mg_printf(struct mg_connection *, const char *fmt, ...);
1231 size_t mg_vprintf(struct mg_connection *, const char *fmt, va_list *ap);
1232 bool mg_aton(struct mg_str str, struct mg_addr *addr);
1233 int mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *, bool udp);
1235 // These functions are used to integrate with custom network stacks
1236 struct mg_connection *mg_alloc_conn(struct mg_mgr *);
1237 void mg_close_conn(struct mg_connection *c);
1238 bool mg_open_listener(struct mg_connection *c, const char *url);
1240 // Utility functions
1241 struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
1242 unsigned flags, void (*fn)(void *), void *arg);
1244 // Low-level IO primives used by TLS layer
1245 enum { MG_IO_ERR = -1, MG_IO_WAIT = -2, MG_IO_RESET = -3 };
1246 long mg_io_send(struct mg_connection *c, const void *buf, size_t len);
1247 long mg_io_recv(struct mg_connection *c, void *buf, size_t len);
1256 struct mg_http_header {
1257 struct mg_str name; // Header name
1258 struct mg_str value; // Header value
1261 struct mg_http_message {
1262 struct mg_str method, uri, query, proto; // Request/response line
1263 struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
1264 struct mg_str body; // Body
1265 struct mg_str head; // Request + headers
1266 struct mg_str chunk; // Chunk for chunked encoding, or partial body
1267 struct mg_str message; // Request + headers + body
1270 // Parameter for mg_http_serve_dir()
1271 struct mg_http_serve_opts {
1272 const char *root_dir; // Web root directory, must be non-NULL
1273 const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
1274 const char *extra_headers; // Extra HTTP headers to add in responses
1275 const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
1276 const char *page404; // Path to the 404 page, or NULL by default
1277 struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
1280 // Parameter for mg_http_next_multipart
1281 struct mg_http_part {
1282 struct mg_str name; // Form field name
1283 struct mg_str filename; // Filename for file uploads
1284 struct mg_str body; // Part contents
1287 int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
1288 int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
1289 void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...);
1290 void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
1291 void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
1292 struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url,
1293 mg_event_handler_t fn, void *fn_data);
1294 struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
1295 mg_event_handler_t fn, void *fn_data);
1296 void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
1297 const struct mg_http_serve_opts *);
1298 void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
1299 const char *path, const struct mg_http_serve_opts *);
1300 void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
1301 const char *body_fmt, ...);
1302 struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
1303 struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
1304 int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
1305 int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
1306 size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
1307 void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
1308 bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
1309 long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
1310 struct mg_fs *fs, const char *path, size_t max_size);
1311 void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
1312 struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
1313 size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
1314 int mg_http_status(const struct mg_http_message *hm);
1315 void mg_hello(const char *url);
1318 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
1319 const char *fullpath);
1322 #define MG_TLS_NONE 0 // No TLS support
1323 #define MG_TLS_MBED 1 // mbedTLS
1324 #define MG_TLS_OPENSSL 2 // OpenSSL
1325 #define MG_TLS_BUILTIN 3 // Built-in
1326 #define MG_TLS_CUSTOM 4 // Custom implementation
1329 #define MG_TLS MG_TLS_NONE
1336 struct mg_tls_opts {
1337 struct mg_str client_ca;
1338 struct mg_str server_ca;
1339 struct mg_str server_cert;
1340 struct mg_str server_key;
1341 struct mg_str client_cert;
1342 struct mg_str client_key;
1345 void mg_tls_ctx_init(struct mg_mgr *, const struct mg_tls_opts *);
1346 void mg_tls_ctx_free(struct mg_mgr *);
1347 void mg_tls_init(struct mg_connection *, struct mg_str hostname);
1348 void mg_tls_free(struct mg_connection *);
1349 long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
1350 long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
1351 size_t mg_tls_pending(struct mg_connection *);
1352 void mg_tls_handshake(struct mg_connection *);
1360 #if MG_TLS == MG_TLS_MBED
1361 #include <mbedtls/debug.h>
1362 #include <mbedtls/net_sockets.h>
1363 #include <mbedtls/ssl.h>
1364 #include <mbedtls/ssl_ticket.h>
1367 mbedtls_x509_crt server_ca; // Parsed CA certificate
1368 mbedtls_x509_crt client_ca; // Parsed CA certificate
1369 mbedtls_x509_crt server_cert; // Parsed server certificate
1370 mbedtls_pk_context server_key; // Parsed server private key context
1371 mbedtls_x509_crt client_cert; // Parsed client certificate
1372 mbedtls_pk_context client_key; // Parsed client private key context
1373 #ifdef MBEDTLS_SSL_SESSION_TICKETS
1374 mbedtls_ssl_ticket_context ticket_ctx; // Session tickets context
1379 mbedtls_ssl_context ssl; // SSL/TLS context
1380 mbedtls_ssl_config conf; // SSL-TLS config
1385 #if MG_TLS == MG_TLS_OPENSSL
1387 #include <openssl/err.h>
1388 #include <openssl/ssl.h>
1392 EVP_PKEY *server_key;
1393 STACK_OF(X509_INFO) *server_ca;
1395 EVP_PKEY *client_key;
1396 STACK_OF(X509_INFO) *client_ca;
1406 #define WEBSOCKET_OP_CONTINUE 0
1407 #define WEBSOCKET_OP_TEXT 1
1408 #define WEBSOCKET_OP_BINARY 2
1409 #define WEBSOCKET_OP_CLOSE 8
1410 #define WEBSOCKET_OP_PING 9
1411 #define WEBSOCKET_OP_PONG 10
1415 struct mg_ws_message {
1416 struct mg_str data; // Websocket message data
1417 uint8_t flags; // Websocket message flags
1420 struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url,
1421 mg_event_handler_t fn, void *fn_data,
1422 const char *fmt, ...);
1423 void mg_ws_upgrade(struct mg_connection *, struct mg_http_message *,
1424 const char *fmt, ...);
1425 size_t mg_ws_send(struct mg_connection *, const void *buf, size_t len, int op);
1426 size_t mg_ws_wrap(struct mg_connection *, size_t len, int op);
1427 size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...);
1428 size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt,
1434 struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
1435 mg_event_handler_t fn, void *fn_data);
1436 void mg_sntp_request(struct mg_connection *c);
1437 int64_t mg_sntp_parse(const unsigned char *buf, size_t len);
1443 #define MQTT_CMD_CONNECT 1
1444 #define MQTT_CMD_CONNACK 2
1445 #define MQTT_CMD_PUBLISH 3
1446 #define MQTT_CMD_PUBACK 4
1447 #define MQTT_CMD_PUBREC 5
1448 #define MQTT_CMD_PUBREL 6
1449 #define MQTT_CMD_PUBCOMP 7
1450 #define MQTT_CMD_SUBSCRIBE 8
1451 #define MQTT_CMD_SUBACK 9
1452 #define MQTT_CMD_UNSUBSCRIBE 10
1453 #define MQTT_CMD_UNSUBACK 11
1454 #define MQTT_CMD_PINGREQ 12
1455 #define MQTT_CMD_PINGRESP 13
1456 #define MQTT_CMD_DISCONNECT 14
1457 #define MQTT_CMD_AUTH 15
1459 #define MQTT_PROP_PAYLOAD_FORMAT_INDICATOR 0x01
1460 #define MQTT_PROP_MESSAGE_EXPIRY_INTERVAL 0x02
1461 #define MQTT_PROP_CONTENT_TYPE 0x03
1462 #define MQTT_PROP_RESPONSE_TOPIC 0x08
1463 #define MQTT_PROP_CORRELATION_DATA 0x09
1464 #define MQTT_PROP_SUBSCRIPTION_IDENTIFIER 0x0B
1465 #define MQTT_PROP_SESSION_EXPIRY_INTERVAL 0x11
1466 #define MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER 0x12
1467 #define MQTT_PROP_SERVER_KEEP_ALIVE 0x13
1468 #define MQTT_PROP_AUTHENTICATION_METHOD 0x15
1469 #define MQTT_PROP_AUTHENTICATION_DATA 0x16
1470 #define MQTT_PROP_REQUEST_PROBLEM_INFORMATION 0x17
1471 #define MQTT_PROP_WILL_DELAY_INTERVAL 0x18
1472 #define MQTT_PROP_REQUEST_RESPONSE_INFORMATION 0x19
1473 #define MQTT_PROP_RESPONSE_INFORMATION 0x1A
1474 #define MQTT_PROP_SERVER_REFERENCE 0x1C
1475 #define MQTT_PROP_REASON_STRING 0x1F
1476 #define MQTT_PROP_RECEIVE_MAXIMUM 0x21
1477 #define MQTT_PROP_TOPIC_ALIAS_MAXIMUM 0x22
1478 #define MQTT_PROP_TOPIC_ALIAS 0x23
1479 #define MQTT_PROP_MAXIMUM_QOS 0x24
1480 #define MQTT_PROP_RETAIN_AVAILABLE 0x25
1481 #define MQTT_PROP_USER_PROPERTY 0x26
1482 #define MQTT_PROP_MAXIMUM_PACKET_SIZE 0x27
1483 #define MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE 0x28
1484 #define MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE 0x29
1485 #define MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE 0x2A
1488 MQTT_PROP_TYPE_BYTE,
1489 MQTT_PROP_TYPE_STRING,
1490 MQTT_PROP_TYPE_STRING_PAIR,
1491 MQTT_PROP_TYPE_BINARY_DATA,
1492 MQTT_PROP_TYPE_VARIABLE_INT,
1494 MQTT_PROP_TYPE_SHORT
1497 enum { MQTT_OK, MQTT_INCOMPLETE, MQTT_MALFORMED };
1499 struct mg_mqtt_prop {
1500 uint8_t id; // Enumerated at MQTT5 Reference
1501 uint32_t iv; // Integer value for 8-, 16-, 32-bit integers types
1502 struct mg_str key; // Non-NULL only for user property type
1503 struct mg_str val; // Non-NULL only for UTF-8 types and user properties
1506 struct mg_mqtt_opts {
1507 struct mg_str user; // Username, can be empty
1508 struct mg_str pass; // Password, can be empty
1509 struct mg_str client_id; // Client ID
1510 struct mg_str topic; // message/subscription topic
1511 struct mg_str message; // message content
1512 uint8_t qos; // message quality of service
1513 uint8_t version; // Can be 4 (3.1.1), or 5. If 0, assume 4
1514 uint16_t keepalive; // Keep-alive timer in seconds
1515 bool retain; // Retain flag
1516 bool clean; // Clean session flag
1517 struct mg_mqtt_prop *props; // MQTT5 props array
1518 size_t num_props; // number of props
1519 struct mg_mqtt_prop *will_props; // Valid only for CONNECT packet (MQTT5)
1520 size_t num_will_props; // Number of will props
1523 struct mg_mqtt_message {
1524 struct mg_str topic; // Parsed topic for PUBLISH
1525 struct mg_str data; // Parsed message for PUBLISH
1526 struct mg_str dgram; // Whole MQTT packet, including headers
1527 uint16_t id; // For PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
1528 uint8_t cmd; // MQTT command, one of MQTT_CMD_*
1529 uint8_t qos; // Quality of service
1530 uint8_t ack; // CONNACK return code, 0 = success
1531 size_t props_start; // Offset to the start of the properties (MQTT5)
1532 size_t props_size; // Length of the properties
1535 struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url,
1536 const struct mg_mqtt_opts *opts,
1537 mg_event_handler_t fn, void *fn_data);
1538 struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
1539 mg_event_handler_t fn, void *fn_data);
1540 void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts);
1541 void mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts);
1542 void mg_mqtt_sub(struct mg_connection *, const struct mg_mqtt_opts *opts);
1543 int mg_mqtt_parse(const uint8_t *, size_t, uint8_t, struct mg_mqtt_message *);
1544 void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
1546 void mg_mqtt_ping(struct mg_connection *);
1547 void mg_mqtt_pong(struct mg_connection *);
1548 void mg_mqtt_disconnect(struct mg_connection *, const struct mg_mqtt_opts *);
1549 size_t mg_mqtt_next_prop(struct mg_mqtt_message *, struct mg_mqtt_prop *,
1556 // Mongoose sends DNS queries that contain only one question:
1557 // either A (IPv4) or AAAA (IPv6) address lookup.
1558 // Therefore, we expect zero or one answer.
1559 // If `resolved` is true, then `addr` contains resolved IPv4 or IPV6 address.
1560 struct mg_dns_message {
1561 uint16_t txnid; // Transaction ID
1562 bool resolved; // Resolve successful, addr is set
1563 struct mg_addr addr; // Resolved address
1564 char name[256]; // Host name
1567 struct mg_dns_header {
1568 uint16_t txnid; // Transaction ID
1570 uint16_t num_questions;
1571 uint16_t num_answers;
1572 uint16_t num_authority_prs;
1573 uint16_t num_other_prs;
1576 // DNS resource record
1578 uint16_t nlen; // Name or pointer length
1579 uint16_t atype; // Address type
1580 uint16_t aclass; // Address class
1581 uint16_t alen; // Address length
1584 void mg_resolve(struct mg_connection *, const char *url);
1585 void mg_resolve_cancel(struct mg_connection *);
1586 bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
1587 size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
1588 bool is_question, struct mg_dns_rr *);
1594 #ifndef MG_JSON_MAX_DEPTH
1595 #define MG_JSON_MAX_DEPTH 30
1598 // Error return values - negative. Successful returns are >= 0
1599 enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
1600 int mg_json_get(struct mg_str json, const char *path, int *toklen);
1602 bool mg_json_get_num(struct mg_str json, const char *path, double *v);
1603 bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
1604 long mg_json_get_long(struct mg_str json, const char *path, long dflt);
1605 char *mg_json_get_str(struct mg_str json, const char *path);
1606 char *mg_json_get_hex(struct mg_str json, const char *path, int *len);
1607 char *mg_json_get_b64(struct mg_str json, const char *path, int *len);
1609 bool mg_json_unescape(struct mg_str str, char *buf, size_t len);
1614 // JSON-RPC request descriptor
1616 struct mg_rpc **head; // RPC handlers list head
1617 struct mg_rpc *rpc; // RPC handler being called
1618 mg_pfn_t pfn; // Response printing function
1619 void *pfn_data; // Response printing function data
1620 void *req_data; // Arbitrary request data
1621 struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
1624 // JSON-RPC method handler
1626 struct mg_rpc *next; // Next in list
1627 struct mg_str method; // Method pattern
1628 void (*fn)(struct mg_rpc_req *); // Handler function
1629 void *fn_data; // Handler function argument
1632 void mg_rpc_add(struct mg_rpc **head, struct mg_str method_pattern,
1633 void (*handler)(struct mg_rpc_req *), void *handler_data);
1634 void mg_rpc_del(struct mg_rpc **head, void (*handler)(struct mg_rpc_req *));
1635 void mg_rpc_process(struct mg_rpc_req *);
1637 // Helper functions to print result or error frame
1638 void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
1639 void mg_rpc_vok(struct mg_rpc_req *, const char *fmt, va_list *ap);
1640 void mg_rpc_err(struct mg_rpc_req *, int code, const char *fmt, ...);
1641 void mg_rpc_verr(struct mg_rpc_req *, int code, const char *fmt, va_list *);
1642 void mg_rpc_list(struct mg_rpc_req *r);
1649 #if defined(MG_ENABLE_TCPIP) && MG_ENABLE_TCPIP
1650 struct mg_tcpip_if; // Mongoose TCP/IP network interface
1652 struct mg_tcpip_driver {
1653 bool (*init)(struct mg_tcpip_if *); // Init driver
1654 size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame
1655 size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame
1656 bool (*up)(struct mg_tcpip_if *); // Up/down status
1659 // Network interface
1660 struct mg_tcpip_if {
1661 uint8_t mac[6]; // MAC address. Must be set to a valid MAC
1662 uint32_t ip, mask, gw; // IP address, mask, default gateway
1663 struct mg_str tx; // Output (TX) buffer
1664 bool enable_dhcp_client; // Enable DCHP client
1665 bool enable_dhcp_server; // Enable DCHP server
1666 bool enable_crc32_check; // Do a CRC check on RX frames and strip it
1667 bool enable_mac_check; // Do a MAC check on RX frames
1668 struct mg_tcpip_driver *driver; // Low level driver
1669 void *driver_data; // Driver-specific data
1670 struct mg_mgr *mgr; // Mongoose event manager
1671 struct mg_queue recv_queue; // Receive queue
1673 // Internal state, user can use it but should not change it
1674 uint8_t gwmac[6]; // Router's MAC
1675 uint64_t now; // Current time
1676 uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
1677 uint64_t lease_expire; // Lease expiration time, in ms
1678 uint16_t eport; // Next ephemeral port
1679 volatile uint32_t ndrop; // Number of received, but dropped frames
1680 volatile uint32_t nrecv; // Number of received frames
1681 volatile uint32_t nsent; // Number of transmitted frames
1682 volatile uint32_t nerr; // Number of driver errors
1683 uint8_t state; // Current state
1684 #define MG_TCPIP_STATE_DOWN 0 // Interface is down
1685 #define MG_TCPIP_STATE_UP 1 // Interface is up
1686 #define MG_TCPIP_STATE_REQ 2 // Interface is up and has requested an IP
1687 #define MG_TCPIP_STATE_READY 3 // Interface is up and has an IP assigned
1690 void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
1691 void mg_tcpip_free(struct mg_tcpip_if *);
1692 void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
1694 extern struct mg_tcpip_driver mg_tcpip_driver_stm32;
1695 extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
1696 extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
1697 extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
1698 extern struct mg_tcpip_driver mg_tcpip_driver_imxrt;
1699 extern struct mg_tcpip_driver mg_tcpip_driver_same54;
1701 // Drivers that require SPI, can use this SPI abstraction
1702 struct mg_tcpip_spi {
1703 void *spi; // Opaque SPI bus descriptor
1704 void (*begin)(void *); // SPI begin: slave select low
1705 void (*end)(void *); // SPI end: slave select high
1706 uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
1711 struct mg_tcpip_driver_imxrt1020_data {
1712 // MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
1713 // must not exceed 2.5MHz. Configuration for clock range 2.36~2.50 MHz
1714 // ipg_clk MSCR mdc_cr VALUE
1715 // -------------------------------------
1716 // -1 <-- tell driver to guess the value
1721 // 66 MHz 0x0D 4 <-- value for iMXRT1020-EVK at max freq.
1722 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4
1726 #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
1728 struct mg_tcpip_driver_same54_data {
1735 struct mg_tcpip_driver_stm32_data {
1736 // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
1737 // HCLK range DIVIDER mdc_cr VALUE
1738 // -------------------------------------
1739 // -1 <-- tell driver to guess the value
1740 // 60-100 MHz HCLK/42 0
1741 // 100-150 MHz HCLK/62 1
1742 // 20-35 MHz HCLK/16 2
1743 // 35-60 MHz HCLK/26 3
1744 // 150-216 MHz HCLK/102 4 <-- value for Nucleo-F* on max speed
1745 // 216-310 MHz HCLK/124 5
1746 // 110, 111 Reserved
1747 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
1751 struct mg_tcpip_driver_stm32h_data {
1752 // MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
1753 // HCLK range DIVIDER mdc_cr VALUE
1754 // -------------------------------------
1755 // -1 <-- tell driver to guess the value
1756 // 60-100 MHz HCLK/42 0
1757 // 100-150 MHz HCLK/62 1
1758 // 20-35 MHz HCLK/16 2
1759 // 35-60 MHz HCLK/26 3
1760 // 150-250 MHz HCLK/102 4 <-- value for Nucleo-H* on max speed driven by HSI
1761 // 250-300 MHz HCLK/124 5 <-- value for Nucleo-H* on max speed driven by CSI
1762 // 110, 111 Reserved
1763 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
1767 struct mg_tcpip_driver_tm4c_data {
1768 // MDC clock divider. MDC clock is derived from SYSCLK, must not exceed 2.5MHz
1769 // SYSCLK range DIVIDER mdc_cr VALUE
1770 // -------------------------------------
1771 // -1 <-- tell driver to guess the value
1772 // 60-100 MHz SYSCLK/42 0
1773 // 100-150 MHz SYSCLK/62 1 <-- value for EK-TM4C129* on max speed
1774 // 20-35 MHz SYSCLK/16 2
1775 // 35-60 MHz SYSCLK/26 3
1777 int mdc_cr; // Valid values: -1, 0, 1, 2, 3
1781 #define CA_ISRG_ROOT_X2 \
1782 "-----BEGIN CERTIFICATE-----\n" \
1783 "MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw\n" \
1784 "CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg\n" \
1785 "R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00\n" \
1786 "MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT\n" \
1787 "ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw\n" \
1788 "EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW\n" \
1789 "+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9\n" \
1790 "ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T\n" \
1791 "AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI\n" \
1792 "zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW\n" \
1793 "tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1\n" \
1794 "/q4AaOeMSQ+2b1tbFfLn\n" \
1795 "-----END CERTIFICATE-----\n"
1797 #define CA_ISRG_ROOT_X1 \
1798 "-----BEGIN CERTIFICATE-----\n" \
1799 "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \
1800 "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \
1801 "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" \
1802 "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" \
1803 "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" \
1804 "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" \
1805 "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" \
1806 "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n" \
1807 "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n" \
1808 "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n" \
1809 "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n" \
1810 "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n" \
1811 "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n" \
1812 "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n" \
1813 "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n" \
1814 "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n" \
1815 "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" \
1816 "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n" \
1817 "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n" \
1818 "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n" \
1819 "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n" \
1820 "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n" \
1821 "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n" \
1822 "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n" \
1823 "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n" \
1824 "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n" \
1825 "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n" \
1826 "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" \
1827 "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \
1828 "-----END CERTIFICATE-----\n"
1830 #define CA_GOOGLE_TRUST \
1831 "-----BEGIN CERTIFICATE-----\n" \
1832 "MIIBxTCCAWugAwIBAgINAfD3nVndblD3QnNxUDAKBggqhkjOPQQDAjBEMQswCQYD\n" \
1833 "VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzERMA8G\n" \
1834 "A1UEAxMIR1RTIExUU1IwHhcNMTgxMTAxMDAwMDQyWhcNNDIxMTAxMDAwMDQyWjBE\n" \
1835 "MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM\n" \
1836 "QzERMA8GA1UEAxMIR1RTIExUU1IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATN\n" \
1837 "8YyO2u+yCQoZdwAkUNv5c3dokfULfrA6QJgFV2XMuENtQZIG5HUOS6jFn8f0ySlV\n" \
1838 "eORCxqFyjDJyRn86d+Iko0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\n" \
1839 "AwEB/zAdBgNVHQ4EFgQUPv7/zFLrvzQ+PfNA0OQlsV+4u1IwCgYIKoZIzj0EAwID\n" \
1840 "SAAwRQIhAPKuf/VtBHqGw3TUwUIq7TfaExp3bH7bjCBmVXJupT9FAiBr0SmCtsuk\n" \
1841 "miGgpajjf/gFigGM34F9021bCWs1MbL0SA==\n" \
1842 "-----END CERTIFICATE-----\n"
1844 #define CA_GLOBALSIGN_EC \
1845 "-----BEGIN CERTIFICATE-----\n" \
1846 "MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk\n" \
1847 "MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH\n" \
1848 "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX\n" \
1849 "DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD\n" \
1850 "QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu\n" \
1851 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ\n" \
1852 "FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw\n" \
1853 "DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F\n" \
1854 "uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX\n" \
1855 "kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs\n" \
1857 "-----END CERTIFICATE-----\n"
1859 #define CA_GLOBALSIGN_RSA \
1860 "-----BEGIN CERTIFICATE-----\n" \
1861 "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n" \
1862 "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n" \
1863 "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n" \
1864 "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n" \
1865 "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n" \
1866 "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n" \
1867 "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n" \
1868 "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n" \
1869 "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n" \
1870 "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n" \
1871 "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n" \
1872 "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n" \
1873 "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n" \
1874 "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n" \
1875 "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n" \
1876 "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n" \
1877 "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n" \
1878 "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n" \
1879 "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n" \
1880 "-----END CERTIFICATE-----\n"
1882 #define CA_DIGICERT \
1883 "-----BEGIN CERTIFICATE-----\n" \
1884 "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \
1885 "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
1886 "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \
1887 "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \
1888 "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \
1889 "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \
1890 "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \
1891 "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \
1892 "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \
1893 "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \
1894 "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \
1895 "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \
1896 "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \
1897 "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \
1898 "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \
1899 "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \
1900 "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \
1901 "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \
1902 "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \
1903 "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \
1904 "-----END CERTIFICATE-----\n"
1906 #define CA_AMAZON_4 \
1907 "-----BEGIN CERTIFICATE-----\n" \
1908 "MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5\n" \
1909 "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" \
1910 "Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" \
1911 "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" \
1912 "Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi\n" \
1913 "9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk\n" \
1914 "M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB\n" \
1915 "/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB\n" \
1916 "MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw\n" \
1917 "CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW\n" \
1918 "1KyLa2tJElMzrdfkviT8tQp21KW8EA==\n" \
1919 "-----END CERTIFICATE-----\n"
1921 #define CA_AMAZON_3 \
1922 "-----BEGIN CERTIFICATE-----\n" \
1923 "MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5\n" \
1924 "MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g\n" \
1925 "Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG\n" \
1926 "A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg\n" \
1927 "Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl\n" \
1928 "ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j\n" \
1929 "QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr\n" \
1930 "ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr\n" \
1931 "BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM\n" \
1932 "YyRIHN8wfdVoOw==\n" \
1933 "-----END CERTIFICATE-----\n"
1936 CA_ISRG_ROOT_X1 CA_ISRG_ROOT_X2 CA_GOOGLE_TRUST CA_GLOBALSIGN_EC \
1937 CA_GLOBALSIGN_RSA CA_DIGICERT CA_AMAZON_4 CA_AMAZON_3
1942 #endif // MONGOOSE_H