source: smplayer/trunk/webserver/mongoose.h

Last change on this file was 186, checked in by Silvan Scherrer, 8 years ago

SMPlayer: update vendor to 17.1.0

File size: 166.4 KB
Line 
1#ifdef MG_MODULE_LINES
2#line 1 "mongoose/src/common.h"
3#endif
4/*
5 * Copyright (c) 2004-2013 Sergey Lyubka
6 * Copyright (c) 2013-2015 Cesanta Software Limited
7 * All rights reserved
8 *
9 * This software is dual-licensed: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. For the terms of this
12 * license, see <http://www.gnu.org/licenses/>.
13 *
14 * You are free to use this software under the terms of the GNU General
15 * Public License, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * See the GNU General Public License for more details.
18 *
19 * Alternatively, you can license this software under a commercial
20 * license, as set out in <https://www.cesanta.com/license>.
21 */
22
23#ifndef CS_MONGOOSE_SRC_COMMON_H_
24#define CS_MONGOOSE_SRC_COMMON_H_
25
26#define MG_VERSION "6.6"
27
28/* Local tweaks, applied before any of Mongoose's own headers. */
29#ifdef MG_LOCALS
30#include <mg_locals.h>
31#endif
32
33#endif /* CS_MONGOOSE_SRC_COMMON_H_ */
34#ifdef MG_MODULE_LINES
35#line 1 "common/platform.h"
36#endif
37#ifndef CS_COMMON_PLATFORM_H_
38#define CS_COMMON_PLATFORM_H_
39
40/*
41 * For the "custom" platform, includes and dependencies can be
42 * provided through mg_locals.h.
43 */
44#define CS_P_CUSTOM 0
45#define CS_P_UNIX 1
46#define CS_P_WINDOWS 2
47#define CS_P_ESP32 15
48#define CS_P_ESP8266 3
49#define CS_P_CC3200 4
50#define CS_P_MSP432 5
51#define CS_P_CC3100 6
52#define CS_P_TM4C129 14
53#define CS_P_MBED 7
54#define CS_P_WINCE 8
55#define CS_P_NXP_LPC 13
56#define CS_P_NXP_KINETIS 9
57#define CS_P_NRF51 12
58#define CS_P_NRF52 10
59#define CS_P_PIC32 11
60/* Next id: 16 */
61
62/* If not specified explicitly, we guess platform by defines. */
63#ifndef CS_PLATFORM
64
65#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
66#define CS_PLATFORM CS_P_MSP432
67#elif defined(cc3200)
68#define CS_PLATFORM CS_P_CC3200
69#elif defined(__unix__) || defined(__APPLE__)
70#define CS_PLATFORM CS_P_UNIX
71#elif defined(WINCE)
72#define CS_PLATFORM CS_P_WINCE
73#elif defined(_WIN32)
74#define CS_PLATFORM CS_P_WINDOWS
75#elif defined(__MBED__)
76#define CS_PLATFORM CS_P_MBED
77#elif defined(__USE_LPCOPEN)
78#define CS_PLATFORM CS_P_NXP_LPC
79#elif defined(FRDM_K64F) || defined(FREEDOM)
80#define CS_PLATFORM CS_P_NXP_KINETIS
81#elif defined(PIC32)
82#define CS_PLATFORM CS_P_PIC32
83#elif defined(ESP_PLATFORM)
84#define CS_PLATFORM CS_P_ESP32
85#elif defined(ICACHE_FLASH)
86#define CS_PLATFORM CS_P_ESP8266
87#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
88 defined(TARGET_IS_TM4C129_RA2)
89#define CS_PLATFORM CS_P_TM4C129
90#endif
91
92#ifndef CS_PLATFORM
93#error "CS_PLATFORM is not specified and we couldn't guess it."
94#endif
95
96#endif /* !defined(CS_PLATFORM) */
97
98#define MG_NET_IF_SOCKET 1
99#define MG_NET_IF_SIMPLELINK 2
100#define MG_NET_IF_LWIP_LOW_LEVEL 3
101#define MG_NET_IF_PIC32 4
102
103#define MG_SSL_IF_OPENSSL 1
104#define MG_SSL_IF_MBEDTLS 2
105#define MG_SSL_IF_SIMPLELINK 3
106
107/* Amalgamated: #include "common/platforms/platform_unix.h" */
108/* Amalgamated: #include "common/platforms/platform_windows.h" */
109/* Amalgamated: #include "common/platforms/platform_esp32.h" */
110/* Amalgamated: #include "common/platforms/platform_esp8266.h" */
111/* Amalgamated: #include "common/platforms/platform_cc3200.h" */
112/* Amalgamated: #include "common/platforms/platform_cc3100.h" */
113/* Amalgamated: #include "common/platforms/platform_mbed.h" */
114/* Amalgamated: #include "common/platforms/platform_nrf51.h" */
115/* Amalgamated: #include "common/platforms/platform_nrf52.h" */
116/* Amalgamated: #include "common/platforms/platform_wince.h" */
117/* Amalgamated: #include "common/platforms/platform_nxp_lpc.h" */
118/* Amalgamated: #include "common/platforms/platform_nxp_kinetis.h" */
119/* Amalgamated: #include "common/platforms/platform_pic32.h" */
120
121/* Common stuff */
122
123#if !defined(WEAK)
124#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
125#define WEAK __attribute__((weak))
126#else
127#define WEAK
128#endif
129#endif
130
131#ifdef __GNUC__
132#define NORETURN __attribute__((noreturn))
133#define NOINLINE __attribute__((noinline))
134#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
135#define NOINSTR __attribute__((no_instrument_function))
136#define DO_NOT_WARN_UNUSED __attribute__((unused))
137#else
138#define NORETURN
139#define NOINLINE
140#define WARN_UNUSED_RESULT
141#define NOINSTR
142#define DO_NOT_WARN_UNUSED
143#endif /* __GNUC__ */
144
145#ifndef ARRAY_SIZE
146#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
147#endif
148
149#endif /* CS_COMMON_PLATFORM_H_ */
150#ifdef MG_MODULE_LINES
151#line 1 "common/platforms/platform_windows.h"
152#endif
153#ifndef CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
154#define CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
155#if CS_PLATFORM == CS_P_WINDOWS
156
157/*
158 * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
159 * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
160 * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
161 * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
162 * MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
163 * MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
164 * MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
165 * MSVC++ 7.0 _MSC_VER == 1300
166 * MSVC++ 6.0 _MSC_VER == 1200
167 * MSVC++ 5.0 _MSC_VER == 1100
168 */
169#ifdef _MSC_VER
170#pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */
171#pragma warning(disable : 4204) /* missing c99 support */
172#endif
173
174#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
175#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
176#endif
177
178#ifndef _CRT_SECURE_NO_WARNINGS
179#define _CRT_SECURE_NO_WARNINGS
180#endif
181
182#include <assert.h>
183#include <direct.h>
184#include <errno.h>
185#include <fcntl.h>
186#include <io.h>
187#include <limits.h>
188#include <signal.h>
189#include <stddef.h>
190#include <stdio.h>
191#include <stdlib.h>
192#include <sys/stat.h>
193#include <time.h>
194
195#ifdef _MSC_VER
196#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
197#endif
198
199#include <winsock2.h>
200#include <ws2tcpip.h>
201#include <windows.h>
202#include <process.h>
203
204#if defined(_MSC_VER) && _MSC_VER >= 1800
205#define strdup _strdup
206#endif
207
208#ifndef EINPROGRESS
209#define EINPROGRESS WSAEINPROGRESS
210#endif
211#ifndef EWOULDBLOCK
212#define EWOULDBLOCK WSAEWOULDBLOCK
213#endif
214#ifndef __func__
215#define STRX(x) #x
216#define STR(x) STRX(x)
217#define __func__ __FILE__ ":" STR(__LINE__)
218#endif
219#define snprintf _snprintf
220#define fileno _fileno
221#define vsnprintf _vsnprintf
222#define sleep(x) Sleep((x) *1000)
223#define to64(x) _atoi64(x)
224#if !defined(__MINGW32__) && !defined(__MINGW64__)
225#define popen(x, y) _popen((x), (y))
226#define pclose(x) _pclose(x)
227#endif
228#define rmdir _rmdir
229#if defined(_MSC_VER) && _MSC_VER >= 1400
230#define fseeko(x, y, z) _fseeki64((x), (y), (z))
231#else
232#define fseeko(x, y, z) fseek((x), (y), (z))
233#endif
234#if defined(_MSC_VER) && _MSC_VER <= 1200
235typedef unsigned long uintptr_t;
236typedef long intptr_t;
237#endif
238typedef int socklen_t;
239#if _MSC_VER >= 1700
240#include <stdint.h>
241#else
242typedef signed char int8_t;
243typedef unsigned char uint8_t;
244typedef int int32_t;
245typedef unsigned int uint32_t;
246typedef short int16_t;
247typedef unsigned short uint16_t;
248typedef __int64 int64_t;
249typedef unsigned __int64 uint64_t;
250#endif
251typedef SOCKET sock_t;
252typedef uint32_t in_addr_t;
253#ifndef UINT16_MAX
254#define UINT16_MAX 65535
255#endif
256#ifndef UINT32_MAX
257#define UINT32_MAX 4294967295
258#endif
259#ifndef pid_t
260#define pid_t HANDLE
261#endif
262#define INT64_FMT "I64d"
263#define INT64_X_FMT "I64x"
264#define SIZE_T_FMT "Iu"
265typedef struct _stati64 cs_stat_t;
266#ifndef S_ISDIR
267#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
268#endif
269#ifndef S_ISREG
270#define S_ISREG(x) (((x) &_S_IFMT) == _S_IFREG)
271#endif
272#define DIRSEP '\\'
273
274#ifndef va_copy
275#ifdef __va_copy
276#define va_copy __va_copy
277#else
278#define va_copy(x, y) (x) = (y)
279#endif
280#endif
281
282#ifndef MG_MAX_HTTP_REQUEST_SIZE
283#define MG_MAX_HTTP_REQUEST_SIZE 8192
284#endif
285
286#ifndef MG_MAX_HTTP_SEND_MBUF
287#define MG_MAX_HTTP_SEND_MBUF 4096
288#endif
289
290#ifndef MG_MAX_HTTP_HEADERS
291#define MG_MAX_HTTP_HEADERS 40
292#endif
293
294#ifndef CS_ENABLE_STDIO
295#define CS_ENABLE_STDIO 1
296#endif
297
298#ifndef MG_ENABLE_BROADCAST
299#define MG_ENABLE_BROADCAST 1
300#endif
301
302#ifndef MG_ENABLE_DIRECTORY_LISTING
303#define MG_ENABLE_DIRECTORY_LISTING 1
304#endif
305
306#ifndef MG_ENABLE_FILESYSTEM
307#define MG_ENABLE_FILESYSTEM 1
308#endif
309
310#ifndef MG_ENABLE_HTTP_CGI
311#define MG_ENABLE_HTTP_CGI MG_ENABLE_FILESYSTEM
312#endif
313
314#ifndef MG_NET_IF
315#define MG_NET_IF MG_NET_IF_SOCKET
316#endif
317
318#endif /* CS_PLATFORM == CS_P_WINDOWS */
319#endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */
320#ifdef MG_MODULE_LINES
321#line 1 "common/platforms/platform_unix.h"
322#endif
323#ifndef CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
324#define CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
325#if CS_PLATFORM == CS_P_UNIX
326
327#ifndef _XOPEN_SOURCE
328#define _XOPEN_SOURCE 600
329#endif
330
331/* <inttypes.h> wants this for C++ */
332#ifndef __STDC_FORMAT_MACROS
333#define __STDC_FORMAT_MACROS
334#endif
335
336/* C++ wants that for INT64_MAX */
337#ifndef __STDC_LIMIT_MACROS
338#define __STDC_LIMIT_MACROS
339#endif
340
341/* Enable fseeko() and ftello() functions */
342#ifndef _LARGEFILE_SOURCE
343#define _LARGEFILE_SOURCE
344#endif
345
346/* Enable 64-bit file offsets */
347#ifndef _FILE_OFFSET_BITS
348#define _FILE_OFFSET_BITS 64
349#endif
350
351#include <arpa/inet.h>
352#include <assert.h>
353#include <ctype.h>
354#include <dirent.h>
355#include <errno.h>
356#include <fcntl.h>
357#include <inttypes.h>
358#include <stdint.h>
359#include <limits.h>
360#include <math.h>
361#include <netdb.h>
362#include <netinet/in.h>
363#include <pthread.h>
364#include <signal.h>
365#include <stdarg.h>
366#include <stdio.h>
367#include <stdlib.h>
368#include <string.h>
369#include <sys/param.h>
370#include <sys/socket.h>
371#include <sys/select.h>
372#include <sys/stat.h>
373#include <sys/time.h>
374#include <sys/types.h>
375#include <unistd.h>
376
377#ifdef __APPLE__
378#include <machine/endian.h>
379#ifndef BYTE_ORDER
380#define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
381#define BIG_ENDIAN __DARWIN_BIG_ENDIAN
382#define PDP_ENDIAN __DARWIN_PDP_ENDIAN
383#define BYTE_ORDER __DARWIN_BYTE_ORDER
384#endif
385#endif
386
387/*
388 * osx correctly avoids defining strtoll when compiling in strict ansi mode.
389 * c++ 11 standard defines strtoll as well.
390 * We require strtoll, and if your embedded pre-c99 compiler lacks one, please
391 * implement a shim.
392 */
393#if !(defined(__cplusplus) && __cplusplus >= 201103L) && \
394 !(defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L)
395long long strtoll(const char *, char **, int);
396#endif
397
398typedef int sock_t;
399#define INVALID_SOCKET (-1)
400#define SIZE_T_FMT "zu"
401typedef struct stat cs_stat_t;
402#define DIRSEP '/'
403#define to64(x) strtoll(x, NULL, 10)
404#define INT64_FMT PRId64
405#define INT64_X_FMT PRIx64
406
407#ifndef __cdecl
408#define __cdecl
409#endif
410
411#ifndef va_copy
412#ifdef __va_copy
413#define va_copy __va_copy
414#else
415#define va_copy(x, y) (x) = (y)
416#endif
417#endif
418
419#define closesocket(x) close(x)
420
421#ifndef MG_MAX_HTTP_REQUEST_SIZE
422#define MG_MAX_HTTP_REQUEST_SIZE 8192
423#endif
424
425#ifndef MG_MAX_HTTP_SEND_MBUF
426#define MG_MAX_HTTP_SEND_MBUF 4096
427#endif
428
429#ifndef MG_MAX_HTTP_HEADERS
430#define MG_MAX_HTTP_HEADERS 40
431#endif
432
433#ifndef CS_ENABLE_STDIO
434#define CS_ENABLE_STDIO 1
435#endif
436
437#ifndef MG_ENABLE_BROADCAST
438#define MG_ENABLE_BROADCAST 1
439#endif
440
441#ifndef MG_ENABLE_DIRECTORY_LISTING
442#define MG_ENABLE_DIRECTORY_LISTING 1
443#endif
444
445#ifndef MG_ENABLE_FILESYSTEM
446#define MG_ENABLE_FILESYSTEM 1
447#endif
448
449#ifndef MG_ENABLE_HTTP_CGI
450#define MG_ENABLE_HTTP_CGI MG_ENABLE_FILESYSTEM
451#endif
452
453#ifndef MG_NET_IF
454#define MG_NET_IF MG_NET_IF_SOCKET
455#endif
456
457#endif /* CS_PLATFORM == CS_P_UNIX */
458#endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */
459#ifdef MG_MODULE_LINES
460#line 1 "common/platforms/platform_esp32.h"
461#endif
462/*
463 * Copyright (c) 2014-2016 Cesanta Software Limited
464 * All rights reserved
465 */
466
467#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_
468#define CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_
469#if CS_PLATFORM == CS_P_ESP32
470
471#include <assert.h>
472#include <ctype.h>
473#include <fcntl.h>
474#include <inttypes.h>
475#include <machine/endian.h>
476#include <stdint.h>
477#include <string.h>
478#include <sys/stat.h>
479#include <sys/time.h>
480
481#define SIZE_T_FMT "u"
482typedef struct stat cs_stat_t;
483#define DIRSEP '/'
484#define to64(x) strtoll(x, NULL, 10)
485#define INT64_FMT PRId64
486#define INT64_X_FMT PRIx64
487#define __cdecl
488#define _FILE_OFFSET_BITS 32
489
490#define MG_LWIP 1
491
492#ifndef MG_NET_IF
493#define MG_NET_IF MG_NET_IF_SOCKET
494#endif
495
496#ifndef CS_ENABLE_STDIO
497#define CS_ENABLE_STDIO 1
498#endif
499
500#endif /* CS_PLATFORM == CS_P_ESP32 */
501#endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP32_H_ */
502#ifdef MG_MODULE_LINES
503#line 1 "common/platforms/platform_esp8266.h"
504#endif
505/*
506 * Copyright (c) 2014-2016 Cesanta Software Limited
507 * All rights reserved
508 */
509
510#ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_
511#define CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_
512#if CS_PLATFORM == CS_P_ESP8266
513
514#include <assert.h>
515#include <ctype.h>
516#include <fcntl.h>
517#include <inttypes.h>
518#include <machine/endian.h>
519#include <string.h>
520#include <sys/stat.h>
521#include <sys/time.h>
522
523#define SIZE_T_FMT "u"
524typedef struct stat cs_stat_t;
525#define DIRSEP '/'
526#define to64(x) strtoll(x, NULL, 10)
527#define INT64_FMT PRId64
528#define INT64_X_FMT PRIx64
529#define __cdecl
530#define _FILE_OFFSET_BITS 32
531
532#ifndef RTOS_SDK
533#define fileno(x) -1
534#endif
535
536#define MG_LWIP 1
537
538/* struct timeval is defined in sys/time.h. */
539#define LWIP_TIMEVAL_PRIVATE 0
540
541#ifndef MG_NET_IF
542#include <lwip/opt.h>
543#if LWIP_SOCKET /* RTOS SDK has LWIP sockets */
544# define MG_NET_IF MG_NET_IF_SOCKET
545#else
546# define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
547#endif
548#endif
549
550#ifndef CS_ENABLE_STDIO
551#define CS_ENABLE_STDIO 1
552#endif
553
554#endif /* CS_PLATFORM == CS_P_ESP8266 */
555#endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP8266_H_ */
556#ifdef MG_MODULE_LINES
557#line 1 "common/platforms/platform_cc3100.h"
558#endif
559/*
560 * Copyright (c) 2014-2016 Cesanta Software Limited
561 * All rights reserved
562 */
563
564#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
565#define CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
566#if CS_PLATFORM == CS_P_CC3100
567
568#include <assert.h>
569#include <ctype.h>
570#include <errno.h>
571#include <inttypes.h>
572#include <stdint.h>
573#include <string.h>
574#include <time.h>
575
576#define MG_NET_IF MG_NET_IF_SIMPLELINK
577#define MG_SSL_IF MG_SSL_IF_SIMPLELINK
578
579/*
580 * CC3100 SDK and STM32 SDK include headers w/out path, just like
581 * #include "simplelink.h". As result, we have to add all required directories
582 * into Makefile IPATH and do the same thing (include w/out path)
583 */
584
585#include <simplelink.h>
586#include <netapp.h>
587#undef timeval
588
589typedef int sock_t;
590#define INVALID_SOCKET (-1)
591
592#define to64(x) strtoll(x, NULL, 10)
593#define INT64_FMT PRId64
594#define INT64_X_FMT PRIx64
595#define SIZE_T_FMT "u"
596
597#define SOMAXCONN 8
598
599const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
600char *inet_ntoa(struct in_addr in);
601int inet_pton(int af, const char *src, void *dst);
602
603#endif /* CS_PLATFORM == CS_P_CC3100 */
604#endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ */
605#ifdef MG_MODULE_LINES
606#line 1 "common/platforms/platform_cc3200.h"
607#endif
608/*
609 * Copyright (c) 2014-2016 Cesanta Software Limited
610 * All rights reserved
611 */
612
613#ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
614#define CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
615#if CS_PLATFORM == CS_P_CC3200
616
617#include <assert.h>
618#include <ctype.h>
619#include <errno.h>
620#include <inttypes.h>
621#include <stdint.h>
622#include <string.h>
623#include <time.h>
624
625#ifndef __TI_COMPILER_VERSION__
626#include <fcntl.h>
627#include <sys/time.h>
628#endif
629
630#define MG_NET_IF MG_NET_IF_SIMPLELINK
631#define MG_SSL_IF MG_SSL_IF_SIMPLELINK
632
633/* Only SPIFFS supports directories, SLFS does not. */
634#if defined(CC3200_FS_SPIFFS) && !defined(MG_ENABLE_DIRECTORY_LISTING)
635#define MG_ENABLE_DIRECTORY_LISTING 1
636#endif
637
638/* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */
639
640typedef int sock_t;
641#define INVALID_SOCKET (-1)
642#define SIZE_T_FMT "u"
643typedef struct stat cs_stat_t;
644#define DIRSEP '/'
645#define to64(x) strtoll(x, NULL, 10)
646#define INT64_FMT PRId64
647#define INT64_X_FMT PRIx64
648#define __cdecl
649
650#define fileno(x) -1
651
652/* Some functions we implement for Mongoose. */
653
654#ifdef __cplusplus
655extern "C" {
656#endif
657
658#ifdef __TI_COMPILER_VERSION__
659struct SlTimeval_t;
660#define timeval SlTimeval_t
661int gettimeofday(struct timeval *t, void *tz);
662
663int asprintf(char **strp, const char *fmt, ...);
664
665#endif
666
667/* TI's libc does not have stat & friends, add them. */
668#ifdef __TI_COMPILER_VERSION__
669
670#include <file.h>
671
672typedef unsigned int mode_t;
673typedef size_t _off_t;
674typedef long ssize_t;
675
676struct stat {
677 int st_ino;
678 mode_t st_mode;
679 int st_nlink;
680 time_t st_mtime;
681 off_t st_size;
682};
683
684int _stat(const char *pathname, struct stat *st);
685#define stat(a, b) _stat(a, b)
686
687#define __S_IFMT 0170000
688
689#define __S_IFDIR 0040000
690#define __S_IFCHR 0020000
691#define __S_IFREG 0100000
692
693#define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask))
694
695#define S_IFDIR __S_IFDIR
696#define S_IFCHR __S_IFCHR
697#define S_IFREG __S_IFREG
698#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
699#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
700
701/* As of 5.2.7, TI compiler does not support va_copy() yet. */
702#define va_copy(apc, ap) ((apc) = (ap))
703
704#endif /* __TI_COMPILER_VERSION__ */
705
706#ifdef CC3200_FS_SPIFFS
707#include <common/spiffs/spiffs.h>
708
709typedef struct {
710 spiffs_DIR dh;
711 struct spiffs_dirent de;
712} DIR;
713
714#define d_name name
715#define dirent spiffs_dirent
716
717DIR *opendir(const char *dir_name);
718int closedir(DIR *dir);
719struct dirent *readdir(DIR *dir);
720#endif /* CC3200_FS_SPIFFS */
721
722#ifdef CC3200_FS_SLFS
723#define MG_FS_SLFS
724#endif
725
726#if (defined(CC3200_FS_SPIFFS) || defined(CC3200_FS_SLFS)) && \
727 !defined(MG_ENABLE_FILESYSTEM)
728#define MG_ENABLE_FILESYSTEM 1
729#endif
730
731#ifndef CS_ENABLE_STDIO
732#define CS_ENABLE_STDIO 1
733#endif
734
735#ifdef __cplusplus
736}
737#endif
738
739#endif /* CS_PLATFORM == CS_P_CC3200 */
740#endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ */
741#ifdef MG_MODULE_LINES
742#line 1 "common/platforms/platform_msp432.h"
743#endif
744/*
745 * Copyright (c) 2014-2016 Cesanta Software Limited
746 * All rights reserved
747 */
748
749#ifndef CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_
750#define CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_
751#if CS_PLATFORM == CS_P_MSP432
752
753#include <assert.h>
754#include <ctype.h>
755#include <errno.h>
756#include <inttypes.h>
757#include <stdint.h>
758#include <string.h>
759#include <time.h>
760
761#ifndef __TI_COMPILER_VERSION__
762#include <fcntl.h>
763#include <sys/time.h>
764#endif
765
766#define MG_NET_IF MG_NET_IF_SIMPLELINK
767#define MG_SSL_IF MG_SSL_IF_SIMPLELINK
768
769/* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */
770
771typedef int sock_t;
772#define INVALID_SOCKET (-1)
773#define SIZE_T_FMT "u"
774typedef struct stat cs_stat_t;
775#define DIRSEP '/'
776#define to64(x) strtoll(x, NULL, 10)
777#define INT64_FMT PRId64
778#define INT64_X_FMT PRIx64
779#define __cdecl
780
781#define fileno(x) -1
782
783/* Some functions we implement for Mongoose. */
784
785#ifdef __cplusplus
786extern "C" {
787#endif
788
789#ifdef __TI_COMPILER_VERSION__
790struct SlTimeval_t;
791#define timeval SlTimeval_t
792int gettimeofday(struct timeval *t, void *tz);
793#endif
794
795/* TI's libc does not have stat & friends, add them. */
796#ifdef __TI_COMPILER_VERSION__
797
798#include <file.h>
799
800typedef unsigned int mode_t;
801typedef size_t _off_t;
802typedef long ssize_t;
803
804struct stat {
805 int st_ino;
806 mode_t st_mode;
807 int st_nlink;
808 time_t st_mtime;
809 off_t st_size;
810};
811
812int _stat(const char *pathname, struct stat *st);
813#define stat(a, b) _stat(a, b)
814
815#define __S_IFMT 0170000
816
817#define __S_IFDIR 0040000
818#define __S_IFCHR 0020000
819#define __S_IFREG 0100000
820
821#define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask))
822
823#define S_IFDIR __S_IFDIR
824#define S_IFCHR __S_IFCHR
825#define S_IFREG __S_IFREG
826#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
827#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
828
829/* As of 5.2.7, TI compiler does not support va_copy() yet. */
830#define va_copy(apc, ap) ((apc) = (ap))
831
832#endif /* __TI_COMPILER_VERSION__ */
833
834#ifndef CS_ENABLE_STDIO
835#define CS_ENABLE_STDIO 1
836#endif
837
838#if (defined(CC3200_FS_SPIFFS) || defined(CC3200_FS_SLFS)) && !defined(MG_ENABLE_FILESYSTEM)
839#define MG_ENABLE_FILESYSTEM 1
840#endif
841
842#ifdef __cplusplus
843}
844#endif
845
846#endif /* CS_PLATFORM == CS_P_MSP432 */
847#endif /* CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_ */
848#ifdef MG_MODULE_LINES
849#line 1 "common/platforms/platform_tm4c129.h"
850#endif
851/*
852 * Copyright (c) 2014-2016 Cesanta Software Limited
853 * All rights reserved
854 */
855
856#ifndef CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_
857#define CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_
858#if CS_PLATFORM == CS_P_TM4C129
859
860#include <assert.h>
861#include <ctype.h>
862#include <errno.h>
863#include <inttypes.h>
864#include <stdint.h>
865#include <string.h>
866#include <time.h>
867
868#ifndef __TI_COMPILER_VERSION__
869#include <fcntl.h>
870#include <sys/time.h>
871#endif
872
873#define SIZE_T_FMT "u"
874typedef struct stat cs_stat_t;
875#define DIRSEP '/'
876#define to64(x) strtoll(x, NULL, 10)
877#define INT64_FMT PRId64
878#define INT64_X_FMT PRIx64
879#define __cdecl
880
881#ifndef MG_NET_IF
882# include <lwip/opt.h>
883# if LWIP_SOCKET
884# define MG_NET_IF MG_NET_IF_SOCKET
885# else
886# define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
887# endif
888# define MG_LWIP 1
889#elif MG_NET_IF == MG_NET_IF_SIMPLELINK
890# include "common/platforms/simplelink/cs_simplelink.h"
891#endif
892
893#ifndef CS_ENABLE_STDIO
894#define CS_ENABLE_STDIO 1
895#endif
896
897#ifdef __TI_COMPILER_VERSION__
898/* As of 5.2.8, TI compiler does not support va_copy() yet. */
899#define va_copy(apc, ap) ((apc) = (ap))
900#endif /* __TI_COMPILER_VERSION__ */
901
902#ifdef __cplusplus
903}
904#endif
905
906#endif /* CS_PLATFORM == CS_P_TM4C129 */
907#endif /* CS_COMMON_PLATFORMS_PLATFORM_TM4C129_H_ */
908#ifdef MG_MODULE_LINES
909#line 1 "common/platforms/platform_mbed.h"
910#endif
911/*
912 * Copyright (c) 2014-2016 Cesanta Software Limited
913 * All rights reserved
914 */
915
916#ifndef CS_COMMON_PLATFORMS_PLATFORM_MBED_H_
917#define CS_COMMON_PLATFORMS_PLATFORM_MBED_H_
918#if CS_PLATFORM == CS_P_MBED
919
920/*
921 * mbed.h contains C++ code (e.g. templates), thus, it should be processed
922 * only if included directly to startup file (ex: main.cpp)
923 */
924#ifdef __cplusplus
925/* Amalgamated: #include "mbed.h" */
926#endif /* __cplusplus */
927
928#include <assert.h>
929#include <ctype.h>
930#include <errno.h>
931#include <inttypes.h>
932#include <stdint.h>
933#include <string.h>
934#include <time.h>
935#include <sys/stat.h>
936#include <sys/types.h>
937#include <fcntl.h>
938#include <stdio.h>
939
940typedef struct stat cs_stat_t;
941#define DIRSEP '/'
942
943#ifndef CS_ENABLE_STDIO
944#define CS_ENABLE_STDIO 1
945#endif
946
947/*
948 * mbed can be compiled with the ARM compiler which
949 * just doesn't come with a gettimeofday shim
950 * because it's a BSD API and ARM targets embedded
951 * non-unix platforms.
952 */
953#if defined(__ARMCC_VERSION) || defined(__ICCARM__)
954#define _TIMEVAL_DEFINED
955#define gettimeofday _gettimeofday
956
957/* copied from GCC on ARM; for some reason useconds are signed */
958typedef long suseconds_t; /* microseconds (signed) */
959struct timeval {
960 time_t tv_sec; /* seconds */
961 suseconds_t tv_usec; /* and microseconds */
962};
963
964#endif
965
966#if MG_NET_IF == MG_NET_IF_SIMPLELINK
967
968#define MG_SIMPLELINK_NO_OSI 1
969
970#include <simplelink.h>
971
972typedef int sock_t;
973#define INVALID_SOCKET (-1)
974
975#define to64(x) strtoll(x, NULL, 10)
976#define INT64_FMT PRId64
977#define INT64_X_FMT PRIx64
978#define SIZE_T_FMT "u"
979
980#define SOMAXCONN 8
981
982const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
983char *inet_ntoa(struct in_addr in);
984int inet_pton(int af, const char *src, void *dst);
985int inet_aton(const char *cp, struct in_addr *inp);
986in_addr_t inet_addr(const char *cp);
987
988#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK */
989
990#endif /* CS_PLATFORM == CS_P_MBED */
991#endif /* CS_COMMON_PLATFORMS_PLATFORM_MBED_H_ */
992#ifdef MG_MODULE_LINES
993#line 1 "common/platforms/platform_nrf51.h"
994#endif
995/*
996 * Copyright (c) 2014-2016 Cesanta Software Limited
997 * All rights reserved
998 */
999#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_
1000#define CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_
1001#if CS_PLATFORM == CS_P_NRF51
1002
1003#include <assert.h>
1004#include <ctype.h>
1005#include <inttypes.h>
1006#include <stdint.h>
1007#include <string.h>
1008#include <time.h>
1009
1010#define to64(x) strtoll(x, NULL, 10)
1011
1012#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
1013#define MG_LWIP 1
1014#define MG_ENABLE_IPV6 1
1015
1016/*
1017 * For ARM C Compiler, make lwip to export `struct timeval`; for other
1018 * compilers, suppress it.
1019 */
1020#if !defined(__ARMCC_VERSION)
1021# define LWIP_TIMEVAL_PRIVATE 0
1022#else
1023struct timeval;
1024int gettimeofday(struct timeval *tp, void *tzp);
1025#endif
1026
1027#define INT64_FMT PRId64
1028#define SIZE_T_FMT "u"
1029
1030/*
1031 * ARM C Compiler doesn't have strdup, so we provide it
1032 */
1033#define CS_ENABLE_STRDUP defined(__ARMCC_VERSION)
1034
1035#endif /* CS_PLATFORM == CS_P_NRF51 */
1036#endif /* CS_COMMON_PLATFORMS_PLATFORM_NRF51_H_ */
1037#ifdef MG_MODULE_LINES
1038#line 1 "common/platforms/platform_nrf52.h"
1039#endif
1040/*
1041 * Copyright (c) 2014-2016 Cesanta Software Limited
1042 * All rights reserved
1043 */
1044#ifndef CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_
1045#define CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_
1046#if CS_PLATFORM == CS_P_NRF52
1047
1048#include <assert.h>
1049#include <ctype.h>
1050#include <errno.h>
1051#include <inttypes.h>
1052#include <stdint.h>
1053#include <string.h>
1054#include <time.h>
1055
1056#define to64(x) strtoll(x, NULL, 10)
1057
1058#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
1059#define MG_LWIP 1
1060#define MG_ENABLE_IPV6 1
1061
1062#if !defined(ENOSPC)
1063# define ENOSPC 28 /* No space left on device */
1064#endif
1065
1066/*
1067 * For ARM C Compiler, make lwip to export `struct timeval`; for other
1068 * compilers, suppress it.
1069 */
1070#if !defined(__ARMCC_VERSION)
1071# define LWIP_TIMEVAL_PRIVATE 0
1072#endif
1073
1074#define INT64_FMT PRId64
1075#define SIZE_T_FMT "u"
1076
1077/*
1078 * ARM C Compiler doesn't have strdup, so we provide it
1079 */
1080#define CS_ENABLE_STRDUP defined(__ARMCC_VERSION)
1081
1082#endif /* CS_PLATFORM == CS_P_NRF52 */
1083#endif /* CS_COMMON_PLATFORMS_PLATFORM_NRF52_H_ */
1084#ifdef MG_MODULE_LINES
1085#line 1 "common/platforms/simplelink/cs_simplelink.h"
1086#endif
1087/*
1088 * Copyright (c) 2014-2016 Cesanta Software Limited
1089 * All rights reserved
1090 */
1091
1092#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
1093#define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
1094
1095/* If simplelink.h is already included, all bets are off. */
1096#if defined(MG_NET_IF) && MG_NET_IF == MG_NET_IF_SIMPLELINK && \
1097 !defined(__SIMPLELINK_H__)
1098
1099#include <stdbool.h>
1100
1101#ifndef __TI_COMPILER_VERSION__
1102#undef __CONCAT
1103#undef FD_CLR
1104#undef FD_ISSET
1105#undef FD_SET
1106#undef FD_SETSIZE
1107#undef FD_ZERO
1108#undef fd_set
1109#endif
1110
1111/* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves
1112 * and undef it. */
1113#define PROVISIONING_API_H_
1114#include <simplelink/user.h>
1115#undef PROVISIONING_API_H_
1116#undef SL_INC_STD_BSD_API_NAMING
1117
1118#include <simplelink/include/simplelink.h>
1119#include <simplelink/include/netapp.h>
1120
1121/* Now define only the subset of the BSD API that we use.
1122 * Notably, close(), read() and write() are not defined. */
1123#define AF_INET SL_AF_INET
1124
1125#define socklen_t SlSocklen_t
1126#define sockaddr SlSockAddr_t
1127#define sockaddr_in SlSockAddrIn_t
1128#define in_addr SlInAddr_t
1129
1130#define SOCK_STREAM SL_SOCK_STREAM
1131#define SOCK_DGRAM SL_SOCK_DGRAM
1132
1133#define htonl sl_Htonl
1134#define ntohl sl_Ntohl
1135#define htons sl_Htons
1136#define ntohs sl_Ntohs
1137
1138#ifndef EACCES
1139#define EACCES SL_EACCES
1140#endif
1141#ifndef EAFNOSUPPORT
1142#define EAFNOSUPPORT SL_EAFNOSUPPORT
1143#endif
1144#ifndef EAGAIN
1145#define EAGAIN SL_EAGAIN
1146#endif
1147#ifndef EBADF
1148#define EBADF SL_EBADF
1149#endif
1150#ifndef EINVAL
1151#define EINVAL SL_EINVAL
1152#endif
1153#ifndef ENOMEM
1154#define ENOMEM SL_ENOMEM
1155#endif
1156#ifndef EWOULDBLOCK
1157#define EWOULDBLOCK SL_EWOULDBLOCK
1158#endif
1159
1160#define SOMAXCONN 8
1161
1162#ifdef __cplusplus
1163extern "C" {
1164#endif
1165
1166const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
1167char *inet_ntoa(struct in_addr in);
1168int inet_pton(int af, const char *src, void *dst);
1169
1170struct mg_mgr;
1171struct mg_connection;
1172
1173typedef void (*mg_init_cb)(struct mg_mgr *mgr);
1174bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init);
1175
1176void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg);
1177
1178int sl_fs_init(void);
1179
1180void sl_restart_cb(struct mg_mgr *mgr);
1181
1182int sl_set_ssl_opts(struct mg_connection *nc);
1183
1184#ifdef __cplusplus
1185}
1186#endif
1187
1188#endif /* MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(__SIMPLELINK_H__) */
1189
1190#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */
1191#ifdef MG_MODULE_LINES
1192#line 1 "common/platforms/platform_wince.h"
1193#endif
1194#ifndef CS_COMMON_PLATFORMS_PLATFORM_WINCE_H_
1195#define CS_COMMON_PLATFORMS_PLATFORM_WINCE_H_
1196
1197#if CS_PLATFORM == CS_P_WINCE
1198
1199/*
1200 * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
1201 * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
1202 * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
1203 * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
1204 * MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
1205 * MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
1206 * MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
1207 * MSVC++ 7.0 _MSC_VER == 1300
1208 * MSVC++ 6.0 _MSC_VER == 1200
1209 * MSVC++ 5.0 _MSC_VER == 1100
1210 */
1211#pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */
1212#pragma warning(disable : 4204) /* missing c99 support */
1213
1214#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
1215#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
1216#endif
1217
1218#ifndef _CRT_SECURE_NO_WARNINGS
1219#define _CRT_SECURE_NO_WARNINGS
1220#endif
1221
1222#include <assert.h>
1223#include <limits.h>
1224#include <stddef.h>
1225#include <stdio.h>
1226#include <stdlib.h>
1227#include <time.h>
1228
1229#pragma comment(lib, "ws2.lib") /* Linking with WinCE winsock library */
1230
1231#include <winsock2.h>
1232#include <ws2tcpip.h>
1233#include <windows.h>
1234
1235#define strdup _strdup
1236
1237#ifndef EINPROGRESS
1238#define EINPROGRESS WSAEINPROGRESS
1239#endif
1240
1241#ifndef EWOULDBLOCK
1242#define EWOULDBLOCK WSAEWOULDBLOCK
1243#endif
1244
1245#ifndef __func__
1246#define STRX(x) #x
1247#define STR(x) STRX(x)
1248#define __func__ __FILE__ ":" STR(__LINE__)
1249#endif
1250
1251#define snprintf _snprintf
1252#define fileno _fileno
1253#define vsnprintf _vsnprintf
1254#define sleep(x) Sleep((x) *1000)
1255#define to64(x) _atoi64(x)
1256#define rmdir _rmdir
1257
1258#if defined(_MSC_VER) && _MSC_VER >= 1400
1259#define fseeko(x, y, z) _fseeki64((x), (y), (z))
1260#else
1261#define fseeko(x, y, z) fseek((x), (y), (z))
1262#endif
1263
1264typedef int socklen_t;
1265
1266#if _MSC_VER >= 1700
1267#include <stdint.h>
1268#else
1269typedef signed char int8_t;
1270typedef unsigned char uint8_t;
1271typedef int int32_t;
1272typedef unsigned int uint32_t;
1273typedef short int16_t;
1274typedef unsigned short uint16_t;
1275typedef __int64 int64_t;
1276typedef unsigned __int64 uint64_t;
1277#endif
1278
1279typedef SOCKET sock_t;
1280typedef uint32_t in_addr_t;
1281
1282#ifndef UINT16_MAX
1283#define UINT16_MAX 65535
1284#endif
1285
1286#ifndef UINT32_MAX
1287#define UINT32_MAX 4294967295
1288#endif
1289
1290#ifndef pid_t
1291#define pid_t HANDLE
1292#endif
1293
1294#define INT64_FMT "I64d"
1295#define INT64_X_FMT "I64x"
1296/* TODO(alashkin): check if this is correct */
1297#define SIZE_T_FMT "u"
1298
1299#define DIRSEP '\\'
1300
1301#ifndef va_copy
1302#ifdef __va_copy
1303#define va_copy __va_copy
1304#else
1305#define va_copy(x, y) (x) = (y)
1306#endif
1307#endif
1308
1309#ifndef MG_MAX_HTTP_REQUEST_SIZE
1310#define MG_MAX_HTTP_REQUEST_SIZE 8192
1311#endif
1312
1313#ifndef MG_MAX_HTTP_SEND_MBUF
1314#define MG_MAX_HTTP_SEND_MBUF 4096
1315#endif
1316
1317#ifndef MG_MAX_HTTP_HEADERS
1318#define MG_MAX_HTTP_HEADERS 40
1319#endif
1320
1321#ifndef CS_ENABLE_STDIO
1322#define CS_ENABLE_STDIO 1
1323#endif
1324
1325#define abort() DebugBreak();
1326
1327#ifndef BUFSIZ
1328#define BUFSIZ 4096
1329#endif
1330/*
1331 * Explicitly disabling MG_ENABLE_THREADS for WinCE
1332 * because they are enabled for _WIN32 by default
1333 */
1334#ifndef MG_ENABLE_THREADS
1335#define MG_ENABLE_THREADS 0
1336#endif
1337
1338#ifndef MG_ENABLE_FILESYSTEM
1339#define MG_ENABLE_FILESYSTEM 1
1340#endif
1341
1342#ifndef MG_NET_IF
1343#define MG_NET_IF MG_NET_IF_SOCKET
1344#endif
1345
1346typedef struct _stati64 {
1347 uint32_t st_mtime;
1348 uint32_t st_size;
1349 uint32_t st_mode;
1350} cs_stat_t;
1351
1352/*
1353 * WinCE 6.0 has a lot of useful definitions in ATL (not windows.h) headers
1354 * use #ifdefs to avoid conflicts
1355 */
1356
1357#ifndef ENOENT
1358#define ENOENT ERROR_PATH_NOT_FOUND
1359#endif
1360
1361#ifndef EACCES
1362#define EACCES ERROR_ACCESS_DENIED
1363#endif
1364
1365#ifndef ENOMEM
1366#define ENOMEM ERROR_NOT_ENOUGH_MEMORY
1367#endif
1368
1369#ifndef _UINTPTR_T_DEFINED
1370typedef unsigned int* uintptr_t;
1371#endif
1372
1373#define _S_IFREG 2
1374#define _S_IFDIR 4
1375
1376#ifndef S_ISDIR
1377#define S_ISDIR(x) (((x) & _S_IFDIR) != 0)
1378#endif
1379
1380#ifndef S_ISREG
1381#define S_ISREG(x) (((x) & _S_IFREG) != 0)
1382#endif
1383
1384int open(const char *filename, int oflag, int pmode);
1385int _wstati64(const wchar_t *path, cs_stat_t *st);
1386const char *strerror();
1387
1388#endif /* CS_PLATFORM == CS_P_WINCE */
1389#endif /* CS_COMMON_PLATFORMS_PLATFORM_WINCE_H_ */
1390#ifdef MG_MODULE_LINES
1391#line 1 "common/platforms/platform_nxp_lpc.h"
1392#endif
1393/*
1394 * Copyright (c) 2014-2016 Cesanta Software Limited
1395 * All rights reserved
1396 */
1397
1398#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_
1399#define CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_
1400
1401#if CS_PLATFORM == CS_P_NXP_LPC
1402
1403#include <ctype.h>
1404#include <stdint.h>
1405#include <string.h>
1406
1407#define SIZE_T_FMT "u"
1408typedef struct stat cs_stat_t;
1409#define INT64_FMT "lld"
1410#define INT64_X_FMT "llx"
1411#define __cdecl
1412
1413#define MG_LWIP 1
1414
1415#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
1416
1417/*
1418 * LPCXpress comes with 3 C library implementations: Newlib, NewlibNano and Redlib.
1419 * See https://community.nxp.com/message/630860 for more details.
1420 *
1421 * Redlib is the default and lacks certain things, so we provide them.
1422 */
1423#ifdef __REDLIB_INTERFACE_VERSION__
1424
1425/* Let LWIP define timeval for us. */
1426#define LWIP_TIMEVAL_PRIVATE 1
1427
1428#define va_copy(d, s) __builtin_va_copy(d, s)
1429
1430#define CS_ENABLE_TO64 1
1431#define to64(x) cs_to64(x)
1432
1433#define CS_ENABLE_STRDUP 1
1434
1435#else
1436
1437#include <sys/time.h>
1438#define LWIP_TIMEVAL_PRIVATE 0
1439#define to64(x) strtoll(x, NULL, 10)
1440
1441#endif
1442
1443#endif /* CS_PLATFORM == CS_P_NXP_LPC */
1444#endif /* CS_COMMON_PLATFORMS_PLATFORM_NXP_LPC_H_ */
1445#ifdef MG_MODULE_LINES
1446#line 1 "common/platforms/platform_nxp_kinetis.h"
1447#endif
1448/*
1449 * Copyright (c) 2014-2016 Cesanta Software Limited
1450 * All rights reserved
1451 */
1452
1453#ifndef CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_
1454#define CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_
1455
1456#if CS_PLATFORM == CS_P_NXP_KINETIS
1457
1458#include <ctype.h>
1459#include <inttypes.h>
1460#include <string.h>
1461#include <sys/time.h>
1462
1463#define SIZE_T_FMT "u"
1464typedef struct stat cs_stat_t;
1465#define to64(x) strtoll(x, NULL, 10)
1466#define INT64_FMT "lld"
1467#define INT64_X_FMT "llx"
1468#define __cdecl
1469
1470#define MG_LWIP 1
1471
1472#define MG_NET_IF MG_NET_IF_LWIP_LOW_LEVEL
1473
1474/* struct timeval is defined in sys/time.h. */
1475#define LWIP_TIMEVAL_PRIVATE 0
1476
1477#endif /* CS_PLATFORM == CS_P_NXP_KINETIS */
1478#endif /* CS_COMMON_PLATFORMS_PLATFORM_NXP_KINETIS_H_ */
1479#ifdef MG_MODULE_LINES
1480#line 1 "common/platforms/platform_pic32.h"
1481#endif
1482/*
1483 * Copyright (c) 2014-2016 Cesanta Software Limited
1484 * All rights reserved
1485 */
1486
1487#ifndef CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_
1488#define CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_
1489
1490#if CS_PLATFORM == CS_P_PIC32
1491
1492#define MG_NET_IF MG_NET_IF_PIC32
1493
1494#include <stdint.h>
1495#include <time.h>
1496#include <ctype.h>
1497#include <stdlib.h>
1498
1499#include <system_config.h>
1500#include <system_definitions.h>
1501
1502#include <sys/types.h>
1503
1504typedef TCP_SOCKET sock_t;
1505#define to64(x) strtoll(x, NULL, 10)
1506
1507#define SIZE_T_FMT "lu"
1508#define INT64_FMT "lld"
1509
1510#ifndef CS_ENABLE_STDIO
1511#define CS_ENABLE_STDIO 1
1512#endif
1513
1514char* inet_ntoa(struct in_addr in);
1515
1516#endif /* CS_PLATFORM == CS_P_PIC32 */
1517
1518#endif /* CS_COMMON_PLATFORMS_PLATFORM_PIC32_H_ */
1519#ifdef MG_MODULE_LINES
1520#line 1 "common/platforms/lwip/mg_lwip.h"
1521#endif
1522/*
1523 * Copyright (c) 2014-2016 Cesanta Software Limited
1524 * All rights reserved
1525 */
1526
1527#ifndef CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_
1528#define CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_
1529
1530#ifndef MG_LWIP
1531#define MG_LWIP 0
1532#endif
1533
1534#if MG_LWIP
1535
1536/*
1537 * When compiling for nRF5x chips with arm-none-eabi-gcc, it has BYTE_ORDER
1538 * already defined, so in order to avoid warnings in lwip, we have to undefine
1539 * it.
1540 *
1541 * TODO: Check if in the future versions of nRF5 SDK that changes.
1542 * Current version of nRF51 SDK: 0.8.0
1543 * nRF5 SDK: 0.9.0
1544 */
1545#if CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52
1546#undef BYTE_ORDER
1547#endif
1548
1549#include <lwip/opt.h>
1550#include <lwip/err.h>
1551#include <lwip/ip_addr.h>
1552#include <lwip/inet.h>
1553#include <lwip/netdb.h>
1554#include <lwip/dns.h>
1555
1556#ifndef LWIP_PROVIDE_ERRNO
1557#include <errno.h>
1558#endif
1559
1560#if LWIP_SOCKET
1561#include <lwip/sockets.h>
1562#else
1563/* We really need the definitions from sockets.h. */
1564#undef LWIP_SOCKET
1565#define LWIP_SOCKET 1
1566#include <lwip/sockets.h>
1567#undef LWIP_SOCKET
1568#define LWIP_SOCKET 0
1569#endif
1570
1571#define INVALID_SOCKET (-1)
1572#define SOMAXCONN 10
1573typedef int sock_t;
1574
1575#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
1576struct mg_mgr;
1577struct mg_connection;
1578uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr);
1579void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
1580 int interval, int count);
1581#endif
1582
1583#endif /* MG_LWIP */
1584
1585#endif /* CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ */
1586#ifdef MG_MODULE_LINES
1587#line 1 "common/cs_time.h"
1588#endif
1589/*
1590 * Copyright (c) 2014-2016 Cesanta Software Limited
1591 * All rights reserved
1592 */
1593
1594#ifndef CS_COMMON_CS_TIME_H_
1595#define CS_COMMON_CS_TIME_H_
1596
1597/* Amalgamated: #include "common/platform.h" */
1598
1599#ifdef __cplusplus
1600extern "C" {
1601#endif /* __cplusplus */
1602
1603/* Sub-second granularity time(). */
1604double cs_time(void);
1605
1606#ifdef __cplusplus
1607}
1608#endif /* __cplusplus */
1609
1610#endif /* CS_COMMON_CS_TIME_H_ */
1611#ifdef MG_MODULE_LINES
1612#line 1 "common/mg_str.h"
1613#endif
1614/*
1615 * Copyright (c) 2014-2016 Cesanta Software Limited
1616 * All rights reserved
1617 */
1618
1619#ifndef CS_COMMON_MG_STR_H_
1620#define CS_COMMON_MG_STR_H_
1621
1622#include <stddef.h>
1623
1624/* Amalgamated: #include "common/platform.h" */
1625
1626#ifdef __cplusplus
1627extern "C" {
1628#endif /* __cplusplus */
1629
1630/* Describes chunk of memory */
1631struct mg_str {
1632 const char *p; /* Memory chunk pointer */
1633 size_t len; /* Memory chunk length */
1634};
1635
1636/*
1637 * Helper functions for creating mg_str struct from plain C string.
1638 * `NULL` is allowed and becomes `{NULL, 0}`.
1639 */
1640struct mg_str mg_mk_str(const char *s);
1641struct mg_str mg_mk_str_n(const char *s, size_t len);
1642
1643/* Macro for initializing mg_str. */
1644#define MG_MK_STR(str_literal) \
1645 { str_literal, sizeof(str_literal) - 1 }
1646
1647/*
1648 * Cross-platform version of `strcmp()` where where first string is
1649 * specified by `struct mg_str`.
1650 */
1651int mg_vcmp(const struct mg_str *str2, const char *str1);
1652
1653/*
1654 * Cross-platform version of `strncasecmp()` where first string is
1655 * specified by `struct mg_str`.
1656 */
1657int mg_vcasecmp(const struct mg_str *str2, const char *str1);
1658
1659struct mg_str mg_strdup(const struct mg_str s);
1660int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
1661int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n);
1662
1663#ifdef __cplusplus
1664}
1665#endif /* __cplusplus */
1666
1667#endif /* CS_COMMON_MG_STR_H_ */
1668#ifdef MG_MODULE_LINES
1669#line 1 "common/mbuf.h"
1670#endif
1671/*
1672 * Copyright (c) 2015 Cesanta Software Limited
1673 * All rights reserved
1674 */
1675
1676/*
1677 * === Memory Buffers
1678 *
1679 * Mbufs are mutable/growing memory buffers, like C++ strings.
1680 * Mbuf can append data to the end of a buffer or insert data into arbitrary
1681 * position in the middle of a buffer. The buffer grows automatically when
1682 * needed.
1683 */
1684
1685#ifndef CS_COMMON_MBUF_H_
1686#define CS_COMMON_MBUF_H_
1687
1688#include <stdlib.h>
1689/* Amalgamated: #include "common/platform.h" */
1690
1691#if defined(__cplusplus)
1692extern "C" {
1693#endif
1694
1695#ifndef MBUF_SIZE_MULTIPLIER
1696#define MBUF_SIZE_MULTIPLIER 1.5
1697#endif
1698
1699/* Memory buffer descriptor */
1700struct mbuf {
1701 char *buf; /* Buffer pointer */
1702 size_t len; /* Data length. Data is located between offset 0 and len. */
1703 size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
1704};
1705
1706/*
1707 * Initialises an Mbuf.
1708 * `initial_capacity` specifies the initial capacity of the mbuf.
1709 */
1710void mbuf_init(struct mbuf *, size_t initial_capacity);
1711
1712/* Frees the space allocated for the mbuffer and resets the mbuf structure. */
1713void mbuf_free(struct mbuf *);
1714
1715/*
1716 * Appends data to the Mbuf.
1717 *
1718 * Returns the number of bytes appended or 0 if out of memory.
1719 */
1720size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
1721
1722/*
1723 * Inserts data at a specified offset in the Mbuf.
1724 *
1725 * Existing data will be shifted forwards and the buffer will
1726 * be grown if necessary.
1727 * Returns the number of bytes inserted.
1728 */
1729size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
1730
1731/* Removes `data_size` bytes from the beginning of the buffer. */
1732void mbuf_remove(struct mbuf *, size_t data_size);
1733
1734/*
1735 * Resizes an Mbuf.
1736 *
1737 * If `new_size` is smaller than buffer's `len`, the
1738 * resize is not performed.
1739 */
1740void mbuf_resize(struct mbuf *, size_t new_size);
1741
1742/* Shrinks an Mbuf by resizing its `size` to `len`. */
1743void mbuf_trim(struct mbuf *);
1744
1745#if defined(__cplusplus)
1746}
1747#endif /* __cplusplus */
1748
1749#endif /* CS_COMMON_MBUF_H_ */
1750#ifdef MG_MODULE_LINES
1751#line 1 "common/sha1.h"
1752#endif
1753/*
1754 * Copyright (c) 2014 Cesanta Software Limited
1755 * All rights reserved
1756 */
1757
1758#ifndef CS_COMMON_SHA1_H_
1759#define CS_COMMON_SHA1_H_
1760
1761#ifndef DISABLE_SHA1
1762#define DISABLE_SHA1 0
1763#endif
1764
1765#if !DISABLE_SHA1
1766
1767/* Amalgamated: #include "common/platform.h" */
1768
1769#ifdef __cplusplus
1770extern "C" {
1771#endif /* __cplusplus */
1772
1773typedef struct {
1774 uint32_t state[5];
1775 uint32_t count[2];
1776 unsigned char buffer[64];
1777} cs_sha1_ctx;
1778
1779void cs_sha1_init(cs_sha1_ctx *);
1780void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
1781void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
1782void cs_hmac_sha1(const unsigned char *key, size_t key_len,
1783 const unsigned char *text, size_t text_len,
1784 unsigned char out[20]);
1785#ifdef __cplusplus
1786}
1787#endif /* __cplusplus */
1788
1789#endif /* DISABLE_SHA1 */
1790
1791#endif /* CS_COMMON_SHA1_H_ */
1792#ifdef MG_MODULE_LINES
1793#line 1 "common/md5.h"
1794#endif
1795/*
1796 * Copyright (c) 2014 Cesanta Software Limited
1797 * All rights reserved
1798 */
1799
1800#ifndef CS_COMMON_MD5_H_
1801#define CS_COMMON_MD5_H_
1802
1803/* Amalgamated: #include "common/platform.h" */
1804
1805#ifndef DISABLE_MD5
1806#define DISABLE_MD5 0
1807#endif
1808
1809#ifdef __cplusplus
1810extern "C" {
1811#endif /* __cplusplus */
1812
1813typedef struct MD5Context {
1814 uint32_t buf[4];
1815 uint32_t bits[2];
1816 unsigned char in[64];
1817} MD5_CTX;
1818
1819void MD5_Init(MD5_CTX *c);
1820void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
1821void MD5_Final(unsigned char *md, MD5_CTX *c);
1822
1823/*
1824 * Return stringified MD5 hash for NULL terminated list of pointer/length pairs.
1825 * A length should be specified as size_t variable.
1826 * Example:
1827 *
1828 * char buf[33];
1829 * cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL);
1830 */
1831char *cs_md5(char buf[33], ...);
1832
1833#ifdef __cplusplus
1834}
1835#endif /* __cplusplus */
1836
1837#endif /* CS_COMMON_MD5_H_ */
1838#ifdef MG_MODULE_LINES
1839#line 1 "common/base64.h"
1840#endif
1841/*
1842 * Copyright (c) 2014 Cesanta Software Limited
1843 * All rights reserved
1844 */
1845
1846#ifndef CS_COMMON_BASE64_H_
1847#define CS_COMMON_BASE64_H_
1848
1849#ifndef DISABLE_BASE64
1850#define DISABLE_BASE64 0
1851#endif
1852
1853#if !DISABLE_BASE64
1854
1855#include <stdio.h>
1856
1857#ifdef __cplusplus
1858extern "C" {
1859#endif
1860
1861typedef void (*cs_base64_putc_t)(char, void *);
1862
1863struct cs_base64_ctx {
1864 /* cannot call it putc because it's a macro on some environments */
1865 cs_base64_putc_t b64_putc;
1866 unsigned char chunk[3];
1867 int chunk_size;
1868 void *user_data;
1869};
1870
1871void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc,
1872 void *user_data);
1873void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len);
1874void cs_base64_finish(struct cs_base64_ctx *ctx);
1875
1876void cs_base64_encode(const unsigned char *src, int src_len, char *dst);
1877void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len);
1878int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len);
1879
1880#ifdef __cplusplus
1881}
1882#endif
1883
1884#endif /* DISABLE_BASE64 */
1885
1886#endif /* CS_COMMON_BASE64_H_ */
1887#ifdef MG_MODULE_LINES
1888#line 1 "common/str_util.h"
1889#endif
1890/*
1891 * Copyright (c) 2015 Cesanta Software Limited
1892 * All rights reserved
1893 */
1894
1895#ifndef CS_COMMON_STR_UTIL_H_
1896#define CS_COMMON_STR_UTIL_H_
1897
1898#include <stdarg.h>
1899#include <stdlib.h>
1900
1901/* Amalgamated: #include "common/platform.h" */
1902
1903#ifndef CS_ENABLE_STRDUP
1904#define CS_ENABLE_STRDUP 0
1905#endif
1906
1907#ifndef CS_ENABLE_TO64
1908#define CS_ENABLE_TO64 0
1909#endif
1910
1911/*
1912 * Expands to a string representation of its argument: e.g.
1913 * `CS_STRINGIFY_LIT(5) expands to "5"`
1914 */
1915#define CS_STRINGIFY_LIT(x) #x
1916
1917/*
1918 * Expands to a string representation of its argument, which is allowed
1919 * to be a macro: e.g.
1920 *
1921 * #define FOO 123
1922 * CS_STRINGIFY_MACRO(FOO)
1923 *
1924 * expands to 123.
1925 */
1926#define CS_STRINGIFY_MACRO(x) CS_STRINGIFY_LIT(x)
1927
1928#ifdef __cplusplus
1929extern "C" {
1930#endif
1931
1932size_t c_strnlen(const char *s, size_t maxlen);
1933int c_snprintf(char *buf, size_t buf_size, const char *format, ...);
1934int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap);
1935/*
1936 * Find the first occurrence of find in s, where the search is limited to the
1937 * first slen characters of s.
1938 */
1939const char *c_strnstr(const char *s, const char *find, size_t slen);
1940
1941/*
1942 * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
1943 * because each byte of input takes 2 bytes in string representation
1944 * plus 1 byte for the terminating \0 character.
1945 */
1946void cs_to_hex(char *to, const unsigned char *p, size_t len);
1947
1948/*
1949 * Convert stringified binary data back to binary.
1950 * Does the reverse of `cs_to_hex()`.
1951 */
1952void cs_from_hex(char *to, const char *p, size_t len);
1953
1954#if CS_ENABLE_STRDUP
1955char *strdup(const char *src);
1956#endif
1957
1958#if CS_ENABLE_TO64
1959#include <stdint.h>
1960/*
1961 * Simple string -> int64 conversion routine.
1962 */
1963int64_t cs_to64(const char *s);
1964#endif
1965
1966/*
1967 * Cross-platform version of `strncasecmp()`.
1968 */
1969int mg_ncasecmp(const char *s1, const char *s2, size_t len);
1970
1971/*
1972 * Cross-platform version of `strcasecmp()`.
1973 */
1974int mg_casecmp(const char *s1, const char *s2);
1975
1976/*
1977 * Prints message to the buffer. If the buffer is large enough to hold the
1978 * message, it returns buffer. If buffer is to small, it allocates a large
1979 * enough buffer on heap and returns allocated buffer.
1980 * This is a supposed use case:
1981 *
1982 * char buf[5], *p = buf;
1983 * mg_avprintf(&p, sizeof(buf), "%s", "hi there");
1984 * use_p_somehow(p);
1985 * if (p != buf) {
1986 * free(p);
1987 * }
1988 *
1989 * The purpose of this is to avoid malloc-ing if generated strings are small.
1990 */
1991int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
1992
1993/* Same as mg_asprintf, but takes varargs list. */
1994int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
1995
1996#ifdef __cplusplus
1997}
1998#endif
1999
2000#endif /* CS_COMMON_STR_UTIL_H_ */
2001#ifdef MG_MODULE_LINES
2002#line 1 "common/queue.h"
2003#endif
2004/* clang-format off */
2005/*-
2006 * Copyright (c) 1991, 1993
2007 * The Regents of the University of California. All rights reserved.
2008 *
2009 * Redistribution and use in source and binary forms, with or without
2010 * modification, are permitted provided that the following conditions
2011 * are met:
2012 * 1. Redistributions of source code must retain the above copyright
2013 * notice, this list of conditions and the following disclaimer.
2014 * 2. Redistributions in binary form must reproduce the above copyright
2015 * notice, this list of conditions and the following disclaimer in the
2016 * documentation and/or other materials provided with the distribution.
2017 * 4. Neither the name of the University nor the names of its contributors
2018 * may be used to endorse or promote products derived from this software
2019 * without specific prior written permission.
2020 *
2021 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2022 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2023 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2024 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2025 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2026 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2027 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2028 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2029 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2030 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2031 * SUCH DAMAGE.
2032 *
2033 * @(#)queue.h 8.5 (Berkeley) 8/20/94
2034 * $FreeBSD$
2035 */
2036
2037#ifndef _SYS_QUEUE_H_
2038#define _SYS_QUEUE_H_
2039
2040/*
2041 * This file defines four types of data structures: singly-linked lists,
2042 * singly-linked tail queues, lists and tail queues.
2043 *
2044 * A singly-linked list is headed by a single forward pointer. The elements
2045 * are singly linked for minimum space and pointer manipulation overhead at
2046 * the expense of O(n) removal for arbitrary elements. New elements can be
2047 * added to the list after an existing element or at the head of the list.
2048 * Elements being removed from the head of the list should use the explicit
2049 * macro for this purpose for optimum efficiency. A singly-linked list may
2050 * only be traversed in the forward direction. Singly-linked lists are ideal
2051 * for applications with large datasets and few or no removals or for
2052 * implementing a LIFO queue.
2053 *
2054 * A singly-linked tail queue is headed by a pair of pointers, one to the
2055 * head of the list and the other to the tail of the list. The elements are
2056 * singly linked for minimum space and pointer manipulation overhead at the
2057 * expense of O(n) removal for arbitrary elements. New elements can be added
2058 * to the list after an existing element, at the head of the list, or at the
2059 * end of the list. Elements being removed from the head of the tail queue
2060 * should use the explicit macro for this purpose for optimum efficiency.
2061 * A singly-linked tail queue may only be traversed in the forward direction.
2062 * Singly-linked tail queues are ideal for applications with large datasets
2063 * and few or no removals or for implementing a FIFO queue.
2064 *
2065 * A list is headed by a single forward pointer (or an array of forward
2066 * pointers for a hash table header). The elements are doubly linked
2067 * so that an arbitrary element can be removed without a need to
2068 * traverse the list. New elements can be added to the list before
2069 * or after an existing element or at the head of the list. A list
2070 * may be traversed in either direction.
2071 *
2072 * A tail queue is headed by a pair of pointers, one to the head of the
2073 * list and the other to the tail of the list. The elements are doubly
2074 * linked so that an arbitrary element can be removed without a need to
2075 * traverse the list. New elements can be added to the list before or
2076 * after an existing element, at the head of the list, or at the end of
2077 * the list. A tail queue may be traversed in either direction.
2078 *
2079 * For details on the use of these macros, see the queue(3) manual page.
2080 *
2081 *
2082 * SLIST LIST STAILQ TAILQ
2083 * _HEAD + + + +
2084 * _CLASS_HEAD + + + +
2085 * _HEAD_INITIALIZER + + + +
2086 * _ENTRY + + + +
2087 * _CLASS_ENTRY + + + +
2088 * _INIT + + + +
2089 * _EMPTY + + + +
2090 * _FIRST + + + +
2091 * _NEXT + + + +
2092 * _PREV - + - +
2093 * _LAST - - + +
2094 * _FOREACH + + + +
2095 * _FOREACH_FROM + + + +
2096 * _FOREACH_SAFE + + + +
2097 * _FOREACH_FROM_SAFE + + + +
2098 * _FOREACH_REVERSE - - - +
2099 * _FOREACH_REVERSE_FROM - - - +
2100 * _FOREACH_REVERSE_SAFE - - - +
2101 * _FOREACH_REVERSE_FROM_SAFE - - - +
2102 * _INSERT_HEAD + + + +
2103 * _INSERT_BEFORE - + - +
2104 * _INSERT_AFTER + + + +
2105 * _INSERT_TAIL - - + +
2106 * _CONCAT - - + +
2107 * _REMOVE_AFTER + - + -
2108 * _REMOVE_HEAD + - + -
2109 * _REMOVE + + + +
2110 * _SWAP + + + +
2111 *
2112 */
2113#ifdef QUEUE_MACRO_DEBUG
2114/* Store the last 2 places the queue element or head was altered */
2115struct qm_trace {
2116 unsigned long lastline;
2117 unsigned long prevline;
2118 const char *lastfile;
2119 const char *prevfile;
2120};
2121
2122#define TRACEBUF struct qm_trace trace;
2123#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } ,
2124#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
2125#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
2126
2127#define QMD_TRACE_HEAD(head) do { \
2128 (head)->trace.prevline = (head)->trace.lastline; \
2129 (head)->trace.prevfile = (head)->trace.lastfile; \
2130 (head)->trace.lastline = __LINE__; \
2131 (head)->trace.lastfile = __FILE__; \
2132} while (0)
2133
2134#define QMD_TRACE_ELEM(elem) do { \
2135 (elem)->trace.prevline = (elem)->trace.lastline; \
2136 (elem)->trace.prevfile = (elem)->trace.lastfile; \
2137 (elem)->trace.lastline = __LINE__; \
2138 (elem)->trace.lastfile = __FILE__; \
2139} while (0)
2140
2141#else
2142#define QMD_TRACE_ELEM(elem)
2143#define QMD_TRACE_HEAD(head)
2144#define QMD_SAVELINK(name, link)
2145#define TRACEBUF
2146#define TRACEBUF_INITIALIZER
2147#define TRASHIT(x)
2148#endif /* QUEUE_MACRO_DEBUG */
2149
2150#ifdef __cplusplus
2151/*
2152 * In C++ there can be structure lists and class lists:
2153 */
2154#define QUEUE_TYPEOF(type) type
2155#else
2156#define QUEUE_TYPEOF(type) struct type
2157#endif
2158
2159/*
2160 * Singly-linked List declarations.
2161 */
2162#define SLIST_HEAD(name, type) \
2163struct name { \
2164 struct type *slh_first; /* first element */ \
2165}
2166
2167#define SLIST_CLASS_HEAD(name, type) \
2168struct name { \
2169 class type *slh_first; /* first element */ \
2170}
2171
2172#define SLIST_HEAD_INITIALIZER(head) \
2173 { NULL }
2174
2175#define SLIST_ENTRY(type) \
2176struct { \
2177 struct type *sle_next; /* next element */ \
2178}
2179
2180#define SLIST_CLASS_ENTRY(type) \
2181struct { \
2182 class type *sle_next; /* next element */ \
2183}
2184
2185/*
2186 * Singly-linked List functions.
2187 */
2188#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
2189
2190#define SLIST_FIRST(head) ((head)->slh_first)
2191
2192#define SLIST_FOREACH(var, head, field) \
2193 for ((var) = SLIST_FIRST((head)); \
2194 (var); \
2195 (var) = SLIST_NEXT((var), field))
2196
2197#define SLIST_FOREACH_FROM(var, head, field) \
2198 for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
2199 (var); \
2200 (var) = SLIST_NEXT((var), field))
2201
2202#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
2203 for ((var) = SLIST_FIRST((head)); \
2204 (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
2205 (var) = (tvar))
2206
2207#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
2208 for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
2209 (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
2210 (var) = (tvar))
2211
2212#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
2213 for ((varp) = &SLIST_FIRST((head)); \
2214 ((var) = *(varp)) != NULL; \
2215 (varp) = &SLIST_NEXT((var), field))
2216
2217#define SLIST_INIT(head) do { \
2218 SLIST_FIRST((head)) = NULL; \
2219} while (0)
2220
2221#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
2222 SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
2223 SLIST_NEXT((slistelm), field) = (elm); \
2224} while (0)
2225
2226#define SLIST_INSERT_HEAD(head, elm, field) do { \
2227 SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
2228 SLIST_FIRST((head)) = (elm); \
2229} while (0)
2230
2231#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
2232
2233#define SLIST_REMOVE(head, elm, type, field) do { \
2234 QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
2235 if (SLIST_FIRST((head)) == (elm)) { \
2236 SLIST_REMOVE_HEAD((head), field); \
2237 } \
2238 else { \
2239 QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \
2240 while (SLIST_NEXT(curelm, field) != (elm)) \
2241 curelm = SLIST_NEXT(curelm, field); \
2242 SLIST_REMOVE_AFTER(curelm, field); \
2243 } \
2244 TRASHIT(*oldnext); \
2245} while (0)
2246
2247#define SLIST_REMOVE_AFTER(elm, field) do { \
2248 SLIST_NEXT(elm, field) = \
2249 SLIST_NEXT(SLIST_NEXT(elm, field), field); \
2250} while (0)
2251
2252#define SLIST_REMOVE_HEAD(head, field) do { \
2253 SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
2254} while (0)
2255
2256#define SLIST_SWAP(head1, head2, type) do { \
2257 QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \
2258 SLIST_FIRST(head1) = SLIST_FIRST(head2); \
2259 SLIST_FIRST(head2) = swap_first; \
2260} while (0)
2261
2262/*
2263 * Singly-linked Tail queue declarations.
2264 */
2265#define STAILQ_HEAD(name, type) \
2266struct name { \
2267 struct type *stqh_first;/* first element */ \
2268 struct type **stqh_last;/* addr of last next element */ \
2269}
2270
2271#define STAILQ_CLASS_HEAD(name, type) \
2272struct name { \
2273 class type *stqh_first; /* first element */ \
2274 class type **stqh_last; /* addr of last next element */ \
2275}
2276
2277#define STAILQ_HEAD_INITIALIZER(head) \
2278 { NULL, &(head).stqh_first }
2279
2280#define STAILQ_ENTRY(type) \
2281struct { \
2282 struct type *stqe_next; /* next element */ \
2283}
2284
2285#define STAILQ_CLASS_ENTRY(type) \
2286struct { \
2287 class type *stqe_next; /* next element */ \
2288}
2289
2290/*
2291 * Singly-linked Tail queue functions.
2292 */
2293#define STAILQ_CONCAT(head1, head2) do { \
2294 if (!STAILQ_EMPTY((head2))) { \
2295 *(head1)->stqh_last = (head2)->stqh_first; \
2296 (head1)->stqh_last = (head2)->stqh_last; \
2297 STAILQ_INIT((head2)); \
2298 } \
2299} while (0)
2300
2301#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
2302
2303#define STAILQ_FIRST(head) ((head)->stqh_first)
2304
2305#define STAILQ_FOREACH(var, head, field) \
2306 for((var) = STAILQ_FIRST((head)); \
2307 (var); \
2308 (var) = STAILQ_NEXT((var), field))
2309
2310#define STAILQ_FOREACH_FROM(var, head, field) \
2311 for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
2312 (var); \
2313 (var) = STAILQ_NEXT((var), field))
2314
2315#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
2316 for ((var) = STAILQ_FIRST((head)); \
2317 (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
2318 (var) = (tvar))
2319
2320#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
2321 for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
2322 (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
2323 (var) = (tvar))
2324
2325#define STAILQ_INIT(head) do { \
2326 STAILQ_FIRST((head)) = NULL; \
2327 (head)->stqh_last = &STAILQ_FIRST((head)); \
2328} while (0)
2329
2330#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
2331 if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
2332 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
2333 STAILQ_NEXT((tqelm), field) = (elm); \
2334} while (0)
2335
2336#define STAILQ_INSERT_HEAD(head, elm, field) do { \
2337 if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
2338 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
2339 STAILQ_FIRST((head)) = (elm); \
2340} while (0)
2341
2342#define STAILQ_INSERT_TAIL(head, elm, field) do { \
2343 STAILQ_NEXT((elm), field) = NULL; \
2344 *(head)->stqh_last = (elm); \
2345 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
2346} while (0)
2347
2348#define STAILQ_LAST(head, type, field) \
2349 (STAILQ_EMPTY((head)) ? NULL : \
2350 __containerof((head)->stqh_last, \
2351 QUEUE_TYPEOF(type), field.stqe_next))
2352
2353#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
2354
2355#define STAILQ_REMOVE(head, elm, type, field) do { \
2356 QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
2357 if (STAILQ_FIRST((head)) == (elm)) { \
2358 STAILQ_REMOVE_HEAD((head), field); \
2359 } \
2360 else { \
2361 QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \
2362 while (STAILQ_NEXT(curelm, field) != (elm)) \
2363 curelm = STAILQ_NEXT(curelm, field); \
2364 STAILQ_REMOVE_AFTER(head, curelm, field); \
2365 } \
2366 TRASHIT(*oldnext); \
2367} while (0)
2368
2369#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
2370 if ((STAILQ_NEXT(elm, field) = \
2371 STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
2372 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
2373} while (0)
2374
2375#define STAILQ_REMOVE_HEAD(head, field) do { \
2376 if ((STAILQ_FIRST((head)) = \
2377 STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
2378 (head)->stqh_last = &STAILQ_FIRST((head)); \
2379} while (0)
2380
2381#define STAILQ_SWAP(head1, head2, type) do { \
2382 QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \
2383 QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \
2384 STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
2385 (head1)->stqh_last = (head2)->stqh_last; \
2386 STAILQ_FIRST(head2) = swap_first; \
2387 (head2)->stqh_last = swap_last; \
2388 if (STAILQ_EMPTY(head1)) \
2389 (head1)->stqh_last = &STAILQ_FIRST(head1); \
2390 if (STAILQ_EMPTY(head2)) \
2391 (head2)->stqh_last = &STAILQ_FIRST(head2); \
2392} while (0)
2393
2394
2395/*
2396 * List declarations.
2397 */
2398#define LIST_HEAD(name, type) \
2399struct name { \
2400 struct type *lh_first; /* first element */ \
2401}
2402
2403#define LIST_CLASS_HEAD(name, type) \
2404struct name { \
2405 class type *lh_first; /* first element */ \
2406}
2407
2408#define LIST_HEAD_INITIALIZER(head) \
2409 { NULL }
2410
2411#define LIST_ENTRY(type) \
2412struct { \
2413 struct type *le_next; /* next element */ \
2414 struct type **le_prev; /* address of previous next element */ \
2415}
2416
2417#define LIST_CLASS_ENTRY(type) \
2418struct { \
2419 class type *le_next; /* next element */ \
2420 class type **le_prev; /* address of previous next element */ \
2421}
2422
2423/*
2424 * List functions.
2425 */
2426
2427#if (defined(_KERNEL) && defined(INVARIANTS))
2428#define QMD_LIST_CHECK_HEAD(head, field) do { \
2429 if (LIST_FIRST((head)) != NULL && \
2430 LIST_FIRST((head))->field.le_prev != \
2431 &LIST_FIRST((head))) \
2432 panic("Bad list head %p first->prev != head", (head)); \
2433} while (0)
2434
2435#define QMD_LIST_CHECK_NEXT(elm, field) do { \
2436 if (LIST_NEXT((elm), field) != NULL && \
2437 LIST_NEXT((elm), field)->field.le_prev != \
2438 &((elm)->field.le_next)) \
2439 panic("Bad link elm %p next->prev != elm", (elm)); \
2440} while (0)
2441
2442#define QMD_LIST_CHECK_PREV(elm, field) do { \
2443 if (*(elm)->field.le_prev != (elm)) \
2444 panic("Bad link elm %p prev->next != elm", (elm)); \
2445} while (0)
2446#else
2447#define QMD_LIST_CHECK_HEAD(head, field)
2448#define QMD_LIST_CHECK_NEXT(elm, field)
2449#define QMD_LIST_CHECK_PREV(elm, field)
2450#endif /* (_KERNEL && INVARIANTS) */
2451
2452#define LIST_EMPTY(head) ((head)->lh_first == NULL)
2453
2454#define LIST_FIRST(head) ((head)->lh_first)
2455
2456#define LIST_FOREACH(var, head, field) \
2457 for ((var) = LIST_FIRST((head)); \
2458 (var); \
2459 (var) = LIST_NEXT((var), field))
2460
2461#define LIST_FOREACH_FROM(var, head, field) \
2462 for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
2463 (var); \
2464 (var) = LIST_NEXT((var), field))
2465
2466#define LIST_FOREACH_SAFE(var, head, field, tvar) \
2467 for ((var) = LIST_FIRST((head)); \
2468 (var) && ((tvar) = LIST_NEXT((var), field), 1); \
2469 (var) = (tvar))
2470
2471#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
2472 for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
2473 (var) && ((tvar) = LIST_NEXT((var), field), 1); \
2474 (var) = (tvar))
2475
2476#define LIST_INIT(head) do { \
2477 LIST_FIRST((head)) = NULL; \
2478} while (0)
2479
2480#define LIST_INSERT_AFTER(listelm, elm, field) do { \
2481 QMD_LIST_CHECK_NEXT(listelm, field); \
2482 if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
2483 LIST_NEXT((listelm), field)->field.le_prev = \
2484 &LIST_NEXT((elm), field); \
2485 LIST_NEXT((listelm), field) = (elm); \
2486 (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
2487} while (0)
2488
2489#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
2490 QMD_LIST_CHECK_PREV(listelm, field); \
2491 (elm)->field.le_prev = (listelm)->field.le_prev; \
2492 LIST_NEXT((elm), field) = (listelm); \
2493 *(listelm)->field.le_prev = (elm); \
2494 (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
2495} while (0)
2496
2497#define LIST_INSERT_HEAD(head, elm, field) do { \
2498 QMD_LIST_CHECK_HEAD((head), field); \
2499 if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
2500 LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
2501 LIST_FIRST((head)) = (elm); \
2502 (elm)->field.le_prev = &LIST_FIRST((head)); \
2503} while (0)
2504
2505#define LIST_NEXT(elm, field) ((elm)->field.le_next)
2506
2507#define LIST_PREV(elm, head, type, field) \
2508 ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
2509 __containerof((elm)->field.le_prev, \
2510 QUEUE_TYPEOF(type), field.le_next))
2511
2512#define LIST_REMOVE(elm, field) do { \
2513 QMD_SAVELINK(oldnext, (elm)->field.le_next); \
2514 QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
2515 QMD_LIST_CHECK_NEXT(elm, field); \
2516 QMD_LIST_CHECK_PREV(elm, field); \
2517 if (LIST_NEXT((elm), field) != NULL) \
2518 LIST_NEXT((elm), field)->field.le_prev = \
2519 (elm)->field.le_prev; \
2520 *(elm)->field.le_prev = LIST_NEXT((elm), field); \
2521 TRASHIT(*oldnext); \
2522 TRASHIT(*oldprev); \
2523} while (0)
2524
2525#define LIST_SWAP(head1, head2, type, field) do { \
2526 QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \
2527 LIST_FIRST((head1)) = LIST_FIRST((head2)); \
2528 LIST_FIRST((head2)) = swap_tmp; \
2529 if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
2530 swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
2531 if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
2532 swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
2533} while (0)
2534
2535/*
2536 * Tail queue declarations.
2537 */
2538#define TAILQ_HEAD(name, type) \
2539struct name { \
2540 struct type *tqh_first; /* first element */ \
2541 struct type **tqh_last; /* addr of last next element */ \
2542 TRACEBUF \
2543}
2544
2545#define TAILQ_CLASS_HEAD(name, type) \
2546struct name { \
2547 class type *tqh_first; /* first element */ \
2548 class type **tqh_last; /* addr of last next element */ \
2549 TRACEBUF \
2550}
2551
2552#define TAILQ_HEAD_INITIALIZER(head) \
2553 { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
2554
2555#define TAILQ_ENTRY(type) \
2556struct { \
2557 struct type *tqe_next; /* next element */ \
2558 struct type **tqe_prev; /* address of previous next element */ \
2559 TRACEBUF \
2560}
2561
2562#define TAILQ_CLASS_ENTRY(type) \
2563struct { \
2564 class type *tqe_next; /* next element */ \
2565 class type **tqe_prev; /* address of previous next element */ \
2566 TRACEBUF \
2567}
2568
2569/*
2570 * Tail queue functions.
2571 */
2572#if (defined(_KERNEL) && defined(INVARIANTS))
2573#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
2574 if (!TAILQ_EMPTY(head) && \
2575 TAILQ_FIRST((head))->field.tqe_prev != \
2576 &TAILQ_FIRST((head))) \
2577 panic("Bad tailq head %p first->prev != head", (head)); \
2578} while (0)
2579
2580#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
2581 if (*(head)->tqh_last != NULL) \
2582 panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
2583} while (0)
2584
2585#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
2586 if (TAILQ_NEXT((elm), field) != NULL && \
2587 TAILQ_NEXT((elm), field)->field.tqe_prev != \
2588 &((elm)->field.tqe_next)) \
2589 panic("Bad link elm %p next->prev != elm", (elm)); \
2590} while (0)
2591
2592#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
2593 if (*(elm)->field.tqe_prev != (elm)) \
2594 panic("Bad link elm %p prev->next != elm", (elm)); \
2595} while (0)
2596#else
2597#define QMD_TAILQ_CHECK_HEAD(head, field)
2598#define QMD_TAILQ_CHECK_TAIL(head, headname)
2599#define QMD_TAILQ_CHECK_NEXT(elm, field)
2600#define QMD_TAILQ_CHECK_PREV(elm, field)
2601#endif /* (_KERNEL && INVARIANTS) */
2602
2603#define TAILQ_CONCAT(head1, head2, field) do { \
2604 if (!TAILQ_EMPTY(head2)) { \
2605 *(head1)->tqh_last = (head2)->tqh_first; \
2606 (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
2607 (head1)->tqh_last = (head2)->tqh_last; \
2608 TAILQ_INIT((head2)); \
2609 QMD_TRACE_HEAD(head1); \
2610 QMD_TRACE_HEAD(head2); \
2611 } \
2612} while (0)
2613
2614#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
2615
2616#define TAILQ_FIRST(head) ((head)->tqh_first)
2617
2618#define TAILQ_FOREACH(var, head, field) \
2619 for ((var) = TAILQ_FIRST((head)); \
2620 (var); \
2621 (var) = TAILQ_NEXT((var), field))
2622
2623#define TAILQ_FOREACH_FROM(var, head, field) \
2624 for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
2625 (var); \
2626 (var) = TAILQ_NEXT((var), field))
2627
2628#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
2629 for ((var) = TAILQ_FIRST((head)); \
2630 (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
2631 (var) = (tvar))
2632
2633#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
2634 for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
2635 (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
2636 (var) = (tvar))
2637
2638#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
2639 for ((var) = TAILQ_LAST((head), headname); \
2640 (var); \
2641 (var) = TAILQ_PREV((var), headname, field))
2642
2643#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
2644 for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
2645 (var); \
2646 (var) = TAILQ_PREV((var), headname, field))
2647
2648#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
2649 for ((var) = TAILQ_LAST((head), headname); \
2650 (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
2651 (var) = (tvar))
2652
2653#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
2654 for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
2655 (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
2656 (var) = (tvar))
2657
2658#define TAILQ_INIT(head) do { \
2659 TAILQ_FIRST((head)) = NULL; \
2660 (head)->tqh_last = &TAILQ_FIRST((head)); \
2661 QMD_TRACE_HEAD(head); \
2662} while (0)
2663
2664#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
2665 QMD_TAILQ_CHECK_NEXT(listelm, field); \
2666 if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
2667 TAILQ_NEXT((elm), field)->field.tqe_prev = \
2668 &TAILQ_NEXT((elm), field); \
2669 else { \
2670 (head)->tqh_last = &TAILQ_NEXT((elm), field); \
2671 QMD_TRACE_HEAD(head); \
2672 } \
2673 TAILQ_NEXT((listelm), field) = (elm); \
2674 (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
2675 QMD_TRACE_ELEM(&(elm)->field); \
2676 QMD_TRACE_ELEM(&(listelm)->field); \
2677} while (0)
2678
2679#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
2680 QMD_TAILQ_CHECK_PREV(listelm, field); \
2681 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
2682 TAILQ_NEXT((elm), field) = (listelm); \
2683 *(listelm)->field.tqe_prev = (elm); \
2684 (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
2685 QMD_TRACE_ELEM(&(elm)->field); \
2686 QMD_TRACE_ELEM(&(listelm)->field); \
2687} while (0)
2688
2689#define TAILQ_INSERT_HEAD(head, elm, field) do { \
2690 QMD_TAILQ_CHECK_HEAD(head, field); \
2691 if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
2692 TAILQ_FIRST((head))->field.tqe_prev = \
2693 &TAILQ_NEXT((elm), field); \
2694 else \
2695 (head)->tqh_last = &TAILQ_NEXT((elm), field); \
2696 TAILQ_FIRST((head)) = (elm); \
2697 (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
2698 QMD_TRACE_HEAD(head); \
2699 QMD_TRACE_ELEM(&(elm)->field); \
2700} while (0)
2701
2702#define TAILQ_INSERT_TAIL(head, elm, field) do { \
2703 QMD_TAILQ_CHECK_TAIL(head, field); \
2704 TAILQ_NEXT((elm), field) = NULL; \
2705 (elm)->field.tqe_prev = (head)->tqh_last; \
2706 *(head)->tqh_last = (elm); \
2707 (head)->tqh_last = &TAILQ_NEXT((elm), field); \
2708 QMD_TRACE_HEAD(head); \
2709 QMD_TRACE_ELEM(&(elm)->field); \
2710} while (0)
2711
2712#define TAILQ_LAST(head, headname) \
2713 (*(((struct headname *)((head)->tqh_last))->tqh_last))
2714
2715#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
2716
2717#define TAILQ_PREV(elm, headname, field) \
2718 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
2719
2720#define TAILQ_REMOVE(head, elm, field) do { \
2721 QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
2722 QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
2723 QMD_TAILQ_CHECK_NEXT(elm, field); \
2724 QMD_TAILQ_CHECK_PREV(elm, field); \
2725 if ((TAILQ_NEXT((elm), field)) != NULL) \
2726 TAILQ_NEXT((elm), field)->field.tqe_prev = \
2727 (elm)->field.tqe_prev; \
2728 else { \
2729 (head)->tqh_last = (elm)->field.tqe_prev; \
2730 QMD_TRACE_HEAD(head); \
2731 } \
2732 *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
2733 TRASHIT(*oldnext); \
2734 TRASHIT(*oldprev); \
2735 QMD_TRACE_ELEM(&(elm)->field); \
2736} while (0)
2737
2738#define TAILQ_SWAP(head1, head2, type, field) do { \
2739 QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \
2740 QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \
2741 (head1)->tqh_first = (head2)->tqh_first; \
2742 (head1)->tqh_last = (head2)->tqh_last; \
2743 (head2)->tqh_first = swap_first; \
2744 (head2)->tqh_last = swap_last; \
2745 if ((swap_first = (head1)->tqh_first) != NULL) \
2746 swap_first->field.tqe_prev = &(head1)->tqh_first; \
2747 else \
2748 (head1)->tqh_last = &(head1)->tqh_first; \
2749 if ((swap_first = (head2)->tqh_first) != NULL) \
2750 swap_first->field.tqe_prev = &(head2)->tqh_first; \
2751 else \
2752 (head2)->tqh_last = &(head2)->tqh_first; \
2753} while (0)
2754
2755#endif /* !_SYS_QUEUE_H_ */
2756#ifdef MG_MODULE_LINES
2757#line 1 "mongoose/src/features.h"
2758#endif
2759/*
2760 * Copyright (c) 2014-2016 Cesanta Software Limited
2761 * All rights reserved
2762 */
2763
2764#ifndef CS_MONGOOSE_SRC_FEATURES_H_
2765#define CS_MONGOOSE_SRC_FEATURES_H_
2766
2767#ifndef MG_DISABLE_HTTP_DIGEST_AUTH
2768#define MG_DISABLE_HTTP_DIGEST_AUTH 0
2769#endif
2770
2771#ifndef MG_DISABLE_HTTP_KEEP_ALIVE
2772#define MG_DISABLE_HTTP_KEEP_ALIVE 0
2773#endif
2774
2775#ifndef MG_DISABLE_PFS
2776#define MG_DISABLE_PFS 0
2777#endif
2778
2779#ifndef MG_DISABLE_WS_RANDOM_MASK
2780#define MG_DISABLE_WS_RANDOM_MASK 0
2781#endif
2782
2783#ifndef MG_ENABLE_ASYNC_RESOLVER
2784#define MG_ENABLE_ASYNC_RESOLVER 1
2785#endif
2786
2787#ifndef MG_ENABLE_BROADCAST
2788#define MG_ENABLE_BROADCAST 0
2789#endif
2790
2791#ifndef MG_ENABLE_COAP
2792#define MG_ENABLE_COAP 0
2793#endif
2794
2795#ifndef MG_ENABLE_DEBUG
2796#define MG_ENABLE_DEBUG 0
2797#endif
2798
2799#ifndef MG_ENABLE_DIRECTORY_LISTING
2800#define MG_ENABLE_DIRECTORY_LISTING 0
2801#endif
2802
2803#ifndef MG_ENABLE_DNS
2804#define MG_ENABLE_DNS 1
2805#endif
2806
2807#ifndef MG_ENABLE_DNS_SERVER
2808#define MG_ENABLE_DNS_SERVER 0
2809#endif
2810
2811#ifndef MG_ENABLE_FAKE_DAVLOCK
2812#define MG_ENABLE_FAKE_DAVLOCK 0
2813#endif
2814
2815#ifndef MG_ENABLE_FILESYSTEM
2816#define MG_ENABLE_FILESYSTEM 0
2817#endif
2818
2819#ifndef MG_ENABLE_GETADDRINFO
2820#define MG_ENABLE_GETADDRINFO 0
2821#endif
2822
2823#ifndef MG_ENABLE_HEXDUMP
2824#define MG_ENABLE_HEXDUMP CS_ENABLE_STDIO
2825#endif
2826
2827#ifndef MG_ENABLE_HTTP
2828#define MG_ENABLE_HTTP 1
2829#endif
2830
2831#ifndef MG_ENABLE_HTTP_CGI
2832#define MG_ENABLE_HTTP_CGI 0
2833#endif
2834
2835#ifndef MG_ENABLE_HTTP_SSI
2836#define MG_ENABLE_HTTP_SSI MG_ENABLE_FILESYSTEM
2837#endif
2838
2839#ifndef MG_ENABLE_HTTP_SSI_EXEC
2840#define MG_ENABLE_HTTP_SSI_EXEC 0
2841#endif
2842
2843#ifndef MG_ENABLE_HTTP_STREAMING_MULTIPART
2844#define MG_ENABLE_HTTP_STREAMING_MULTIPART 0
2845#endif
2846
2847#ifndef MG_ENABLE_HTTP_WEBDAV
2848#define MG_ENABLE_HTTP_WEBDAV 0
2849#endif
2850
2851#ifndef MG_ENABLE_HTTP_WEBSOCKET
2852#define MG_ENABLE_HTTP_WEBSOCKET MG_ENABLE_HTTP
2853#endif
2854
2855#ifndef MG_ENABLE_IPV6
2856#define MG_ENABLE_IPV6 0
2857#endif
2858
2859#ifndef MG_ENABLE_JAVASCRIPT
2860#define MG_ENABLE_JAVASCRIPT 0
2861#endif
2862
2863#ifndef MG_ENABLE_MQTT
2864#define MG_ENABLE_MQTT 1
2865#endif
2866
2867#ifndef MG_ENABLE_MQTT_BROKER
2868#define MG_ENABLE_MQTT_BROKER 0
2869#endif
2870
2871#ifndef MG_ENABLE_SSL
2872#define MG_ENABLE_SSL 0
2873#endif
2874
2875#ifndef MG_ENABLE_SYNC_RESOLVER
2876#define MG_ENABLE_SYNC_RESOLVER 0
2877#endif
2878
2879#ifndef MG_ENABLE_STDIO
2880#define MG_ENABLE_STDIO CS_ENABLE_STDIO
2881#endif
2882
2883#ifndef MG_NET_IF
2884#define MG_NET_IF MG_NET_IF_SOCKET
2885#endif
2886
2887#ifndef MG_SSL_IF
2888#define MG_SSL_IF MG_SSL_IF_OPENSSL
2889#endif
2890
2891#ifndef MG_ENABLE_THREADS /* ifdef-ok */
2892#ifdef _WIN32
2893#define MG_ENABLE_THREADS 1
2894#else
2895#define MG_ENABLE_THREADS 0
2896#endif
2897#endif
2898
2899#if MG_ENABLE_DEBUG && !defined(CS_ENABLE_DEBUG)
2900#define CS_ENABLE_DEBUG 1
2901#endif
2902
2903/* MQTT broker requires MQTT */
2904#if MG_ENABLE_MQTT_BROKER && !MG_ENABLE_MQTT
2905#undef MG_ENABLE_MQTT
2906#define MG_ENABLE_MQTT 1
2907#endif
2908
2909#ifndef MG_ENABLE_HTTP_URL_REWRITES
2910#define MG_ENABLE_HTTP_URL_REWRITES \
2911 (CS_PLATFORM == CS_P_WINDOWS || CS_PLATFORM == CS_P_UNIX)
2912#endif
2913
2914#ifndef MG_ENABLE_TUN
2915#define MG_ENABLE_TUN MG_ENABLE_HTTP_WEBSOCKET
2916#endif
2917
2918#ifndef MG_ENABLE_SNTP
2919#define MG_ENABLE_SNTP 0
2920#endif
2921
2922#ifndef MG_ENABLE_EXTRA_ERRORS_DESC
2923#define MG_ENABLE_EXTRA_ERRORS_DESC 0
2924#endif
2925
2926#endif /* CS_MONGOOSE_SRC_FEATURES_H_ */
2927#ifdef MG_MODULE_LINES
2928#line 1 "mongoose/src/net_if.h"
2929#endif
2930/*
2931 * Copyright (c) 2014-2016 Cesanta Software Limited
2932 * All rights reserved
2933 */
2934
2935#ifndef CS_MONGOOSE_SRC_NET_IF_H_
2936#define CS_MONGOOSE_SRC_NET_IF_H_
2937
2938/* Amalgamated: #include "common/platform.h" */
2939
2940/*
2941 * Internal async networking core interface.
2942 * Consists of calls made by the core, which should not block,
2943 * and callbacks back into the core ("..._cb").
2944 * Callbacks may (will) cause methods to be invoked from within,
2945 * but methods are not allowed to invoke callbacks inline.
2946 *
2947 * Implementation must ensure that only one callback is invoked at any time.
2948 */
2949
2950#ifdef __cplusplus
2951extern "C" {
2952#endif /* __cplusplus */
2953
2954#define MG_MAIN_IFACE 0
2955
2956struct mg_mgr;
2957struct mg_connection;
2958union socket_address;
2959
2960struct mg_iface_vtable;
2961
2962struct mg_iface {
2963 struct mg_mgr *mgr;
2964 void *data; /* Implementation-specific data */
2965 struct mg_iface_vtable *vtable;
2966};
2967
2968struct mg_iface_vtable {
2969 void (*init)(struct mg_iface *iface);
2970 void (*free)(struct mg_iface *iface);
2971 void (*add_conn)(struct mg_connection *nc);
2972 void (*remove_conn)(struct mg_connection *nc);
2973 time_t (*poll)(struct mg_iface *iface, int timeout_ms);
2974
2975 /* Set up a listening TCP socket on a given address. rv = 0 -> ok. */
2976 int (*listen_tcp)(struct mg_connection *nc, union socket_address *sa);
2977 /* Request that a "listening" UDP socket be created. */
2978 int (*listen_udp)(struct mg_connection *nc, union socket_address *sa);
2979
2980 /* Request that a TCP connection is made to the specified address. */
2981 void (*connect_tcp)(struct mg_connection *nc, const union socket_address *sa);
2982 /* Open a UDP socket. Doesn't actually connect anything. */
2983 void (*connect_udp)(struct mg_connection *nc);
2984
2985 /* Send functions for TCP and UDP. Sent data is copied before return. */
2986 void (*tcp_send)(struct mg_connection *nc, const void *buf, size_t len);
2987 void (*udp_send)(struct mg_connection *nc, const void *buf, size_t len);
2988
2989 void (*recved)(struct mg_connection *nc, size_t len);
2990
2991 /* Perform interface-related connection initialization. Return 1 on ok. */
2992 int (*create_conn)(struct mg_connection *nc);
2993 /* Perform interface-related cleanup on connection before destruction. */
2994 void (*destroy_conn)(struct mg_connection *nc);
2995
2996 /* Associate a socket to a connection. */
2997 void (*sock_set)(struct mg_connection *nc, sock_t sock);
2998
2999 /* Put connection's address into *sa, local (remote = 0) or remote. */
3000 void (*get_conn_addr)(struct mg_connection *nc, int remote,
3001 union socket_address *sa);
3002};
3003
3004extern struct mg_iface_vtable *mg_ifaces[];
3005extern int mg_num_ifaces;
3006
3007/* Creates a new interface instance. */
3008struct mg_iface *mg_if_create_iface(struct mg_iface_vtable *vtable,
3009 struct mg_mgr *mgr);
3010
3011/*
3012 * Find an interface with a given implementation. The search is started from
3013 * interface `from`, exclusive. Returns NULL if none is found.
3014 */
3015struct mg_iface *mg_find_iface(struct mg_mgr *mgr,
3016 struct mg_iface_vtable *vtable,
3017 struct mg_iface *from);
3018/*
3019 * Deliver a new TCP connection. Returns NULL in case on error (unable to
3020 * create connection, in which case interface state should be discarded.
3021 * This is phase 1 of the two-phase process - MG_EV_ACCEPT will be delivered
3022 * when mg_if_accept_tcp_cb is invoked.
3023 */
3024struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc);
3025void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa,
3026 size_t sa_len);
3027
3028/* Callback invoked by connect methods. err = 0 -> ok, != 0 -> error. */
3029void mg_if_connect_cb(struct mg_connection *nc, int err);
3030/* Callback that reports that data has been put on the wire. */
3031void mg_if_sent_cb(struct mg_connection *nc, int num_sent);
3032/*
3033 * Receive callback.
3034 * if `own` is true, buf must be heap-allocated and ownership is transferred
3035 * to the core.
3036 * Core will acknowledge consumption by calling iface::recved.
3037 */
3038void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len, int own);
3039/*
3040 * Receive callback.
3041 * buf must be heap-allocated and ownership is transferred to the core.
3042 * Core will acknowledge consumption by calling iface::recved.
3043 */
3044void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len,
3045 union socket_address *sa, size_t sa_len);
3046
3047/* void mg_if_close_conn(struct mg_connection *nc); */
3048
3049/* Deliver a POLL event to the connection. */
3050void mg_if_poll(struct mg_connection *nc, time_t now);
3051
3052/* Deliver a TIMER event to the connection. */
3053void mg_if_timer(struct mg_connection *c, double now);
3054
3055#ifdef __cplusplus
3056}
3057#endif /* __cplusplus */
3058
3059#endif /* CS_MONGOOSE_SRC_NET_IF_H_ */
3060#ifdef MG_MODULE_LINES
3061#line 1 "mongoose/src/ssl_if.h"
3062#endif
3063/*
3064 * Copyright (c) 2014-2016 Cesanta Software Limited
3065 * All rights reserved
3066 */
3067
3068#ifndef CS_MONGOOSE_SRC_SSL_IF_H_
3069#define CS_MONGOOSE_SRC_SSL_IF_H_
3070
3071#if MG_ENABLE_SSL
3072
3073#ifdef __cplusplus
3074extern "C" {
3075#endif /* __cplusplus */
3076
3077struct mg_ssl_if_ctx;
3078struct mg_connection;
3079
3080void mg_ssl_if_init();
3081
3082enum mg_ssl_if_result {
3083 MG_SSL_OK = 0,
3084 MG_SSL_WANT_READ = -1,
3085 MG_SSL_WANT_WRITE = -2,
3086 MG_SSL_ERROR = -3,
3087};
3088
3089struct mg_ssl_if_conn_params {
3090 const char *cert;
3091 const char *key;
3092 const char *ca_cert;
3093 const char *server_name;
3094};
3095
3096enum mg_ssl_if_result mg_ssl_if_conn_init(
3097 struct mg_connection *nc, const struct mg_ssl_if_conn_params *params,
3098 const char **err_msg);
3099enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc,
3100 struct mg_connection *lc);
3101void mg_ssl_if_conn_free(struct mg_connection *nc);
3102
3103enum mg_ssl_if_result mg_ssl_if_handshake(struct mg_connection *nc);
3104int mg_ssl_if_read(struct mg_connection *nc, void *buf, size_t buf_size);
3105int mg_ssl_if_write(struct mg_connection *nc, const void *data, size_t len);
3106
3107#ifdef __cplusplus
3108}
3109#endif /* __cplusplus */
3110
3111#endif /* MG_ENABLE_SSL */
3112
3113#endif /* CS_MONGOOSE_SRC_SSL_IF_H_ */
3114#ifdef MG_MODULE_LINES
3115#line 1 "mongoose/src/net.h"
3116#endif
3117/*
3118 * Copyright (c) 2014 Cesanta Software Limited
3119 * All rights reserved
3120 * This software is dual-licensed: you can redistribute it and/or modify
3121 * it under the terms of the GNU General Public License version 2 as
3122 * published by the Free Software Foundation. For the terms of this
3123 * license, see <http://www.gnu.org/licenses/>.
3124 *
3125 * You are free to use this software under the terms of the GNU General
3126 * Public License, but WITHOUT ANY WARRANTY; without even the implied
3127 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3128 * See the GNU General Public License for more details.
3129 *
3130 * Alternatively, you can license this software under a commercial
3131 * license, as set out in <https://www.cesanta.com/license>.
3132 */
3133
3134/*
3135 * === Core API: TCP/UDP/SSL
3136 *
3137 * NOTE: Mongoose manager is single threaded. It does not protect
3138 * its data structures by mutexes, therefore all functions that are dealing
3139 * with a particular event manager should be called from the same thread,
3140 * with exception of the `mg_broadcast()` function. It is fine to have different
3141 * event managers handled by different threads.
3142 */
3143
3144#ifndef CS_MONGOOSE_SRC_NET_H_
3145#define CS_MONGOOSE_SRC_NET_H_
3146
3147#if MG_ENABLE_JAVASCRIPT
3148#define EXCLUDE_COMMON
3149#include <v7.h>
3150#endif
3151
3152/* Amalgamated: #include "mongoose/src/common.h" */
3153/* Amalgamated: #include "mongoose/src/net_if.h" */
3154/* Amalgamated: #include "common/mbuf.h" */
3155
3156#ifndef MG_VPRINTF_BUFFER_SIZE
3157#define MG_VPRINTF_BUFFER_SIZE 100
3158#endif
3159
3160#ifdef MG_USE_READ_WRITE
3161#define MG_RECV_FUNC(s, b, l, f) read(s, b, l)
3162#define MG_SEND_FUNC(s, b, l, f) write(s, b, l)
3163#else
3164#define MG_RECV_FUNC(s, b, l, f) recv(s, b, l, f)
3165#define MG_SEND_FUNC(s, b, l, f) send(s, b, l, f)
3166#endif
3167
3168#ifdef __cplusplus
3169extern "C" {
3170#endif /* __cplusplus */
3171
3172union socket_address {
3173 struct sockaddr sa;
3174 struct sockaddr_in sin;
3175#if MG_ENABLE_IPV6
3176 struct sockaddr_in6 sin6;
3177#else
3178 struct sockaddr sin6;
3179#endif
3180};
3181
3182struct mg_connection;
3183
3184/*
3185 * Callback function (event handler) prototype. Must be defined by the user.
3186 * Mongoose calls the event handler, passing the events defined below.
3187 */
3188typedef void (*mg_event_handler_t)(struct mg_connection *nc, int ev,
3189 void *ev_data);
3190
3191/* Events. Meaning of event parameter (evp) is given in the comment. */
3192#define MG_EV_POLL 0 /* Sent to each connection on each mg_mgr_poll() call */
3193#define MG_EV_ACCEPT 1 /* New connection accepted. union socket_address * */
3194#define MG_EV_CONNECT 2 /* connect() succeeded or failed. int * */
3195#define MG_EV_RECV 3 /* Data has benn received. int *num_bytes */
3196#define MG_EV_SEND 4 /* Data has been written to a socket. int *num_bytes */
3197#define MG_EV_CLOSE 5 /* Connection is closed. NULL */
3198#define MG_EV_TIMER 6 /* now >= conn->ev_timer_time. double * */
3199
3200/*
3201 * Mongoose event manager.
3202 */
3203struct mg_mgr {
3204 struct mg_connection *active_connections;
3205#if MG_ENABLE_HEXDUMP
3206 const char *hexdump_file; /* Debug hexdump file path */
3207#endif
3208#if MG_ENABLE_BROADCAST
3209 sock_t ctl[2]; /* Socketpair for mg_broadcast() */
3210#endif
3211 void *user_data; /* User data */
3212 int num_ifaces;
3213 struct mg_iface **ifaces; /* network interfaces */
3214#if MG_ENABLE_JAVASCRIPT
3215 struct v7 *v7;
3216#endif
3217};
3218
3219/*
3220 * Mongoose connection.
3221 */
3222struct mg_connection {
3223 struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
3224 struct mg_connection *listener; /* Set only for accept()-ed connections */
3225 struct mg_mgr *mgr; /* Pointer to containing manager */
3226
3227 sock_t sock; /* Socket to the remote peer */
3228 int err;
3229 union socket_address sa; /* Remote peer address */
3230 size_t recv_mbuf_limit; /* Max size of recv buffer */
3231 struct mbuf recv_mbuf; /* Received data */
3232 struct mbuf send_mbuf; /* Data scheduled for sending */
3233 time_t last_io_time; /* Timestamp of the last socket IO */
3234 double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
3235#if MG_ENABLE_SSL
3236 void *ssl_if_data; /* SSL library data. */
3237#endif
3238 mg_event_handler_t proto_handler; /* Protocol-specific event handler */
3239 void *proto_data; /* Protocol-specific data */
3240 void (*proto_data_destructor)(void *proto_data);
3241 mg_event_handler_t handler; /* Event handler function */
3242 void *user_data; /* User-specific data */
3243 union {
3244 void *v;
3245 /*
3246 * the C standard is fussy about fitting function pointers into
3247 * void pointers, since some archs might have fat pointers for functions.
3248 */
3249 mg_event_handler_t f;
3250 } priv_1; /* Used by mg_enable_multithreading() */
3251 void *priv_2; /* Used by mg_enable_multithreading() */
3252 void *mgr_data; /* Implementation-specific event manager's data. */
3253 struct mg_iface *iface;
3254 unsigned long flags;
3255/* Flags set by Mongoose */
3256#define MG_F_LISTENING (1 << 0) /* This connection is listening */
3257#define MG_F_UDP (1 << 1) /* This connection is UDP */
3258#define MG_F_RESOLVING (1 << 2) /* Waiting for async resolver */
3259#define MG_F_CONNECTING (1 << 3) /* connect() call in progress */
3260#define MG_F_SSL (1 << 4) /* SSL is enabled on the connection */
3261#define MG_F_SSL_HANDSHAKE_DONE (1 << 5) /* SSL hanshake has completed */
3262#define MG_F_WANT_READ (1 << 6) /* SSL specific */
3263#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
3264#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
3265
3266/* Flags that are settable by user */
3267#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
3268#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */
3269#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
3270#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */
3271#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */
3272#define MG_F_TUN_DO_NOT_RECONNECT (1 << 15) /* Don't reconnect tunnel */
3273
3274#define MG_F_USER_1 (1 << 20) /* Flags left for application */
3275#define MG_F_USER_2 (1 << 21)
3276#define MG_F_USER_3 (1 << 22)
3277#define MG_F_USER_4 (1 << 23)
3278#define MG_F_USER_5 (1 << 24)
3279#define MG_F_USER_6 (1 << 25)
3280};
3281
3282/*
3283 * Initialise Mongoose manager. Side effect: ignores SIGPIPE signal.
3284 * `mgr->user_data` field will be initialised with a `user_data` parameter.
3285 * That is an arbitrary pointer, where the user code can associate some data
3286 * with the particular Mongoose manager. For example, a C++ wrapper class
3287 * could be written in which case `user_data` can hold a pointer to the
3288 * class instance.
3289 */
3290void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
3291
3292/*
3293 * Optional parameters to `mg_mgr_init_opt()`.
3294 *
3295 * If `main_iface` is not NULL, it will be used as the main interface in the
3296 * default interface set. The pointer will be free'd by `mg_mgr_free`.
3297 * Otherwise, the main interface will be autodetected based on the current
3298 * platform.
3299 *
3300 * If `num_ifaces` is 0 and `ifaces` is NULL, the default interface set will be
3301 * used.
3302 * This is an advanced option, as it requires you to construct a full interface
3303 * set, including special networking interfaces required by some optional
3304 * features such as TCP tunneling. Memory backing `ifaces` and each of the
3305 * `num_ifaces` pointers it contains will be reclaimed by `mg_mgr_free`.
3306 */
3307struct mg_mgr_init_opts {
3308 struct mg_iface_vtable *main_iface;
3309 int num_ifaces;
3310 struct mg_iface_vtable **ifaces;
3311};
3312
3313/*
3314 * Like `mg_mgr_init` but with more options.
3315 *
3316 * Notably, this allows you to create a manger and choose
3317 * dynamically which networking interface implementation to use.
3318 */
3319void mg_mgr_init_opt(struct mg_mgr *mgr, void *user_data,
3320 struct mg_mgr_init_opts opts);
3321
3322/*
3323 * De-initialises Mongoose manager.
3324 *
3325 * Closes and deallocates all active connections.
3326 */
3327void mg_mgr_free(struct mg_mgr *);
3328
3329/*
3330 * This function performs the actual IO and must be called in a loop
3331 * (an event loop). It returns the current timestamp.
3332 * `milli` is the maximum number of milliseconds to sleep.
3333 * `mg_mgr_poll()` checks all connections for IO readiness. If at least one
3334 * of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
3335 * event handlers and returns.
3336 */
3337time_t mg_mgr_poll(struct mg_mgr *, int milli);
3338
3339#if MG_ENABLE_BROADCAST
3340/*
3341 * Passes a message of a given length to all connections.
3342 *
3343 * Must be called from a thread that does NOT call `mg_mgr_poll()`.
3344 * Note that `mg_broadcast()` is the only function
3345 * that can be, and must be, called from a different (non-IO) thread.
3346 *
3347 * `func` callback function will be called by the IO thread for each
3348 * connection. When called, the event will be `MG_EV_POLL`, and a message will
3349 * be passed as the `ev_data` pointer. Maximum message size is capped
3350 * by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
3351 */
3352void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
3353#endif
3354
3355/*
3356 * Iterates over all active connections.
3357 *
3358 * Returns the next connection from the list
3359 * of active connections or `NULL` if there are no more connections. Below
3360 * is the iteration idiom:
3361 *
3362 * ```c
3363 * for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
3364 * // Do something with connection `c`
3365 * }
3366 * ```
3367 */
3368struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
3369
3370/*
3371 * Optional parameters to `mg_add_sock_opt()`.
3372 *
3373 * `flags` is an initial `struct mg_connection::flags` bitmask to set,
3374 * see `MG_F_*` flags definitions.
3375 */
3376struct mg_add_sock_opts {
3377 void *user_data; /* Initial value for connection's user_data */
3378 unsigned int flags; /* Initial connection flags */
3379 const char **error_string; /* Placeholder for the error string */
3380 struct mg_iface *iface; /* Interface instance */
3381};
3382
3383/*
3384 * Creates a connection, associates it with the given socket and event handler
3385 * and adds it to the manager.
3386 *
3387 * For more options see the `mg_add_sock_opt` variant.
3388 */
3389struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
3390
3391/*
3392 * Creates a connection, associates it with the given socket and event handler
3393 * and adds to the manager.
3394 *
3395 * See the `mg_add_sock_opts` structure for a description of the options.
3396 */
3397struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
3398 mg_event_handler_t,
3399 struct mg_add_sock_opts);
3400
3401/*
3402 * Optional parameters to `mg_bind_opt()`.
3403 *
3404 * `flags` is an initial `struct mg_connection::flags` bitmask to set,
3405 * see `MG_F_*` flags definitions.
3406 */
3407struct mg_bind_opts {
3408 void *user_data; /* Initial value for connection's user_data */
3409 unsigned int flags; /* Extra connection flags */
3410 const char **error_string; /* Placeholder for the error string */
3411 struct mg_iface *iface; /* Interface instance */
3412#if MG_ENABLE_SSL
3413 /* SSL settings. */
3414 const char *ssl_cert; /* Server certificate to present to clients
3415 * Or client certificate to present to tunnel
3416 * dispatcher. */
3417 const char *ssl_key; /* Private key corresponding to the certificate.
3418 If ssl_cert is set but ssl_key is not, ssl_cert
3419 is used. */
3420 const char *ssl_ca_cert; /* CA bundle used to verify client certificates or
3421 * tunnel dispatchers. */
3422#endif
3423};
3424
3425/*
3426 * Creates a listening connection.
3427 *
3428 * See `mg_bind_opt` for full documentation.
3429 */
3430struct mg_connection *mg_bind(struct mg_mgr *, const char *,
3431 mg_event_handler_t);
3432/*
3433 * Creates a listening connection.
3434 *
3435 * The `address` parameter specifies which address to bind to. It's format is
3436 * the same as for the `mg_connect()` call, where `HOST` part is optional.
3437 * `address` can be just a port number, e.g. `:8000`. To bind to a specific
3438 * interface, an IP address can be specified, e.g. `1.2.3.4:8000`. By default,
3439 * a TCP connection is created. To create UDP connection, prepend `udp://`
3440 * prefix, e.g. `udp://:8000`. To summarize, `address` paramer has following
3441 * format: `[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or
3442 * `udp`.
3443 *
3444 * See the `mg_bind_opts` structure for a description of the optional
3445 * parameters.
3446 *
3447 * Returns a new listening connection or `NULL` on error.
3448 * NOTE: The connection remains owned by the manager, do not free().
3449 */
3450struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
3451 mg_event_handler_t handler,
3452 struct mg_bind_opts opts);
3453
3454/* Optional parameters to `mg_connect_opt()` */
3455struct mg_connect_opts {
3456 void *user_data; /* Initial value for connection's user_data */
3457 unsigned int flags; /* Extra connection flags */
3458 const char **error_string; /* Placeholder for the error string */
3459 struct mg_iface *iface; /* Interface instance */
3460#if MG_ENABLE_SSL
3461 /* SSL settings. */
3462 const char *ssl_cert; /* Client certificate to present to the server */
3463 const char *ssl_key; /* Private key corresponding to the certificate.
3464 If ssl_cert is set but ssl_key is not, ssl_cert
3465 is used. */
3466 const char *ssl_ca_cert; /* Verify server certificate using this CA bundle.
3467 If set to "*", then SSL is enabled but no cert
3468 verification is performed. */
3469
3470 /*
3471 * Server name verification. If ssl_ca_cert is set and the certificate has
3472 * passed verification, its subject will be verified against this string.
3473 * By default (if ssl_server_name is NULL) hostname part of the address will
3474 * be used. Wildcard matching is supported. A special value of "*" disables
3475 * name verification.
3476 */
3477 const char *ssl_server_name;
3478#endif
3479};
3480
3481/*
3482 * Connects to a remote host.
3483 *
3484 * See `mg_connect_opt()` for full documentation.
3485 */
3486struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
3487 mg_event_handler_t handler);
3488
3489/*
3490 * Connects to a remote host.
3491 *
3492 * The `address` format is `[PROTO://]HOST:PORT`. `PROTO` could be `tcp` or
3493 * `udp`. `HOST` could be an IP address,
3494 * IPv6 address (if Mongoose is compiled with `-DMG_ENABLE_IPV6`) or a host
3495 * name. If `HOST` is a name, Mongoose will resolve it asynchronously. Examples
3496 * of valid addresses: `google.com:80`, `udp://1.2.3.4:53`, `10.0.0.1:443`,
3497 * `[::1]:80`
3498 *
3499 * See the `mg_connect_opts` structure for a description of the optional
3500 * parameters.
3501 *
3502 * Returns a new outbound connection or `NULL` on error.
3503 *
3504 * NOTE: The connection remains owned by the manager, do not free().
3505 *
3506 * NOTE: To enable IPv6 addresses `-DMG_ENABLE_IPV6` should be specified
3507 * in the compilation flags.
3508 *
3509 * NOTE: The new connection will receive `MG_EV_CONNECT` as its first event
3510 * which will report the connect success status.
3511 * If the asynchronous resolution fails or the `connect()` syscall fails for
3512 * whatever reason (e.g. with `ECONNREFUSED` or `ENETUNREACH`), then
3513 * `MG_EV_CONNECT` event will report failure. Code example below:
3514 *
3515 * ```c
3516 * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
3517 * int connect_status;
3518 *
3519 * switch (ev) {
3520 * case MG_EV_CONNECT:
3521 * connect_status = * (int *) ev_data;
3522 * if (connect_status == 0) {
3523 * // Success
3524 * } else {
3525 * // Error
3526 * printf("connect() error: %s\n", strerror(connect_status));
3527 * }
3528 * break;
3529 * ...
3530 * }
3531 * }
3532 *
3533 * ...
3534 * mg_connect(mgr, "my_site.com:80", ev_handler);
3535 * ```
3536 */
3537struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
3538 mg_event_handler_t handler,
3539 struct mg_connect_opts opts);
3540
3541#if MG_ENABLE_SSL && MG_NET_IF != MG_NET_IF_SIMPLELINK
3542/*
3543 * Note: This function is deprecated. Please, use SSL options in
3544 * mg_connect_opt.
3545 *
3546 * Enables SSL for a given connection.
3547 * `cert` is a server certificate file name for a listening connection
3548 * or a client certificate file name for an outgoing connection.
3549 * The certificate files must be in PEM format. The server certificate file
3550 * must contain a certificate, concatenated with a private key, optionally
3551 * concatenated with DH parameters.
3552 * `ca_cert` is a CA certificate or NULL if peer verification is not
3553 * required.
3554 * Return: NULL on success or error message on error.
3555 */
3556const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
3557 const char *ca_cert);
3558#endif
3559
3560/*
3561 * Sends data to the connection.
3562 *
3563 * Note that sending functions do not actually push data to the socket.
3564 * They just append data to the output buffer. MG_EV_SEND will be delivered when
3565 * the data has actually been pushed out.
3566 */
3567void mg_send(struct mg_connection *, const void *buf, int len);
3568
3569/* Enables format string warnings for mg_printf */
3570#if defined(__GNUC__)
3571__attribute__((format(printf, 2, 3)))
3572#endif
3573/* don't separate from mg_printf declaration */
3574
3575/*
3576 * Sends `printf`-style formatted data to the connection.
3577 *
3578 * See `mg_send` for more details on send semantics.
3579 */
3580int mg_printf(struct mg_connection *, const char *fmt, ...);
3581
3582/* Same as `mg_printf()`, but takes `va_list ap` as an argument. */
3583int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
3584
3585/*
3586 * Creates a socket pair.
3587 * `sock_type` can be either `SOCK_STREAM` or `SOCK_DGRAM`.
3588 * Returns 0 on failure and 1 on success.
3589 */
3590int mg_socketpair(sock_t[2], int sock_type);
3591
3592#if MG_ENABLE_SYNC_RESOLVER
3593/*
3594 * Convert domain name into IP address.
3595 *
3596 * This is a utility function. If compilation flags have
3597 * `-DMG_ENABLE_GETADDRINFO`, then `getaddrinfo()` call is used for name
3598 * resolution. Otherwise, `gethostbyname()` is used.
3599 *
3600 * CAUTION: this function can block.
3601 * Return 1 on success, 0 on failure.
3602 */
3603int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
3604#endif
3605
3606/*
3607 * Verify given IP address against the ACL.
3608 *
3609 * `remote_ip` - an IPv4 address to check, in host byte order
3610 * `acl` - a comma separated list of IP subnets: `x.x.x.x/x` or `x.x.x.x`.
3611 * Each subnet is
3612 * prepended by either a - or a + sign. A plus sign means allow, where a
3613 * minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
3614 * it means that only that single IP address is denied.
3615 * Subnet masks may vary from 0 to 32, inclusive. The default setting
3616 * is to allow all access. On each request the full list is traversed,
3617 * and the last match wins. Example:
3618 *
3619 * `-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
3620 *
3621 * To learn more about subnet masks, see this
3622 * link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork].
3623 *
3624 * Returns -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
3625 */
3626int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
3627
3628/*
3629 * Optional parameters for mg_enable_multithreading_opt()
3630 */
3631struct mg_multithreading_opts {
3632 int poll_timeout; /* Polling interval */
3633};
3634
3635/*
3636 * Enables multi-threaded handling for the given listening connection `nc`.
3637 * For each accepted connection, Mongoose will create a separate thread
3638 * and run an event handler in that thread. Thus, if an event handler is doing
3639 * a blocking call or some long computation, it will not slow down
3640 * other connections.
3641 */
3642void mg_enable_multithreading(struct mg_connection *nc);
3643void mg_enable_multithreading_opt(struct mg_connection *nc,
3644 struct mg_multithreading_opts opts);
3645
3646#if MG_ENABLE_JAVASCRIPT
3647/*
3648 * Enables server-side JavaScript scripting.
3649 * Requires a `-DMG_ENABLE_JAVASCRIPT` compilation flag and V7 engine sources.
3650 * V7 instance must not be destroyed during manager's lifetime.
3651 * Returns a V7 error.
3652 */
3653enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
3654 const char *init_js_file_name);
3655#endif
3656
3657/*
3658 * Schedules an MG_EV_TIMER event to be delivered at `timestamp` time.
3659 * `timestamp` is UNIX time (the number of seconds since Epoch). It is
3660 * `double` instead of `time_t` to allow for sub-second precision.
3661 * Returns the old timer value.
3662 *
3663 * Example: set the connect timeout to 1.5 seconds:
3664 *
3665 * ```
3666 * c = mg_connect(&mgr, "cesanta.com", ev_handler);
3667 * mg_set_timer(c, mg_time() + 1.5);
3668 * ...
3669 *
3670 * void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
3671 * switch (ev) {
3672 * case MG_EV_CONNECT:
3673 * mg_set_timer(c, 0); // Clear connect timer
3674 * break;
3675 * case MG_EV_TIMER:
3676 * log("Connect timeout");
3677 * c->flags |= MG_F_CLOSE_IMMEDIATELY;
3678 * break;
3679 * ```
3680 */
3681double mg_set_timer(struct mg_connection *c, double timestamp);
3682
3683/*
3684 * A sub-second precision version of time().
3685 */
3686double mg_time(void);
3687
3688#ifdef __cplusplus
3689}
3690#endif /* __cplusplus */
3691
3692#endif /* CS_MONGOOSE_SRC_NET_H_ */
3693#ifdef MG_MODULE_LINES
3694#line 1 "mongoose/src/uri.h"
3695#endif
3696/*
3697 * Copyright (c) 2014 Cesanta Software Limited
3698 * All rights reserved
3699 */
3700
3701/*
3702 * === URI
3703 */
3704
3705#ifndef CS_MONGOOSE_SRC_URI_H_
3706#define CS_MONGOOSE_SRC_URI_H_
3707
3708/* Amalgamated: #include "mongoose/src/net.h" */
3709
3710#ifdef __cplusplus
3711extern "C" {
3712#endif /* __cplusplus */
3713
3714/*
3715 * Parses an URI and fills string chunks with locations of the respective
3716 * uri components within the input uri string. NULL pointers will be
3717 * ignored.
3718 *
3719 * General syntax:
3720 *
3721 * [scheme://[user_info@]]host[:port][/path][?query][#fragment]
3722 *
3723 * Example:
3724 *
3725 * foo.com:80
3726 * tcp://foo.com:1234
3727 * http://foo.com:80/bar?baz=1
3728 * https://user:pw@foo.com:443/blah
3729 *
3730 * `path` will include the leading slash. `query` won't include the leading `?`.
3731 * `host` can contain embedded colons if surrounded by square brackets in order
3732 * to support IPv6 literal addresses.
3733 *
3734 *
3735 * Returns 0 on success, -1 on error.
3736 */
3737int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
3738 struct mg_str *user_info, struct mg_str *host,
3739 unsigned int *port, struct mg_str *path, struct mg_str *query,
3740 struct mg_str *fragment);
3741
3742int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out);
3743
3744#ifdef __cplusplus
3745}
3746#endif /* __cplusplus */
3747#endif /* CS_MONGOOSE_SRC_URI_H_ */
3748#ifdef MG_MODULE_LINES
3749#line 1 "mongoose/src/util.h"
3750#endif
3751/*
3752 * Copyright (c) 2014 Cesanta Software Limited
3753 * All rights reserved
3754 */
3755
3756/*
3757 * === Utility API
3758 */
3759
3760#ifndef CS_MONGOOSE_SRC_UTIL_H_
3761#define CS_MONGOOSE_SRC_UTIL_H_
3762
3763#include <stdio.h>
3764
3765/* Amalgamated: #include "mongoose/src/common.h" */
3766/* Amalgamated: #include "mongoose/src/net_if.h" */
3767
3768#ifdef __cplusplus
3769extern "C" {
3770#endif /* __cplusplus */
3771
3772#ifndef MAX_PATH_SIZE
3773#define MAX_PATH_SIZE 500
3774#endif
3775
3776/*
3777 * Fetches substring from input string `s`, `end` into `v`.
3778 * Skips initial delimiter characters. Records first non-delimiter character
3779 * at the beginning of substring `v`. Then scans the rest of the string
3780 * until a delimiter character or end-of-string is found.
3781 * `delimiters` is a 0-terminated string containing delimiter characters.
3782 * Either one of `delimiters` or `end_string` terminates the search.
3783 * Returns an `s` pointer, advanced forward where parsing has stopped.
3784 */
3785const char *mg_skip(const char *s, const char *end_string,
3786 const char *delimiters, struct mg_str *v);
3787
3788/*
3789 * Decodes base64-encoded string `s`, `len` into the destination `dst`.
3790 * The destination has to have enough space to hold the decoded buffer.
3791 * Decoding stops either when all strings have been decoded or invalid an
3792 * character appeared.
3793 * Destination is '\0'-terminated.
3794 * Returns the number of decoded characters. On success, that should be equal
3795 * to `len`. On error (invalid character) the return value is smaller then
3796 * `len`.
3797 */
3798int mg_base64_decode(const unsigned char *s, int len, char *dst);
3799
3800/*
3801 * Base64-encode chunk of memory `src`, `src_len` into the destination `dst`.
3802 * Destination has to have enough space to hold encoded buffer.
3803 * Destination is '\0'-terminated.
3804 */
3805void mg_base64_encode(const unsigned char *src, int src_len, char *dst);
3806
3807#if MG_ENABLE_FILESYSTEM
3808/*
3809 * Performs a 64-bit `stat()` call against a given file.
3810 *
3811 * `path` should be UTF8 encoded.
3812 *
3813 * Return value is the same as for `stat()` syscall.
3814 */
3815int mg_stat(const char *path, cs_stat_t *st);
3816
3817/*
3818 * Opens the given file and returns a file stream.
3819 *
3820 * `path` and `mode` should be UTF8 encoded.
3821 *
3822 * Return value is the same as for the `fopen()` call.
3823 */
3824FILE *mg_fopen(const char *path, const char *mode);
3825
3826/*
3827 * Opens the given file and returns a file stream.
3828 *
3829 * `path` should be UTF8 encoded.
3830 *
3831 * Return value is the same as for the `open()` syscall.
3832 */
3833int mg_open(const char *path, int flag, int mode);
3834#endif /* MG_ENABLE_FILESYSTEM */
3835
3836#if MG_ENABLE_THREADS
3837/*
3838 * Starts a new detached thread.
3839 * Arguments and semantics are the same as pthead's `pthread_create()`.
3840 * `thread_func` is a thread function, `thread_func_param` is a parameter
3841 * that is passed to the thread function.
3842 */
3843void *mg_start_thread(void *(*thread_func)(void *), void *thread_func_param);
3844#endif
3845
3846void mg_set_close_on_exec(sock_t);
3847
3848#define MG_SOCK_STRINGIFY_IP 1
3849#define MG_SOCK_STRINGIFY_PORT 2
3850#define MG_SOCK_STRINGIFY_REMOTE 4
3851/*
3852 * Converts a connection's local or remote address into string.
3853 *
3854 * The `flags` parameter is a bit mask that controls the behaviour,
3855 * see `MG_SOCK_STRINGIFY_*` definitions.
3856 *
3857 * - MG_SOCK_STRINGIFY_IP - print IP address
3858 * - MG_SOCK_STRINGIFY_PORT - print port number
3859 * - MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address
3860 *
3861 * If both port number and IP address are printed, they are separated by `:`.
3862 * If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported.
3863 */
3864void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
3865 int flags);
3866#if MG_NET_IF == MG_NET_IF_SOCKET
3867/* Legacy interface. */
3868void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
3869#endif
3870
3871/*
3872 * Convert the socket's address into string.
3873 *
3874 * `flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT.
3875 */
3876void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
3877 int flags);
3878
3879#if MG_ENABLE_HEXDUMP
3880/*
3881 * Generates a human-readable hexdump of memory chunk.
3882 *
3883 * Takes a memory buffer `buf` of length `len` and creates a hex dump of that
3884 * buffer in `dst`. The generated output is a-la hexdump(1).
3885 * Returns the length of generated string, excluding terminating `\0`. If
3886 * returned length is bigger than `dst_len`, the overflow bytes are discarded.
3887 */
3888int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
3889
3890/*
3891 * Generates human-readable hexdump of the data sent or received by the
3892 * connection. `path` is a file name where hexdump should be written.
3893 * `num_bytes` is a number of bytes sent/received. `ev` is one of the `MG_*`
3894 * events sent to an event handler. This function is supposed to be called from
3895 * the event handler.
3896 */
3897void mg_hexdump_connection(struct mg_connection *nc, const char *path,
3898 const void *buf, int num_bytes, int ev);
3899#endif
3900
3901/*
3902 * Returns true if target platform is big endian.
3903 */
3904int mg_is_big_endian(void);
3905
3906/*
3907 * A helper function for traversing a comma separated list of values.
3908 * It returns a list pointer shifted to the next value or NULL if the end
3909 * of the list found.
3910 * The value is stored in a val vector. If the value has a form "x=y", then
3911 * eq_val vector is initialised to point to the "y" part, and val vector length
3912 * is adjusted to point only to "x".
3913 * If the list is just a comma separated list of entries, like "aa,bb,cc" then
3914 * `eq_val` will contain zero-length string.
3915 *
3916 * The purpose of this function is to parse comma separated string without
3917 * any copying/memory allocation.
3918 */
3919const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
3920 struct mg_str *eq_val);
3921
3922/*
3923 * Matches 0-terminated string (mg_match_prefix) or string with given length
3924 * mg_match_prefix_n against a glob pattern.
3925 *
3926 * Match is case-insensitive. Returns number of bytes matched, or -1 if no
3927 * match.
3928 */
3929int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
3930int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str);
3931
3932/*
3933 * Use with cs_base64_init/update/finish in order to write out base64 in chunks.
3934 */
3935void mg_mbuf_append_base64_putc(char ch, void *user_data);
3936
3937/*
3938 * Encode `len` bytes starting at `data` as base64 and append them to an mbuf.
3939 */
3940void mg_mbuf_append_base64(struct mbuf *mbuf, const void *data, size_t len);
3941
3942/*
3943 * Generate a Basic Auth header and appends it to buf.
3944 * If pass is NULL, then user is expected to contain the credentials pair
3945 * already encoded as `user:pass`.
3946 */
3947void mg_basic_auth_header(const char *user, const char *pass, struct mbuf *buf);
3948
3949#ifdef __cplusplus
3950}
3951#endif /* __cplusplus */
3952#endif /* CS_MONGOOSE_SRC_UTIL_H_ */
3953#ifdef MG_MODULE_LINES
3954#line 1 "mongoose/src/http.h"
3955#endif
3956/*
3957 * Copyright (c) 2014 Cesanta Software Limited
3958 * All rights reserved
3959 */
3960
3961/*
3962 * === Common API reference
3963 */
3964
3965#ifndef CS_MONGOOSE_SRC_HTTP_H_
3966#define CS_MONGOOSE_SRC_HTTP_H_
3967
3968#if MG_ENABLE_HTTP
3969
3970/* Amalgamated: #include "mongoose/src/net.h" */
3971/* Amalgamated: #include "common/mg_str.h" */
3972
3973#ifdef __cplusplus
3974extern "C" {
3975#endif /* __cplusplus */
3976
3977#ifndef MG_MAX_HTTP_HEADERS
3978#define MG_MAX_HTTP_HEADERS 20
3979#endif
3980
3981#ifndef MG_MAX_HTTP_REQUEST_SIZE
3982#define MG_MAX_HTTP_REQUEST_SIZE 1024
3983#endif
3984
3985#ifndef MG_MAX_PATH
3986#ifdef PATH_MAX
3987#define MG_MAX_PATH PATH_MAX
3988#else
3989#define MG_MAX_PATH 256
3990#endif
3991#endif
3992
3993#ifndef MG_MAX_HTTP_SEND_MBUF
3994#define MG_MAX_HTTP_SEND_MBUF 1024
3995#endif
3996
3997#ifndef MG_CGI_ENVIRONMENT_SIZE
3998#define MG_CGI_ENVIRONMENT_SIZE 8192
3999#endif
4000
4001/* HTTP message */
4002struct http_message {
4003 struct mg_str message; /* Whole message: request line + headers + body */
4004
4005 /* HTTP Request line (or HTTP response line) */
4006 struct mg_str method; /* "GET" */
4007 struct mg_str uri; /* "/my_file.html" */
4008 struct mg_str proto; /* "HTTP/1.1" -- for both request and response */
4009
4010 /* For responses, code and response status message are set */
4011 int resp_code;
4012 struct mg_str resp_status_msg;
4013
4014 /*
4015 * Query-string part of the URI. For example, for HTTP request
4016 * GET /foo/bar?param1=val1&param2=val2
4017 * | uri | query_string |
4018 *
4019 * Note that question mark character doesn't belong neither to the uri,
4020 * nor to the query_string
4021 */
4022 struct mg_str query_string;
4023
4024 /* Headers */
4025 struct mg_str header_names[MG_MAX_HTTP_HEADERS];
4026 struct mg_str header_values[MG_MAX_HTTP_HEADERS];
4027
4028 /* Message body */
4029 struct mg_str body; /* Zero-length for requests with no body */
4030};
4031
4032#if MG_ENABLE_HTTP_WEBSOCKET
4033/* WebSocket message */
4034struct websocket_message {
4035 unsigned char *data;
4036 size_t size;
4037 unsigned char flags;
4038};
4039#endif
4040
4041/* HTTP multipart part */
4042struct mg_http_multipart_part {
4043 const char *file_name;
4044 const char *var_name;
4045 struct mg_str data;
4046 int status; /* <0 on error */
4047 void *user_data;
4048};
4049
4050/* SSI call context */
4051struct mg_ssi_call_ctx {
4052 struct http_message *req; /* The request being processed. */
4053 struct mg_str file; /* Filesystem path of the file being processed. */
4054 struct mg_str arg; /* The argument passed to the tag: <!-- call arg -->. */
4055};
4056
4057/* HTTP and websocket events. void *ev_data is described in a comment. */
4058#define MG_EV_HTTP_REQUEST 100 /* struct http_message * */
4059#define MG_EV_HTTP_REPLY 101 /* struct http_message * */
4060#define MG_EV_HTTP_CHUNK 102 /* struct http_message * */
4061#define MG_EV_SSI_CALL 105 /* char * */
4062#define MG_EV_SSI_CALL_CTX 106 /* struct mg_ssi_call_ctx * */
4063
4064#if MG_ENABLE_HTTP_WEBSOCKET
4065#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* struct http_message * */
4066#define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112 /* NULL */
4067#define MG_EV_WEBSOCKET_FRAME 113 /* struct websocket_message * */
4068#define MG_EV_WEBSOCKET_CONTROL_FRAME 114 /* struct websocket_message * */
4069#endif
4070
4071#if MG_ENABLE_HTTP_STREAMING_MULTIPART
4072#define MG_EV_HTTP_MULTIPART_REQUEST 121 /* struct http_message */
4073#define MG_EV_HTTP_PART_BEGIN 122 /* struct mg_http_multipart_part */
4074#define MG_EV_HTTP_PART_DATA 123 /* struct mg_http_multipart_part */
4075#define MG_EV_HTTP_PART_END 124 /* struct mg_http_multipart_part */
4076/* struct mg_http_multipart_part */
4077#define MG_EV_HTTP_MULTIPART_REQUEST_END 125
4078#endif
4079
4080/*
4081 * Attaches a built-in HTTP event handler to the given connection.
4082 * The user-defined event handler will receive following extra events:
4083 *
4084 * - MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request
4085 * is passed as
4086 * `struct http_message` through the handler's `void *ev_data` pointer.
4087 * - MG_EV_HTTP_REPLY: The HTTP reply has arrived. The parsed HTTP reply is
4088 * passed as `struct http_message` through the handler's `void *ev_data`
4089 * pointer.
4090 * - MG_EV_HTTP_CHUNK: The HTTP chunked-encoding chunk has arrived.
4091 * The parsed HTTP reply is passed as `struct http_message` through the
4092 * handler's `void *ev_data` pointer. `http_message::body` would contain
4093 * incomplete, reassembled HTTP body.
4094 * It will grow with every new chunk that arrives, and it can
4095 * potentially consume a lot of memory. An event handler may process
4096 * the body as chunks are coming, and signal Mongoose to delete processed
4097 * body by setting `MG_F_DELETE_CHUNK` in `mg_connection::flags`. When
4098 * the last zero chunk is received,
4099 * Mongoose sends `MG_EV_HTTP_REPLY` event with
4100 * full reassembled body (if handler did not signal to delete chunks) or
4101 * with empty body (if handler did signal to delete chunks).
4102 * - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
4103 * handshake request. `ev_data` contains parsed HTTP request.
4104 * - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
4105 * handshake. `ev_data` is `NULL`.
4106 * - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
4107 * `struct websocket_message *`
4108 *
4109 * When compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART, Mongoose parses
4110 * multipart requests and splits them into separate events:
4111 * - MG_EV_HTTP_MULTIPART_REQUEST: Start of the request.
4112 * This event is sent before body is parsed. After this, the user
4113 * should expect a sequence of PART_BEGIN/DATA/END requests.
4114 * This is also the last time when headers and other request fields are
4115 * accessible.
4116 * - MG_EV_HTTP_PART_BEGIN: Start of a part of a multipart message.
4117 * Argument: mg_http_multipart_part with var_name and file_name set
4118 * (if present). No data is passed in this message.
4119 * - MG_EV_HTTP_PART_DATA: new portion of data from the multipart message.
4120 * Argument: mg_http_multipart_part. var_name and file_name are preserved,
4121 * data is available in mg_http_multipart_part.data.
4122 * - MG_EV_HTTP_PART_END: End of the current part. var_name, file_name are
4123 * the same, no data in the message. If status is 0, then the part is
4124 * properly terminated with a boundary, status < 0 means that connection
4125 * was terminated.
4126 * - MG_EV_HTTP_MULTIPART_REQUEST_END: End of the multipart request.
4127 * Argument: mg_http_multipart_part, var_name and file_name are NULL,
4128 * status = 0 means request was properly closed, < 0 means connection
4129 * was terminated (note: in this case both PART_END and REQUEST_END are
4130 * delivered).
4131 */
4132void mg_set_protocol_http_websocket(struct mg_connection *nc);
4133
4134#if MG_ENABLE_HTTP_WEBSOCKET
4135/*
4136 * Send websocket handshake to the server.
4137 *
4138 * `nc` must be a valid connection, connected to a server. `uri` is an URI
4139 * to fetch, extra_headers` is extra HTTP headers to send or `NULL`.
4140 *
4141 * This function is intended to be used by websocket client.
4142 *
4143 * Note that the Host header is mandatory in HTTP/1.1 and must be
4144 * included in `extra_headers`. `mg_send_websocket_handshake2` offers
4145 * a better API for that.
4146 *
4147 * Deprecated in favour of `mg_send_websocket_handshake2`
4148 */
4149void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri,
4150 const char *extra_headers);
4151
4152/*
4153 * Send websocket handshake to the server.
4154 *
4155 * `nc` must be a valid connection, connected to a server. `uri` is an URI
4156 * to fetch, `host` goes into the `Host` header, `protocol` goes into the
4157 * `Sec-WebSocket-Proto` header (NULL to omit), extra_headers` is extra HTTP
4158 * headers to send or `NULL`.
4159 *
4160 * This function is intended to be used by websocket client.
4161 */
4162void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path,
4163 const char *host, const char *protocol,
4164 const char *extra_headers);
4165
4166/* Like mg_send_websocket_handshake2 but also passes basic auth header */
4167void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path,
4168 const char *host, const char *protocol,
4169 const char *extra_headers, const char *user,
4170 const char *pass);
4171/*
4172 * Helper function that creates an outbound WebSocket connection.
4173 *
4174 * `url` is a URL to connect to. It must be properly URL-encoded, e.g. have
4175 * no spaces, etc. By default, `mg_connect_ws()` sends Connection and
4176 * Host headers. `extra_headers` is an extra HTTP header to send, e.g.
4177 * `"User-Agent: my-app\r\n"`.
4178 * If `protocol` is not NULL, then a `Sec-WebSocket-Protocol` header is sent.
4179 *
4180 * Examples:
4181 *
4182 * ```c
4183 * nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL,
4184 * NULL);
4185 * nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL,
4186 * NULL);
4187 * nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com",
4188 * "clubby.cesanta.com", NULL);
4189 * ```
4190 */
4191struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
4192 mg_event_handler_t event_handler,
4193 const char *url, const char *protocol,
4194 const char *extra_headers);
4195
4196/*
4197 * Helper function that creates an outbound WebSocket connection
4198 *
4199 * Mostly identical to `mg_connect_ws`, but allows to provide extra parameters
4200 * (for example, SSL parameters)
4201 */
4202struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
4203 mg_event_handler_t ev_handler,
4204 struct mg_connect_opts opts,
4205 const char *url, const char *protocol,
4206 const char *extra_headers);
4207
4208/*
4209 * Send WebSocket frame to the remote end.
4210 *
4211 * `op_and_flags` specifies the frame's type. It's one of:
4212 *
4213 * - WEBSOCKET_OP_CONTINUE
4214 * - WEBSOCKET_OP_TEXT
4215 * - WEBSOCKET_OP_BINARY
4216 * - WEBSOCKET_OP_CLOSE
4217 * - WEBSOCKET_OP_PING
4218 * - WEBSOCKET_OP_PONG
4219 *
4220 * Orred with one of the flags:
4221 *
4222 * - WEBSOCKET_DONT_FIN: Don't set the FIN flag on the frame to be sent.
4223 *
4224 * `data` and `data_len` contain frame data.
4225 */
4226void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
4227 const void *data, size_t data_len);
4228
4229/*
4230 * Sends multiple websocket frames.
4231 *
4232 * Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers.
4233 */
4234void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
4235 const struct mg_str *strings, int num_strings);
4236
4237/*
4238 * Sends WebSocket frame to the remote end.
4239 *
4240 * Like `mg_send_websocket_frame()`, but allows to create formatted messages
4241 * with `printf()`-like semantics.
4242 */
4243void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
4244 const char *fmt, ...);
4245
4246/* Websocket opcodes, from http://tools.ietf.org/html/rfc6455 */
4247#define WEBSOCKET_OP_CONTINUE 0
4248#define WEBSOCKET_OP_TEXT 1
4249#define WEBSOCKET_OP_BINARY 2
4250#define WEBSOCKET_OP_CLOSE 8
4251#define WEBSOCKET_OP_PING 9
4252#define WEBSOCKET_OP_PONG 10
4253
4254/*
4255 * If set causes the FIN flag to not be set on outbound
4256 * frames. This enables sending multiple fragments of a single
4257 * logical message.
4258 *
4259 * The WebSocket protocol mandates that if the FIN flag of a data
4260 * frame is not set, the next frame must be a WEBSOCKET_OP_CONTINUE.
4261 * The last frame must have the FIN bit set.
4262 *
4263 * Note that mongoose will automatically defragment incoming messages,
4264 * so this flag is used only on outbound messages.
4265 */
4266#define WEBSOCKET_DONT_FIN 0x100
4267
4268#endif /* MG_ENABLE_HTTP_WEBSOCKET */
4269
4270/*
4271 * Decodes a URL-encoded string.
4272 *
4273 * Source string is specified by (`src`, `src_len`), and destination is
4274 * (`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
4275 * `+` character is decoded as a blank space character. This function
4276 * guarantees to NUL-terminate the destination. If destination is too small,
4277 * then the source string is partially decoded and `-1` is returned. Otherwise,
4278 * a length of the decoded string is returned, not counting final NUL.
4279 */
4280int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
4281 int is_form_url_encoded);
4282
4283#ifdef __cplusplus
4284}
4285#endif /* __cplusplus */
4286
4287#endif /* MG_ENABLE_HTTP */
4288
4289#endif /* CS_MONGOOSE_SRC_HTTP_H_ */
4290#ifdef MG_MODULE_LINES
4291#line 1 "mongoose/src/http_server.h"
4292#endif
4293/*
4294 * === Server API reference
4295 */
4296
4297#ifndef CS_MONGOOSE_SRC_HTTP_SERVER_H_
4298#define CS_MONGOOSE_SRC_HTTP_SERVER_H_
4299
4300#if MG_ENABLE_HTTP
4301
4302#ifdef __cplusplus
4303extern "C" {
4304#endif /* __cplusplus */
4305
4306/*
4307 * Parses a HTTP message.
4308 *
4309 * `is_req` should be set to 1 if parsing a request, 0 if reply.
4310 *
4311 * Returns the number of bytes parsed. If HTTP message is
4312 * incomplete `0` is returned. On parse error, a negative number is returned.
4313 */
4314int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req);
4315
4316/*
4317 * Searches and returns the header `name` in parsed HTTP message `hm`.
4318 * If header is not found, NULL is returned. Example:
4319 *
4320 * struct mg_str *host_hdr = mg_get_http_header(hm, "Host");
4321 */
4322struct mg_str *mg_get_http_header(struct http_message *hm, const char *name);
4323
4324/*
4325 * Parses the HTTP header `hdr`. Finds variable `var_name` and stores its value
4326 * in the buffer `buf`, `buf_size`. Returns 0 if variable not found, non-zero
4327 * otherwise.
4328 *
4329 * This function is supposed to parse cookies, authentication headers, etc.
4330 * Example (error handling omitted):
4331 *
4332 * char user[20];
4333 * struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
4334 * mg_http_parse_header(hdr, "username", user, sizeof(user));
4335 *
4336 * Returns the length of the variable's value. If buffer is not large enough,
4337 * or variable not found, 0 is returned.
4338 */
4339int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
4340 size_t buf_size);
4341
4342/*
4343 * Gets and parses the Authorization: Basic header
4344 * Returns -1 if no Authorization header is found, or if
4345 * mg_parse_http_basic_auth
4346 * fails parsing the resulting header.
4347 */
4348int mg_get_http_basic_auth(struct http_message *hm, char *user, size_t user_len,
4349 char *pass, size_t pass_len);
4350
4351/*
4352 * Parses the Authorization: Basic header
4353 * Returns -1 iif the authorization type is not "Basic" or any other error such
4354 * as incorrectly encoded base64 user password pair.
4355 */
4356int mg_parse_http_basic_auth(struct mg_str *hdr, char *user, size_t user_len,
4357 char *pass, size_t pass_len);
4358
4359/*
4360 * Parses the buffer `buf`, `buf_len` that contains multipart form data chunks.
4361 * Stores the chunk name in a `var_name`, `var_name_len` buffer.
4362 * If a chunk is an uploaded file, then `file_name`, `file_name_len` is
4363 * filled with an uploaded file name. `chunk`, `chunk_len`
4364 * points to the chunk data.
4365 *
4366 * Return: number of bytes to skip to the next chunk or 0 if there are
4367 * no more chunks.
4368 *
4369 * Usage example:
4370 *
4371 * ```c
4372 * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
4373 * switch(ev) {
4374 * case MG_EV_HTTP_REQUEST: {
4375 * struct http_message *hm = (struct http_message *) ev_data;
4376 * char var_name[100], file_name[100];
4377 * const char *chunk;
4378 * size_t chunk_len, n1, n2;
4379 *
4380 * n1 = n2 = 0;
4381 * while ((n2 = mg_parse_multipart(hm->body.p + n1,
4382 * hm->body.len - n1,
4383 * var_name, sizeof(var_name),
4384 * file_name, sizeof(file_name),
4385 * &chunk, &chunk_len)) > 0) {
4386 * printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n",
4387 * var_name, file_name, (int) chunk_len,
4388 * (int) chunk_len, chunk);
4389 * n1 += n2;
4390 * }
4391 * }
4392 * break;
4393 * ```
4394 */
4395size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
4396 size_t var_name_len, char *file_name,
4397 size_t file_name_len, const char **chunk,
4398 size_t *chunk_len);
4399
4400/*
4401 * Fetches a HTTP form variable.
4402 *
4403 * Fetches a variable `name` from a `buf` into a buffer specified by `dst`,
4404 * `dst_len`. The destination is always zero-terminated. Returns the length of
4405 * a fetched variable. If not found, 0 is returned. `buf` must be valid
4406 * url-encoded buffer. If destination is too small, `-1` is returned.
4407 */
4408int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
4409 size_t dst_len);
4410
4411#if MG_ENABLE_FILESYSTEM
4412/*
4413 * This structure defines how `mg_serve_http()` works.
4414 * Best practice is to set only required settings, and leave the rest as NULL.
4415 */
4416struct mg_serve_http_opts {
4417 /* Path to web root directory */
4418 const char *document_root;
4419
4420 /* List of index files. Default is "" */
4421 const char *index_files;
4422
4423 /*
4424 * Leave as NULL to disable authentication.
4425 * To enable directory protection with authentication, set this to ".htpasswd"
4426 * Then, creating ".htpasswd" file in any directory automatically protects
4427 * it with digest authentication.
4428 * Use `mongoose` web server binary, or `htdigest` Apache utility to
4429 * create/manipulate passwords file.
4430 * Make sure `auth_domain` is set to a valid domain name.
4431 */
4432 const char *per_directory_auth_file;
4433
4434 /* Authorization domain (domain name of this web server) */
4435 const char *auth_domain;
4436
4437 /*
4438 * Leave as NULL to disable authentication.
4439 * Normally, only selected directories in the document root are protected.
4440 * If absolutely every access to the web server needs to be authenticated,
4441 * regardless of the URI, set this option to the path to the passwords file.
4442 * Format of that file is the same as ".htpasswd" file. Make sure that file
4443 * is located outside document root to prevent people fetching it.
4444 */
4445 const char *global_auth_file;
4446
4447 /* Set to "no" to disable directory listing. Enabled by default. */
4448 const char *enable_directory_listing;
4449
4450 /*
4451 * SSI files pattern. If not set, "**.shtml$|**.shtm$" is used.
4452 *
4453 * All files that match ssi_pattern are treated as SSI.
4454 *
4455 * Server Side Includes (SSI) is a simple interpreted server-side scripting
4456 * language which is most commonly used to include the contents of a file
4457 * into a web page. It can be useful when it is desirable to include a common
4458 * piece of code throughout a website, for example, headers and footers.
4459 *
4460 * In order for a webpage to recognize an SSI-enabled HTML file, the
4461 * filename should end with a special extension, by default the extension
4462 * should be either .shtml or .shtm
4463 *
4464 * Unknown SSI directives are silently ignored by Mongoose. Currently,
4465 * the following SSI directives are supported:
4466 * &lt;!--#include FILE_TO_INCLUDE --&gt;
4467 * &lt;!--#exec "COMMAND_TO_EXECUTE" --&gt;
4468 * &lt;!--#call COMMAND --&gt;
4469 *
4470 * Note that &lt;!--#include ...> directive supports three path
4471 *specifications:
4472 *
4473 * &lt;!--#include virtual="path" --&gt; Path is relative to web server root
4474 * &lt;!--#include abspath="path" --&gt; Path is absolute or relative to the
4475 * web server working dir
4476 * &lt;!--#include file="path" --&gt;, Path is relative to current document
4477 * &lt;!--#include "path" --&gt;
4478 *
4479 * The include directive may be used to include the contents of a file or
4480 * the result of running a CGI script.
4481 *
4482 * The exec directive is used to execute
4483 * a command on a server, and show command's output. Example:
4484 *
4485 * &lt;!--#exec "ls -l" --&gt;
4486 *
4487 * The call directive is a way to invoke a C handler from the HTML page.
4488 * On each occurence of &lt;!--#call COMMAND OPTIONAL_PARAMS> directive,
4489 * Mongoose calls a registered event handler with MG_EV_SSI_CALL event,
4490 * and event parameter will point to the COMMAND OPTIONAL_PARAMS string.
4491 * An event handler can output any text, for example by calling
4492 * `mg_printf()`. This is a flexible way of generating a web page on
4493 * server side by calling a C event handler. Example:
4494 *
4495 * &lt;!--#call foo --&gt; ... &lt;!--#call bar --&gt;
4496 *
4497 * In the event handler:
4498 * case MG_EV_SSI_CALL: {
4499 * const char *param = (const char *) ev_data;
4500 * if (strcmp(param, "foo") == 0) {
4501 * mg_printf(c, "hello from foo");
4502 * } else if (strcmp(param, "bar") == 0) {
4503 * mg_printf(c, "hello from bar");
4504 * }
4505 * break;
4506 * }
4507 */
4508 const char *ssi_pattern;
4509
4510 /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */
4511 const char *ip_acl;
4512
4513#if MG_ENABLE_HTTP_URL_REWRITES
4514 /* URL rewrites.
4515 *
4516 * Comma-separated list of `uri_pattern=url_file_or_directory_path` rewrites.
4517 * When HTTP request is received, Mongoose constructs a file name from the
4518 * requested URI by combining `document_root` and the URI. However, if the
4519 * rewrite option is used and `uri_pattern` matches requested URI, then
4520 * `document_root` is ignored. Instead, `url_file_or_directory_path` is used,
4521 * which should be a full path name or a path relative to the web server's
4522 * current working directory. It can also be an URI (http:// or https://)
4523 * in which case mongoose will behave as a reverse proxy for that destination.
4524 *
4525 * Note that `uri_pattern`, as all Mongoose patterns, is a prefix pattern.
4526 *
4527 * If uri_pattern starts with `@` symbol, then Mongoose compares it with the
4528 * HOST header of the request. If they are equal, Mongoose sets document root
4529 * to `file_or_directory_path`, implementing virtual hosts support.
4530 * Example: `@foo.com=/document/root/for/foo.com`
4531 *
4532 * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with
4533 * the listening port. If they match, then Mongoose issues a 301 redirect.
4534 * For example, to redirect all HTTP requests to the
4535 * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is
4536 * automatically appended to the redirect location.
4537 */
4538 const char *url_rewrites;
4539#endif
4540
4541 /* DAV document root. If NULL, DAV requests are going to fail. */
4542 const char *dav_document_root;
4543
4544 /*
4545 * DAV passwords file. If NULL, DAV requests are going to fail.
4546 * If passwords file is set to "-", then DAV auth is disabled.
4547 */
4548 const char *dav_auth_file;
4549
4550 /* Glob pattern for the files to hide. */
4551 const char *hidden_file_pattern;
4552
4553 /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */
4554 const char *cgi_file_pattern;
4555
4556 /* If not NULL, ignore CGI script hashbang and use this interpreter */
4557 const char *cgi_interpreter;
4558
4559 /*
4560 * Comma-separated list of Content-Type overrides for path suffixes, e.g.
4561 * ".txt=text/plain; charset=utf-8,.c=text/plain"
4562 */
4563 const char *custom_mime_types;
4564
4565 /*
4566 * Extra HTTP headers to add to each server response.
4567 * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *".
4568 */
4569 const char *extra_headers;
4570};
4571
4572/*
4573 * Serves given HTTP request according to the `options`.
4574 *
4575 * Example code snippet:
4576 *
4577 * ```c
4578 * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
4579 * struct http_message *hm = (struct http_message *) ev_data;
4580 * struct mg_serve_http_opts opts = { .document_root = "/var/www" }; // C99
4581 *
4582 * switch (ev) {
4583 * case MG_EV_HTTP_REQUEST:
4584 * mg_serve_http(nc, hm, opts);
4585 * break;
4586 * default:
4587 * break;
4588 * }
4589 * }
4590 * ```
4591 */
4592void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
4593 struct mg_serve_http_opts opts);
4594
4595/*
4596 * Serves a specific file with a given MIME type and optional extra headers.
4597 *
4598 * Example code snippet:
4599 *
4600 * ```c
4601 * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
4602 * switch (ev) {
4603 * case MG_EV_HTTP_REQUEST: {
4604 * struct http_message *hm = (struct http_message *) ev_data;
4605 * mg_http_serve_file(nc, hm, "file.txt",
4606 * mg_mk_str("text/plain"), mg_mk_str(""));
4607 * break;
4608 * }
4609 * ...
4610 * }
4611 * }
4612 * ```
4613 */
4614void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm,
4615 const char *path, const struct mg_str mime_type,
4616 const struct mg_str extra_headers);
4617
4618#if MG_ENABLE_HTTP_STREAMING_MULTIPART
4619
4620/* Callback prototype for `mg_file_upload_handler()`. */
4621typedef struct mg_str (*mg_fu_fname_fn)(struct mg_connection *nc,
4622 struct mg_str fname);
4623
4624/*
4625 * File upload handler.
4626 * This handler can be used to implement file uploads with minimum code.
4627 * This handler will process MG_EV_HTTP_PART_* events and store file data into
4628 * a local file.
4629 * `local_name_fn` will be invoked with whatever name was provided by the client
4630 * and will expect the name of the local file to open. A return value of NULL
4631 * will abort file upload (client will get a "403 Forbidden" response). If
4632 * non-null, the returned string must be heap-allocated and will be freed by
4633 * the caller.
4634 * Exception: it is ok to return the same string verbatim.
4635 *
4636 * Example:
4637 *
4638 * ```c
4639 * struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
4640 * // Just return the same filename. Do not actually do this except in test!
4641 * // fname is user-controlled and needs to be sanitized.
4642 * return fname;
4643 * }
4644 * void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
4645 * switch (ev) {
4646 * ...
4647 * case MG_EV_HTTP_PART_BEGIN:
4648 * case MG_EV_HTTP_PART_DATA:
4649 * case MG_EV_HTTP_PART_END:
4650 * mg_file_upload_handler(nc, ev, ev_data, upload_fname);
4651 * break;
4652 * }
4653 * }
4654 * ```
4655 */
4656void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
4657 mg_fu_fname_fn local_name_fn);
4658#endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
4659#endif /* MG_ENABLE_FILESYSTEM */
4660
4661/*
4662 * Registers a callback for a specified http endpoint
4663 * Note: if callback is registered it is called instead of the
4664 * callback provided in mg_bind
4665 *
4666 * Example code snippet:
4667 *
4668 * ```c
4669 * static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
4670 * (void) ev; (void) ev_data;
4671 * mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
4672 * nc->flags |= MG_F_SEND_AND_CLOSE;
4673 * }
4674 *
4675 * static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
4676 * (void) ev; (void) ev_data;
4677 * mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
4678 * nc->flags |= MG_F_SEND_AND_CLOSE;
4679 * }
4680 *
4681 * void init() {
4682 * nc = mg_bind(&mgr, local_addr, cb1);
4683 * mg_register_http_endpoint(nc, "/hello1", handle_hello1);
4684 * mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
4685 * }
4686 * ```
4687 */
4688void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
4689 mg_event_handler_t handler);
4690
4691/*
4692 * Authenticates a HTTP request against an opened password file.
4693 * Returns 1 if authenticated, 0 otherwise.
4694 */
4695int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
4696 FILE *fp);
4697
4698/*
4699 * Sends buffer `buf` of size `len` to the client using chunked HTTP encoding.
4700 * This function sends the buffer size as hex number + newline first, then
4701 * the buffer itself, then the newline. For example,
4702 * `mg_send_http_chunk(nc, "foo", 3)` whill append the `3\r\nfoo\r\n` string
4703 * to the `nc->send_mbuf` output IO buffer.
4704 *
4705 * NOTE: The HTTP header "Transfer-Encoding: chunked" should be sent prior to
4706 * using this function.
4707 *
4708 * NOTE: do not forget to send an empty chunk at the end of the response,
4709 * to tell the client that everything was sent. Example:
4710 *
4711 * ```
4712 * mg_printf_http_chunk(nc, "%s", "my response!");
4713 * mg_send_http_chunk(nc, "", 0); // Tell the client we're finished
4714 * ```
4715 */
4716void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len);
4717
4718/*
4719 * Sends a printf-formatted HTTP chunk.
4720 * Functionality is similar to `mg_send_http_chunk()`.
4721 */
4722void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
4723
4724/*
4725 * Sends the response status line.
4726 * If `extra_headers` is not NULL, then `extra_headers` are also sent
4727 * after the reponse line. `extra_headers` must NOT end end with new line.
4728 * Example:
4729 *
4730 * mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
4731 *
4732 * Will result in:
4733 *
4734 * HTTP/1.1 200 OK\r\n
4735 * Access-Control-Allow-Origin: *\r\n
4736 */
4737void mg_send_response_line(struct mg_connection *nc, int status_code,
4738 const char *extra_headers);
4739
4740/*
4741 * Sends an error response. If reason is NULL, the message will be inferred
4742 * from the error code (if supported).
4743 */
4744void mg_http_send_error(struct mg_connection *nc, int code, const char *reason);
4745
4746/*
4747 * Sends a redirect response.
4748 * `status_code` should be either 301 or 302 and `location` point to the
4749 * new location.
4750 * If `extra_headers` is not empty, then `extra_headers` are also sent
4751 * after the reponse line. `extra_headers` must NOT end end with new line.
4752 *
4753 * Example:
4754 *
4755 * mg_http_send_redirect(nc, 302, mg_mk_str("/login"), mg_mk_str(NULL));
4756 */
4757void mg_http_send_redirect(struct mg_connection *nc, int status_code,
4758 const struct mg_str location,
4759 const struct mg_str extra_headers);
4760
4761/*
4762 * Sends the response line and headers.
4763 * This function sends the response line with the `status_code`, and
4764 * automatically
4765 * sends one header: either "Content-Length" or "Transfer-Encoding".
4766 * If `content_length` is negative, then "Transfer-Encoding: chunked" header
4767 * is sent, otherwise, "Content-Length" header is sent.
4768 *
4769 * NOTE: If `Transfer-Encoding` is `chunked`, then message body must be sent
4770 * using `mg_send_http_chunk()` or `mg_printf_http_chunk()` functions.
4771 * Otherwise, `mg_send()` or `mg_printf()` must be used.
4772 * Extra headers could be set through `extra_headers`. Note `extra_headers`
4773 * must NOT be terminated by a new line.
4774 */
4775void mg_send_head(struct mg_connection *n, int status_code,
4776 int64_t content_length, const char *extra_headers);
4777
4778/*
4779 * Sends a printf-formatted HTTP chunk, escaping HTML tags.
4780 */
4781void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...);
4782
4783#if MG_ENABLE_HTTP_URL_REWRITES
4784/*
4785 * Proxies a given request to a given upstream http server. The path prefix
4786 * in `mount` will be stripped of the path requested to the upstream server,
4787 * e.g. if mount is /api and upstream is http://localhost:8001/foo
4788 * then an incoming request to /api/bar will cause a request to
4789 * http://localhost:8001/foo/bar
4790 *
4791 * EXPERIMENTAL API. Please use http_serve_http + url_rewrites if a static
4792 * mapping is good enough.
4793 */
4794void mg_http_reverse_proxy(struct mg_connection *nc,
4795 const struct http_message *hm, struct mg_str mount,
4796 struct mg_str upstream);
4797#endif
4798
4799#ifdef __cplusplus
4800}
4801#endif /* __cplusplus */
4802
4803#endif /* MG_ENABLE_HTTP */
4804
4805#endif /* CS_MONGOOSE_SRC_HTTP_SERVER_H_ */
4806#ifdef MG_MODULE_LINES
4807#line 1 "mongoose/src/http_client.h"
4808#endif
4809/*
4810 * === Client API reference
4811 */
4812
4813#ifndef CS_MONGOOSE_SRC_HTTP_CLIENT_H_
4814#define CS_MONGOOSE_SRC_HTTP_CLIENT_H_
4815
4816#ifdef __cplusplus
4817extern "C" {
4818#endif /* __cplusplus */
4819
4820/*
4821 * Helper function that creates an outbound HTTP connection.
4822 *
4823 * `url` is the URL to fetch. It must be properly URL-encoded, e.g. have
4824 * no spaces, etc. By default, `mg_connect_http()` sends the Connection and
4825 * Host headers. `extra_headers` is an extra HTTP header to send, e.g.
4826 * `"User-Agent: my-app\r\n"`.
4827 * If `post_data` is NULL, then a GET request is created. Otherwise, a POST
4828 * request is created with the specified POST data. Note that if the data being
4829 * posted is a form submission, the `Content-Type` header should be set
4830 * accordingly (see example below).
4831 *
4832 * Examples:
4833 *
4834 * ```c
4835 * nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL,
4836 * NULL);
4837 * nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL);
4838 * nc3 = mg_connect_http(
4839 * mgr, ev_handler_1, "my_server:8000/form_submit/",
4840 * "Content-Type: application/x-www-form-urlencoded\r\n",
4841 * "var_1=value_1&var_2=value_2");
4842 * ```
4843 */
4844struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
4845 mg_event_handler_t event_handler,
4846 const char *url,
4847 const char *extra_headers,
4848 const char *post_data);
4849
4850/*
4851 * Helper function that creates an outbound HTTP connection.
4852 *
4853 * Mostly identical to mg_connect_http, but allows you to provide extra
4854 *parameters
4855 * (for example, SSL parameters)
4856 */
4857struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
4858 mg_event_handler_t ev_handler,
4859 struct mg_connect_opts opts,
4860 const char *url,
4861 const char *extra_headers,
4862 const char *post_data);
4863
4864/* Creates digest authentication header for a client request. */
4865int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
4866 const char *method, const char *uri,
4867 const char *auth_domain, const char *user,
4868 const char *passwd);
4869
4870#ifdef __cplusplus
4871}
4872#endif /* __cplusplus */
4873#endif /* CS_MONGOOSE_SRC_HTTP_CLIENT_H_ */
4874#ifdef MG_MODULE_LINES
4875#line 1 "mongoose/src/mqtt.h"
4876#endif
4877/*
4878 * Copyright (c) 2014 Cesanta Software Limited
4879 * All rights reserved
4880 * This software is dual-licensed: you can redistribute it and/or modify
4881 * it under the terms of the GNU General Public License version 2 as
4882 * published by the Free Software Foundation. For the terms of this
4883 * license, see <http://www.gnu.org/licenses/>.
4884 *
4885 * You are free to use this software under the terms of the GNU General
4886 * Public License, but WITHOUT ANY WARRANTY; without even the implied
4887 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4888 * See the GNU General Public License for more details.
4889 *
4890 * Alternatively, you can license this software under a commercial
4891 * license, as set out in <https://www.cesanta.com/license>.
4892 */
4893
4894/*
4895 * === MQTT API reference
4896 */
4897
4898#ifndef CS_MONGOOSE_SRC_MQTT_H_
4899#define CS_MONGOOSE_SRC_MQTT_H_
4900
4901/* Amalgamated: #include "mongoose/src/net.h" */
4902
4903struct mg_mqtt_message {
4904 int cmd;
4905 int qos;
4906 struct mg_str topic;
4907 struct mg_str payload;
4908
4909 uint8_t connack_ret_code; /* connack */
4910 uint16_t message_id; /* puback */
4911
4912 /* connect */
4913 uint8_t protocol_version;
4914 uint8_t connect_flags;
4915 uint16_t keep_alive_timer;
4916 struct mg_str protocol_name;
4917 struct mg_str client_id;
4918 struct mg_str will_topic;
4919 struct mg_str will_message;
4920 struct mg_str user_name;
4921 struct mg_str password;
4922};
4923
4924struct mg_mqtt_topic_expression {
4925 const char *topic;
4926 uint8_t qos;
4927};
4928
4929struct mg_send_mqtt_handshake_opts {
4930 unsigned char flags; /* connection flags */
4931 uint16_t keep_alive;
4932 const char *will_topic;
4933 const char *will_message;
4934 const char *user_name;
4935 const char *password;
4936};
4937
4938/* mg_mqtt_proto_data should be in header to allow external access to it */
4939struct mg_mqtt_proto_data {
4940 uint16_t keep_alive;
4941};
4942
4943/* Message types */
4944#define MG_MQTT_CMD_CONNECT 1
4945#define MG_MQTT_CMD_CONNACK 2
4946#define MG_MQTT_CMD_PUBLISH 3
4947#define MG_MQTT_CMD_PUBACK 4
4948#define MG_MQTT_CMD_PUBREC 5
4949#define MG_MQTT_CMD_PUBREL 6
4950#define MG_MQTT_CMD_PUBCOMP 7
4951#define MG_MQTT_CMD_SUBSCRIBE 8
4952#define MG_MQTT_CMD_SUBACK 9
4953#define MG_MQTT_CMD_UNSUBSCRIBE 10
4954#define MG_MQTT_CMD_UNSUBACK 11
4955#define MG_MQTT_CMD_PINGREQ 12
4956#define MG_MQTT_CMD_PINGRESP 13
4957#define MG_MQTT_CMD_DISCONNECT 14
4958
4959/* MQTT event types */
4960#define MG_MQTT_EVENT_BASE 200
4961#define MG_EV_MQTT_CONNECT (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_CONNECT)
4962#define MG_EV_MQTT_CONNACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_CONNACK)
4963#define MG_EV_MQTT_PUBLISH (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBLISH)
4964#define MG_EV_MQTT_PUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBACK)
4965#define MG_EV_MQTT_PUBREC (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBREC)
4966#define MG_EV_MQTT_PUBREL (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBREL)
4967#define MG_EV_MQTT_PUBCOMP (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBCOMP)
4968#define MG_EV_MQTT_SUBSCRIBE (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_SUBSCRIBE)
4969#define MG_EV_MQTT_SUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_SUBACK)
4970#define MG_EV_MQTT_UNSUBSCRIBE (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_UNSUBSCRIBE)
4971#define MG_EV_MQTT_UNSUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_UNSUBACK)
4972#define MG_EV_MQTT_PINGREQ (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PINGREQ)
4973#define MG_EV_MQTT_PINGRESP (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PINGRESP)
4974#define MG_EV_MQTT_DISCONNECT (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_DISCONNECT)
4975
4976/* Message flags */
4977#define MG_MQTT_RETAIN 0x1
4978#define MG_MQTT_DUP 0x4
4979#define MG_MQTT_QOS(qos) ((qos) << 1)
4980#define MG_MQTT_GET_QOS(flags) (((flags) &0x6) >> 1)
4981#define MG_MQTT_SET_QOS(flags, qos) (flags) = ((flags) & ~0x6) | ((qos) << 1)
4982
4983/* Connection flags */
4984#define MG_MQTT_CLEAN_SESSION 0x02
4985#define MG_MQTT_HAS_WILL 0x04
4986#define MG_MQTT_WILL_RETAIN 0x20
4987#define MG_MQTT_HAS_PASSWORD 0x40
4988#define MG_MQTT_HAS_USER_NAME 0x80
4989#define MG_MQTT_GET_WILL_QOS(flags) (((flags) &0x18) >> 3)
4990#define MG_MQTT_SET_WILL_QOS(flags, qos) \
4991 (flags) = ((flags) & ~0x18) | ((qos) << 3)
4992
4993/* CONNACK return codes */
4994#define MG_EV_MQTT_CONNACK_ACCEPTED 0
4995#define MG_EV_MQTT_CONNACK_UNACCEPTABLE_VERSION 1
4996#define MG_EV_MQTT_CONNACK_IDENTIFIER_REJECTED 2
4997#define MG_EV_MQTT_CONNACK_SERVER_UNAVAILABLE 3
4998#define MG_EV_MQTT_CONNACK_BAD_AUTH 4
4999#define MG_EV_MQTT_CONNACK_NOT_AUTHORIZED 5
5000
5001#ifdef __cplusplus
5002extern "C" {
5003#endif /* __cplusplus */
5004
5005/*
5006 * Attaches a built-in MQTT event handler to the given connection.
5007 *
5008 * The user-defined event handler will receive following extra events:
5009 *
5010 * - MG_EV_MQTT_CONNACK
5011 * - MG_EV_MQTT_PUBLISH
5012 * - MG_EV_MQTT_PUBACK
5013 * - MG_EV_MQTT_PUBREC
5014 * - MG_EV_MQTT_PUBREL
5015 * - MG_EV_MQTT_PUBCOMP
5016 * - MG_EV_MQTT_SUBACK
5017 */
5018void mg_set_protocol_mqtt(struct mg_connection *nc);
5019
5020/* Sends an MQTT handshake. */
5021void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);
5022
5023/* Sends an MQTT handshake with optional parameters. */
5024void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
5025 struct mg_send_mqtt_handshake_opts);
5026
5027/* Publishes a message to a given topic. */
5028void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
5029 uint16_t message_id, int flags, const void *data,
5030 size_t len);
5031
5032/* Subscribes to a bunch of topics. */
5033void mg_mqtt_subscribe(struct mg_connection *nc,
5034 const struct mg_mqtt_topic_expression *topics,
5035 size_t topics_len, uint16_t message_id);
5036
5037/* Unsubscribes from a bunch of topics. */
5038void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
5039 size_t topics_len, uint16_t message_id);
5040
5041/* Sends a DISCONNECT command. */
5042void mg_mqtt_disconnect(struct mg_connection *nc);
5043
5044/* Sends a CONNACK command with a given `return_code`. */
5045void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);
5046
5047/* Sends a PUBACK command with a given `message_id`. */
5048void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);
5049
5050/* Sends a PUBREC command with a given `message_id`. */
5051void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);
5052
5053/* Sends a PUBREL command with a given `message_id`. */
5054void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);
5055
5056/* Sends a PUBCOMP command with a given `message_id`. */
5057void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);
5058
5059/*
5060 * Sends a SUBACK command with a given `message_id`
5061 * and a sequence of granted QoSs.
5062 */
5063void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
5064 uint16_t message_id);
5065
5066/* Sends a UNSUBACK command with a given `message_id`. */
5067void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);
5068
5069/* Sends a PINGREQ command. */
5070void mg_mqtt_ping(struct mg_connection *nc);
5071
5072/* Sends a PINGRESP command. */
5073void mg_mqtt_pong(struct mg_connection *nc);
5074
5075/*
5076 * Extracts the next topic expression from a SUBSCRIBE command payload.
5077 *
5078 * The topic expression name will point to a string in the payload buffer.
5079 * Returns the pos of the next topic expression or -1 when the list
5080 * of topics is exhausted.
5081 */
5082int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
5083 struct mg_str *topic, uint8_t *qos, int pos);
5084
5085#ifdef __cplusplus
5086}
5087#endif /* __cplusplus */
5088
5089#endif /* CS_MONGOOSE_SRC_MQTT_H_ */
5090#ifdef MG_MODULE_LINES
5091#line 1 "mongoose/src/mqtt_server.h"
5092#endif
5093/*
5094 * Copyright (c) 2014 Cesanta Software Limited
5095 * All rights reserved
5096 * This software is dual-licensed: you can redistribute it and/or modify
5097 * it under the terms of the GNU General Public License version 2 as
5098 * published by the Free Software Foundation. For the terms of this
5099 * license, see <http://www.gnu.org/licenses/>.
5100 *
5101 * You are free to use this software under the terms of the GNU General
5102 * Public License, but WITHOUT ANY WARRANTY; without even the implied
5103 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5104 * See the GNU General Public License for more details.
5105 *
5106 * Alternatively, you can license this software under a commercial
5107 * license, as set out in <https://www.cesanta.com/license>.
5108 */
5109
5110/*
5111 * === MQTT Server API reference
5112 */
5113
5114#ifndef CS_MONGOOSE_SRC_MQTT_BROKER_H_
5115#define CS_MONGOOSE_SRC_MQTT_BROKER_H_
5116
5117#if MG_ENABLE_MQTT_BROKER
5118
5119/* Amalgamated: #include "common/queue.h" */
5120/* Amalgamated: #include "mongoose/src/mqtt.h" */
5121
5122#ifdef __cplusplus
5123extern "C" {
5124#endif /* __cplusplus */
5125
5126#define MG_MQTT_MAX_SESSION_SUBSCRIPTIONS 512;
5127
5128struct mg_mqtt_broker;
5129
5130/* MQTT session (Broker side). */
5131struct mg_mqtt_session {
5132 struct mg_mqtt_broker *brk; /* Broker */
5133 LIST_ENTRY(mg_mqtt_session) link; /* mg_mqtt_broker::sessions linkage */
5134 struct mg_connection *nc; /* Connection with the client */
5135 size_t num_subscriptions; /* Size of `subscriptions` array */
5136 void *user_data; /* User data */
5137 struct mg_mqtt_topic_expression *subscriptions;
5138};
5139
5140/* MQTT broker. */
5141struct mg_mqtt_broker {
5142 LIST_HEAD(_mg_sesshead, mg_mqtt_session) sessions; /* Session list */
5143 void *user_data; /* User data */
5144};
5145
5146/* Initialises a MQTT broker. */
5147void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);
5148
5149/*
5150 * Processes a MQTT broker message.
5151 *
5152 * The listening connection expects a pointer to an initialised
5153 * `mg_mqtt_broker` structure in the `user_data` field.
5154 *
5155 * Basic usage:
5156 *
5157 * ```c
5158 * mg_mqtt_broker_init(&brk, NULL);
5159 *
5160 * if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
5161 * // fail;
5162 * }
5163 * nc->user_data = &brk;
5164 * ```
5165 *
5166 * New incoming connections will receive a `mg_mqtt_session` structure
5167 * in the connection `user_data`. The original `user_data` will be stored
5168 * in the `user_data` field of the session structure. This allows the user
5169 * handler to store user data before `mg_mqtt_broker` creates the session.
5170 *
5171 * Since only the MG_EV_ACCEPT message is processed by the listening socket,
5172 * for most events the `user_data` will thus point to a `mg_mqtt_session`.
5173 */
5174void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);
5175
5176/*
5177 * Iterates over all MQTT session connections. Example:
5178 *
5179 * ```c
5180 * struct mg_mqtt_session *s;
5181 * for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
5182 * // Do something
5183 * }
5184 * ```
5185 */
5186struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
5187 struct mg_mqtt_session *s);
5188
5189#ifdef __cplusplus
5190}
5191#endif /* __cplusplus */
5192
5193#endif /* MG_ENABLE_MQTT_BROKER */
5194#endif /* CS_MONGOOSE_SRC_MQTT_BROKER_H_ */
5195#ifdef MG_MODULE_LINES
5196#line 1 "mongoose/src/dns.h"
5197#endif
5198/*
5199 * Copyright (c) 2014 Cesanta Software Limited
5200 * All rights reserved
5201 */
5202
5203/*
5204 * === DNS API reference
5205 */
5206
5207#ifndef CS_MONGOOSE_SRC_DNS_H_
5208#define CS_MONGOOSE_SRC_DNS_H_
5209
5210/* Amalgamated: #include "mongoose/src/net.h" */
5211
5212#ifdef __cplusplus
5213extern "C" {
5214#endif /* __cplusplus */
5215
5216#define MG_DNS_A_RECORD 0x01 /* Lookup IP address */
5217#define MG_DNS_CNAME_RECORD 0x05 /* Lookup CNAME */
5218#define MG_DNS_PTR_RECORD 0x0c /* Lookup PTR */
5219#define MG_DNS_TXT_RECORD 0x10 /* Lookup TXT */
5220#define MG_DNS_AAAA_RECORD 0x1c /* Lookup IPv6 address */
5221#define MG_DNS_SRV_RECORD 0x21 /* Lookup SRV */
5222#define MG_DNS_MX_RECORD 0x0f /* Lookup mail server for domain */
5223
5224#define MG_MAX_DNS_QUESTIONS 32
5225#define MG_MAX_DNS_ANSWERS 32
5226
5227#define MG_DNS_MESSAGE 100 /* High-level DNS message event */
5228
5229enum mg_dns_resource_record_kind {
5230 MG_DNS_INVALID_RECORD = 0,
5231 MG_DNS_QUESTION,
5232 MG_DNS_ANSWER
5233};
5234
5235/* DNS resource record. */
5236struct mg_dns_resource_record {
5237 struct mg_str name; /* buffer with compressed name */
5238 int rtype;
5239 int rclass;
5240 int ttl;
5241 enum mg_dns_resource_record_kind kind;
5242 struct mg_str rdata; /* protocol data (can be a compressed name) */
5243};
5244
5245/* DNS message (request and response). */
5246struct mg_dns_message {
5247 struct mg_str pkt; /* packet body */
5248 uint16_t flags;
5249 uint16_t transaction_id;
5250 int num_questions;
5251 int num_answers;
5252 struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
5253 struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
5254};
5255
5256struct mg_dns_resource_record *mg_dns_next_record(
5257 struct mg_dns_message *msg, int query, struct mg_dns_resource_record *prev);
5258
5259/*
5260 * Parses the record data from a DNS resource record.
5261 *
5262 * - A: struct in_addr *ina
5263 * - AAAA: struct in6_addr *ina
5264 * - CNAME: char buffer
5265 *
5266 * Returns -1 on error.
5267 *
5268 * TODO(mkm): MX
5269 */
5270int mg_dns_parse_record_data(struct mg_dns_message *msg,
5271 struct mg_dns_resource_record *rr, void *data,
5272 size_t data_len);
5273
5274/*
5275 * Sends a DNS query to the remote end.
5276 */
5277void mg_send_dns_query(struct mg_connection *nc, const char *name,
5278 int query_type);
5279
5280/*
5281 * Inserts a DNS header to an IO buffer.
5282 *
5283 * Returns the number of bytes inserted.
5284 */
5285int mg_dns_insert_header(struct mbuf *io, size_t pos,
5286 struct mg_dns_message *msg);
5287
5288/*
5289 * Appends already encoded questions from an existing message.
5290 *
5291 * This is useful when generating a DNS reply message which includes
5292 * all question records.
5293 *
5294 * Returns the number of appended bytes.
5295 */
5296int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
5297
5298/*
5299 * Encodes and appends a DNS resource record to an IO buffer.
5300 *
5301 * The record metadata is taken from the `rr` parameter, while the name and data
5302 * are taken from the parameters, encoded in the appropriate format depending on
5303 * record type and stored in the IO buffer. The encoded values might contain
5304 * offsets within the IO buffer. It's thus important that the IO buffer doesn't
5305 * get trimmed while a sequence of records are encoded while preparing a DNS
5306 * reply.
5307 *
5308 * This function doesn't update the `name` and `rdata` pointers in the `rr`
5309 * struct because they might be invalidated as soon as the IO buffer grows
5310 * again.
5311 *
5312 * Returns the number of bytes appened or -1 in case of error.
5313 */
5314int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
5315 const char *name, size_t nlen, const void *rdata,
5316 size_t rlen);
5317
5318/*
5319 * Encodes a DNS name.
5320 */
5321int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len);
5322
5323/* Low-level: parses a DNS response. */
5324int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
5325
5326/*
5327 * Uncompresses a DNS compressed name.
5328 *
5329 * The containing DNS message is required because of the compressed encoding
5330 * and reference suffixes present elsewhere in the packet.
5331 *
5332 * If the name is less than `dst_len` characters long, the remainder
5333 * of `dst` is terminated with `\0` characters. Otherwise, `dst` is not
5334 * terminated.
5335 *
5336 * If `dst_len` is 0 `dst` can be NULL.
5337 * Returns the uncompressed name length.
5338 */
5339size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
5340 char *dst, int dst_len);
5341
5342/*
5343 * Attaches a built-in DNS event handler to the given listening connection.
5344 *
5345 * The DNS event handler parses the incoming UDP packets, treating them as DNS
5346 * requests. If an incoming packet gets successfully parsed by the DNS event
5347 * handler, a user event handler will receive an `MG_DNS_REQUEST` event, with
5348 * `ev_data` pointing to the parsed `struct mg_dns_message`.
5349 *
5350 * See
5351 * [captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server)
5352 * example on how to handle DNS request and send DNS reply.
5353 */
5354void mg_set_protocol_dns(struct mg_connection *nc);
5355
5356#ifdef __cplusplus
5357}
5358#endif /* __cplusplus */
5359#endif /* CS_MONGOOSE_SRC_DNS_H_ */
5360#ifdef MG_MODULE_LINES
5361#line 1 "mongoose/src/dns_server.h"
5362#endif
5363/*
5364 * Copyright (c) 2014 Cesanta Software Limited
5365 * All rights reserved
5366 */
5367
5368/*
5369 * === DNS server API reference
5370 *
5371 * Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`.
5372 */
5373
5374#ifndef CS_MONGOOSE_SRC_DNS_SERVER_H_
5375#define CS_MONGOOSE_SRC_DNS_SERVER_H_
5376
5377#if MG_ENABLE_DNS_SERVER
5378
5379/* Amalgamated: #include "mongoose/src/dns.h" */
5380
5381#ifdef __cplusplus
5382extern "C" {
5383#endif /* __cplusplus */
5384
5385#define MG_DNS_SERVER_DEFAULT_TTL 3600
5386
5387struct mg_dns_reply {
5388 struct mg_dns_message *msg;
5389 struct mbuf *io;
5390 size_t start;
5391};
5392
5393/*
5394 * Creates a DNS reply.
5395 *
5396 * The reply will be based on an existing query message `msg`.
5397 * The query body will be appended to the output buffer.
5398 * "reply + recursion allowed" will be added to the message flags and the
5399 * message's num_answers will be set to 0.
5400 *
5401 * Answer records can be appended with `mg_dns_send_reply` or by lower
5402 * level function defined in the DNS API.
5403 *
5404 * In order to send a reply use `mg_dns_send_reply`.
5405 * It's possible to use a connection's send buffer as reply buffer,
5406 * and it will work for both UDP and TCP connections.
5407 *
5408 * Example:
5409 *
5410 * ```c
5411 * reply = mg_dns_create_reply(&nc->send_mbuf, msg);
5412 * for (i = 0; i < msg->num_questions; i++) {
5413 * rr = &msg->questions[i];
5414 * if (rr->rtype == MG_DNS_A_RECORD) {
5415 * mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4);
5416 * }
5417 * }
5418 * mg_dns_send_reply(nc, &reply);
5419 * ```
5420 */
5421struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
5422 struct mg_dns_message *msg);
5423
5424/*
5425 * Appends a DNS reply record to the IO buffer and to the DNS message.
5426 *
5427 * The message's num_answers field will be incremented. It's the caller's duty
5428 * to ensure num_answers is properly initialised.
5429 *
5430 * Returns -1 on error.
5431 */
5432int mg_dns_reply_record(struct mg_dns_reply *reply,
5433 struct mg_dns_resource_record *question,
5434 const char *name, int rtype, int ttl, const void *rdata,
5435 size_t rdata_len);
5436
5437/*
5438 * Sends a DNS reply through a connection.
5439 *
5440 * The DNS data is stored in an IO buffer pointed by reply structure in `r`.
5441 * This function mutates the content of that buffer in order to ensure that
5442 * the DNS header reflects the size and flags of the message, that might have
5443 * been updated either with `mg_dns_reply_record` or by direct manipulation of
5444 * `r->message`.
5445 *
5446 * Once sent, the IO buffer will be trimmed unless the reply IO buffer
5447 * is the connection's send buffer and the connection is not in UDP mode.
5448 */
5449void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);
5450
5451#ifdef __cplusplus
5452}
5453#endif /* __cplusplus */
5454
5455#endif /* MG_ENABLE_DNS_SERVER */
5456#endif /* CS_MONGOOSE_SRC_DNS_SERVER_H_ */
5457#ifdef MG_MODULE_LINES
5458#line 1 "mongoose/src/resolv.h"
5459#endif
5460/*
5461 * Copyright (c) 2014 Cesanta Software Limited
5462 * All rights reserved
5463 */
5464
5465/*
5466 * === API reference
5467 */
5468
5469#ifndef CS_MONGOOSE_SRC_RESOLV_H_
5470#define CS_MONGOOSE_SRC_RESOLV_H_
5471
5472/* Amalgamated: #include "mongoose/src/dns.h" */
5473
5474#ifdef __cplusplus
5475extern "C" {
5476#endif /* __cplusplus */
5477
5478enum mg_resolve_err {
5479 MG_RESOLVE_OK = 0,
5480 MG_RESOLVE_NO_ANSWERS = 1,
5481 MG_RESOLVE_EXCEEDED_RETRY_COUNT = 2,
5482 MG_RESOLVE_TIMEOUT = 3
5483};
5484
5485typedef void (*mg_resolve_callback_t)(struct mg_dns_message *dns_message,
5486 void *user_data, enum mg_resolve_err);
5487
5488/* Options for `mg_resolve_async_opt`. */
5489struct mg_resolve_async_opts {
5490 const char *nameserver_url;
5491 int max_retries; /* defaults to 2 if zero */
5492 int timeout; /* in seconds; defaults to 5 if zero */
5493 int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
5494 int only_literal; /* only resolves literal addrs; sync cb invocation */
5495 struct mg_connection **dns_conn; /* return DNS connection */
5496};
5497
5498/* See `mg_resolve_async_opt()` */
5499int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
5500 mg_resolve_callback_t cb, void *data);
5501
5502/*
5503 * Resolved a DNS name asynchronously.
5504 *
5505 * Upon successful resolution, the user callback will be invoked
5506 * with the full DNS response message and a pointer to the user's
5507 * context `data`.
5508 *
5509 * In case of timeout while performing the resolution the callback
5510 * will receive a NULL `msg`.
5511 *
5512 * The DNS answers can be extracted with `mg_next_record` and
5513 * `mg_dns_parse_record_data`:
5514 *
5515 * [source,c]
5516 * ----
5517 * struct in_addr ina;
5518 * struct mg_dns_resource_record *rr = mg_next_record(msg, MG_DNS_A_RECORD,
5519 * NULL);
5520 * mg_dns_parse_record_data(msg, rr, &ina, sizeof(ina));
5521 * ----
5522 */
5523int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
5524 mg_resolve_callback_t cb, void *data,
5525 struct mg_resolve_async_opts opts);
5526
5527/*
5528 * Resolve a name from `/etc/hosts`.
5529 *
5530 * Returns 0 on success, -1 on failure.
5531 */
5532int mg_resolve_from_hosts_file(const char *host, union socket_address *usa);
5533
5534#ifdef __cplusplus
5535}
5536#endif /* __cplusplus */
5537#endif /* CS_MONGOOSE_SRC_RESOLV_H_ */
5538#ifdef MG_MODULE_LINES
5539#line 1 "mongoose/src/coap.h"
5540#endif
5541/*
5542 * Copyright (c) 2015 Cesanta Software Limited
5543 * All rights reserved
5544 * This software is dual-licensed: you can redistribute it and/or modify
5545 * it under the terms of the GNU General Public License version 2 as
5546 * published by the Free Software Foundation. For the terms of this
5547 * license, see <http://www.gnu.org/licenses/>.
5548 *
5549 * You are free to use this software under the terms of the GNU General
5550 * Public License, but WITHOUT ANY WARRANTY; without even the implied
5551 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5552 * See the GNU General Public License for more details.
5553 *
5554 * Alternatively, you can license this software under a commercial
5555 * license, as set out in <https://www.cesanta.com/license>.
5556 */
5557
5558/*
5559 * === CoAP API reference
5560 *
5561 * CoAP message format:
5562 *
5563 * ```
5564 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
5565 * |Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
5566 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
5567 * | Options (if any) ... |1 1 1 1 1 1 1 1| Payload (if any) ...
5568 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
5569 * ```
5570 */
5571
5572#ifndef CS_MONGOOSE_SRC_COAP_H_
5573#define CS_MONGOOSE_SRC_COAP_H_
5574
5575#if MG_ENABLE_COAP
5576
5577#define MG_COAP_MSG_TYPE_FIELD 0x2
5578#define MG_COAP_CODE_CLASS_FIELD 0x4
5579#define MG_COAP_CODE_DETAIL_FIELD 0x8
5580#define MG_COAP_MSG_ID_FIELD 0x10
5581#define MG_COAP_TOKEN_FIELD 0x20
5582#define MG_COAP_OPTIOMG_FIELD 0x40
5583#define MG_COAP_PAYLOAD_FIELD 0x80
5584
5585#define MG_COAP_ERROR 0x10000
5586#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)
5587#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)
5588#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)
5589#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)
5590
5591#define MG_COAP_MSG_CON 0
5592#define MG_COAP_MSG_NOC 1
5593#define MG_COAP_MSG_ACK 2
5594#define MG_COAP_MSG_RST 3
5595#define MG_COAP_MSG_MAX 3
5596
5597#define MG_COAP_CODECLASS_REQUEST 0
5598#define MG_COAP_CODECLASS_RESP_OK 2
5599#define MG_COAP_CODECLASS_CLIENT_ERR 4
5600#define MG_COAP_CODECLASS_SRV_ERR 5
5601
5602#define MG_COAP_EVENT_BASE 300
5603#define MG_EV_COAP_CON (MG_COAP_EVENT_BASE + MG_COAP_MSG_CON)
5604#define MG_EV_COAP_NOC (MG_COAP_EVENT_BASE + MG_COAP_MSG_NOC)
5605#define MG_EV_COAP_ACK (MG_COAP_EVENT_BASE + MG_COAP_MSG_ACK)
5606#define MG_EV_COAP_RST (MG_COAP_EVENT_BASE + MG_COAP_MSG_RST)
5607
5608/*
5609 * CoAP options.
5610 * Use mg_coap_add_option and mg_coap_free_options
5611 * for creation and destruction.
5612 */
5613struct mg_coap_option {
5614 struct mg_coap_option *next;
5615 uint32_t number;
5616 struct mg_str value;
5617};
5618
5619/* CoAP message. See RFC 7252 for details. */
5620struct mg_coap_message {
5621 uint32_t flags;
5622 uint8_t msg_type;
5623 uint8_t code_class;
5624 uint8_t code_detail;
5625 uint16_t msg_id;
5626 struct mg_str token;
5627 struct mg_coap_option *options;
5628 struct mg_str payload;
5629 struct mg_coap_option *optiomg_tail;
5630};
5631
5632#ifdef __cplusplus
5633extern "C" {
5634#endif /* __cplusplus */
5635
5636/* Sets CoAP protocol handler - triggers CoAP specific events. */
5637int mg_set_protocol_coap(struct mg_connection *nc);
5638
5639/*
5640 * Adds a new option to mg_coap_message structure.
5641 * Returns pointer to the newly created option.
5642 * Note: options must be freed by using mg_coap_free_options
5643 */
5644struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
5645 uint32_t number, char *value,
5646 size_t len);
5647
5648/*
5649 * Frees the memory allocated for options.
5650 * If the cm paramater doesn't contain any option it does nothing.
5651 */
5652void mg_coap_free_options(struct mg_coap_message *cm);
5653
5654/*
5655 * Composes a CoAP message from `mg_coap_message`
5656 * and sends it into `nc` connection.
5657 * Returns 0 on success. On error, it is a bitmask:
5658 *
5659 * - `#define MG_COAP_ERROR 0x10000`
5660 * - `#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)`
5661 * - `#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)`
5662 * - `#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)`
5663 * - `#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)`
5664 */
5665uint32_t mg_coap_send_message(struct mg_connection *nc,
5666 struct mg_coap_message *cm);
5667
5668/*
5669 * Composes CoAP acknowledgement from `mg_coap_message`
5670 * and sends it into `nc` connection.
5671 * Return value: see `mg_coap_send_message()`
5672 */
5673uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);
5674
5675/*
5676 * Parses CoAP message and fills mg_coap_message and returns cm->flags.
5677 * This is a helper function.
5678 *
5679 * NOTE: usually CoAP works over UDP, so lack of data means format error.
5680 * But, in theory, it is possible to use CoAP over TCP (according to RFC)
5681 *
5682 * The caller has to check results and treat COAP_NOT_ENOUGH_DATA according to
5683 * underlying protocol:
5684 *
5685 * - in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,
5686 * - in case of TCP client can try to receive more data
5687 *
5688 * Return value: see `mg_coap_send_message()`
5689 */
5690uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);
5691
5692/*
5693 * Composes CoAP message from mg_coap_message structure.
5694 * This is a helper function.
5695 * Return value: see `mg_coap_send_message()`
5696 */
5697uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
5698
5699#ifdef __cplusplus
5700}
5701#endif /* __cplusplus */
5702
5703#endif /* MG_ENABLE_COAP */
5704
5705#endif /* CS_MONGOOSE_SRC_COAP_H_ */
5706#ifdef MG_MODULE_LINES
5707#line 1 "mongoose/src/sntp.h"
5708#endif
5709/*
5710 * Copyright (c) 2016 Cesanta Software Limited
5711 * All rights reserved
5712 */
5713
5714#ifndef CS_MONGOOSE_SRC_SNTP_H_
5715#define CS_MONGOOSE_SRC_SNTP_H_
5716
5717#if MG_ENABLE_SNTP
5718
5719#define MG_SNTP_EVENT_BASE 500
5720
5721/*
5722 * Received reply from time server. Event handler parameter contains
5723 * pointer to mg_sntp_message structure
5724 */
5725#define MG_SNTP_REPLY (MG_SNTP_EVENT_BASE + 1)
5726
5727/* Received malformed SNTP packet */
5728#define MG_SNTP_MALFORMED_REPLY (MG_SNTP_EVENT_BASE + 2)
5729
5730/* Failed to get time from server (timeout etc) */
5731#define MG_SNTP_FAILED (MG_SNTP_EVENT_BASE + 3)
5732
5733struct mg_sntp_message {
5734 /* if server sends this flags, user should not send requests to it */
5735 int kiss_of_death;
5736 /* usual mg_time */
5737 double time;
5738};
5739
5740/* Establishes connection to given sntp server */
5741struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr,
5742 mg_event_handler_t event_handler,
5743 const char *sntp_server_name);
5744
5745/* Sends time request to given connection */
5746void mg_sntp_send_request(struct mg_connection *c);
5747
5748/*
5749 * Helper function
5750 * Establishes connection to time server, tries to send request
5751 * repeats sending SNTP_ATTEMPTS times every SNTP_TIMEOUT sec
5752 * (if needed)
5753 * See sntp_client example
5754 */
5755struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr,
5756 mg_event_handler_t event_handler,
5757 const char *sntp_server_name);
5758
5759#endif
5760
5761#endif /* CS_MONGOOSE_SRC_SNTP_H_ */
Note: See TracBrowser for help on using the repository browser.