3#line 1 "./src/internal.h"
10#ifndef CS_MONGOOSE_SRC_INTERNAL_H_
11#define CS_MONGOOSE_SRC_INTERNAL_H_
14#define MG_MALLOC malloc
18#define MG_CALLOC calloc
22#define MG_REALLOC realloc
30#define MBUF_REALLOC MG_REALLOC
34#define MBUF_FREE MG_FREE
37#define MG_SET_PTRPTR(_ptr, _v) \
39 if (_ptr) *(_ptr) = _v; \
43#define MG_INTERNAL static
48#define MG_DISABLE_FILESYSTEM
49#define MG_DISABLE_POPEN
51#define MG_DISABLE_DIRECTORY_LISTING
52#define MG_DISABLE_SOCKETPAIR
59#define MG_CTL_MSG_MESSAGE_SIZE 8192
67 int *proto,
char *host,
size_t host_len);
76#ifndef MG_DISABLE_FILESYSTEM
84int to_wchar(
const char *path,
wchar_t *wbuf,
size_t wbuf_len);
102#ifndef MG_DISABLE_FILESYSTEM
112#ifndef MG_DISABLE_MQTT
118extern void *(*test_malloc)(
size_t size);
119extern void *(*test_calloc)(
size_t count,
size_t size);
122#ifdef MG_MODULE_LINES
123#line 1 "./src/../../common/base64.c"
130#ifndef EXCLUDE_COMMON
137#define NUM_UPPERCASES ('Z' - 'A' + 1)
138#define NUM_LETTERS (NUM_UPPERCASES * 2)
139#define NUM_DIGITS ('9' - '0' + 1)
184 const unsigned char *src = (
const unsigned char *)
str;
186 for (
i = 0;
i <
len;
i++) {
206#define BASE64_ENCODE_BODY \
207 static const char *b64 = \
208 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
211 for (i = j = 0; i < src_len; i += 3) { \
213 b = i + 1 >= src_len ? 0 : src[i + 1]; \
214 c = i + 2 >= src_len ? 0 : src[i + 2]; \
216 BASE64_OUT(b64[a >> 2]); \
217 BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
218 if (i + 1 < src_len) { \
219 BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
221 if (i + 2 < src_len) { \
222 BASE64_OUT(b64[c & 63]); \
226 while (j % 4 != 0) { \
231#define BASE64_OUT(ch) \
236#define BASE64_FLUSH() \
248#ifndef CS_DISABLE_STDIO
249#define BASE64_OUT(ch) \
251 fprintf(f, "%c", (ch)); \
255#define BASE64_FLUSH()
268 static const unsigned char tab[128] = {
302 return tab[ch & 127];
306 unsigned char a, b,
c,
d;
313 if (a == 200 || b == 200)
break;
314 *dst++ = a << 2 | b >> 4;
316 *dst++ = b << 4 | c >> 2;
321 return orig_len -
len;
325#ifdef MG_MODULE_LINES
326#line 1 "./src/../../common/cs_dbg.c"
341#ifdef CS_ENABLE_DEBUG
347#ifndef CS_DISABLE_STDIO
361 fprintf(
cs_log_file,
"%7u ", (
unsigned int) ((now - cs_log_ts) * 1000000));
384#if defined(CS_LOG_TS_DIFF) && !defined(CS_DISABLE_STDIO)
388#ifdef MG_MODULE_LINES
389#line 1 "./src/../../common/cs_dirent.c"
396#ifndef EXCLUDE_COMMON
410#define MG_MALLOC malloc
414DIR *opendir(
const char *
name) {
416 wchar_t wpath[MAX_PATH];
420 SetLastError(ERROR_BAD_ARGUMENTS);
421 }
else if ((dir = (
DIR *)
MG_MALLOC(
sizeof(*dir))) == NULL) {
422 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
425 attrs = GetFileAttributesW(wpath);
426 if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
427 (void) wcscat(wpath, L
"\\*");
428 dir->handle = FindFirstFileW(wpath, &dir->info);
429 dir->result.d_name[0] =
'\0';
439int closedir(
DIR *dir) {
443 if (dir->handle != INVALID_HANDLE_VALUE)
444 result = FindClose(dir->handle) ? 0 : -1;
448 SetLastError(ERROR_BAD_ARGUMENTS);
454struct dirent *readdir(
DIR *dir) {
455 struct dirent *result = NULL;
458 if (dir->handle != INVALID_HANDLE_VALUE) {
459 result = &dir->result;
460 (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1,
461 result->d_name,
sizeof(result->d_name), NULL,
464 if (!FindNextFileW(dir->handle, &dir->info)) {
465 (void) FindClose(dir->handle);
466 dir->handle = INVALID_HANDLE_VALUE;
470 SetLastError(ERROR_FILE_NOT_FOUND);
473 SetLastError(ERROR_BAD_ARGUMENTS);
480#ifdef CS_ENABLE_SPIFFS
482DIR *opendir(
const char *dir_name) {
486 if (dir_name != NULL && (dir = (
DIR *) malloc(
sizeof(*dir))) != NULL &&
487 SPIFFS_opendir(&fs, (
char *) dir_name, &dir->dh) == NULL) {
495int closedir(
DIR *dir) {
497 SPIFFS_closedir(&dir->dh);
503struct dirent *readdir(
DIR *dir) {
504 return SPIFFS_readdir(&dir->dh, &dir->de);
508int rmdir(
const char *path) {
513int mkdir(
const char *path, mode_t mode) {
517 return (strlen(path) == 1 && *path ==
'.') ? 0 : ENOTDIR;
526#ifdef MG_MODULE_LINES
527#line 1 "./src/../../common/cs_time.c"
536#if !defined(CS_PLATFORM) || \
537 (CS_PLATFORM != CS_P_CC3200 && CS_PLATFORM != CS_P_MSP432)
549 now = (double)
tv.tv_sec + (((
double)
tv.tv_usec) / 1000000.0);
551 now = GetTickCount() / 1000.0;
555#ifdef MG_MODULE_LINES
556#line 1 "./src/../deps/frozen/frozen.c"
577#ifndef _CRT_SECURE_NO_WARNINGS
578#define _CRT_SECURE_NO_WARNINGS
588#define snprintf _snprintf
591#ifndef FROZEN_REALLOC
592#define FROZEN_REALLOC realloc
596#define FROZEN_FREE free
611#define EXPECT(cond, err_code) \
613 if (!(cond)) return (err_code); \
618 if (_n < 0) return _n; \
620#define END_OF_STRING (-1)
627 return ch ==
' ' || ch ==
'\t' || ch ==
'\r' || ch ==
'\n';
641 if (ch == expected) {
650 if (ch == expected) {
657 return (ch >=
'a' && ch <=
'z') || (ch >=
'A' && ch <=
'Z');
661 return ch >=
'0' && ch <=
'9';
665 return is_digit(ch) || (ch >=
'a' && ch <=
'f') || (ch >=
'A' && ch <=
'F');
727 if ((ch & 0x80) == 0)
return 1;
740 int n, ch = 0,
len = 0;
744 ch = *(
unsigned char *) f->
cur;
751 }
else if (ch ==
'"') {
764 if (ch ==
'-') f->
cur++;
768 if (f->
cur < f->
end && f->
cur[0] ==
'.') {
774 if (f->
cur < f->
end && (f->
cur[0] ==
'e' || f->
cur[0] ==
'E')) {
777 if ((f->
cur[0] ==
'+' || f->
cur[0] ==
'-')) f->
cur++;
792 while (
cur(f) !=
']') {
794 if (
cur(f) ==
',') f->
cur++;
804 return i ==
len ? 1 : 0;
811 for (
i = 0;
i <
len;
i++) {
868 printf(
"%s 1 [%.*s]\n", __func__, (
int) (f->
end - f->
cur), f->
cur);
872 }
else if (ch ==
'"') {
894 while (
cur(f) !=
'}') {
896 if (
cur(f) ==
',') f->
cur++;
954 while (p[
i] !=
'\0' && p[
i] !=
'[' && p[
i] !=
'.')
i++;
959 while (path != 0 && path[0] !=
'\0') {
961 if (path[0] ==
'[') {
963 for (ind = 0,
n = 1; path[
n] !=
']' && path[
n] !=
'\0';
n++) {
966 ind += path[
n] -
'0';
968 if (path[
n++] !=
']')
return 0;
988 if (path[0] ==
'.') path++;
989 if (path[0] ==
'\0')
return &toks[
i];
997 int n = snprintf(tmp,
sizeof(tmp),
"%ld",
value);
998 strncpy(buf, tmp, buf_len > 0 ? buf_len : 0);
1004 int n = snprintf(tmp,
sizeof(tmp),
"%g",
value);
1005 strncpy(buf, tmp, buf_len > 0 ? buf_len : 0);
1015 if (s < end) *s = x; \
1020 while (
str < str_end) {
1064 if (buf_len > 0 &&
len > 0) {
1065 int n =
len < buf_len ?
len : buf_len;
1066 memcpy(buf,
str,
n);
1075 const char *
end = s + s_len, *
str, *orig = s;
1078 while (*fmt !=
'\0') {
1102 str = va_arg(ap,
char *);
1103 len = va_arg(ap,
size_t);
1107 str = va_arg(ap,
char *);
1108 len = va_arg(ap,
size_t);
1112 str = va_arg(ap,
char *);
1116 str = va_arg(ap,
char *);
1142int json_emit(
char *buf,
int buf_len,
const char *fmt, ...) {
1152#ifdef MG_MODULE_LINES
1153#line 1 "./src/../../common/md5.c"
1172#if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
1176#ifndef CS_ENABLE_NATIVE_MD5
1179#if BYTE_ORDER == BIG_ENDIAN
1181 uint32_t t = (uint32_t)((
unsigned) buf[3] << 8 | buf[2]) << 16 |
1182 ((
unsigned) buf[1] << 8 | buf[0]);
1183 *(uint32_t *) buf = t;
1192#define F1(x, y, z) (z ^ (x & (y ^ z)))
1193#define F2(x, y, z) F1(z, x, y)
1194#define F3(x, y, z) (x ^ y ^ z)
1195#define F4(x, y, z) (y ^ (x | ~z))
1197#define MD5STEP(f, w, x, y, z, data, s) \
1198 (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
1205 ctx->
buf[0] = 0x67452301;
1206 ctx->
buf[1] = 0xefcdab89;
1207 ctx->
buf[2] = 0x98badcfe;
1208 ctx->
buf[3] = 0x10325476;
1215 uint32_t a, b,
c,
d;
1300 if ((ctx->
bits[0] = t + ((uint32_t)
len << 3)) < t) ctx->
bits[1]++;
1301 ctx->
bits[1] += (uint32_t)
len >> 29;
1303 t = (t >> 3) & 0x3f;
1306 unsigned char *p = (
unsigned char *) ctx->
in + t;
1310 memcpy(p, buf,
len);
1321 memcpy(ctx->
in, buf, 64);
1328 memcpy(ctx->
in, buf,
len);
1342 memset(p, 0,
count);
1345 memset(ctx->
in, 0, 56);
1347 memset(p, 0,
count - 8);
1351 a = (uint32_t *) ctx->
in;
1352 a[14] = ctx->
bits[0];
1353 a[15] = ctx->
bits[1];
1357 memcpy(digest, ctx->
buf, 16);
1358 memset((
char *) ctx, 0,
sizeof(*ctx));
1368 static const char *hex =
"0123456789abcdef";
1370 for (;
len--; p++) {
1371 *to++ = hex[p[0] >> 4];
1372 *to++ = hex[p[0] & 0x0f];
1378 unsigned char hash[16];
1379 const unsigned char *p;
1386 while ((p = va_arg(ap,
const unsigned char *) ) != NULL) {
1387 size_t len = va_arg(ap,
size_t);
1399#ifdef MG_MODULE_LINES
1400#line 1 "./src/../../common/mbuf.c"
1407#ifndef EXCLUDE_COMMON
1414#define MBUF_REALLOC realloc
1418#define MBUF_FREE free
1435 if (new_size > a->
size || (new_size < a->size && new_size >= a->
len)) {
1442 if (buf == NULL && new_size != 0)
return;
1457 assert(off <= a->
len);
1460 if (~(
size_t) 0 - (
size_t) a->
buf <
len)
return 0;
1462 if (a->
len + len <= a->size) {
1463 memmove(a->
buf + off +
len, a->
buf + off, a->
len - off);
1465 memcpy(a->
buf + off, buf,
len);
1472 memmove(a->
buf + off +
len, a->
buf + off, a->
len - off);
1473 if (buf != NULL) memcpy(a->
buf + off, buf,
len);
1489 if (
n > 0 && n <= mb->
len) {
1496#ifdef MG_MODULE_LINES
1497#line 1 "./src/../../common/sha1.c"
1502#if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
1512 unsigned char c[64];
1516#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
1520#if BYTE_ORDER == LITTLE_ENDIAN
1522 (
rol(block->
l[
i], 24) & 0xFF00FF00) | (
rol(block->
l[
i], 8) & 0x00FF00FF);
1536 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
1537 block->l[(i + 2) & 15] ^ block->l[i & 15], \
1539#define R0(v, w, x, y, z, i) \
1540 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
1542#define R1(v, w, x, y, z, i) \
1543 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
1545#define R2(v, w, x, y, z, i) \
1546 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
1548#define R3(v, w, x, y, z, i) \
1549 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
1551#define R4(v, w, x, y, z, i) \
1552 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
1556 uint32_t a, b,
c,
d,
e;
1559 memcpy(block, buffer, 64);
1565 R0(a, b,
c,
d,
e, 0);
1566 R0(
e, a, b,
c,
d, 1);
1567 R0(
d,
e, a, b,
c, 2);
1568 R0(
c,
d,
e, a, b, 3);
1569 R0(b,
c,
d,
e, a, 4);
1570 R0(a, b,
c,
d,
e, 5);
1571 R0(
e, a, b,
c,
d, 6);
1572 R0(
d,
e, a, b,
c, 7);
1573 R0(
c,
d,
e, a, b, 8);
1574 R0(b,
c,
d,
e, a, 9);
1575 R0(a, b,
c,
d,
e, 10);
1576 R0(
e, a, b,
c,
d, 11);
1577 R0(
d,
e, a, b,
c, 12);
1578 R0(
c,
d,
e, a, b, 13);
1579 R0(b,
c,
d,
e, a, 14);
1580 R0(a, b,
c,
d,
e, 15);
1581 R1(
e, a, b,
c,
d, 16);
1582 R1(
d,
e, a, b,
c, 17);
1583 R1(
c,
d,
e, a, b, 18);
1584 R1(b,
c,
d,
e, a, 19);
1585 R2(a, b,
c,
d,
e, 20);
1586 R2(
e, a, b,
c,
d, 21);
1587 R2(
d,
e, a, b,
c, 22);
1588 R2(
c,
d,
e, a, b, 23);
1589 R2(b,
c,
d,
e, a, 24);
1590 R2(a, b,
c,
d,
e, 25);
1591 R2(
e, a, b,
c,
d, 26);
1592 R2(
d,
e, a, b,
c, 27);
1593 R2(
c,
d,
e, a, b, 28);
1594 R2(b,
c,
d,
e, a, 29);
1595 R2(a, b,
c,
d,
e, 30);
1596 R2(
e, a, b,
c,
d, 31);
1597 R2(
d,
e, a, b,
c, 32);
1598 R2(
c,
d,
e, a, b, 33);
1599 R2(b,
c,
d,
e, a, 34);
1600 R2(a, b,
c,
d,
e, 35);
1601 R2(
e, a, b,
c,
d, 36);
1602 R2(
d,
e, a, b,
c, 37);
1603 R2(
c,
d,
e, a, b, 38);
1604 R2(b,
c,
d,
e, a, 39);
1605 R3(a, b,
c,
d,
e, 40);
1606 R3(
e, a, b,
c,
d, 41);
1607 R3(
d,
e, a, b,
c, 42);
1608 R3(
c,
d,
e, a, b, 43);
1609 R3(b,
c,
d,
e, a, 44);
1610 R3(a, b,
c,
d,
e, 45);
1611 R3(
e, a, b,
c,
d, 46);
1612 R3(
d,
e, a, b,
c, 47);
1613 R3(
c,
d,
e, a, b, 48);
1614 R3(b,
c,
d,
e, a, 49);
1615 R3(a, b,
c,
d,
e, 50);
1616 R3(
e, a, b,
c,
d, 51);
1617 R3(
d,
e, a, b,
c, 52);
1618 R3(
c,
d,
e, a, b, 53);
1619 R3(b,
c,
d,
e, a, 54);
1620 R3(a, b,
c,
d,
e, 55);
1621 R3(
e, a, b,
c,
d, 56);
1622 R3(
d,
e, a, b,
c, 57);
1623 R3(
c,
d,
e, a, b, 58);
1624 R3(b,
c,
d,
e, a, 59);
1625 R4(a, b,
c,
d,
e, 60);
1626 R4(
e, a, b,
c,
d, 61);
1627 R4(
d,
e, a, b,
c, 62);
1628 R4(
c,
d,
e, a, b, 63);
1629 R4(b,
c,
d,
e, a, 64);
1630 R4(a, b,
c,
d,
e, 65);
1631 R4(
e, a, b,
c,
d, 66);
1632 R4(
d,
e, a, b,
c, 67);
1633 R4(
c,
d,
e, a, b, 68);
1634 R4(b,
c,
d,
e, a, 69);
1635 R4(a, b,
c,
d,
e, 70);
1636 R4(
e, a, b,
c,
d, 71);
1637 R4(
d,
e, a, b,
c, 72);
1638 R4(
c,
d,
e, a, b, 73);
1639 R4(b,
c,
d,
e, a, 74);
1640 R4(a, b,
c,
d,
e, 75);
1641 R4(
e, a, b,
c,
d, 76);
1642 R4(
d,
e, a, b,
c, 77);
1643 R4(
c,
d,
e, a, b, 78);
1644 R4(b,
c,
d,
e, a, 79);
1652 memset(block, 0,
sizeof(block));
1653 a = b =
c =
d =
e = 0;
1662 context->
state[0] = 0x67452301;
1663 context->
state[1] = 0xEFCDAB89;
1664 context->
state[2] = 0x98BADCFE;
1665 context->
state[3] = 0x10325476;
1666 context->
state[4] = 0xC3D2E1F0;
1675 if ((context->
count[0] += len << 3) <
j) context->
count[1]++;
1676 context->
count[1] += (len >> 29);
1678 if ((
j + len) > 63) {
1681 for (;
i + 63 < len;
i += 64) {
1692 unsigned char finalcount[8],
c;
1694 for (
i = 0;
i < 8;
i++) {
1695 finalcount[
i] = (
unsigned char) ((context->
count[(
i >= 4 ? 0 : 1)] >>
1696 ((3 - (
i & 3)) * 8)) &
1701 while ((context->
count[0] & 504) != 448) {
1706 for (
i = 0;
i < 20;
i++) {
1708 (
unsigned char) ((context->
state[
i >> 2] >> ((3 - (
i & 3)) * 8)) & 255);
1710 memset(context,
'\0',
sizeof(*context));
1711 memset(&finalcount,
'\0',
sizeof(finalcount));
1715 const unsigned char *
data,
size_t datalen,
1716 unsigned char out[20]) {
1718 unsigned char buf1[64], buf2[64], tmp_key[20],
i;
1720 if (keylen >
sizeof(buf1)) {
1725 keylen =
sizeof(tmp_key);
1728 memset(buf1, 0,
sizeof(buf1));
1729 memset(buf2, 0,
sizeof(buf2));
1730 memcpy(buf1,
key, keylen);
1731 memcpy(buf2,
key, keylen);
1733 for (
i = 0;
i <
sizeof(buf1);
i++) {
1750#ifdef MG_MODULE_LINES
1751#line 1 "./src/../../common/str_util.c"
1758#ifndef EXCLUDE_COMMON
1765 for (;
l < maxlen && s[
l] !=
'\0';
l++) {
1770#define C_SNPRINTF_APPEND_CHAR(ch) \
1772 if (i < (int) buf_size) buf[i] = ch; \
1776#define C_SNPRINTF_FLAG_ZERO 1
1778#ifdef C_DISABLE_BUILTIN_SNPRINTF
1779int c_vsnprintf(
char *buf,
size_t buf_size,
const char *fmt, va_list ap) {
1780 return vsnprintf(buf, buf_size, fmt, ap);
1783static int c_itoa(
char *buf,
size_t buf_size, int64_t num,
int base,
int flags,
1786 int i = 0,
k = 0, neg = 0;
1795 int rem = num %
base;
1797 tmp[
k++] =
'0' + rem;
1799 tmp[
k++] =
'a' + (rem - 10);
1806 while (
k < field_width &&
k < (
int)
sizeof(tmp) - 1) {
1824int c_vsnprintf(
char *buf,
size_t buf_size,
const char *fmt, va_list ap) {
1825 int ch,
i = 0, len_mod, flags, precision, field_width;
1827 while ((ch = *fmt++) !=
'\0') {
1839 flags = field_width = precision = len_mod = 0;
1847 while (*fmt >=
'0' && *fmt <=
'9') {
1849 field_width += *fmt++ -
'0';
1853 field_width = va_arg(ap,
int);
1861 precision = va_arg(ap,
int);
1864 while (*fmt >=
'0' && *fmt <=
'9') {
1866 precision += *fmt++ -
'0';
1895 const char *s = va_arg(ap,
const char *);
1897 int pad = field_width - (precision >= 0 ?
c_strnlen(s, precision) : 0);
1898 for (
j = 0;
j < pad;
j++) {
1905 for (
j = 0; (precision <= 0 ||
j < precision) && s[
j] !=
'\0';
j++) {
1909 }
else if (ch ==
'c') {
1910 ch = va_arg(ap,
int);
1912 }
else if (ch ==
'd' && len_mod == 0) {
1913 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
int), 10, flags,
1915 }
else if (ch ==
'd' && len_mod ==
'l') {
1916 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
long), 10, flags,
1919 }
else if (ch ==
'd' && len_mod ==
'z') {
1920 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap, ssize_t), 10, flags,
1923 }
else if (ch ==
'd' && len_mod ==
'q') {
1924 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap, int64_t), 10, flags,
1926 }
else if ((ch ==
'x' || ch ==
'u') && len_mod == 0) {
1927 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
unsigned),
1928 ch ==
'x' ? 16 : 10, flags, field_width);
1929 }
else if ((ch ==
'x' || ch ==
'u') && len_mod ==
'l') {
1930 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
unsigned long),
1931 ch ==
'x' ? 16 : 10, flags, field_width);
1932 }
else if ((ch ==
'x' || ch ==
'u') && len_mod ==
'z') {
1933 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
size_t),
1934 ch ==
'x' ? 16 : 10, flags, field_width);
1935 }
else if (ch ==
'p') {
1936 unsigned long num = (
unsigned long) va_arg(ap,
void *);
1939 i +=
c_itoa(buf +
i, buf_size -
i, num, 16, flags, 0);
1954 buf[
i < (int) buf_size ?
i : (int) buf_size - 1] =
'\0';
1961int c_snprintf(
char *buf,
size_t buf_size,
const char *fmt, ...) {
1971int to_wchar(
const char *path,
wchar_t *wbuf,
size_t wbuf_len) {
1973 char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
1975 strncpy(buf, path,
sizeof(buf));
1976 buf[
sizeof(buf) - 1] =
'\0';
1979 p = buf + strlen(buf) - 1;
1980 while (p > buf && p[-1] !=
':' && (p[0] ==
'\\' || p[0] ==
'/')) *p-- =
'\0';
1982 memset(wbuf, 0, wbuf_len *
sizeof(
wchar_t));
1983 ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (
int) wbuf_len);
1989 WideCharToMultiByte(CP_UTF8, 0, wbuf, (
int) wbuf_len, buf2,
sizeof(buf2),
1991 if (strcmp(buf, buf2) != 0) {
2001const char *
c_strnstr(
const char *s,
const char *find,
size_t slen) {
2002 size_t find_length = strlen(find);
2005 for (
i = 0;
i < slen;
i++) {
2006 if (
i + find_length > slen) {
2010 if (strncmp(&s[
i], find, find_length) == 0) {
2019#ifdef MG_MODULE_LINES
2020#line 1 "./src/net.c"
2046#define MG_MAX_HOST_LEN 200
2048#define MG_COPY_COMMON_CONNECTION_OPTIONS(dst, src) \
2049 memcpy(dst, src, sizeof(*dst));
2052#define _MG_ALLOWED_CONNECT_FLAGS_MASK \
2053 (MG_F_USER_1 | MG_F_USER_2 | MG_F_USER_3 | MG_F_USER_4 | MG_F_USER_5 | \
2054 MG_F_USER_6 | MG_F_WEBSOCKET_NO_DEFRAG)
2056#define _MG_CALLBACK_MODIFIABLE_FLAGS_MASK \
2057 (MG_F_USER_1 | MG_F_USER_2 | MG_F_USER_3 | MG_F_USER_4 | MG_F_USER_5 | \
2058 MG_F_USER_6 | MG_F_WEBSOCKET_NO_DEFRAG | MG_F_SEND_AND_CLOSE | \
2059 MG_F_CLOSE_IMMEDIATELY | MG_F_IS_WEBSOCKET | MG_F_DELETE_CHUNK)
2062#define intptr_t long
2074 DBG((
"%p %p", mgr,
c));
2093 if (ev_handler == NULL) {
2100 DBG((
"%p %s ev=%d ev_data=%p flags=%lu rmbl=%d smbl=%d", nc,
2101 ev_handler == nc->
handler ?
"user" :
"proto", ev, ev_data, nc->
flags,
2104#if !defined(NO_LIBC) && !defined(MG_DISABLE_HEXDUMP)
2110 *(
int *) ev_data, ev);
2117 if (ev_handler != NULL) {
2118 unsigned long flags_before = nc->
flags;
2120 ev_handler(nc, ev, ev_data);
2123 if (ev_handler == nc->
handler && nc->
flags != flags_before) {
2124 nc->
flags = (flags_before & ~_MG_CALLBACK_MODIFIABLE_FLAGS_MASK) |
2131 DBG((
"%p after %s flags=%lu rmbl=%d smbl=%d", nc,
2132 ev_handler == nc->
handler ?
"user" :
"proto", nc->
flags,
2137 if (
c->ev_timer_time > 0 && now >=
c->ev_timer_time) {
2138 double old_value =
c->ev_timer_time;
2144 if (
c->ev_timer_time == old_value) {
2145 c->ev_timer_time = 0;
2162 if (conn->
ssl != NULL) SSL_free(conn->
ssl);
2168 memset(conn, 0,
sizeof(*conn));
2173 DBG((
"%p %lu", conn, conn->
flags));
2180 memset(m, 0,
sizeof(*m));
2181#ifndef MG_DISABLE_SOCKETPAIR
2189 WSAStartup(MAKEWORD(2, 2), &
data);
2191#elif defined(__unix__)
2194 signal(SIGPIPE, SIG_IGN);
2199 static int init_done;
2208 DBG((
"=================================="));
2209 DBG((
"init mgr=%p", m));
2212#ifdef MG_ENABLE_JAVASCRIPT
2213static enum v7_err mg_send_js(
struct v7 *v7, v7_val_t *res) {
2214 v7_val_t arg0 = v7_arg(v7, 0);
2215 v7_val_t arg1 = v7_arg(v7, 1);
2219 if (v7_is_string(arg1)) {
2220 const char *
data = v7_get_string_data(v7, &arg1, &len);
2224 *res = v7_mk_number(len);
2229enum v7_err mg_enable_javascript(
struct mg_mgr *m,
struct v7 *v7,
2230 const char *init_file_name) {
2233 v7_set_method(v7, v7_get_global(v7),
"mg_send", mg_send_js);
2234 return v7_exec_file(v7, init_file_name, &
v);
2242 if (m == NULL)
return;
2246#ifndef MG_DISABLE_SOCKETPAIR
2253 tmp_conn = conn->
next;
2267 if (
buf != mem &&
buf != NULL) {
2283#ifndef MG_DISABLE_SYNC_RESOLVER
2286#ifdef MG_ENABLE_GETADDRINFO
2288 struct addrinfo hints, *servinfo, *p;
2289 struct sockaddr_in *h = NULL;
2290 memset(&hints, 0,
sizeof hints);
2291 hints.ai_family = AF_INET;
2292 hints.ai_socktype = SOCK_STREAM;
2293 if ((rv = getaddrinfo(host, NULL, NULL, &servinfo)) != 0) {
2294 DBG((
"getaddrinfo(%s) failed: %s", host, strerror(errno)));
2297 for (p = servinfo; p != NULL; p = p->ai_next) {
2298 memcpy(&h, &p->ai_addr,
sizeof(
struct sockaddr_in *));
2299 memcpy(ina, &h->sin_addr,
sizeof(ina));
2301 freeaddrinfo(servinfo);
2305 if ((he = gethostbyname(host)) == NULL) {
2306 DBG((
"gethostbyname(%s) failed: %s", host, strerror(errno)));
2308 memcpy(ina, he->h_addr_list[0],
sizeof(*ina));
2374 int *proto,
char *host,
size_t host_len) {
2375 unsigned int a, b,
c,
d, port = 0;
2377#ifdef MG_ENABLE_IPV6
2386 memset(
sa, 0,
sizeof(*
sa));
2387 sa->
sin.sin_family = AF_INET;
2389 *proto = SOCK_STREAM;
2391 if (strncmp(
str,
"udp://", 6) == 0) {
2393 *proto = SOCK_DGRAM;
2394 }
else if (strncmp(
str,
"tcp://", 6) == 0) {
2398 if (sscanf(
str,
"%u.%u.%u.%u:%u%n", &a, &b, &
c, &
d, &port, &len) == 5) {
2400 sa->
sin.sin_addr.s_addr =
2401 htonl(((uint32_t) a << 24) | ((uint32_t) b << 16) |
c << 8 |
d);
2402 sa->
sin.sin_port = htons((uint16_t) port);
2403#ifdef MG_ENABLE_IPV6
2404 }
else if (sscanf(
str,
"[%99[^]]]:%u%n",
buf, &port, &len) == 2 &&
2407 sa->
sin6.sin6_family = AF_INET6;
2408 sa->
sin.sin_port = htons((uint16_t) port);
2410#ifndef MG_DISABLE_RESOLVER
2411 }
else if (strlen(
str) < host_len &&
2412 sscanf(
str,
"%[^ :]:%u%n", host, &port, &len) == 2) {
2413 sa->
sin.sin_port = htons((uint16_t) port);
2418 }
else if (sscanf(
str,
":%u%n", &port, &len) == 1 ||
2419 sscanf(
str,
"%u%n", &port, &len) == 1) {
2421 sa->
sin.sin_port = htons((uint16_t) port);
2427 return port < 0xffffUL && (ch ==
'\0' || ch ==
',' || isspace(ch)) ? len : -1;
2436#ifndef MG_DISABLE_PFS
2441static const char mg_s_cipher_list[] =
2442#if defined(MG_SSL_CRYPTO_MODERN)
2443 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
2444 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
2445 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
2446 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
2447 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
2448 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
2449 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
2450 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:"
2451 "!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"
2452#elif defined(MG_SSL_CRYPTO_OLD)
2453 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
2454 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
2455 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
2456 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
2457 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
2458 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
2459 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
2460 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:"
2461 "ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:"
2462 "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:"
2463 "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:"
2464 "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
2466 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
2467 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
2468 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
2470 "ECDHE-ECDSA-AES128-SHA256:"
2472 "ECDHE-ECDSA-AES128-SHA:"
2474 "ECDHE-ECDSA-AES256-SHA384:"
2476 "ECDHE-ECDSA-AES256-SHA:"
2480 "AES128-GCM-SHA256:AES256-GCM-SHA384:"
2481 "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:"
2483 "!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!RSA:!CBC-SHA:!CAMELLIA:"
2484 "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
2492static const char mg_s_default_dh_params[] =
2494-----BEGIN DH PARAMETERS-----\n\
2495MIIBCAKCAQEAlvbgD/qh9znWIlGFcV0zdltD7rq8FeShIqIhkQ0C7hYFThrBvF2E\n\
2496Z9bmgaP+sfQwGpVlv9mtaWjvERbu6mEG7JTkgmVUJrUt/wiRzwTaCXBqZkdUO8Tq\n\
2497+E6VOEQAilstG90ikN1Tfo+K6+X68XkRUIlgawBTKuvKVwBhuvlqTGerOtnXWnrt\n\
2498ym//hd3cd5PBYGBix0i7oR4xdghvfR2WLVu0LgdThTBb6XP7gLd19cQ1JuBtAajZ\n\
2499wMuPn7qlUkEFDIkAZy59/Hue/H2Q2vU/JsvVhHWCQBL4F1ofEAt50il6ZxR1QfFK\n\
25009VGKDC4oOgm9DlxwwBoC2FjqmvQlqVV3kwIBAg==\n\
2501-----END DH PARAMETERS-----\n";
2504static int mg_use_ca_cert(
SSL_CTX *
ctx,
const char *cert) {
2507 }
else if (cert == NULL || cert[0] ==
'\0') {
2510 SSL_CTX_set_verify(
ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
2511 return SSL_CTX_load_verify_locations(
ctx, cert, NULL) == 1 ? 0 : -2;
2514static int mg_use_cert(
SSL_CTX *
ctx,
const char *pem_file) {
2517 }
else if (pem_file == NULL || pem_file[0] ==
'\0') {
2519 }
else if (SSL_CTX_use_certificate_file(
ctx, pem_file, 1) == 0 ||
2520 SSL_CTX_use_PrivateKey_file(
ctx, pem_file, 1) == 0) {
2523#ifndef MG_DISABLE_PFS
2528 bio = BIO_new_file(pem_file,
"r");
2530 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2538 bio = BIO_new_mem_buf((
void *) mg_s_default_dh_params, -1);
2539 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2543 SSL_CTX_set_tmp_dh(
ctx, dh);
2544 SSL_CTX_set_options(
ctx, SSL_OP_SINGLE_DH_USE);
2548 SSL_CTX_set_mode(
ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
2549 SSL_CTX_use_certificate_chain_file(
ctx, pem_file);
2571 const char *ca_cert) {
2572 const char *result = NULL;
2573 DBG((
"%p %s %s", nc, (cert ? cert :
""), (ca_cert ? ca_cert :
"")));
2576 return "SSL for UDP is not supported";
2579 if (nc->
ssl != NULL) {
2589 (nc->
ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
2590 result =
"SSL_CTX_new() failed";
2592 (nc->
ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
2593 result =
"SSL_CTX_new() failed";
2594 }
else if (mg_use_cert(nc->
ssl_ctx, cert) != 0) {
2595 result =
"Invalid ssl cert";
2596 }
else if (mg_use_ca_cert(nc->
ssl_ctx, ca_cert) != 0) {
2597 result =
"Invalid CA cert";
2600 result =
"SSL_new() failed";
2606 SSL_set_fd(nc->
ssl, nc->
sock);
2609 SSL_CTX_set_options(nc->
ssl_ctx, SSL_OP_NO_SSLv2);
2610 SSL_CTX_set_options(nc->
ssl_ctx, SSL_OP_NO_SSLv3);
2612#ifndef MG_DISABLE_PFS
2613 SSL_CTX_set_cipher_list(nc->
ssl_ctx, mg_s_cipher_list);
2622 memset(&opts, 0,
sizeof(opts));
2624 if (nc == NULL)
return NULL;
2649#if !defined(NO_LIBC) && !defined(MG_DISABLE_HEXDUMP)
2666 DBG((
"%p discarded %d bytes", nc, len));
2694 DBG((
"%p %u", nc, (
unsigned int) len));
2708 memset(&opts, 0,
sizeof(opts));
2745 DBG((
"%p %s://%s:%hu", nc, proto == SOCK_DGRAM ?
"udp" :
"tcp",
2749 if (proto == SOCK_DGRAM) {
2759 DBG((
"%p connect, err=%d", nc,
err));
2760 nc->
flags &= ~MG_F_CONNECTING;
2767#ifndef MG_DISABLE_RESOLVER
2780 nc->
flags &= ~MG_F_RESOLVING;
2817 memset(&opts, 0,
sizeof(opts));
2834 sizeof(host))) < 0) {
2845 if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
2846 const char *err =
mg_set_ssl(nc, opts.ssl_cert, opts.ssl_ca_cert);
2852 if (opts.ssl_ca_cert != NULL && (opts.ssl_server_name == NULL ||
2853 strcmp(opts.ssl_server_name,
"*") != 0)) {
2854 if (opts.ssl_server_name == NULL) opts.ssl_server_name = host;
2856 SSL_CTX_kr_set_verify_name(nc->
ssl_ctx, opts.ssl_server_name);
2860 "Server name verification requested but is not supported");
2869#ifndef MG_DISABLE_RESOLVER
2876 memset(&o, 0,
sizeof(o));
2901 memset(&opts, 0,
sizeof(opts));
2902 return mg_bind_opt(srv, address, event_handler, opts);
2928 if (proto == SOCK_DGRAM) {
2935 DBG((
"Failed to open listener: %d", rc));
2941 if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
2942 const char *err =
mg_set_ssl(nc, opts.ssl_cert, opts.ssl_ca_cert);
2959#ifndef MG_DISABLE_SOCKETPAIR
2986 return n >= 0 &&
n <= 255;
2990 int n, a, b,
c,
d, slash = 32, len = 0;
2992 if ((sscanf(spec,
"%d.%d.%d.%d/%d%n", &a, &b, &
c, &
d, &slash, &
n) == 5 ||
2993 sscanf(spec,
"%d.%d.%d.%d%n", &a, &b, &
c, &
d, &
n) == 4) &&
2998 ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t)
c << 8) |
d;
2999 *
mask = slash ? 0xffffffffU << (32 - slash) : 0;
3011 allowed = (acl == NULL || *acl ==
'\0') ?
'+' :
'-';
3015 if ((flag !=
'+' && flag !=
'-') ||
3020 if (net == (remote_ip &
mask)) {
3025 DBG((
"%08x %c", remote_ip, allowed));
3026 return allowed ==
'+';
3036 double result =
c->ev_timer_time;
3037 c->ev_timer_time = timestamp;
3044 (
unsigned long) timestamp));
3065 memset(&opts, 0,
sizeof(opts));
3072#ifdef MG_MODULE_LINES
3073#line 1 "./src/net_if_socket.c"
3080#ifndef MG_DISABLE_SOCKET_IF
3085#define MG_TCP_RECV_BUFFER_SIZE 1024
3086#define MG_UDP_RECV_BUFFER_SIZE 1500
3096 unsigned long on = 1;
3097 ioctlsocket(sock, FIONBIO, &on);
3098#elif defined(MG_SOCKET_SIMPLELINK)
3099 SlSockNonblocking_t opt;
3100 opt.NonblockingEnabled = 1;
3101 sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &opt,
sizeof(opt));
3103 int flags = fcntl(sock, F_GETFL, 0);
3104 fcntl(sock, F_SETFL,
flags | O_NONBLOCK);
3109#ifdef MG_SOCKET_SIMPLELINK
3110 DBG((
"n = %d, errno = %d",
n, errno));
3111 if (
n < 0) errno =
n;
3113 return n == 0 || (
n < 0 && errno != EINTR && errno != EINPROGRESS &&
3114 errno != EAGAIN && errno != EWOULDBLOCK
3115#ifdef MG_SOCKET_SIMPLELINK
3116 && errno != SL_EALREADY
3119 && WSAGetLastError() != WSAEINTR &&
3120 WSAGetLastError() != WSAEWOULDBLOCK
3131 nc->
err = errno ? errno : 1;
3134#if !defined(MG_SOCKET_SIMPLELINK) && !defined(MG_ESP8266)
3137 rc = connect(nc->
sock, &sa->
sa,
sizeof(sa->
sin));
3139 DBG((
"%p sock %d err %d", nc, nc->
sock, nc->
err));
3146 nc->
err = errno ? errno : 1;
3155 return (errno ? errno : 1);
3163 if (sock < 0)
return (errno ? errno : 1);
3207 socklen_t sa_len =
sizeof(
sa);
3208 extern int check_midas_acl(
const struct sockaddr *
sa,
int len);
3210 sock_t sock = accept(lc->
sock, &
sa.sa, &sa_len);
3212 DBG((
"%p: failed to accept: %d", lc, errno));
3215 if (!check_midas_acl(&
sa.sa, sa_len)) {
3228 if (nc->
ssl == NULL || SSL_set_fd(nc->
ssl, sock) != 1) {
3242 (
sa->sa.sa_family == AF_INET) ?
sizeof(
sa->sin) :
sizeof(
sa->sin6);
3244#if !defined(MG_SOCKET_SIMPLELINK) && !defined(MG_LWIP)
3249#
if !defined(MG_SOCKET_SIMPLELINK) && \
3251#if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)
3253 !setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
void *) &on,
3257#if !defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE)
3267 !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
void *) &on,
sizeof(on)) &&
3271 !bind(sock, &
sa->sa, sa_len) &&
3272 (proto == SOCK_DGRAM || listen(sock,
SOMAXCONN) == 0)) {
3273#if !defined(MG_SOCKET_SIMPLELINK) && \
3277 (void) getsockname(sock, &
sa->sa, &sa_len);
3293 if (io->
len == 0)
return;
3296 assert(io->
len > 0);
3301 DBG((
"%p %d %d %d %s:%hu", nc, nc->
sock,
n, errno,
3311 if (nc->
ssl != NULL) {
3314 DBG((
"%p %d bytes -> %d (SSL)", nc,
n, nc->
sock));
3316 int ssl_err = mg_ssl_err(nc,
n);
3317 if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
3332 DBG((
"%p %d bytes -> %d", nc,
n, nc->
sock));
3345 return avail > max ? max : avail;
3358 if (conn->
ssl != NULL) {
3364 DBG((
"%p %d bytes <- %d (SSL)", conn,
n, conn->
sock));
3370 if (
buf == NULL)
break;
3373 mg_ssl_err(conn,
n);
3385 DBG((
"%p %d bytes (PLAIN) <- %d", conn,
n, conn->
sock));
3397 socklen_t *sa_len,
char **
buf) {
3401 DBG((
"Out of memory"));
3406 DBG((
"%p recvfrom: %s", nc, strerror(errno)));
3415 socklen_t sa_len =
sizeof(
sa);
3418 ntohs(nc->
sa.
sin.sin_port)));
3424 int ssl_err = SSL_get_error(conn->
ssl, res);
3425 DBG((
"%p %d -> %d", conn, res, ssl_err));
3426 if (ssl_err == SSL_ERROR_WANT_READ) {
3428 }
else if (ssl_err == SSL_ERROR_WANT_WRITE) {
3432 SSL_write(conn->
ssl,
"", 0);
3439 int server_side = (nc->
listener != NULL);
3440 int res = server_side ? SSL_accept(nc->
ssl) : SSL_connect(nc->ssl);
3441 DBG((
"%p %d res %d %d", nc, server_side, res, errno));
3449 socklen_t sa_len =
sizeof(
sa);
3450 (void) getpeername(nc->
sock, &
sa.sa, &sa_len);
3456 int ssl_err = mg_ssl_err(nc, res);
3457 if (ssl_err != SSL_ERROR_WANT_READ && ssl_err != SSL_ERROR_WANT_WRITE) {
3467#define _MG_F_FD_CAN_READ 1
3468#define _MG_F_FD_CAN_WRITE 1 << 1
3469#define _MG_F_FD_ERROR 1 << 2
3472 DBG((
"%p fd=%d fd_flags=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->
sock,
3476 if (fd_flags != 0) {
3478#if !defined(MG_SOCKET_SIMPLELINK) && !defined(MG_ESP8266)
3480 socklen_t len =
sizeof(err);
3482 getsockopt(nc->
sock, SOL_SOCKET, SO_ERROR, (
char *) &err, &len);
3483 if (ret != 0) err = 1;
3492 if (nc->
ssl != NULL && err == 0) {
3493 SSL_set_fd(nc->
ssl, nc->
sock);
3501 }
else if (nc->
err != 0) {
3534 DBG((
"%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->
sock, nc->
flags,
3538#ifndef MG_DISABLE_SOCKETPAIR
3544 DBG((
"read %d from ctl socket", len));
3565 DBG((
"%p using select()",
mgr));
3566#ifndef MG_DISABLE_SOCKETPAIR
3599 fd_set read_set, write_set, err_set;
3601 int num_fds, num_ev, num_timers = 0;
3604 FD_ZERO(&write_set);
3606#ifndef MG_DISABLE_SOCKETPAIR
3648 if (num_timers > 0) {
3649 double timer_timeout_ms = (min_timer -
mg_time()) * 1000 + 1 ;
3650 if (timer_timeout_ms < timeout_ms) {
3651 timeout_ms = timer_timeout_ms;
3654 if (timeout_ms < 0) timeout_ms = 0;
3656 tv.tv_sec = timeout_ms / 1000;
3657 tv.tv_usec = (timeout_ms % 1000) * 1000;
3659 num_ev = select((
int) max_fd + 1, &read_set, &write_set, &err_set, &
tv);
3661 DBG((
"select @ %ld num_ev=%d of %d, timeout=%d", (
long) now, num_ev, num_fds,
3664#ifndef MG_DISABLE_SOCKETPAIR
3666 FD_ISSET(mgr->
ctl[1], &read_set)) {
3675 fd_flags = (FD_ISSET(nc->
sock, &read_set) &&
3682#ifdef MG_SOCKET_SIMPLELINK
3710#ifndef MG_DISABLE_SOCKETPAIR
3714 socklen_t len =
sizeof(
sa.sin);
3719 (void) memset(&
sa, 0,
sizeof(
sa));
3720 sa.
sin.sin_family = AF_INET;
3721 sa.sin.sin_port = htons(0);
3722 sa.sin.sin_addr.s_addr = htonl(0x7f000001);
3725 }
else if (bind(sock, &
sa.sa, len) != 0) {
3726 }
else if (sock_type == SOCK_STREAM && listen(sock, 1) != 0) {
3727 }
else if (getsockname(sock, &
sa.sa, &len) != 0) {
3729 }
else if (connect(sp[0], &
sa.sa, len) != 0) {
3730 }
else if (sock_type == SOCK_DGRAM &&
3731 (getsockname(sp[0], &
sa.sa, &len) != 0 ||
3732 connect(sock, &
sa.sa, len) != 0)) {
3733 }
else if ((sp[1] = (sock_type == SOCK_DGRAM ? sock
3734 : accept(sock, &
sa.sa, &len))) ==
3754#ifndef MG_SOCKET_SIMPLELINK
3757 socklen_t slen =
sizeof(*sa);
3758 memset(
sa, 0, slen);
3760 getpeername(sock, &
sa->sa, &slen);
3762 getsockname(sock, &
sa->sa, &slen);
3775#ifndef MG_SOCKET_SIMPLELINK
3781 if (remote) memcpy(
sa, &nc->
sa,
sizeof(*
sa));
3786#ifdef MG_MODULE_LINES
3787#line 1 "./src/multithreading.c"
3797#ifdef MG_ENABLE_THREADS
3799static void multithreaded_ev_handler(
struct mg_connection *
c,
int ev,
void *p);
3806static void *per_connection_thread_function(
void *
param) {
3829 peer->priv_2 = NULL;
3834static void forwarder_ev_handler(
struct mg_connection *
c,
int ev,
void *p) {
3843static void spawn_handling_thread(
struct mg_connection *nc) {
3854 memset(&dummy, 0,
sizeof(dummy));
3855 c[0] =
mg_add_sock(&dummy, sp[0], forwarder_ev_handler);
3859 link_conns(
c[0], nc);
3884static void multithreaded_ev_handler(
struct mg_connection *
c,
int ev,
void *p) {
3887 spawn_handling_thread(
c);
3888 c->handler = forwarder_ev_handler;
3895 nc->
handler = multithreaded_ev_handler;
3898#ifdef MG_MODULE_LINES
3899#line 1 "./src/uri.c"
3917 for (; *p <
end; (*p)++) {
3922 res->
len = (*p) - res->
p;
3923 if (*p <
end) (*p)++;
3928 unsigned int *port,
struct mg_str *path,
struct mg_str *query,
3929 struct mg_str *fragment) {
3930 struct mg_str rscheme = {0, 0}, ruser_info = {0, 0}, rhost = {0, 0},
3931 rpath = {0, 0}, rquery = {0, 0}, rfragment = {0, 0};
3932 unsigned int rport = 0;
3942 const char *
p = uri.
p, *
end =
p + uri.
len;
3952 for (;
p <
end;
p++) {
3954 state = P_SCHEME_OR_PORT;
3956 }
else if (*
p ==
'/') {
3963 rhost.len =
p - uri.
p;
3966 case P_SCHEME_OR_PORT:
3967 if (
end -
p >= 3 && memcmp(
p,
"://", 3) == 0) {
3969 rscheme.
len =
p - uri.
p;
3970 state = P_USER_INFO;
3974 rhost.len =
p - uri.
p;
3981 for (;
p <
end;
p++) {
3985 }
else if (*
p ==
'/') {
3989 if (
p ==
end || *
p ==
'/') {
3994 ruser_info.len =
p - ruser_info.p;
3999 for (;
p <
end;
p++) {
4003 }
else if (*
p ==
'/') {
4008 rhost.len =
p - rhost.p;
4012 for (;
p <
end;
p++) {
4030 if (scheme != 0) *scheme = rscheme;
4031 if (user_info != 0) *user_info = ruser_info;
4032 if (host != 0) *host = rhost;
4033 if (port != 0) *port = rport;
4034 if (path != 0) *path = rpath;
4035 if (query != 0) *query = rquery;
4036 if (fragment != 0) *fragment = rfragment;
4043 const char *s = in->
p, *se = s + in->
len;
4044 char *cp = (
char *) out->
p, *
d;
4046 if (in->
len == 0 || *s !=
'/') {
4054 const char *next = s;
4057 if (
mg_vcmp(&component,
".") == 0) {
4059 }
else if (
mg_vcmp(&component,
"..") == 0) {
4061 if (
d > cp + 1 && *(
d - 1) ==
'/')
d--;
4062 while (
d > cp && *(
d - 1) !=
'/')
d--;
4064 memmove(
d, s, next - s);
4069 if (
d == cp) *
d++ =
'/';
4075#ifdef MG_MODULE_LINES
4076#line 1 "./src/http.c"
4083#ifndef MG_DISABLE_HTTP
4090#ifndef MG_DISABLE_HTTP_WEBSOCKET
4091#define MG_WS_NO_HOST_HEADER_MAGIC ((char *) 0x1)
4140#ifndef MG_DISABLE_FILESYSTEM
4143#ifndef MG_DISABLE_CGI
4146#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
4158 if (
c->proto_data == NULL) {
4169#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
4170static void mg_http_free_proto_data_mp_stream(
4181#ifndef MG_DISABLE_FILESYSTEM
4184 if (
d->fp != NULL) {
4192#ifndef MG_DISABLE_CGI
4204 while (current != NULL) {
4206 free((
void *) current->
name);
4217#ifndef MG_DISABLE_FILESYSTEM
4220#ifndef MG_DISABLE_CGI
4223#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
4224 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
4248#define MIME_ENTRY(_ext, _type) \
4249 { _ext, sizeof(_ext) - 1, _type }
4250static const struct {
4261 MIME_ENTRY(
"js",
"application/x-javascript"),
4269 MIME_ENTRY(
"torrent",
"application/x-bittorrent"),
4283 MIME_ENTRY(
"exe",
"application/octet-stream"),
4284 MIME_ENTRY(
"zip",
"application/x-zip-compressed"),
4289 MIME_ENTRY(
"arj",
"application/x-arj-compressed"),
4290 MIME_ENTRY(
"rar",
"application/x-rar-compressed"),
4293 MIME_ENTRY(
"swf",
"application/x-shockwave-flash"),
4305#ifndef MG_DISABLE_FILESYSTEM
4307#ifndef MG_DISABLE_DAV
4310 return mkdir(path, mode);
4313 return _mkdir(path);
4320 const char *ext, *overrides;
4324 path_len = strlen(path);
4326 overrides = opts->custom_mime_types;
4328 ext = path + (path_len -
k.len);
4339 r.
len = strlen(r.
p);
4345 r.
len = strlen(r.
p);
4357 const unsigned char *buf = (
unsigned char *) s;
4360 for (
i = 0;
i < buf_len;
i++) {
4361 if (!isprint(buf[
i]) && buf[
i] !=
'\r' && buf[
i] !=
'\n' && buf[
i] < 128) {
4363 }
else if (buf[
i] ==
'\n' &&
i + 1 < buf_len && buf[
i + 1] ==
'\n') {
4365 }
else if (buf[
i] ==
'\n' &&
i + 2 < buf_len && buf[
i + 1] ==
'\r' &&
4366 buf[
i + 2] ==
'\n') {
4383 while (v->len > 0 && v->p[v->len - 1] ==
' ') {
4387 if (
k->len == 0 || v->len == 0) {
4389 k->len = v->len = 0;
4403 const char *
end, *qs;
4406 if (
len <= 0)
return len;
4408 memset(hm, 0,
sizeof(*hm));
4415 while (s <
end && isspace(*(
unsigned char *) s)) s++;
4425 if ((qs = (
char *) memchr(hm->
uri.
p,
'?', hm->
uri.
len)) != NULL) {
4432 if (
end - s < 4 || s[3] !=
' ')
return -1;
4456 if (hm->
body.
len == (
size_t) ~0 && is_req &&
4478#ifndef MG_DISABLE_HTTP_WEBSOCKET
4481 return (flags & 0x80) == 0 || (flags & 0x0f) == 0;
4485 return (flags & 0x80) == 0 && (flags & 0x0f) != 0;
4490 if (wsm->
flags & 0x8) {
4500 mask_len = 0, header_len = 0;
4501 unsigned char *
p = (
unsigned char *) nc->
recv_mbuf.
buf, *buf =
p,
4503 unsigned *sizep = (
unsigned *) &
p[1];
4509 buf_len >= 1 +
sizeof(*sizep) && buf_len >= 1 +
sizeof(*sizep) + *sizep) {
4510 buf += 1 +
sizeof(*sizep) + *sizep;
4511 buf_len -= 1 +
sizeof(*sizep) + *sizep;
4516 mask_len = buf[1] & 128 ? 4 : 0;
4517 if (len < 126 && buf_len >= mask_len) {
4519 header_len = 2 + mask_len;
4520 }
else if (
len == 126 && buf_len >= 4 + mask_len) {
4521 header_len = 4 + mask_len;
4522 data_len = ntohs(*(uint16_t *) &buf[2]);
4523 }
else if (buf_len >= 10 + mask_len) {
4524 header_len = 10 + mask_len;
4525 data_len = (((uint64_t) ntohl(*(uint32_t *) &buf[2])) << 32) +
4526 ntohl(*(uint32_t *) &buf[6]);
4530 frame_len = header_len + data_len;
4531 ok = frame_len > 0 && frame_len <= buf_len;
4536 wsm.
size = (size_t) data_len;
4537 wsm.
data = buf + header_len;
4542 for (
i = 0;
i < data_len;
i++) {
4543 buf[
i + header_len] ^= (buf + header_len - mask_len)[
i % 4];
4552 buf = p + 1 +
sizeof(*sizep);
4558 (*sizep) += wsm.
size;
4562 if (wsm.
flags & 0x80) {
4563 wsm.
data = p + 1 +
sizeof(*sizep);
4604#ifdef MG_DISABLE_WS_RANDOM_MASK
4607 if (
sizeof(
long) >= 4) {
4609 }
else if (
sizeof(
long) == 2) {
4619 unsigned char header[10];
4625 }
else if (len < 65535) {
4626 uint16_t tmp = htons((uint16_t) len);
4628 memcpy(&header[2], &tmp,
sizeof(tmp));
4633 tmp = htonl((uint32_t)((uint64_t) len >> 32));
4634 memcpy(&header[2], &tmp,
sizeof(tmp));
4635 tmp = htonl((uint32_t)(len & 0xffffffff));
4636 memcpy(&header[6], &tmp,
sizeof(tmp));
4642 header[1] |= 1 << 7;
4643 mg_send(nc, header, header_len);
4648 mg_send(nc, header, header_len);
4655 if (ctx->
pos == 0)
return;
4664 DBG((
"%p %d %d", nc, op, (
int) len));
4676 const struct mg_str *strv,
int strvcnt) {
4680 for (
i = 0;
i < strvcnt;
i++) {
4686 for (
i = 0;
i < strvcnt;
i++) {
4698 const char *fmt, ...) {
4704 if ((len =
mg_avprintf(&buf,
sizeof(mem), fmt, ap)) > 0) {
4709 if (buf != mem && buf != NULL) {
4726 time_t now = *(time_t *) ev_data;
4740 static const char *magic =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
4744 snprintf(buf,
sizeof(buf),
"%.*s%s", (
int)
key->len,
key->p, magic);
4752 "HTTP/1.1 101 Switching Protocols\r\n"
4753 "Upgrade: websocket\r\n"
4754 "Connection: Upgrade\r\n"
4755 "Sec-WebSocket-Accept: ",
4756 b64_sha,
"\r\n\r\n");
4757 DBG((
"%p %.*s %s", nc, (
int)
key->len,
key->p, b64_sha));
4762#ifndef MG_DISABLE_FILESYSTEM
4767 size_t n = 0, to_read = 0;
4771 if (io->
len <
sizeof(
buf)) {
4772 to_read =
sizeof(
buf) - io->
len;
4775 if (
left > 0 && to_read > (
size_t)
left) {
4782 (
n = fread(
buf, 1, to_read, pd->
file.
fp)) > 0) {
4787#ifdef MG_DISABLE_HTTP_KEEP_ALIVE
4795 size_t n = fwrite(io->
buf, 1, to_write, pd->
file.
fp);
4802#ifdef MG_DISABLE_HTTP_KEEP_ALIVE
4807#ifndef MG_DISABLE_CGI
4826 size_t *chunk_len) {
4827 unsigned char *s = (
unsigned char *)
buf;
4832 while (
i <
len && isxdigit(s[
i])) {
4834 n += (s[
i] >=
'0' && s[
i] <=
'9') ? s[
i] -
'0' : tolower(s[
i]) -
'a' + 10;
4839 if (
i == 0 ||
i + 2 >
len || s[
i] !=
'\r' || s[
i + 1] !=
'\n') {
4845 *chunk_data = (
char *) s +
i;
4852 if (
i == 0 ||
i + 2 >
len || s[
i] !=
'\r' || s[
i + 1] !=
'\n') {
4863 size_t i,
n, data_len, body_len, zero_chunk_received = 0;
4867 assert(blen >= body_len);
4874 memmove(buf + body_len,
data, data_len);
4875 body_len += data_len;
4878 if (data_len == 0) {
4879 zero_chunk_received = 1;
4888 memmove(buf + body_len, buf +
i, blen -
i);
4889 memset(buf + body_len + blen -
i, 0,
i - body_len);
4894 nc->
flags &= ~MG_F_DELETE_CHUNK;
4899 memset(buf, 0, body_len);
4900 memmove(buf, buf + body_len, blen -
i);
4905 if (zero_chunk_received) {
4917 int matched, matched_max = 0;
4927 while (ep != NULL) {
4930 if (matched > matched_max) {
4933 matched_max = matched;
4957#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
4958static void mg_http_multipart_continue(
struct mg_connection *nc);
4960static void mg_http_multipart_begin(
struct mg_connection *nc,
4971static void mg_http_handler2(
struct mg_connection *nc,
int ev,
void *ev_data,
4976 mg_http_handler2(nc, ev, ev_data, &hm);
4979static void mg_http_handler2(
struct mg_connection *nc,
int ev,
void *ev_data,
4989 const int is_req = (nc->
listener != NULL);
4990#ifndef MG_DISABLE_HTTP_WEBSOCKET
4994#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
4995 if (pd->mp_stream.boundary != NULL) {
5001 memset(&mp, 0,
sizeof(mp));
5004 mp.
var_name = pd->mp_stream.var_name;
5007 MG_EV_HTTP_PART_END, &mp);
5022#ifndef MG_DISABLE_FILESYSTEM
5024 printf(
"nc %p, pd %p, file fp %p cl %d\n", nc, pd, pd->
file.
fp, (
int)pd->
file.
cl);
5026 assert(pd->
file.
fp == NULL);
5027 if (pd->
file.
fp != NULL) {
5037#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
5038 if (pd->mp_stream.boundary != NULL) {
5039 mg_http_multipart_continue(nc);
5052#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
5054 s->
len >= 9 && strncmp(s->
p,
"multipart", 9) == 0) {
5055 mg_http_multipart_begin(nc, hm, req_len);
5056 mg_http_multipart_continue(nc);
5064 DBG((
"invalid request"));
5066 }
else if (req_len == 0) {
5069#ifndef MG_DISABLE_HTTP_WEBSOCKET
5101#ifdef MG_ENABLE_JAVASCRIPT
5102 v7_val_t v1, v2, headers, req, args, res;
5103 struct v7 *v7 = nc->
mgr->v7;
5105 int i, js_callback_handled_request = 0;
5109 v1 = v7_get(v7, v7_get_global(v7),
"Http", ~0);
5110 v2 = v7_get(v7, v1, ev_name, ~0);
5113 args = v7_mk_array(v7);
5114 req = v7_mk_object(v7);
5115 headers = v7_mk_object(v7);
5118 v7_set(v7, req,
"method", ~0,
5120 v7_set(v7, req,
"uri", ~0, v7_mk_string(v7, hm->
uri.
p, hm->
uri.
len, 1));
5121 v7_set(v7, req,
"body", ~0,
5123 v7_set(v7, req,
"headers", ~0, headers);
5127 v7_set(v7, headers,
name->p,
name->len,
5132 v7_array_push(v7, args, v7_mk_foreign(nc));
5133 v7_array_push(v7, args, req);
5134 if (v7_apply(v7, v2, v7_mk_undefined(), args, &res) == V7_OK &&
5135 v7_is_truthy(v7, res)) {
5136 js_callback_handled_request++;
5141 if (js_callback_handled_request) {
5157 while (
len < buf_len && buf[
len] !=
'\n')
len++;
5158 return len == buf_len ? 0 :
len + 1;
5161#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
5162static void mg_http_multipart_begin(
struct mg_connection *nc,
5183 if (ct->
len < 9 || strncmp(ct->
p,
"multipart", 9) != 0) {
5189 if (boundary_len == 0) {
5195 DBG((
"invalid request"));
5201 if (pd->mp_stream.boundary != NULL) {
5208 pd->mp_stream.boundary = strdup(boundary);
5209 pd->mp_stream.boundary_len = strlen(boundary);
5210 pd->mp_stream.var_name = pd->mp_stream.file_name = NULL;
5225#define CONTENT_DISPOSITION "Content-Disposition: "
5227static void mg_http_multipart_call_handler(
struct mg_connection *
c,
int ev,
5228 const char *
data,
size_t data_len) {
5231 memset(&mp, 0,
sizeof(mp));
5233 mp.
var_name = pd->mp_stream.var_name;
5237 mp.data.len = data_len;
5244 struct mbuf *io = &
c->recv_mbuf;
5246 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_DATA, io->
buf,
5247 pd->mp_stream.prev_io_len);
5249 pd->mp_stream.prev_io_len = 0;
5258 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_END, NULL, 0);
5259 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
5265static int mg_http_multipart_wait_for_boundary(
struct mg_connection *
c) {
5266 const char *boundary;
5267 struct mbuf *io = &
c->recv_mbuf;
5270 if ((
int) io->
len < pd->mp_stream.boundary_len + 2) {
5275 if (boundary != NULL) {
5276 if (io->
len - (boundary - io->
buf) < 4) {
5279 if (memcmp(boundary + pd->mp_stream.boundary_len,
"--", 2) == 0) {
5291static int mg_http_multipart_process_boundary(
struct mg_connection *
c) {
5293 const char *boundary, *block_begin;
5294 struct mbuf *io = &
c->recv_mbuf;
5299 block_begin = boundary + pd->mp_stream.boundary_len + 2;
5300 data_size = io->
len - (block_begin - io->
buf);
5302 while (data_size > 0 &&
5304 if (line_len > (
int)
sizeof(CONTENT_DISPOSITION) &&
5306 sizeof(CONTENT_DISPOSITION) - 1) == 0) {
5309 header.
p = block_begin +
sizeof(CONTENT_DISPOSITION) - 1;
5310 header.len = line_len -
sizeof(CONTENT_DISPOSITION) - 1;
5314 block_begin += line_len;
5315 data_size -= line_len;
5319 if (line_len == 2 &&
mg_ncasecmp(block_begin,
"\r\n", 2) == 0) {
5322 if (pd->mp_stream.processing_part != 0) {
5323 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_END, NULL, 0);
5326 free((
void *) pd->mp_stream.file_name);
5327 pd->mp_stream.file_name = strdup(
file_name);
5328 free((
void *) pd->mp_stream.var_name);
5329 pd->mp_stream.var_name = strdup(
var_name);
5331 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_BEGIN, NULL, 0);
5333 pd->mp_stream.processing_part++;
5337 block_begin += line_len;
5345static int mg_http_multipart_continue_wait_for_chunk(
struct mg_connection *
c) {
5347 struct mbuf *io = &
c->recv_mbuf;
5349 const char *boundary;
5350 if ((
int) io->
len < pd->mp_stream.boundary_len + 6 ) {
5355 if (boundary == NULL && pd->mp_stream.prev_io_len == 0) {
5356 pd->mp_stream.prev_io_len = io->
len;
5358 }
else if (boundary == NULL &&
5360 pd->mp_stream.prev_io_len + pd->mp_stream.boundary_len + 4) {
5363 }
else if (boundary != NULL) {
5364 int data_size = (boundary - io->
buf - 4);
5365 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_DATA, io->
buf, data_size);
5367 pd->mp_stream.prev_io_len = 0;
5378 switch (pd->mp_stream.state) {
5384 if (mg_http_multipart_wait_for_boundary(
c) == 0) {
5390 if (mg_http_multipart_process_boundary(
c) == 0) {
5396 if (mg_http_multipart_continue_wait_for_chunk(
c) == 0) {
5402 if (mg_http_multipart_got_chunk(
c) == 0) {
5408 if (mg_http_multipart_finalize(
c) == 0) {
5421struct file_upload_state {
5427void mg_file_upload_handler(
struct mg_connection *nc,
int ev,
void *ev_data,
5428 mg_fu_fname_fn local_name_fn) {
5430 case MG_EV_HTTP_PART_BEGIN: {
5433 struct file_upload_state *fus =
5434 (
struct file_upload_state *) calloc(1,
sizeof(*fus));
5438 if (lfn.
p == NULL || lfn.
len == 0) {
5441 "HTTP/1.1 403 Not Allowed\r\n"
5442 "Content-Type: text/plain\r\n"
5443 "Connection: close\r\n\r\n"
5444 "Not allowed to upload %s\r\n",
5449 fus->lfn = (
char *) malloc(lfn.
len + 1);
5450 memcpy(fus->lfn, lfn.
p, lfn.
len);
5451 fus->lfn[lfn.
len] =
'\0';
5454 (
"%p Receiving file %s -> %s", nc, mp->
file_name, fus->lfn));
5455 fus->fp = fopen(fus->lfn,
"w");
5456 if (fus->fp == NULL) {
5458 "HTTP/1.1 500 Internal Server Error\r\n"
5459 "Content-Type: text/plain\r\n"
5460 "Connection: close\r\n\r\n");
5461 LOG(
LL_ERROR, (
"Failed to open %s: %d\n", fus->lfn, errno));
5462 mg_printf(nc,
"Failed to open %s: %d\n", fus->lfn, errno);
5470 case MG_EV_HTTP_PART_DATA: {
5473 struct file_upload_state *fus =
5474 (
struct file_upload_state *) mp->
user_data;
5475 if (fus == NULL || fus->fp == NULL)
break;
5477 LOG(
LL_ERROR, (
"Failed to write to %s: %d, wrote %d", fus->lfn, errno,
5478 (
int) fus->num_recd));
5480#ifdef SPIFFS_ERR_FULL
5481 || errno == SPIFFS_ERR_FULL
5485 "HTTP/1.1 413 Payload Too Large\r\n"
5486 "Content-Type: text/plain\r\n"
5487 "Connection: close\r\n\r\n");
5488 mg_printf(nc,
"Failed to write to %s: no space left; wrote %d\r\n",
5489 fus->lfn, (
int) fus->num_recd);
5492 "HTTP/1.1 500 Internal Server Error\r\n"
5493 "Content-Type: text/plain\r\n"
5494 "Connection: close\r\n\r\n");
5496 errno, (
int) fus->num_recd);
5506 fus->num_recd += mp->
data.
len;
5508 (
int) fus->num_recd));
5511 case MG_EV_HTTP_PART_END: {
5514 struct file_upload_state *fus =
5515 (
struct file_upload_state *) mp->
user_data;
5516 if (fus == NULL)
break;
5517 if (mp->
status >= 0 && fus->fp != NULL) {
5519 fus->lfn, (
int) fus->num_recd));
5521 "HTTP/1.1 200 OK\r\n"
5522 "Content-Type: text/plain\r\n"
5523 "Connection: close\r\n\r\n"
5524 "Ok, %s - %d bytes.\r\n",
5533 if (fus->fp != NULL) fclose(fus->fp);
5549#ifndef MG_DISABLE_HTTP_WEBSOCKET
5552 const char *host,
const char *protocol,
5553 const char *extra_headers) {
5555 unsigned long random = (
unsigned long) path;
5560 "GET %s HTTP/1.1\r\n"
5561 "Upgrade: websocket\r\n"
5562 "Connection: Upgrade\r\n"
5563 "Sec-WebSocket-Version: 13\r\n"
5564 "Sec-WebSocket-Key: %s\r\n",
5571 if (protocol != NULL) {
5572 mg_printf(nc,
"Sec-WebSocket-Protocol: %s\r\n", protocol);
5574 if (extra_headers != NULL) {
5581 const char *extra_headers) {
5589 const char *extra_headers) {
5590 const char *status_message =
"OK";
5591 switch (status_code) {
5593 status_message =
"Partial Content";
5596 status_message =
"Moved";
5599 status_message =
"Found";
5602 status_message =
"Unauthorized";
5605 status_message =
"Forbidden";
5608 status_message =
"Not Found";
5611 status_message =
"Requested range not satisfiable";
5614 status_message =
"I'm a teapot";
5617 status_message =
"Internal Server Error";
5620 mg_printf(nc,
"HTTP/1.1 %d %s\r\n", status_code, status_message);
5621 if (extra_headers != NULL) {
5627 int64_t content_length,
const char *extra_headers) {
5629 if (content_length < 0) {
5630 mg_printf(
c,
"%s",
"Transfer-Encoding: chunked\r\n");
5637#ifdef MG_DISABLE_FILESYSTEM
5644 const char *reason) {
5645 if (!reason) reason =
"";
5646 DBG((
"%p %d %s", nc, code, reason));
5648 "Content-Type: text/plain\r\nConnection: close");
5649 mg_send(nc, reason, strlen(reason));
5652#ifndef MG_DISABLE_SSI
5659 while ((
n = fread(buf, 1,
sizeof(buf),
fp)) > 0) {
5665static void mg_do_ssi_include(
struct mg_connection *nc,
const char *ssi,
5666 char *tag,
int include_level,
5675 if (sscanf(tag,
" virtual=\"%[^\"]\"",
file_name) == 1) {
5678 }
else if (sscanf(tag,
" abspath=\"%[^\"]\"",
file_name) == 1) {
5683 snprintf(path,
sizeof(path),
"%s",
file_name);
5684 }
else if (sscanf(tag,
" file=\"%[^\"]\"",
file_name) == 1 ||
5685 sscanf(tag,
" \"%[^\"]\"",
file_name) == 1) {
5687 snprintf(path,
sizeof(path),
"%s", ssi);
5688 if ((p = strrchr(path, DIRSEP)) != NULL) {
5691 snprintf(path + strlen(path),
sizeof(path) - strlen(path),
"%s",
file_name);
5693 mg_printf(nc,
"Bad SSI #include: [%s]", tag);
5697 if ((
fp = fopen(path,
"rb")) == NULL) {
5698 mg_printf(nc,
"SSI include error: fopen(%s): %s", path, strerror(errno));
5712#ifndef MG_DISABLE_POPEN
5717 if (sscanf(tag,
" \"%[^\"]\"", cmd) != 1) {
5718 mg_printf(nc,
"Bad SSI #exec: [%s]", tag);
5719 }
else if ((
fp = popen(cmd,
"r")) == NULL) {
5720 mg_printf(nc,
"Cannot SSI #exec: [%s]: %s", cmd, strerror(errno));
5737 FILE *
fp,
int include_level,
5744#ifndef MG_DISABLE_POPEN
5747 char buf[BUFSIZ], *
p = buf + btag.
len;
5748 int ch,
len, in_ssi_tag;
5750 if (include_level > 10) {
5751 mg_printf(nc,
"SSI #include level is too deep (%s)", path);
5755 in_ssi_tag =
len = 0;
5756 while ((ch = fgetc(
fp)) != EOF) {
5757 if (in_ssi_tag && ch ==
'>' && buf[
len - 1] ==
'-' && buf[
len - 2] ==
'-') {
5763 while (
i > 0 && buf[
i] ==
' ') {
5768 if (memcmp(
p, d_include.
p, d_include.
len) == 0) {
5769 mg_do_ssi_include(nc, path,
p + d_include.
len + 1, include_level, opts);
5770 }
else if (memcmp(
p, d_call.
p, d_call.
len) == 0) {
5772#ifndef MG_DISABLE_POPEN
5773 }
else if (memcmp(
p, d_exec.
p, d_exec.
len) == 0) {
5780 }
else if (ch ==
'<') {
5786 buf[
len++] = ch & 0xff;
5787 }
else if (in_ssi_tag) {
5788 if (
len == (
int) btag.
len && memcmp(buf, btag.
p, btag.
len) != 0) {
5791 }
else if (
len == (
int)
sizeof(buf) - 2) {
5792 mg_printf(nc,
"%s: SSI tag is too large", path);
5795 buf[
len++] = ch & 0xff;
5797 buf[
len++] = ch & 0xff;
5798 if (
len == (
int)
sizeof(buf)) {
5817 if ((
fp = fopen(path,
"rb")) == NULL) {
5825 "Content-Type: %.*s\r\n"
5826 "Connection: close\r\n\r\n",
5843 const cs_stat_t *st) {
5844 snprintf(buf, buf_len,
"\"%lx.%" INT64_FMT "\"", (
unsigned long) st->st_mtime,
5845 (int64_t) st->st_size);
5848 strftime(buf, buf_len,
"%a, %d %b %Y %H:%M:%S GMT",
gmtime(t));
5859 if (
p == NULL)
return 0;
5860 memcpy(
p, header->
p, header->
len);
5861 p[header->
len] =
'\0';
5873 DBG((
"%p [%s]", nc, path));
5875 if ((pd->
file.
fp = fopen(path,
"rb")) == NULL) {
5892 char etag[50], current_time[50], last_modified[50], range[70];
5893 time_t t = time(NULL);
5894 int64_t r1 = 0, r2 = 0, cl = st->st_size;
5896 int n, status_code = 200;
5900 if (range_hdr != NULL &&
5907 if (r1 > r2 || r2 >= cl) {
5910 snprintf(range,
sizeof(range),
5911 "Content-Range: bytes */%" INT64_FMT "\r\n",
5912 (int64_t) st->st_size);
5916 snprintf(range,
sizeof(range),
"Content-Range: bytes %" INT64_FMT
5918 r1, r1 + cl - 1, (int64_t) st->st_size);
5919#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
5920 _XOPEN_SOURCE >= 600
5921 fseeko(pd->
file.
fp, r1, SEEK_SET);
5923 fseek(pd->
file.
fp, r1, SEEK_SET);
5942 "Last-Modified: %s\r\n"
5943 "Accept-Ranges: bytes\r\n"
5944 "Content-Type: %.*s\r\n"
5946 "Connection: close\r\n"
5948 "Content-Length: %" SIZE_T_FMT
5950 "%sEtag: %s\r\n\r\n",
5952 (
size_t) cl, range, etag);
5963 int is_form_url_encoded) {
5965#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
5967 for (
i =
j = 0;
i < src_len &&
j < dst_len - 1;
i++,
j++) {
5968 if (src[
i] ==
'%') {
5969 if (
i < src_len - 2 && isxdigit(*(
const unsigned char *) (src +
i + 1)) &&
5970 isxdigit(*(
const unsigned char *) (src +
i + 2))) {
5971 a = tolower(*(
const unsigned char *) (src +
i + 1));
5972 b = tolower(*(
const unsigned char *) (src +
i + 2));
5978 }
else if (is_form_url_encoded && src[
i] ==
'+') {
5987 return i >= src_len ?
j : -1;
5992 const char *
p, *
e, *s;
5996 if (dst == NULL || dst_len == 0) {
5998 }
else if (buf->
p == NULL ||
name == NULL || buf->
len == 0) {
6002 name_len = strlen(
name);
6003 e = buf->
p + buf->
len;
6007 for (
p = buf->
p;
p + name_len <
e;
p++) {
6008 if ((
p == buf->
p ||
p[-1] ==
'&') &&
p[name_len] ==
'=' &&
6011 s = (
const char *) memchr(
p,
'&', (
size_t)(
e -
p));
6028 char chunk_size[50];
6031 n = snprintf(chunk_size,
sizeof(chunk_size),
"%lX\r\n", (
unsigned long)
len);
6051 if (buf != mem && buf != NULL) {
6067 for (
i =
j = 0;
i <
len;
i++) {
6068 if (buf[
i] ==
'<' || buf[
i] ==
'>') {
6070 mg_send(nc, buf[
i] ==
'<' ?
"<" :
">", 4);
6078 if (buf != mem && buf != NULL) {
6086 int ch =
' ', ch1 =
',',
len = 0,
n = strlen(
var_name);
6087 const char *
p, *
end = hdr ? hdr->
p + hdr->
len : NULL, *s = NULL;
6089 if (buf != NULL && buf_size > 0) buf[0] =
'\0';
6090 if (hdr == NULL)
return 0;
6093 for (s = hdr->
p; s != NULL && s +
n <
end; s++) {
6094 if ((s == hdr->
p || s[-1] == ch || s[-1] == ch1) && s[
n] ==
'=' &&
6099 if (s != NULL && &s[
n + 1] <
end) {
6101 if (*s ==
'"' || *s ==
'\'') {
6105 while (
p <
end &&
p[0] != ch &&
p[0] != ch1 &&
len < (
int) buf_size) {
6106 if (ch !=
' ' &&
p[0] ==
'\\' &&
p[1] == ch)
p++;
6109 if (
len >= (
int) buf_size || (ch !=
' ' && *
p != ch)) {
6112 if (
len > 0 && s[
len - 1] ==
',')
len--;
6113 if (
len > 0 && s[
len - 1] ==
';')
len--;
6121#ifndef MG_DISABLE_FILESYSTEM
6124 int exclude_specials) {
6129 const char *pdir = strrchr(path, DIRSEP);
6134 return (exclude_specials && (!strcmp(path,
".") || !strcmp(path,
".."))) ||
6140#ifndef MG_DISABLE_HTTP_DIGEST_AUTH
6141static void mg_mkmd5resp(
const char *method,
size_t method_len,
const char *uri,
6142 size_t uri_len,
const char *ha1,
size_t ha1_len,
6143 const char *nonce,
size_t nonce_len,
const char *nc,
6144 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
6145 const char *qop,
size_t qop_len,
char *resp) {
6146 static const char colon[] =
":";
6147 static const size_t one = 1;
6150 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
6151 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
6152 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
6153 colon, one, ha2,
sizeof(ha2) - 1, NULL);
6157 const char *method,
const char *uri,
6158 const char *auth_domain,
const char *user,
6159 const char *passwd) {
6160 static const char colon[] =
":", qop[] =
"auth";
6161 static const size_t one = 1;
6162 char ha1[33], resp[33], cnonce[40];
6164 snprintf(cnonce,
sizeof(cnonce),
"%x", (
unsigned int) time(NULL));
6165 cs_md5(ha1, user, (
size_t) strlen(user), colon, one, auth_domain,
6166 (
size_t) strlen(auth_domain), colon, one, passwd,
6167 (
size_t) strlen(passwd), NULL);
6168 mg_mkmd5resp(method, strlen(method), uri, strlen(uri), ha1,
sizeof(ha1) - 1,
6169 cnonce, strlen(cnonce),
"1", one, cnonce, strlen(cnonce), qop,
6170 sizeof(qop) - 1, resp);
6171 return snprintf(buf, buf_len,
6172 "Authorization: Digest username=\"%s\","
6173 "realm=\"%s\",uri=\"%s\",qop=%s,nc=1,cnonce=%s,"
6174 "nonce=%s,response=%s\r\n",
6175 user, auth_domain, uri, qop, cnonce, cnonce, resp);
6185 unsigned long now = (
unsigned long) time(NULL);
6186 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
6187 return now < val || now - val < 3600;
6195 const char *auth_domain, FILE *
fp) {
6197 char buf[128], f_user[
sizeof(buf)], f_ha1[
sizeof(buf)], f_domain[
sizeof(buf)];
6198 char user[50], cnonce[33],
response[40], uri[200], qop[20], nc[20], nonce[30];
6199 char expected_response[33];
6202 if (hm == NULL ||
fp == NULL ||
6220 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
6221 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3 &&
6222 strcmp(user, f_user) == 0 &&
6224 strcmp(auth_domain, f_domain) == 0) {
6229 f_ha1, strlen(f_ha1), nonce, strlen(nonce), nc, strlen(nc), cnonce,
6230 strlen(cnonce), qop, strlen(qop), expected_response);
6240 int is_directory,
const char *domain,
6241 const char *passwords_file,
6242 int is_global_pass_file) {
6248 if (domain != NULL && passwords_file != NULL) {
6249 if (is_global_pass_file) {
6250 fp = fopen(passwords_file,
"r");
6251 }
else if (is_directory) {
6252 snprintf(buf,
sizeof(buf),
"%s%c%s", path, DIRSEP, passwords_file);
6253 fp = fopen(buf,
"r");
6255 p = strrchr(path, DIRSEP);
6256 if (
p == NULL)
p = path;
6257 snprintf(buf,
sizeof(buf),
"%.*s%c%s", (
int) (
p - path), path, DIRSEP,
6259 fp = fopen(buf,
"r");
6268 DBG((
"%s %s %d %d", path, passwords_file ? passwords_file :
"",
6269 is_global_pass_file, authorized));
6274 int is_directory,
const char *domain,
6275 const char *passwords_file,
6276 int is_global_pass_file) {
6279 (void) is_directory;
6281 (void) passwords_file;
6282 (void) is_global_pass_file;
6287#ifndef MG_DISABLE_DIRECTORY_LISTING
6290 static const char *dont_escape =
"._-$,;~()/";
6291 static const char *hex =
"0123456789abcdef";
6292 size_t i = 0,
j = 0;
6294 for (
i =
j = 0; dst_len > 0 &&
i < s_len &&
j + 2 < dst_len - 1;
i++,
j++) {
6295 if (isalnum(*(
const unsigned char *) (src +
i)) ||
6296 strchr(dont_escape, *(
const unsigned char *) (src +
i)) != NULL) {
6298 }
else if (
j + 3 < dst_len) {
6300 dst[
j + 1] = hex[(*(
const unsigned char *) (src +
i)) >> 4];
6301 dst[
j + 2] = hex[(*(
const unsigned char *) (src +
i)) & 0xf];
6310static void mg_escape(
const char *src,
char *dst,
size_t dst_len) {
6312 while (*src !=
'\0' &&
n + 5 < dst_len) {
6313 unsigned char ch = *(
unsigned char *) src++;
6315 n += snprintf(dst +
n, dst_len -
n,
"%s",
"<");
6326 int64_t fsize = stp->st_size;
6327 int is_dir = S_ISDIR(stp->st_mode);
6328 const char *slash = is_dir ?
"/" :
"";
6331 snprintf(size,
sizeof(size),
"%s",
"[DIRECTORY]");
6338 snprintf(size,
sizeof(size),
"%d", (
int) fsize);
6339 }
else if (fsize < 0x100000) {
6340 snprintf(size,
sizeof(size),
"%.1fk", (
double) fsize / 1024.0);
6341 }
else if (fsize < 0x40000000) {
6342 snprintf(size,
sizeof(size),
"%.1fM", (
double) fsize / 1048576);
6344 snprintf(size,
sizeof(size),
"%.1fG", (
double) fsize / 1073741824);
6347 strftime(mod,
sizeof(mod),
"%d-%b-%Y %H:%M",
localtime(&stp->st_mtime));
6351 "<tr><td><a href=\"%s%s\">%s%s</a></td>"
6352 "<td>%s</td><td name=%" INT64_FMT ">%s</td></tr>\n",
6353 href, slash, path, slash, mod, is_dir ? -1 : fsize,
6366 DBG((
"%p [%s]", nc, dir));
6367 if ((dirp = (opendir(dir))) != NULL) {
6368 while ((dp = readdir(dirp)) != NULL) {
6373 snprintf(path,
sizeof(path),
"%s/%s", dir, dp->d_name);
6374 if (
mg_stat(path, &st) == 0) {
6375 func(nc, (
const char *) dp->d_name, &st);
6380 DBG((
"%p opendir(%s) -> %d", nc, dir, errno));
6387 static const char *sort_js_code =
6388 "<script>function srt(tb, col) {"
6389 "var tr = Array.prototype.slice.call(tb.rows, 0),"
6390 "tr = tr.sort(function (a, b) { var c1 = a.cells[col], c2 = b.cells[col],"
6391 "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
6392 "t1 = a.cells[2].getAttribute('name'), "
6393 "t2 = b.cells[2].getAttribute('name'); "
6394 "return t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
6395 "n1 ? parseInt(n2) - parseInt(n1) : "
6396 "c1.textContent.trim().localeCompare(c2.textContent.trim()); });";
6397 static const char *sort_js_code2 =
6398 "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]);}"
6399 "window.onload = function() { "
6400 "var tb = document.getElementById('tb');"
6401 "document.onclick = function(ev){ "
6402 "var c = ev.target.rel; if (c) srt(tb, c)}; srt(tb, 2); };</script>";
6405 mg_printf(nc,
"%s: %s\r\n%s: %s\r\n\r\n",
"Transfer-Encoding",
"chunked",
6406 "Content-Type",
"text/html; charset=utf-8");
6410 "<html><head><title>Index of %.*s</title>%s%s"
6411 "<style>th,td {text-align: left; padding-right: 1em; }</style></head>"
6412 "<body><h1>Index of %.*s</h1><pre><table cellpadding=\"0\"><thead>"
6413 "<tr><th><a href=# rel=0>Name</a></th><th>"
6414 "<a href=# rel=1>Modified</a</th>"
6415 "<th><a href=# rel=2>Size</a></th></tr>"
6416 "<tr><td colspan=\"3\"><hr></td></tr></thead><tbody id=tb>",
6417 (
int) hm->
uri.
len, hm->
uri.
p, sort_js_code, sort_js_code2,
6427#ifndef MG_DISABLE_DAV
6431 time_t t = stp->st_mtime;
6436 "<d:href>%s</d:href>"
6439 "<d:resourcetype>%s</d:resourcetype>"
6441 "</d:getcontentlength>"
6442 "<d:getlastmodified>%s</d:getlastmodified>"
6444 "<d:status>HTTP/1.1 200 OK</d:status>"
6447 buf, S_ISDIR(stp->st_mode) ?
"<d:collection/>" :
"",
6448 (int64_t) stp->st_size, mtime);
6454 static const char header[] =
6455 "HTTP/1.1 207 Multi-Status\r\n"
6456 "Connection: close\r\n"
6457 "Content-Type: text/xml; charset=utf-8\r\n\r\n"
6458 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
6459 "<d:multistatus xmlns:d='DAV:'>\n";
6460 static const char footer[] =
"</d:multistatus>\n";
6464 if (S_ISDIR(stp->st_mode) &&
6466 mg_printf(nc,
"%s",
"HTTP/1.1 403 Directory Listing Denied\r\n\r\n");
6469 mg_send(nc, header,
sizeof(header) - 1);
6470 snprintf(uri,
sizeof(uri),
"%.*s", (
int) hm->
uri.
len, hm->
uri.
p);
6472 if (S_ISDIR(stp->st_mode) && (depth == NULL ||
mg_vcmp(depth,
"0") != 0)) {
6475 mg_send(nc, footer,
sizeof(footer) - 1);
6480#ifdef MG_ENABLE_FAKE_DAVLOCK
6492static void mg_handle_lock(
struct mg_connection *nc,
const char *path) {
6493 static const char *reply =
6494 "HTTP/1.1 207 Multi-Status\r\n"
6495 "Connection: close\r\n"
6496 "Content-Type: text/xml; charset=utf-8\r\n\r\n"
6497 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
6498 "<d:multistatus xmlns:d='DAV:'>\n"
6499 "<D:lockdiscovery>\n"
6503 "opaquelocktoken:%s%u"
6507 "</D:lockdiscovery>"
6508 "</d:multistatus>\n";
6509 mg_printf(nc, reply, path, (
unsigned int) time(NULL));
6516 int status_code = 500;
6519 }
else if (!
mg_mkdir(path, 0755)) {
6521 }
else if (errno == EEXIST) {
6523 }
else if (errno == EACCES) {
6525 }
else if (errno == ENOENT) {
6540 if ((dirp = opendir(dir)) == NULL)
return 0;
6542 while ((dp = readdir(dirp)) != NULL) {
6546 snprintf(path,
sizeof(path),
"%s%c%s", dir,
'/', dp->d_name);
6548 if (S_ISDIR(st.st_mode)) {
6567 const char *
p = (
char *) memchr(dest->
p,
'/', dest->
len);
6568 if (
p != NULL &&
p[1] ==
'/' &&
6569 (
p = (
char *) memchr(
p + 2,
'/', dest->
p + dest->
len -
p)) != NULL) {
6572 (
int) (dest->
p + dest->
len -
p),
p);
6573 if (rename(path, buf) == 0) {
6588 if (
mg_stat(path, &st) != 0) {
6590 }
else if (S_ISDIR(st.st_mode)) {
6593 }
else if (
remove(path) == 0) {
6605 for (s = path + 1; *s !=
'\0'; s++) {
6609 snprintf(buf,
sizeof(buf),
"%.*s", (
int) (s - path), path);
6610 buf[
sizeof(buf) - 1] =
'\0';
6625 int rc, status_code =
mg_stat(path, &st) == 0 ? 200 : 201;
6629 mg_printf(nc,
"HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code);
6630 }
else if (rc == -1) {
6632 }
else if (cl_hdr == NULL) {
6634 }
else if ((pd->
file.
fp = fopen(path,
"w+b")) == NULL) {
6638 int64_t r1 = 0, r2 = 0;
6641 pd->
file.
cl = to64(cl_hdr->
p);
6642 if (range_hdr != NULL &&
6645 fseeko(pd->
file.
fp, r1, SEEK_SET);
6646 pd->
file.
cl = r2 > r1 ? r2 - r1 + 1 : pd->
file.
cl - r1;
6648 mg_printf(nc,
"HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code);
6657 static const char *methods[] = {
"PUT",
"DELETE",
"MKCOL",
"PROPFIND",
"MOVE"
6658#ifdef MG_ENABLE_FAKE_DAVLOCK
6682 char **index_file, cs_stat_t *stp) {
6684 size_t path_len = strlen(path);
6692 size_t len = path_len + 1 +
vec.
len + 1;
6694 if (*index_file == NULL)
break;
6695 snprintf(*index_file,
len,
"%s%c%.*s", path, DIRSEP, (
int)
vec.
len,
vec.p);
6698 if (
mg_stat(*index_file, &st) == 0 && S_ISREG(st.st_mode)) {
6709 DBG((
"[%s] [%s]", path, (*index_file ? *index_file :
"")));
6717 char local_port[20] = {
'%'};
6723 if (
mg_vcmp(&a, local_port) == 0) {
6725 mg_printf(
c,
"Content-Length: 0\r\nLocation: %.*s%.*s\r\n\r\n",
6738 struct mg_str *remainder) {
6741 struct mg_str root = {NULL, 0};
6742 const char *file_uri_start = cp;
6744 remainder->
p = NULL;
6753 if (a.
len > 1 && a.
p[0] ==
'@') {
6755 if (hh != NULL && hh->
len == a.
len - 1 &&
6763 if (match_len > 0) {
6764 file_uri_start = hm->
uri.
p + match_len;
6765 if (*file_uri_start ==
'/' || file_uri_start == cp_end) {
6767 }
else if (*(file_uri_start - 1) ==
'/') {
6780 if (root.
p == NULL) {
6781#ifndef MG_DISABLE_DAV
6792 assert(root.
p != NULL && root.
len > 0);
6796 const char *u = file_uri_start + 1;
6798 char *lp_end = lp + root.
len + hm->
uri.
len + 1;
6805 memcpy(
p, root.
p, root.
len);
6807 if (*(
p - 1) == DIRSEP)
p--;
6812 while (u <= cp_end) {
6813 const char *next = u;
6817 exists = (
mg_stat(lp, &st) == 0);
6818 if (exists && S_ISREG(st.st_mode)) {
6821 if (*(u - 1) ==
'/') u--;
6825 if (u >= cp_end)
break;
6827 if (component.
len > 0) {
6829 memmove(
p + 1, component.
p, component.
len);
6835 component.
p =
p + 1;
6837 if (
mg_vcmp(&component,
".") == 0) {
6839 }
else if (
mg_vcmp(&component,
"..") == 0) {
6840 while (
p > ps && *
p != DIRSEP)
p--;
6848 DBG((
"[%.*s] smells funny", (
int) component.
len, component.
p));
6855 for (
i = 0;
i < component.
len;
i++,
p++) {
6856 if (*
p ==
'\0' || *
p == DIRSEP
6874 remainder->
len = cp_end - u;
6881 DBG((
"'%.*s' -> '%s' + '%.*s'", (
int) hm->
uri.
len, hm->
uri.
p,
6882 *local_path ? *local_path :
"", (int) remainder->
len, remainder->
p));
6886#ifndef MG_DISABLE_CGI
6888struct mg_threadparam {
6893static int mg_wait_until_ready(sock_t sock,
int for_read) {
6897 return select(sock + 1, for_read ? &
set : 0, for_read ? 0 : &
set, 0, 0) == 1;
6900static void *mg_push_to_stdin(
void *arg) {
6901 struct mg_threadparam *tp = (
struct mg_threadparam *) arg;
6902 int n, sent, stop = 0;
6906 while (!stop && mg_wait_until_ready(tp->s, 1) &&
6907 (
n = recv(tp->s, buf,
sizeof(buf), 0)) > 0) {
6908 if (
n == -1 && GetLastError() == WSAEWOULDBLOCK)
continue;
6909 for (sent = 0; !stop && sent <
n; sent +=
k) {
6910 if (!WriteFile(tp->hPipe, buf + sent,
n - sent, &
k, 0)) stop = 1;
6913 DBG((
"%s",
"FORWARED EVERYTHING TO CGI"));
6914 CloseHandle(tp->hPipe);
6920static void *mg_pull_from_stdout(
void *arg) {
6921 struct mg_threadparam *tp = (
struct mg_threadparam *) arg;
6922 int k = 0, stop = 0;
6926 while (!stop && ReadFile(tp->hPipe, buf,
sizeof(buf), &
n, NULL)) {
6927 for (sent = 0; !stop && sent <
n; sent +=
k) {
6928 if (mg_wait_until_ready(tp->s, 0) &&
6929 (
k = send(tp->s, buf + sent,
n - sent, 0)) <= 0)
6933 DBG((
"%s",
"EOF FROM CGI"));
6934 CloseHandle(tp->hPipe);
6942static void mg_spawn_stdio_thread(sock_t sock, HANDLE hPipe,
6943 void *(*func)(
void *)) {
6944 struct mg_threadparam *tp = (
struct mg_threadparam *)
MG_MALLOC(
sizeof(*tp));
6952static void mg_abs_path(
const char *utf8_path,
char *abs_path,
size_t len) {
6955 GetFullPathNameW(buf,
ARRAY_SIZE(buf2), buf2, NULL);
6956 WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0);
6960 const char *env,
const char *envp[],
6961 const char *dir, sock_t sock) {
6963 PROCESS_INFORMATION
pi;
6964 HANDLE a[2], b[2], me = GetCurrentProcess();
6968 DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;
6971 memset(&si, 0,
sizeof(si));
6972 memset(&
pi, 0,
sizeof(
pi));
6975 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
6976 si.wShowWindow = SW_HIDE;
6977 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
6979 CreatePipe(&a[0], &a[1], NULL, 0);
6980 CreatePipe(&b[0], &b[1], NULL, 0);
6981 DuplicateHandle(me, a[0], me, &si.hStdInput, 0,
TRUE, flags);
6982 DuplicateHandle(me, b[1], me, &si.hStdOutput, 0,
TRUE, flags);
6984 if (interp == NULL && (
fp = fopen(cmd,
"r")) != NULL) {
6985 buf[0] = buf[1] =
'\0';
6986 fgets(buf,
sizeof(buf),
fp);
6987 buf[
sizeof(buf) - 1] =
'\0';
6988 if (buf[0] ==
'#' && buf[1] ==
'!') {
6991 while (*interp !=
'\0' && isspace(*(
unsigned char *) interp)) {
6998 snprintf(buf,
sizeof(buf),
"%s/%s", dir, cmd);
7002 to_wchar(dir, full_dir,
ARRAY_SIZE(full_dir));
7004 if (interp != NULL) {
7006 snprintf(cmdline,
sizeof(cmdline),
"%s \"%s\"", buf4, buf2);
7008 snprintf(cmdline,
sizeof(cmdline),
"\"%s\"", buf2);
7012 if (CreateProcessW(NULL, wcmd, NULL, NULL,
TRUE, CREATE_NEW_PROCESS_GROUP,
7013 (
void *) env, full_dir, &si, &
pi) != 0) {
7014 mg_spawn_stdio_thread(sock, a[1], mg_push_to_stdin);
7015 mg_spawn_stdio_thread(sock, b[0], mg_pull_from_stdout);
7021 DBG((
"CGI command: [%ls] -> %p", wcmd,
pi.hProcess));
7024 CloseHandle(si.hStdOutput);
7025 CloseHandle(si.hStdInput);
7034 const char *env,
const char *envp[],
7035 const char *dir, sock_t sock) {
7045 int tmp = chdir(dir);
7047 (void) dup2(sock, 0);
7048 (void) dup2(sock, 1);
7057 signal(SIGCHLD, SIG_DFL);
7059 if (interp == NULL) {
7060 execle(cmd, cmd, (
char *) 0, envp);
7062 execle(interp, interp, cmd, (
char *) 0, envp);
7064 snprintf(buf,
sizeof(buf),
7065 "Status: 500\r\n\r\n"
7066 "500 Server Error: %s%s%s: %s",
7067 interp == NULL ?
"" : interp, interp == NULL ?
"" :
" ", cmd,
7069 send(1, buf, strlen(buf), 0);
7083 char *added = block->
buf + block->
len;
7087 space =
sizeof(block->
buf) - (block->
len + 2);
7091 n = vsnprintf(added, (
size_t) space, fmt, ap);
7095 if (
n > 0 &&
n + 1 < space &&
7100 block->
len +=
n + 1;
7114 const struct mg_str *path_info,
7126 if ((s = getenv(
"SERVER_NAME")) != NULL) {
7147 addenv(
blk,
"REMOTE_ADDR=%s", ri->remote_ip);
7148 addenv(
blk,
"REMOTE_PORT=%d", ri->remote_port);
7156 const char *base_name = strrchr(prog, DIRSEP);
7158 (base_name != NULL ? base_name + 1 : prog));
7164 if (path_info != NULL && path_info->
len > 0) {
7167 mg_addenv(
blk,
"PATH_TRANSLATED=%.*s", (
int) path_info->
len, path_info->
p);
7212 for (; *
p !=
'=' && *
p !=
'\0';
p++) {
7213 if (*
p ==
'-') *
p =
'_';
7214 *
p = (char) toupper(*(
unsigned char *)
p);
7218 blk->vars[
blk->nvars++] = NULL;
7219 blk->buf[
blk->len++] =
'\0';
7227 if (nc == NULL)
return;
7248 if (
len == 0)
break;
7257 mg_printf(nc,
"%s",
"HTTP/1.1 302 Moved\r\n");
7261 mg_printf(nc,
"%s",
"HTTP/1.1 200 OK\r\n");
7264 nc->
flags &= ~MG_F_USER_1;
7278 const struct mg_str *path_info,
7286 DBG((
"%p [%s]",
nc, prog));
7293 if ((p = strrchr(prog, DIRSEP)) == NULL) {
7294 snprintf(dir,
sizeof(dir),
"%s",
".");
7296 snprintf(dir,
sizeof(dir),
"%.*s", (
int) (p - prog), prog);
7319 if (
n > 0 && n < nc->recv_mbuf.len) {
7335 static const char *
month_names[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
7336 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
7346 return year / 4 - year / 100 + year / 400;
7351 static const unsigned short days_before_month[] = {
7352 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
7354 int second, minute, hour, day, month, year, leap_days, days;
7355 time_t result = (time_t) 0;
7357 if (((sscanf(datetime,
"%d/%3s/%d %d:%d:%d", &day, month_str, &year, &hour,
7358 &minute, &second) == 6) ||
7359 (sscanf(datetime,
"%d %3s %d %d:%d:%d", &day, month_str, &year, &hour,
7360 &minute, &second) == 6) ||
7361 (sscanf(datetime,
"%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year,
7362 &hour, &minute, &second) == 6) ||
7363 (sscanf(datetime,
"%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour,
7364 &minute, &second) == 6)) &&
7368 days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
7369 result = days * 24 * 3600 + hour * 3600 + minute * 60 + second;
7389 const char *domain) {
7391 "HTTP/1.1 401 Unauthorized\r\n"
7392 "WWW-Authenticate: Digest qop=\"auth\", "
7393 "realm=\"%s\", nonce=\"%lu\"\r\n"
7394 "Content-Length: 0\r\n\r\n",
7395 domain, (
unsigned long) time(NULL));
7400 "HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, CONNECT, OPTIONS"
7401#ifndef MG_DISABLE_DAV
7402 ", MKCOL, PUT, DELETE, PROPFIND, MOVE\r\nDAV: 1,2"
7413 const struct mg_str *path_info,
7418 char *index_file = NULL;
7421 exists = (
mg_stat(path, &st) == 0);
7422 is_directory = exists && S_ISDIR(st.st_mode);
7429 index_file ? index_file : path) > 0);
7431 DBG((
"%p %.*s [%s] exists=%d is_dir=%d is_dav=%d is_cgi=%d index=%s", nc,
7433 is_cgi, index_file ? index_file :
""));
7435 if (is_directory && hm->
uri.
p[hm->
uri.
len - 1] !=
'/' && !is_dav) {
7437 "HTTP/1.1 301 Moved\r\nLocation: %.*s/\r\n"
7438 "Content-Length: 0\r\n\r\n",
7445 if (path_info->
len > 0 && !is_cgi) {
7458 }
else if (is_cgi) {
7459#if !defined(MG_DISABLE_CGI)
7460 mg_handle_cgi(nc, index_file ? index_file : path, path_info, hm, opts);
7464 }
else if ((!exists ||
7468#ifndef MG_DISABLE_DAV
7471#ifndef MG_DISABLE_DAV_AUTH
7472 }
else if (is_dav &&
7487#ifdef MG_ENABLE_FAKE_DAVLOCK
7489 mg_handle_lock(nc, path);
7494 }
else if (is_directory && index_file == NULL) {
7495#ifndef MG_DISABLE_DIRECTORY_LISTING
7515 struct mg_str *hdr, path_info;
7516 uint32_t remote_ip = ntohl(*(uint32_t *) &nc->
sa.
sin.sin_addr);
7545 opts.
index_files =
"index.html,index.htm,index.shtml,index.cgi,index.php";
7564 mg_vcmp(hdr,
"keep-alive") != 0)) {
7575 const char *schema_tls,
int *use_ssl,
7576 char **
addr,
int *port_i,
7577 const char **path) {
7580 if (memcmp(url, schema, strlen(schema)) == 0) {
7581 url += strlen(schema);
7582 }
else if (memcmp(url, schema_tls, strlen(schema_tls)) == 0) {
7583 url += strlen(schema_tls);
7585#ifndef MG_ENABLE_SSL
7590 while (*url !=
'\0') {
7592 if (*
addr == NULL) {
7599 if (*url ==
':') *port_i = addr_len;
7600 (*addr)[addr_len++] = *url;
7601 (*addr)[addr_len] =
'\0';
7604 if (addr_len == 0)
goto cleanup;
7607 strcpy(*
addr + *port_i, *use_ssl ?
":443" :
":80");
7612 if (*path == NULL) *path = url;
7614 if (**path ==
'\0') *path =
"/";
7627 struct mg_connect_opts opts,
const char *schema,
const char *schema_ssl,
7628 const char *url,
const char **path,
char **
addr) {
7638#ifndef MG_ENABLE_SSL
7648 if (use_ssl && nc->
ssl_ctx == NULL) {
7660 if (port_i >= 0) (*addr)[port_i] =
'\0';
7670 const char *extra_headers,
7671 const char *post_data) {
7673 const char *path = NULL;
7675 mgr, ev_handler, opts,
"http://",
"https://", url, &path, &
addr);
7681 mg_printf(nc,
"%s %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %" SIZE_T_FMT
7683 post_data == NULL ?
"GET" :
"POST", path,
addr,
7684 post_data == NULL ? 0 : strlen(post_data),
7685 extra_headers == NULL ?
"" : extra_headers,
7686 post_data == NULL ?
"" : post_data);
7695 const char *extra_headers,
7696 const char *post_data) {
7698 memset(&opts, 0,
sizeof(opts));
7706 const char *url,
const char *protocol,
7707 const char *extra_headers) {
7709 const char *path = NULL;
7711 mgr, ev_handler, opts,
"ws://",
"wss://", url, &path, &
addr);
7725 const char *url,
const char *protocol,
7726 const char *extra_headers) {
7728 memset(&opts, 0,
sizeof(opts));
7734 size_t file_name_len,
const char **
data,
7736 static const char cd[] =
"Content-Disposition: ";
7737 size_t hl,
bl,
n, ll, pos, cdl =
sizeof(cd) - 1;
7739 if (buf == NULL || buf_len <= 0)
return 0;
7741 if (buf[0] !=
'-' || buf[1] !=
'-' || buf[2] ==
'\n')
return 0;
7751 header.
p = buf +
n + cdl;
7752 header.
len = ll - (cdl + 2);
7759 for (pos = hl; pos + (
bl - 2) < buf_len; pos++) {
7760 if (buf[pos] ==
'-' && !memcmp(buf, &buf[pos],
bl - 2)) {
7761 if (data_len != NULL) *data_len = (pos - 2) - hl;
7762 if (
data != NULL) *
data = buf + hl;
7775 new_ep->
name = strdup(uri_path);
7783#ifdef MG_MODULE_LINES
7784#line 1 "./src/util.c"
7795const char *
mg_skip(
const char *s,
const char *
end,
const char *delims,
7798 while (s <
end && strchr(delims, *(
unsigned char *) s) == NULL) s++;
7800 while (s <
end && strchr(delims, *(
unsigned char *) s) != NULL) s++;
7805 return tolower(*(
const unsigned char *) s);
7813 }
while (diff == 0 && s1[-1] !=
'\0' && --len > 0);
7823 size_t n2 = strlen(str2), n1 = str1->
len;
7824 int r =
mg_ncasecmp(str1->
p, str2, (n1 < n2) ? n1 : n2);
7832 size_t n2 = strlen(str2), n1 = str1->
len;
7833 int r = memcmp(str1->
p, str2, (n1 < n2) ? n1 : n2);
7840#ifndef MG_DISABLE_FILESYSTEM
7845 DBG((
"[%ls] -> %d", wpath, _wstati64(wpath, st)));
7846 return _wstati64(wpath, (
struct _stati64 *) st);
7848 return stat(path, st);
7857 return _wfopen(wpath, wmode);
7859 return fopen(path, mode);
7863int mg_open(
const char *path,
int flag,
int mode) {
7867 return _wopen(wpath, flag, mode);
7869 return open(path, flag, mode);
7882#ifdef MG_ENABLE_THREADS
7885 return (
void *) _beginthread((
void(__cdecl *) (
void *) ) f, 0, p);
7887 pthread_t thread_id = (pthread_t) 0;
7888 pthread_attr_t attr;
7890 (void) pthread_attr_init(&attr);
7891 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7893#if defined(MG_STACK_SIZE) && MG_STACK_SIZE > 1
7894 (void) pthread_attr_setstacksize(&attr, MG_STACK_SIZE);
7897 pthread_create(&thread_id, &attr, f, p);
7898 pthread_attr_destroy(&attr);
7900 return (
void *) thread_id;
7908 (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
7909#elif defined(__unix__)
7910 fcntl(sock, F_SETFD, FD_CLOEXEC);
7919 if (buf == NULL || len <= 0)
return;
7921#if defined(MG_ENABLE_IPV6)
7922 is_v6 = sa->
sa.sa_family == AF_INET6;
7927#if defined(MG_ENABLE_IPV6)
7928 const void *
addr = NULL;
7930 socklen_t capacity = len;
7934 addr = (
void *) &sa->
sin6.sin6_addr;
7944#elif defined(_WIN32) || defined(MG_LWIP)
7948 inet_ntop(AF_INET, (
void *) &sa->
sin.sin_addr, buf, len);
7952 int port = ntohs(sa->
sin.sin_port);
7954 snprintf(buf + strlen(buf), len - (strlen(buf) + 1),
"%s:%d",
7955 (is_v6 ?
"]" :
""), port);
7957 snprintf(buf, len,
"%d", port);
7965 memset(&
sa, 0,
sizeof(
sa));
7970#ifndef MG_DISABLE_HEXDUMP
7971int mg_hexdump(
const void *buf,
int len,
char *dst,
int dst_len) {
7972 const unsigned char *p = (
const unsigned char *) buf;
7973 char ascii[17] =
"";
7976 for (
i = 0;
i < len;
i++) {
7979 if (
i > 0)
n += snprintf(dst +
n, dst_len -
n,
" %s\n", ascii);
7980 n += snprintf(dst +
n, dst_len -
n,
"%04x ",
i);
7982 n += snprintf(dst +
n, dst_len -
n,
" %02x", p[
i]);
7983 ascii[idx] = p[
i] < 0x20 || p[
i] > 0x7e ?
'.' : p[
i];
7984 ascii[idx + 1] =
'\0';
7987 while (
i++ % 16)
n += snprintf(dst +
n, dst_len -
n,
"%s",
" ");
7988 n += snprintf(dst +
n, dst_len -
n,
" %s\n\n", ascii);
7994int mg_avprintf(
char **buf,
size_t size,
const char *fmt, va_list ap) {
7998 va_copy(ap_copy, ap);
7999 len = vsnprintf(*buf, size, fmt, ap_copy);
8010 if ((*buf = (
char *)
MG_MALLOC(size)) == NULL)
break;
8011 va_copy(ap_copy, ap);
8012 len = vsnprintf(*buf, size, fmt, ap_copy);
8016 }
else if (len >= (
int) size) {
8018 if ((*buf = (
char *)
MG_MALLOC(len + 1)) == NULL) {
8021 va_copy(ap_copy, ap);
8022 len = vsnprintf(*buf, len + 1, fmt, ap_copy);
8030#if !defined(MG_DISABLE_HEXDUMP)
8032 const void *buf,
int num_bytes,
int ev) {
8033#if !defined(NO_LIBC) && !defined(MG_DISABLE_STDIO)
8035 char *hexbuf, src[60], dst[60];
8036 int buf_size = num_bytes * 5 + 100;
8038 if (strcmp(path,
"-") == 0) {
8040 }
else if (strcmp(path,
"--") == 0) {
8042#ifndef MG_DISABLE_FILESYSTEM
8044 fp = fopen(path,
"a");
8047 if (
fp == NULL)
return;
8055 fp,
"%lu %p %s %s %s %d\n", (
unsigned long) time(NULL), (
void *) nc, src,
8062 if (num_bytes > 0 && (hexbuf = (
char *)
MG_MALLOC(buf_size)) != NULL) {
8063 mg_hexdump(buf, num_bytes, hexbuf, buf_size);
8064 fprintf(
fp,
"%s", hexbuf);
8067 if (
fp != stdin &&
fp != stdout) fclose(
fp);
8073 static const int n = 1;
8075 return ((
char *) &
n)[0] == 0;
8080 if (
list == NULL || *
list ==
'\0') {
8085 if ((
list = strchr(val->
p,
',')) != NULL) {
8091 list = val->
p + strlen(val->
p);
8095 if (eq_val != NULL) {
8099 eq_val->
p = (
const char *) memchr(val->
p,
'=', val->
len);
8100 if (eq_val->
p != NULL) {
8102 eq_val->
len = val->
p + val->
len - eq_val->
p;
8103 val->
len = (eq_val->
p - val->
p) - 1;
8113 size_t len,
i = 0,
j = 0;
8116 if ((or_str = (
const char *) memchr(pattern.
p,
'|', pattern.
len)) != NULL) {
8117 struct mg_str pstr = {pattern.
p, (size_t)(or_str - pattern.
p)};
8119 if (res > 0)
return res;
8120 pstr.
p = or_str + 1;
8121 pstr.
len = (pattern.
p + pattern.
len) - (or_str + 1);
8125 for (;
i < pattern.
len;
i++,
j++) {
8126 if (pattern.
p[
i] ==
'?' &&
j !=
str.len) {
8128 }
else if (pattern.
p[
i] ==
'$') {
8129 return j ==
str.len ? (int)
j : -1;
8130 }
else if (pattern.
p[
i] ==
'*') {
8132 if (pattern.
p[
i] ==
'*') {
8141 if (
i == pattern.
len) {
8145 const struct mg_str pstr = {pattern.
p +
i, pattern.
len -
i};
8148 }
while (res == -1 &&
len-- > 0);
8149 return res == -1 ? -1 : (int) (
j + res +
len);
8158 const struct mg_str pstr = {pattern, (size_t) pattern_len};
8163 struct mg_str ret = {s, 0};
8164 if (s != NULL) ret.
len = strlen(s);
8167#ifdef MG_MODULE_LINES
8168#line 1 "./src/json-rpc.c"
8173#ifndef MG_DISABLE_JSON_RPC
8180 const char *result_fmt, ...) {
8182 const struct json_token *
id = req->
id == NULL ? &null_tok : req->
id;
8194 va_start(ap, result_fmt);
8204 const char *
id,
const char *params_fmt, ...) {
8208 n +=
json_emit(buf +
n,
len -
n,
"{s:s,s:s,s:s,s:",
"jsonrpc",
"2.0",
"id",
8209 id,
"method", method,
"params");
8210 va_start(ap, params_fmt);
8220 int code,
const char *
message,
const char *fmt, ...) {
8224 n +=
json_emit(buf +
n,
len -
n,
"{s:s,s:V,s:{s:i,s:s,s:",
"jsonrpc",
"2.0",
8225 "id", req->
id == NULL ?
"null" : req->
id->
ptr,
8226 req->
id == NULL ? 4 : req->
id->
len,
"error",
"code",
8227 (long) code,
"message",
message,
"data");
8252 message =
"invalid parameters";
8258 message =
"unspecified error";
8271 memset(&req, 0,
sizeof(req));
8272 n =
parse_json(buf, len, tokens,
sizeof(tokens) /
sizeof(tokens[0]));
8284 if (req.
id == NULL || req.
method == NULL) {
8289 for (
i = 0; methods[
i] != NULL;
i++) {
8290 int mlen = strlen(methods[
i]);
8292 memcmp(methods[
i], req.
method->
ptr, mlen) == 0)
8296 if (methods[
i] == NULL) {
8301 return handlers[
i](dst, dst_len, &req);
8309 memset(rep, 0,
sizeof(*rep));
8310 memset(er, 0,
sizeof(*er));
8328#ifdef MG_MODULE_LINES
8329#line 1 "./src/mqtt.c"
8336#ifndef MG_DISABLE_MQTT
8346 char *vlen = &io->
buf[1];
8348 if (io->
len < 2)
return -1;
8350 header = io->
buf[0];
8355 len += (*vlen & 127) << 7 * (vlen - &io->
buf[1]);
8356 }
while ((*vlen++ & 128) != 0 && ((size_t)(vlen - io->
buf) <= io->
len));
8358 if (len != 0 && io->
len < (
size_t)(len - 1))
return -1;
8381 uint16_t topic_len = ntohs(*(uint16_t *) io->
buf);
8383 mm->
topic[topic_len] = 0;
8384 strncpy(mm->
topic, io->
buf + 2, topic_len);
8385 var_len = topic_len + 2;
8406 return len - var_len;
8413 memset(&mm, 0,
sizeof(mm));
8420 if (
len == -1)
break;
8448 uint16_t client_id_len;
8455 rem_len = 9 + 1 + 2 + 2 + strlen(client_id);
8459 mg_send(nc,
"\00\06MQIsdp\03", 9);
8468 client_id_len = htons(strlen(client_id));
8469 mg_send(nc, &client_id_len, 2);
8470 mg_send(nc, client_id, strlen(client_id));
8474 uint8_t
flags,
size_t len) {
8476 uint8_t header = cmd << 4 | (uint8_t)
flags;
8478 uint8_t buf[1 +
sizeof(size_t)];
8479 uint8_t *vlen = &buf[1];
8489 if (len > 0) *vlen |= 0x80;
8497 uint16_t message_id,
int flags,
const void *
data,
8501 uint16_t topic_len = htons(strlen(topic));
8502 uint16_t message_id_net = htons(message_id);
8505 mg_send(nc, topic, strlen(topic));
8507 mg_send(nc, &message_id_net, 2);
8517 size_t topics_len, uint16_t message_id) {
8520 uint16_t message_id_n = htons(message_id);
8523 mg_send(nc, (
char *) &message_id_n, 2);
8524 for (
i = 0;
i < topics_len;
i++) {
8525 uint16_t topic_len_n = htons(strlen(topics[
i].topic));
8527 mg_send(nc, topics[
i].topic, strlen(topics[
i].topic));
8536 struct mg_str *topic, uint8_t *qos,
int pos) {
8537 unsigned char *buf = (
unsigned char *) msg->
payload.
p + pos;
8542 topic->
len = buf[0] << 8 | buf[1];
8543 topic->
p = (
char *) buf + 2;
8544 *qos = buf[2 + topic->
len];
8545 return pos + 2 + topic->
len + 1;
8549 size_t topics_len, uint16_t message_id) {
8552 uint16_t message_id_n = htons(message_id);
8555 mg_send(nc, (
char *) &message_id_n, 2);
8556 for (
i = 0;
i < topics_len;
i++) {
8557 uint16_t topic_len_n = htons(strlen(topics[
i]));
8559 mg_send(nc, topics[
i], strlen(topics[
i]));
8579 uint16_t message_id) {
8580 uint16_t message_id_net = htons(message_id);
8581 mg_send(nc, &message_id_net, 2);
8602 uint16_t message_id) {
8604 uint16_t message_id_net = htons(message_id);
8605 mg_send(nc, &message_id_net, 2);
8606 for (
i = 0;
i < qoss_len;
i++) {
8629#ifdef MG_MODULE_LINES
8630#line 1 "./src/mqtt-broker.c"
8640#ifdef MG_ENABLE_MQTT_BROKER
8642static void mg_mqtt_session_init(
struct mg_mqtt_broker *brk,
8643 struct mg_mqtt_session *s,
8646 s->subscriptions = NULL;
8647 s->num_subscriptions = 0;
8651static void mg_mqtt_add_session(
struct mg_mqtt_session *s) {
8652 s->
next = s->brk->sessions;
8653 s->brk->sessions = s;
8655 if (s->next != NULL) s->
next->
prev = s;
8658static void mg_mqtt_remove_session(
struct mg_mqtt_session *s) {
8659 if (s->prev == NULL) s->brk->sessions = s->
next;
8664static void mg_mqtt_destroy_session(
struct mg_mqtt_session *s) {
8666 for (
i = 0;
i < s->num_subscriptions;
i++) {
8667 MG_FREE((
void *) s->subscriptions[
i].topic);
8673static void mg_mqtt_close_session(
struct mg_mqtt_session *s) {
8674 mg_mqtt_remove_session(s);
8675 mg_mqtt_destroy_session(s);
8678void mg_mqtt_broker_init(
struct mg_mqtt_broker *brk,
void *user_data) {
8679 brk->sessions = NULL;
8680 brk->user_data = user_data;
8683static void mg_mqtt_broker_handle_connect(
struct mg_mqtt_broker *brk,
8685 struct mg_mqtt_session *s = (
struct mg_mqtt_session *) malloc(
sizeof *s);
8695 mg_mqtt_session_init(brk, s, nc);
8698 mg_mqtt_add_session(s);
8703static void mg_mqtt_broker_handle_subscribe(
struct mg_connection *nc,
8705 struct mg_mqtt_session *ss = (
struct mg_mqtt_session *) nc->
user_data;
8707 size_t qoss_len = 0;
8715 qoss[qoss_len++] =
qos;
8719 ss->subscriptions,
sizeof(*ss->subscriptions) * qoss_len);
8722 ss->num_subscriptions++) {
8723 te = &ss->subscriptions[ss->num_subscriptions];
8741 int len = strlen(exp);
8742 if (strchr(exp,
'#')) {
8745 return strncmp(exp,
topic, len) == 0;
8748static void mg_mqtt_broker_handle_publish(
struct mg_mqtt_broker *brk,
8750 struct mg_mqtt_session *s;
8753 for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
8754 for (
i = 0;
i < s->num_subscriptions;
i++) {
8767 struct mg_mqtt_broker *brk;
8772 brk = (
struct mg_mqtt_broker *) nc->
user_data;
8780 mg_mqtt_broker_handle_connect(brk, nc);
8783 mg_mqtt_broker_handle_subscribe(nc, msg);
8786 mg_mqtt_broker_handle_publish(brk, msg);
8790 mg_mqtt_close_session((
struct mg_mqtt_session *) nc->
user_data);
8796struct mg_mqtt_session *mg_mqtt_next(
struct mg_mqtt_broker *brk,
8797 struct mg_mqtt_session *s) {
8798 return s == NULL ? brk->sessions : s->next;
8802#ifdef MG_MODULE_LINES
8803#line 1 "./src/dns.c"
8810#ifndef MG_DISABLE_DNS
8831 for (rr = (prev == NULL ? msg->
answers : prev + 1);
8833 if (rr->
rtype == query) {
8843 switch (rr->
rtype) {
8845 if (data_len <
sizeof(
struct in_addr)) {
8853#ifdef MG_ENABLE_IPV6
8855 if (data_len <
sizeof(
struct in6_addr)) {
8873 memset(&header, 0,
sizeof(header));
8879 return mbuf_insert(io, pos, &header,
sizeof(header));
8890 size_t pos = io->
len;
8893 if ((s = strchr(
name,
'.')) == NULL) {
8897 if (s -
name > 127) {
8910 }
while (*s !=
'\0');
8913 return io->
len - pos;
8917 const char *
name,
size_t nlen,
const void *rdata,
8919 size_t pos = io->
len;
8931 u16 = htons(rr->
rtype);
8937 u32 = htonl(rr->
ttl);
8943 size_t off = io->
len;
8949 io->
buf[off] = u16 >> 8;
8950 io->
buf[off + 1] = u16 & 0xff;
8958 return io->
len - pos;
8968 DBG((
"%s %d",
name, query_type));
8978 rr->
rtype = query_type;
8989 uint16_t len = htons(pkt.
len);
9004 int chunk_len, data_len;
9007 if (((
unsigned char *)
data)[0] & 0xc0) {
9011 data += chunk_len + 1;
9034 rr->
ttl = (uint32_t)
data[0] << 24 | (uint32_t)
data[1] << 16 |
9038 data_len = *
data << 8 | *(
data + 1);
9050 unsigned char *
data = (
unsigned char *) buf +
sizeof(*header);
9051 unsigned char *
end = (
unsigned char *) buf + len;
9054 memset(msg, 0,
sizeof(*msg));
9058 if (len < (
int)
sizeof(*header))
return -1;
9073 if (
data == NULL)
return -1;
9078 if (
data == NULL)
return -1;
9085 char *dst,
int dst_len) {
9087 char *old_dst = dst;
9088 const unsigned char *
data = (
unsigned char *)
name->p;
9089 const unsigned char *
end = (
unsigned char *) msg->
pkt.
p + msg->
pkt.
len;
9095 while ((chunk_len = *
data++)) {
9096 int leeway = dst_len - (dst - old_dst);
9101 if (chunk_len & 0xc0) {
9102 uint16_t off = (
data[-1] & (~0xc0)) << 8 |
data[0];
9103 if (off >= msg->
pkt.
len) {
9106 data = (
unsigned char *) msg->
pkt.
p + off;
9109 if (chunk_len > leeway) {
9113 if (
data + chunk_len >=
end) {
9117 memcpy(dst,
data, chunk_len);
9120 leeway -= chunk_len;
9122 return dst - old_dst;
9127 if (dst != old_dst) {
9130 return dst - old_dst;
9147 memset(&msg, 0,
sizeof(msg));
9151 uint16_t len = htons(io->
len);
9169#ifdef MG_MODULE_LINES
9170#line 1 "./src/dns-server.c"
9177#ifdef MG_ENABLE_DNS_SERVER
9182struct mg_dns_reply mg_dns_create_reply(struct
mbuf *io,
9184 struct mg_dns_reply rep;
9187 rep.start = io->
len;
9190 msg->flags |= 0x8080;
9193 msg->num_answers = 0;
9197void mg_dns_send_reply(
struct mg_connection *nc,
struct mg_dns_reply *r) {
9198 size_t sent = r->io->
len - r->start;
9201 uint16_t len = htons(sent);
9206 mg_send(nc, r->io->buf + r->start, r->io->len - r->start);
9207 r->io->len = r->start;
9211int mg_dns_reply_record(
struct mg_dns_reply *reply,
9213 const char *
name,
int rtype,
int ttl,
const void *rdata,
9243#ifdef MG_MODULE_LINES
9244#line 1 "./src/resolv.c"
9251#ifndef MG_DISABLE_RESOLVER
9256#ifndef MG_DEFAULT_NAMESERVER
9257#define MG_DEFAULT_NAMESERVER "8.8.8.8"
9290 char subkey[512],
value[128],
9291 *
key =
"SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces";
9293 if ((err = RegOpenKeyA(HKEY_LOCAL_MACHINE,
key, &
hKey)) != ERROR_SUCCESS) {
9294 fprintf(stderr,
"cannot open reg key %s: %d\n",
key, err);
9297 for (ret = -1,
i = 0;
9298 RegEnumKeyA(
hKey,
i, subkey,
sizeof(subkey)) == ERROR_SUCCESS;
i++) {
9300 if (RegOpenKeyA(
hKey, subkey, &hSub) == ERROR_SUCCESS &&
9301 (RegQueryValueExA(hSub,
"NameServer", 0, &
type, (
void *)
value,
9302 &len) == ERROR_SUCCESS ||
9303 RegQueryValueExA(hSub,
"DhcpNameServer", 0, &
type, (
void *)
value,
9304 &len) == ERROR_SUCCESS)) {
9313 if (
value[0] ==
'\0') {
9316 if (
comma != NULL) {
9319 snprintf(
name, name_len,
"udp://%s:53",
value);
9327#elif !defined(MG_DISABLE_FILESYSTEM)
9331 if ((
fp = fopen(
"/etc/resolv.conf",
"r")) == NULL) {
9335 for (ret = -1; fgets(line,
sizeof(line),
fp) != NULL;) {
9337 if (sscanf(line,
"nameserver %255[^\n\t #]s", buf) == 1) {
9338 snprintf(
name, name_len,
"udp://%s:53", buf);
9353#ifndef MG_DISABLE_FILESYSTEM
9359 unsigned int a, b,
c,
d;
9362 if ((
fp = fopen(
"/etc/hosts",
"r")) == NULL) {
9366 for (; fgets(line,
sizeof(line),
fp) != NULL;) {
9367 if (line[0] ==
'#')
continue;
9369 if (sscanf(line,
"%u.%u.%u.%u%n", &a, &b, &
c, &
d, &len) == 0) {
9373 for (p = line + len; sscanf(p,
"%s%n", alias, &len) == 1; p += len) {
9374 if (strcmp(alias,
name) == 0) {
9375 usa->
sin.sin_addr.s_addr = htonl(a << 24 | b << 16 |
c << 8 |
d);
9389 time_t now = time(NULL);
9429 nc->
flags &= ~MG_F_CLOSE_IMMEDIATELY;
9450 memset(&opts, 0,
sizeof(opts));
9469 memset(req->
name, 0,
sizeof(req->
name));
9485 if (nameserver == NULL) {
9490 if (dns_nc == NULL) {
9503#ifdef MG_MODULE_LINES
9504#line 1 "./src/coap.c"
9526#ifdef MG_ENABLE_COAP
9528void mg_coap_free_options(
struct mg_coap_message *cm) {
9529 while (cm->options != NULL) {
9530 struct mg_coap_option *next = cm->options->
next;
9536struct mg_coap_option *mg_coap_add_option(
struct mg_coap_message *cm,
9537 uint32_t number,
char *
value,
9539 struct mg_coap_option *new_option =
9540 (
struct mg_coap_option *)
MG_CALLOC(1,
sizeof(*new_option));
9542 new_option->number = number;
9543 new_option->value.p =
value;
9544 new_option->value.len = len;
9546 if (cm->options == NULL) {
9547 cm->options = cm->optiomg_tail = new_option;
9554 if (cm->optiomg_tail->number <= new_option->number) {
9556 cm->optiomg_tail = cm->optiomg_tail->next = new_option;
9559 struct mg_coap_option *current_opt = cm->options;
9560 struct mg_coap_option *prev_opt = 0;
9562 while (current_opt != NULL) {
9563 if (current_opt->number > new_option->number) {
9566 prev_opt = current_opt;
9567 current_opt = current_opt->next;
9570 if (prev_opt != NULL) {
9571 prev_opt->next = new_option;
9572 new_option->next = current_opt;
9575 new_option->next = cm->options;
9576 cm->options = new_option;
9589static char *coap_parse_header(
char *ptr,
struct mbuf *io,
9590 struct mg_coap_message *cm) {
9591 if (io->
len <
sizeof(uint32_t)) {
9592 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
9602 if (((uint8_t) *ptr >> 6) != 1) {
9603 cm->flags |= MG_COAP_IGNORE;
9612 cm->msg_type = ((uint8_t) *ptr & 0x30) >> 4;
9613 cm->flags |= MG_COAP_MSG_TYPE_FIELD;
9621 cm->token.len = *ptr & 0x0F;
9622 if (cm->token.len > 8) {
9623 cm->flags |= MG_COAP_FORMAT_ERROR;
9633 cm->code_class = (uint8_t) *ptr >> 5;
9634 cm->code_detail = *ptr & 0x1F;
9635 cm->flags |= (MG_COAP_CODE_CLASS_FIELD | MG_COAP_CODE_DETAIL_FIELD);
9640 cm->msg_id = (uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1);
9641 cm->flags |= MG_COAP_MSG_ID_FIELD;
9653static char *coap_get_token(
char *ptr,
struct mbuf *io,
9654 struct mg_coap_message *cm) {
9655 if (cm->token.len != 0) {
9656 if (ptr + cm->token.len > io->
buf + io->
len) {
9657 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
9661 ptr += cm->token.len;
9662 cm->flags |= MG_COAP_TOKEN_FIELD;
9674static int coap_get_ext_opt(
char *ptr,
struct mbuf *io, uint16_t *opt_info) {
9677 if (*opt_info == 13) {
9682 if (ptr < io->buf + io->
len) {
9683 *opt_info = (uint8_t) *ptr + 13;
9684 ret =
sizeof(uint8_t);
9688 }
else if (*opt_info == 14) {
9693 if (ptr +
sizeof(uint8_t) < io->
buf + io->
len) {
9694 *opt_info = ((uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1)) + 269;
9695 ret =
sizeof(uint16_t);
9720static char *coap_get_options(
char *ptr,
struct mbuf *io,
9721 struct mg_coap_message *cm) {
9722 uint16_t prev_opt = 0;
9724 if (ptr == io->
buf + io->
len) {
9730 while (ptr < io->buf + io->
len && (uint8_t) *ptr != 0xFF) {
9731 uint16_t option_delta, option_lenght;
9735 option_delta = ((uint8_t) *ptr & 0xF0) >> 4;
9737 option_lenght = *ptr & 0x0F;
9739 if (option_delta == 15 || option_lenght == 15) {
9744 cm->flags |= MG_COAP_FORMAT_ERROR;
9751 optinfo_len = coap_get_ext_opt(ptr, io, &option_delta);
9752 if (optinfo_len == -1) {
9753 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
9760 optinfo_len = coap_get_ext_opt(ptr, io, &option_lenght);
9761 if (optinfo_len == -1) {
9762 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
9773 option_delta += prev_opt;
9775 mg_coap_add_option(cm, option_delta, ptr, option_lenght);
9777 prev_opt = option_delta;
9779 if (ptr + option_lenght > io->
buf + io->
len) {
9780 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
9784 ptr += option_lenght;
9787 if ((cm->flags & MG_COAP_ERROR) != 0) {
9788 mg_coap_free_options(cm);
9792 cm->flags |= MG_COAP_OPTIOMG_FIELD;
9794 if (ptr == io->
buf + io->
len) {
9804uint32_t mg_coap_parse(
struct mbuf *io,
struct mg_coap_message *cm) {
9807 memset(cm, 0,
sizeof(*cm));
9809 if ((ptr = coap_parse_header(io->
buf, io, cm)) == NULL) {
9813 if ((ptr = coap_get_token(ptr, io, cm)) == NULL) {
9817 if ((ptr = coap_get_options(ptr, io, cm)) == NULL) {
9822 cm->payload.len = io->
len - (ptr - io->
buf);
9823 if (cm->payload.len != 0) {
9824 cm->payload.p = ptr;
9825 cm->flags |= MG_COAP_PAYLOAD_FIELD;
9836static size_t coap_get_ext_opt_size(uint32_t
value) {
9840 ret =
sizeof(uint8_t);
9841 }
else if (
value > 0xFF + 13 &&
value <= 0xFFFF + 269) {
9842 ret =
sizeof(uint16_t);
9853static int coap_split_opt(uint32_t
value, uint8_t *
base, uint16_t *ext) {
9858 }
else if (
value >= 13 &&
value <= 0xFF + 13) {
9861 ret =
sizeof(uint8_t);
9862 }
else if (
value > 0xFF + 13 &&
value <= 0xFFFF + 269) {
9865 ret =
sizeof(uint16_t);
9876static char *coap_add_uint16(
char *ptr, uint16_t val) {
9879 *ptr = val & 0x00FF;
9889static char *coap_add_opt_info(
char *ptr, uint16_t val,
size_t len) {
9890 if (len ==
sizeof(uint8_t)) {
9893 }
else if (len ==
sizeof(uint16_t)) {
9894 ptr = coap_add_uint16(ptr, val);
9905static uint32_t coap_calculate_packet_size(
struct mg_coap_message *cm,
9907 struct mg_coap_option *opt;
9908 uint32_t prev_opt_number;
9911 if (cm->msg_type > MG_COAP_MSG_MAX) {
9912 return MG_COAP_ERROR | MG_COAP_MSG_TYPE_FIELD;
9914 if (cm->token.len > 8) {
9915 return MG_COAP_ERROR | MG_COAP_TOKEN_FIELD;
9917 if (cm->code_class > 7) {
9918 return MG_COAP_ERROR | MG_COAP_CODE_CLASS_FIELD;
9920 if (cm->code_detail > 31) {
9921 return MG_COAP_ERROR | MG_COAP_CODE_DETAIL_FIELD;
9924 *len += cm->token.len;
9925 if (cm->payload.len != 0) {
9926 *len += cm->payload.len + 1;
9930 prev_opt_number = 0;
9931 while (opt != NULL) {
9933 *len += coap_get_ext_opt_size(opt->number);
9934 *len += coap_get_ext_opt_size((uint32_t) opt->value.len);
9941 if ((opt->next != NULL && opt->number > opt->next->number) ||
9942 opt->value.len > 0xFFFF + 269 ||
9943 opt->number - prev_opt_number > 0xFFFF + 269) {
9944 return MG_COAP_ERROR | MG_COAP_OPTIOMG_FIELD;
9946 *len += opt->value.len;
9953uint32_t mg_coap_compose(
struct mg_coap_message *cm,
struct mbuf *io) {
9954 struct mg_coap_option *opt;
9955 uint32_t res, prev_opt_number;
9956 size_t prev_io_len, packet_size;
9959 res = coap_calculate_packet_size(cm, &packet_size);
9965 prev_io_len = io->
len;
9967 ptr = io->
buf + prev_io_len;
9975 *ptr = (1 << 6) | (cm->msg_type << 4) | (cm->token.len);
9979 *ptr = (cm->code_class << 5) | (cm->code_detail);
9982 ptr = coap_add_uint16(ptr, cm->msg_id);
9984 if (cm->token.len != 0) {
9985 memcpy(ptr, cm->token.p, cm->token.len);
9986 ptr += cm->token.len;
9990 prev_opt_number = 0;
9991 while (opt != NULL) {
9992 uint8_t delta_base = 0, length_base = 0;
9993 uint16_t delta_ext, length_ext;
9995 size_t opt_delta_len =
9996 coap_split_opt(opt->number - prev_opt_number, &delta_base, &delta_ext);
9997 size_t opt_lenght_len =
9998 coap_split_opt((uint32_t) opt->value.len, &length_base, &length_ext);
10000 *ptr = (delta_base << 4) | length_base;
10003 ptr = coap_add_opt_info(ptr, delta_ext, opt_delta_len);
10004 ptr = coap_add_opt_info(ptr, length_ext, opt_lenght_len);
10006 if (opt->value.len != 0) {
10007 memcpy(ptr, opt->value.p, opt->value.len);
10008 ptr += opt->value.len;
10011 prev_opt_number = opt->number;
10015 if (cm->payload.len != 0) {
10018 memcpy(ptr, cm->payload.p, cm->payload.len);
10025 struct mg_coap_message *cm) {
10026 struct mbuf packet_out;
10027 uint32_t compose_res;
10030 compose_res = mg_coap_compose(cm, &packet_out);
10031 if (compose_res != 0) {
10032 return compose_res;
10035 mg_send(nc, packet_out.buf, (
int) packet_out.len);
10041uint32_t mg_coap_send_ack(
struct mg_connection *nc, uint16_t msg_id) {
10042 struct mg_coap_message cm;
10043 memset(&cm, 0,
sizeof(cm));
10044 cm.msg_type = MG_COAP_MSG_ACK;
10045 cm.msg_id = msg_id;
10047 return mg_coap_send_message(nc, &cm);
10050static void coap_handler(
struct mg_connection *nc,
int ev,
void *ev_data) {
10052 struct mg_coap_message cm;
10053 uint32_t parse_res;
10055 memset(&cm, 0,
sizeof(cm));
10057 nc->
handler(nc, ev, ev_data);
10061 parse_res = mg_coap_parse(io, &cm);
10062 if ((parse_res & MG_COAP_IGNORE) == 0) {
10063 if ((cm.flags & MG_COAP_NOT_ENOUGH_DATA) != 0) {
10068 cm.flags |= MG_COAP_FORMAT_ERROR;
10070 nc->
handler(nc, MG_COAP_EVENT_BASE + cm.msg_type, &cm);
10073 mg_coap_free_options(&cm);
10100#ifdef MG_MODULE_LINES
10101#line 1 "./src/../../common/platforms/cc3200/cc3200_libc.c"
10108#if CS_PLATFORM == CS_P_CC3200
10113#ifndef __TI_COMPILER_VERSION__
10115#include <sys/stat.h>
10116#include <sys/time.h>
10120#include <inc/hw_types.h>
10121#include <inc/hw_memmap.h>
10122#include <driverlib/prcm.h>
10123#include <driverlib/rom.h>
10124#include <driverlib/rom_map.h>
10125#include <driverlib/uart.h>
10126#include <driverlib/utils.h>
10128#define CONSOLE_UART UARTA0_BASE
10130#ifndef __TI_COMPILER_VERSION__
10135 unsigned long long r1 = 0, r2;
10139 r1 = PRCMSlowClkCtrFastGet();
10140 }
while (r1 != r2);
10142 tp->tv_sec = (r1 >> 15);
10145 tp->tv_usec = (r1 & 0x7FFF) * 30;
10154 while (*
str !=
'\0') {
10170 fprint_str(stderr,
" is not implemented\n");
10182 fprint_str(stderr,
"_getpid is not implemented\n");
10192#ifdef MG_MODULE_LINES
10193#line 1 "./src/../../common/platforms/msp432/msp432_libc.c"
10200#if CS_PLATFORM == CS_P_MSP432
10202#include <ti/sysbios/BIOS.h>
10203#include <ti/sysbios/knl/Clock.h>
10206 uint32_t ticks = Clock_getTicks();
10207 tp->tv_sec = ticks / 1000;
10208 tp->tv_usec = (ticks % 1000) * 1000;
10217#ifdef MG_MODULE_LINES
10218#line 1 "./src/../../common/platforms/simplelink/sl_fs_slfs.h"
10225#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
10226#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
10228#if defined(MG_FS_SLFS)
10231#ifndef __TI_COMPILER_VERSION__
10233#include <sys/stat.h>
10236#define MAX_OPEN_SLFS_FILES 8
10239int fs_slfs_open(
const char *pathname,
int flags, mode_t mode);
10240int fs_slfs_close(
int fd);
10241ssize_t fs_slfs_read(
int fd,
void *buf,
size_t count);
10242ssize_t fs_slfs_write(
int fd,
const void *buf,
size_t count);
10243int fs_slfs_stat(
const char *pathname,
struct stat *s);
10244int fs_slfs_fstat(
int fd,
struct stat *s);
10245off_t fs_slfs_lseek(
int fd, off_t
offset,
int whence);
10246int fs_slfs_unlink(
const char *filename);
10247int fs_slfs_rename(
const char *from,
const char *to);
10252#ifdef MG_MODULE_LINES
10253#line 1 "./src/../../common/platforms/simplelink/sl_fs_slfs.c"
10262#if defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS)
10268#if CS_PLATFORM == CS_P_CC3200
10269#include <inc/hw_types.h>
10271#include <simplelink/include/simplelink.h>
10272#include <simplelink/include/fs.h>
10276extern int set_errno(
int e);
10282#ifndef FS_SLFS_MAX_FILE_SIZE
10283#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
10292static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
10294static int sl_fs_to_errno(_i32 r) {
10295 DBG((
"SL error: %d", (
int) r));
10299 case SL_FS_FILE_NAME_EXIST:
10301 case SL_FS_WRONG_FILE_NAME:
10303 case SL_FS_ERR_NO_AVAILABLE_NV_INDEX:
10304 case SL_FS_ERR_NO_AVAILABLE_BLOCKS:
10306 case SL_FS_ERR_FAILED_TO_ALLOCATE_MEM:
10308 case SL_FS_ERR_FILE_NOT_EXISTS:
10310 case SL_FS_ERR_NOT_SUPPORTED:
10316int fs_slfs_open(
const char *pathname,
int flags, mode_t mode) {
10318 for (fd = 0; fd < MAX_OPEN_SLFS_FILES; fd++) {
10319 if (s_sl_fds[fd].fh <= 0)
break;
10321 if (fd >= MAX_OPEN_SLFS_FILES)
return set_errno(ENOMEM);
10322 struct sl_fd_info *fi = &s_sl_fds[fd];
10325 fi->size = (size_t) -1;
10326 if (pathname[0] ==
'/') pathname++;
10327 int rw = (flags & 3);
10328 if (rw == O_RDONLY) {
10329 SlFsFileInfo_t sl_fi;
10330 _i32 r = sl_FsGetInfo((
const _u8 *) pathname, 0, &sl_fi);
10331 if (r == SL_FS_OK) {
10332 fi->size = sl_fi.FileLen;
10334 am = FS_MODE_OPEN_READ;
10336 if (!(flags & O_TRUNC) || (flags & O_APPEND)) {
10339 return set_errno(ENOTSUP);
10341 if (flags & O_CREAT) {
10342 am = FS_MODE_OPEN_CREATE(FS_SLFS_MAX_FILE_SIZE, 0);
10344 am = FS_MODE_OPEN_WRITE;
10347 _i32 r = sl_FsOpen((_u8 *) pathname, am, NULL, &fi->fh);
10348 DBG((
"sl_FsOpen(%s, 0x%x) = %d, %d", pathname, (
int) am, (
int) r,
10350 if (r == SL_FS_OK) {
10355 r = set_errno(sl_fs_to_errno(r));
10360int fs_slfs_close(
int fd) {
10361 struct sl_fd_info *fi = &s_sl_fds[fd];
10362 if (fi->fh <= 0)
return set_errno(EBADF);
10363 _i32 r = sl_FsClose(fi->fh, NULL, NULL, 0);
10364 DBG((
"sl_FsClose(%d) = %d", (
int) fi->fh, (
int) r));
10365 s_sl_fds[fd].fh = -1;
10366 return set_errno(sl_fs_to_errno(r));
10369ssize_t fs_slfs_read(
int fd,
void *buf,
size_t count) {
10370 struct sl_fd_info *fi = &s_sl_fds[fd];
10371 if (fi->fh <= 0)
return set_errno(EBADF);
10374 if (fi->pos == fi->size)
return 0;
10375 _i32 r = sl_FsRead(fi->fh, fi->pos, buf,
count);
10376 DBG((
"sl_FsRead(%d, %d, %d) = %d", (
int) fi->fh, (
int) fi->pos, (
int)
count,
10382 return set_errno(sl_fs_to_errno(r));
10385ssize_t fs_slfs_write(
int fd,
const void *buf,
size_t count) {
10386 struct sl_fd_info *fi = &s_sl_fds[fd];
10387 if (fi->fh <= 0)
return set_errno(EBADF);
10388 _i32 r = sl_FsWrite(fi->fh, fi->pos, (_u8 *) buf,
count);
10389 DBG((
"sl_FsWrite(%d, %d, %d) = %d", (
int) fi->fh, (
int) fi->pos, (
int)
count,
10395 return set_errno(sl_fs_to_errno(r));
10398int fs_slfs_stat(
const char *pathname,
struct stat *s) {
10399 SlFsFileInfo_t sl_fi;
10400 _i32 r = sl_FsGetInfo((
const _u8 *) pathname, 0, &sl_fi);
10401 if (r == SL_FS_OK) {
10402 s->st_mode = S_IFREG | 0666;
10404 s->st_size = sl_fi.FileLen;
10407 return set_errno(sl_fs_to_errno(r));
10410int fs_slfs_fstat(
int fd,
struct stat *s) {
10411 struct sl_fd_info *fi = &s_sl_fds[fd];
10412 if (fi->fh <= 0)
return set_errno(EBADF);
10414 s->st_mode = S_IFREG | 0666;
10416 s->st_size = fi->size;
10420off_t fs_slfs_lseek(
int fd, off_t
offset,
int whence) {
10421 if (s_sl_fds[fd].fh <= 0)
return set_errno(EBADF);
10424 s_sl_fds[fd].pos =
offset;
10427 s_sl_fds[fd].pos +=
offset;
10430 return set_errno(ENOTSUP);
10435int fs_slfs_unlink(
const char *filename) {
10436 return set_errno(sl_fs_to_errno(sl_FsDel((
const _u8 *) filename, 0)));
10439int fs_slfs_rename(
const char *from,
const char *to) {
10440 return set_errno(ENOTSUP);
10444#ifdef MG_MODULE_LINES
10445#line 1 "./src/../../common/platforms/simplelink/sl_fs.c"
10452#if defined(MG_SOCKET_SIMPLELINK) && \
10453 (defined(MG_FS_SLFS) || defined(MG_FS_SPIFFS))
10459#ifdef __TI_COMPILER_VERSION__
10463#if CS_PLATFORM == CS_P_CC3200
10464#include <inc/hw_types.h>
10465#include <inc/hw_memmap.h>
10466#include <driverlib/rom.h>
10467#include <driverlib/rom_map.h>
10468#include <driverlib/uart.h>
10474#ifdef CC3200_FS_SPIFFS
10482#define NUM_SYS_FDS 3
10483#define SPIFFS_FD_BASE 10
10484#define SLFS_FD_BASE 100
10486#define CONSOLE_UART UARTA0_BASE
10488int set_errno(
int e) {
10493static int is_sl_fname(
const char *fname) {
10494 return strncmp(fname,
"SL:", 3) == 0;
10497static const char *sl_fname(
const char *fname) {
10501static const char *drop_dir(
const char *fname) {
10502 if (*fname ==
'.') fname++;
10503 if (*fname ==
'/') fname++;
10510#ifdef CC3200_FS_SPIFFS
10517static int fd_type(
int fd) {
10518 if (fd >= 0 && fd < NUM_SYS_FDS)
return FD_SYS;
10519#ifdef CC3200_FS_SPIFFS
10520 if (fd >= SPIFFS_FD_BASE && fd < SPIFFS_FD_BASE + MAX_OPEN_SPIFFS_FILES) {
10525 if (fd >= SLFS_FD_BASE && fd < SLFS_FD_BASE + MAX_OPEN_SLFS_FILES) {
10532int _open(
const char *pathname,
int flags, mode_t mode) {
10534 pathname = drop_dir(pathname);
10535 if (is_sl_fname(pathname)) {
10537 fd = fs_slfs_open(sl_fname(pathname), flags, mode);
10538 if (fd >= 0) fd += SLFS_FD_BASE;
10541#ifdef CC3200_FS_SPIFFS
10542 fd = fs_spiffs_open(pathname, flags, mode);
10543 if (fd >= 0) fd += SPIFFS_FD_BASE;
10546 DBG((
"open(%s, 0x%x) = %d", pathname, flags, fd));
10550int _stat(
const char *pathname,
struct stat *st) {
10552 const char *fname = pathname;
10553 int is_sl = is_sl_fname(pathname);
10554 if (is_sl) fname = sl_fname(pathname);
10555 fname = drop_dir(fname);
10556 memset(st, 0,
sizeof(*st));
10558 if (strcmp(fname,
"") == 0) {
10560 st->st_mode = S_IFDIR | 0777;
10567 res = fs_slfs_stat(fname, st);
10570#ifdef CC3200_FS_SPIFFS
10571 res = fs_spiffs_stat(fname, st);
10574 DBG((
"stat(%s) = %d; fname = %s", pathname, res, fname));
10578int _close(
int fd) {
10580 switch (fd_type(fd)) {
10582 r = set_errno(EBADF);
10585 r = set_errno(EACCES);
10587#ifdef CC3200_FS_SPIFFS
10589 r = fs_spiffs_close(fd - SPIFFS_FD_BASE);
10594 r = fs_slfs_close(fd - SLFS_FD_BASE);
10598 DBG((
"close(%d) = %d", fd, r));
10602off_t _lseek(
int fd, off_t
offset,
int whence) {
10604 switch (fd_type(fd)) {
10606 r = set_errno(EBADF);
10609 r = set_errno(ESPIPE);
10611#ifdef CC3200_FS_SPIFFS
10613 r = fs_spiffs_lseek(fd - SPIFFS_FD_BASE,
offset, whence);
10618 r = fs_slfs_lseek(fd - SLFS_FD_BASE,
offset, whence);
10622 DBG((
"lseek(%d, %d, %d) = %d", fd, (
int)
offset, whence, r));
10626int _fstat(
int fd,
struct stat *s) {
10628 memset(s, 0,
sizeof(*s));
10629 switch (fd_type(fd)) {
10631 r = set_errno(EBADF);
10635 memset(s, 0,
sizeof(*s));
10637 s->st_mode = S_IFCHR | 0666;
10641#ifdef CC3200_FS_SPIFFS
10643 r = fs_spiffs_fstat(fd - SPIFFS_FD_BASE, s);
10648 r = fs_slfs_fstat(fd - SLFS_FD_BASE, s);
10652 DBG((
"fstat(%d) = %d", fd, r));
10656ssize_t _read(
int fd,
void *buf,
size_t count) {
10658 switch (fd_type(fd)) {
10660 r = set_errno(EBADF);
10664 r = set_errno(EACCES);
10668 r = set_errno(ENOTSUP);
10671#ifdef CC3200_FS_SPIFFS
10673 r = fs_spiffs_read(fd - SPIFFS_FD_BASE, buf,
count);
10678 r = fs_slfs_read(fd - SLFS_FD_BASE, buf,
count);
10682 DBG((
"read(%d, %u) = %d", fd,
count, r));
10686ssize_t _write(
int fd,
const void *buf,
size_t count) {
10689 switch (fd_type(fd)) {
10691 r = set_errno(EBADF);
10695 r = set_errno(EACCES);
10698#if CS_PLATFORM == CS_P_CC3200
10700 const char c = ((
const char *) buf)[
i];
10710#ifdef CC3200_FS_SPIFFS
10712 r = fs_spiffs_write(fd - SPIFFS_FD_BASE, buf,
count);
10717 r = fs_slfs_write(fd - SLFS_FD_BASE, buf,
count);
10724int _rename(
const char *from,
const char *to) {
10726 from = drop_dir(from);
10728 if (is_sl_fname(from) || is_sl_fname(to)) {
10730 r = fs_slfs_rename(sl_fname(from), sl_fname(to));
10733#ifdef CC3200_FS_SPIFFS
10734 r = fs_spiffs_rename(from, to);
10737 DBG((
"rename(%s, %s) = %d", from, to, r));
10741int _link(
const char *from,
const char *to) {
10742 DBG((
"link(%s, %s)", from, to));
10743 return set_errno(ENOTSUP);
10746int _unlink(
const char *filename) {
10748 filename = drop_dir(filename);
10749 if (is_sl_fname(filename)) {
10751 r = fs_slfs_unlink(sl_fname(filename));
10754#ifdef CC3200_FS_SPIFFS
10755 r = fs_spiffs_unlink(filename);
10758 DBG((
"unlink(%s) = %d", filename, r));
10762#ifdef CC3200_FS_SPIFFS
10763DIR *opendir(
const char *dir_name) {
10765 if (is_sl_fname(dir_name)) {
10767 set_errno(ENOTSUP);
10769 r = fs_spiffs_opendir(dir_name);
10771 DBG((
"opendir(%s) = %p", dir_name, r));
10775struct dirent *readdir(
DIR *dir) {
10776 struct dirent *res = fs_spiffs_readdir(dir);
10777 DBG((
"readdir(%p) = %p", dir, res));
10781int closedir(
DIR *dir) {
10782 int res = fs_spiffs_closedir(dir);
10783 DBG((
"closedir(%p) = %d", dir, res));
10787int rmdir(
const char *path) {
10788 return fs_spiffs_rmdir(path);
10791int mkdir(
const char *path, mode_t mode) {
10795 return (strlen(path) == 1 && *path ==
'.') ? 0 : ENOTDIR;
10801#ifdef __TI_COMPILER_VERSION__
10803 ret = (add_device(
"SL", _MSA, fs_slfs_open, fs_slfs_close, fs_slfs_read,
10804 fs_slfs_write, fs_slfs_lseek, fs_slfs_unlink,
10805 fs_slfs_rename) == 0);
10813#ifdef MG_MODULE_LINES
10814#line 1 "./src/../../common/platforms/simplelink/sl_socket.c"
10821#ifdef MG_SOCKET_SIMPLELINK
10828#include <simplelink/include/netapp.h>
10830const char *
inet_ntop(
int af,
const void *src,
char *dst, socklen_t size) {
10832 struct in_addr *in = (
struct in_addr *) src;
10833 if (af != AF_INET) {
10834 errno = EAFNOSUPPORT;
10837 res = snprintf(dst, size,
"%lu.%lu.%lu.%lu", SL_IPV4_BYTE(in->s_addr, 0),
10838 SL_IPV4_BYTE(in->s_addr, 1), SL_IPV4_BYTE(in->s_addr, 2),
10839 SL_IPV4_BYTE(in->s_addr, 3));
10840 return res > 0 ? dst : NULL;
10845 return (
char *)
inet_ntop(AF_INET, &
n, a,
sizeof(
n));
10848int inet_pton(
int af,
const char *src,
void *dst) {
10849 uint32_t a0, a1, a2, a3;
10850 uint8_t *db = (uint8_t *) dst;
10851 if (af != AF_INET) {
10852 errno = EAFNOSUPPORT;
10855 if (sscanf(src,
"%lu.%lu.%lu.%lu", &a0, &a1, &a2, &a3) != 4) {
10866#ifdef MG_MODULE_LINES
10867#line 1 "./src/../../common/platforms/simplelink/sl_mg_task.c"
10869#if defined(MG_SOCKET_SIMPLELINK)
10873#include <oslib/osi.h>
10884static void mg_task(
void *arg);
10886bool mg_start_task(
int priority,
int stack_size, mg_init_cb mg_init) {
10887 if (osi_MsgQCreate(&
s_mg_q,
"MG",
sizeof(
struct mg_q_msg), 16) != OSI_OK) {
10890 if (osi_TaskCreate(
mg_task, (
const signed char *)
"MG", stack_size,
10891 (
void *) mg_init, priority, NULL) != OSI_OK) {
10897static void mg_task(
void *arg) {
10899 mg_init_cb mg_init = (mg_init_cb) arg;
10905 if (osi_MsgQRead(&
s_mg_q, &msg, 1) != OSI_OK)
continue;
10906 switch (msg.type) {
10908 msg.cb(&mgr, msg.arg);
10916 osi_MsgQWrite(&
s_mg_q, &msg, OSI_NO_WAIT);
int mg_start_thread(mg_thread_func_t f, void *p)
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
int(* mg_event_handler_t)(struct mg_event *event)
time_t mg_mgr_poll(struct mg_mgr *mgr, int timeout_ms)
void mg_mqtt_ping(struct mg_connection *nc)
void MD5_Init(MD5_CTX *ctx)
void mg_set_protocol_mqtt(struct mg_connection *nc)
#define JSON_STRING_INCOMPLETE
void mg_mgr_free(struct mg_mgr *m)
const char * hexdump_file
int mg_resolve_from_hosts_file(const char *name, union socket_address *usa)
void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len)
void cs_to_hex(char *to, const unsigned char *p, size_t len)
#define WEBSOCKET_DONT_FIN
#define MG_MK_STR(str_literal)
void mg_send_dns_query(struct mg_connection *nc, const char *name, int query_type)
#define WEBSOCKET_OP_PING
char * cs_md5(char buf[33],...)
struct json_token * message
void mg_mqtt_disconnect(struct mg_connection *nc)
#define MG_MQTT_CMD_PUBREC
void mg_mqtt_publish(struct mg_connection *nc, const char *topic, uint16_t message_id, int flags, const void *data, size_t len)
void mg_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
#define MG_MQTT_CMD_UNSUBACK
struct mg_str header_names[MG_MAX_HTTP_HEADERS]
int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap)
int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap)
void mg_if_destroy_conn(struct mg_connection *nc)
#define MG_MAX_HTTP_SEND_MBUF
#define MG_MAX_DNS_ANSWERS
int mg_dns_copy_body(struct mbuf *io, struct mg_dns_message *msg)
#define MG_EV_WEBSOCKET_FRAME
int mg_stat(const char *path, cs_stat_t *st)
#define JSON_RPC_INVALID_PARAMS_ERROR
struct mg_connection * mg_connect_http(struct mg_mgr *mgr, mg_event_handler_t ev_handler, const char *url, const char *extra_headers, const char *post_data)
const char * global_auth_file
#define MG_EV_WEBSOCKET_HANDSHAKE_DONE
int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query, mg_resolve_callback_t cb, void *data, struct mg_resolve_async_opts opts)
mg_event_handler_t handler
struct mg_connection * active_connections
void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code)
#define MG_MQTT_CMD_PUBACK
int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr, const char *name, size_t nlen, const void *rdata, size_t rlen)
void mg_mqtt_pong(struct mg_connection *nc)
struct mg_connection ** dns_conn
struct json_token * message
int mg_is_big_endian(void)
#define MG_F_CLOSE_IMMEDIATELY
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len)
size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name, size_t var_name_len, char *file_name, size_t file_name_len, const char **data, size_t *data_len)
#define MG_SOCK_STRINGIFY_PORT
void mbuf_remove(struct mbuf *mb, size_t n)
void mg_mgr_init(struct mg_mgr *m, void *user_data)
int mg_dns_insert_header(struct mbuf *io, size_t pos, struct mg_dns_message *msg)
const char * extra_headers
void mg_send_head(struct mg_connection *c, int status_code, int64_t content_length, const char *extra_headers)
void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id)
void mg_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
void(* proto_data_destructor)(void *proto_data)
struct mg_connection * mg_next(struct mg_mgr *s, struct mg_connection *conn)
int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query, mg_resolve_callback_t cb, void *data)
void mg_if_connect_udp(struct mg_connection *nc)
void mg_if_accept_tcp_cb(struct mg_connection *nc, union socket_address *sa, size_t sa_len)
int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out)
#define WEBSOCKET_OP_CLOSE
const char * c_strnstr(const char *s, const char *find, size_t slen)
int mg_vprintf(struct mg_connection *nc, const char *fmt, va_list ap)
const char * mg_set_ssl(struct mg_connection *nc, const char *cert, const char *ca_cert)
void mg_broadcast(struct mg_mgr *mgr, mg_event_handler_t cb, void *data, size_t len)
#define MG_DNS_AAAA_RECORD
int json_emit_unquoted_str(char *buf, int buf_len, const char *str, int len)
void mg_send_response_line(struct mg_connection *nc, int status_code, const char *extra_headers)
#define MG_MQTT_CMD_CONNACK
void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id)
#define MG_VPRINTF_BUFFER_SIZE
struct mg_str header_values[MG_MAX_HTTP_HEADERS]
void mg_if_recv_udp_cb(struct mg_connection *nc, void *buf, int len, union socket_address *sa, size_t sa_len)
void mbuf_free(struct mbuf *mbuf)
const char * url_rewrites
#define MG_EV_WEBSOCKET_CONTROL_FRAME
void mg_serve_http(struct mg_connection *nc, struct http_message *hm, struct mg_serve_http_opts opts)
const char ** error_string
#define MG_MAX_CGI_ENVIR_VARS
#define MG_SOCK_STRINGIFY_REMOTE
void mg_if_poll(struct mg_connection *nc, time_t now)
int mg_open(const char *path, int flag, int mode)
struct json_token * method
double mg_set_timer(struct mg_connection *c, double timestamp)
struct mg_connection * mg_connect(struct mg_mgr *mgr, const char *address, mg_event_handler_t callback)
void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len, int flags)
#define MG_MQTT_GET_QOS(flags)
struct json_token * message
struct json_token * error_message
int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req)
int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str)
#define MG_SEND_FUNC(s, b, l, f)
union mg_connection::@11 priv_1
void mbuf_resize(struct mbuf *a, size_t new_size)
void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len)
void mg_printf_html_escape(struct mg_connection *nc, const char *fmt,...)
cs_base64_putc_t b64_putc
void mg_if_sent_cb(struct mg_connection *nc, int num_sent)
#define MG_DNS_CNAME_RECORD
struct mg_connection * mg_if_accept_new_conn(struct mg_connection *lc)
#define MG_CGI_ENVIRONMENT_SIZE
const char * cgi_file_pattern
int mg_casecmp(const char *s1, const char *s2)
int mg_if_create_conn(struct mg_connection *nc)
void mg_send(struct mg_connection *nc, const void *buf, int len)
int mg_socketpair(sock_t sp[2], int sock_type)
#define MG_MQTT_CMD_PUBREL
int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req, int code, const char *message, const char *fmt,...)
struct mg_connection * next
void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len)
int json_emit_double(char *buf, int buf_len, double value)
#define MG_MQTT_CMD_PINGREQ
const char * cgi_interpreter
#define MG_EV_MQTT_CONNACK_SERVER_UNAVAILABLE
#define MG_ENV_EXPORT_TO_CGI
void mg_hexdump_connection(struct mg_connection *nc, const char *path, const void *buf, int num_bytes, int ev)
enum mg_dns_resource_record_kind kind
#define MG_F_WEBSOCKET_NO_DEFRAG
#define ARRAY_SIZE(array)
struct json_token * result
void mg_if_connect_cb(struct mg_connection *nc, int err)
int mg_http_create_digest_auth_header(char *buf, size_t buf_len, const char *method, const char *uri, const char *auth_domain, const char *user, const char *passwd)
struct mg_connection * mg_add_sock_opt(struct mg_mgr *s, sock_t sock, mg_event_handler_t callback, struct mg_add_sock_opts opts)
#define MG_EV_MQTT_CONNECT
int mg_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
void mg_sock_set(struct mg_connection *nc, sock_t sock)
void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path, const char *host, const char *protocol, const char *extra_headers)
void mg_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
int(* mg_rpc_handler_t)(char *buf, int len, struct mg_rpc_request *req)
void cs_base64_finish(struct cs_base64_ctx *ctx)
int mg_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
struct mg_connection * mg_connect_opt(struct mg_mgr *mgr, const char *address, mg_event_handler_t callback, struct mg_connect_opts opts)
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, mg_event_handler_t handler)
void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags)
#define MG_MQTT_CMD_PUBCOMP
void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id)
struct mg_str query_string
void mg_printf_websocket_frame(struct mg_connection *nc, int op, const char *fmt,...)
#define MG_MQTT_EVENT_BASE
#define MG_MQTT_CMD_PUBLISH
#define MBUF_SIZE_MULTIPLIER
struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS]
void cs_log_set_level(enum cs_log_level level)
void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len)
#define JSON_RPC_SERVER_ERROR
int parse_json(const char *s, int s_len, struct json_token *arr, int arr_len)
int cs_base64_decode(const unsigned char *s, int len, char *dst)
#define MG_SOCK_STRINGIFY_IP
const char * enable_directory_listing
size_t c_strnlen(const char *s, size_t maxlen)
int mg_match_prefix(const char *pattern, int pattern_len, const char *str)
#define MG_MQTT_CMD_PINGRESP
#define MG_MQTT_CMD_CONNECT
void cs_hmac_sha1(const unsigned char *key, size_t keylen, const unsigned char *data, size_t datalen, unsigned char out[20])
const char * dav_auth_file
void mg_set_protocol_http_websocket(struct mg_connection *nc)
void mg_send_websocket_framev(struct mg_connection *nc, int op, const struct mg_str *strv, int strvcnt)
void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len)
int mg_hexdump(const void *buf, int len, char *dst, int dst_len)
int mg_vcasecmp(const struct mg_str *str1, const char *str2)
#define MG_WEBSOCKET_PING_INTERVAL_SECONDS
int mg_base64_decode(const unsigned char *s, int len, char *dst)
struct mg_connection * mg_connect_ws(struct mg_mgr *mgr, mg_event_handler_t ev_handler, const char *url, const char *protocol, const char *extra_headers)
struct mg_connection * listener
struct mg_connection * prev
void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id)
void mg_set_close_on_exec(sock_t sock)
void cs_log_print_prefix(const char *func)
void(* cs_base64_putc_t)(char, void *)
struct mg_connection * mg_connect_ws_opt(struct mg_mgr *mgr, mg_event_handler_t ev_handler, struct mg_connect_opts opts, const char *url, const char *protocol, const char *extra_headers)
#define MG_F_DELETE_CHUNK
int mg_resolve(const char *host, char *buf, size_t n)
void mg_set_protocol_dns(struct mg_connection *nc)
const char * mg_skip(const char *s, const char *end, const char *delims, struct mg_str *v)
int json_emit(char *buf, int buf_len, const char *fmt,...)
void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len, uint16_t message_id)
int json_emit_va(char *s, int s_len, const char *fmt, va_list ap)
#define MG_MAX_HTTP_REQUEST_SIZE
#define MG_MQTT_CMD_UNSUBSCRIBE
int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg)
const char * hidden_file_pattern
int c_snprintf(char *buf, size_t buf_size, const char *fmt,...)
struct json_token * error_code
void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id)
void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc, void *user_data)
struct mg_dns_resource_record * mg_dns_next_record(struct mg_dns_message *msg, int query, struct mg_dns_resource_record *prev)
const char * document_root
void mbuf_init(struct mbuf *mbuf, size_t initial_size)
struct mg_connection * mg_bind_opt(struct mg_mgr *mgr, const char *address, mg_event_handler_t callback, struct mg_bind_opts opts)
void cs_log_printf(const char *fmt,...)
void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id, struct mg_send_mqtt_handshake_opts opts)
#define JSON_RPC_PARSE_ERROR
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len)
int json_emit_quoted_str(char *s, int s_len, const char *str, int len)
struct json_token * error_data
#define MG_F_SSL_HANDSHAKE_DONE
void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len, int flags)
const char * per_directory_auth_file
void mg_base64_encode(const unsigned char *src, int src_len, char *dst)
#define JSON_TOKEN_ARRAY_TOO_SMALL
void mg_send_websocket_frame(struct mg_connection *nc, int op, const void *data, size_t len)
#define MG_EV_MQTT_PUBLISH
struct mg_connection * mg_bind(struct mg_mgr *srv, const char *address, mg_event_handler_t event_handler)
void(* mg_resolve_callback_t)(struct mg_dns_message *dns_message, void *user_data, enum mg_resolve_err)
#define MG_F_IS_WEBSOCKET
#define MG_RECV_FUNC(s, b, l, f)
struct json_token * find_json_token(struct json_token *toks, const char *path)
struct json_token * parse_json2(const char *s, int s_len)
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context)
const char ** error_string
int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf, size_t buf_size)
int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks, int max_toks, struct mg_rpc_reply *rep, struct mg_rpc_error *er)
struct mg_str mg_mk_str(const char *s)
const char ** error_string
int mg_rpc_create_request(char *buf, int len, const char *method, const char *id, const char *params_fmt,...)
void cs_base64_encode(const unsigned char *src, int src_len, char *dst)
int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req, int code)
int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst, size_t dst_len)
void mg_send_websocket_handshake(struct mg_connection *nc, const char *path, const char *extra_headers)
#define JSON_RPC_METHOD_NOT_FOUND_ERROR
void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt,...)
void mg_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
#define MG_EV_MQTT_SUBSCRIBE
const char * mg_next_comma_list_entry(const char *list, struct mg_str *val, struct mg_str *eq_val)
struct json_token * params
size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name, char *dst, int dst_len)
struct mg_connection * mg_connect_http_opt(struct mg_mgr *mgr, mg_event_handler_t ev_handler, struct mg_connect_opts opts, const char *url, const char *extra_headers, const char *post_data)
const char * nameserver_url
void mbuf_trim(struct mbuf *mbuf)
#define MG_MQTT_CMD_DISCONNECT
#define JSON_STRING_INVALID
FILE * mg_fopen(const char *path, const char *mode)
void mg_enable_multithreading(struct mg_connection *nc)
struct mg_str * mg_get_http_header(struct http_message *hm, const char *name)
void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data, uint32_t len)
#define MG_MQTT_CMD_SUBSCRIBE
#define MG_MQTT_CMD_SUBACK
void mg_if_recved(struct mg_connection *nc, size_t len)
int mg_vcmp(const struct mg_str *str1, const char *str2)
int mg_parse_uri(struct mg_str uri, struct mg_str *scheme, struct mg_str *user_info, struct mg_str *host, unsigned int *port, struct mg_str *path, struct mg_str *query, struct mg_str *fragment)
int mg_check_ip_acl(const char *acl, uint32_t remote_ip)
struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS]
void mg_if_timer(struct mg_connection *c, double now)
mg_event_handler_t proto_handler
const char * dav_document_root
void mg_close_conn(struct mg_connection *conn)
struct mg_str resp_status_msg
void cs_sha1_init(cs_sha1_ctx *context)
int mg_ncasecmp(const char *s1, const char *s2, size_t len)
int mg_dns_parse_record_data(struct mg_dns_message *msg, struct mg_dns_resource_record *rr, void *data, size_t data_len)
int mg_rpc_dispatch(const char *buf, int len, char *dst, int dst_len, const char **methods, mg_rpc_handler_t *handlers)
struct mg_connection * mg_add_sock(struct mg_mgr *s, sock_t sock, mg_event_handler_t callback)
#define MG_EV_MQTT_CONNACK_ACCEPTED
void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics, size_t topics_len, uint16_t message_id)
#define MG_EV_WEBSOCKET_HANDSHAKE_REQUEST
#define JSON_RPC_INVALID_REQUEST_ERROR
int mg_printf(struct mg_connection *conn, const char *fmt,...)
void mg_mqtt_subscribe(struct mg_connection *nc, const struct mg_mqtt_topic_expression *topics, size_t topics_len, uint16_t message_id)
int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req, const char *result_fmt,...)
void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id)
void cs_log_set_file(FILE *file)
int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg, struct mg_str *topic, uint8_t *qos, int pos)
#define MG_F_SEND_AND_CLOSE
#define MG_EV_HTTP_REQUEST
@ MG_RESOLVE_EXCEEDED_RETRY_COUNT
#define message(type, str)
static std::string remove(const std::string s, char c)
static char * skip(char **buf, const char *delimiters)
static const char * month_names[]
static char * addenv(struct cgi_env_block *block, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init)
char * inet_ntoa(struct in_addr n)
static void mg_task(void *arg)
const char * inet_ntop(int af, const void *src, char *dst, socklen_t size)
int inet_pton(int af, const char *src, void *dst)
static int mg_is_error(void)
void mg_run_in_task(void(*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg)
#define MG_DISABLE_HTTP_KEEP_ALIVE
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic)
#define MG_CTL_MSG_MESSAGE_SIZE
#define MG_COPY_COMMON_CONNECTION_OPTIONS(dst, src)
static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data, size_t *chunk_len)
#define MD5STEP(f, w, x, y, z, data, s)
mg_http_multipart_stream_state
@ MPS_WAITING_FOR_BOUNDARY
int _kill(int pid, int sig)
MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm)
static void mg_send_directory_listing(struct mg_connection *nc, const char *dir, struct http_message *hm, struct mg_serve_http_opts *opts)
static void do_ssi_exec(struct mg_connection *nc, char *tag)
static int parse_key(struct frozen *f)
MG_INTERNAL int mg_uri_to_local_path(struct http_message *hm, const struct mg_serve_http_opts *opts, char **local_path, struct mg_str *remainder)
static int capture_ptr(struct frozen *f, const char *ptr, enum json_type type)
static void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d)
static void mqtt_handler(struct mg_connection *nc, int ev, void *ev_data)
static void mg_recv_common(struct mg_connection *nc, void *buf, int len)
static int path_part_len(const char *p)
static int is_alpha(int ch)
static int mg_resolve2(const char *host, struct in_addr *ina)
static void mg_handle_cgi(struct mg_connection *nc, const char *prog, const struct mg_str *path_info, const struct http_message *hm, const struct mg_serve_http_opts *opts)
static struct mg_http_proto_data * mg_http_get_proto_data(struct mg_connection *c)
static void mg_send_file_data(struct mg_connection *nc, FILE *fp)
void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64])
#define MG_WS_NO_HOST_HEADER_MAGIC
MG_INTERNAL void mg_remove_conn(struct mg_connection *c)
static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data)
void mg_ev_mgr_add_conn(struct mg_connection *nc)
static const struct @23 mg_static_builtin_mime_types[]
#define MIME_ENTRY(_ext, _type)
MG_INTERNAL struct mg_connection * mg_create_connection_base(struct mg_mgr *mgr, mg_event_handler_t callback, struct mg_add_sock_opts opts)
#define R1(v, w, x, y, z, i)
MG_INTERNAL struct mg_connection * mg_create_connection(struct mg_mgr *mgr, mg_event_handler_t callback, struct mg_add_sock_opts opts)
MG_INTERNAL void mg_call(struct mg_connection *nc, mg_event_handler_t ev_handler, int ev, void *ev_data)
static int mg_recvfrom(struct mg_connection *nc, union socket_address *sa, socklen_t *sa_len, char **buf)
static void mg_write_to_socket(struct mg_connection *nc)
static int parse_value(struct frozen *f)
#define _MG_CALLBACK_MODIFIABLE_FLAGS_MASK
static unsigned char from_b64(unsigned char ch)
static int mg_create_itermediate_directories(const char *path)
MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path, const struct mg_str *path_info, struct http_message *hm, struct mg_serve_http_opts *opts)
static void dns_handler(struct mg_connection *nc, int ev, void *ev_data)
static void mg_websocket_handler(struct mg_connection *nc, int ev, void *ev_data)
static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags, int field_width)
#define MG_UDP_RECV_BUFFER_SIZE
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
static int parse_object(struct frozen *f)
static int capture_len(struct frozen *f, int token_index, const char *ptr)
static void mg_http_construct_etag(char *buf, size_t buf_len, const cs_stat_t *st)
MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max)
static void mg_http_conn_destructor(void *proto_data)
static int parse_array(struct frozen *f)
MG_INTERNAL char mg_dns_server[300]
void _not_implemented(const char *what)
MG_INTERNAL time_t mg_parse_date_string(const char *datetime)
static void resolve_cb(struct mg_dns_message *msg, void *data, enum mg_resolve_err e)
static sock_t mg_open_listening_socket(union socket_address *sa, int proto)
static int parse_number(struct frozen *f)
static mg_event_handler_t mg_http_get_endpoint_handler(struct mg_connection *nc, struct mg_str *uri_path)
static int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len)
static int mg_is_ws_first_fragment(unsigned char flags)
static int mg_remove_directory(const struct mg_serve_http_opts *opts, const char *dir)
static int mg_http_common_url_parse(const char *url, const char *schema, const char *schema_tls, int *use_ssl, char **addr, int *port_i, const char **path)
static int mg_check_nonce(const char *nonce)
static void mg_scan_directory(struct mg_connection *nc, const char *dir, const struct mg_serve_http_opts *opts, void(*func)(struct mg_connection *, const char *, cs_stat_t *))
static void mg_do_ssi_call(struct mg_connection *nc, char *tag)
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name, cs_stat_t *stp)
static void mg_destroy_conn(struct mg_connection *conn)
static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx)
#define _MG_ALLOWED_CONNECT_FLAGS_MASK
struct mg_connection * mg_connect_http_base(struct mg_mgr *mgr, mg_event_handler_t ev_handler, struct mg_connect_opts opts, const char *schema, const char *schema_ssl, const char *url, const char **path, char **addr)
static void mg_http_send_error(struct mg_connection *nc, int code, const char *reason)
static void mg_handle_udp_read(struct mg_connection *nc)
static int left(const struct frozen *f)
static void mg_handle_put(struct mg_connection *nc, const char *path, struct http_message *hm)
static const char * mg_http_parse_headers(const char *s, const char *end, int len, struct http_message *req)
static size_t mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len)
static int is_space(int ch)
static int parse_string(struct frozen *f)
static void mg_escape(const char *src, char *dst, size_t dst_len)
#define R2(v, w, x, y, z, i)
static void mg_send_ssi_file(struct mg_connection *, const char *, FILE *, int, const struct mg_serve_http_opts *)
MG_INTERNAL int mg_is_not_modified(struct http_message *hm, cs_stat_t *st)
static int parse_pair(struct frozen *f)
static int mg_get_month_index(const char *s)
static int get_utf8_char_len(unsigned char ch)
static uint32_t mg_ws_random_mask(void)
static void mg_sock_get_addr(sock_t sock, int remote, union socket_address *sa)
void mg_ev_mgr_remove_conn(struct mg_connection *nc)
static void skip_whitespaces(struct frozen *f)
static const char * mg_default_dns_server
MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, int *proto, char *host, size_t host_len)
static void mg_http_free_proto_data_file(struct mg_http_proto_data_file *d)
static int parse_identifier(struct frozen *f)
#define _MG_F_FD_CAN_READ
static void byteReverse(unsigned char *buf, unsigned longs)
static int mg_get_ip_address_of_nameserver(char *name, size_t name_len)
static void parse_uri_component(const char **p, const char *end, char sep, struct mg_str *res)
static int mg_is_dav_request(const struct mg_str *s)
#define R0(v, w, x, y, z, i)
static unsigned char * mg_parse_dns_resource_record(unsigned char *data, unsigned char *end, struct mg_dns_resource_record *rr, int reply)
static int doit(struct frozen *f)
static void mg_mgr_handle_ctl_sock(struct mg_mgr *mgr)
#define MG_SET_PTRPTR(_ptr, _v)
static char * mg_addenv(struct mg_cgi_env_block *block, const char *fmt,...)
static int lowercase(const char *s)
static int test_and_skip(struct frozen *f, int expected)
static void mg_read_from_socket(struct mg_connection *conn)
static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v)
static void mg_ws_mask_frame(struct mbuf *mbuf, struct ws_mask_ctx *ctx)
static void mg_prepare_cgi_environment(struct mg_connection *nc, const char *prog, const struct mg_str *path_info, const struct http_message *hm, const struct mg_serve_http_opts *opts, struct mg_cgi_env_block *blk)
void mg_ev_mgr_init(struct mg_mgr *mgr)
static void mg_handle_incoming_websocket_frame(struct mg_connection *nc, struct websocket_message *wsm)
void mg_forward(struct mg_connection *from, struct mg_connection *to)
static int mg_is_file_hidden(const char *path, const struct mg_serve_http_opts *opts, int exclude_specials)
static void mg_handle_ssi_request(struct mg_connection *nc, const char *path, const struct mg_serve_http_opts *opts)
static int mg_http_get_request_len(const char *s, int buf_len)
MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc, struct http_message *hm, char *buf, size_t blen)
int _gettimeofday_r(struct _reent *r, struct timeval *tp, void *tzp)
static int expect(struct frozen *f, const char *s, int len, enum json_type t)
static void mg_addenv2(struct mg_cgi_env_block *blk, const char *name)
static int is_hex_digit(int ch)
void mg_set_non_blocking_mode(sock_t sock)
static void mg_send_ws_header(struct mg_connection *nc, int op, size_t len, struct ws_mask_ctx *ctx)
#define C_SNPRINTF_FLAG_ZERO
static int mg_http_parse_range_header(const struct mg_str *header, int64_t *a, int64_t *b)
static void mg_print_props(struct mg_connection *nc, const char *name, cs_stat_t *stp)
#define BASE64_ENCODE_BODY
static pid_t mg_start_process(const char *interp, const char *cmd, const char *env, const char *envp[], const char *dir, sock_t sock)
#define R3(v, w, x, y, z, i)
static void mg_accept_conn(struct mg_connection *lc)
static int test_no_skip(struct frozen *f, int expected)
static void mg_http_send_file2(struct mg_connection *nc, const char *path, cs_stat_t *st, struct http_message *hm, struct mg_serve_http_opts *opts)
#define MG_TCP_RECV_BUFFER_SIZE
int gettimeofday(struct timeval *tp, void *tzp)
static int mg_is_ws_fragment(unsigned char flags)
MG_INTERNAL void mg_find_index_file(const char *path, const char *list, char **index_file, cs_stat_t *stp)
static int mg_deliver_websocket_data(struct mg_connection *nc)
MG_INTERNAL void mg_add_conn(struct mg_mgr *mgr, struct mg_connection *c)
static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep)
static void mg_cgi_ev_handler(struct mg_connection *cgi_nc, int ev, void *ev_data)
#define _MG_F_FD_CAN_WRITE
static int cur(struct frozen *f)
static void mg_http_send_digest_auth_request(struct mg_connection *c, const char *domain)
static size_t mg_get_line_len(const char *buf, size_t buf_len)
MG_INTERNAL struct mg_connection * mg_do_connect(struct mg_connection *nc, int proto, union socket_address *sa)
static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev, struct http_message *hm)
static void mg_handle_mkcol(struct mg_connection *nc, const char *path, struct http_message *hm)
static void mg_http_transfer_file_data(struct mg_connection *nc)
static void mg_mkmd5resp(const char *method, size_t method_len, const char *uri, size_t uri_len, const char *ha1, size_t ha1_len, const char *nonce, size_t nonce_len, const char *nc, size_t nc_len, const char *cnonce, size_t cnonce_len, const char *qop, size_t qop_len, char *resp)
static int mg_is_authorized(struct http_message *hm, const char *path, int is_directory, const char *domain, const char *passwords_file, int is_global_pass_file)
void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data)
#define EXPECT(cond, err_code)
static void mg_mqtt_prepend_header(struct mg_connection *nc, uint8_t cmd, uint8_t flags, size_t len)
static int mg_http_send_port_based_redirect(struct mg_connection *c, struct http_message *hm, const struct mg_serve_http_opts *opts)
static void mg_handle_delete(struct mg_connection *nc, const struct mg_serve_http_opts *opts, const char *path)
int json_emit_long(char *buf, int buf_len, long int value)
static int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain, FILE *fp)
void mg_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd)
void fprint_str(FILE *fp, const char *str)
static void mg_handle_move(struct mg_connection *c, const struct mg_serve_http_opts *opts, const char *path, struct http_message *hm)
static int get_escape_len(const char *s, int len)
static void mg_handle_propfind(struct mg_connection *nc, const char *path, cs_stat_t *stp, struct http_message *hm, struct mg_serve_http_opts *opts)
void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
static void mg_gmt_time_string(char *buf, size_t buf_len, time_t *t)
static int compare(const char *s, const char *str, int len)
static void mg_http_send_options(struct mg_connection *nc)
static uint32_t blk0(union char64long16 *block, int i)
#define MG_DEFAULT_NAMESERVER
#define C_SNPRINTF_APPEND_CHAR(ch)
static int is_digit(int ch)
static void mg_ws_handshake(struct mg_connection *nc, const struct mg_str *key)
static int mg_is_creation_request(const struct http_message *hm)
void mg_ev_mgr_free(struct mg_mgr *mgr)
static int mg_num_leap_years(int year)
#define R4(v, w, x, y, z, i)
void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now)
static struct mg_str mg_get_mime_type(const char *path, const char *dflt, const struct mg_serve_http_opts *opts)
static void mg_send_mqtt_short_command(struct mg_connection *nc, uint8_t cmd, uint16_t message_id)
struct callback_addr callback
char message[MG_CTL_MSG_MESSAGE_SIZE]
mg_event_handler_t callback
struct json_token * tokens
const char * vars[MG_MAX_CGI_ENVIR_VARS]
struct mg_connection * nc
char buf[MG_CGI_ENVIRONMENT_SIZE]
mg_event_handler_t handler
struct mg_http_endpoint * next
enum mg_http_multipart_stream_state state
struct mg_connection * cgi_nc
enum mg_http_proto_data_type type
struct mg_http_proto_data_chuncked chunk
struct mg_http_endpoint * endpoints
struct mg_http_proto_data_cgi cgi
mg_event_handler_t endpoint_handler
struct mg_http_proto_data_file file
void(* cb)(struct mg_mgr *mgr, void *arg)
mg_resolve_callback_t callback
bool rmdir(HNDLE hDB, HNDLE hROOT, const char *path)
static double comma(double a, double b)
static te_expr * base(state *s)
static te_expr * list(state *s)