1 // Copyright (c) 2004-2013 Sergey Lyubka
2 // Copyright (c) 2013-2021 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/
21 #define MG_VERSION "7.5"
28 #ifndef MG_ENABLE_SOCKET
29 #define MG_ENABLE_SOCKET 1
32 #ifndef MG_ENABLE_MBEDTLS
33 #define MG_ENABLE_MBEDTLS 0
36 #ifndef MG_ENABLE_OPENSSL
37 #define MG_ENABLE_OPENSSL 0
40 #ifndef MG_ENABLE_CUSTOM_TLS
41 #define MG_ENABLE_CUSTOM_TLS 0
45 #define MG_ENABLE_SSI 1
48 #ifndef MG_ENABLE_IPV6
49 #define MG_ENABLE_IPV6 0
53 #define MG_ENABLE_LOG 1
57 #define MG_ENABLE_MD5 0
60 // Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
61 #ifndef MG_ENABLE_WINSOCK
62 #define MG_ENABLE_WINSOCK 1
65 #ifndef MG_ENABLE_DIRLIST
66 #define MG_ENABLE_DIRLIST 0
69 #ifndef MG_ENABLE_CUSTOM_RANDOM
70 #define MG_ENABLE_CUSTOM_RANDOM 0
73 #ifndef MG_ENABLE_PACKED_FS
74 #define MG_ENABLE_PACKED_FS 0
77 // Granularity of the send/recv IO buffer growth
79 #define MG_IO_SIZE 2048
82 // Maximum size of the recv IO buffer
83 #ifndef MG_MAX_RECV_BUF_SIZE
84 #define MG_MAX_RECV_BUF_SIZE (3 * 1024 * 1024)
87 #ifndef MG_MAX_HTTP_HEADERS
88 #define MG_MAX_HTTP_HEADERS 40
92 #define MG_HTTP_INDEX "index.html"
96 #define MG_PATH_MAX PATH_MAX
99 #ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
100 #define MG_SOCK_LISTEN_BACKLOG_SIZE 128
104 #define MG_ARCH_CUSTOM 0
105 #define MG_ARCH_UNIX 1
106 #define MG_ARCH_WIN32 2
107 #define MG_ARCH_ESP32 3
108 #define MG_ARCH_ESP8266 4
109 #define MG_ARCH_FREERTOS_TCP 5
110 #define MG_ARCH_FREERTOS_LWIP 6
111 #define MG_ARCH_AZURERTOS 7
113 #if !defined(MG_ARCH)
114 #if defined(__unix__) || defined(__APPLE__)
115 #define MG_ARCH MG_ARCH_UNIX
116 #elif defined(_WIN32)
117 #define MG_ARCH MG_ARCH_WIN32
118 #elif defined(ICACHE_FLASH) || defined(ICACHE_RAM_ATTR)
119 #define MG_ARCH MG_ARCH_ESP8266
120 #elif defined(ESP_PLATFORM)
121 #define MG_ARCH MG_ARCH_ESP32
122 #elif defined(FREERTOS_IP_H)
123 #define MG_ARCH MG_ARCH_FREERTOS_TCP
124 #elif defined(AZURE_RTOS_THREADX)
125 #define MG_ARCH MG_ARCH_AZURERTOS
128 #if !defined(MG_ARCH)
129 #error "MG_ARCH is not specified and we couldn't guess it."
131 #endif // !defined(MG_ARCH)
133 #if !defined(PRINTF_LIKE)
134 #if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
135 #define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
137 #define PRINTF_LIKE(f, a)
141 #if MG_ARCH == MG_ARCH_CUSTOM
142 #include <mongoose_custom.h>
153 #if MG_ARCH == MG_ARCH_AZURERTOS
170 #define va_copy(d,s)__builtin_va_copy(d,s)
173 #define PATH_MAX FX_MAXIMUM_PATH
174 #define MG_DIRSEP '\\'
176 #define socklen_t int
177 #define closesocket(x) soc_close(x)
178 #define gmtime_r(a, b) gmtime(a)
179 #define MG_INT64_FMT "%lld"
181 static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
191 #if MG_ARCH == MG_ARCH_ESP32
204 #include <sys/stat.h>
205 #include <sys/types.h>
209 #undef MG_ENABLE_DIRLIST
211 #define MG_DIRSEP '/'
212 #define MG_INT64_FMT "%lld"
213 #define MG_PATH_MAX 128
214 #define MG_ENABLE_DIRLIST 1
219 #if MG_ARCH == MG_ARCH_ESP8266
233 #include <sys/stat.h>
234 #include <sys/time.h>
235 #include <sys/types.h>
238 #include <esp_system.h>
241 #undef MG_ENABLE_DIRLIST
243 #define MG_DIRSEP '/'
244 #define MG_INT64_FMT "%lld"
245 #define MG_PATH_MAX 128
246 #define MG_ENABLE_DIRLIST 1
251 #if MG_ARCH == MG_ARCH_FREERTOS_LWIP
259 #if defined(__GNUC__)
260 #include <sys/stat.h>
261 #include <sys/time.h>
263 typedef long suseconds_t;
270 #include <FreeRTOS.h>
273 #include <lwip/sockets.h>
276 // Sockets support disabled in LWIP by default
277 #error Set LWIP_SOCKET variable to 1 (in lwipopts.h)
280 #if LWIP_POSIX_SOCKETS_IO_NAMES != 0
281 // LWIP_POSIX_SOCKETS_IO_NAMES must be disabled in posix-compatible OS
282 // enviroment (freertos mimics to one) otherwise names like `read` and `write`
284 #error LWIP_POSIX_SOCKETS_IO_NAMES must be set to 0 (in lwipopts.h) for FreeRTOS
287 #define MG_INT64_FMT "%lld"
288 #define MG_DIRSEP '/'
290 // Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
291 static inline void *mg_calloc(int cnt, size_t size) {
292 void *p = pvPortMalloc(cnt * size);
293 if (p != NULL) memset(p, 0, size);
296 #define calloc(a, b) mg_calloc((a), (b))
297 #define free(a) vPortFree(a)
298 #define malloc(a) pvPortMalloc(a)
300 #define gmtime_r(a, b) gmtime(a)
302 #endif // MG_ARCH == MG_ARCH_FREERTOS_LWIP
305 #if MG_ARCH == MG_ARCH_FREERTOS_TCP
316 #include <sys/stat.h>
319 #include <FreeRTOS.h>
320 #include <FreeRTOS_IP.h>
321 #include <FreeRTOS_Sockets.h>
324 #define MG_INT64_FMT "%lld"
325 #define MG_DIRSEP '/'
327 // Why FreeRTOS-TCP did not implement a clean BSD API, but its own thing
328 // with FreeRTOS_ prefix, is beyond me
329 #define IPPROTO_TCP FREERTOS_IPPROTO_TCP
330 #define IPPROTO_UDP FREERTOS_IPPROTO_UDP
331 #define AF_INET FREERTOS_AF_INET
332 #define SOCK_STREAM FREERTOS_SOCK_STREAM
333 #define SOCK_DGRAM FREERTOS_SOCK_DGRAM
334 #define SO_BROADCAST 0
337 #define SO_REUSEADDR 0
338 #define sockaddr_in freertos_sockaddr
339 #define sockaddr freertos_sockaddr
340 #define accept(a, b, c) FreeRTOS_accept((a), (b), (c))
341 #define connect(a, b, c) FreeRTOS_connect((a), (b), (c))
342 #define bind(a, b, c) FreeRTOS_bind((a), (b), (c))
343 #define listen(a, b) FreeRTOS_listen((a), (b))
344 #define socket(a, b, c) FreeRTOS_socket((a), (b), (c))
345 #define send(a, b, c, d) FreeRTOS_send((a), (b), (c), (d))
346 #define recv(a, b, c, d) FreeRTOS_recv((a), (b), (c), (d))
347 #define setsockopt(a, b, c, d, e) FreeRTOS_setsockopt((a), (b), (c), (d), (e))
348 #define sendto(a, b, c, d, e, f) FreeRTOS_sendto((a), (b), (c), (d), (e), (f))
349 #define recvfrom(a, b, c, d, e, f) \
350 FreeRTOS_recvfrom((a), (b), (c), (d), (e), (f))
351 #define closesocket(x) FreeRTOS_closesocket(x)
352 #define gethostbyname(x) FreeRTOS_gethostbyname(x)
353 #define getsockname(a, b, c) (-1)
355 // Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
356 static inline void *mg_calloc(int cnt, size_t size) {
357 void *p = pvPortMalloc(cnt * size);
358 if (p != NULL) memset(p, 0, size);
361 #define calloc(a, b) mg_calloc((a), (b))
362 #define free(a) vPortFree(a)
363 #define malloc(a) pvPortMalloc(a)
365 #define gmtime_r(a, b) gmtime(a)
367 #if !defined(__GNUC__)
368 // copied from GCC on ARM; for some reason useconds are signed
369 typedef long suseconds_t;
377 #define EINPROGRESS pdFREERTOS_ERRNO_EINPROGRESS
380 #define EWOULDBLOCK pdFREERTOS_ERRNO_EWOULDBLOCK
383 #define EAGAIN pdFREERTOS_ERRNO_EAGAIN
386 #define EINTR pdFREERTOS_ERRNO_EINTR
389 #endif // MG_ARCH == MG_ARCH_FREERTOS_TCP
392 #if MG_ARCH == MG_ARCH_UNIX
394 #define _DARWIN_UNLIMITED_SELECT 1 // No limit on file descriptors
396 #include <arpa/inet.h>
401 #include <inttypes.h>
404 #include <netinet/tcp.h>
413 #include <sys/select.h>
414 #include <sys/socket.h>
415 #include <sys/stat.h>
416 #include <sys/time.h>
417 #include <sys/types.h>
421 #define MG_DIRSEP '/'
422 #define MG_INT64_FMT "%" PRId64
423 #undef MG_ENABLE_DIRLIST
424 #define MG_ENABLE_DIRLIST 1
429 #if MG_ARCH == MG_ARCH_WIN32
431 #ifndef WIN32_LEAN_AND_MEAN
432 #define WIN32_LEAN_AND_MEAN
435 #ifndef _CRT_SECURE_NO_WARNINGS
436 #define _CRT_SECURE_NO_WARNINGS
439 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
440 #define _WINSOCK_DEPRECATED_NO_WARNINGS
452 #include <sys/stat.h>
453 #include <sys/types.h>
456 #if defined(_MSC_VER) && _MSC_VER < 1700
458 typedef __int64 int64_t;
459 typedef unsigned __int64 uint64_t;
460 typedef unsigned char uint8_t;
462 typedef unsigned short uint16_t;
463 typedef short int16_t;
464 typedef unsigned int uint32_t;
466 typedef enum { false = 0, true = 1 } bool;
470 #include <ws2tcpip.h>
473 #include <winsock2.h>
475 // Protect from calls like std::snprintf in app code
476 // See https://github.com/cesanta/mongoose/issues/1047
478 #define snprintf _snprintf
479 #define vsnprintf _vsnprintf
480 #ifndef strdup // For MSVC with _DEBUG, see #1359
481 #define strdup(x) _strdup(x)
485 typedef unsigned suseconds_t;
486 typedef int socklen_t;
487 #define MG_DIRSEP '\\'
489 #define PATH_MAX MAX_PATH
492 #define EINPROGRESS WSAEINPROGRESS
495 #define EWOULDBLOCK WSAEWOULDBLOCK
500 #define va_copy __va_copy
502 #define va_copy(x, y) (x) = (y)
506 #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
509 #define MG_INT64_FMT "%I64d"
511 #undef MG_ENABLE_DIRLIST
512 #define MG_ENABLE_DIRLIST 1
514 // https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
515 static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
520 static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
532 const char *ptr; // Pointer to string data
533 size_t len; // String len
536 #define MG_NULL_STR \
539 // Using macro to avoid shadowing C++ struct constructor, see #1298
540 #define mg_str(s) mg_str_s(s)
542 struct mg_str mg_str(const char *s);
543 struct mg_str mg_str_n(const char *s, size_t n);
544 int mg_lower(const char *s);
545 int mg_ncasecmp(const char *s1, const char *s2, size_t len);
546 int mg_casecmp(const char *s1, const char *s2);
547 int mg_vcmp(const struct mg_str *s1, const char *s2);
548 int mg_vcasecmp(const struct mg_str *str1, const char *str2);
549 int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
550 struct mg_str mg_strstrip(struct mg_str s);
551 struct mg_str mg_strdup(const struct mg_str s);
552 const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
559 #define LOG(level, args) \
561 if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \
563 enum { LL_NONE, LL_ERROR, LL_INFO, LL_DEBUG, LL_VERBOSE_DEBUG };
564 bool mg_log_prefix(int ll, const char *file, int line, const char *fname);
565 void mg_log(const char *fmt, ...) PRINTF_LIKE(1, 2);
566 void mg_log_set(const char *spec);
567 void mg_log_set_callback(void (*fn)(const void *, size_t, void *), void *param);
569 #define LOG(level, args) (void) 0
570 #define mg_log_set(x) (void) (x)
575 unsigned long period_ms; // Timer period in milliseconds
576 unsigned long expire; // Expiration timestamp in milliseconds
577 unsigned flags; // Possible flags values below
578 #define MG_TIMER_REPEAT 1 // Call function periodically, otherwise run once
579 #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
580 void (*fn)(void *); // Function to call
581 void *arg; // Function argument
582 struct mg_timer *next; // Linkage in g_timers list
585 extern struct mg_timer *g_timers; // Global list of timers
587 void mg_timer_init(struct mg_timer *, unsigned long ms, unsigned,
588 void (*fn)(void *), void *);
589 void mg_timer_free(struct mg_timer *);
590 void mg_timer_poll(unsigned long current_time_ms);
596 char *mg_file_read(const char *path, size_t *size);
597 bool mg_file_write(const char *path, const void *buf, size_t len);
598 bool mg_file_printf(const char *path, const char *fmt, ...);
599 void mg_random(void *buf, size_t len);
600 bool mg_globmatch(const char *pattern, size_t plen, const char *s, size_t n);
601 bool mg_commalist(struct mg_str *s, struct mg_str *k, struct mg_str *v);
602 uint16_t mg_ntohs(uint16_t net);
603 uint32_t mg_ntohl(uint32_t net);
604 uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
605 char *mg_hexdump(const void *buf, size_t len);
606 char *mg_hex(const void *buf, size_t len, char *dst);
607 void mg_unhex(const char *buf, size_t len, unsigned char *to);
608 unsigned long mg_unhexn(const char *s, size_t len);
609 int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
610 int mg_vasprintf(char **buf, size_t size, const char *fmt, va_list ap);
611 int64_t mg_to64(struct mg_str str);
612 int mg_check_ip_acl(struct mg_str acl, uint32_t remote_ip);
613 double mg_time(void);
614 unsigned long mg_millis(void);
615 void mg_usleep(unsigned long usecs);
617 #define mg_htons(x) mg_ntohs(x)
618 #define mg_htonl(x) mg_ntohl(x)
622 #define EXTERN_C extern "C"
628 // Expands to a string representation of its argument: e.g.
629 // MG_STRINGIFY_LITERAL(5) expands to "5"
630 #if !defined(_MSC_VER) || _MSC_VER >= 1900
631 #define MG_STRINGIFY_LITERAL(...) #__VA_ARGS__
633 #define MG_STRINGIFY_LITERAL(x) #x
635 // Expands to a string representation of its argument, which can be a macro:
637 // MG_STRINGIFY_MACRO(FOO) // Expands to 123
638 #define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
640 // Linked list management macros
641 #define LIST_ADD_HEAD(type_, head_, elem_) \
643 (elem_)->next = (*head_); \
644 *(head_) = (elem_); \
647 #define LIST_ADD_TAIL(type_, head_, elem_) \
650 while (*h != NULL) h = &(*h)->next; \
654 #define LIST_DELETE(type_, head_, elem_) \
657 while (*h != (elem_)) h = &(*h)->next; \
658 *h = (elem_)->next; \
664 enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
666 // Filesystem API functions
667 // stat() returns MG_FS_* flags and populates file size and modification time
668 // list() calls fn() for every directory entry, allowing to list a directory
670 int (*stat)(const char *path, size_t *size, time_t *mtime);
671 void (*list)(const char *path, void (*fn)(const char *, void *), void *);
672 struct mg_fd *(*open)(const char *path, int flags); // Open file
673 void (*close)(struct mg_fd *fd); // Close file
674 size_t (*read)(void *fd, void *buf, size_t len); // Read file
675 size_t (*write)(void *fd, const void *buf, size_t len); // Write file
676 size_t (*seek)(void *fd, size_t offset); // Set file position
685 extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
686 extern struct mg_fs mg_fs_packed; // Packed FS, see examples/complete
690 unsigned short mg_url_port(const char *url);
691 int mg_url_is_ssl(const char *url);
692 struct mg_str mg_url_host(const char *url);
693 struct mg_str mg_url_user(const char *url);
694 struct mg_str mg_url_pass(const char *url);
695 const char *mg_url_uri(const char *url);
701 unsigned char *buf; // Pointer to stored data
702 size_t size; // Total size available
703 size_t len; // Current number of bytes
706 int mg_iobuf_init(struct mg_iobuf *, size_t);
707 int mg_iobuf_resize(struct mg_iobuf *, size_t);
708 void mg_iobuf_free(struct mg_iobuf *);
709 size_t mg_iobuf_add(struct mg_iobuf *, size_t, const void *, size_t, size_t);
710 size_t mg_iobuf_del(struct mg_iobuf *, size_t ofs, size_t len);
712 int mg_base64_update(unsigned char p, char *to, int len);
713 int mg_base64_final(char *to, int len);
714 int mg_base64_encode(const unsigned char *p, int n, char *to);
715 int mg_base64_decode(const char *src, int n, char *dst);
723 unsigned char in[64];
726 void mg_md5_init(mg_md5_ctx *c);
727 void mg_md5_update(mg_md5_ctx *c, const unsigned char *data, size_t len);
728 void mg_md5_final(mg_md5_ctx *c, unsigned char[16]);
736 unsigned char buffer[64];
739 void mg_sha1_init(mg_sha1_ctx *);
740 void mg_sha1_update(mg_sha1_ctx *, const unsigned char *data, size_t len);
741 void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *);
742 void mg_hmac_sha1(const unsigned char *key, size_t key_len,
743 const unsigned char *text, size_t text_len,
744 unsigned char out[20]);
747 struct mg_connection;
748 typedef void (*mg_event_handler_t)(struct mg_connection *, int ev,
749 void *ev_data, void *fn_data);
750 void mg_call(struct mg_connection *c, int ev, void *ev_data);
751 void mg_error(struct mg_connection *c, const char *fmt, ...);
754 MG_EV_ERROR, // Error char *error_message
755 MG_EV_OPEN, // Connection created NULL
756 MG_EV_POLL, // mg_mgr_poll iteration unsigned long *millis
757 MG_EV_RESOLVE, // Host name is resolved NULL
758 MG_EV_CONNECT, // Connection established NULL
759 MG_EV_ACCEPT, // Connection accepted NULL
760 MG_EV_READ, // Data received from socket struct mg_str *
761 MG_EV_WRITE, // Data written to socket long *bytes_written
762 MG_EV_CLOSE, // Connection closed NULL
763 MG_EV_HTTP_MSG, // HTTP request/response struct mg_http_message *
764 MG_EV_HTTP_CHUNK, // HTTP chunk (partial msg) struct mg_http_message *
765 MG_EV_WS_OPEN, // Websocket handshake done struct mg_http_message *
766 MG_EV_WS_MSG, // Websocket msg, text or bin struct mg_ws_message *
767 MG_EV_WS_CTL, // Websocket control msg struct mg_ws_message *
768 MG_EV_MQTT_CMD, // MQTT low-level command struct mg_mqtt_message *
769 MG_EV_MQTT_MSG, // MQTT PUBLISH received struct mg_mqtt_message *
770 MG_EV_MQTT_OPEN, // MQTT CONNACK received int *connack_status_code
771 MG_EV_SNTP_TIME, // SNTP time received struct timeval *
772 MG_EV_USER, // Starting ID for user events
782 const char *url; // DNS server URL
783 struct mg_connection *c; // DNS server connection
787 uint16_t port; // TCP or UDP port in network byte order
788 uint32_t ip; // IP address in network byte order
789 uint8_t ip6[16]; // IPv6 address
790 bool is_ip6; // True when address is IPv6 address
794 struct mg_connection *conns; // List of active connections
795 struct mg_dns dns4; // DNS for IPv4
796 struct mg_dns dns6; // DNS for IPv6
797 int dnstimeout; // DNS resolve timeout in milliseconds
798 unsigned long nextid; // Next connection ID
799 void *userdata; // Arbitrary user data pointer
800 #if MG_ARCH == MG_ARCH_FREERTOS_TCP
801 SocketSet_t ss; // NOTE(lsm): referenced from socket struct
805 struct mg_connection {
806 struct mg_connection *next; // Linkage in struct mg_mgr :: connections
807 struct mg_mgr *mgr; // Our container
808 struct mg_addr peer; // Remote address. For listeners, local address
809 void *fd; // Connected socket, or LWIP data
810 unsigned long id; // Auto-incrementing unique connection ID
811 struct mg_iobuf recv; // Incoming data
812 struct mg_iobuf send; // Outgoing data
813 mg_event_handler_t fn; // User-specified event handler function
814 void *fn_data; // User-specified function parameter
815 mg_event_handler_t pfn; // Protocol-specific handler function
816 void *pfn_data; // Protocol-specific function parameter
817 char label[50]; // Arbitrary label
818 void *tls; // TLS specific data
819 unsigned is_listening : 1; // Listening connection
820 unsigned is_client : 1; // Outbound (client) connection
821 unsigned is_accepted : 1; // Accepted (server) connection
822 unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
823 unsigned is_connecting : 1; // Non-blocking connect is in progress
824 unsigned is_tls : 1; // TLS-enabled connection
825 unsigned is_tls_hs : 1; // TLS handshake is in progress
826 unsigned is_udp : 1; // UDP connection
827 unsigned is_websocket : 1; // WebSocket connection
828 unsigned is_hexdumping : 1; // Hexdump in/out traffic
829 unsigned is_draining : 1; // Send remaining data, then close and free
830 unsigned is_closing : 1; // Close and free the connection immediately
831 unsigned is_readable : 1; // Connection is ready to read
832 unsigned is_writable : 1; // Connection is ready to write
835 void mg_mgr_poll(struct mg_mgr *, int ms);
836 void mg_mgr_init(struct mg_mgr *);
837 void mg_mgr_free(struct mg_mgr *);
839 struct mg_connection *mg_listen(struct mg_mgr *, const char *url,
840 mg_event_handler_t fn, void *fn_data);
841 struct mg_connection *mg_connect(struct mg_mgr *, const char *url,
842 mg_event_handler_t fn, void *fn_data);
843 void mg_connect_resolved(struct mg_connection *);
844 bool mg_send(struct mg_connection *, const void *, size_t);
845 int mg_printf(struct mg_connection *, const char *fmt, ...);
846 int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
847 char *mg_straddr(struct mg_connection *, char *, size_t);
848 bool mg_aton(struct mg_str str, struct mg_addr *addr);
849 char *mg_ntoa(const struct mg_addr *addr, char *buf, size_t len);
851 struct mg_connection *mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *);
852 void mg_mgr_wakeup(struct mg_connection *pipe);
860 struct mg_http_header {
861 struct mg_str name; // Header name
862 struct mg_str value; // Header value
865 struct mg_http_message {
866 struct mg_str method, uri, query, proto; // Request/response line
867 struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
868 struct mg_str body; // Body
869 struct mg_str head; // Request + headers
870 struct mg_str chunk; // Chunk for chunked encoding, or partial body
871 struct mg_str message; // Request + headers + body
874 // Parameter for mg_http_serve_dir()
875 struct mg_http_serve_opts {
876 const char *root_dir; // Web root directory, must be non-NULL
877 const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
878 const char *extra_headers; // Extra HTTP headers to add in responses
879 const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
880 struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
883 // Parameter for mg_http_next_multipart
884 struct mg_http_part {
885 struct mg_str name; // Form field name
886 struct mg_str filename; // Filename for file uploads
887 struct mg_str body; // Part contents
890 int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
891 int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
892 void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...);
893 void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
894 void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
895 struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url,
896 mg_event_handler_t fn, void *fn_data);
897 struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
898 mg_event_handler_t fn, void *fn_data);
899 void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
900 struct mg_http_serve_opts *opts);
901 void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
902 const char *path, struct mg_http_serve_opts *opts);
903 void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
904 const char *body_fmt, ...);
905 struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
906 int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
907 int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
908 size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
909 void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
910 bool mg_http_match_uri(const struct mg_http_message *, const char *glob);
911 int mg_http_upload(struct mg_connection *, struct mg_http_message *hm,
913 void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
914 struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
915 size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
918 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
919 const char *fullpath);
927 const char *ca; // CA certificate file. For both listeners and clients
928 const char *crl; // Certificate Revocation List. For clients
929 const char *cert; // Certificate
930 const char *certkey; // Certificate key
931 const char *ciphers; // Cipher list
932 struct mg_str srvname; // If not empty, enables server name verification
935 void mg_tls_init(struct mg_connection *, struct mg_tls_opts *);
936 void mg_tls_free(struct mg_connection *);
937 long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
938 long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
939 void mg_tls_handshake(struct mg_connection *);
942 #if MG_ENABLE_MBEDTLS
947 #include <mbedtls/debug.h>
948 #include <mbedtls/ssl.h>
950 #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
951 #define RNG , rng_get, NULL
956 // Different versions have those in different files, so declare here
957 EXTERN_C int mbedtls_net_recv(void *, unsigned char *, size_t);
958 EXTERN_C int mbedtls_net_send(void *, const unsigned char *, size_t);
961 char *cafile; // CA certificate path
962 mbedtls_x509_crt ca; // Parsed CA certificate
963 mbedtls_x509_crl crl; // Parsed Certificate Revocation List
964 mbedtls_x509_crt cert; // Parsed certificate
965 mbedtls_ssl_context ssl; // SSL/TLS context
966 mbedtls_ssl_config conf; // SSL-TLS config
967 mbedtls_pk_context pk; // Private key context
972 #if MG_ENABLE_OPENSSL
974 #include <openssl/err.h>
975 #include <openssl/ssl.h>
984 #define WEBSOCKET_OP_CONTINUE 0
985 #define WEBSOCKET_OP_TEXT 1
986 #define WEBSOCKET_OP_BINARY 2
987 #define WEBSOCKET_OP_CLOSE 8
988 #define WEBSOCKET_OP_PING 9
989 #define WEBSOCKET_OP_PONG 10
993 struct mg_ws_message {
994 struct mg_str data; // Websocket message data
995 uint8_t flags; // Websocket message flags
998 struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url,
999 mg_event_handler_t fn, void *fn_data,
1000 const char *fmt, ...);
1001 void mg_ws_upgrade(struct mg_connection *, struct mg_http_message *,
1002 const char *fmt, ...);
1003 size_t mg_ws_send(struct mg_connection *, const char *buf, size_t len, int op);
1004 size_t mg_ws_wrap(struct mg_connection *, size_t len, int op);
1009 struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
1010 mg_event_handler_t fn, void *fn_data);
1011 void mg_sntp_send(struct mg_connection *c, unsigned long utc);
1012 int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv);
1018 #define MQTT_CMD_CONNECT 1
1019 #define MQTT_CMD_CONNACK 2
1020 #define MQTT_CMD_PUBLISH 3
1021 #define MQTT_CMD_PUBACK 4
1022 #define MQTT_CMD_PUBREC 5
1023 #define MQTT_CMD_PUBREL 6
1024 #define MQTT_CMD_PUBCOMP 7
1025 #define MQTT_CMD_SUBSCRIBE 8
1026 #define MQTT_CMD_SUBACK 9
1027 #define MQTT_CMD_UNSUBSCRIBE 10
1028 #define MQTT_CMD_UNSUBACK 11
1029 #define MQTT_CMD_PINGREQ 12
1030 #define MQTT_CMD_PINGRESP 13
1031 #define MQTT_CMD_DISCONNECT 14
1033 struct mg_mqtt_opts {
1034 struct mg_str user; // Username, can be empty
1035 struct mg_str pass; // Password, can be empty
1036 struct mg_str client_id; // Client ID
1037 struct mg_str will_topic; // Will topic
1038 struct mg_str will_message; // Will message
1039 uint8_t qos; // Quality of service
1040 bool will_retain; // Retain last will
1041 bool clean; // Use clean session, 0 or 1
1042 uint16_t keepalive; // Keep-alive timer in seconds
1045 struct mg_mqtt_message {
1046 struct mg_str topic; // Parsed topic
1047 struct mg_str data; // Parsed message
1048 struct mg_str dgram; // Whole MQTT datagram, including headers
1049 uint16_t id; // Set for PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
1050 uint8_t cmd; // MQTT command, one of MQTT_CMD_*
1051 uint8_t qos; // Quality of service
1052 uint8_t ack; // Connack return code. 0 - success
1055 struct mg_connection *mg_mqtt_connect(struct mg_mgr *, const char *url,
1056 struct mg_mqtt_opts *opts,
1057 mg_event_handler_t fn, void *fn_data);
1058 struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
1059 mg_event_handler_t fn, void *fn_data);
1060 void mg_mqtt_login(struct mg_connection *c, struct mg_mqtt_opts *opts);
1061 void mg_mqtt_pub(struct mg_connection *c, struct mg_str *topic,
1062 struct mg_str *data, int qos, bool retain);
1063 void mg_mqtt_sub(struct mg_connection *, struct mg_str *topic, int qos);
1064 int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
1065 void mg_mqtt_send_header(struct mg_connection *, uint8_t cmd, uint8_t flags,
1067 size_t mg_mqtt_next_sub(struct mg_mqtt_message *msg, struct mg_str *topic,
1068 uint8_t *qos, size_t pos);
1069 size_t mg_mqtt_next_unsub(struct mg_mqtt_message *msg, struct mg_str *topic,
1071 void mg_mqtt_ping(struct mg_connection *);
1072 void mg_mqtt_pong(struct mg_connection *);
1073 void mg_mqtt_disconnect(struct mg_connection *);
1079 // Mongoose sends DNS queries that contain only one question:
1080 // either A (IPv4) or AAAA (IPv6) address lookup.
1081 // Therefore, we expect zero or one answer.
1082 // If `resolved` is true, then `addr` contains resolved IPv4 or IPV6 address.
1083 struct mg_dns_message {
1084 uint16_t txnid; // Transaction ID
1085 bool resolved; // Resolve successful, addr is set
1086 struct mg_addr addr; // Resolved address
1087 char name[256]; // Host name
1090 struct mg_dns_header {
1091 uint16_t txnid; // Transaction ID
1093 uint16_t num_questions;
1094 uint16_t num_answers;
1095 uint16_t num_authority_prs;
1096 uint16_t num_other_prs;
1099 // DNS resource record
1101 uint16_t nlen; // Name or pointer length
1102 uint16_t atype; // Address type
1103 uint16_t aclass; // Address class
1104 uint16_t alen; // Address length
1107 void mg_resolve(struct mg_connection *, struct mg_str *, int);
1108 void mg_resolve_cancel(struct mg_connection *);
1109 bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
1110 size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
1111 bool is_question, struct mg_dns_rr *);
1112 size_t mg_dns_decode_name(const uint8_t *, size_t, size_t, char *, size_t);
1117 #endif // MONGOOSE_H