Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-02 08:21:06

0001 /*
0002  * Copyright (c) 2004-2013 Sergey Lyubka
0003  * Copyright (c) 2013-2015 Cesanta Software Limited
0004  * All rights reserved
0005  *
0006  * This software is dual-licensed: you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License version 2 as
0008  * published by the Free Software Foundation. For the terms of this
0009  * license, see <http://www.gnu.org/licenses/>.
0010  *
0011  * You are free to use this software under the terms of the GNU General
0012  * Public License, but WITHOUT ANY WARRANTY; without even the implied
0013  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0014  * See the GNU General Public License for more details.
0015  *
0016  * Alternatively, you can license this software under a commercial
0017  * license, as set out in <https://www.cesanta.com/license>.
0018  */
0019 
0020 #ifndef CS_MONGOOSE_SRC_COMMON_H_
0021 #define CS_MONGOOSE_SRC_COMMON_H_
0022 
0023 #define MG_VERSION "6.4"
0024 
0025 /* Local tweaks, applied before any of Mongoose's own headers. */
0026 #ifdef MG_LOCALS
0027 #include <mg_locals.h>
0028 #endif
0029 
0030 #if defined(MG_ENABLE_DEBUG) && !defined(CS_ENABLE_DEBUG)
0031 #define CS_ENABLE_DEBUG
0032 #endif
0033 #if defined(MG_DISABLE_STDIO) && !defined(CS_DISABLE_STDIO)
0034 #define CS_DISABLE_STDIO
0035 #elif defined(CS_DISABLE_STDIO) && !defined(MG_DISABLE_STDIO)
0036 #define MG_DISABLE_STDIO
0037 #endif
0038 
0039 /* All of the below features depend on filesystem access, disable them. */
0040 #ifdef MG_DISABLE_FILESYSTEM
0041 #ifndef MG_DISABLE_DAV
0042 #define MG_DISABLE_DAV
0043 #endif
0044 #ifndef MG_DISABLE_CGI
0045 #define MG_DISABLE_CGI
0046 #endif
0047 #ifndef MG_DISABLE_DIRECTORY_LISTING
0048 #define MG_DISABLE_DIRECTORY_LISTING
0049 #endif
0050 #ifndef MG_DISABLE_DAV
0051 #define MG_DISABLE_DAV
0052 #endif
0053 #endif /* MG_DISABLE_FILESYSTEM */
0054 
0055 #ifdef MG_NO_BSD_SOCKETS
0056 #ifndef MG_DISABLE_SYNC_RESOLVER
0057 #define MG_DISABLE_SYNC_RESOLVER
0058 #endif
0059 #ifndef MG_DISABLE_SOCKETPAIR
0060 #define MG_DISABLE_SOCKETPAIR
0061 #endif
0062 #endif /* MG_NO_BSD_SOCKETS */
0063 
0064 
0065 #endif /* CS_MONGOOSE_SRC_COMMON_H_ */
0066 #ifndef CS_COMMON_PLATFORM_H_
0067 #define CS_COMMON_PLATFORM_H_
0068 
0069 /*
0070  * For the "custom" platform, includes and dependencies can be
0071  * provided through mg_locals.h.
0072  */
0073 #define CS_P_CUSTOM 0
0074 #define CS_P_UNIX 1
0075 #define CS_P_WINDOWS 2
0076 #define CS_P_ESP_LWIP 3
0077 #define CS_P_CC3200 4
0078 #define CS_P_MSP432 5
0079 
0080 /* If not specified explicitly, we guess platform by defines. */
0081 #ifndef CS_PLATFORM
0082 
0083 #if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
0084 
0085 #define CS_PLATFORM CS_P_MSP432
0086 #elif defined(cc3200)
0087 #define CS_PLATFORM CS_P_CC3200
0088 #elif defined(__unix__) || defined(__APPLE__)
0089 #define CS_PLATFORM CS_P_UNIX
0090 #elif defined(_WIN32)
0091 #define CS_PLATFORM CS_P_WINDOWS
0092 #endif
0093 
0094 #ifndef CS_PLATFORM
0095 #error "CS_PLATFORM is not specified and we couldn't guess it."
0096 #endif
0097 
0098 #endif /* !defined(CS_PLATFORM) */
0099 
0100 
0101 /* Common stuff */
0102 
0103 #ifdef __GNUC__
0104 #define NORETURN __attribute__((noreturn))
0105 #define NOINLINE __attribute__((noinline))
0106 #define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
0107 #else
0108 #define NORETURN
0109 #define NOINLINE
0110 #define WARN_UNUSED_RESULT
0111 #endif /* __GNUC__ */
0112 
0113 #ifndef ARRAY_SIZE
0114 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
0115 #endif
0116 
0117 #endif /* CS_COMMON_PLATFORM_H_ */
0118 #ifndef CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
0119 #define CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
0120 #if CS_PLATFORM == CS_P_WINDOWS
0121 
0122 /*
0123  * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
0124  * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
0125  * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
0126  * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
0127  * MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)
0128  * MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)
0129  * MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio 2003)
0130  * MSVC++ 7.0  _MSC_VER == 1300
0131  * MSVC++ 6.0  _MSC_VER == 1200
0132  * MSVC++ 5.0  _MSC_VER == 1100
0133  */
0134 #ifdef _MSC_VER
0135 #pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */
0136 #pragma warning(disable : 4204) /* missing c99 support */
0137 #endif
0138 
0139 #include <assert.h>
0140 #include <direct.h>
0141 #include <errno.h>
0142 #include <fcntl.h>
0143 #include <io.h>
0144 #include <limits.h>
0145 #include <signal.h>
0146 #include <stddef.h>
0147 #include <stdio.h>
0148 #include <stdlib.h>
0149 #include <sys/stat.h>
0150 #include <time.h>
0151 
0152 #define random() rand()
0153 #ifdef _MSC_VER
0154 #pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
0155 #endif
0156 
0157 #include <winsock2.h>
0158 #include <ws2tcpip.h>
0159 #include <windows.h>
0160 #include <process.h>
0161 
0162 #ifndef EINPROGRESS
0163 #define EINPROGRESS WSAEINPROGRESS
0164 #endif
0165 #ifndef EWOULDBLOCK
0166 #define EWOULDBLOCK WSAEWOULDBLOCK
0167 #endif
0168 #ifndef __func__
0169 #define STRX(x) #x
0170 #define STR(x) STRX(x)
0171 #define __func__ __FILE__ ":" STR(__LINE__)
0172 #endif
0173 #define snprintf _snprintf
0174 #define fileno _fileno
0175 #define vsnprintf _vsnprintf
0176 #define sleep(x) Sleep((x) *1000)
0177 #define to64(x) _atoi64(x)
0178 #if !defined(__MINGW32__) && !defined(__MINGW64__)
0179 #define popen(x, y) _popen((x), (y))
0180 #define pclose(x) _pclose(x)
0181 #endif
0182 #define rmdir _rmdir
0183 #if defined(_MSC_VER) && _MSC_VER >= 1400
0184 #define fseeko(x, y, z) _fseeki64((x), (y), (z))
0185 #else
0186 #define fseeko(x, y, z) fseek((x), (y), (z))
0187 #endif
0188 #define random() rand()
0189 typedef int socklen_t;
0190 #if _MSC_VER >= 1700
0191 #include <stdint.h>
0192 #else
0193 typedef signed char int8_t;
0194 typedef unsigned char uint8_t;
0195 typedef int int32_t;
0196 typedef unsigned int uint32_t;
0197 typedef short int16_t;
0198 typedef unsigned short uint16_t;
0199 typedef __int64 int64_t;
0200 typedef unsigned __int64 uint64_t;
0201 #endif
0202 typedef SOCKET sock_t;
0203 typedef uint32_t in_addr_t;
0204 #ifndef UINT16_MAX
0205 #define UINT16_MAX 65535
0206 #endif
0207 #ifndef UINT32_MAX
0208 #define UINT32_MAX 4294967295
0209 #endif
0210 #ifndef pid_t
0211 #define pid_t HANDLE
0212 #endif
0213 #define INT64_FMT "I64d"
0214 #define INT64_X_FMT "I64x"
0215 #define SIZE_T_FMT "Iu"
0216 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
0217 typedef struct stat cs_stat_t;
0218 #else
0219 typedef struct _stati64 cs_stat_t;
0220 #endif
0221 #ifndef S_ISDIR
0222 #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
0223 #endif
0224 #ifndef S_ISREG
0225 #define S_ISREG(x) (((x) &_S_IFMT) == _S_IFREG)
0226 #endif
0227 #define DIRSEP '\\'
0228 
0229 #ifndef va_copy
0230 #ifdef __va_copy
0231 #define va_copy __va_copy
0232 #else
0233 #define va_copy(x, y) (x) = (y)
0234 #endif
0235 #endif
0236 
0237 #ifndef MG_MAX_HTTP_REQUEST_SIZE
0238 #define MG_MAX_HTTP_REQUEST_SIZE 8192
0239 #endif
0240 
0241 #ifndef MG_MAX_HTTP_SEND_MBUF
0242 #define MG_MAX_HTTP_SEND_MBUF 4096
0243 #endif
0244 
0245 #ifndef MG_MAX_HTTP_HEADERS
0246 #define MG_MAX_HTTP_HEADERS 40
0247 #endif
0248 
0249 #endif /* CS_PLATFORM == CS_P_WINDOWS */
0250 #endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */
0251 #ifndef CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
0252 #define CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
0253 #if CS_PLATFORM == CS_P_UNIX
0254 
0255 #ifndef _XOPEN_SOURCE
0256 #define _XOPEN_SOURCE 600
0257 #endif
0258 
0259 /* <inttypes.h> wants this for C++ */
0260 #ifndef __STDC_FORMAT_MACROS
0261 #define __STDC_FORMAT_MACROS
0262 #endif
0263 
0264 /* C++ wants that for INT64_MAX */
0265 #ifndef __STDC_LIMIT_MACROS
0266 #define __STDC_LIMIT_MACROS
0267 #endif
0268 
0269 /* Enable fseeko() and ftello() functions */
0270 #ifndef _LARGEFILE_SOURCE
0271 #define _LARGEFILE_SOURCE
0272 #endif
0273 
0274 /* Enable 64-bit file offsets */
0275 #ifndef _FILE_OFFSET_BITS
0276 #define _FILE_OFFSET_BITS 64
0277 #endif
0278 
0279 #include <arpa/inet.h>
0280 #include <assert.h>
0281 #include <ctype.h>
0282 #include <dirent.h>
0283 #include <errno.h>
0284 #include <fcntl.h>
0285 #include <inttypes.h>
0286 #include <limits.h>
0287 #include <math.h>
0288 #include <netdb.h>
0289 #include <netinet/in.h>
0290 #include <pthread.h>
0291 #include <signal.h>
0292 #include <stdarg.h>
0293 #include <stdio.h>
0294 #include <stdlib.h>
0295 #include <string.h>
0296 #include <sys/socket.h>
0297 #include <sys/select.h>
0298 #include <sys/stat.h>
0299 #include <sys/time.h>
0300 #include <sys/types.h>
0301 #include <unistd.h>
0302 
0303 /*
0304  * osx correctly avoids defining strtoll when compiling in strict ansi mode.
0305  * We require strtoll, and if your embedded pre-c99 compiler lacks one, please
0306  * implement a shim.
0307  */
0308 #if !(defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L)
0309 long long strtoll(const char *, char **, int);
0310 #endif
0311 
0312 typedef int sock_t;
0313 #define INVALID_SOCKET (-1)
0314 #define SIZE_T_FMT "zu"
0315 typedef struct stat cs_stat_t;
0316 #define DIRSEP '/'
0317 #define to64(x) strtoll(x, NULL, 10)
0318 #define INT64_FMT PRId64
0319 #define INT64_X_FMT PRIx64
0320 
0321 #ifndef __cdecl
0322 #define __cdecl
0323 #endif
0324 
0325 #ifndef va_copy
0326 #ifdef __va_copy
0327 #define va_copy __va_copy
0328 #else
0329 #define va_copy(x, y) (x) = (y)
0330 #endif
0331 #endif
0332 
0333 #define closesocket(x) close(x)
0334 
0335 #ifndef MG_MAX_HTTP_REQUEST_SIZE
0336 #define MG_MAX_HTTP_REQUEST_SIZE 8192
0337 #endif
0338 
0339 #ifndef MG_MAX_HTTP_SEND_MBUF
0340 #define MG_MAX_HTTP_SEND_MBUF 4096
0341 #endif
0342 
0343 #ifndef MG_MAX_HTTP_HEADERS
0344 #define MG_MAX_HTTP_HEADERS 40
0345 #endif
0346 
0347 #endif /* CS_PLATFORM == CS_P_UNIX */
0348 #endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */
0349 #ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_
0350 #define CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_
0351 #if CS_PLATFORM == CS_P_ESP_LWIP
0352 
0353 #include <assert.h>
0354 #include <ctype.h>
0355 #include <fcntl.h>
0356 #include <inttypes.h>
0357 #include <string.h>
0358 #include <sys/stat.h>
0359 #include <sys/time.h>
0360 
0361 #include <lwip/err.h>
0362 #include <lwip/ip_addr.h>
0363 #include <lwip/inet.h>
0364 #include <lwip/netdb.h>
0365 #include <lwip/dns.h>
0366 
0367 #ifndef LWIP_PROVIDE_ERRNO
0368 #include <errno.h>
0369 #endif
0370 
0371 #define LWIP_TIMEVAL_PRIVATE 0
0372 
0373 #if LWIP_SOCKET
0374 #include <lwip/sockets.h>
0375 #define SOMAXCONN 10
0376 #else
0377 /* We really need the definitions from sockets.h. */
0378 #undef LWIP_SOCKET
0379 #define LWIP_SOCKET 1
0380 #include <lwip/sockets.h>
0381 #undef LWIP_SOCKET
0382 #define LWIP_SOCKET 0
0383 #endif
0384 
0385 typedef int sock_t;
0386 #define INVALID_SOCKET (-1)
0387 #define SIZE_T_FMT "u"
0388 typedef struct stat cs_stat_t;
0389 #define DIRSEP '/'
0390 #define to64(x) strtoll(x, NULL, 10)
0391 #define INT64_FMT PRId64
0392 #define INT64_X_FMT PRIx64
0393 #define __cdecl
0394 
0395 unsigned long os_random(void);
0396 #define random os_random
0397 
0398 #endif /* CS_PLATFORM == CS_P_ESP_LWIP */
0399 #endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_ */
0400 /*
0401  * Copyright (c) 2014-2016 Cesanta Software Limited
0402  * All rights reserved
0403  */
0404 
0405 #ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
0406 #define CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
0407 #if CS_PLATFORM == CS_P_CC3200
0408 
0409 #include <assert.h>
0410 #include <ctype.h>
0411 #include <errno.h>
0412 #include <inttypes.h>
0413 #include <stdint.h>
0414 #include <string.h>
0415 #include <time.h>
0416 
0417 #ifndef __TI_COMPILER_VERSION__
0418 #include <fcntl.h>
0419 #include <sys/time.h>
0420 #endif
0421 
0422 #define MG_SOCKET_SIMPLELINK 1
0423 #define MG_DISABLE_SOCKETPAIR 1
0424 #define MG_DISABLE_SYNC_RESOLVER 1
0425 #define MG_DISABLE_POPEN 1
0426 #define MG_DISABLE_CGI 1
0427 /* Only SPIFFS supports directories, SLFS does not. */
0428 #ifndef CC3200_FS_SPIFFS
0429 #define MG_DISABLE_DAV 1
0430 #define MG_DISABLE_DIRECTORY_LISTING 1
0431 #endif
0432 
0433 
0434 typedef int sock_t;
0435 #define INVALID_SOCKET (-1)
0436 #define SIZE_T_FMT "u"
0437 typedef struct stat cs_stat_t;
0438 #define DIRSEP '/'
0439 #define to64(x) strtoll(x, NULL, 10)
0440 #define INT64_FMT PRId64
0441 #define INT64_X_FMT PRIx64
0442 #define __cdecl
0443 
0444 #define fileno(x) -1
0445 
0446 /* Some functions we implement for Mongoose. */
0447 
0448 #ifdef __cplusplus
0449 extern "C" {
0450 #endif
0451    
0452 #ifdef __TI_COMPILER_VERSION__
0453    struct SlTimeval_t;
0454 #define timeval SlTimeval_t
0455    int gettimeofday(struct timeval *t, void *tz);
0456    
0457    int asprintf(char **strp, const char *fmt, ...);
0458    
0459 #endif
0460    
0461    long int random(void);
0462    
0463    /* TI's libc does not have stat & friends, add them. */
0464 #ifdef __TI_COMPILER_VERSION__
0465    
0466 #include <file.h>
0467    
0468    typedef unsigned int mode_t;
0469    typedef size_t _off_t;
0470    typedef long ssize_t;
0471    
0472    struct stat {
0473       int st_ino;
0474       mode_t st_mode;
0475       int st_nlink;
0476       time_t st_mtime;
0477       off_t st_size;
0478    };
0479    
0480    int _stat(const char *pathname, struct stat *st);
0481 #define stat(a, b) _stat(a, b)
0482    
0483 #define __S_IFMT 0170000
0484    
0485 #define __S_IFDIR 0040000
0486 #define __S_IFCHR 0020000
0487 #define __S_IFREG 0100000
0488    
0489 #define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask))
0490    
0491 #define S_IFDIR __S_IFDIR
0492 #define S_IFCHR __S_IFCHR
0493 #define S_IFREG __S_IFREG
0494 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
0495 #define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
0496    
0497    /* As of 5.2.7, TI compiler does not support va_copy() yet. */
0498 #define va_copy(apc, ap) ((apc) = (ap))
0499    
0500 #endif /* __TI_COMPILER_VERSION__ */
0501    
0502 #ifdef CC3200_FS_SPIFFS
0503 #include <common/spiffs/spiffs.h>
0504    
0505    typedef struct {
0506       spiffs_DIR dh;
0507       struct spiffs_dirent de;
0508    } DIR;
0509    
0510 #define d_name name
0511 #define dirent spiffs_dirent
0512    
0513    DIR *opendir(const char *dir_name);
0514    int closedir(DIR *dir);
0515    struct dirent *readdir(DIR *dir);
0516 #endif /* CC3200_FS_SPIFFS */
0517    
0518 #ifdef CC3200_FS_SLFS
0519 #define MG_FS_SLFS
0520 #endif
0521    
0522 #ifdef __cplusplus
0523 }
0524 #endif
0525 
0526 #endif /* CS_PLATFORM == CS_P_CC3200 */
0527 #endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ */
0528 /*
0529  * Copyright (c) 2014-2016 Cesanta Software Limited
0530  * All rights reserved
0531  */
0532 
0533 #ifndef CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_
0534 #define CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_
0535 #if CS_PLATFORM == CS_P_MSP432
0536 
0537 #include <assert.h>
0538 #include <ctype.h>
0539 #include <errno.h>
0540 #include <inttypes.h>
0541 #include <stdint.h>
0542 #include <string.h>
0543 #include <time.h>
0544 
0545 #ifndef __TI_COMPILER_VERSION__
0546 #include <fcntl.h>
0547 #include <sys/time.h>
0548 #endif
0549 
0550 #define MG_SOCKET_SIMPLELINK 1
0551 #define MG_DISABLE_SOCKETPAIR 1
0552 #define MG_DISABLE_SYNC_RESOLVER 1
0553 #define MG_DISABLE_POPEN 1
0554 #define MG_DISABLE_CGI 1
0555 #define MG_DISABLE_DAV 1
0556 #define MG_DISABLE_DIRECTORY_LISTING 1
0557 
0558 
0559 typedef int sock_t;
0560 #define INVALID_SOCKET (-1)
0561 #define SIZE_T_FMT "u"
0562 typedef struct stat cs_stat_t;
0563 #define DIRSEP '/'
0564 #define to64(x) strtoll(x, NULL, 10)
0565 #define INT64_FMT PRId64
0566 #define INT64_X_FMT PRIx64
0567 #define __cdecl
0568 
0569 #define fileno(x) -1
0570 
0571 /* Some functions we implement for Mongoose. */
0572 
0573 #ifdef __cplusplus
0574 extern "C" {
0575 #endif
0576    
0577 #ifdef __TI_COMPILER_VERSION__
0578    struct SlTimeval_t;
0579 #define timeval SlTimeval_t
0580    int gettimeofday(struct timeval *t, void *tz);
0581 #endif
0582    
0583    long int random(void);
0584    
0585    /* TI's libc does not have stat & friends, add them. */
0586 #ifdef __TI_COMPILER_VERSION__
0587    
0588 #include <file.h>
0589    
0590    typedef unsigned int mode_t;
0591    typedef size_t _off_t;
0592    typedef long ssize_t;
0593    
0594    struct stat {
0595       int st_ino;
0596       mode_t st_mode;
0597       int st_nlink;
0598       time_t st_mtime;
0599       off_t st_size;
0600    };
0601    
0602    int _stat(const char *pathname, struct stat *st);
0603 #define stat(a, b) _stat(a, b)
0604    
0605 #define __S_IFMT 0170000
0606    
0607 #define __S_IFDIR 0040000
0608 #define __S_IFCHR 0020000
0609 #define __S_IFREG 0100000
0610    
0611 #define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask))
0612    
0613 #define S_IFDIR __S_IFDIR
0614 #define S_IFCHR __S_IFCHR
0615 #define S_IFREG __S_IFREG
0616 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
0617 #define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
0618    
0619    /* As of 5.2.7, TI compiler does not support va_copy() yet. */
0620 #define va_copy(apc, ap) ((apc) = (ap))
0621    
0622 #endif /* __TI_COMPILER_VERSION__ */
0623    
0624 #ifdef __cplusplus
0625 }
0626 #endif
0627 
0628 #endif /* CS_PLATFORM == CS_P_MSP432 */
0629 #endif /* CS_COMMON_PLATFORMS_PLATFORM_MSP432_H_ */
0630 /*
0631  * Copyright (c) 2014-2016 Cesanta Software Limited
0632  * All rights reserved
0633  */
0634 
0635 #ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
0636 #define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
0637 
0638 /* If simplelink.h is already included, all bets are off. */
0639 #if defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__)
0640 
0641 #include <stdbool.h>
0642 
0643 #ifndef __TI_COMPILER_VERSION__
0644 #undef __CONCAT
0645 #undef FD_CLR
0646 #undef FD_ISSET
0647 #undef FD_SET
0648 #undef FD_SETSIZE
0649 #undef FD_ZERO
0650 #undef fd_set
0651 #endif
0652 
0653 /* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves
0654  * and undef it. */
0655 #define PROVISIONING_API_H_
0656 #include <simplelink/user.h>
0657 #undef PROVISIONING_API_H_
0658 #undef SL_INC_STD_BSD_API_NAMING
0659 
0660 #include <simplelink/include/simplelink.h>
0661 
0662 /* Now define only the subset of the BSD API that we use.
0663  * Notably, close(), read() and write() are not defined. */
0664 #define AF_INET SL_AF_INET
0665 
0666 #define socklen_t SlSocklen_t
0667 #define sockaddr SlSockAddr_t
0668 #define sockaddr_in SlSockAddrIn_t
0669 #define in_addr SlInAddr_t
0670 
0671 #define SOCK_STREAM SL_SOCK_STREAM
0672 #define SOCK_DGRAM SL_SOCK_DGRAM
0673 
0674 #define FD_SET SL_FD_SET
0675 #define FD_CLR SL_FD_CLR
0676 #define FD_ISSET SL_FD_ISSET
0677 #define FD_ZERO SL_FD_ZERO
0678 #define fd_set SlFdSet_t
0679 
0680 #define htonl sl_Htonl
0681 #define ntohl sl_Ntohl
0682 #define htons sl_Htons
0683 #define ntohs sl_Ntohs
0684 
0685 #define accept sl_Accept
0686 #define closesocket sl_Close
0687 #define bind sl_Bind
0688 #define connect sl_Connect
0689 #define listen sl_Listen
0690 #define recv sl_Recv
0691 #define recvfrom sl_RecvFrom
0692 #define send sl_Send
0693 #define sendto sl_SendTo
0694 #define socket sl_Socket
0695 
0696 #define select(nfds, rfds, wfds, efds, tout) \
0697 sl_Select((nfds), (rfds), (wfds), (efds), (struct SlTimeval_t *)(tout))
0698 
0699 #ifndef EACCES
0700 #define EACCES SL_EACCES
0701 #endif
0702 #ifndef EAFNOSUPPORT
0703 #define EAFNOSUPPORT SL_EAFNOSUPPORT
0704 #endif
0705 #ifndef EAGAIN
0706 #define EAGAIN SL_EAGAIN
0707 #endif
0708 #ifndef EBADF
0709 #define EBADF SL_EBADF
0710 #endif
0711 #ifndef EINVAL
0712 #define EINVAL SL_EINVAL
0713 #endif
0714 #ifndef ENOMEM
0715 #define ENOMEM SL_ENOMEM
0716 #endif
0717 #ifndef EWOULDBLOCK
0718 #define EWOULDBLOCK SL_EWOULDBLOCK
0719 #endif
0720 
0721 #define SOMAXCONN 8
0722 
0723 #ifdef __cplusplus
0724 extern "C" {
0725 #endif
0726    
0727    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
0728    char *inet_ntoa(struct in_addr in);
0729    int inet_pton(int af, const char *src, void *dst);
0730    
0731    struct mg_mgr;
0732    
0733    typedef void (*mg_init_cb)(struct mg_mgr *mgr);
0734    bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init);
0735    
0736    void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg);
0737    
0738    int sl_fs_init();
0739    
0740 #ifdef __cplusplus
0741 }
0742 #endif
0743 
0744 #endif /* defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__) */
0745 
0746 #endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */
0747 /*
0748  * Copyright (c) 2014-2016 Cesanta Software Limited
0749  * All rights reserved
0750  */
0751 
0752 #ifndef CS_COMMON_CS_DBG_H_
0753 #define CS_COMMON_CS_DBG_H_
0754 
0755 #ifndef CS_DISABLE_STDIO
0756 #include <stdio.h>
0757 #endif
0758 
0759 #ifdef __cplusplus
0760 extern "C" {
0761 #endif /* __cplusplus */
0762    
0763    enum cs_log_level {
0764       LL_NONE = -1,
0765       LL_ERROR = 0,
0766       LL_WARN = 1,
0767       LL_INFO = 2,
0768       LL_DEBUG = 3,
0769       LL_VERBOSE_DEBUG = 4,
0770       
0771       _LL_MIN = -2,
0772       _LL_MAX = 5,
0773    };
0774    
0775    void cs_log_set_level(enum cs_log_level level);
0776    
0777 #ifndef CS_DISABLE_STDIO
0778    
0779    void cs_log_set_file(FILE *file);
0780    
0781    extern enum cs_log_level cs_log_level;
0782    void cs_log_print_prefix(const char *func);
0783    void cs_log_printf(const char *fmt, ...);
0784    
0785 #define LOG(l, x)                  \
0786 if (cs_log_level >= l) {         \
0787 cs_log_print_prefix(__func__); \
0788 cs_log_printf x;               \
0789 }
0790    
0791 #ifndef CS_NDEBUG
0792    
0793 #define DBG(x)                            \
0794 if (cs_log_level >= LL_VERBOSE_DEBUG) { \
0795 cs_log_print_prefix(__func__);        \
0796 cs_log_printf x;                      \
0797 }
0798    
0799 #else /* NDEBUG */
0800    
0801 #define DBG(x)
0802    
0803 #endif
0804    
0805 #else /* CS_DISABLE_STDIO */
0806    
0807 #define LOG(l, x)
0808 #define DBG(x)
0809    
0810 #endif
0811    
0812 #ifdef __cplusplus
0813 }
0814 #endif /* __cplusplus */
0815 
0816 #endif /* CS_COMMON_CS_DBG_H_ */
0817 /*
0818  * Copyright (c) 2014-2016 Cesanta Software Limited
0819  * All rights reserved
0820  */
0821 
0822 #ifndef CS_COMMON_CS_TIME_H_
0823 #define CS_COMMON_CS_TIME_H_
0824 
0825 #ifdef __cplusplus
0826 extern "C" {
0827 #endif /* __cplusplus */
0828    
0829    /* Sub-second granularity time(). */
0830    double cs_time();
0831    
0832 #ifdef __cplusplus
0833 }
0834 #endif /* __cplusplus */
0835 
0836 #endif /* CS_COMMON_CS_TIME_H_ */
0837 /*
0838  * Copyright (c) 2015 Cesanta Software Limited
0839  * All rights reserved
0840  */
0841 
0842 /*
0843  * === Memory Buffers
0844  *
0845  * Mbufs are mutable/growing memory buffers, like C++ strings.
0846  * Mbuf can append data to the end of a buffer, or insert data into arbitrary
0847  * position in the middle of a buffer. The buffer grows automatically when
0848  * needed.
0849  */
0850 
0851 #ifndef CS_COMMON_MBUF_H_
0852 #define CS_COMMON_MBUF_H_
0853 
0854 #if defined(__cplusplus)
0855 extern "C" {
0856 #endif
0857    
0858 #include <stdlib.h>
0859    
0860 #ifndef MBUF_SIZE_MULTIPLIER
0861 #define MBUF_SIZE_MULTIPLIER 1.5
0862 #endif
0863    
0864    /* Memory buffer descriptor */
0865    struct mbuf {
0866       char *buf;   /* Buffer pointer */
0867       size_t len;  /* Data length. Data is located between offset 0 and len. */
0868       size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
0869    };
0870    
0871    /*
0872     * Initialize an Mbuf.
0873     * `initial_capacity` specifies the initial capacity of the mbuf.
0874     */
0875    void mbuf_init(struct mbuf *, size_t initial_capacity);
0876    
0877    /* Free the space allocated for the mbuffer and resets the mbuf structure. */
0878    void mbuf_free(struct mbuf *);
0879    
0880    /*
0881     * Appends data to the Mbuf.
0882     *
0883     * Return the number of bytes appended, or 0 if out of memory.
0884     */
0885    size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
0886    
0887    /*
0888     * Insert data at a specified offset in the Mbuf.
0889     *
0890     * Existing data will be shifted forwards and the buffer will
0891     * be grown if necessary.
0892     * Return the number of bytes inserted.
0893     */
0894    size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
0895    
0896    /* Remove `data_size` bytes from the beginning of the buffer. */
0897    void mbuf_remove(struct mbuf *, size_t data_size);
0898    
0899    /*
0900     * Resize an Mbuf.
0901     *
0902     * If `new_size` is smaller than buffer's `len`, the
0903     * resize is not performed.
0904     */
0905    void mbuf_resize(struct mbuf *, size_t new_size);
0906    
0907    /* Shrink an Mbuf by resizing its `size` to `len`. */
0908    void mbuf_trim(struct mbuf *);
0909    
0910 #if defined(__cplusplus)
0911 }
0912 #endif /* __cplusplus */
0913 
0914 #endif /* CS_COMMON_MBUF_H_ */
0915 /*
0916  * Copyright (c) 2014 Cesanta Software Limited
0917  * All rights reserved
0918  */
0919 
0920 #ifndef CS_COMMON_SHA1_H_
0921 #define CS_COMMON_SHA1_H_
0922 
0923 #ifndef DISABLE_SHA1
0924 
0925 
0926 #ifdef __cplusplus
0927 extern "C" {
0928 #endif /* __cplusplus */
0929    
0930    typedef struct {
0931       uint32_t state[5];
0932       uint32_t count[2];
0933       unsigned char buffer[64];
0934    } cs_sha1_ctx;
0935    
0936    void cs_sha1_init(cs_sha1_ctx *);
0937    void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
0938    void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
0939    void cs_hmac_sha1(const unsigned char *key, size_t key_len,
0940                      const unsigned char *text, size_t text_len,
0941                      unsigned char out[20]);
0942 #ifdef __cplusplus
0943 }
0944 #endif /* __cplusplus */
0945 
0946 #endif /* DISABLE_SHA1 */
0947 
0948 #endif /* CS_COMMON_SHA1_H_ */
0949 /*
0950  * Copyright (c) 2014 Cesanta Software Limited
0951  * All rights reserved
0952  */
0953 
0954 #ifndef CS_COMMON_MD5_H_
0955 #define CS_COMMON_MD5_H_
0956 
0957 
0958 #ifdef __cplusplus
0959 extern "C" {
0960 #endif /* __cplusplus */
0961    
0962    typedef struct MD5Context {
0963       uint32_t buf[4];
0964       uint32_t bits[2];
0965       unsigned char in[64];
0966    } MD5_CTX;
0967    
0968    void MD5_Init(MD5_CTX *c);
0969    void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
0970    void MD5_Final(unsigned char *md, MD5_CTX *c);
0971    
0972    /*
0973     * Return stringified MD5 hash for NULL terminated list of pointer/length pairs.
0974     * A length should be specified as size_t variable.
0975     * Example:
0976     *
0977     *    char buf[33];
0978     *    cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL);
0979     */
0980    char *cs_md5(char buf[33], ...);
0981    
0982    /*
0983     * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
0984     * because each byte of input takes 2 bytes in string representation
0985     * plus 1 byte for the terminating \0 character.
0986     */
0987    void cs_to_hex(char *to, const unsigned char *p, size_t len);
0988    
0989 #ifdef __cplusplus
0990 }
0991 #endif /* __cplusplus */
0992 
0993 #endif /* CS_COMMON_MD5_H_ */
0994 /*
0995  * Copyright (c) 2014 Cesanta Software Limited
0996  * All rights reserved
0997  */
0998 
0999 #ifndef CS_COMMON_BASE64_H_
1000 #define CS_COMMON_BASE64_H_
1001 
1002 #ifndef DISABLE_BASE64
1003 
1004 #include <stdio.h>
1005 
1006 #ifdef __cplusplus
1007 extern "C" {
1008 #endif
1009    
1010    typedef void (*cs_base64_putc_t)(char, void *);
1011    
1012    struct cs_base64_ctx {
1013       /* cannot call it putc because it's a macro on some environments */
1014       cs_base64_putc_t b64_putc;
1015       unsigned char chunk[3];
1016       int chunk_size;
1017       void *user_data;
1018    };
1019    
1020    void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc,
1021                        void *user_data);
1022    void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len);
1023    void cs_base64_finish(struct cs_base64_ctx *ctx);
1024    
1025    void cs_base64_encode(const unsigned char *src, int src_len, char *dst);
1026    void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len);
1027    int cs_base64_decode(const unsigned char *s, int len, char *dst);
1028    
1029 #ifdef __cplusplus
1030 }
1031 #endif
1032 
1033 #endif /* DISABLE_BASE64 */
1034 
1035 #endif /* CS_COMMON_BASE64_H_ */
1036 /*
1037  * Copyright (c) 2015 Cesanta Software Limited
1038  * All rights reserved
1039  */
1040 
1041 #ifndef CS_COMMON_STR_UTIL_H_
1042 #define CS_COMMON_STR_UTIL_H_
1043 
1044 #include <stdarg.h>
1045 #include <stdlib.h>
1046 
1047 #ifdef __cplusplus
1048 extern "C" {
1049 #endif
1050    
1051    size_t c_strnlen(const char *s, size_t maxlen);
1052    int c_snprintf(char *buf, size_t buf_size, const char *format, ...);
1053    int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap);
1054    /*
1055     * Find the first occurrence of find in s, where the search is limited to the
1056     * first slen characters of s.
1057     */
1058    const char *c_strnstr(const char *s, const char *find, size_t slen);
1059    
1060 #ifdef __cplusplus
1061 }
1062 #endif
1063 
1064 #endif /* CS_COMMON_STR_UTIL_H_ */
1065 /*
1066  * Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
1067  * Copyright (c) 2013 Cesanta Software Limited
1068  * All rights reserved
1069  *
1070  * This library is dual-licensed: you can redistribute it and/or modify
1071  * it under the terms of the GNU General Public License version 2 as
1072  * published by the Free Software Foundation. For the terms of this
1073  * license, see <http: *www.gnu.org/licenses/>.
1074  *
1075  * You are free to use this library under the terms of the GNU General
1076  * Public License, but WITHOUT ANY WARRANTY; without even the implied
1077  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1078  * See the GNU General Public License for more details.
1079  *
1080  * Alternatively, you can license this library under a commercial
1081  * license, as set out in <http://cesanta.com/products.html>.
1082  */
1083 
1084 #ifndef CS_MONGOOSE_DEPS_FROZEN_FROZEN_H_
1085 #define CS_MONGOOSE_DEPS_FROZEN_FROZEN_H_
1086 
1087 #ifdef __cplusplus
1088 extern "C" {
1089 #endif /* __cplusplus */
1090    
1091 #include <stdarg.h>
1092    
1093    enum json_type {
1094       JSON_TYPE_EOF = 0, /* End of parsed tokens marker */
1095       JSON_TYPE_STRING = 1,
1096       JSON_TYPE_NUMBER = 2,
1097       JSON_TYPE_OBJECT = 3,
1098       JSON_TYPE_TRUE = 4,
1099       JSON_TYPE_FALSE = 5,
1100       JSON_TYPE_NULL = 6,
1101       JSON_TYPE_ARRAY = 7
1102    };
1103    
1104    struct json_token {
1105       const char *ptr;     /* Points to the beginning of the token */
1106       int len;             /* Token length */
1107       int num_desc;        /* For arrays and object, total number of descendants */
1108       enum json_type type; /* Type of the token, possible values above */
1109    };
1110    
1111    /* Error codes */
1112 #define JSON_STRING_INVALID -1
1113 #define JSON_STRING_INCOMPLETE -2
1114 #define JSON_TOKEN_ARRAY_TOO_SMALL -3
1115    
1116    int parse_json(const char *json_string, int json_string_length,
1117                   struct json_token *tokens_array, int size_of_tokens_array);
1118    struct json_token *parse_json2(const char *json_string, int string_length);
1119    struct json_token *find_json_token(struct json_token *toks, const char *path);
1120    
1121    int json_emit_long(char *buf, int buf_len, long value);
1122    int json_emit_double(char *buf, int buf_len, double value);
1123    int json_emit_quoted_str(char *buf, int buf_len, const char *str, int len);
1124    int json_emit_unquoted_str(char *buf, int buf_len, const char *str, int len);
1125    int json_emit(char *buf, int buf_len, const char *fmt, ...);
1126    int json_emit_va(char *buf, int buf_len, const char *fmt, va_list);
1127    
1128 #ifdef __cplusplus
1129 }
1130 #endif /* __cplusplus */
1131 
1132 #endif /* CS_MONGOOSE_DEPS_FROZEN_FROZEN_H_ */
1133 /*
1134  * Copyright (c) 2014 Cesanta Software Limited
1135  * All rights reserved
1136  * This software is dual-licensed: you can redistribute it and/or modify
1137  * it under the terms of the GNU General Public License version 2 as
1138  * published by the Free Software Foundation. For the terms of this
1139  * license, see <http://www.gnu.org/licenses/>.
1140  *
1141  * You are free to use this software under the terms of the GNU General
1142  * Public License, but WITHOUT ANY WARRANTY; without even the implied
1143  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1144  * See the GNU General Public License for more details.
1145  *
1146  * Alternatively, you can license this software under a commercial
1147  * license, as set out in <https://www.cesanta.com/license>.
1148  */
1149 
1150 /*
1151  * === Core: TCP/UDP/SSL
1152  *
1153  * NOTE: Mongoose manager is single threaded. It does not protect
1154  * its data structures by mutexes, therefore all functions that are dealing
1155  * with particular event manager should be called from the same thread,
1156  * with exception of `mg_broadcast()` function. It is fine to have different
1157  * event managers handled by different threads.
1158  */
1159 
1160 #ifndef CS_MONGOOSE_SRC_NET_H_
1161 #define CS_MONGOOSE_SRC_NET_H_
1162 
1163 #ifdef MG_ENABLE_JAVASCRIPT
1164 #define EXCLUDE_COMMON
1165 #include <v7.h>
1166 #endif
1167 
1168 
1169 #ifdef MG_ENABLE_SSL
1170 #ifdef __APPLE__
1171 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1172 #endif
1173 #include <openssl/ssl.h>
1174 #else
1175 typedef void *SSL;
1176 typedef void *SSL_CTX;
1177 #endif
1178 
1179 #ifndef MG_VPRINTF_BUFFER_SIZE
1180 #define MG_VPRINTF_BUFFER_SIZE 100
1181 #endif
1182 
1183 #ifdef MG_USE_READ_WRITE
1184 #define MG_RECV_FUNC(s, b, l, f) read(s, b, l)
1185 #define MG_SEND_FUNC(s, b, l, f) write(s, b, l)
1186 #else
1187 #define MG_RECV_FUNC(s, b, l, f) recv(s, b, l, f)
1188 #define MG_SEND_FUNC(s, b, l, f) send(s, b, l, f)
1189 #endif
1190 
1191 #ifdef __cplusplus
1192 extern "C" {
1193 #endif /* __cplusplus */
1194    
1195    union socket_address {
1196       struct sockaddr sa;
1197       struct sockaddr_in sin;
1198 #ifdef MG_ENABLE_IPV6
1199       struct sockaddr_in6 sin6;
1200 #else
1201       struct sockaddr sin6;
1202 #endif
1203    };
1204    
1205    /* Describes chunk of memory */
1206    struct mg_str {
1207       const char *p; /* Memory chunk pointer */
1208       size_t len;    /* Memory chunk length */
1209    };
1210    
1211    struct mg_connection;
1212    
1213    /*
1214     * Callback function (event handler) prototype, must be defined by user.
1215     * Mongoose calls event handler, passing events defined below.
1216     */
1217    typedef void (*mg_event_handler_t)(struct mg_connection *, int ev, void *);
1218    
1219    /* Events. Meaning of event parameter (evp) is given in the comment. */
1220 #define MG_EV_POLL 0    /* Sent to each connection on each mg_mgr_poll() call */
1221 #define MG_EV_ACCEPT 1  /* New connection accepted. union socket_address * */
1222 #define MG_EV_CONNECT 2 /* connect() succeeded or failed. int *  */
1223 #define MG_EV_RECV 3    /* Data has benn received. int *num_bytes */
1224 #define MG_EV_SEND 4    /* Data has been written to a socket. int *num_bytes */
1225 #define MG_EV_CLOSE 5   /* Connection is closed. NULL */
1226 #define MG_EV_TIMER 6   /* now >= conn->ev_timer_time. double * */
1227    
1228    /*
1229     * Mongoose event manager.
1230     */
1231    struct mg_mgr {
1232       struct mg_connection *active_connections;
1233       const char *hexdump_file; /* Debug hexdump file path */
1234 #ifndef MG_DISABLE_SOCKETPAIR
1235       sock_t ctl[2]; /* Socketpair for mg_wakeup() */
1236 #endif
1237       void *user_data; /* User data */
1238       void *mgr_data;  /* Implementation-specific event manager's data. */
1239 #ifdef MG_ENABLE_JAVASCRIPT
1240       struct v7 *v7;
1241 #endif
1242    };
1243    
1244    /*
1245     * Mongoose connection.
1246     */
1247    struct mg_connection {
1248       struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
1249       struct mg_connection *listener;    /* Set only for accept()-ed connections */
1250       struct mg_mgr *mgr;                /* Pointer to containing manager */
1251       
1252       sock_t sock; /* Socket to the remote peer */
1253       int err;
1254       union socket_address sa; /* Remote peer address */
1255       size_t recv_mbuf_limit;  /* Max size of recv buffer */
1256       struct mbuf recv_mbuf;   /* Received data */
1257       struct mbuf send_mbuf;   /* Data scheduled for sending */
1258       SSL *ssl;
1259       SSL_CTX *ssl_ctx;
1260       time_t last_io_time;              /* Timestamp of the last socket IO */
1261       double ev_timer_time;             /* Timestamp of the future MG_EV_TIMER */
1262       mg_event_handler_t proto_handler; /* Protocol-specific event handler */
1263       void *proto_data;                 /* Protocol-specific data */
1264       void (*proto_data_destructor)(void *proto_data);
1265       mg_event_handler_t handler; /* Event handler function */
1266       void *user_data;            /* User-specific data */
1267       union {
1268          void *v;
1269          /*
1270           * the C standard is fussy about fitting function pointers into
1271           * void pointers, since some archs might have fat pointers for functions.
1272           */
1273          mg_event_handler_t f;
1274       } priv_1;       /* Used by mg_enable_multithreading() */
1275       void *priv_2;   /* Used by mg_enable_multithreading() */
1276       void *mgr_data; /* Implementation-specific event manager's data. */
1277       unsigned long flags;
1278       /* Flags set by Mongoose */
1279 #define MG_F_LISTENING (1 << 0)          /* This connection is listening */
1280 #define MG_F_UDP (1 << 1)                /* This connection is UDP */
1281 #define MG_F_RESOLVING (1 << 2)          /* Waiting for async resolver */
1282 #define MG_F_CONNECTING (1 << 3)         /* connect() call in progress */
1283 #define MG_F_SSL_HANDSHAKE_DONE (1 << 4) /* SSL specific */
1284 #define MG_F_WANT_READ (1 << 5)          /* SSL specific */
1285 #define MG_F_WANT_WRITE (1 << 6)         /* SSL specific */
1286 #define MG_F_IS_WEBSOCKET (1 << 7)       /* Websocket specific */
1287       
1288       /* Flags that are settable by user */
1289 #define MG_F_SEND_AND_CLOSE (1 << 10)      /* Push remaining data and close  */
1290 #define MG_F_CLOSE_IMMEDIATELY (1 << 11)   /* Disconnect */
1291 #define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
1292 #define MG_F_DELETE_CHUNK (1 << 13)        /* HTTP specific */
1293       
1294 #define MG_F_USER_1 (1 << 20) /* Flags left for application */
1295 #define MG_F_USER_2 (1 << 21)
1296 #define MG_F_USER_3 (1 << 22)
1297 #define MG_F_USER_4 (1 << 23)
1298 #define MG_F_USER_5 (1 << 24)
1299 #define MG_F_USER_6 (1 << 25)
1300    };
1301    
1302    /*
1303     * Initialize Mongoose manager. Side effect: ignores SIGPIPE signal.
1304     * `mgr->user_data` field will be initialized with `user_data` parameter.
1305     * That is an arbitrary pointer, where user code can associate some data
1306     * with the particular Mongoose manager. For example, a C++ wrapper class
1307     * could be written, in which case `user_data` can hold a pointer to the
1308     * class instance.
1309     */
1310    void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
1311    
1312    /*
1313     * De-initializes Mongoose manager.
1314     *
1315     * Close and deallocate all active connections.
1316     */
1317    void mg_mgr_free(struct mg_mgr *);
1318    
1319    /*
1320     * This function performs the actual IO, and must be called in a loop
1321     * (an event loop). Returns the current timestamp.
1322     * `milli` is the maximum number of milliseconds to sleep.
1323     * `mg_mgr_poll()` checks all connection for IO readiness. If at least one
1324     * of the connections is IO-ready, `mg_mgr_poll()` triggers respective
1325     * event handlers and returns.
1326     */
1327    time_t mg_mgr_poll(struct mg_mgr *, int milli);
1328    
1329 #ifndef MG_DISABLE_SOCKETPAIR
1330    /*
1331     * Pass a message of a given length to all connections.
1332     *
1333     * Must be called from a thread that does NOT call `mg_mgr_poll()`.
1334     * Note that `mg_broadcast()` is the only function
1335     * that can be, and must be, called from a different (non-IO) thread.
1336     *
1337     * `func` callback function will be called by the IO thread for each
1338     * connection. When called, event would be `MG_EV_POLL`, and message will
1339     * be passed as `ev_data` pointer. Maximum message size is capped
1340     * by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
1341     */
1342    void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
1343 #endif
1344    
1345    /*
1346     * Iterate over all active connections.
1347     *
1348     * Returns next connection from the list
1349     * of active connections, or `NULL` if there is no more connections. Below
1350     * is the iteration idiom:
1351     *
1352     * ```c
1353     * for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
1354     *   // Do something with connection `c`
1355     * }
1356     * ```
1357     */
1358    struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
1359    
1360    /*
1361     * Optional parameters to `mg_add_sock_opt()`.
1362     *
1363     * `flags` is an initial `struct mg_connection::flags` bitmask to set,
1364     * see `MG_F_*` flags definitions.
1365     */
1366    struct mg_add_sock_opts {
1367       void *user_data;           /* Initial value for connection's user_data */
1368       unsigned int flags;        /* Initial connection flags */
1369       const char **error_string; /* Placeholder for the error string */
1370    };
1371    
1372    /*
1373     * Create a connection, associate it with the given socket and event handler,
1374     * and add it to the manager.
1375     *
1376     * For more options see the `mg_add_sock_opt` variant.
1377     */
1378    struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
1379    
1380    /*
1381     * Create a connection, associate it with the given socket and event handler,
1382     * and add to the manager.
1383     *
1384     * See the `mg_add_sock_opts` structure for a description of the options.
1385     */
1386    struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
1387                                          mg_event_handler_t,
1388                                          struct mg_add_sock_opts);
1389    
1390    /*
1391     * Optional parameters to `mg_bind_opt()`.
1392     *
1393     * `flags` is an initial `struct mg_connection::flags` bitmask to set,
1394     * see `MG_F_*` flags definitions.
1395     */
1396    struct mg_bind_opts {
1397       void *user_data;           /* Initial value for connection's user_data */
1398       unsigned int flags;        /* Extra connection flags */
1399       const char **error_string; /* Placeholder for the error string */
1400 #ifdef MG_ENABLE_SSL
1401       /* SSL settings. */
1402       const char *ssl_cert;    /* Server certificate to present to clients */
1403       const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
1404 #endif
1405    };
1406    
1407    /*
1408     * Create listening connection.
1409     *
1410     * See `mg_bind_opt` for full documentation.
1411     */
1412    struct mg_connection *mg_bind(struct mg_mgr *, const char *,
1413                                  mg_event_handler_t);
1414    /*
1415     * Create listening connection.
1416     *
1417     * `address` parameter tells which address to bind to. It's format is the same
1418     * as for the `mg_connect()` call, where `HOST` part is optional. `address`
1419     * can be just a port number, e.g. `:8000`. To bind to a specific interface,
1420     * an IP address can be specified, e.g. `1.2.3.4:8000`. By default, a TCP
1421     * connection is created. To create UDP connection, prepend `udp://` prefix,
1422     * e.g. `udp://:8000`. To summarize, `address` paramer has following format:
1423     * `[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or `udp`.
1424     *
1425     * See the `mg_bind_opts` structure for a description of the optional
1426     * parameters.
1427     *
1428     * Return a new listening connection, or `NULL` on error.
1429     * NOTE: Connection remains owned by the manager, do not free().
1430     */
1431    struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
1432                                      mg_event_handler_t handler,
1433                                      struct mg_bind_opts opts);
1434    
1435    /* Optional parameters to `mg_connect_opt()` */
1436    struct mg_connect_opts {
1437       void *user_data;           /* Initial value for connection's user_data */
1438       unsigned int flags;        /* Extra connection flags */
1439       const char **error_string; /* Placeholder for the error string */
1440 #ifdef MG_ENABLE_SSL
1441       /* SSL settings. */
1442       const char *ssl_cert;    /* Client certificate to present to the server */
1443       const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
1444       
1445       /*
1446        * Server name verification. If ssl_ca_cert is set and the certificate has
1447        * passed verification, its subject will be verified against this string.
1448        * By default (if ssl_server_name is NULL) hostname part of the address will
1449        * be used. Wildcard matching is supported. A special value of "*" disables
1450        * name verification.
1451        */
1452       const char *ssl_server_name;
1453 #endif
1454    };
1455    
1456    /*
1457     * Connect to a remote host.
1458     *
1459     * See `mg_connect_opt()` for full documentation.
1460     */
1461    struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
1462                                     mg_event_handler_t handler);
1463    
1464    /*
1465     * Connect to a remote host.
1466     *
1467     * `address` format is `[PROTO://]HOST:PORT`. `PROTO` could be `tcp` or `udp`.
1468     * `HOST` could be an IP address,
1469     * IPv6 address (if Mongoose is compiled with `-DMG_ENABLE_IPV6`), or a host
1470     * name. If `HOST` is a name, Mongoose will resolve it asynchronously. Examples
1471     * of valid addresses: `google.com:80`, `udp://1.2.3.4:53`, `10.0.0.1:443`,
1472     * `[::1]:80`
1473     *
1474     * See the `mg_connect_opts` structure for a description of the optional
1475     * parameters.
1476     *
1477     * Returns a new outbound connection, or `NULL` on error.
1478     *
1479     * NOTE: Connection remains owned by the manager, do not free().
1480     *
1481     * NOTE: To enable IPv6 addresses, `-DMG_ENABLE_IPV6` should be specified
1482     * in the compilation flags.
1483     *
1484     * NOTE: New connection will receive `MG_EV_CONNECT` as it's first event
1485     * which will report connect success status.
1486     * If asynchronous resolution fail, or `connect()` syscall fail for whatever
1487     * reason (e.g. with `ECONNREFUSED` or `ENETUNREACH`), then `MG_EV_CONNECT`
1488     * event report failure. Code example below:
1489     *
1490     * ```c
1491     * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
1492     *   int connect_status;
1493     *
1494     *   switch (ev) {
1495     *     case MG_EV_CONNECT:
1496     *       connect_status = * (int *) ev_data;
1497     *       if (connect_status == 0) {
1498     *         // Success
1499     *       } else  {
1500     *         // Error
1501     *         printf("connect() error: %s\n", strerror(connect_status));
1502     *       }
1503     *       break;
1504     *     ...
1505     *   }
1506     * }
1507     *
1508     *   ...
1509     *   mg_connect(mgr, "my_site.com:80", ev_handler);
1510     * ```
1511     */
1512    struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
1513                                         mg_event_handler_t handler,
1514                                         struct mg_connect_opts opts);
1515    
1516    /*
1517     * Enable SSL for a given connection.
1518     * `cert` is a server certificate file name for a listening connection,
1519     * or a client certificate file name for an outgoing connection.
1520     * Certificate files must be in PEM format. Server certificate file
1521     * must contain a certificate, concatenated with a private key, optionally
1522     * concatenated with parameters.
1523     * `ca_cert` is a CA certificate, or NULL if peer verification is not
1524     * required.
1525     * Return: NULL on success, or error message on error.
1526     */
1527    const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
1528                           const char *ca_cert);
1529    
1530    /*
1531     * Send data to the connection.
1532     *
1533     * Note that sending functions do not actually push data to the socket.
1534     * They just append data to the output buffer. MG_EV_SEND will be delivered when
1535     * the data has actually been pushed out.
1536     */
1537    void mg_send(struct mg_connection *, const void *buf, int len);
1538    
1539    /* Enables format string warnings for mg_printf */
1540 #if defined(__GNUC__)
1541    __attribute__((format(printf, 2, 3)))
1542 #endif
1543    /* don't separate from mg_printf declaration */
1544    
1545    /*
1546     * Send `printf`-style formatted data to the connection.
1547     *
1548     * See `mg_send` for more details on send semantics.
1549     */
1550    int mg_printf(struct mg_connection *, const char *fmt, ...);
1551    
1552    /* Same as `mg_printf()`, but takes `va_list ap` as an argument. */
1553    int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
1554    
1555    /*
1556     * Create a socket pair.
1557     * `sock_type` can be either `SOCK_STREAM` or `SOCK_DGRAM`.
1558     * Return 0 on failure, 1 on success.
1559     */
1560    int mg_socketpair(sock_t[2], int sock_type);
1561    
1562    /*
1563     * Convert domain name into IP address.
1564     *
1565     * This is a utility function. If compilation flags have
1566     * `-DMG_ENABLE_GETADDRINFO`, then `getaddrinfo()` call is used for name
1567     * resolution. Otherwise, `gethostbyname()` is used.
1568     *
1569     * CAUTION: this function can block.
1570     * Return 1 on success, 0 on failure.
1571     */
1572 #ifndef MG_DISABLE_SYNC_RESOLVER
1573    int mg_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
1574 #endif
1575    
1576    /*
1577     * Verify given IP address against the ACL.
1578     *
1579     * `remote_ip` - an IPv4 address to check, in host byte order
1580     * `acl` - a comma separated list of IP subnets: `x.x.x.x/x` or `x.x.x.x`.
1581     * Each subnet is
1582     * prepended by either a - or a + sign. A plus sign means allow, where a
1583     * minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
1584     * this means to deny only that single IP address.
1585     * Subnet masks may vary from 0 to 32, inclusive. The default setting
1586     * is to allow all accesses. On each request the full list is traversed,
1587     * and the last match wins. Example:
1588     *
1589     * `-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
1590     *
1591     * To learn more about subnet masks, see the
1592     * link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork]
1593     *
1594     * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
1595     */
1596    int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
1597    
1598    /*
1599     * Enable multi-threaded handling for the given listening connection `nc`.
1600     * For each accepted connection, Mongoose will create a separate thread
1601     * and run event handler in that thread. Thus, if an event hanler is doing
1602     * a blocking call or some long computation, that will not slow down
1603     * other connections.
1604     */
1605    void mg_enable_multithreading(struct mg_connection *nc);
1606    
1607 #ifdef MG_ENABLE_JAVASCRIPT
1608    /*
1609     * Enable server-side JavaScript scripting.
1610     * Requires `-DMG_ENABLE_JAVASCRIPT` compilation flag, and V7 engine sources.
1611     * v7 instance must not be destroyed during manager's lifetime.
1612     * Return V7 error.
1613     */
1614    enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
1615                                     const char *init_js_file_name);
1616 #endif
1617    
1618    /*
1619     * Schedule MG_EV_TIMER event to be delivered at `timestamp` time.
1620     * `timestamp` is a UNIX time (a number of seconds since Epoch). It is
1621     * `double` instead of `time_t` to allow for sub-second precision.
1622     * Return the old timer value.
1623     *
1624     * Example: set connect timeout to 1.5 seconds:
1625     *
1626     * ```
1627     *  c = mg_connect(&mgr, "cesanta.com", ev_handler);
1628     *  mg_set_timer(c, mg_time() + 1.5);
1629     *  ...
1630     *
1631     *  void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
1632     *  switch (ev) {
1633     *    case MG_EV_CONNECT:
1634     *      mg_set_timer(c, 0);  // Clear connect timer
1635     *      break;
1636     *    case MG_EV_TIMER:
1637     *      log("Connect timeout");
1638     *      c->flags |= MG_F_CLOSE_IMMEDIATELY;
1639     *      break;
1640     * ```
1641     */
1642    double mg_set_timer(struct mg_connection *c, double timestamp);
1643    
1644    /*
1645     * A sub-second precision version of time().
1646     */
1647    double mg_time();
1648    
1649 #ifdef __cplusplus
1650 }
1651 #endif /* __cplusplus */
1652 
1653 #endif /* CS_MONGOOSE_SRC_NET_H_ */
1654 /*
1655  * Copyright (c) 2014-2016 Cesanta Software Limited
1656  * All rights reserved
1657  */
1658 
1659 #ifndef CS_MONGOOSE_SRC_NET_IF_H_
1660 #define CS_MONGOOSE_SRC_NET_IF_H_
1661 
1662 /*
1663  * Internal async networking core interface.
1664  * Consists of calls made by the core, which should not block,
1665  * and callbacks back into the core ("..._cb").
1666  * Callbacks may (will) cause methods to be invoked from within,
1667  * but methods are not allowed to invoke callbacks inline.
1668  *
1669  * Implementation must ensure that only one callback is invoked at any time.
1670  */
1671 
1672 #ifdef __cplusplus
1673 extern "C" {
1674 #endif /* __cplusplus */
1675    
1676    /* Request that a TCP connection is made to the specified address. */
1677    void mg_if_connect_tcp(struct mg_connection *nc,
1678                           const union socket_address *sa);
1679    /* Open a UDP socket. Doesn't actually connect anything. */
1680    void mg_if_connect_udp(struct mg_connection *nc);
1681    /* Callback invoked by connect methods. err = 0 -> ok, != 0 -> error. */
1682    void mg_if_connect_cb(struct mg_connection *nc, int err);
1683    
1684    /* Set up a listening TCP socket on a given address. rv = 0 -> ok. */
1685    int mg_if_listen_tcp(struct mg_connection *nc, union socket_address *sa);
1686    
1687    /*
1688     * Deliver a new TCP connection. Returns NULL in case on error (unable to
1689     * create connection, in which case interface state should be discarded.
1690     * This is phase 1 of the two-phase process - MG_EV_ACCEPT will be delivered
1691     * when mg_if_accept_tcp_cb is invoked.
1692     */
1693    struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc);
1694    void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa,
1695                             size_t sa_len);
1696    
1697    /* Request that a "listening" UDP socket be created. */
1698    int mg_if_listen_udp(struct mg_connection *nc, union socket_address *sa);
1699    
1700    /* Send functions for TCP and UDP. Sent data is copied before return. */
1701    void mg_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len);
1702    void mg_if_udp_send(struct mg_connection *nc, const void *buf, size_t len);
1703    /* Callback that reports that data has been put on the wire. */
1704    void mg_if_sent_cb(struct mg_connection *nc, int num_sent);
1705    
1706    /*
1707     * Receive callback.
1708     * buf must be heap-allocated and ownership is transferred to the core.
1709     * Core will acknowledge consumption by calling mg_if_recved.
1710     */
1711    void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len);
1712    void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len,
1713                           union socket_address *sa, size_t sa_len);
1714    void mg_if_recved(struct mg_connection *nc, size_t len);
1715    
1716    /* Deliver a POLL event to the connection. */
1717    void mg_if_poll(struct mg_connection *nc, time_t now);
1718    
1719    /* Deliver a TIMER event to the connection. */
1720    void mg_if_timer(struct mg_connection *c, double now);
1721    
1722    /* Perform interface-related connection initialization. Return 1 on success. */
1723    int mg_if_create_conn(struct mg_connection *nc);
1724    
1725    /* Perform interface-related cleanup on connection before destruction. */
1726    void mg_if_destroy_conn(struct mg_connection *nc);
1727    
1728    void mg_close_conn(struct mg_connection *nc);
1729    
1730    /* Put connection's address into *sa, local (remote = 0) or remote. */
1731    void mg_if_get_conn_addr(struct mg_connection *nc, int remote,
1732                             union socket_address *sa);
1733    
1734    /* Associate a socket to a connection. */
1735    void mg_sock_set(struct mg_connection *nc, sock_t sock);
1736    
1737 #ifdef __cplusplus
1738 }
1739 #endif /* __cplusplus */
1740 
1741 #endif /* CS_MONGOOSE_SRC_NET_IF_H_ */
1742 /*
1743  * Copyright (c) 2014 Cesanta Software Limited
1744  * All rights reserved
1745  */
1746 
1747 /*
1748  * === URI
1749  */
1750 
1751 #ifndef CS_MONGOOSE_SRC_URI_H_
1752 #define CS_MONGOOSE_SRC_URI_H_
1753 
1754 
1755 #ifdef __cplusplus
1756 extern "C" {
1757 #endif /* __cplusplus */
1758    
1759    /*
1760     * Parses an URI and fills string chunks with locations of the respective
1761     * uri components within the input uri string. NULL pointers will be
1762     * ignored.
1763     *
1764     * General syntax:
1765     *
1766     *     [scheme://[user_info@]]host[:port][/path][?query][#fragment]
1767     *
1768     * Example:
1769     *
1770     *     foo.com:80
1771     *     tcp://foo.com:1234
1772     *     http://foo.com:80/bar?baz=1
1773     *     https://user:pw@foo.com:443/blah
1774     *
1775     * `path` will include the leading slash. `query` won't include the leading `?`.
1776     * `host` can contain embedded colons if surrounded by square brackets in order
1777     * to support IPv6 literal addresses.
1778     *
1779     *
1780     * Returns 0 on success, -1 on error.
1781     */
1782    int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
1783                     struct mg_str *user_info, struct mg_str *host,
1784                     unsigned int *port, struct mg_str *path, struct mg_str *query,
1785                     struct mg_str *fragment);
1786    
1787    int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out);
1788    
1789 #ifdef __cplusplus
1790 }
1791 #endif /* __cplusplus */
1792 #endif /* CS_MONGOOSE_SRC_URI_H_ */
1793 /*
1794  * Copyright (c) 2014 Cesanta Software Limited
1795  * All rights reserved
1796  */
1797 
1798 /*
1799  * === Utilities
1800  */
1801 
1802 #ifndef CS_MONGOOSE_SRC_UTIL_H_
1803 #define CS_MONGOOSE_SRC_UTIL_H_
1804 
1805 #include <stdio.h>
1806 
1807 
1808 #ifdef __cplusplus
1809 extern "C" {
1810 #endif /* __cplusplus */
1811    
1812 #ifndef MAX_PATH_SIZE
1813 #define MAX_PATH_SIZE 500
1814 #endif
1815    
1816    /*
1817     * Fetch substring from input string `s`, `end` into `v`.
1818     * Skips initial delimiter characters. Records first non-delimiter character
1819     * as the beginning of substring `v`. Then scans the rest of the string
1820     * until a delimiter character or end-of-string is found.
1821     * `delimiters` is a 0-terminated string containing delimiter characters.
1822     * Either one of `delimiters` or `end_string` terminates the search.
1823     * Return an `s` pointer, advanced forward where parsing stopped.
1824     */
1825    const char *mg_skip(const char *s, const char *end_string,
1826                        const char *delimiters, struct mg_str *v);
1827    
1828    /*
1829     * Cross-platform version of `strncasecmp()`.
1830     */
1831    int mg_ncasecmp(const char *s1, const char *s2, size_t len);
1832    
1833    /*
1834     * Cross-platform version of `strcasecmp()`.
1835     */
1836    int mg_casecmp(const char *s1, const char *s2);
1837    
1838    /*
1839     * Cross-platform version of `strcmp()` where where first string is
1840     * specified by `struct mg_str`.
1841     */
1842    int mg_vcmp(const struct mg_str *str2, const char *str1);
1843    
1844    /*
1845     * Cross-platform version of `strncasecmp()` where first string is
1846     * specified by `struct mg_str`.
1847     */
1848    int mg_vcasecmp(const struct mg_str *str2, const char *str1);
1849    
1850    /*
1851     * Decode base64-encoded string `s`, `len` into the destination `dst`.
1852     * Destination has to have enough space to hold decoded buffer.
1853     * Decoding stops either when all string has been decoded, or invalid
1854     * character appeared.
1855     * Destination is '\0'-terminated.
1856     * Return number of decoded characters. On success, that should be equal to
1857     * `len`. On error (invalid character) the return value is smaller then `len`.
1858     */
1859    int mg_base64_decode(const unsigned char *s, int len, char *dst);
1860    
1861    /*
1862     * Base64-encode chunk of memory `src`, `src_len` into the destination `dst`.
1863     * Destination has to have enough space to hold encoded buffer.
1864     * Destination is '\0'-terminated.
1865     */
1866    void mg_base64_encode(const unsigned char *src, int src_len, char *dst);
1867    
1868 #ifndef MG_DISABLE_FILESYSTEM
1869    /*
1870     * Perform a 64-bit `stat()` call against given file.
1871     *
1872     * `path` should be UTF8 encoded.
1873     *
1874     * Return value is the same as for `stat()` syscall.
1875     */
1876    int mg_stat(const char *path, cs_stat_t *st);
1877    
1878    /*
1879     * Open the given file and return a file stream.
1880     *
1881     * `path` and `mode` should be UTF8 encoded.
1882     *
1883     * Return value is the same as for the `fopen()` call.
1884     */
1885    FILE *mg_fopen(const char *path, const char *mode);
1886    
1887    /*
1888     * Open the given file and return a file stream.
1889     *
1890     * `path` should be UTF8 encoded.
1891     *
1892     * Return value is the same as for the `open()` syscall.
1893     */
1894    int mg_open(const char *path, int flag, int mode);
1895 #endif /* MG_DISABLE_FILESYSTEM */
1896    
1897 #if defined(_WIN32) && !defined(MG_ENABLE_THREADS)
1898 #define MG_ENABLE_THREADS
1899 #endif
1900    
1901 #ifdef MG_ENABLE_THREADS
1902    /*
1903     * Start a new detached thread.
1904     * Arguments and semantic is the same as pthead's `pthread_create()`.
1905     * `thread_func` is a thread function, `thread_func_param` is a parameter
1906     * that is passed to the thread function.
1907     */
1908    void *mg_start_thread(void *(*thread_func)(void *), void *thread_func_param);
1909 #endif
1910    
1911    void mg_set_close_on_exec(sock_t);
1912    
1913 #define MG_SOCK_STRINGIFY_IP 1
1914 #define MG_SOCK_STRINGIFY_PORT 2
1915 #define MG_SOCK_STRINGIFY_REMOTE 4
1916    /*
1917     * Convert connection's local or remote address into string.
1918     *
1919     * The `flags` parameter is a bit mask that controls the behavior,
1920     * see `MG_SOCK_STRINGIFY_*` definitions.
1921     *
1922     * - MG_SOCK_STRINGIFY_IP - print IP address
1923     * - MG_SOCK_STRINGIFY_PORT - print port number
1924     * - MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address
1925     *
1926     * If both port number and IP address are printed, they are separated by `:`.
1927     * If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported.
1928     */
1929    void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
1930                             int flags);
1931 #ifndef MG_DISABLE_SOCKET_IF /* Legacy interface. */
1932    void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
1933 #endif
1934    
1935    /*
1936     * Convert socket's address into string.
1937     *
1938     * `flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT.
1939     */
1940    void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
1941                             int flags);
1942    
1943    /*
1944     * Generates human-readable hexdump of memory chunk.
1945     *
1946     * Takes a memory buffer `buf` of length `len` and creates a hex dump of that
1947     * buffer in `dst`. Generated output is a-la hexdump(1).
1948     * Return length of generated string, excluding terminating `\0`. If returned
1949     * length is bigger than `dst_len`, overflow bytes are discarded.
1950     */
1951    int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
1952    
1953    /*
1954     * Generates human-readable hexdump of the data sent or received by connection.
1955     * `path` is a file name where hexdump should be written. `num_bytes` is
1956     * a number of bytes sent/received. `ev` is one of the `MG_*` events sent to
1957     * an event handler. This function is supposed to be called from the
1958     * event handler.
1959     */
1960    void mg_hexdump_connection(struct mg_connection *nc, const char *path,
1961                               const void *buf, int num_bytes, int ev);
1962    /*
1963     * Print message to buffer. If buffer is large enough to hold the message,
1964     * return buffer. If buffer is to small, allocate large enough buffer on heap,
1965     * and return allocated buffer.
1966     * This is a supposed use case:
1967     *
1968     *    char buf[5], *p = buf;
1969     *    p = mg_avprintf(&p, sizeof(buf), "%s", "hi there");
1970     *    use_p_somehow(p);
1971     *    if (p != buf) {
1972     *      free(p);
1973     *    }
1974     *
1975     * The purpose of this is to avoid malloc-ing if generated strings are small.
1976     */
1977    int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
1978    
1979    /*
1980     * Return true if target platform is big endian.
1981     */
1982    int mg_is_big_endian(void);
1983    
1984    /*
1985     * A helper function for traversing a comma separated list of values.
1986     * It returns a list pointer shifted to the next value, or NULL if the end
1987     * of the list found.
1988     * Value is stored in val vector. If value has form "x=y", then eq_val
1989     * vector is initialized to point to the "y" part, and val vector length
1990     * is adjusted to point only to "x".
1991     * If list is just a comma separated list of entries, like "aa,bb,cc" then
1992     * `eq_val` will contain zero-length string.
1993     *
1994     * The purpose of this function is to parse comma separated string without
1995     * any copying/memory allocation.
1996     */
1997    const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
1998                                         struct mg_str *eq_val);
1999    
2000    /*
2001     * Match 0-terminated string (mg_match_prefix) or string with given length
2002     * mg_match_prefix_n against a glob pattern.
2003     * Match is case-insensitive. Return number of bytes matched, or -1 if no match.
2004     */
2005    int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
2006    int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str);
2007    
2008    /*
2009     * A helper function for creating mg_str struct from plain C string.
2010     * `NULL` is allowed and becomes `{NULL, 0}`.
2011     */
2012    struct mg_str mg_mk_str(const char *s);
2013    
2014    /* Macro for initializing mg_str. */
2015 #define MG_MK_STR(str_literal) \
2016 { str_literal, sizeof(str_literal) - 1 }
2017    
2018 #ifdef __cplusplus
2019 }
2020 #endif /* __cplusplus */
2021 #endif /* CS_MONGOOSE_SRC_UTIL_H_ */
2022 /*
2023  * Copyright (c) 2014 Cesanta Software Limited
2024  * All rights reserved
2025  */
2026 
2027 /*
2028  * === HTTP + Websocket
2029  */
2030 
2031 #ifndef CS_MONGOOSE_SRC_HTTP_H_
2032 #define CS_MONGOOSE_SRC_HTTP_H_
2033 
2034 
2035 #ifdef __cplusplus
2036 extern "C" {
2037 #endif /* __cplusplus */
2038    
2039 #ifndef MG_MAX_HTTP_HEADERS
2040 #define MG_MAX_HTTP_HEADERS 20
2041 #endif
2042    
2043 #ifndef MG_MAX_HTTP_REQUEST_SIZE
2044 #define MG_MAX_HTTP_REQUEST_SIZE 1024
2045 #endif
2046    
2047 #ifndef MG_MAX_PATH
2048 #ifdef PATH_MAX
2049 #define MG_MAX_PATH PATH_MAX
2050 #else
2051 #define MG_MAX_PATH 256
2052 #endif
2053 #endif
2054    
2055 #ifndef MG_MAX_HTTP_SEND_MBUF
2056 #define MG_MAX_HTTP_SEND_MBUF 1024
2057 #endif
2058    
2059 #ifndef MG_WEBSOCKET_PING_INTERVAL_SECONDS
2060 #define MG_WEBSOCKET_PING_INTERVAL_SECONDS 5
2061 #endif
2062    
2063 #ifndef MG_CGI_ENVIRONMENT_SIZE
2064 #define MG_CGI_ENVIRONMENT_SIZE 8192
2065 #endif
2066    
2067 #ifndef MG_MAX_CGI_ENVIR_VARS
2068 #define MG_MAX_CGI_ENVIR_VARS 64
2069 #endif
2070    
2071 #ifndef MG_ENV_EXPORT_TO_CGI
2072 #define MG_ENV_EXPORT_TO_CGI "MONGOOSE_CGI"
2073 #endif
2074    
2075    /* HTTP message */
2076    struct http_message {
2077       struct mg_str message; /* Whole message: request line + headers + body */
2078       
2079       /* HTTP Request line (or HTTP response line) */
2080       struct mg_str method; /* "GET" */
2081       struct mg_str uri;    /* "/my_file.html" */
2082       struct mg_str proto;  /* "HTTP/1.1" -- for both request and response */
2083       
2084       /* For responses, code and response status message are set */
2085       int resp_code;
2086       struct mg_str resp_status_msg;
2087       
2088       /*
2089        * Query-string part of the URI. For example, for HTTP request
2090        *    GET /foo/bar?param1=val1&param2=val2
2091        *    |    uri    |     query_string     |
2092        *
2093        * Note that question mark character doesn't belong neither to the uri,
2094        * nor to the query_string
2095        */
2096       struct mg_str query_string;
2097       
2098       /* Headers */
2099       struct mg_str header_names[MG_MAX_HTTP_HEADERS];
2100       struct mg_str header_values[MG_MAX_HTTP_HEADERS];
2101       
2102       /* Message body */
2103       struct mg_str body; /* Zero-length for requests with no body */
2104    };
2105    
2106    /* WebSocket message */
2107    struct websocket_message {
2108       unsigned char *data;
2109       size_t size;
2110       unsigned char flags;
2111    };
2112    
2113    /* HTTP multipart part */
2114    struct mg_http_multipart_part {
2115       const char *file_name;
2116       const char *var_name;
2117       struct mg_str data;
2118       int status; /* <0 on error */
2119       void *user_data;
2120    };
2121    
2122    /* HTTP and websocket events. void *ev_data is described in a comment. */
2123 #define MG_EV_HTTP_REQUEST 100 /* struct http_message * */
2124 #define MG_EV_HTTP_REPLY 101   /* struct http_message * */
2125 #define MG_EV_HTTP_CHUNK 102   /* struct http_message * */
2126 #define MG_EV_SSI_CALL 105     /* char * */
2127    
2128 #define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST 111 /* NULL */
2129 #define MG_EV_WEBSOCKET_HANDSHAKE_DONE 112    /* NULL */
2130 #define MG_EV_WEBSOCKET_FRAME 113             /* struct websocket_message * */
2131 #define MG_EV_WEBSOCKET_CONTROL_FRAME 114     /* struct websocket_message * */
2132    
2133 #ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
2134 #define MG_EV_HTTP_MULTIPART_REQUEST 121 /* struct http_message */
2135 #define MG_EV_HTTP_PART_BEGIN 122        /* struct mg_http_multipart_part */
2136 #define MG_EV_HTTP_PART_DATA 123         /* struct mg_http_multipart_part */
2137 #define MG_EV_HTTP_PART_END 124          /* struct mg_http_multipart_part */
2138 #endif
2139    
2140    /*
2141     * Attach built-in HTTP event handler to the given connection.
2142     * User-defined event handler will receive following extra events:
2143     *
2144     * - MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request
2145     *  is passed as
2146     *   `struct http_message` through the handler's `void *ev_data` pointer.
2147     * - MG_EV_HTTP_MULTIPART_REQUEST: A multipart POST request has received.
2148     *   This event is sent before body is parsed. After this user
2149     *   should expect a sequence of MG_EV_HTTP_PART_BEGIN/DATA/END requests.
2150     *   This is also the last time when headers and other request fields are
2151     *   accessible.
2152     * - MG_EV_HTTP_REPLY: HTTP reply has arrived. Parsed HTTP reply is passed as
2153     *   `struct http_message` through the handler's `void *ev_data` pointer.
2154     * - MG_EV_HTTP_CHUNK: HTTP chunked-encoding chunk has arrived.
2155     *   Parsed HTTP reply is passed as `struct http_message` through the
2156     *   handler's `void *ev_data` pointer. `http_message::body` would contain
2157     *   incomplete, reassembled HTTP body.
2158     *   It will grow with every new chunk arrived, and
2159     *   potentially can consume a lot of memory. An event handler may process
2160     *   the body as chunks are coming, and signal Mongoose to delete processed
2161     *   body by setting `MG_F_DELETE_CHUNK` in `mg_connection::flags`. When
2162     *   the last zero chunk is received,
2163     *   Mongoose sends `MG_EV_HTTP_REPLY` event with
2164     *   full reassembled body (if handler did not signal to delete chunks) or
2165     *   with empty body (if handler did signal to delete chunks).
2166     * - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received websocket handshake
2167     *   request. `ev_data` contains parsed HTTP request.
2168     * - MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed Websocket handshake.
2169     *   `ev_data` is `NULL`.
2170     * - MG_EV_WEBSOCKET_FRAME: new websocket frame has arrived. `ev_data` is
2171     *   `struct websocket_message *`
2172     * - MG_EV_HTTP_PART_BEGIN: new part of multipart message is started,
2173     *   extra parameters are passed in mg_http_multipart_part
2174     * - MG_EV_HTTP_PART_DATA: new portion of data from multiparted message
2175     *   no additional headers are available, only data and data size
2176     * - MG_EV_HTTP_PART_END: final boundary received, analogue to maybe used to
2177     *   find the end of packet
2178     *   Note: Mongoose should be compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART
2179     *   to enable MG_EV_HTTP_MULTIPART_REQUEST, MG_EV_HTTP_REQUEST_END,
2180     *   MG_EV_HTTP_REQUEST_CANCEL, MG_EV_HTTP_PART_BEGIN, MG_EV_HTTP_PART_DATA,
2181     *   MG_EV_HTTP_PART_END constants
2182     */
2183    void mg_set_protocol_http_websocket(struct mg_connection *nc);
2184    
2185    /*
2186     * Send websocket handshake to the server.
2187     *
2188     * `nc` must be a valid connection, connected to a server. `uri` is an URI
2189     * to fetch, extra_headers` is extra HTTP headers to send or `NULL`.
2190     *
2191     * This function is intended to be used by websocket client.
2192     *
2193     * Note that the Host header is mandatory in HTTP/1.1 and must be
2194     * included in `extra_headers`. `mg_send_websocket_handshake2` offers
2195     * a better API for that.
2196     *
2197     * Deprecated in favour of `mg_send_websocket_handshake2`
2198     */
2199    void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri,
2200                                     const char *extra_headers);
2201    
2202    /*
2203     * Send websocket handshake to the server.
2204     *
2205     * `nc` must be a valid connection, connected to a server. `uri` is an URI
2206     * to fetch, `host` goes into the `Host` header, `protocol` goes into the
2207     * `Sec-WebSocket-Proto` header (NULL to omit), extra_headers` is extra HTTP
2208     * headers to send or `NULL`.
2209     *
2210     * This function is intended to be used by websocket client.
2211     */
2212    void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path,
2213                                      const char *host, const char *protocol,
2214                                      const char *extra_headers);
2215    
2216    /*
2217     * Helper function that creates an outbound WebSocket connection.
2218     *
2219     * `url` is a URL to connect to. It must be properly URL-encoded, e.g. have
2220     * no spaces, etc. By default, `mg_connect_ws()` sends Connection and
2221     * Host headers. `extra_headers` is an extra HTTP headers to send, e.g.
2222     * `"User-Agent: my-app\r\n"`.
2223     * If `protocol` is not NULL, then a `Sec-WebSocket-Protocol` header is sent.
2224     *
2225     * Examples:
2226     *
2227     * ```c
2228     *   nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL,
2229     *                       NULL);
2230     *   nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL,
2231     *                       NULL);
2232     *   nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com",
2233     *                       "clubby.cesanta.com", NULL);
2234     * ```
2235     */
2236    struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
2237                                        mg_event_handler_t event_handler,
2238                                        const char *url, const char *protocol,
2239                                        const char *extra_headers);
2240    
2241    /*
2242     * Helper function that creates an outbound WebSocket connection
2243     *
2244     * Mostly identical to mg_connect_ws, but allows to provide extra parameters
2245     * (for example, SSL parameters
2246     */
2247    struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
2248                                            mg_event_handler_t ev_handler,
2249                                            struct mg_connect_opts opts,
2250                                            const char *url, const char *protocol,
2251                                            const char *extra_headers);
2252    
2253    /*
2254     * Send websocket frame to the remote end.
2255     *
2256     * `op_and_flags` specifies frame's type, one of:
2257     *
2258     * - WEBSOCKET_OP_CONTINUE
2259     * - WEBSOCKET_OP_TEXT
2260     * - WEBSOCKET_OP_BINARY
2261     * - WEBSOCKET_OP_CLOSE
2262     * - WEBSOCKET_OP_PING
2263     * - WEBSOCKET_OP_PONG
2264     *
2265     * Orred with one of the flags:
2266     *
2267     * - WEBSOCKET_DONT_FIN: Don't set the FIN flag on the frame to be sent.
2268     *
2269     * `data` and `data_len` contain frame data.
2270     */
2271    void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
2272                                 const void *data, size_t data_len);
2273    
2274    /*
2275     * Send multiple websocket frames.
2276     *
2277     * Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers.
2278     */
2279    void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
2280                                  const struct mg_str *strings, int num_strings);
2281    
2282    /*
2283     * Send websocket frame to the remote end.
2284     *
2285     * Like `mg_send_websocket_frame()`, but allows to create formatted message
2286     * with `printf()`-like semantics.
2287     */
2288    void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
2289                                   const char *fmt, ...);
2290    
2291    /*
2292     * Send buffer `buf` of size `len` to the client using chunked HTTP encoding.
2293     * This function first sends buffer size as hex number + newline, then
2294     * buffer itself, then newline. For example,
2295     *   `mg_send_http_chunk(nc, "foo", 3)` whill append `3\r\nfoo\r\n` string to
2296     * the `nc->send_mbuf` output IO buffer.
2297     *
2298     * NOTE: HTTP header "Transfer-Encoding: chunked" should be sent prior to
2299     * using this function.
2300     *
2301     * NOTE: do not forget to send empty chunk at the end of the response,
2302     * to tell the client that everything was sent. Example:
2303     *
2304     * ```
2305     *   mg_printf_http_chunk(nc, "%s", "my response!");
2306     *   mg_send_http_chunk(nc, "", 0); // Tell the client we're finished
2307     * ```
2308     */
2309    void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len);
2310    
2311    /*
2312     * Send printf-formatted HTTP chunk.
2313     * Functionality is similar to `mg_send_http_chunk()`.
2314     */
2315    void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
2316    
2317    /*
2318     * Send response status line.
2319     * If `extra_headers` is not NULL, then `extra_headers` are also sent
2320     * after the reponse line. `extra_headers` must NOT end end with new line.
2321     * Example:
2322     *
2323     *      mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
2324     *
2325     * Will result in:
2326     *
2327     *      HTTP/1.1 200 OK\r\n
2328     *      Access-Control-Allow-Origin: *\r\n
2329     */
2330    void mg_send_response_line(struct mg_connection *c, int status_code,
2331                               const char *extra_headers);
2332    
2333    /*
2334     * Send response line and headers.
2335     * This function sends response line with the `status_code`, and automatically
2336     * sends one header: either "Content-Length", or "Transfer-Encoding".
2337     * If `content_length` is negative, then "Transfer-Encoding: chunked" header
2338     * is sent, otherwise, "Content-Length" header is sent.
2339     *
2340     * NOTE: If `Transfer-Encoding` is `chunked`, then message body must be sent
2341     * using `mg_send_http_chunk()` or `mg_printf_http_chunk()` functions.
2342     * Otherwise, `mg_send()` or `mg_printf()` must be used.
2343     * Extra headers could be set through `extra_headers` - and note `extra_headers`
2344     * must NOT be terminated by a new line.
2345     */
2346    void mg_send_head(struct mg_connection *n, int status_code,
2347                      int64_t content_length, const char *extra_headers);
2348    
2349    /*
2350     * Send printf-formatted HTTP chunk, escaping HTML tags.
2351     */
2352    void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...);
2353    
2354    /* Websocket opcodes, from http://tools.ietf.org/html/rfc6455 */
2355 #define WEBSOCKET_OP_CONTINUE 0
2356 #define WEBSOCKET_OP_TEXT 1
2357 #define WEBSOCKET_OP_BINARY 2
2358 #define WEBSOCKET_OP_CLOSE 8
2359 #define WEBSOCKET_OP_PING 9
2360 #define WEBSOCKET_OP_PONG 10
2361    
2362    /*
2363     * If set causes the FIN flag to not be set on outbound
2364     * frames. This enables sending multiple fragments of a single
2365     * logical message.
2366     *
2367     * The WebSocket protocol mandates that if the FIN flag of a data
2368     * frame is not set, the next frame must be a WEBSOCKET_OP_CONTINUE.
2369     * The last frame must have the FIN bit set.
2370     *
2371     * Note that mongoose will automatically defragment incoming messages,
2372     * so this flag is used only on outbound messages.
2373     */
2374 #define WEBSOCKET_DONT_FIN 0x100
2375    
2376    /*
2377     * Parse a HTTP message.
2378     *
2379     * `is_req` should be set to 1 if parsing request, 0 if reply.
2380     *
2381     * Return number of bytes parsed. If HTTP message is
2382     * incomplete, `0` is returned. On parse error, negative number is returned.
2383     */
2384    int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req);
2385    
2386    /*
2387     * Search and return header `name` in parsed HTTP message `hm`.
2388     * If header is not found, NULL is returned. Example:
2389     *
2390     *     struct mg_str *host_hdr = mg_get_http_header(hm, "Host");
2391     */
2392    struct mg_str *mg_get_http_header(struct http_message *hm, const char *name);
2393    
2394    /*
2395     * Parse HTTP header `hdr`. Find variable `var_name` and store it's value
2396     * in the buffer `buf`, `buf_size`. Return 0 if variable not found, non-zero
2397     * otherwise.
2398     *
2399     * This function is supposed to parse
2400     * cookies, authentication headers, etcetera. Example (error handling omitted):
2401     *
2402     *     char user[20];
2403     *     struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
2404     *     mg_http_parse_header(hdr, "username", user, sizeof(user));
2405     *
2406     * Return length of the variable's value. If buffer is not large enough,
2407     * or variable not found, 0 is returned.
2408     */
2409    int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
2410                             size_t buf_size);
2411    
2412    /*
2413     * Parse buffer `buf`, `buf_len` that contains multipart form data chunks.
2414     * Store chunk name in a `var_name`, `var_name_len` buffer.
2415     * If a chunk is an uploaded file, then `file_name`, `file_name_len` is
2416     * filled with an uploaded file name. `chunk`, `chunk_len`
2417     * points to the chunk data.
2418     *
2419     * Return: number of bytes to skip to the next chunk, or 0 if there are
2420     *         no more chunks.
2421     *
2422     * Usage example:
2423     *
2424     * ```c
2425     *    static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
2426     *      switch(ev) {
2427     *        case MG_EV_HTTP_REQUEST: {
2428     *          struct http_message *hm = (struct http_message *) ev_data;
2429     *          char var_name[100], file_name[100];
2430     *          const char *chunk;
2431     *          size_t chunk_len, n1, n2;
2432     *
2433     *          n1 = n2 = 0;
2434     *          while ((n2 = mg_parse_multipart(hm->body.p + n1,
2435     *                                          hm->body.len - n1,
2436     *                                          var_name, sizeof(var_name),
2437     *                                          file_name, sizeof(file_name),
2438     *                                          &chunk, &chunk_len)) > 0) {
2439     *            printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n",
2440     *                   var_name, file_name, (int) chunk_len,
2441     *                   (int) chunk_len, chunk);
2442     *            n1 += n2;
2443     *          }
2444     *        }
2445     *        break;
2446     * ```
2447     */
2448    size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
2449                              size_t var_name_len, char *file_name,
2450                              size_t file_name_len, const char **chunk,
2451                              size_t *chunk_len);
2452    
2453    /*
2454     * Fetch an HTTP form variable.
2455     *
2456     * Fetch a variable `name` from a `buf` into a buffer specified by
2457     * `dst`, `dst_len`. Destination is always zero-terminated. Return length
2458     * of a fetched variable. If not found, 0 is returned. `buf` must be
2459     * valid url-encoded buffer. If destination is too small, `-1` is returned.
2460     */
2461    int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
2462                        size_t dst_len);
2463    
2464    /*
2465     * Decode URL-encoded string.
2466     *
2467     * Source string is specified by (`src`, `src_len`), and destination is
2468     * (`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
2469     * `+` character is decoded as a blank space character. This function
2470     * guarantees to `\0`-terminate the destination. If destination is too small,
2471     * then source string is partially decoded and `-1` is returned. Otherwise,
2472     * a length of decoded string is returned, not counting final `\0`.
2473     */
2474    int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
2475                      int is_form_url_encoded);
2476    
2477    /* Create Digest authentication header for client request. */
2478    int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
2479                                          const char *method, const char *uri,
2480                                          const char *auth_domain, const char *user,
2481                                          const char *passwd);
2482    
2483    /*
2484     * Helper function that creates outbound HTTP connection.
2485     *
2486     * `url` is a URL to fetch. It must be properly URL-encoded, e.g. have
2487     * no spaces, etc. By default, `mg_connect_http()` sends Connection and
2488     * Host headers. `extra_headers` is an extra HTTP headers to send, e.g.
2489     * `"User-Agent: my-app\r\n"`.
2490     * If `post_data` is NULL, then GET request is created. Otherwise, POST request
2491     * is created with the specified POST data. Note that if the data being posted
2492     * is a form submission, the `Content-Type` header should be set accordingly
2493     * (see example below).
2494     *
2495     * Examples:
2496     *
2497     * ```c
2498     *   nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL,
2499     *                         NULL);
2500     *   nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL);
2501     *   nc3 = mg_connect_http(
2502     *       mgr, ev_handler_1, "my_server:8000/form_submit/",
2503     *       "Content-Type: application/x-www-form-urlencoded\r\n",
2504     *       "var_1=value_1&var_2=value_2");
2505     * ```
2506     */
2507    struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
2508                                          mg_event_handler_t event_handler,
2509                                          const char *url,
2510                                          const char *extra_headers,
2511                                          const char *post_data);
2512    
2513    /*
2514     * Helper function that creates outbound HTTP connection.
2515     *
2516     * Mostly identical to mg_connect_http, but allows to provide extra parameters
2517     * (for example, SSL parameters
2518     */
2519    struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
2520                                              mg_event_handler_t ev_handler,
2521                                              struct mg_connect_opts opts,
2522                                              const char *url,
2523                                              const char *extra_headers,
2524                                              const char *post_data);
2525    /*
2526     * This structure defines how `mg_serve_http()` works.
2527     * Best practice is to set only required settings, and leave the rest as NULL.
2528     */
2529    struct mg_serve_http_opts {
2530       /* Path to web root directory */
2531       const char *document_root;
2532       
2533       /* List of index files. Default is "" */
2534       const char *index_files;
2535       
2536       /*
2537        * Leave as NULL to disable authentication.
2538        * To enable directory protection with authentication, set this to ".htpasswd"
2539        * Then, creating ".htpasswd" file in any directory automatically protects
2540        * it with digest authentication.
2541        * Use `mongoose` web server binary, or `htdigest` Apache utility to
2542        * create/manipulate passwords file.
2543        * Make sure `auth_domain` is set to a valid domain name.
2544        */
2545       const char *per_directory_auth_file;
2546       
2547       /* Authorization domain (domain name of this web server) */
2548       const char *auth_domain;
2549       
2550       /*
2551        * Leave as NULL to disable authentication.
2552        * Normally, only selected directories in the document root are protected.
2553        * If absolutely every access to the web server needs to be authenticated,
2554        * regardless of the URI, set this option to the path to the passwords file.
2555        * Format of that file is the same as ".htpasswd" file. Make sure that file
2556        * is located outside document root to prevent people fetching it.
2557        */
2558       const char *global_auth_file;
2559       
2560       /* Set to "no" to disable directory listing. Enabled by default. */
2561       const char *enable_directory_listing;
2562       
2563       /* SSI files pattern. If not set, "**.shtml$|**.shtm$" is used. */
2564       const char *ssi_pattern;
2565       
2566       /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */
2567       const char *ip_acl;
2568       
2569       /* URL rewrites.
2570        *
2571        * Comma-separated list of `uri_pattern=file_or_directory_path` rewrites.
2572        * When HTTP request is received, Mongoose constructs a file name from the
2573        * requested URI by combining `document_root` and the URI. However, if the
2574        * rewrite option is used and `uri_pattern` matches requested URI, then
2575        * `document_root` is ignored. Instead, `file_or_directory_path` is used,
2576        * which should be a full path name or a path relative to the web server's
2577        * current working directory. Note that `uri_pattern`, as all Mongoose
2578        * patterns, is a prefix pattern.
2579        *
2580        * If uri_pattern starts with `@` symbol, then Mongoose compares it with the
2581        * HOST header of the request. If they are equal, Mongoose sets document root
2582        * to `file_or_directory_path`, implementing virtual hosts support.
2583        * Example: `@foo.com=/document/root/for/foo.com`
2584        *
2585        * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with
2586        * the listening port. If they match, then Mongoose issues a 301 redirect.
2587        * For example, to redirect all HTTP requests to the
2588        * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is
2589        * automatically appended to the redirect location.
2590        */
2591       const char *url_rewrites;
2592       
2593       /* DAV document root. If NULL, DAV requests are going to fail. */
2594       const char *dav_document_root;
2595       
2596       /*
2597        * DAV passwords file. If NULL, DAV requests are going to fail.
2598        * If passwords file is set to "-", then DAV auth is disabled.
2599        */
2600       const char *dav_auth_file;
2601       
2602       /* Glob pattern for the files to hide. */
2603       const char *hidden_file_pattern;
2604       
2605       /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */
2606       const char *cgi_file_pattern;
2607       
2608       /* If not NULL, ignore CGI script hashbang and use this interpreter */
2609       const char *cgi_interpreter;
2610       
2611       /*
2612        * Comma-separated list of Content-Type overrides for path suffixes, e.g.
2613        * ".txt=text/plain; charset=utf-8,.c=text/plain"
2614        */
2615       const char *custom_mime_types;
2616       
2617       /*
2618        * Extra HTTP headers to add to each server response.
2619        * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *".
2620        */
2621       const char *extra_headers;
2622    };
2623    
2624    /*
2625     * Serve given HTTP request according to the `options`.
2626     *
2627     * Example code snippet:
2628     *
2629     * ```c
2630     * static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
2631     *   struct http_message *hm = (struct http_message *) ev_data;
2632     *   struct mg_serve_http_opts opts = { .document_root = "/var/www" };  // C99
2633     *
2634     *   switch (ev) {
2635     *     case MG_EV_HTTP_REQUEST:
2636     *       mg_serve_http(nc, hm, opts);
2637     *       break;
2638     *     default:
2639     *       break;
2640     *   }
2641     * }
2642     * ```
2643     */
2644    void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
2645                       struct mg_serve_http_opts opts);
2646    
2647    /*
2648     * Register callback for specified http endpoint
2649     * Note: if callback is registered it is called instead of
2650     * callback provided in mg_bind
2651     *
2652     * Example code snippet:
2653     *
2654     * ```c
2655     * static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
2656     *   (void) ev; (void) ev_data;
2657     *   mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
2658     *  nc->flags |= MG_F_SEND_AND_CLOSE;
2659     * }
2660     *
2661     * static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
2662     *  (void) ev; (void) ev_data;
2663     *   mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
2664     *  nc->flags |= MG_F_SEND_AND_CLOSE;
2665     * }
2666     *
2667     * void init() {
2668     *   nc = mg_bind(&mgr, local_addr, cb1);
2669     *   mg_register_http_endpoint(nc, "/hello1", handle_hello1);
2670     *   mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
2671     * }
2672     * ```
2673     */
2674    void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
2675                                   mg_event_handler_t handler);
2676    
2677 #ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
2678    
2679    /* Callback prototype for `mg_file_upload_handler()`. */
2680    typedef struct mg_str (*mg_fu_fname_fn)(struct mg_connection *nc,
2681    struct mg_str fname);
2682    
2683    /*
2684     * File upload handler.
2685     * This handler can be used to implement file uploads with minimum code.
2686     * This handler will process MG_EV_HTTP_PART_* events and store file data into
2687     * a local file.
2688     * `local_name_fn` will be invoked with whatever name was provided by the client
2689     * and will expect the name of the local file to open. Return value of NULL will
2690     * abort file upload (client will get a "403 Forbidden" response). If non-null,
2691     * the returned string must be heap-allocated and will be freed by the caller.
2692     * Exception: it is ok to return the same string verbatim.
2693     *
2694     * Example:
2695     *
2696     * ```c
2697     * struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
2698     *   // Just return the same filename. Do not actually do this except in test!
2699     *   // fname is user-controlled and needs to be sanitized.
2700     *   return fname;
2701     * }
2702     * void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
2703     *   switch (ev) {
2704     *     ...
2705     *     case MG_EV_HTTP_PART_BEGIN:
2706     *     case MG_EV_HTTP_PART_DATA:
2707     *     case MG_EV_HTTP_PART_END:
2708     *       mg_file_upload_handler(nc, ev, ev_data, upload_fname);
2709     *       break;
2710     *   }
2711     * }
2712     * ```
2713     */
2714    void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
2715                                mg_fu_fname_fn local_name_fn);
2716 #endif /* MG_ENABLE_HTTP_STREAMING_MULTIPART */
2717    
2718    /*
2719     * Authenticate HTTP request against opened passwords file.
2720     * Returns 1 if authenticated, 0 otherwise.
2721     */
2722    int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
2723                                  FILE *fp);
2724    
2725 #ifdef __cplusplus
2726 }
2727 #endif /* __cplusplus */
2728 #endif /* CS_MONGOOSE_SRC_HTTP_H_ */
2729 /*
2730  * Copyright (c) 2014 Cesanta Software Limited
2731  * All rights reserved
2732  */
2733 
2734 /*
2735  * === JSON-RPC
2736  */
2737 
2738 #ifndef CS_MONGOOSE_SRC_JSON_RPC_H_
2739 #define CS_MONGOOSE_SRC_JSON_RPC_H_
2740 
2741 #ifdef __cplusplus
2742 extern "C" {
2743 #endif /* __cplusplus */
2744    
2745    /* JSON-RPC request */
2746    struct mg_rpc_request {
2747       struct json_token *message; /* Whole RPC message */
2748       struct json_token *id;      /* Message ID */
2749       struct json_token *method;  /* Method name */
2750       struct json_token *params;  /* Method params */
2751    };
2752    
2753    /* JSON-RPC response */
2754    struct mg_rpc_reply {
2755       struct json_token *message; /* Whole RPC message */
2756       struct json_token *id;      /* Message ID */
2757       struct json_token *result;  /* Remote call result */
2758    };
2759    
2760    /* JSON-RPC error */
2761    struct mg_rpc_error {
2762       struct json_token *message;       /* Whole RPC message */
2763       struct json_token *id;            /* Message ID */
2764       struct json_token *error_code;    /* error.code */
2765       struct json_token *error_message; /* error.message */
2766       struct json_token *error_data;    /* error.data, can be NULL */
2767    };
2768    
2769    /*
2770     * Parse JSON-RPC reply contained in `buf`, `len` into JSON tokens array
2771     * `toks`, `max_toks`. If buffer contains valid reply, `reply` structure is
2772     * populated. The result of RPC call is located in `reply.result`. On error,
2773     * `error` structure is populated. Returns: the result of calling
2774     * `parse_json(buf, len, toks, max_toks)`:
2775     *
2776     * On success, an offset inside `json_string` is returned
2777     * where parsing has finished. On failure, a negative number is
2778     * returned, one of:
2779     *
2780     * - `#define JSON_STRING_INVALID           -1`
2781     * - `#define JSON_STRING_INCOMPLETE        -2`
2782     * - `#define JSON_TOKEN_ARRAY_TOO_SMALL    -3`
2783     */
2784    int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks,
2785                           int max_toks, struct mg_rpc_reply *,
2786                           struct mg_rpc_error *);
2787    
2788    /*
2789     * Create JSON-RPC request in a given buffer.
2790     *
2791     * Return length of the request, which
2792     * can be larger then `len` that indicates an overflow.
2793     * `params_fmt` format string should conform to `json_emit()` API,
2794     * see https://github.com/cesanta/frozen
2795     */
2796    int mg_rpc_create_request(char *buf, int len, const char *method,
2797                              const char *id, const char *params_fmt, ...);
2798    
2799    /*
2800     * Create JSON-RPC reply in a given buffer.
2801     *
2802     * Return length of the reply, which
2803     * can be larger then `len` that indicates an overflow.
2804     * `result_fmt` format string should conform to `json_emit()` API,
2805     * see https://github.com/cesanta/frozen
2806     */
2807    int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req,
2808                            const char *result_fmt, ...);
2809    
2810    /*
2811     * Create JSON-RPC error reply in a given buffer.
2812     *
2813     * Return length of the error, which
2814     * can be larger then `len` that indicates an overflow.
2815     * `fmt` format string should conform to `json_emit()` API,
2816     * see https://github.com/cesanta/frozen
2817     */
2818    int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req,
2819                            int code, const char *message, const char *fmt, ...);
2820    
2821    /* JSON-RPC standard error codes */
2822 #define JSON_RPC_PARSE_ERROR (-32700)
2823 #define JSON_RPC_INVALID_REQUEST_ERROR (-32600)
2824 #define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)
2825 #define JSON_RPC_INVALID_PARAMS_ERROR (-32602)
2826 #define JSON_RPC_INTERNAL_ERROR (-32603)
2827 #define JSON_RPC_SERVER_ERROR (-32000)
2828    
2829    /*
2830     * Create JSON-RPC error in a given buffer.
2831     *
2832     * Return length of the error, which
2833     * can be larger then `len` that indicates an overflow. See
2834     * JSON_RPC_*_ERROR definitions for standard error values:
2835     *
2836     * - `#define JSON_RPC_PARSE_ERROR (-32700)`
2837     * - `#define JSON_RPC_INVALID_REQUEST_ERROR (-32600)`
2838     * - `#define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)`
2839     * - `#define JSON_RPC_INVALID_PARAMS_ERROR (-32602)`
2840     * - `#define JSON_RPC_INTERNAL_ERROR (-32603)`
2841     * - `#define JSON_RPC_SERVER_ERROR (-32000)`
2842     */
2843    int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req,
2844                                int code);
2845    
2846    typedef int (*mg_rpc_handler_t)(char *buf, int len, struct mg_rpc_request *req);
2847    
2848    /*
2849     * Dispatches a JSON-RPC request.
2850     *
2851     * Parses JSON-RPC request contained in `buf`, `len`.
2852     * Then, dispatches the request to the correct handler method.
2853     * Valid method names should be specified in NULL
2854     * terminated array `methods`, and corresponding handlers in `handlers`.
2855     * Result is put in `dst`, `dst_len`. Return: length of the result, which
2856     * can be larger then `dst_len` that indicates an overflow.
2857     * Overflown bytes are not written to the buffer.
2858     * If method is not found, an error is automatically generated.
2859     */
2860    int mg_rpc_dispatch(const char *buf, int, char *dst, int dst_len,
2861                        const char **methods, mg_rpc_handler_t *handlers);
2862    
2863 #ifdef __cplusplus
2864 }
2865 #endif /* __cplusplus */
2866 #endif /* CS_MONGOOSE_SRC_JSON_RPC_H_ */
2867 /*
2868  * Copyright (c) 2014 Cesanta Software Limited
2869  * All rights reserved
2870  * This software is dual-licensed: you can redistribute it and/or modify
2871  * it under the terms of the GNU General Public License version 2 as
2872  * published by the Free Software Foundation. For the terms of this
2873  * license, see <http://www.gnu.org/licenses/>.
2874  *
2875  * You are free to use this software under the terms of the GNU General
2876  * Public License, but WITHOUT ANY WARRANTY; without even the implied
2877  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2878  * See the GNU General Public License for more details.
2879  *
2880  * Alternatively, you can license this software under a commercial
2881  * license, as set out in <https://www.cesanta.com/license>.
2882  */
2883 
2884 /*
2885  * === MQTT
2886  */
2887 
2888 #ifndef CS_MONGOOSE_SRC_MQTT_H_
2889 #define CS_MONGOOSE_SRC_MQTT_H_
2890 
2891 
2892 struct mg_mqtt_message {
2893    int cmd;
2894    struct mg_str payload;
2895    int qos;
2896    uint8_t connack_ret_code; /* connack */
2897    uint16_t message_id;      /* puback */
2898    char *topic;
2899 };
2900 
2901 struct mg_mqtt_topic_expression {
2902    const char *topic;
2903    uint8_t qos;
2904 };
2905 
2906 struct mg_send_mqtt_handshake_opts {
2907    unsigned char flags; /* connection flags */
2908    uint16_t keep_alive;
2909    const char *will_topic;
2910    const char *will_message;
2911    const char *user_name;
2912    const char *password;
2913 };
2914 
2915 /* Message types */
2916 #define MG_MQTT_CMD_CONNECT 1
2917 #define MG_MQTT_CMD_CONNACK 2
2918 #define MG_MQTT_CMD_PUBLISH 3
2919 #define MG_MQTT_CMD_PUBACK 4
2920 #define MG_MQTT_CMD_PUBREC 5
2921 #define MG_MQTT_CMD_PUBREL 6
2922 #define MG_MQTT_CMD_PUBCOMP 7
2923 #define MG_MQTT_CMD_SUBSCRIBE 8
2924 #define MG_MQTT_CMD_SUBACK 9
2925 #define MG_MQTT_CMD_UNSUBSCRIBE 10
2926 #define MG_MQTT_CMD_UNSUBACK 11
2927 #define MG_MQTT_CMD_PINGREQ 12
2928 #define MG_MQTT_CMD_PINGRESP 13
2929 #define MG_MQTT_CMD_DISCONNECT 14
2930 
2931 /* MQTT event types */
2932 #define MG_MQTT_EVENT_BASE 200
2933 #define MG_EV_MQTT_CONNECT (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_CONNECT)
2934 #define MG_EV_MQTT_CONNACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_CONNACK)
2935 #define MG_EV_MQTT_PUBLISH (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBLISH)
2936 #define MG_EV_MQTT_PUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBACK)
2937 #define MG_EV_MQTT_PUBREC (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBREC)
2938 #define MG_EV_MQTT_PUBREL (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBREL)
2939 #define MG_EV_MQTT_PUBCOMP (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PUBCOMP)
2940 #define MG_EV_MQTT_SUBSCRIBE (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_SUBSCRIBE)
2941 #define MG_EV_MQTT_SUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_SUBACK)
2942 #define MG_EV_MQTT_UNSUBSCRIBE (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_UNSUBSCRIBE)
2943 #define MG_EV_MQTT_UNSUBACK (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_UNSUBACK)
2944 #define MG_EV_MQTT_PINGREQ (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PINGREQ)
2945 #define MG_EV_MQTT_PINGRESP (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_PINGRESP)
2946 #define MG_EV_MQTT_DISCONNECT (MG_MQTT_EVENT_BASE + MG_MQTT_CMD_DISCONNECT)
2947 
2948 /* Message flags */
2949 #define MG_MQTT_RETAIN 0x1
2950 #define MG_MQTT_DUP 0x4
2951 #define MG_MQTT_QOS(qos) ((qos) << 1)
2952 #define MG_MQTT_GET_QOS(flags) (((flags) &0x6) >> 1)
2953 #define MG_MQTT_SET_QOS(flags, qos) (flags) = ((flags) & ~0x6) | ((qos) << 1)
2954 
2955 /* Connection flags */
2956 #define MG_MQTT_CLEAN_SESSION 0x02
2957 #define MG_MQTT_HAS_WILL 0x04
2958 #define MG_MQTT_WILL_RETAIN 0x20
2959 #define MG_MQTT_HAS_PASSWORD 0x40
2960 #define MG_MQTT_HAS_USER_NAME 0x80
2961 #define MG_MQTT_GET_WILL_QOS(flags) (((flags) &0x18) >> 3)
2962 #define MG_MQTT_SET_WILL_QOS(flags, qos) \
2963 (flags) = ((flags) & ~0x18) | ((qos) << 3)
2964 
2965 /* CONNACK return codes */
2966 #define MG_EV_MQTT_CONNACK_ACCEPTED 0
2967 #define MG_EV_MQTT_CONNACK_UNACCEPTABLE_VERSION 1
2968 #define MG_EV_MQTT_CONNACK_IDENTIFIER_REJECTED 2
2969 #define MG_EV_MQTT_CONNACK_SERVER_UNAVAILABLE 3
2970 #define MG_EV_MQTT_CONNACK_BAD_AUTH 4
2971 #define MG_EV_MQTT_CONNACK_NOT_AUTHORIZED 5
2972 
2973 #ifdef __cplusplus
2974 extern "C" {
2975 #endif /* __cplusplus */
2976    
2977    /*
2978     * Attach built-in MQTT event handler to the given connection.
2979     *
2980     * The user-defined event handler will receive following extra events:
2981     *
2982     * - MG_EV_MQTT_CONNACK
2983     * - MG_EV_MQTT_PUBLISH
2984     * - MG_EV_MQTT_PUBACK
2985     * - MG_EV_MQTT_PUBREC
2986     * - MG_EV_MQTT_PUBREL
2987     * - MG_EV_MQTT_PUBCOMP
2988     * - MG_EV_MQTT_SUBACK
2989     */
2990    void mg_set_protocol_mqtt(struct mg_connection *nc);
2991    
2992    /* Send MQTT handshake. */
2993    void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);
2994    
2995    /* Send MQTT handshake with optional parameters. */
2996    void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
2997                                    struct mg_send_mqtt_handshake_opts);
2998    
2999    /* Publish a message to a given topic. */
3000    void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
3001                         uint16_t message_id, int flags, const void *data,
3002                         size_t len);
3003    
3004    /* Subscribe to a bunch of topics. */
3005    void mg_mqtt_subscribe(struct mg_connection *nc,
3006                           const struct mg_mqtt_topic_expression *topics,
3007                           size_t topics_len, uint16_t message_id);
3008    
3009    /* Unsubscribe from a bunch of topics. */
3010    void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
3011                             size_t topics_len, uint16_t message_id);
3012    
3013    /* Send a DISCONNECT command. */
3014    void mg_mqtt_disconnect(struct mg_connection *nc);
3015    
3016    /* Send a CONNACK command with a given `return_code`. */
3017    void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);
3018    
3019    /* Send a PUBACK command with a given `message_id`. */
3020    void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);
3021    
3022    /* Send a PUBREC command with a given `message_id`. */
3023    void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);
3024    
3025    /* Send a PUBREL command with a given `message_id`. */
3026    void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);
3027    
3028    /* Send a PUBCOMP command with a given `message_id`. */
3029    void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);
3030    
3031    /*
3032     * Send a SUBACK command with a given `message_id`
3033     * and a sequence of granted QoSs.
3034     */
3035    void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
3036                        uint16_t message_id);
3037    
3038    /* Send a UNSUBACK command with a given `message_id`. */
3039    void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);
3040    
3041    /* Send a PINGREQ command. */
3042    void mg_mqtt_ping(struct mg_connection *nc);
3043    
3044    /* Send a PINGRESP command. */
3045    void mg_mqtt_pong(struct mg_connection *nc);
3046    
3047    /*
3048     * Extract the next topic expression from a SUBSCRIBE command payload.
3049     *
3050     * Topic expression name will point to a string in the payload buffer.
3051     * Return the pos of the next topic expression or -1 when the list
3052     * of topics is exhausted.
3053     */
3054    int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
3055                                     struct mg_str *topic, uint8_t *qos, int pos);
3056    
3057 #ifdef __cplusplus
3058 }
3059 #endif /* __cplusplus */
3060 
3061 #endif /* CS_MONGOOSE_SRC_MQTT_H_ */
3062 /*
3063  * Copyright (c) 2014 Cesanta Software Limited
3064  * All rights reserved
3065  * This software is dual-licensed: you can redistribute it and/or modify
3066  * it under the terms of the GNU General Public License version 2 as
3067  * published by the Free Software Foundation. For the terms of this
3068  * license, see <http://www.gnu.org/licenses/>.
3069  *
3070  * You are free to use this software under the terms of the GNU General
3071  * Public License, but WITHOUT ANY WARRANTY; without even the implied
3072  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3073  * See the GNU General Public License for more details.
3074  *
3075  * Alternatively, you can license this software under a commercial
3076  * license, as set out in <https://www.cesanta.com/license>.
3077  */
3078 
3079 /*
3080  * === MQTT Broker
3081  */
3082 
3083 #ifndef CS_MONGOOSE_SRC_MQTT_BROKER_H_
3084 #define CS_MONGOOSE_SRC_MQTT_BROKER_H_
3085 
3086 #ifdef MG_ENABLE_MQTT_BROKER
3087 
3088 
3089 #ifdef __cplusplus
3090 extern "C" {
3091 #endif /* __cplusplus */
3092    
3093 #define MG_MQTT_MAX_SESSION_SUBSCRIPTIONS 512;
3094    
3095    struct mg_mqtt_broker;
3096    
3097    /* MQTT session (Broker side). */
3098    struct mg_mqtt_session {
3099       struct mg_mqtt_broker *brk;          /* Broker */
3100       struct mg_mqtt_session *next, *prev; /* mg_mqtt_broker::sessions linkage */
3101       struct mg_connection *nc;            /* Connection with the client */
3102       size_t num_subscriptions;            /* Size of `subscriptions` array */
3103       struct mg_mqtt_topic_expression *subscriptions;
3104       void *user_data; /* User data */
3105    };
3106    
3107    /* MQTT broker. */
3108    struct mg_mqtt_broker {
3109       struct mg_mqtt_session *sessions; /* Session list */
3110       void *user_data;                  /* User data */
3111    };
3112    
3113    /* Initialize a MQTT broker. */
3114    void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);
3115    
3116    /*
3117     * Process a MQTT broker message.
3118     *
3119     * Listening connection expects a pointer to an initialized `mg_mqtt_broker`
3120     * structure in the `user_data` field.
3121     *
3122     * Basic usage:
3123     *
3124     * ```c
3125     * mg_mqtt_broker_init(&brk, NULL);
3126     *
3127     * if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
3128     *   // fail;
3129     * }
3130     * nc->user_data = &brk;
3131     * ```
3132     *
3133     * New incoming connections will receive a `mg_mqtt_session` structure
3134     * in the connection `user_data`. The original `user_data` will be stored
3135     * in the `user_data` field of the session structure. This allows the user
3136     * handler to store user data before `mg_mqtt_broker` creates the session.
3137     *
3138     * Since only the MG_EV_ACCEPT message is processed by the listening socket,
3139     * for most events the `user_data` will thus point to a `mg_mqtt_session`.
3140     */
3141    void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);
3142    
3143    /*
3144     * Iterate over all mqtt sessions connections. Example:
3145     *
3146     * ```c
3147     * struct mg_mqtt_session *s;
3148     * for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
3149     *   // Do something
3150     * }
3151     * ```
3152     */
3153    struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
3154                                         struct mg_mqtt_session *s);
3155    
3156 #ifdef __cplusplus
3157 }
3158 #endif /* __cplusplus */
3159 
3160 #endif /* MG_ENABLE_MQTT_BROKER */
3161 #endif /* CS_MONGOOSE_SRC_MQTT_BROKER_H_ */
3162 /*
3163  * Copyright (c) 2014 Cesanta Software Limited
3164  * All rights reserved
3165  */
3166 
3167 /*
3168  * === DNS
3169  */
3170 
3171 #ifndef CS_MONGOOSE_SRC_DNS_H_
3172 #define CS_MONGOOSE_SRC_DNS_H_
3173 
3174 
3175 #ifdef __cplusplus
3176 extern "C" {
3177 #endif /* __cplusplus */
3178    
3179 #define MG_DNS_A_RECORD 0x01     /* Lookup IP address */
3180 #define MG_DNS_CNAME_RECORD 0x05 /* Lookup CNAME */
3181 #define MG_DNS_AAAA_RECORD 0x1c  /* Lookup IPv6 address */
3182 #define MG_DNS_MX_RECORD 0x0f    /* Lookup mail server for domain */
3183    
3184 #define MG_MAX_DNS_QUESTIONS 32
3185 #define MG_MAX_DNS_ANSWERS 32
3186    
3187 #define MG_DNS_MESSAGE 100 /* High-level DNS message event */
3188    
3189    enum mg_dns_resource_record_kind {
3190       MG_DNS_INVALID_RECORD = 0,
3191       MG_DNS_QUESTION,
3192       MG_DNS_ANSWER
3193    };
3194    
3195    /* DNS resource record. */
3196    struct mg_dns_resource_record {
3197       struct mg_str name; /* buffer with compressed name */
3198       int rtype;
3199       int rclass;
3200       int ttl;
3201       enum mg_dns_resource_record_kind kind;
3202       struct mg_str rdata; /* protocol data (can be a compressed name) */
3203    };
3204    
3205    /* DNS message (request and response). */
3206    struct mg_dns_message {
3207       struct mg_str pkt; /* packet body */
3208       uint16_t flags;
3209       uint16_t transaction_id;
3210       int num_questions;
3211       int num_answers;
3212       struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
3213       struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
3214    };
3215    
3216    struct mg_dns_resource_record *mg_dns_next_record(
3217                                                      struct mg_dns_message *msg, int query, struct mg_dns_resource_record *prev);
3218    
3219    /*
3220     * Parse the record data from a DNS resource record.
3221     *
3222     *  - A:     struct in_addr *ina
3223     *  - AAAA:  struct in6_addr *ina
3224     *  - CNAME: char buffer
3225     *
3226     * Returns -1 on error.
3227     *
3228     * TODO(mkm): MX
3229     */
3230    int mg_dns_parse_record_data(struct mg_dns_message *msg,
3231                                 struct mg_dns_resource_record *rr, void *data,
3232                                 size_t data_len);
3233    
3234    /*
3235     * Send a DNS query to the remote end.
3236     */
3237    void mg_send_dns_query(struct mg_connection *nc, const char *name,
3238                           int query_type);
3239    
3240    /*
3241     * Insert a DNS header to an IO buffer.
3242     *
3243     * Return number of bytes inserted.
3244     */
3245    int mg_dns_insert_header(struct mbuf *io, size_t pos,
3246                             struct mg_dns_message *msg);
3247    
3248    /*
3249     * Append already encoded questions from an existing message.
3250     *
3251     * This is useful when generating a DNS reply message which includes
3252     * all question records.
3253     *
3254     * Return number of appened bytes.
3255     */
3256    int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
3257    
3258    /*
3259     * Encode and append a DNS resource record to an IO buffer.
3260     *
3261     * The record metadata is taken from the `rr` parameter, while the name and data
3262     * are taken from the parameters, encoded in the appropriate format depending on
3263     * record type, and stored in the IO buffer. The encoded values might contain
3264     * offsets within the IO buffer. It's thus important that the IO buffer doesn't
3265     * get trimmed while a sequence of records are encoded while preparing a DNS
3266     *reply.
3267     *
3268     * This function doesn't update the `name` and `rdata` pointers in the `rr`
3269     *struct
3270     * because they might be invalidated as soon as the IO buffer grows again.
3271     *
3272     * Return the number of bytes appened or -1 in case of error.
3273     */
3274    int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
3275                             const char *name, size_t nlen, const void *rdata,
3276                             size_t rlen);
3277    
3278    /* Low-level: parses a DNS response. */
3279    int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
3280    
3281    /*
3282     * Uncompress a DNS compressed name.
3283     *
3284     * The containing dns message is required because the compressed encoding
3285     * and reference suffixes present elsewhere in the packet.
3286     *
3287     * If name is less than `dst_len` characters long, the remainder
3288     * of `dst` is terminated with `\0' characters. Otherwise, `dst` is not
3289     *terminated.
3290     *
3291     * If `dst_len` is 0 `dst` can be NULL.
3292     * Return the uncompressed name length.
3293     */
3294    size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
3295                                  char *dst, int dst_len);
3296    
3297    /*
3298     * Attach built-in DNS event handler to the given listening connection.
3299     *
3300     * DNS event handler parses incoming UDP packets, treating them as DNS
3301     * requests. If incoming packet gets successfully parsed by the DNS event
3302     * handler, a user event handler will receive `MG_DNS_REQUEST` event, with
3303     * `ev_data` pointing to the parsed `struct mg_dns_message`.
3304     *
3305     * See
3306     * [captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server)
3307     * example on how to handle DNS request and send DNS reply.
3308     */
3309    void mg_set_protocol_dns(struct mg_connection *nc);
3310    
3311 #ifdef __cplusplus
3312 }
3313 #endif /* __cplusplus */
3314 #endif /* CS_MONGOOSE_SRC_DNS_H_ */
3315 /*
3316  * Copyright (c) 2014 Cesanta Software Limited
3317  * All rights reserved
3318  */
3319 
3320 /*
3321  * === DNS server
3322  *
3323  * Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`.
3324  */
3325 
3326 #ifndef CS_MONGOOSE_SRC_DNS_SERVER_H_
3327 #define CS_MONGOOSE_SRC_DNS_SERVER_H_
3328 
3329 #ifdef MG_ENABLE_DNS_SERVER
3330 
3331 
3332 #ifdef __cplusplus
3333 extern "C" {
3334 #endif /* __cplusplus */
3335    
3336 #define MG_DNS_SERVER_DEFAULT_TTL 3600
3337    
3338    struct mg_dns_reply {
3339       struct mg_dns_message *msg;
3340       struct mbuf *io;
3341       size_t start;
3342    };
3343    
3344    /*
3345     * Create a DNS reply.
3346     *
3347     * The reply will be based on an existing query message `msg`.
3348     * The query body will be appended to the output buffer.
3349     * "reply + recursion allowed" will be added to the message flags and
3350     * message's num_answers will be set to 0.
3351     *
3352     * Answer records can be appended with `mg_dns_send_reply` or by lower
3353     * level function defined in the DNS API.
3354     *
3355     * In order to send the reply use `mg_dns_send_reply`.
3356     * It's possible to use a connection's send buffer as reply buffers,
3357     * and it will work for both UDP and TCP connections.
3358     *
3359     * Example:
3360     *
3361     * ```c
3362     * reply = mg_dns_create_reply(&nc->send_mbuf, msg);
3363     * for (i = 0; i < msg->num_questions; i++) {
3364     *   rr = &msg->questions[i];
3365     *   if (rr->rtype == MG_DNS_A_RECORD) {
3366     *     mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4);
3367     *   }
3368     * }
3369     * mg_dns_send_reply(nc, &reply);
3370     * ```
3371     */
3372    struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
3373                                            struct mg_dns_message *msg);
3374    
3375    /*
3376     * Append a DNS reply record to the IO buffer and to the DNS message.
3377     *
3378     * The message num_answers field will be incremented. It's caller's duty
3379     * to ensure num_answers is propertly initialized.
3380     *
3381     * Returns -1 on error.
3382     */
3383    int mg_dns_reply_record(struct mg_dns_reply *reply,
3384                            struct mg_dns_resource_record *question,
3385                            const char *name, int rtype, int ttl, const void *rdata,
3386                            size_t rdata_len);
3387    
3388    /*
3389     * Send a DNS reply through a connection.
3390     *
3391     * The DNS data is stored in an IO buffer pointed by reply structure in `r`.
3392     * This function mutates the content of that buffer in order to ensure that
3393     * the DNS header reflects size and flags of the mssage, that might have been
3394     * updated either with `mg_dns_reply_record` or by direct manipulation of
3395     * `r->message`.
3396     *
3397     * Once sent, the IO buffer will be trimmed unless the reply IO buffer
3398     * is the connection's send buffer and the connection is not in UDP mode.
3399     */
3400    void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);
3401    
3402 #ifdef __cplusplus
3403 }
3404 #endif /* __cplusplus */
3405 
3406 #endif /* MG_ENABLE_DNS_SERVER */
3407 #endif /* CS_MONGOOSE_SRC_DNS_SERVER_H_ */
3408 /*
3409  * Copyright (c) 2014 Cesanta Software Limited
3410  * All rights reserved
3411  */
3412 
3413 /*
3414  * === Asynchronouns DNS resolver
3415  */
3416 
3417 #ifndef CS_MONGOOSE_SRC_RESOLV_H_
3418 #define CS_MONGOOSE_SRC_RESOLV_H_
3419 
3420 
3421 #ifdef __cplusplus
3422 extern "C" {
3423 #endif /* __cplusplus */
3424    
3425    enum mg_resolve_err {
3426       MG_RESOLVE_OK = 0,
3427       MG_RESOLVE_NO_ANSWERS = 1,
3428       MG_RESOLVE_EXCEEDED_RETRY_COUNT = 2,
3429       MG_RESOLVE_TIMEOUT = 3
3430    };
3431    
3432    typedef void (*mg_resolve_callback_t)(struct mg_dns_message *dns_message,
3433    void *user_data, enum mg_resolve_err);
3434    
3435    /* Options for `mg_resolve_async_opt`. */
3436    struct mg_resolve_async_opts {
3437       const char *nameserver_url;
3438       int max_retries;    /* defaults to 2 if zero */
3439       int timeout;        /* in seconds; defaults to 5 if zero */
3440       int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
3441       int only_literal;   /* only resolves literal addrs; sync cb invocation */
3442       struct mg_connection **dns_conn; /* return DNS connection */
3443    };
3444    
3445    /* See `mg_resolve_async_opt()` */
3446    int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
3447                         mg_resolve_callback_t cb, void *data);
3448    
3449    /*
3450     * Resolved a DNS name asynchronously.
3451     *
3452     * Upon successful resolution, the user callback will be invoked
3453     * with the full DNS response message and a pointer to the user's
3454     * context `data`.
3455     *
3456     * In case of timeout while performing the resolution the callback
3457     * will receive a NULL `msg`.
3458     *
3459     * The DNS answers can be extracted with `mg_next_record` and
3460     * `mg_dns_parse_record_data`:
3461     *
3462     * [source,c]
3463     * ----
3464     * struct in_addr ina;
3465     * struct mg_dns_resource_record *rr = mg_next_record(msg, MG_DNS_A_RECORD,
3466     *   NULL);
3467     * mg_dns_parse_record_data(msg, rr, &ina, sizeof(ina));
3468     * ----
3469     */
3470    int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
3471                             mg_resolve_callback_t cb, void *data,
3472                             struct mg_resolve_async_opts opts);
3473    
3474    /*
3475     * Resolve a name from `/etc/hosts`.
3476     *
3477     * Returns 0 on success, -1 on failure.
3478     */
3479    int mg_resolve_from_hosts_file(const char *host, union socket_address *usa);
3480    
3481 #ifdef __cplusplus
3482 }
3483 #endif /* __cplusplus */
3484 #endif /* CS_MONGOOSE_SRC_RESOLV_H_ */
3485 /*
3486  * Copyright (c) 2015 Cesanta Software Limited
3487  * All rights reserved
3488  * This software is dual-licensed: you can redistribute it and/or modify
3489  * it under the terms of the GNU General Public License version 2 as
3490  * published by the Free Software Foundation. For the terms of this
3491  * license, see <http://www.gnu.org/licenses/>.
3492  *
3493  * You are free to use this software under the terms of the GNU General
3494  * Public License, but WITHOUT ANY WARRANTY; without even the implied
3495  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3496  * See the GNU General Public License for more details.
3497  *
3498  * Alternatively, you can license this software under a commercial
3499  * license, as set out in <https://www.cesanta.com/license>.
3500  */
3501 
3502 /*
3503  * === CoAP
3504  *
3505  * CoAP message format:
3506  *
3507  * ```
3508  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
3509  * |Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
3510  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
3511  * | Options (if any) ...            |1 1 1 1 1 1 1 1| Payload (if any) ...
3512  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
3513  * ```
3514  */
3515 
3516 #ifndef CS_MONGOOSE_SRC_COAP_H_
3517 #define CS_MONGOOSE_SRC_COAP_H_
3518 
3519 #ifdef MG_ENABLE_COAP
3520 
3521 #define MG_COAP_MSG_TYPE_FIELD 0x2
3522 #define MG_COAP_CODE_CLASS_FIELD 0x4
3523 #define MG_COAP_CODE_DETAIL_FIELD 0x8
3524 #define MG_COAP_MSG_ID_FIELD 0x10
3525 #define MG_COAP_TOKEN_FIELD 0x20
3526 #define MG_COAP_OPTIOMG_FIELD 0x40
3527 #define MG_COAP_PAYLOAD_FIELD 0x80
3528 
3529 #define MG_COAP_ERROR 0x10000
3530 #define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)
3531 #define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)
3532 #define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)
3533 #define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)
3534 
3535 #define MG_COAP_MSG_CON 0
3536 #define MG_COAP_MSG_NOC 1
3537 #define MG_COAP_MSG_ACK 2
3538 #define MG_COAP_MSG_RST 3
3539 #define MG_COAP_MSG_MAX 3
3540 
3541 #define MG_COAP_CODECLASS_REQUEST 0
3542 #define MG_COAP_CODECLASS_RESP_OK 2
3543 #define MG_COAP_CODECLASS_CLIENT_ERR 4
3544 #define MG_COAP_CODECLASS_SRV_ERR 5
3545 
3546 #define MG_COAP_EVENT_BASE 300
3547 #define MG_EV_COAP_CON (MG_COAP_EVENT_BASE + MG_COAP_MSG_CON)
3548 #define MG_EV_COAP_NOC (MG_COAP_EVENT_BASE + MG_COAP_MSG_NOC)
3549 #define MG_EV_COAP_ACK (MG_COAP_EVENT_BASE + MG_COAP_MSG_ACK)
3550 #define MG_EV_COAP_RST (MG_COAP_EVENT_BASE + MG_COAP_MSG_RST)
3551 
3552 /*
3553  * CoAP options.
3554  * Use mg_coap_add_option and mg_coap_free_options
3555  * for creation and destruction.
3556  */
3557 struct mg_coap_option {
3558    struct mg_coap_option *next;
3559    uint32_t number;
3560    struct mg_str value;
3561 };
3562 
3563 /* CoAP message. See RFC 7252 for details. */
3564 struct mg_coap_message {
3565    uint32_t flags;
3566    uint8_t msg_type;
3567    uint8_t code_class;
3568    uint8_t code_detail;
3569    uint16_t msg_id;
3570    struct mg_str token;
3571    struct mg_coap_option *options;
3572    struct mg_str payload;
3573    struct mg_coap_option *optiomg_tail;
3574 };
3575 
3576 #ifdef __cplusplus
3577 extern "C" {
3578 #endif /* __cplusplus */
3579    
3580    /* Set CoAP protocol handler - trigger CoAP specific events */
3581    int mg_set_protocol_coap(struct mg_connection *nc);
3582    
3583    /*
3584     * Add new option to mg_coap_message structure.
3585     * Returns pointer to the newly created option.
3586     */
3587    struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
3588                                              uint32_t number, char *value,
3589                                              size_t len);
3590    
3591    /*
3592     * Free the memory allocated for options,
3593     * if cm paramater doesn't contain any option does nothing.
3594     */
3595    void mg_coap_free_options(struct mg_coap_message *cm);
3596    
3597    /*
3598     * Compose CoAP message from `mg_coap_message`
3599     * and send it into `nc` connection.
3600     * Return 0 on success. On error, it is a bitmask:
3601     *
3602     * - `#define MG_COAP_ERROR 0x10000`
3603     * - `#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)`
3604     * - `#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)`
3605     * - `#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)`
3606     * - `#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)`
3607     */
3608    uint32_t mg_coap_send_message(struct mg_connection *nc,
3609                                  struct mg_coap_message *cm);
3610    
3611    /*
3612     * Compose CoAP acknowledgement from `mg_coap_message`
3613     * and send it into `nc` connection.
3614     * Return value: see `mg_coap_send_message()`
3615     */
3616    uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);
3617    
3618    /*
3619     * Parse COAP message and fills mg_coap_message and returns cm->flags.
3620     * This is a helper function.
3621     *
3622     * NOTE: usually CoAP work over UDP, so lack of data means format error,
3623     * but in theory it is possible to use CoAP over TCP (according to RFC)
3624     *
3625     * The caller have to check results and treat COAP_NOT_ENOUGH_DATA according to
3626     * underlying protocol:
3627     *
3628     * - in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,
3629     * - in case of TCP client can try to receive more data
3630     *
3631     * Return value: see `mg_coap_send_message()`
3632     */
3633    uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);
3634    
3635    /*
3636     * Composes CoAP message from mg_coap_message structure.
3637     * This is a helper function.
3638     * Return value: see `mg_coap_send_message()`
3639     */
3640    uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
3641    
3642 #ifdef __cplusplus
3643 }
3644 #endif /* __cplusplus */
3645 
3646 #endif /* MG_ENABLE_COAP */
3647 
3648 #endif /* CS_MONGOOSE_SRC_COAP_H_ */