]> gitweb.ps.run Git - autorec/blob - src/mongoose.h
Merge branch 'main' of ps.run:autorec
[autorec] / src / mongoose.h
1 // Copyright (c) 2004-2013 Sergey Lyubka
2 // Copyright (c) 2013-2021 Cesanta Software Limited
3 // All rights reserved
4 //
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/
9 //
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.
14 //
15 // Alternatively, you can license this software under a commercial
16 // license, as set out in https://www.mongoose.ws/licensing/
17
18 #ifndef MONGOOSE_H
19 #define MONGOOSE_H
20
21 #define MG_VERSION "7.5"
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27
28 #ifndef MG_ENABLE_SOCKET
29 #define MG_ENABLE_SOCKET 1
30 #endif
31
32 #ifndef MG_ENABLE_MBEDTLS
33 #define MG_ENABLE_MBEDTLS 0
34 #endif
35
36 #ifndef MG_ENABLE_OPENSSL
37 #define MG_ENABLE_OPENSSL 0
38 #endif
39
40 #ifndef MG_ENABLE_CUSTOM_TLS
41 #define MG_ENABLE_CUSTOM_TLS 0
42 #endif
43
44 #ifndef MG_ENABLE_SSI
45 #define MG_ENABLE_SSI 1
46 #endif
47
48 #ifndef MG_ENABLE_IPV6
49 #define MG_ENABLE_IPV6 0
50 #endif
51
52 #ifndef MG_ENABLE_LOG
53 #define MG_ENABLE_LOG 1
54 #endif
55
56 #ifndef MG_ENABLE_MD5
57 #define MG_ENABLE_MD5 0
58 #endif
59
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
63 #endif
64
65 #ifndef MG_ENABLE_DIRLIST
66 #define MG_ENABLE_DIRLIST 0
67 #endif
68
69 #ifndef MG_ENABLE_CUSTOM_RANDOM
70 #define MG_ENABLE_CUSTOM_RANDOM 0
71 #endif
72
73 #ifndef MG_ENABLE_PACKED_FS
74 #define MG_ENABLE_PACKED_FS 0
75 #endif
76
77 // Granularity of the send/recv IO buffer growth
78 #ifndef MG_IO_SIZE
79 #define MG_IO_SIZE 2048
80 #endif
81
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)
85 #endif
86
87 #ifndef MG_MAX_HTTP_HEADERS
88 #define MG_MAX_HTTP_HEADERS 40
89 #endif
90
91 #ifndef MG_HTTP_INDEX
92 #define MG_HTTP_INDEX "index.html"
93 #endif
94
95 #ifndef MG_PATH_MAX
96 #define MG_PATH_MAX PATH_MAX
97 #endif
98
99 #ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
100 #define MG_SOCK_LISTEN_BACKLOG_SIZE 128
101 #endif
102
103
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
112
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
126 #endif
127
128 #if !defined(MG_ARCH)
129 #error "MG_ARCH is not specified and we couldn't guess it."
130 #endif
131 #endif  // !defined(MG_ARCH)
132
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)))
136 #else
137 #define PRINTF_LIKE(f, a)
138 #endif
139 #endif
140
141 #if MG_ARCH == MG_ARCH_CUSTOM
142 #include <mongoose_custom.h>
143 #endif
144
145
146
147
148
149
150
151
152
153 #if MG_ARCH == MG_ARCH_AZURERTOS
154
155 #include <stdarg.h>
156 #include <stdint.h>
157 #include <stdbool.h>
158 #include <time.h>
159 #include <stdio.h>
160  
161 #include <tx_api.h>
162 #include <fx_api.h>
163
164 #include <tx_port.h>
165 #include <nx_port.h>
166 #include <nx_api.h>
167 #include <nx_bsd.h>
168
169 #ifdef __REDLIB__
170 #define va_copy(d,s)__builtin_va_copy(d,s)
171 #endif
172
173 #define PATH_MAX FX_MAXIMUM_PATH
174 #define MG_DIRSEP '\\'
175
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"
180
181 static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
182   (void) tm;
183   return localtime(t);
184 }
185
186 #undef FOPEN_MAX
187
188 #endif
189
190
191 #if MG_ARCH == MG_ARCH_ESP32
192
193 #include <ctype.h>
194 #include <dirent.h>
195 #include <errno.h>
196 #include <fcntl.h>
197 #include <limits.h>
198 #include <netdb.h>
199 #include <stdarg.h>
200 #include <stddef.h>
201 #include <stdio.h>
202 #include <stdlib.h>
203 #include <string.h>
204 #include <sys/stat.h>
205 #include <sys/types.h>
206 #include <time.h>
207
208 #undef MG_PATH_MAX
209 #undef MG_ENABLE_DIRLIST
210
211 #define MG_DIRSEP '/'
212 #define MG_INT64_FMT "%lld"
213 #define MG_PATH_MAX 128
214 #define MG_ENABLE_DIRLIST 1
215
216 #endif
217
218
219 #if MG_ARCH == MG_ARCH_ESP8266
220
221 #include <ctype.h>
222 #include <dirent.h>
223 #include <errno.h>
224 #include <fcntl.h>
225 #include <limits.h>
226 #include <netdb.h>
227 #include <stdarg.h>
228 #include <stdbool.h>
229 #include <stddef.h>
230 #include <stdio.h>
231 #include <stdlib.h>
232 #include <string.h>
233 #include <sys/stat.h>
234 #include <sys/time.h>
235 #include <sys/types.h>
236 #include <time.h>
237
238 #include <esp_system.h>
239
240 #undef MG_PATH_MAX
241 #undef MG_ENABLE_DIRLIST
242
243 #define MG_DIRSEP '/'
244 #define MG_INT64_FMT "%lld"
245 #define MG_PATH_MAX 128
246 #define MG_ENABLE_DIRLIST 1
247
248 #endif
249
250
251 #if MG_ARCH == MG_ARCH_FREERTOS_LWIP
252
253 #include <stdarg.h>
254 #include <stdbool.h>
255 #include <stdint.h>
256 #include <string.h>
257 #include <stdio.h>
258
259 #if defined(__GNUC__)
260 #include <sys/stat.h>
261 #include <sys/time.h>
262 #else
263 typedef long suseconds_t;
264 struct timeval {
265   time_t tv_sec;
266   suseconds_t tv_usec;
267 };
268 #endif
269
270 #include <FreeRTOS.h>
271 #include <task.h>
272
273 #include <lwip/sockets.h>
274
275 #if LWIP_SOCKET != 1
276 // Sockets support disabled in LWIP by default
277 #error Set LWIP_SOCKET variable to 1 (in lwipopts.h)
278 #endif
279
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`
283 // conflict
284 #error LWIP_POSIX_SOCKETS_IO_NAMES must be set to 0 (in lwipopts.h) for FreeRTOS
285 #endif
286
287 #define MG_INT64_FMT "%lld"
288 #define MG_DIRSEP '/'
289
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);
294   return p;
295 }
296 #define calloc(a, b) mg_calloc((a), (b))
297 #define free(a) vPortFree(a)
298 #define malloc(a) pvPortMalloc(a)
299
300 #define gmtime_r(a, b) gmtime(a)
301
302 #endif  // MG_ARCH == MG_ARCH_FREERTOS_LWIP
303
304
305 #if MG_ARCH == MG_ARCH_FREERTOS_TCP
306
307 #include <ctype.h>
308 #include <errno.h>
309 #include <limits.h>
310 #include <stdarg.h>
311 #include <stdbool.h>
312 #include <stddef.h>
313 #include <stdio.h>
314 #include <stdlib.h>
315 #include <string.h>
316 #include <sys/stat.h>
317 #include <time.h>
318
319 #include <FreeRTOS.h>
320 #include <FreeRTOS_IP.h>
321 #include <FreeRTOS_Sockets.h>
322 #include <task.h>
323
324 #define MG_INT64_FMT "%lld"
325 #define MG_DIRSEP '/'
326
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
335 #define SO_ERROR 0
336 #define SOL_SOCKET 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)
354
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);
359   return p;
360 }
361 #define calloc(a, b) mg_calloc((a), (b))
362 #define free(a) vPortFree(a)
363 #define malloc(a) pvPortMalloc(a)
364
365 #define gmtime_r(a, b) gmtime(a)
366
367 #if !defined(__GNUC__)
368 // copied from GCC on ARM; for some reason useconds are signed
369 typedef long suseconds_t;
370 struct timeval {
371   time_t tv_sec;
372   suseconds_t tv_usec;
373 };
374 #endif
375
376 #ifndef EINPROGRESS
377 #define EINPROGRESS pdFREERTOS_ERRNO_EINPROGRESS
378 #endif
379 #ifndef EWOULDBLOCK
380 #define EWOULDBLOCK pdFREERTOS_ERRNO_EWOULDBLOCK
381 #endif
382 #ifndef EAGAIN
383 #define EAGAIN pdFREERTOS_ERRNO_EAGAIN
384 #endif
385 #ifndef EINTR
386 #define EINTR pdFREERTOS_ERRNO_EINTR
387 #endif
388
389 #endif  // MG_ARCH == MG_ARCH_FREERTOS_TCP
390
391
392 #if MG_ARCH == MG_ARCH_UNIX
393
394 #define _DARWIN_UNLIMITED_SELECT 1  // No limit on file descriptors
395
396 #include <arpa/inet.h>
397 #include <ctype.h>
398 #include <dirent.h>
399 #include <errno.h>
400 #include <fcntl.h>
401 #include <inttypes.h>
402 #include <limits.h>
403 #include <netdb.h>
404 #include <netinet/tcp.h>
405 #include <signal.h>
406 #include <stdarg.h>
407 #include <stdbool.h>
408 #include <stddef.h>
409 #include <stdint.h>
410 #include <stdio.h>
411 #include <stdlib.h>
412 #include <string.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>
418 #include <time.h>
419 #include <unistd.h>
420
421 #define MG_DIRSEP '/'
422 #define MG_INT64_FMT "%" PRId64
423 #undef MG_ENABLE_DIRLIST
424 #define MG_ENABLE_DIRLIST 1
425
426 #endif
427
428
429 #if MG_ARCH == MG_ARCH_WIN32
430
431 #ifndef WIN32_LEAN_AND_MEAN
432 #define WIN32_LEAN_AND_MEAN
433 #endif
434
435 #ifndef _CRT_SECURE_NO_WARNINGS
436 #define _CRT_SECURE_NO_WARNINGS
437 #endif
438
439 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
440 #define _WINSOCK_DEPRECATED_NO_WARNINGS
441 #endif
442
443 #include <ctype.h>
444 #include <errno.h>
445 #include <fcntl.h>
446 #include <limits.h>
447 #include <stdarg.h>
448 #include <stddef.h>
449 #include <stdio.h>
450 #include <stdlib.h>
451 #include <string.h>
452 #include <sys/stat.h>
453 #include <sys/types.h>
454 #include <time.h>
455
456 #if defined(_MSC_VER) && _MSC_VER < 1700
457 #define __func__ ""
458 typedef __int64 int64_t;
459 typedef unsigned __int64 uint64_t;
460 typedef unsigned char uint8_t;
461 typedef char int8_t;
462 typedef unsigned short uint16_t;
463 typedef short int16_t;
464 typedef unsigned int uint32_t;
465 typedef int int32_t;
466 typedef enum { false = 0, true = 1 } bool;
467 #else
468 #include <stdbool.h>
469 #include <stdint.h>
470 #include <ws2tcpip.h>
471 #endif
472
473 #include <winsock2.h>
474
475 // Protect from calls like std::snprintf in app code
476 // See https://github.com/cesanta/mongoose/issues/1047
477 #ifndef __cplusplus
478 #define snprintf _snprintf
479 #define vsnprintf _vsnprintf
480 #ifndef strdup  // For MSVC with _DEBUG, see #1359
481 #define strdup(x) _strdup(x)
482 #endif
483 #endif
484
485 typedef unsigned suseconds_t;
486 typedef int socklen_t;
487 #define MG_DIRSEP '\\'
488 #ifndef PATH_MAX
489 #define PATH_MAX MAX_PATH
490 #endif
491 #ifndef EINPROGRESS
492 #define EINPROGRESS WSAEINPROGRESS
493 #endif
494 #ifndef EWOULDBLOCK
495 #define EWOULDBLOCK WSAEWOULDBLOCK
496 #endif
497
498 #ifndef va_copy
499 #ifdef __va_copy
500 #define va_copy __va_copy
501 #else
502 #define va_copy(x, y) (x) = (y)
503 #endif
504 #endif
505 #ifndef S_ISDIR
506 #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
507 #endif
508
509 #define MG_INT64_FMT "%I64d"
510
511 #undef MG_ENABLE_DIRLIST
512 #define MG_ENABLE_DIRLIST 1
513
514 // https://lgtm.com/rules/2154840805/ -gmtime, localtime, ctime and asctime
515 static __inline struct tm *gmtime_r(time_t *t, struct tm *tm) {
516   (void) tm;
517   return gmtime(t);
518 }
519
520 static __inline struct tm *localtime_r(time_t *t, struct tm *tm) {
521   (void) tm;
522   return localtime(t);
523 }
524
525 #endif
526
527
528 #include <ctype.h>
529 #include <string.h>
530
531 struct mg_str {
532   const char *ptr;  // Pointer to string data
533   size_t len;       // String len
534 };
535
536 #define MG_NULL_STR \
537   { NULL, 0 }
538
539 // Using macro to avoid shadowing C++ struct constructor, see #1298
540 #define mg_str(s) mg_str_s(s)
541
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);
553
554
555
556
557
558 #if MG_ENABLE_LOG
559 #define LOG(level, args)                                                   \
560   do {                                                                     \
561     if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \
562   } while (0)
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);
568 #else
569 #define LOG(level, args) (void) 0
570 #define mg_log_set(x) (void) (x)
571 #endif
572
573
574 struct mg_timer {
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
583 };
584
585 extern struct mg_timer *g_timers;  // Global list of timers
586
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);
591
592
593
594
595
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);
616
617 #define mg_htons(x) mg_ntohs(x)
618 #define mg_htonl(x) mg_ntohl(x)
619
620 #ifndef EXTERN_C
621 #ifdef __cplusplus
622 #define EXTERN_C extern "C"
623 #else
624 #define EXTERN_C
625 #endif
626 #endif
627
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__
632 #else
633 #define MG_STRINGIFY_LITERAL(x) #x
634 #endif
635 // Expands to a string representation of its argument, which can be a macro:
636 // #define FOO 123
637 // MG_STRINGIFY_MACRO(FOO)  // Expands to 123
638 #define MG_STRINGIFY_MACRO(x) MG_STRINGIFY_LITERAL(x)
639
640 // Linked list management macros
641 #define LIST_ADD_HEAD(type_, head_, elem_) \
642   do {                                     \
643     (elem_)->next = (*head_);              \
644     *(head_) = (elem_);                    \
645   } while (0)
646
647 #define LIST_ADD_TAIL(type_, head_, elem_) \
648   do {                                     \
649     type_ **h = head_;                     \
650     while (*h != NULL) h = &(*h)->next;    \
651     *h = (elem_);                          \
652   } while (0)
653
654 #define LIST_DELETE(type_, head_, elem_)   \
655   do {                                     \
656     type_ **h = head_;                     \
657     while (*h != (elem_)) h = &(*h)->next; \
658     *h = (elem_)->next;                    \
659   } while (0)
660
661
662
663
664 enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 };
665
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
669 struct mg_fs {
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
677 };
678
679 // File descriptor
680 struct mg_fd {
681   void *fd;
682   struct mg_fs *fs;
683 };
684
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
687
688
689
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);
696
697
698 #include <stddef.h>
699
700 struct mg_iobuf {
701   unsigned char *buf;  // Pointer to stored data
702   size_t size;         // Total size available
703   size_t len;          // Current number of bytes
704 };
705
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);
711
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);
716
717
718
719
720 typedef struct {
721   uint32_t buf[4];
722   uint32_t bits[2];
723   unsigned char in[64];
724 } mg_md5_ctx;
725
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]);
729
730
731
732
733 typedef struct {
734   uint32_t state[5];
735   uint32_t count[2];
736   unsigned char buffer[64];
737 } mg_sha1_ctx;
738
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]);
745
746
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, ...);
752
753 enum {
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
773 };
774
775
776
777
778
779
780
781 struct mg_dns {
782   const char *url;          // DNS server URL
783   struct mg_connection *c;  // DNS server connection
784 };
785
786 struct mg_addr {
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
791 };
792
793 struct mg_mgr {
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
802 #endif
803 };
804
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
833 };
834
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 *);
838
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);
850
851 struct mg_connection *mg_mkpipe(struct mg_mgr *, mg_event_handler_t, void *);
852 void mg_mgr_wakeup(struct mg_connection *pipe);
853
854
855
856
857
858
859
860 struct mg_http_header {
861   struct mg_str name;   // Header name
862   struct mg_str value;  // Header value
863 };
864
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
872 };
873
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
881 };
882
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
888 };
889
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,
912                    const char *dir);
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 *);
916
917
918 void mg_http_serve_ssi(struct mg_connection *c, const char *root,
919                        const char *fullpath);
920
921
922
923
924
925
926 struct mg_tls_opts {
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
933 };
934
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 *);
940
941
942 #if MG_ENABLE_MBEDTLS
943
944
945
946
947 #include <mbedtls/debug.h>
948 #include <mbedtls/ssl.h>
949
950 #if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
951 #define RNG , rng_get, NULL
952 #else
953 #define RNG
954 #endif
955
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);
959
960 struct mg_tls {
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
968 };
969 #endif
970
971
972 #if MG_ENABLE_OPENSSL
973
974 #include <openssl/err.h>
975 #include <openssl/ssl.h>
976
977 struct mg_tls {
978   SSL_CTX *ctx;
979   SSL *ssl;
980 };
981 #endif
982
983
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
990
991
992
993 struct mg_ws_message {
994   struct mg_str data;  // Websocket message data
995   uint8_t flags;       // Websocket message flags
996 };
997
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);
1005
1006
1007
1008
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);
1013
1014
1015
1016
1017
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
1032
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
1043 };
1044
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
1053 };
1054
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,
1066                          uint32_t len);
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,
1070                           size_t pos);
1071 void mg_mqtt_ping(struct mg_connection *);
1072 void mg_mqtt_pong(struct mg_connection *);
1073 void mg_mqtt_disconnect(struct mg_connection *);
1074
1075
1076
1077
1078
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
1088 };
1089
1090 struct mg_dns_header {
1091   uint16_t txnid;  // Transaction ID
1092   uint16_t flags;
1093   uint16_t num_questions;
1094   uint16_t num_answers;
1095   uint16_t num_authority_prs;
1096   uint16_t num_other_prs;
1097 };
1098
1099 // DNS resource record
1100 struct mg_dns_rr {
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
1105 };
1106
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);
1113
1114 #ifdef __cplusplus
1115 }
1116 #endif
1117 #endif  // MONGOOSE_H