3#line 1 "mongoose/src/mg_internal.h"
10#ifndef CS_MONGOOSE_SRC_INTERNAL_H_
11#define CS_MONGOOSE_SRC_INTERNAL_H_
16#define MBUF_REALLOC MG_REALLOC
20#define MBUF_FREE MG_FREE
23#define MG_SET_PTRPTR(_ptr, _v) \
25 if (_ptr) *(_ptr) = _v; \
29#define MG_INTERNAL static
41#ifndef MG_CTL_MSG_MESSAGE_SIZE
42#define MG_CTL_MSG_MESSAGE_SIZE 8192
51 int *proto,
char *host,
size_t host_len);
63int to_wchar(
const char *path,
wchar_t *wbuf,
size_t wbuf_len);
74#define MG_MQTT_ERROR_INCOMPLETE_MSG -1
75#define MG_MQTT_ERROR_MALFORMED_MSG -2
81extern void *(*test_malloc)(
size_t size);
82extern void *(*test_calloc)(
size_t count,
size_t size);
85#define MIN(a, b) ((a) < (b) ? (a) : (b))
106#if MG_ENABLE_FILESYSTEM
110 struct mg_str *remainder);
114#if MG_ENABLE_HTTP_CGI
116 const struct mg_str *path_info,
122#if MG_ENABLE_HTTP_SSI
128#if MG_ENABLE_HTTP_WEBDAV
145#if MG_ENABLE_HTTP_WEBSOCKET
147 void *ev_data
MG_UD_ARG(
void *user_data));
159MG_INTERNAL int mg_sntp_parse_reply(
const char *buf,
int len,
160 struct mg_sntp_message *msg);
164#ifdef MG_MODULE_LINES
165#line 1 "common/mg_mem.h"
184#ifndef CS_COMMON_MG_MEM_H_
185#define CS_COMMON_MG_MEM_H_
192#define MG_MALLOC malloc
196#define MG_CALLOC calloc
200#define MG_REALLOC realloc
212#ifdef MG_MODULE_LINES
213#line 1 "common/cs_base64.c"
232#ifndef EXCLUDE_COMMON
242#define NUM_UPPERCASES ('Z' - 'A' + 1)
243#define NUM_LETTERS (NUM_UPPERCASES * 2)
244#define NUM_DIGITS ('9' - '0' + 1)
289 const unsigned char *src = (
const unsigned char *)
str;
291 for (
i = 0;
i < len;
i++) {
311#define BASE64_ENCODE_BODY \
312 static const char *b64 = \
313 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
316 for (i = j = 0; i < src_len; i += 3) { \
318 b = i + 1 >= src_len ? 0 : src[i + 1]; \
319 c = i + 2 >= src_len ? 0 : src[i + 2]; \
321 BASE64_OUT(b64[a >> 2]); \
322 BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
323 if (i + 1 < src_len) { \
324 BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
326 if (i + 2 < src_len) { \
327 BASE64_OUT(b64[c & 63]); \
331 while (j % 4 != 0) { \
336#define BASE64_OUT(ch) \
341#define BASE64_FLUSH() \
354#define BASE64_OUT(ch) \
356 fprintf(f, "%c", (ch)); \
360#define BASE64_FLUSH()
373 static const unsigned char tab[128] = {
407 return tab[ch & 127];
411 unsigned char a, b,
c,
d;
413 char *orig_dst = dst;
414 while (len >= 4 && (a =
from_b64(s[0])) != 255 &&
419 if (a == 200 || b == 200)
break;
420 *dst++ = a << 2 | b >> 4;
422 *dst++ = b << 4 | c >> 2;
427 if (dec_len != NULL) *dec_len = (dst - orig_dst);
428 return orig_len - len;
432#ifdef MG_MODULE_LINES
433#line 1 "common/cs_dbg.h"
452#ifndef CS_COMMON_CS_DBG_H_
453#define CS_COMMON_CS_DBG_H_
461#ifndef CS_ENABLE_DEBUG
462#define CS_ENABLE_DEBUG 0
465#ifndef CS_LOG_PREFIX_LEN
466#define CS_LOG_PREFIX_LEN 24
469#ifndef CS_LOG_ENABLE_TS_DIFF
470#define CS_LOG_ENABLE_TS_DIFF 0
547 if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
554#define LOG(l, x) ((void) l)
563#define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
583#ifdef MG_MODULE_LINES
584#line 1 "common/cs_dbg.c"
620static char *s_file_level = NULL;
626#if CS_LOG_ENABLE_TS_DIFF
627double cs_log_ts
WEAK;
633 char *fl = s_file_level;
634 if (file_level != NULL) {
635 s_file_level = strdup(file_level);
646 size_t fl = 0, ll = 0, pl = 0;
648 if (level >
cs_log_level && s_file_level == NULL)
return 0;
653 const char c = *(p - 1);
654 if (
c ==
'/' ||
c ==
'\\')
break;
659 ll = (ln < 10000 ? (ln < 1000 ? (ln < 100 ? (ln < 10 ? 1 : 2) : 3) : 4) : 5);
660 if (fl > (
sizeof(prefix) - ll - 2)) fl = (
sizeof(prefix) - ll - 2);
663 memcpy(prefix, p, fl);
665 memset(
q,
' ',
sizeof(prefix) - pl);
667 *(--
q) =
'0' + (ln % 10);
672 if (s_file_level != NULL) {
682 if (level > pll)
return 0;
686 cs_log_cur_msg_level = level;
688#if CS_LOG_ENABLE_TS_DIFF
691 fprintf(
cs_log_file,
"%7u ", (
unsigned int) ((now - cs_log_ts) * 1000000));
706 cs_log_cur_msg_level =
LL_NONE;
725#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
729#ifdef MG_MODULE_LINES
730#line 1 "common/cs_dirent.h"
749#ifndef CS_COMMON_CS_DIRENT_H_
750#define CS_COMMON_CS_DIRENT_H_
760#ifdef CS_DEFINE_DIRENT
761typedef struct {
int dummy; }
DIR;
766 char d_name[MAX_PATH];
773DIR *opendir(
const char *dir_name);
774int closedir(
DIR *dir);
775struct dirent *readdir(
DIR *dir);
783#ifdef MG_MODULE_LINES
784#line 1 "common/cs_dirent.c"
803#ifndef EXCLUDE_COMMON
817 WIN32_FIND_DATAW
info;
818 struct dirent result;
821DIR *opendir(
const char *
name) {
822 struct win32_dir *dir = NULL;
823 wchar_t wpath[MAX_PATH];
827 SetLastError(ERROR_BAD_ARGUMENTS);
828 }
else if ((dir = (
struct win32_dir *)
MG_MALLOC(
sizeof(*dir))) == NULL) {
829 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
832 attrs = GetFileAttributesW(wpath);
833 if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
834 (void) wcscat(wpath, L
"\\*");
835 dir->handle = FindFirstFileW(wpath, &dir->info);
836 dir->result.d_name[0] =
'\0';
846int closedir(
DIR *
d) {
847 struct win32_dir *dir = (
struct win32_dir *)
d;
851 if (dir->handle != INVALID_HANDLE_VALUE)
852 result = FindClose(dir->handle) ? 0 : -1;
856 SetLastError(ERROR_BAD_ARGUMENTS);
862struct dirent *readdir(
DIR *
d) {
863 struct win32_dir *dir = (
struct win32_dir *)
d;
864 struct dirent *result = NULL;
867 memset(&dir->result, 0,
sizeof(dir->result));
868 if (dir->handle != INVALID_HANDLE_VALUE) {
869 result = &dir->result;
870 (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1,
871 result->d_name,
sizeof(result->d_name), NULL,
874 if (!FindNextFileW(dir->handle, &dir->info)) {
875 (void) FindClose(dir->handle);
876 dir->handle = INVALID_HANDLE_VALUE;
880 SetLastError(ERROR_FILE_NOT_FOUND);
883 SetLastError(ERROR_BAD_ARGUMENTS);
894#ifdef MG_MODULE_LINES
895#line 1 "common/cs_time.c"
921#if !(defined(__ARMCC_VERSION) || defined(__ICCARM__)) && \
922 !defined(__TI_COMPILER_VERSION__) && \
923 (!defined(CS_PLATFORM) || CS_PLATFORM != CS_P_NXP_LPC)
936 now = (double)
tv.tv_sec + (((
double)
tv.tv_usec) / 1000000.0);
940 GetLocalTime(&sysnow);
941 SystemTimeToFileTime(&sysnow, &ftime);
950 now = (double) (((int64_t) ftime.dwLowDateTime +
951 ((int64_t) ftime.dwHighDateTime << 32)) /
960 static const int month_day[12] = {0, 31, 59, 90, 120, 151,
961 181, 212, 243, 273, 304, 334};
964 int month =
tm->tm_mon % 12;
965 int year =
tm->tm_year +
tm->tm_mon / 12;
975 year_for_leap = (month > 1) ? year + 1 : year;
985 24 * (month_day[month] +
tm->tm_mday - 1
987 + (year_for_leap - 69) / 4
988 - (year_for_leap - 1) / 100
989 + (year_for_leap + 299) / 400)));
990 return rt < 0 ? -1 : (double) rt;
992#ifdef MG_MODULE_LINES
993#line 1 "common/cs_endian.h"
1012#ifndef CS_COMMON_CS_ENDIAN_H_
1013#define CS_COMMON_CS_ENDIAN_H_
1024#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
1025#define BYTE_ORDER __BYTE_ORDER
1026#ifndef LITTLE_ENDIAN
1027#define LITTLE_ENDIAN __LITTLE_ENDIAN
1030#define BIG_ENDIAN __LITTLE_ENDIAN
1039#ifdef MG_MODULE_LINES
1040#line 1 "common/cs_md5.c"
1062#if !defined(EXCLUDE_COMMON)
1069#if BYTE_ORDER == BIG_ENDIAN
1071 uint32_t t = (uint32_t)((
unsigned) buf[3] << 8 | buf[2]) << 16 |
1072 ((
unsigned) buf[1] << 8 | buf[0]);
1073 *(uint32_t *) buf = t;
1082#define F1(x, y, z) (z ^ (x & (y ^ z)))
1083#define F2(x, y, z) F1(z, x, y)
1084#define F3(x, y, z) (x ^ y ^ z)
1085#define F4(x, y, z) (y ^ (x | ~z))
1087#define MD5STEP(f, w, x, y, z, data, s) \
1088 (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
1095 ctx->
buf[0] = 0x67452301;
1096 ctx->
buf[1] = 0xefcdab89;
1097 ctx->
buf[2] = 0x98badcfe;
1098 ctx->
buf[3] = 0x10325476;
1105 register uint32_t a, b,
c,
d;
1190 if ((ctx->
bits[0] = t + ((uint32_t) len << 3)) < t) ctx->
bits[1]++;
1191 ctx->
bits[1] += (uint32_t) len >> 29;
1193 t = (t >> 3) & 0x3f;
1196 unsigned char *p = (
unsigned char *) ctx->
in + t;
1200 memcpy(p, buf, len);
1211 memcpy(ctx->
in, buf, 64);
1218 memcpy(ctx->
in, buf, len);
1232 memset(p, 0,
count);
1235 memset(ctx->
in, 0, 56);
1237 memset(p, 0,
count - 8);
1241 a = (uint32_t *) ctx->
in;
1242 a[14] = ctx->
bits[0];
1243 a[15] = ctx->
bits[1];
1247 memcpy(digest, ctx->
buf, 16);
1248 memset((
char *) ctx, 0,
sizeof(*ctx));
1253#ifdef MG_MODULE_LINES
1254#line 1 "common/cs_sha1.c"
1261#if !CS_DISABLE_SHA1 && !defined(EXCLUDE_COMMON)
1271 unsigned char c[64];
1275#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
1279#if BYTE_ORDER == LITTLE_ENDIAN
1281 (
rol(block->
l[
i], 24) & 0xFF00FF00) | (
rol(block->
l[
i], 8) & 0x00FF00FF);
1295 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
1296 block->l[(i + 2) & 15] ^ block->l[i & 15], \
1298#define R0(v, w, x, y, z, i) \
1299 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
1301#define R1(v, w, x, y, z, i) \
1302 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
1304#define R2(v, w, x, y, z, i) \
1305 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
1307#define R3(v, w, x, y, z, i) \
1308 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
1310#define R4(v, w, x, y, z, i) \
1311 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
1315 uint32_t a, b,
c,
d,
e;
1318 memcpy(block, buffer, 64);
1324 R0(a, b,
c,
d,
e, 0);
1325 R0(
e, a, b,
c,
d, 1);
1326 R0(
d,
e, a, b,
c, 2);
1327 R0(
c,
d,
e, a, b, 3);
1328 R0(b,
c,
d,
e, a, 4);
1329 R0(a, b,
c,
d,
e, 5);
1330 R0(
e, a, b,
c,
d, 6);
1331 R0(
d,
e, a, b,
c, 7);
1332 R0(
c,
d,
e, a, b, 8);
1333 R0(b,
c,
d,
e, a, 9);
1334 R0(a, b,
c,
d,
e, 10);
1335 R0(
e, a, b,
c,
d, 11);
1336 R0(
d,
e, a, b,
c, 12);
1337 R0(
c,
d,
e, a, b, 13);
1338 R0(b,
c,
d,
e, a, 14);
1339 R0(a, b,
c,
d,
e, 15);
1340 R1(
e, a, b,
c,
d, 16);
1341 R1(
d,
e, a, b,
c, 17);
1342 R1(
c,
d,
e, a, b, 18);
1343 R1(b,
c,
d,
e, a, 19);
1344 R2(a, b,
c,
d,
e, 20);
1345 R2(
e, a, b,
c,
d, 21);
1346 R2(
d,
e, a, b,
c, 22);
1347 R2(
c,
d,
e, a, b, 23);
1348 R2(b,
c,
d,
e, a, 24);
1349 R2(a, b,
c,
d,
e, 25);
1350 R2(
e, a, b,
c,
d, 26);
1351 R2(
d,
e, a, b,
c, 27);
1352 R2(
c,
d,
e, a, b, 28);
1353 R2(b,
c,
d,
e, a, 29);
1354 R2(a, b,
c,
d,
e, 30);
1355 R2(
e, a, b,
c,
d, 31);
1356 R2(
d,
e, a, b,
c, 32);
1357 R2(
c,
d,
e, a, b, 33);
1358 R2(b,
c,
d,
e, a, 34);
1359 R2(a, b,
c,
d,
e, 35);
1360 R2(
e, a, b,
c,
d, 36);
1361 R2(
d,
e, a, b,
c, 37);
1362 R2(
c,
d,
e, a, b, 38);
1363 R2(b,
c,
d,
e, a, 39);
1364 R3(a, b,
c,
d,
e, 40);
1365 R3(
e, a, b,
c,
d, 41);
1366 R3(
d,
e, a, b,
c, 42);
1367 R3(
c,
d,
e, a, b, 43);
1368 R3(b,
c,
d,
e, a, 44);
1369 R3(a, b,
c,
d,
e, 45);
1370 R3(
e, a, b,
c,
d, 46);
1371 R3(
d,
e, a, b,
c, 47);
1372 R3(
c,
d,
e, a, b, 48);
1373 R3(b,
c,
d,
e, a, 49);
1374 R3(a, b,
c,
d,
e, 50);
1375 R3(
e, a, b,
c,
d, 51);
1376 R3(
d,
e, a, b,
c, 52);
1377 R3(
c,
d,
e, a, b, 53);
1378 R3(b,
c,
d,
e, a, 54);
1379 R3(a, b,
c,
d,
e, 55);
1380 R3(
e, a, b,
c,
d, 56);
1381 R3(
d,
e, a, b,
c, 57);
1382 R3(
c,
d,
e, a, b, 58);
1383 R3(b,
c,
d,
e, a, 59);
1384 R4(a, b,
c,
d,
e, 60);
1385 R4(
e, a, b,
c,
d, 61);
1386 R4(
d,
e, a, b,
c, 62);
1387 R4(
c,
d,
e, a, b, 63);
1388 R4(b,
c,
d,
e, a, 64);
1389 R4(a, b,
c,
d,
e, 65);
1390 R4(
e, a, b,
c,
d, 66);
1391 R4(
d,
e, a, b,
c, 67);
1392 R4(
c,
d,
e, a, b, 68);
1393 R4(b,
c,
d,
e, a, 69);
1394 R4(a, b,
c,
d,
e, 70);
1395 R4(
e, a, b,
c,
d, 71);
1396 R4(
d,
e, a, b,
c, 72);
1397 R4(
c,
d,
e, a, b, 73);
1398 R4(b,
c,
d,
e, a, 74);
1399 R4(a, b,
c,
d,
e, 75);
1400 R4(
e, a, b,
c,
d, 76);
1401 R4(
d,
e, a, b,
c, 77);
1402 R4(
c,
d,
e, a, b, 78);
1403 R4(b,
c,
d,
e, a, 79);
1411 memset(block, 0,
sizeof(block));
1412 a = b =
c =
d =
e = 0;
1421 context->
state[0] = 0x67452301;
1422 context->
state[1] = 0xEFCDAB89;
1423 context->
state[2] = 0x98BADCFE;
1424 context->
state[3] = 0x10325476;
1425 context->
state[4] = 0xC3D2E1F0;
1434 if ((context->
count[0] += len << 3) <
j) context->
count[1]++;
1435 context->
count[1] += (len >> 29);
1437 if ((
j + len) > 63) {
1440 for (;
i + 63 < len;
i += 64) {
1451 unsigned char finalcount[8],
c;
1453 for (
i = 0;
i < 8;
i++) {
1454 finalcount[
i] = (
unsigned char) ((context->
count[(
i >= 4 ? 0 : 1)] >>
1455 ((3 - (
i & 3)) * 8)) &
1460 while ((context->
count[0] & 504) != 448) {
1465 for (
i = 0;
i < 20;
i++) {
1467 (
unsigned char) ((context->
state[
i >> 2] >> ((3 - (
i & 3)) * 8)) & 255);
1469 memset(context,
'\0',
sizeof(*context));
1470 memset(&finalcount,
'\0',
sizeof(finalcount));
1474 const unsigned char *
data,
size_t datalen,
1475 unsigned char out[20]) {
1477 unsigned char buf1[64], buf2[64], tmp_key[20],
i;
1479 if (keylen >
sizeof(buf1)) {
1484 keylen =
sizeof(tmp_key);
1487 memset(buf1, 0,
sizeof(buf1));
1488 memset(buf2, 0,
sizeof(buf2));
1489 memcpy(buf1,
key, keylen);
1490 memcpy(buf2,
key, keylen);
1492 for (
i = 0;
i <
sizeof(buf1);
i++) {
1509#ifdef MG_MODULE_LINES
1510#line 1 "common/mbuf.c"
1529#ifndef EXCLUDE_COMMON
1536#define MBUF_REALLOC realloc
1540#define MBUF_FREE free
1560 if (new_size > a->
size || (new_size < a->size && new_size >= a->
len)) {
1567 if (buf == NULL && new_size != 0)
return;
1584 assert(off <= a->len);
1587 if (~(
size_t) 0 - (
size_t) a->
buf < len)
return 0;
1589 if (a->
len + len <= a->size) {
1590 memmove(a->
buf + off + len, a->
buf + off, a->
len - off);
1592 memcpy(a->
buf + off, buf, len);
1596 size_t min_size = (a->
len + len);
1602 if (p == NULL && new_size != min_size) {
1603 new_size = min_size;
1608 if (off != a->
len) {
1609 memmove(a->
buf + off + len, a->
buf + off, a->
len - off);
1611 if (buf != NULL) memcpy(a->
buf + off, buf, len);
1633 if (a->
buf != NULL) free(a->
buf);
1645 if (
n > 0 && n <= mb->len) {
1658 memcpy(to, from,
sizeof(*to));
1659 memset(from, 0,
sizeof(*from));
1663#ifdef MG_MODULE_LINES
1664#line 1 "common/mg_str.c"
1695 struct mg_str ret = {s, 0};
1696 if (s != NULL) ret.
len = strlen(s);
1708 size_t n2 = strlen(str2), n1 = str1->
len;
1709 int r = strncmp(str1->
p, str2, (n1 < n2) ? n1 : n2);
1718 size_t n2 = strlen(str2), n1 = str1->
len;
1719 int r =
mg_ncasecmp(str1->
p, str2, (n1 < n2) ? n1 : n2);
1727 int nul_terminate) {
1728 struct mg_str r = {NULL, 0};
1729 if (s.
len > 0 && s.
p != NULL) {
1730 char *sc = (
char *)
MG_MALLOC(s.
len + (nul_terminate ? 1 : 0));
1732 memcpy(sc, s.
p, s.
len);
1733 if (nul_terminate) sc[s.
len] =
'\0';
1754 for (
i = 0;
i < s.
len;
i++) {
1755 if (s.
p[
i] ==
c)
return &s.
p[
i];
1763 while (
i < str1.
len &&
i < str2.
len) {
1764 if (str1.
p[
i] < str2.
p[
i])
return -1;
1765 if (str1.
p[
i] > str2.
p[
i])
return 1;
1768 if (
i < str1.
len)
return 1;
1769 if (
i < str2.
len)
return -1;
1789 char *sp = (
char *) s->
p;
1792 if (sp != NULL) free(sp);
1798 const struct mg_str needle) {
1800 if (needle.
len > haystack.
len)
return NULL;
1801 for (
i = 0;
i <= haystack.
len - needle.
len;
i++) {
1802 if (memcmp(haystack.
p +
i, needle.
p, needle.
len) == 0) {
1803 return haystack.
p +
i;
1811 while (s.
len > 0 && isspace((
int) *s.
p)) {
1815 while (s.
len > 0 && isspace((
int) *(s.
p + s.
len - 1))) {
1824 if (s.
len < prefix.
len)
return 0;
1827#ifdef MG_MODULE_LINES
1828#line 1 "common/str_util.c"
1847#ifndef EXCLUDE_COMMON
1853#ifndef C_DISABLE_BUILTIN_SNPRINTF
1854#define C_DISABLE_BUILTIN_SNPRINTF 0
1862 for (; l < maxlen && s[l] !=
'\0'; l++) {
1867#define C_SNPRINTF_APPEND_CHAR(ch) \
1869 if (i < (int) buf_size) buf[i] = ch; \
1873#define C_SNPRINTF_FLAG_ZERO 1
1875#if C_DISABLE_BUILTIN_SNPRINTF
1876int c_vsnprintf(
char *buf,
size_t buf_size,
const char *fmt, va_list ap)
WEAK;
1877int c_vsnprintf(
char *buf,
size_t buf_size,
const char *fmt, va_list ap) {
1878 return vsnprintf(buf, buf_size, fmt, ap);
1881static int c_itoa(
char *buf,
size_t buf_size, int64_t num,
int base,
int flags,
1884 int i = 0,
k = 0, neg = 0;
1893 int rem = num %
base;
1895 tmp[
k++] =
'0' + rem;
1897 tmp[
k++] =
'a' + (rem - 10);
1904 while (
k < field_width &&
k < (
int)
sizeof(tmp) - 1) {
1922int c_vsnprintf(
char *buf,
size_t buf_size,
const char *fmt, va_list ap)
WEAK;
1923int c_vsnprintf(
char *buf,
size_t buf_size,
const char *fmt, va_list ap) {
1924 int ch,
i = 0, len_mod, flags, precision, field_width;
1926 while ((ch = *fmt++) !=
'\0') {
1938 flags = field_width = precision = len_mod = 0;
1946 while (*fmt >=
'0' && *fmt <=
'9') {
1948 field_width += *fmt++ -
'0';
1952 field_width = va_arg(ap,
int);
1960 precision = va_arg(ap,
int);
1963 while (*fmt >=
'0' && *fmt <=
'9') {
1965 precision += *fmt++ -
'0';
1994 const char *s = va_arg(ap,
const char *);
1996 int pad = field_width - (precision >= 0 ?
c_strnlen(s, precision) : 0);
1997 for (
j = 0;
j < pad;
j++) {
2004 for (
j = 0; (precision <= 0 ||
j < precision) && s[
j] !=
'\0';
j++) {
2008 }
else if (ch ==
'c') {
2009 ch = va_arg(ap,
int);
2011 }
else if (ch ==
'd' && len_mod == 0) {
2012 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
int), 10, flags,
2014 }
else if (ch ==
'd' && len_mod ==
'l') {
2015 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
long), 10, flags,
2018 }
else if (ch ==
'd' && len_mod ==
'z') {
2019 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap, ssize_t), 10, flags,
2022 }
else if (ch ==
'd' && len_mod ==
'q') {
2023 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap, int64_t), 10, flags,
2025 }
else if ((ch ==
'x' || ch ==
'u') && len_mod == 0) {
2026 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
unsigned),
2027 ch ==
'x' ? 16 : 10, flags, field_width);
2028 }
else if ((ch ==
'x' || ch ==
'u') && len_mod ==
'l') {
2029 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
unsigned long),
2030 ch ==
'x' ? 16 : 10, flags, field_width);
2031 }
else if ((ch ==
'x' || ch ==
'u') && len_mod ==
'z') {
2032 i +=
c_itoa(buf +
i, buf_size -
i, va_arg(ap,
size_t),
2033 ch ==
'x' ? 16 : 10, flags, field_width);
2034 }
else if (ch ==
'p') {
2035 unsigned long num = (
unsigned long) (uintptr_t) va_arg(ap,
void *);
2038 i +=
c_itoa(buf +
i, buf_size -
i, num, 16, flags, 0);
2053 buf[
i < (int) buf_size ?
i : (int) buf_size - 1] =
'\0';
2060int c_snprintf(
char *buf,
size_t buf_size,
const char *fmt, ...)
WEAK;
2061int c_snprintf(
char *buf,
size_t buf_size, const
char *fmt, ...) {
2071int to_wchar(
const char *path,
wchar_t *wbuf,
size_t wbuf_len) {
2073 char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *
p;
2075 strncpy(buf, path,
sizeof(buf));
2076 buf[
sizeof(buf) - 1] =
'\0';
2079 p = buf + strlen(buf) - 1;
2080 while (
p > buf &&
p[-1] !=
':' && (
p[0] ==
'\\' ||
p[0] ==
'/')) *
p-- =
'\0';
2082 memset(wbuf, 0, wbuf_len *
sizeof(
wchar_t));
2083 ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (
int) wbuf_len);
2089 WideCharToMultiByte(CP_UTF8, 0, wbuf, (
int) wbuf_len, buf2,
sizeof(buf2),
2091 if (strcmp(buf, buf2) != 0) {
2101const char *
c_strnstr(
const char *s,
const char *find,
size_t slen)
WEAK;
2102const char *
c_strnstr(
const char *s,
const char *find,
size_t slen) {
2103 size_t find_length = strlen(find);
2106 for (
i = 0;
i < slen;
i++) {
2107 if (
i + find_length > slen) {
2111 if (strncmp(&s[
i], find, find_length) == 0) {
2120char *strdup(
const char *src)
WEAK;
2121char *strdup(
const char *src) {
2122 size_t len = strlen(src) + 1;
2133 static const char *hex =
"0123456789abcdef";
2135 for (;
len--;
p++) {
2136 *to++ = hex[
p[0] >> 4];
2137 *to++ = hex[
p[0] & 0x0f];
2143 if (ch >=
'0' && ch <=
'9') {
2145 }
else if (ch >=
'a' && ch <=
'f') {
2146 return ch -
'a' + 10;
2147 }
else if (ch >=
'A' && ch <=
'F') {
2148 return ch -
'A' + 10;
2157 for (
i = 0;
i <
len;
i += 2) {
2164int64_t cs_to64(
const char *s)
WEAK;
2165int64_t cs_to64(
const char *s) {
2168 while (*s && isspace((
unsigned char) *s)) s++;
2173 while (isdigit((
unsigned char) *s)) {
2175 result += (*s -
'0');
2178 return result * neg;
2183 return tolower(*(
const unsigned char *) s);
2192 }
while (diff == 0 && s1[-1] !=
'\0' && --
len > 0);
2212int mg_avprintf(
char **buf,
size_t size,
const char *fmt, va_list ap)
WEAK;
2213int mg_avprintf(
char **buf,
size_t size,
const char *fmt, va_list ap) {
2217 va_copy(ap_copy, ap);
2218 len = vsnprintf(*buf, size, fmt, ap_copy);
2232 if ((*buf = (
char *)
MG_MALLOC(size)) == NULL) {
2236 va_copy(ap_copy, ap);
2237 len = vsnprintf(*buf, size - 1, fmt, ap_copy);
2247 }
else if (
len >= (
int) size) {
2252 va_copy(ap_copy, ap);
2253 len = vsnprintf(*buf,
len + 1, fmt, ap_copy);
2273 if (
list.len == 0) {
2277 const char *chr = NULL;
2280 if ((chr =
mg_strchr(*val,
',')) != NULL) {
2282 val->
len = chr - val->
p;
2291 if (eq_val != NULL) {
2295 eq_val->p = (
const char *) memchr(val->
p,
'=', val->
len);
2296 if (eq_val->p != NULL) {
2298 eq_val->len = val->
p + val->
len - eq_val->p;
2299 val->
len = (eq_val->p - val->
p) - 1;
2310 size_t res = 0,
len = 0,
i = 0,
j = 0;
2312 if ((or_str = (
const char *) memchr(pattern.
p,
'|', pattern.
len)) != NULL ||
2313 (or_str = (
const char *) memchr(pattern.
p,
',', pattern.
len)) != NULL) {
2314 struct mg_str pstr = {pattern.
p, (size_t)(or_str - pattern.
p)};
2316 if (res > 0)
return res;
2317 pstr.
p = or_str + 1;
2318 pstr.
len = (pattern.
p + pattern.
len) - (or_str + 1);
2322 for (;
i < pattern.
len &&
j <
str.len;
i++,
j++) {
2323 if (pattern.
p[
i] ==
'?') {
2325 }
else if (pattern.
p[
i] ==
'*') {
2327 if (
i < pattern.
len && pattern.
p[
i] ==
'*') {
2334 if (
i == pattern.
len || (pattern.
p[
i] ==
'$' &&
i == pattern.
len - 1))
2337 const struct mg_str pstr = {pattern.
p +
i, pattern.
len -
i};
2340 }
while (res == 0 &&
len != 0 &&
len-- > 0);
2341 return res == 0 ? 0 :
j + res +
len;
2347 if (
i < pattern.
len && pattern.
p[
i] ==
'$') {
2348 return j ==
str.len ?
str.len : 0;
2350 return i == pattern.
len ?
j : 0;
2355 const struct mg_str pstr = {pattern, (size_t) pattern_len};
2362#ifdef MG_MODULE_LINES
2363#line 1 "mongoose/src/mg_net.c"
2389#define MG_MAX_HOST_LEN 200
2391#ifndef MG_TCP_IO_SIZE
2392#define MG_TCP_IO_SIZE 1460
2394#ifndef MG_UDP_IO_SIZE
2395#define MG_UDP_IO_SIZE 1460
2398#define MG_COPY_COMMON_CONNECTION_OPTIONS(dst, src) \
2399 memcpy(dst, src, sizeof(*dst));
2402#define _MG_ALLOWED_CONNECT_FLAGS_MASK \
2403 (MG_F_USER_1 | MG_F_USER_2 | MG_F_USER_3 | MG_F_USER_4 | MG_F_USER_5 | \
2404 MG_F_USER_6 | MG_F_WEBSOCKET_NO_DEFRAG | MG_F_ENABLE_BROADCAST)
2406#define _MG_CALLBACK_MODIFIABLE_FLAGS_MASK \
2407 (MG_F_USER_1 | MG_F_USER_2 | MG_F_USER_3 | MG_F_USER_4 | MG_F_USER_5 | \
2408 MG_F_USER_6 | MG_F_WEBSOCKET_NO_DEFRAG | MG_F_SEND_AND_CLOSE | \
2409 MG_F_CLOSE_IMMEDIATELY | MG_F_IS_WEBSOCKET | MG_F_DELETE_CHUNK)
2412#define intptr_t long
2416 DBG((
"%p %p", mgr,
c));
2438 if (ev_handler == NULL) {
2446 DBG((
"%p %s ev=%d ev_data=%p flags=0x%lx rmbl=%d smbl=%d", nc,
2447 ev_handler == nc->
handler ?
"user" :
"proto", ev, ev_data, nc->
flags,
2451#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
2457 if (ev_handler != NULL) {
2458 unsigned long flags_before = nc->
flags;
2459 ev_handler(nc, ev, ev_data
MG_UD_ARG(user_data));
2461 if (ev_handler == nc->
handler && nc->
flags != flags_before) {
2462 nc->
flags = (flags_before & ~_MG_CALLBACK_MODIFIABLE_FLAGS_MASK) |
2468 DBG((
"%p after %s flags=0x%lx rmbl=%d smbl=%d", nc,
2469 ev_handler == nc->
handler ?
"user" :
"proto", nc->
flags,
2472#if !MG_ENABLE_CALLBACK_USERDATA
2478 if (
c->ev_timer_time > 0 && now >=
c->ev_timer_time) {
2479 double old_value =
c->ev_timer_time;
2480 c->ev_timer_time = 0;
2489 return avail > max ? max : avail;
2517 }
while (recved > 0);
2522 time_t now_t = (time_t) now;
2537 mg_ssl_if_conn_free(conn);
2542 memset(conn, 0,
sizeof(*conn));
2556 mg_ssl_if_conn_close_notify(conn);
2572 memset(&opts, 0,
sizeof(opts));
2578 memset(m, 0,
sizeof(*m));
2579#if MG_ENABLE_BROADCAST
2587 WSAStartup(MAKEWORD(2, 2), &
data);
2589#elif defined(__unix__)
2592 signal(SIGPIPE, SIG_IGN);
2615 DBG((
"=================================="));
2616 DBG((
"init mgr=%p", m));
2619 static int init_done;
2632 if (m == NULL)
return;
2636#if MG_ENABLE_BROADCAST
2643 tmp_conn = conn->
next;
2667 return (m->
num_calls - num_calls_before);
2677 if (
buf != mem &&
buf != NULL) {
2693#if MG_ENABLE_SYNC_RESOLVER
2695static int mg_resolve2(
const char *host,
struct in_addr *ina) {
2696#if MG_ENABLE_GETADDRINFO
2698 struct addrinfo hints, *servinfo, *p;
2699 struct sockaddr_in *h = NULL;
2700 memset(&hints, 0,
sizeof hints);
2701 hints.ai_family = AF_INET;
2702 hints.ai_socktype = SOCK_STREAM;
2703 if ((rv = getaddrinfo(host, NULL, NULL, &servinfo)) != 0) {
2707 for (p = servinfo; p != NULL; p = p->ai_next) {
2708 memcpy(&h, &p->ai_addr,
sizeof(
struct sockaddr_in *));
2709 memcpy(ina, &h->sin_addr,
sizeof(ina));
2711 freeaddrinfo(servinfo);
2715 if ((he = gethostbyname(host)) == NULL) {
2716 DBG((
"gethostbyname(%s) failed: %s", host, strerror(
mg_get_errno())));
2718 memcpy(ina, he->h_addr_list[0],
sizeof(*ina));
2725int mg_resolve(
const char *host,
char *buf,
size_t n) {
2788 int *proto,
char *host,
size_t host_len) {
2789 unsigned int a, b,
c,
d, port = 0;
2800 memset(
sa, 0,
sizeof(*
sa));
2801 sa->
sin.sin_family = AF_INET;
2803 *proto = SOCK_STREAM;
2805 if (strncmp(
str,
"udp://", 6) == 0) {
2807 *proto = SOCK_DGRAM;
2808 }
else if (strncmp(
str,
"tcp://", 6) == 0) {
2812 if (sscanf(
str,
"%u.%u.%u.%u:%u%n", &a, &b, &
c, &
d, &port, &len) == 5) {
2814 sa->
sin.sin_addr.s_addr =
2815 htonl(((uint32_t) a << 24) | ((uint32_t) b << 16) |
c << 8 |
d);
2816 sa->
sin.sin_port = htons((uint16_t) port);
2818 }
else if (sscanf(
str,
"[%99[^]]]:%u%n",
buf, &port, &len) == 2 &&
2821 sa->
sin6.sin6_family = AF_INET6;
2822 sa->
sin.sin_port = htons((uint16_t) port);
2824#if MG_ENABLE_ASYNC_RESOLVER
2825 }
else if (strlen(
str) < host_len &&
2826 sscanf(
str,
"%[^ :]:%u%n", host, &port, &len) == 2) {
2827 sa->
sin.sin_port = htons((uint16_t) port);
2839#if MG_ENABLE_SYNC_RESOLVER
2848 }
else if (sscanf(
str,
":%u%n", &port, &len) == 1 ||
2849 sscanf(
str,
"%u%n", &port, &len) == 1) {
2851 sa->
sin.sin_port = htons((uint16_t) port);
2861 return port < 0xffffUL && (ch ==
'\0' || ch ==
',' || isspace(ch)) ? len : -1;
2867 int server_side = (nc->
listener != NULL);
2868 enum mg_ssl_if_result res;
2870 res = mg_ssl_if_handshake(nc);
2872 if (res == MG_SSL_OK) {
2880 }
else if (res == MG_SSL_WANT_READ) {
2882 }
else if (res == MG_SSL_WANT_WRITE) {
2897 memset(&opts, 0,
sizeof(opts));
2899 if (nc == NULL)
return NULL;
2919 if (mg_ssl_if_conn_accept(nc, nc->
listener) == MG_SSL_OK) {
2920 mg_ssl_handshake(nc);
2977 n = mg_ssl_if_read(nc,
buf, len);
2978 DBG((
"%p <- %d bytes (SSL)", nc,
n));
2980 if (
n == MG_SSL_WANT_READ) {
2987 nc->
flags &= ~MG_F_WANT_READ;
2990 mg_ssl_handshake(nc);
2996 DBG((
"%p <- %d bytes", nc,
n));
3001#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
3019 size_t sa_len =
sizeof(
sa);
3032 if (memcmp(&nc->
sa.
sa, &
sa.sa, sa_len) == 0 && nc->
listener == lc) {
3038 memset(&opts, 0,
sizeof(opts));
3068 ntohs(nc->
sa.
sin.sin_port)));
3076#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
3107 n = mg_ssl_if_write(nc, buf, len);
3108 DBG((
"%p -> %d bytes (SSL)", nc,
n));
3111 if (
n == MG_SSL_WANT_WRITE) {
3118 nc->
flags &= ~MG_F_WANT_WRITE;
3121 mg_ssl_handshake(nc);
3131 DBG((
"%p -> %d bytes", nc,
n));
3134#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
3158 LOG(
LL_DEBUG, (
"%p %s://%s:%hu", nc, proto == SOCK_DGRAM ?
"udp" :
"tcp",
3162 if (proto == SOCK_DGRAM) {
3173 (
"%p %s://%s:%hu -> %d", nc, (nc->
flags &
MG_F_UDP ?
"udp" :
"tcp"),
3175 nc->
flags &= ~MG_F_CONNECTING;
3181 mg_ssl_handshake(nc);
3189#if MG_ENABLE_ASYNC_RESOLVER
3202 nc->
flags &= ~MG_F_RESOLVING;
3240 memset(&opts, 0,
sizeof(opts));
3269#if MG_ENABLE_CALLBACK_USERDATA
3277 (
"%p %s %s,%s,%s", nc, address, (opts.ssl_cert ? opts.ssl_cert :
"-"),
3278 (opts.ssl_key ? opts.ssl_key :
"-"),
3279 (opts.ssl_ca_cert ? opts.ssl_ca_cert :
"-")));
3281 if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL ||
3282 opts.ssl_psk_identity != NULL) {
3283 const char *err_msg = NULL;
3284 struct mg_ssl_if_conn_params params;
3290 memset(¶ms, 0,
sizeof(params));
3291 params.cert = opts.ssl_cert;
3292 params.key = opts.ssl_key;
3293 params.ca_cert = opts.ssl_ca_cert;
3294 params.cipher_suites = opts.ssl_cipher_suites;
3295 params.psk_identity = opts.ssl_psk_identity;
3296 params.psk_key = opts.ssl_psk_key;
3297 if (opts.ssl_ca_cert != NULL) {
3298 if (opts.ssl_server_name != NULL) {
3299 if (strcmp(opts.ssl_server_name,
"*") != 0) {
3300 params.server_name = opts.ssl_server_name;
3302 }
else if (rc == 0) {
3303 params.server_name = host;
3306 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
3316#if MG_ENABLE_ASYNC_RESOLVER
3323 memset(&o, 0,
sizeof(o));
3350 memset(&opts, 0,
sizeof(opts));
3364#if MG_ENABLE_CALLBACK_USERDATA
3390 DBG((
"%p %s %s,%s,%s", nc, address, (opts.ssl_cert ? opts.ssl_cert :
"-"),
3391 (opts.ssl_key ? opts.ssl_key :
"-"),
3392 (opts.ssl_ca_cert ? opts.ssl_ca_cert :
"-")));
3394 if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
3395 const char *err_msg = NULL;
3396 struct mg_ssl_if_conn_params params;
3402 memset(¶ms, 0,
sizeof(params));
3403 params.cert = opts.ssl_cert;
3404 params.key = opts.ssl_key;
3405 params.ca_cert = opts.ssl_ca_cert;
3406 params.cipher_suites = opts.ssl_cipher_suites;
3407 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
3422 DBG((
"Failed to open listener: %d", rc));
3436#if MG_ENABLE_BROADCAST
3463 return n >= 0 &&
n <= 255;
3467 int n, a, b,
c,
d, slash = 32, len = 0;
3469 if ((sscanf(spec,
"%d.%d.%d.%d/%d%n", &a, &b, &
c, &
d, &slash, &
n) == 5 ||
3470 sscanf(spec,
"%d.%d.%d.%d%n", &a, &b, &
c, &
d, &
n) == 4) &&
3475 ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t)
c << 8) |
d;
3476 *
mask = slash ? 0xffffffffU << (32 - slash) : 0;
3488 allowed = (acl == NULL || *acl ==
'\0') ?
'+' :
'-';
3492 if ((flag !=
'+' && flag !=
'-') ||
3497 if (net == (remote_ip &
mask)) {
3502 DBG((
"%08x %c", (
unsigned int) remote_ip, allowed));
3503 return allowed ==
'+';
3513 double result =
c->ev_timer_time;
3514 c->ev_timer_time = timestamp;
3521 (
unsigned long) timestamp));
3543#if MG_ENABLE_CALLBACK_USERDATA
3559 memset(&opts, 0,
sizeof(opts));
3566#ifdef MG_MODULE_LINES
3567#line 1 "mongoose/src/mg_net_if_socket.h"
3574#ifndef CS_MONGOOSE_SRC_NET_IF_SOCKET_H_
3575#define CS_MONGOOSE_SRC_NET_IF_SOCKET_H_
3583#ifndef MG_ENABLE_NET_IF_SOCKET
3584#define MG_ENABLE_NET_IF_SOCKET MG_NET_IF == MG_NET_IF_SOCKET
3594#ifdef MG_MODULE_LINES
3595#line 1 "mongoose/src/mg_net_if_socks.h"
3602#ifndef CS_MONGOOSE_SRC_NET_IF_SOCKS_H_
3603#define CS_MONGOOSE_SRC_NET_IF_SOCKS_H_
3619#ifdef MG_MODULE_LINES
3620#line 1 "mongoose/src/mg_net_if.c"
3665 double min_timer = 0;
3675#ifdef MG_MODULE_LINES
3676#line 1 "mongoose/src/mg_net_if_null.c"
3794 return (time_t) now;
3804#define MG_NULL_IFACE_VTABLE \
3806 mg_null_if_init, mg_null_if_free, mg_null_if_add_conn, \
3807 mg_null_if_remove_conn, mg_null_if_poll, mg_null_if_listen_tcp, \
3808 mg_null_if_listen_udp, mg_null_if_connect_tcp, mg_null_if_connect_udp, \
3809 mg_null_if_tcp_send, mg_null_if_udp_send, mg_null_if_tcp_recv, \
3810 mg_null_if_udp_recv, mg_null_if_create_conn, mg_null_if_destroy_conn, \
3811 mg_null_if_sock_set, mg_null_if_get_conn_addr, \
3816#if MG_NET_IF == MG_NET_IF_NULL
3819#ifdef MG_MODULE_LINES
3820#line 1 "mongoose/src/mg_net_if_socket.c"
3827#if MG_ENABLE_NET_IF_SOCKET
3838 unsigned long on = 1;
3839 ioctlsocket(sock, FIONBIO, &on);
3841 int flags = fcntl(sock, F_GETFL, 0);
3842 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
3848 return err != EINPROGRESS && err != EWOULDBLOCK
3850 && err != EAGAIN && err != EINTR
3853 && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK
3861 nc->
sock =
socket(AF_INET, SOCK_STREAM, proto);
3866#if !defined(MG_ESP8266)
3869 rc = connect(nc->
sock, &sa->
sa,
sizeof(sa->
sin));
3883 if (setsockopt(nc->
sock, SOL_SOCKET, SO_BROADCAST, (
const char *) &optval,
3884 sizeof(optval)) < 0) {
3920 int n = sendto(nc->
sock, buf, len, 0, &nc->
sa.
sa,
sizeof(nc->
sa.
sin));
3940 socklen_t sa_len_st = *sa_len;
3941 int n = recvfrom(nc->
sock, buf, len, 0, &sa->
sa, &sa_len_st);
3942 *sa_len = sa_len_st;
3966 socklen_t sa_len =
sizeof(
sa);
3968 sock_t sock = accept(lc->
sock, &
sa.sa, &sa_len);
3981 ntohs(
sa.sin.sin_port)));
3991 (
sa->sa.sa_family == AF_INET) ?
sizeof(
sa->sin) :
sizeof(
sa->sin6);
3999#
if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) && !defined(WINCE)
4001 !setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (
void *) &on,
4005#if !defined(_WIN32) || !defined(SO_EXCLUSIVEADDRUSE)
4015 !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
void *) &on,
sizeof(on)) &&
4019 !bind(sock, &
sa->sa, sa_len) &&
4024 (void) getsockname(sock, &
sa->sa, &sa_len);
4034#define _MG_F_FD_CAN_READ 1
4035#define _MG_F_FD_CAN_WRITE 1 << 1
4036#define _MG_F_FD_ERROR 1 << 2
4041 if (worth_logging) {
4042 DBG((
"%p fd=%d fd_flags=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock,
4050 if (fd_flags != 0) {
4052#if !defined(MG_ESP8266)
4054 socklen_t len =
sizeof(err);
4056 getsockopt(nc->
sock, SOL_SOCKET, SO_ERROR, (
char *) &err, &len);
4059 }
else if (err == EAGAIN || err == EWOULDBLOCK) {
4070 }
else if (nc->
err != 0) {
4094 if (worth_logging) {
4095 DBG((
"%p after fd=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock,
4100#if MG_ENABLE_BROADCAST
4106 DBG((
"read %d from ctl socket", len));
4129#if MG_ENABLE_BROADCAST
4165 fd_set read_set, write_set, err_set;
4167 int num_fds, num_ev, num_timers = 0;
4173 FD_ZERO(&write_set);
4175#if MG_ENABLE_BROADCAST
4193 int new_sock = dup(nc->
sock);
4194 if (new_sock >= 0) {
4197 DBG((
"new sock %d -> %d", nc->
sock, new_sock));
4198 nc->
sock = new_sock;
4201 DBG((
"new sock is still larger than FD_SETSIZE, disregard"));
4234 if (num_timers > 0) {
4235 double timer_timeout_ms = (min_timer -
mg_time()) * 1000 + 1 ;
4236 if (timer_timeout_ms < timeout_ms) {
4237 timeout_ms = (int) timer_timeout_ms;
4240 if (timeout_ms < 0) timeout_ms = 0;
4242 tv.tv_sec = timeout_ms / 1000;
4243 tv.tv_usec = (timeout_ms % 1000) * 1000;
4245 num_ev = select((
int) max_fd + 1, &read_set, &write_set, &err_set, &
tv);
4248 DBG((
"select @ %ld num_ev=%d of %d, timeout=%d", (
long) now, num_ev, num_fds,
4252#if MG_ENABLE_BROADCAST
4254 FD_ISSET(mgr->
ctl[1], &read_set)) {
4263 fd_flags = (FD_ISSET(nc->
sock, &read_set) &&
4281 return (time_t) now;
4284#if MG_ENABLE_BROADCAST
4285MG_INTERNAL void mg_socketpair_close(sock_t *sock) {
4287 if (
closesocket(*sock) == -1 && errno == EINTR)
continue;
4294mg_socketpair_accept(sock_t sock,
union socket_address *sa, socklen_t sa_len) {
4308 socklen_t len =
sizeof(
sa.sin);
4313 (void) memset(&
sa, 0,
sizeof(
sa));
4314 sa.
sin.sin_family = AF_INET;
4315 sa.sin.sin_addr.s_addr = htonl(0x7f000001);
4319 }
else if (bind(sock, &
sa.sa, len) != 0) {
4320 }
else if (sock_type == SOCK_STREAM && listen(sock, 1) != 0) {
4321 }
else if (getsockname(sock, &
sa.sa, &len) != 0) {
4323 }
else if (sock_type == SOCK_STREAM && connect(sp[0], &
sa.sa, len) != 0) {
4324 }
else if (sock_type == SOCK_DGRAM &&
4325 (bind(sp[0], &sa2.sa, len) != 0 ||
4326 getsockname(sp[0], &sa2.sa, &len) != 0 ||
4327 connect(sp[0], &
sa.sa, len) != 0 ||
4328 connect(sock, &sa2.sa, len) != 0)) {
4329 }
else if ((sp[1] = (sock_type == SOCK_DGRAM ? sock : mg_socketpair_accept(
4330 sock, &
sa, len))) ==
4335 if (sock_type == SOCK_STREAM) mg_socketpair_close(&sock);
4351 socklen_t slen =
sizeof(*sa);
4352 memset(
sa, 0, slen);
4354 getpeername(sock, &
sa->sa, &slen);
4356 getsockname(sock, &
sa->sa, &slen);
4369 memcpy(
sa, &nc->
sa,
sizeof(*
sa));
4376#define MG_SOCKET_IFACE_VTABLE \
4378 mg_socket_if_init, \
4379 mg_socket_if_free, \
4380 mg_socket_if_add_conn, \
4381 mg_socket_if_remove_conn, \
4382 mg_socket_if_poll, \
4383 mg_socket_if_listen_tcp, \
4384 mg_socket_if_listen_udp, \
4385 mg_socket_if_connect_tcp, \
4386 mg_socket_if_connect_udp, \
4387 mg_socket_if_tcp_send, \
4388 mg_socket_if_udp_send, \
4389 mg_socket_if_tcp_recv, \
4390 mg_socket_if_udp_recv, \
4391 mg_socket_if_create_conn, \
4392 mg_socket_if_destroy_conn, \
4393 mg_socket_if_sock_set, \
4394 mg_socket_if_get_conn_addr, \
4399#if MG_NET_IF == MG_NET_IF_SOCKET
4404#ifdef MG_MODULE_LINES
4405#line 1 "mongoose/src/mg_net_if_socks.c"
4420static void socks_if_disband(
struct socksdata *
d) {
4424 d->c->user_data = NULL;
4429 d->s->user_data = NULL;
4435 struct socksdata *
d = (
struct socksdata *) s->
user_data;
4436 if (
d == NULL ||
d->c == NULL || !(s->flags & MG_SOCKS_CONNECT_DONE) ||
4444static void socks_if_handler(
struct mg_connection *
c,
int ev,
void *ev_data) {
4445 struct socksdata *
d = (
struct socksdata *)
c->user_data;
4446 if (
d == NULL)
return;
4448 int res = *(
int *) ev_data;
4451 unsigned char buf[] = {MG_SOCKS_VERSION, 1, MG_SOCKS_HANDSHAKE_NOAUTH};
4453 LOG(
LL_DEBUG, (
"Sent handshake to %s",
d->proxy_addr));
4455 LOG(
LL_ERROR, (
"Cannot connect to %s: %d",
d->proxy_addr, res));
4459 socks_if_disband(
d);
4462 if (!(
c->flags & MG_SOCKS_HANDSHAKE_DONE)) {
4464 unsigned char buf[10] = {MG_SOCKS_VERSION, MG_SOCKS_CMD_CONNECT, 0,
4465 MG_SOCKS_ADDR_IPV4};
4466 if (
c->recv_mbuf.len < 2)
return;
4467 if ((
unsigned char)
c->recv_mbuf.buf[1] == MG_SOCKS_HANDSHAKE_FAILURE) {
4469 socks_if_disband(
d);
4473 c->flags |= MG_SOCKS_HANDSHAKE_DONE;
4476 memcpy(buf + 4, &
d->c->sa.sin.sin_addr, 4);
4477 memcpy(buf + 8, &
d->c->sa.sin.sin_port, 2);
4482 if ((
c->flags & MG_SOCKS_HANDSHAKE_DONE) &&
4483 !(
c->flags & MG_SOCKS_CONNECT_DONE)) {
4484 if (
c->recv_mbuf.len < 10)
return;
4485 if (
c->recv_mbuf.buf[1] != MG_SOCKS_SUCCESS) {
4486 LOG(
LL_ERROR, (
"Socks connection error: %d",
c->recv_mbuf.buf[1]));
4487 socks_if_disband(
d);
4491 c->flags |= MG_SOCKS_CONNECT_DONE;
4503 struct socksdata *
d = (
struct socksdata *)
c->iface->data;
4506 d->s->user_data =
d;
4529static int mg_socks_if_tcp_send(
struct mg_connection *
c,
const void *buf,
4532 struct socksdata *
d = (
struct socksdata *)
c->iface->data;
4533 if (
d->s == NULL)
return -1;
4535 DBG((
"%p -> %d -> %p",
c, res,
d->s));
4539static int mg_socks_if_udp_send(
struct mg_connection *
c,
const void *buf,
4547int mg_socks_if_tcp_recv(
struct mg_connection *
c,
void *buf,
size_t len) {
4548 struct socksdata *
d = (
struct socksdata *)
c->iface->data;
4549 if (
d->s == NULL)
return -1;
4550 if (len >
d->s->recv_mbuf.len) len =
d->s->recv_mbuf.len;
4552 memcpy(buf,
d->s->recv_mbuf.buf, len);
4555 DBG((
"%p <- %d <- %p",
c, (
int) len,
d->s));
4559int mg_socks_if_udp_recv(
struct mg_connection *
c,
void *buf,
size_t len,
4575 c->iface->vtable->free(
c->iface);
4581static void mg_socks_if_sock_set(
struct mg_connection *
c, sock_t sock) {
4586static void mg_socks_if_init(
struct mg_iface *iface) {
4590static void mg_socks_if_free(
struct mg_iface *iface) {
4591 struct socksdata *
d = (
struct socksdata *) iface->
data;
4594 socks_if_disband(
d);
4609static time_t mg_socks_if_poll(
struct mg_iface *iface,
int timeout_ms) {
4616static void mg_socks_if_get_conn_addr(
struct mg_connection *
c,
int remote,
4625 mg_socks_if_init, mg_socks_if_free,
4626 mg_socks_if_add_conn, mg_socks_if_remove_conn,
4627 mg_socks_if_poll, mg_socks_if_listen_tcp,
4628 mg_socks_if_listen_udp, mg_socks_if_connect_tcp,
4629 mg_socks_if_connect_udp, mg_socks_if_tcp_send,
4630 mg_socks_if_udp_send, mg_socks_if_tcp_recv,
4631 mg_socks_if_udp_recv, mg_socks_if_create_conn,
4632 mg_socks_if_destroy_conn, mg_socks_if_sock_set,
4633 mg_socks_if_get_conn_addr,
4639 ((
struct socksdata *) iface->
data)->proxy_addr = strdup(proxy_addr);
4644#ifdef MG_MODULE_LINES
4645#line 1 "mongoose/src/mg_ssl_if_openssl.c"
4652#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_OPENSSL
4655#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
4658#include <openssl/ssl.h>
4660#include <openssl/tls1.h>
4663struct mg_ssl_if_ctx {
4667 size_t identity_len;
4670void mg_ssl_if_init() {
4674enum mg_ssl_if_result mg_ssl_if_conn_accept(
struct mg_connection *nc,
4676 struct mg_ssl_if_ctx *ctx =
4677 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
4678 struct mg_ssl_if_ctx *lc_ctx = (
struct mg_ssl_if_ctx *) lc->ssl_if_data;
4679 nc->ssl_if_data = ctx;
4680 if (ctx == NULL || lc_ctx == NULL)
return MG_SSL_ERROR;
4681 ctx->ssl_ctx = lc_ctx->ssl_ctx;
4682 if ((ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
4683 return MG_SSL_ERROR;
4688static enum mg_ssl_if_result mg_use_cert(
SSL_CTX *ctx,
const char *cert,
4689 const char *
key,
const char **err_msg);
4690static enum mg_ssl_if_result mg_use_ca_cert(
SSL_CTX *ctx,
const char *cert);
4691static enum mg_ssl_if_result mg_set_cipher_list(
SSL_CTX *ctx,
const char *cl);
4692static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(
struct mg_ssl_if_ctx *ctx,
4693 const char *identity,
4694 const char *key_str);
4696enum mg_ssl_if_result mg_ssl_if_conn_init(
4697 struct mg_connection *nc,
const struct mg_ssl_if_conn_params *params,
4698 const char **err_msg) {
4699 struct mg_ssl_if_ctx *ctx =
4700 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
4701 DBG((
"%p %s,%s,%s", nc, (params->cert ? params->cert :
""),
4702 (params->
key ? params->
key :
""),
4703 (params->ca_cert ? params->ca_cert :
"")));
4706 return MG_SSL_ERROR;
4708 nc->ssl_if_data = ctx;
4710 ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
4712 ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
4714 if (ctx->ssl_ctx == NULL) {
4716 return MG_SSL_ERROR;
4721 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2);
4722 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv3);
4723 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1);
4724#ifdef MG_SSL_OPENSSL_NO_COMPRESSION
4725 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_COMPRESSION);
4727#ifdef MG_SSL_OPENSSL_CIPHER_SERVER_PREFERENCE
4728 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
4734 if (params->cert != NULL &&
4735 mg_use_cert(ctx->ssl_ctx, params->cert, params->key, err_msg) !=
4737 return MG_SSL_ERROR;
4740 if (params->ca_cert != NULL &&
4741 mg_use_ca_cert(ctx->ssl_ctx, params->ca_cert) != MG_SSL_OK) {
4743 return MG_SSL_ERROR;
4746 if (mg_set_cipher_list(ctx->ssl_ctx, params->cipher_suites) != MG_SSL_OK) {
4748 return MG_SSL_ERROR;
4752 if (mg_ssl_if_ossl_set_psk(ctx, params->psk_identity, params->psk_key) !=
4755 return MG_SSL_ERROR;
4759 (ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
4761 return MG_SSL_ERROR;
4764 if (params->server_name != NULL) {
4766 SSL_CTX_kr_set_verify_name(ctx->ssl_ctx, params->server_name);
4768 SSL_set_tlsext_host_name(ctx->ssl, params->server_name);
4777static enum mg_ssl_if_result mg_ssl_if_ssl_err(
struct mg_connection *nc,
4779 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
4780 int err = SSL_get_error(ctx->ssl, res);
4781 if (err == SSL_ERROR_WANT_READ)
return MG_SSL_WANT_READ;
4782 if (err == SSL_ERROR_WANT_WRITE)
return MG_SSL_WANT_WRITE;
4783 DBG((
"%p %p SSL error: %d %d", nc, ctx->ssl_ctx, res, err));
4785 return MG_SSL_ERROR;
4788enum mg_ssl_if_result mg_ssl_if_handshake(
struct mg_connection *nc) {
4789 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
4790 int server_side = (nc->
listener != NULL);
4793 if (SSL_get_fd(ctx->ssl) < 0) {
4794 if (SSL_set_fd(ctx->ssl, nc->
sock) != 1)
return MG_SSL_ERROR;
4796 res = server_side ? SSL_accept(ctx->ssl) : SSL_connect(ctx->ssl);
4797 if (res != 1)
return mg_ssl_if_ssl_err(nc, res);
4801int mg_ssl_if_read(
struct mg_connection *nc,
void *buf,
size_t buf_size) {
4802 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
4803 int n = SSL_read(ctx->ssl, buf, buf_size);
4804 DBG((
"%p %d -> %d", nc, (
int) buf_size,
n));
4805 if (
n < 0)
return mg_ssl_if_ssl_err(nc,
n);
4811 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
4812 int n = SSL_write(ctx->ssl,
data, len);
4813 DBG((
"%p %d -> %d", nc, (
int) len,
n));
4814 if (
n <= 0)
return mg_ssl_if_ssl_err(nc,
n);
4819 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
4820 if (ctx == NULL)
return;
4821 SSL_shutdown(ctx->ssl);
4825 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
4826 if (ctx == NULL)
return;
4827 nc->ssl_if_data = NULL;
4828 if (ctx->ssl != NULL) SSL_free(ctx->ssl);
4829 if (ctx->ssl_ctx != NULL && nc->
listener == NULL) SSL_CTX_free(ctx->ssl_ctx);
4831 memset(ctx, 0,
sizeof(*ctx));
4839static const char mg_s_cipher_list[] =
4840#if defined(MG_SSL_CRYPTO_MODERN)
4841 "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:"
4842 "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:"
4843 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
4844 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
4845 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
4846 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
4847 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
4848 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:"
4849 "!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"
4850#elif defined(MG_SSL_CRYPTO_OLD)
4851 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
4852 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
4853 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
4854 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
4855 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
4856 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
4857 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
4858 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:"
4859 "ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:"
4860 "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:"
4861 "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:"
4862 "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
4864 "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:"
4865 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"
4866 "DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:"
4867 "ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:"
4868 "ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:"
4869 "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:"
4870 "DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:"
4871 "DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:"
4872 "AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:"
4873 "DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:"
4874 "!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"
4882#if !MG_DISABLE_PFS && !defined(KR_VERSION)
4883static const char mg_s_default_dh_params[] =
4885-----BEGIN DH PARAMETERS-----\n\
4886MIIBCAKCAQEAlvbgD/qh9znWIlGFcV0zdltD7rq8FeShIqIhkQ0C7hYFThrBvF2E\n\
4887Z9bmgaP+sfQwGpVlv9mtaWjvERbu6mEG7JTkgmVUJrUt/wiRzwTaCXBqZkdUO8Tq\n\
4888+E6VOEQAilstG90ikN1Tfo+K6+X68XkRUIlgawBTKuvKVwBhuvlqTGerOtnXWnrt\n\
4889ym//hd3cd5PBYGBix0i7oR4xdghvfR2WLVu0LgdThTBb6XP7gLd19cQ1JuBtAajZ\n\
4890wMuPn7qlUkEFDIkAZy59/Hue/H2Q2vU/JsvVhHWCQBL4F1ofEAt50il6ZxR1QfFK\n\
48919VGKDC4oOgm9DlxwwBoC2FjqmvQlqVV3kwIBAg==\n\
4892-----END DH PARAMETERS-----\n";
4895static enum mg_ssl_if_result mg_use_ca_cert(
SSL_CTX *ctx,
const char *cert) {
4896 if (cert == NULL || strcmp(cert,
"*") == 0) {
4899 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
4900 return SSL_CTX_load_verify_locations(ctx, cert, NULL) == 1 ? MG_SSL_OK
4904static enum mg_ssl_if_result mg_use_cert(
SSL_CTX *ctx,
const char *cert,
4906 const char **err_msg) {
4907 if (
key == NULL)
key = cert;
4908 if (cert == NULL || cert[0] ==
'\0' ||
key == NULL ||
key[0] ==
'\0') {
4910 }
else if (SSL_CTX_use_certificate_file(ctx, cert, 1) == 0) {
4912 return MG_SSL_ERROR;
4913 }
else if (SSL_CTX_use_PrivateKey_file(ctx,
key, 1) == 0) {
4915 return MG_SSL_ERROR;
4916 }
else if (SSL_CTX_use_certificate_chain_file(ctx, cert) == 0) {
4918 return MG_SSL_ERROR;
4920 SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
4921#if !MG_DISABLE_PFS && !defined(KR_VERSION)
4926 bio = BIO_new_file(cert,
"r");
4928 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4936 bio = BIO_new_mem_buf((
void *) mg_s_default_dh_params, -1);
4937 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4941 SSL_CTX_set_tmp_dh(ctx, dh);
4942 SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
4945#if OPENSSL_VERSION_NUMBER > 0x10002000L
4946 SSL_CTX_set_ecdh_auto(ctx, 1);
4953static enum mg_ssl_if_result mg_set_cipher_list(
SSL_CTX *ctx,
const char *cl) {
4954 return (SSL_CTX_set_cipher_list(ctx, cl ? cl : mg_s_cipher_list) == 1
4960static unsigned int mg_ssl_if_ossl_psk_cb(
SSL *ssl,
const char *hint,
4962 unsigned int max_identity_len,
4964 unsigned int max_psk_len) {
4965 struct mg_ssl_if_ctx *ctx =
4966 (
struct mg_ssl_if_ctx *) SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl));
4967 size_t key_len = ctx->psk.len - ctx->identity_len - 1;
4968 DBG((
"hint: '%s'", (hint ? hint :
"")));
4969 if (ctx->identity_len + 1 > max_identity_len) {
4970 DBG((
"identity too long"));
4973 if (key_len > max_psk_len) {
4974 DBG((
"key too long"));
4977 memcpy(identity, ctx->psk.buf, ctx->identity_len + 1);
4978 memcpy(psk, ctx->psk.buf + ctx->identity_len + 1, key_len);
4983static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(
struct mg_ssl_if_ctx *ctx,
4984 const char *identity,
4985 const char *key_str) {
4986 unsigned char key[32];
4989 if (identity == NULL && key_str == NULL)
return MG_SSL_OK;
4990 if (identity == NULL || key_str == NULL)
return MG_SSL_ERROR;
4991 key_len = strlen(key_str);
4992 if (key_len != 32 && key_len != 64)
return MG_SSL_ERROR;
4993 memset(
key, 0,
sizeof(
key));
4995 for (
i = 0; key_str[
i] !=
'\0';
i++) {
4997 char hc = tolower((
int) key_str[
i]);
4998 if (hc >=
'0' && hc <=
'9') {
5000 }
else if (hc >=
'a' && hc <=
'f') {
5003 return MG_SSL_ERROR;
5010 DBG((
"identity = '%s', key = (%u)", identity, (
unsigned int) key_len));
5011 ctx->identity_len = strlen(identity);
5012 mbuf_append(&ctx->psk, identity, ctx->identity_len + 1);
5014 SSL_CTX_set_psk_client_callback(ctx->ssl_ctx, mg_ssl_if_ossl_psk_cb);
5015 SSL_CTX_set_app_data(ctx->ssl_ctx, ctx);
5019static enum mg_ssl_if_result mg_ssl_if_ossl_set_psk(
struct mg_ssl_if_ctx *ctx,
5020 const char *identity,
5021 const char *key_str) {
5026 return MG_SSL_ERROR;
5031 const char *ca_cert) {
5032 const char *err_msg = NULL;
5033 struct mg_ssl_if_conn_params params;
5034 memset(¶ms, 0,
sizeof(params));
5036 params.ca_cert = ca_cert;
5037 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
5044#ifdef MG_MODULE_LINES
5045#line 1 "mongoose/src/mg_ssl_if_mbedtls.c"
5052#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_MBEDTLS
5054#include <mbedtls/debug.h>
5055#include <mbedtls/ecp.h>
5056#include <mbedtls/net.h>
5057#include <mbedtls/platform.h>
5058#include <mbedtls/ssl.h>
5059#include <mbedtls/ssl_internal.h>
5060#include <mbedtls/x509_crt.h>
5061#include <mbedtls/version.h>
5063static void mg_ssl_mbed_log(
void *ctx,
int level,
const char *
file,
int line,
5080 LOG(cs_level, (
"%p %.*s", ctx, (
int) (strlen(
str) - 1),
str));
5088struct mg_ssl_if_ctx {
5089 mbedtls_ssl_config *conf;
5090 mbedtls_ssl_context *ssl;
5091 mbedtls_x509_crt *cert;
5092 mbedtls_pk_context *
key;
5093 mbedtls_x509_crt *ca_cert;
5094 struct mbuf cipher_suites;
5099extern int mg_ssl_if_mbed_random(
void *ctx,
unsigned char *
buf,
size_t len);
5101void mg_ssl_if_init() {
5102 LOG(
LL_INFO, (
"%s", MBEDTLS_VERSION_STRING_FULL));
5105enum mg_ssl_if_result mg_ssl_if_conn_accept(
struct mg_connection *nc,
5107 struct mg_ssl_if_ctx *ctx =
5108 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
5109 struct mg_ssl_if_ctx *lc_ctx = (
struct mg_ssl_if_ctx *) lc->ssl_if_data;
5110 nc->ssl_if_data = ctx;
5111 if (ctx == NULL || lc_ctx == NULL)
return MG_SSL_ERROR;
5112 ctx->ssl = (mbedtls_ssl_context *)
MG_CALLOC(1,
sizeof(*ctx->ssl));
5113 if (mbedtls_ssl_setup(ctx->ssl, lc_ctx->conf) != 0) {
5114 return MG_SSL_ERROR;
5119static enum mg_ssl_if_result mg_use_cert(
struct mg_ssl_if_ctx *ctx,
5120 const char *cert,
const char *
key,
5121 const char **err_msg);
5122static enum mg_ssl_if_result mg_use_ca_cert(
struct mg_ssl_if_ctx *ctx,
5124static enum mg_ssl_if_result mg_set_cipher_list(
struct mg_ssl_if_ctx *ctx,
5125 const char *ciphers);
5126#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
5127static enum mg_ssl_if_result mg_ssl_if_mbed_set_psk(
struct mg_ssl_if_ctx *ctx,
5128 const char *identity,
5132enum mg_ssl_if_result mg_ssl_if_conn_init(
5133 struct mg_connection *nc,
const struct mg_ssl_if_conn_params *params,
5134 const char **err_msg) {
5135 struct mg_ssl_if_ctx *ctx =
5136 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
5137 DBG((
"%p %s,%s,%s", nc, (params->cert ? params->cert :
""),
5138 (params->
key ? params->
key :
""),
5139 (params->ca_cert ? params->ca_cert :
"")));
5143 return MG_SSL_ERROR;
5145 nc->ssl_if_data = ctx;
5146 ctx->conf = (mbedtls_ssl_config *)
MG_CALLOC(1,
sizeof(*ctx->conf));
5148 mbedtls_ssl_config_init(ctx->conf);
5149 mbedtls_ssl_conf_dbg(ctx->conf, mg_ssl_mbed_log, nc);
5150 if (mbedtls_ssl_config_defaults(
5152 : MBEDTLS_SSL_IS_CLIENT),
5153 MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
5155 return MG_SSL_ERROR;
5159 mbedtls_ssl_conf_min_version(ctx->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
5160 MBEDTLS_SSL_MINOR_VERSION_3);
5161 mbedtls_ssl_conf_rng(ctx->conf, mg_ssl_if_mbed_random, nc);
5163 if (params->cert != NULL &&
5164 mg_use_cert(ctx, params->cert, params->key, err_msg) != MG_SSL_OK) {
5165 return MG_SSL_ERROR;
5168 if (params->ca_cert != NULL &&
5169 mg_use_ca_cert(ctx, params->ca_cert) != MG_SSL_OK) {
5171 return MG_SSL_ERROR;
5174 if (mg_set_cipher_list(ctx, params->cipher_suites) != MG_SSL_OK) {
5176 return MG_SSL_ERROR;
5179#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
5180 if (mg_ssl_if_mbed_set_psk(ctx, params->psk_identity, params->psk_key) !=
5183 return MG_SSL_ERROR;
5188 ctx->ssl = (mbedtls_ssl_context *)
MG_CALLOC(1,
sizeof(*ctx->ssl));
5189 mbedtls_ssl_init(ctx->ssl);
5190 if (mbedtls_ssl_setup(ctx->ssl, ctx->conf) != 0) {
5192 return MG_SSL_ERROR;
5194 if (params->server_name != NULL &&
5195 mbedtls_ssl_set_hostname(ctx->ssl, params->server_name) != 0) {
5196 return MG_SSL_ERROR;
5200#ifdef MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN
5201 if (mbedtls_ssl_conf_max_frag_len(ctx->conf,
5202#
if MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 512
5203 MBEDTLS_SSL_MAX_FRAG_LEN_512
5204#elif MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 1024
5205 MBEDTLS_SSL_MAX_FRAG_LEN_1024
5206#elif MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 2048
5207 MBEDTLS_SSL_MAX_FRAG_LEN_2048
5208#elif MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN == 4096
5209 MBEDTLS_SSL_MAX_FRAG_LEN_4096
5211#error Invalid MG_SSL_IF_MBEDTLS_MAX_FRAG_LEN
5214 return MG_SSL_ERROR;
5223static int mg_ssl_if_mbed_send(
void *ctx,
const unsigned char *buf,
5227 if (
n > 0)
return n;
5228 if (
n == 0)
return MBEDTLS_ERR_SSL_WANT_WRITE;
5229 return MBEDTLS_ERR_NET_SEND_FAILED;
5232static int mg_ssl_if_mbed_recv(
void *
ctx,
unsigned char *
buf,
size_t len) {
5235 if (
n > 0)
return n;
5236 if (
n == 0)
return MBEDTLS_ERR_SSL_WANT_READ;
5237 return MBEDTLS_ERR_NET_RECV_FAILED;
5240static enum mg_ssl_if_result mg_ssl_if_mbed_err(
struct mg_connection *nc,
5242 enum mg_ssl_if_result res = MG_SSL_OK;
5243 if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
5244 res = MG_SSL_WANT_READ;
5245 }
else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
5246 res = MG_SSL_WANT_WRITE;
5247 }
else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
5248 LOG(
LL_DEBUG, (
"%p TLS connection closed by peer", nc));
5252 LOG(
LL_ERROR, (
"%p mbedTLS error: -0x%04x", nc, -ret));
5260static void mg_ssl_if_mbed_free_certs_and_keys(
struct mg_ssl_if_ctx *
ctx) {
5261 if (
ctx->cert != NULL) {
5262 mbedtls_x509_crt_free(
ctx->cert);
5265 mbedtls_pk_free(
ctx->key);
5269 if (
ctx->ca_cert != NULL) {
5270 mbedtls_ssl_conf_ca_chain(
ctx->conf, NULL, NULL);
5271#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
5272 if (
ctx->conf->ca_chain_file != NULL) {
5274 ctx->conf->ca_chain_file = NULL;
5277 mbedtls_x509_crt_free(
ctx->ca_cert);
5279 ctx->ca_cert = NULL;
5283enum mg_ssl_if_result mg_ssl_if_handshake(
struct mg_connection *nc) {
5284 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
5287 if (ctx->ssl->p_bio == NULL) {
5288 mbedtls_ssl_set_bio(ctx->ssl, nc, mg_ssl_if_mbed_send, mg_ssl_if_mbed_recv,
5291 err = mbedtls_ssl_handshake(ctx->ssl);
5292 if (err != 0)
return mg_ssl_if_mbed_err(nc, err);
5293#ifdef MG_SSL_IF_MBEDTLS_FREE_CERTS
5298 mbedtls_x509_crt_free(ctx->ssl->session->peer_cert);
5299 mbedtls_free(ctx->ssl->session->peer_cert);
5300 ctx->ssl->session->peer_cert = NULL;
5303 if (ctx->conf->key_cert != NULL) {
5306 ctx->conf->key_cert = NULL;
5308 mbedtls_ssl_conf_ca_chain(ctx->conf, NULL, NULL);
5309 mg_ssl_if_mbed_free_certs_and_keys(ctx);
5315int mg_ssl_if_read(
struct mg_connection *nc,
void *buf,
size_t len) {
5316 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
5317 int n = mbedtls_ssl_read(ctx->ssl, (
unsigned char *) buf, len);
5318 DBG((
"%p %d -> %d", nc, (
int) len,
n));
5319 if (
n < 0)
return mg_ssl_if_mbed_err(nc,
n);
5324int mg_ssl_if_write(
struct mg_connection *nc,
const void *buf,
size_t len) {
5325 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
5333 if (ctx->saved_len > 0 && ctx->saved_len < l) l = ctx->saved_len;
5334 int n = mbedtls_ssl_write(ctx->ssl, (
const unsigned char *) buf, l);
5335 DBG((
"%p %d,%d,%d -> %d", nc, (
int) len, (
int) ctx->saved_len, (
int) l,
n));
5337 if (
n == MBEDTLS_ERR_SSL_WANT_READ ||
n == MBEDTLS_ERR_SSL_WANT_WRITE) {
5338 ctx->saved_len = len;
5340 return mg_ssl_if_mbed_err(nc,
n);
5348 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
5349 if (ctx == NULL)
return;
5350 mbedtls_ssl_close_notify(ctx->ssl);
5354 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
5355 if (ctx == NULL)
return;
5356 nc->ssl_if_data = NULL;
5357 if (ctx->ssl != NULL) {
5358 mbedtls_ssl_free(ctx->ssl);
5361 mg_ssl_if_mbed_free_certs_and_keys(ctx);
5362 if (ctx->conf != NULL) {
5363 mbedtls_ssl_config_free(ctx->conf);
5367 memset(ctx, 0,
sizeof(*ctx));
5371static enum mg_ssl_if_result mg_use_ca_cert(
struct mg_ssl_if_ctx *ctx,
5372 const char *ca_cert) {
5373 if (ca_cert == NULL || strcmp(ca_cert,
"*") == 0) {
5374 mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_NONE);
5377 ctx->ca_cert = (mbedtls_x509_crt *)
MG_CALLOC(1,
sizeof(*ctx->ca_cert));
5378 mbedtls_x509_crt_init(ctx->ca_cert);
5379#ifdef MBEDTLS_X509_CA_CHAIN_ON_DISK
5380 ca_cert = strdup(ca_cert);
5381 mbedtls_ssl_conf_ca_chain_file(ctx->conf, ca_cert, NULL);
5383 if (mbedtls_x509_crt_parse_file(ctx->ca_cert, ca_cert) != 0) {
5384 return MG_SSL_ERROR;
5386 mbedtls_ssl_conf_ca_chain(ctx->conf, ctx->ca_cert, NULL);
5388 mbedtls_ssl_conf_authmode(ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
5392static enum mg_ssl_if_result mg_use_cert(
struct mg_ssl_if_ctx *ctx,
5393 const char *cert,
const char *
key,
5394 const char **err_msg) {
5395 if (
key == NULL)
key = cert;
5396 if (cert == NULL || cert[0] ==
'\0' ||
key == NULL ||
key[0] ==
'\0') {
5399 ctx->cert = (mbedtls_x509_crt *)
MG_CALLOC(1,
sizeof(*ctx->cert));
5400 mbedtls_x509_crt_init(ctx->cert);
5401 ctx->key = (mbedtls_pk_context *)
MG_CALLOC(1,
sizeof(*ctx->key));
5402 mbedtls_pk_init(ctx->key);
5403 if (mbedtls_x509_crt_parse_file(ctx->cert, cert) != 0) {
5405 return MG_SSL_ERROR;
5407 if (mbedtls_pk_parse_keyfile(ctx->key,
key, NULL) != 0) {
5409 return MG_SSL_ERROR;
5411 if (mbedtls_ssl_conf_own_cert(ctx->conf, ctx->cert, ctx->key) != 0) {
5413 return MG_SSL_ERROR;
5418static const int mg_s_cipher_list[] = {
5419#if CS_PLATFORM != CS_P_ESP8266
5420 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
5421 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
5422 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
5423 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
5424 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
5425 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
5426 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
5427 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
5428 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
5429 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
5430 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
5431 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
5432 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
5433 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
5434 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
5441 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
5442 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
5443 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
5444 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
5445 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
5446 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
5447 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
5448 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
5449 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
5450 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
5451 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
5452 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
5453 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
5464static enum mg_ssl_if_result mg_set_cipher_list(
struct mg_ssl_if_ctx *ctx,
5465 const char *ciphers) {
5466 if (ciphers != NULL) {
5468 const char *s = ciphers, *
e;
5472 l = (
e != NULL ? (
e - s) : (int) strlen(s));
5475 id = mbedtls_ssl_get_ciphersuite_id(tmp);
5476 DBG((
"%s -> %04x", tmp,
id));
5478 mbuf_append(&ctx->cipher_suites, &
id,
sizeof(
id));
5480 s = (
e != NULL ?
e + 1 : NULL);
5482 if (ctx->cipher_suites.len == 0)
return MG_SSL_ERROR;
5484 mbuf_append(&ctx->cipher_suites, &
id,
sizeof(
id));
5486 mbedtls_ssl_conf_ciphersuites(ctx->conf,
5487 (
const int *) ctx->cipher_suites.buf);
5489 mbedtls_ssl_conf_ciphersuites(ctx->conf, mg_s_cipher_list);
5494#ifdef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
5495static enum mg_ssl_if_result mg_ssl_if_mbed_set_psk(
struct mg_ssl_if_ctx *ctx,
5496 const char *identity,
5497 const char *key_str) {
5498 unsigned char key[32];
5500 if (identity == NULL && key_str == NULL)
return MG_SSL_OK;
5501 if (identity == NULL || key_str == NULL)
return MG_SSL_ERROR;
5502 key_len = strlen(key_str);
5503 if (key_len != 32 && key_len != 64)
return MG_SSL_ERROR;
5505 memset(
key, 0,
sizeof(
key));
5507 for (
i = 0; key_str[
i] !=
'\0';
i++) {
5509 char hc = tolower((
int) key_str[
i]);
5510 if (hc >=
'0' && hc <=
'9') {
5512 }
else if (hc >=
'a' && hc <=
'f') {
5515 return MG_SSL_ERROR;
5522 DBG((
"identity = '%s', key = (%u)", identity, (
unsigned int) key_len));
5524 if (mbedtls_ssl_conf_psk(ctx->conf, (
const unsigned char *)
key, key_len,
5525 (
const unsigned char *) identity,
5526 strlen(identity)) != 0) {
5527 return MG_SSL_ERROR;
5534 const char *ca_cert) {
5535 const char *err_msg = NULL;
5536 struct mg_ssl_if_conn_params params;
5537 memset(¶ms, 0,
sizeof(params));
5539 params.ca_cert = ca_cert;
5540 if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) {
5547#ifdef MG_SSL_MBED_DUMMY_RANDOM
5548int mg_ssl_if_mbed_random(
void *ctx,
unsigned char *buf,
size_t len) {
5550 while (len--) *buf++ = rand();
5556#ifdef MG_MODULE_LINES
5557#line 1 "mongoose/src/mg_uri.c"
5574 const char *seps,
struct mg_str *res) {
5577 for (; *p <
end; (*p)++) {
5578 for (
q = seps; *
q !=
'\0';
q++) {
5579 if (**p == *
q)
break;
5581 if (*
q !=
'\0')
break;
5583 res->
len = (*p) - res->
p;
5584 if (*p <
end) (*p)++;
5589 unsigned int *port,
struct mg_str *path,
struct mg_str *query,
5590 struct mg_str *fragment) {
5591 struct mg_str rscheme = {0, 0}, ruser_info = {0, 0}, rhost = {0, 0},
5592 rpath = {0, 0}, rquery = {0, 0}, rfragment = {0, 0};
5593 unsigned int rport = 0;
5603 const char *
p = uri.
p, *
end =
p + uri.
len;
5618 for (;
p <
end;
p++) {
5620 state = P_SCHEME_OR_PORT;
5622 }
else if (*
p ==
'/') {
5629 rhost.len =
p - uri.
p;
5632 case P_SCHEME_OR_PORT:
5633 if (
end -
p >= 3 && strncmp(
p,
"://", 3) == 0) {
5635 rscheme.
len =
p - uri.
p;
5636 state = P_USER_INFO;
5640 rhost.len =
p - uri.
p;
5646 for (;
p <
end;
p++) {
5647 if (*
p ==
'@' || *
p ==
'[' || *
p ==
'/') {
5651 if (
p ==
end || *
p ==
'/' || *
p ==
'[') {
5655 ruser_info.len =
p - ruser_info.p;
5663 for (; !found &&
p <
end;
p++) {
5664 found = (*
p ==
']');
5666 if (!found)
return -1;
5668 for (;
p <
end;
p++) {
5669 if (*
p ==
':' || *
p ==
'/')
break;
5672 rhost.len =
p - rhost.p;
5677 }
else if (*
p ==
'/') {
5685 for (;
p <
end;
p++) {
5697 if (
p <
end && *(
p - 1) ==
'?') {
5705 if (scheme != 0) *scheme = rscheme;
5706 if (user_info != 0) *user_info = ruser_info;
5707 if (host != 0) *host = rhost;
5708 if (port != 0) *port = rport;
5709 if (path != 0) *path = rpath;
5710 if (query != 0) *query = rquery;
5711 if (fragment != 0) *fragment = rfragment;
5718 const char *s = in->
p, *se = s + in->
len;
5719 char *cp = (
char *) out->
p, *
d;
5721 if (in->
len == 0 || *s !=
'/') {
5729 const char *next = s;
5732 if (
mg_vcmp(&component,
".") == 0) {
5734 }
else if (
mg_vcmp(&component,
"..") == 0) {
5736 if (
d > cp + 1 && *(
d - 1) ==
'/')
d--;
5737 while (
d > cp && *(
d - 1) !=
'/')
d--;
5739 memmove(
d, s, next - s);
5744 if (
d == cp) *
d++ =
'/';
5752 const struct mg_str *host,
unsigned int port,
5754 const struct mg_str *fragment,
int normalize_path,
5760 if (scheme != NULL && scheme->
len > 0) {
5765 if (user_info != NULL && user_info->
len > 0) {
5770 if (host != NULL && host->
len > 0) {
5776 int port_str_len = sprintf(port_str,
":%u", port);
5780 if (path != NULL && path->
len > 0) {
5781 if (normalize_path) {
5783 if (npath.
len != path->
len)
goto out;
5785 free((
void *) npath.
p);
5789 free((
void *) npath.
p);
5793 }
else if (normalize_path) {
5797 if (query != NULL && query->
len > 0) {
5802 if (fragment != NULL && fragment->
len > 0) {
5820#ifdef MG_MODULE_LINES
5821#line 1 "mongoose/src/mg_http.c"
5844 size_t user_buf_size;
5850MG_INTERNAL void altbuf_init(
struct altbuf *ab,
char *
buf,
size_t buf_size) {
5853 ab->user_buf_size = buf_size;
5860MG_INTERNAL void altbuf_append(
struct altbuf *ab,
char c) {
5861 if (ab->len < ab->user_buf_size) {
5863 ab->user_buf[ab->len++] =
c;
5872 if (ab->len > 0 && ab->m.len == 0) {
5877 ab->len = ab->m.len;
5893MG_INTERNAL int altbuf_reallocated(
struct altbuf *ab) {
5894 return ab->len > ab->user_buf_size;
5901MG_INTERNAL char *altbuf_get_buf(
struct altbuf *ab,
int trim) {
5902 if (altbuf_reallocated(ab)) {
5908 return ab->user_buf;
5914static const char *mg_version_header =
"Mongoose/" MG_VERSION;
5926#if MG_ENABLE_HTTP_CGI
5938 struct mg_str uri_pattern;
5943#if MG_ENABLE_CALLBACK_USERDATA
5968struct mg_reverse_proxy_data {
5972struct mg_ws_proto_data {
5983#if MG_ENABLE_FILESYSTEM
5986#if MG_ENABLE_HTTP_CGI
5989#if MG_ENABLE_HTTP_STREAMING_MULTIPART
5992#if MG_ENABLE_HTTP_WEBSOCKET
5993 struct mg_ws_proto_data ws_data;
5998 struct mg_reverse_proxy_data reverse_proxy_data;
6005 struct mg_connect_opts opts,
const char *scheme1,
const char *scheme2,
6006 const char *scheme_ssl1,
const char *scheme_ssl2,
const char *url,
6011 if (
c->proto_data == NULL) {
6019#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6020static void mg_http_free_proto_data_mp_stream(
6025 memset(mp, 0,
sizeof(*mp));
6029#if MG_ENABLE_FILESYSTEM
6032 if (
d->fp != NULL) {
6043 while (current != NULL) {
6045 MG_FREE((
void *) current->uri_pattern.p);
6046 MG_FREE((
void *) current->auth_domain);
6047 MG_FREE((
void *) current->auth_file);
6055static void mg_http_free_reverse_proxy_data(
struct mg_reverse_proxy_data *rpd) {
6056 if (rpd->linked_conn != NULL) {
6063 if (pd->reverse_proxy_data.linked_conn != NULL) {
6065 pd->reverse_proxy_data.linked_conn = NULL;
6067 rpd->linked_conn = NULL;
6073#if MG_ENABLE_FILESYSTEM
6076#if MG_ENABLE_HTTP_CGI
6079#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6080 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
6083 mg_http_free_reverse_proxy_data(&pd->reverse_proxy_data);
6087#if MG_ENABLE_FILESYSTEM
6089#define MIME_ENTRY(_ext, _type) \
6090 { _ext, sizeof(_ext) - 1, _type }
6091static const struct {
6102 MIME_ENTRY(
"js",
"application/x-javascript"),
6110 MIME_ENTRY(
"torrent",
"application/x-bittorrent"),
6124 MIME_ENTRY(
"exe",
"application/octet-stream"),
6125 MIME_ENTRY(
"zip",
"application/x-zip-compressed"),
6130 MIME_ENTRY(
"arj",
"application/x-arj-compressed"),
6131 MIME_ENTRY(
"rar",
"application/x-rar-compressed"),
6134 MIME_ENTRY(
"swf",
"application/x-shockwave-flash"),
6148 const char *ext, *overrides;
6152 path_len = strlen(path);
6154 overrides = opts->custom_mime_types;
6156 ext = path + (path_len -
k.len);
6167 r.len = strlen(r.p);
6173 r.len = strlen(r.p);
6185 const unsigned char *buf = (
unsigned char *) s;
6188 for (
i = 0;
i < buf_len;
i++) {
6189 if (!isprint(buf[
i]) && buf[
i] !=
'\r' && buf[
i] !=
'\n' && buf[
i] < 128) {
6191 }
else if (buf[
i] ==
'\n' &&
i + 1 < buf_len && buf[
i + 1] ==
'\n') {
6193 }
else if (buf[
i] ==
'\n' &&
i + 2 < buf_len && buf[
i + 1] ==
'\r' &&
6194 buf[
i + 2] ==
'\n') {
6211 while (v->len > 0 && v->p[v->len - 1] ==
' ') {
6220 if (
k->len != 0 && v->len == 0) {
6224 if (
k->len == 0 || v->len == 0) {
6226 k->len = v->len = 0;
6231 req->
body.
len = (size_t) to64(v->p);
6242 const char *
end, *qs;
6245 if (
len <= 0)
return len;
6247 memset(hm, 0,
sizeof(*hm));
6254 while (s <
end && isspace(*(
unsigned char *) s)) s++;
6264 if ((qs = (
char *) memchr(hm->
uri.
p,
'?', hm->
uri.
len)) != NULL) {
6271 if (
end - s < 4 || s[3] !=
' ')
return -1;
6295 if (hm->
body.
len == (
size_t) ~0 && is_req &&
6317#if MG_ENABLE_FILESYSTEM
6330 if (to_read >
left) {
6338 DBG((
"%p sent %d (total %d)", nc, (
int)
n, (
int) pd->
file.
sent));
6351 size_t n = mg_fwrite(io->
buf, 1, to_write, pd->
file.
fp);
6361#if MG_ENABLE_HTTP_CGI
6380 size_t *chunk_len) {
6381 unsigned char *s = (
unsigned char *)
buf;
6386 while (
i <
len && isxdigit(s[
i])) {
6388 n += (s[
i] >=
'0' && s[
i] <=
'9') ? s[
i] -
'0' : tolower(s[
i]) -
'a' + 10;
6397 if (
i == 0 ||
i + 2 >
len || s[
i] !=
'\r' || s[
i + 1] !=
'\n') {
6403 *chunk_data = (
char *) s +
i;
6410 if (
i == 0 ||
i + 2 >
len || s[
i] !=
'\r' || s[
i + 1] !=
'\n') {
6421 size_t i,
n, data_len, body_len, zero_chunk_received = 0;
6424 assert(blen >= body_len);
6431 memmove(buf + body_len,
data, data_len);
6432 body_len += data_len;
6435 if (data_len == 0) {
6436 zero_chunk_received = 1;
6445 memmove(buf + body_len, buf +
i, blen -
i);
6446 memset(buf + body_len + blen -
i, 0,
i - body_len);
6451 nc->
flags &= ~MG_F_DELETE_CHUNK;
6456 memset(buf, 0, body_len);
6457 memmove(buf, buf + body_len, blen -
i);
6463 if (zero_chunk_received) {
6474 struct mg_str *uri_path) {
6477 int matched, matched_max = 0;
6487 while (ep != NULL) {
6489 if (matched > matched_max) {
6492 matched_max = matched;
6502#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6503static void mg_http_multipart_continue(
struct mg_connection *nc);
6505static void mg_http_multipart_begin(
struct mg_connection *nc,
6516 hm->
body.
len =
c->recv_mbuf.len - req_len;
6517 c->flags &= ~MG_F_DELETE_CHUNK;
6529static void mg_http_handler2(
struct mg_connection *nc,
int ev,
6530 void *ev_data
MG_UD_ARG(
void *user_data),
6534 void *ev_data
MG_UD_ARG(
void *user_data)) {
6536 mg_http_handler2(nc, ev, ev_data
MG_UD_ARG(user_data), &hm);
6539static void mg_http_handler2(
struct mg_connection *nc,
int ev,
6540 void *ev_data
MG_UD_ARG(
void *user_data),
6544 void *ev_data
MG_UD_ARG(
void *user_data)) {
6550 const int is_req = (nc->
listener != NULL);
6551#if MG_ENABLE_HTTP_WEBSOCKET
6555#if MG_ENABLE_HTTP_CGI
6562#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6563 if (pd->mp_stream.boundary != NULL) {
6569 memset(&mp, 0,
sizeof(mp));
6571 mp.
var_name = pd->mp_stream.var_name;
6574 nc->
user_data, MG_EV_HTTP_PART_END, &mp);
6578 nc->
user_data, MG_EV_HTTP_MULTIPART_REQUEST_END, &mp);
6590 deliver_chunk(nc, hm, req_len);
6599#if MG_ENABLE_FILESYSTEM
6600 if (pd->
file.
fp != NULL) {
6607#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6608 if (pd->mp_stream.boundary != NULL &&
6611 pd->rcvd += *(
int *) ev_data;
6612 mg_http_multipart_continue(nc);
6613 }
else if (pd->mp_stream.data_avail) {
6615 mg_http_multipart_continue(nc);
6623 pd->rcvd += *(
int *) ev_data;
6634#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6636 s->
len >= 9 && strncmp(s->
p,
"multipart", 9) == 0) {
6637 mg_http_multipart_begin(nc, hm, req_len);
6638 mg_http_multipart_continue(nc);
6646 DBG((
"invalid request"));
6648 }
else if (req_len == 0) {
6651#if MG_ENABLE_HTTP_WEBSOCKET
6654 DBG((
"%p WebSocket upgrade code %d", nc, hm->
resp_code));
6686#if MG_ENABLE_CALLBACK_USERDATA
6706 deliver_chunk(nc, hm, req_len);
6708 LOG(
LL_ERROR, (
"%p recv buffer (%lu bytes) exceeds the limit "
6709 "%lu bytes, and not drained, closing",
6716 int request_done = 1;
6723 deliver_chunk(nc, hm, req_len);
6728#if MG_ENABLE_FILESYSTEM
6733 if (pd->
file.
fp != NULL) request_done = 0;
6735#if MG_ENABLE_HTTP_CGI
6737 if (pd->
cgi.
cgi_nc != NULL) request_done = 0;
6757 while (len < buf_len && buf[len] !=
'\n') len++;
6758 return len == buf_len ? 0 : len + 1;
6761#if MG_ENABLE_HTTP_STREAMING_MULTIPART
6762static void mg_http_multipart_begin(
struct mg_connection *nc,
6768 char boundary_buf[100];
6769 char *boundary = boundary_buf;
6779 if (ct->
len < 9 || strncmp(ct->
p,
"multipart", 9) != 0) {
6785 if (boundary_len == 0) {
6791 DBG((
"invalid request"));
6797 if (pd->mp_stream.boundary != NULL) {
6806 pd->mp_stream.boundary = strdup(boundary);
6807 pd->mp_stream.boundary_len = strlen(boundary);
6808 pd->mp_stream.var_name = pd->mp_stream.file_name = NULL;
6821 if (boundary != boundary_buf)
MG_FREE(boundary);
6824#define CONTENT_DISPOSITION "Content-Disposition: "
6826static size_t mg_http_multipart_call_handler(
struct mg_connection *
c,
int ev,
6831 memset(&mp, 0,
sizeof(mp));
6833 mp.
var_name = pd->mp_stream.var_name;
6837 mp.data.len = data_len;
6838 mp.num_data_consumed = data_len;
6841 pd->mp_stream.data_avail = (mp.num_data_consumed != data_len);
6842 return mp.num_data_consumed;
6848 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_END, NULL, 0);
6849 MG_FREE((
void *) pd->mp_stream.file_name);
6850 pd->mp_stream.file_name = NULL;
6851 MG_FREE((
void *) pd->mp_stream.var_name);
6852 pd->mp_stream.var_name = NULL;
6853 mg_http_multipart_call_handler(
c, MG_EV_HTTP_MULTIPART_REQUEST_END, NULL, 0);
6854 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
6860static int mg_http_multipart_wait_for_boundary(
struct mg_connection *
c) {
6861 const char *boundary;
6862 struct mbuf *io = &
c->recv_mbuf;
6865 if (pd->mp_stream.boundary == NULL) {
6867 DBG((
"Invalid request: boundary not initialized"));
6871 if ((
int) io->
len < pd->mp_stream.boundary_len + 2) {
6876 if (boundary != NULL) {
6877 const char *boundary_end = (boundary + pd->mp_stream.boundary_len);
6878 if (io->
len - (boundary_end - io->
buf) < 4) {
6881 if (strncmp(boundary_end,
"--\r\n", 4) == 0) {
6894static void mg_http_parse_header_internal(
struct mg_str *hdr,
6898static int mg_http_multipart_process_boundary(
struct mg_connection *
c) {
6900 const char *boundary, *block_begin;
6901 struct mbuf *io = &
c->recv_mbuf;
6903 struct altbuf ab_file_name, ab_var_name;
6906 block_begin = boundary + pd->mp_stream.boundary_len + 2;
6907 data_size = io->
len - (block_begin - io->
buf);
6909 altbuf_init(&ab_file_name, NULL, 0);
6910 altbuf_init(&ab_var_name, NULL, 0);
6912 while (data_size > 0 &&
6914 if (line_len > (
int)
sizeof(CONTENT_DISPOSITION) &&
6916 sizeof(CONTENT_DISPOSITION) - 1) == 0) {
6919 header.
p = block_begin +
sizeof(CONTENT_DISPOSITION) - 1;
6920 header.len = line_len -
sizeof(CONTENT_DISPOSITION) - 1;
6922 altbuf_reset(&ab_var_name);
6923 mg_http_parse_header_internal(&header,
"name", &ab_var_name);
6925 altbuf_reset(&ab_file_name);
6926 mg_http_parse_header_internal(&header,
"filename", &ab_file_name);
6928 block_begin += line_len;
6929 data_size -= line_len;
6934 if (line_len == 2 &&
mg_ncasecmp(block_begin,
"\r\n", 2) == 0) {
6937 if (pd->mp_stream.processing_part != 0) {
6938 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_END, NULL, 0);
6942 altbuf_append(&ab_file_name,
'\0');
6943 altbuf_append(&ab_file_name,
'\0');
6944 altbuf_append(&ab_var_name,
'\0');
6945 altbuf_append(&ab_var_name,
'\0');
6947 MG_FREE((
void *) pd->mp_stream.file_name);
6948 pd->mp_stream.file_name = altbuf_get_buf(&ab_file_name, 1 );
6949 MG_FREE((
void *) pd->mp_stream.var_name);
6950 pd->mp_stream.var_name = altbuf_get_buf(&ab_var_name, 1 );
6952 mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_BEGIN, NULL, 0);
6954 pd->mp_stream.processing_part++;
6958 block_begin += line_len;
6963 altbuf_reset(&ab_var_name);
6964 altbuf_reset(&ab_file_name);
6969static int mg_http_multipart_continue_wait_for_chunk(
struct mg_connection *
c) {
6971 struct mbuf *io = &
c->recv_mbuf;
6973 const char *boundary;
6974 if ((
int) io->
len < pd->mp_stream.boundary_len + 6 ) {
6979 if (boundary == NULL) {
6980 int data_len = (io->
len - (pd->mp_stream.boundary_len + 6));
6982 size_t consumed = mg_http_multipart_call_handler(
6983 c, MG_EV_HTTP_PART_DATA, io->
buf, (
size_t) data_len);
6987 }
else if (boundary != NULL) {
6988 size_t data_len = ((size_t)(boundary - io->
buf) - 4);
6989 size_t consumed = mg_http_multipart_call_handler(
c, MG_EV_HTTP_PART_DATA,
6992 if (consumed == data_len) {
7007 switch (pd->mp_stream.state) {
7013 if (mg_http_multipart_wait_for_boundary(
c) == 0) {
7019 if (mg_http_multipart_process_boundary(
c) == 0) {
7025 if (mg_http_multipart_continue_wait_for_chunk(
c) == 0) {
7031 if (mg_http_multipart_finalize(
c) == 0) {
7043struct file_upload_state {
7055const char *mg_status_message(
int status_code) {
7056 switch (status_code) {
7058 return "Partial Content";
7064 return "Bad Request";
7066 return "Unauthorized";
7072 return "Requested Range Not Satisfiable";
7074 return "I'm a teapot";
7076 return "Internal Server Error";
7078 return "Bad Gateway";
7080 return "Service Unavailable";
7082#if MG_ENABLE_EXTRA_ERRORS_DESC
7086 return "Switching Protocols";
7088 return "Processing";
7096 return "Non-Authoritative Information";
7098 return "No Content";
7100 return "Reset Content";
7102 return "Multi-Status";
7104 return "Already Reported";
7108 return "Multiple Choices";
7112 return "Not Modified";
7116 return "Switch Proxy";
7118 return "Temporary Redirect";
7120 return "Permanent Redirect";
7122 return "Payment Required";
7124 return "Method Not Allowed";
7126 return "Not Acceptable";
7128 return "Proxy Authentication Required";
7130 return "Request Timeout";
7136 return "Length Required";
7138 return "Precondition Failed";
7140 return "Payload Too Large";
7142 return "URI Too Long";
7144 return "Unsupported Media Type";
7146 return "Expectation Failed";
7148 return "Unprocessable Entity";
7152 return "Failed Dependency";
7154 return "Upgrade Required";
7156 return "Precondition Required";
7158 return "Too Many Requests";
7160 return "Request Header Fields Too Large";
7162 return "Unavailable For Legal Reasons";
7164 return "Not Implemented";
7166 return "Gateway Timeout";
7168 return "HTTP Version Not Supported";
7170 return "Variant Also Negotiates";
7172 return "Insufficient Storage";
7174 return "Loop Detected";
7176 return "Not Extended";
7178 return "Network Authentication Required";
7186void mg_send_response_line_s(
struct mg_connection *nc,
int status_code,
7187 const struct mg_str extra_headers) {
7188 mg_printf(nc,
"HTTP/1.1 %d %s\r\n", status_code,
7189 mg_status_message(status_code));
7190#ifndef MG_HIDE_SERVER_INFO
7191 mg_printf(nc,
"Server: %s\r\n", mg_version_header);
7193 if (extra_headers.
len > 0) {
7194 mg_printf(nc,
"%.*s\r\n", (
int) extra_headers.
len, extra_headers.
p);
7199 const char *extra_headers) {
7200 mg_send_response_line_s(nc, status_code,
mg_mk_str(extra_headers));
7204 const struct mg_str location,
7205 const struct mg_str extra_headers) {
7206 char bbody[100], *pbody = bbody;
7208 "<p>Moved <a href='%.*s'>here</a>.\r\n",
7209 (
int) location.
len, location.
p);
7210 char bhead[150], *phead = bhead;
7212 "Location: %.*s\r\n"
7213 "Content-Type: text/html\r\n"
7214 "Content-Length: %d\r\n"
7215 "Cache-Control: no-cache\r\n"
7217 (
int) location.
len, location.
p,
bl, (
int) extra_headers.
len,
7218 extra_headers.
p, (extra_headers.
len > 0 ?
"\r\n" :
""));
7220 if (phead != bhead)
MG_FREE(phead);
7222 if (pbody != bbody)
MG_FREE(pbody);
7226 int64_t content_length,
const char *extra_headers) {
7228 if (content_length < 0) {
7229 mg_printf(
c,
"%s",
"Transfer-Encoding: chunked\r\n");
7237 const char *reason) {
7238 if (!reason) reason = mg_status_message(code);
7241 "Content-Type: text/plain\r\nConnection: close");
7242 mg_send(nc, reason, strlen(reason));
7246#if MG_ENABLE_FILESYSTEM
7248 const cs_stat_t *st) {
7249 snprintf(buf, buf_len,
"\"%lx.%" INT64_FMT "\"", (
unsigned long) st->st_mtime,
7250 (int64_t) st->st_size);
7255 strftime(buf, buf_len,
"%a, %d %b %Y %H:%M:%S GMT",
gmtime(t));
7270 if (p == NULL)
return 0;
7271 memcpy(p, header->
p, header->
len);
7272 p[header->
len] =
'\0';
7280 const struct mg_str extra_headers) {
7298 char etag[50], current_time[50], last_modified[50], range[70];
7299 time_t t = (time_t)
mg_time();
7300 int64_t r1 = 0, r2 = 0, cl = st.st_size;
7302 int n, status_code = 200;
7306 if (range_hdr != NULL &&
7313 if (r1 > r2 || r2 >= cl) {
7316 snprintf(range,
sizeof(range),
7317 "Content-Range: bytes */%" INT64_FMT "\r\n",
7318 (int64_t) st.st_size);
7322 snprintf(range,
sizeof(range),
"Content-Range: bytes %" INT64_FMT
7324 r1, r1 + cl - 1, (int64_t) st.st_size);
7325#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
7326 _XOPEN_SOURCE >= 600
7327 fseeko(pd->
file.
fp, r1, SEEK_SET);
7329 fseek(pd->
file.
fp, (
long) r1, SEEK_SET);
7334#if !MG_DISABLE_HTTP_KEEP_ALIVE
7337 if (conn_hdr != NULL) {
7355 mg_send_response_line_s(nc, status_code, extra_headers);
7358 "Last-Modified: %s\r\n"
7359 "Accept-Ranges: bytes\r\n"
7360 "Content-Type: %.*s\r\n"
7361 "Connection: %s\r\n"
7362 "Content-Length: %" SIZE_T_FMT
7364 "%sEtag: %s\r\n\r\n",
7366 (pd->
file.keepalive ?
"keep-alive" :
"close"), (size_t) cl, range,
7375static void mg_http_serve_file2(
struct mg_connection *nc,
const char *path,
7378#if MG_ENABLE_HTTP_SSI
7384 mg_http_serve_file(nc, hm, path,
mg_get_mime_type(path,
"text/plain", opts),
7390int mg_url_decode(
const char *src,
int src_len,
char *dst,
int dst_len,
7391 int is_form_url_encoded) {
7393#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
7395 for (
i =
j = 0;
i < src_len &&
j < dst_len - 1;
i++,
j++) {
7396 if (src[
i] ==
'%') {
7397 if (
i < src_len - 2 && isxdigit(*(
const unsigned char *) (src +
i + 1)) &&
7398 isxdigit(*(
const unsigned char *) (src +
i + 2))) {
7399 a = tolower(*(
const unsigned char *) (src +
i + 1));
7400 b = tolower(*(
const unsigned char *) (src +
i + 2));
7406 }
else if (is_form_url_encoded && src[
i] ==
'+') {
7415 return i >= src_len ?
j : -1;
7420 const char *
p, *
e, *s;
7432 if (dst == NULL || dst_len == 0) {
7434 }
else if (buf->
p == NULL ||
name == NULL || buf->
len == 0) {
7438 name_len = strlen(
name);
7439 e = buf->
p + buf->
len;
7443 for (
p = buf->
p;
p + name_len <
e;
p++) {
7444 if ((
p == buf->
p ||
p[-1] ==
'&') &&
p[name_len] ==
'=' &&
7447 s = (
const char *) memchr(
p,
'&', (
size_t)(
e -
p));
7465 char chunk_size[50];
7468 n = snprintf(chunk_size,
sizeof(chunk_size),
"%lX\r\n", (
unsigned long)
len);
7488 if (buf != mem && buf != NULL) {
7504 for (
i =
j = 0;
i <
len;
i++) {
7505 if (buf[
i] ==
'<' || buf[
i] ==
'>') {
7507 mg_send(nc, buf[
i] ==
'<' ?
"<" :
">", 4);
7515 if (buf != mem && buf != NULL) {
7521static void mg_http_parse_header_internal(
struct mg_str *hdr,
7523 struct altbuf *ab) {
7524 int ch =
' ', ch1 =
',', ch2 =
';',
n = strlen(
var_name);
7525 const char *
p, *
end = hdr ? hdr->
p + hdr->
len : NULL, *s = NULL;
7528 for (s = hdr->
p; s != NULL && s +
n <
end; s++) {
7529 if ((s == hdr->
p || s[-1] == ch || s[-1] == ch1 || s[-1] ==
';') &&
7534 if (s != NULL && &s[
n + 1] <
end) {
7536 if (*s ==
'"' || *s ==
'\'') {
7537 ch = ch1 = ch2 = *s++;
7540 while (
p <
end &&
p[0] != ch &&
p[0] != ch1 &&
p[0] != ch2) {
7541 if (ch !=
' ' &&
p[0] ==
'\\' &&
p[1] == ch)
p++;
7542 altbuf_append(ab, *
p++);
7545 if (ch !=
' ' && *
p != ch) {
7552 altbuf_append(ab,
'\0');
7559 altbuf_init(&ab, *buf, buf_size);
7560 if (hdr == NULL)
return 0;
7561 if (*buf != NULL && buf_size > 0) *buf[0] =
'\0';
7563 mg_http_parse_header_internal(hdr,
var_name, &ab);
7569 *buf = altbuf_get_buf(&ab, 1 );
7570 return ab.len > 0 ? ab.len - 1 : 0;
7589 char *pass,
size_t pass_len) {
7591 if (hdr == NULL)
return -1;
7596 char *pass,
size_t pass_len) {
7607 snprintf(fmt,
sizeof(fmt),
"%%%" SIZE_T_FMT
"[^:]:%%%" SIZE_T_FMT
"[^\n]",
7608 user_len - 1, pass_len - 1);
7609 if (sscanf(buf, fmt, user, pass) == 0) {
7617#if MG_ENABLE_FILESYSTEM
7620 int exclude_specials) {
7625 const char *pdir = strrchr(path, DIRSEP);
7630 return (exclude_specials && (!strcmp(path,
".") || !strcmp(path,
".."))) ||
7631 (p1 != NULL &&
mg_match_prefix(p1, strlen(p1), path) == strlen(p1)) ||
7635#if !MG_DISABLE_HTTP_DIGEST_AUTH
7639 const size_t *msg_lens, uint8_t *digest) {
7643 for (
i = 0;
i < num_msgs;
i++) {
7649extern void mg_hash_md5_v(
size_t num_msgs,
const uint8_t *msgs[],
7650 const size_t *msg_lens, uint8_t *digest);
7653void cs_md5(
char buf[33], ...) {
7654 unsigned char hash[16];
7655 const uint8_t *msgs[20], *
p;
7656 size_t msg_lens[20];
7657 size_t num_msgs = 0;
7661 while ((
p = va_arg(ap,
const unsigned char *) ) != NULL) {
7663 msg_lens[num_msgs] = va_arg(ap,
size_t);
7672static void mg_mkmd5resp(
const char *method,
size_t method_len,
const char *uri,
7673 size_t uri_len,
const char *ha1,
size_t ha1_len,
7674 const char *nonce,
size_t nonce_len,
const char *nc,
7675 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
7676 const char *qop,
size_t qop_len,
char *resp) {
7677 static const char colon[] =
":";
7678 static const size_t one = 1;
7680 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
7681 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
7682 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
7683 colon, one, ha2,
sizeof(ha2) - 1, NULL);
7687 const char *method,
const char *uri,
7688 const char *auth_domain,
const char *user,
7689 const char *passwd,
const char *nonce) {
7690 static const char colon[] =
":", qop[] =
"auth";
7691 static const size_t one = 1;
7692 char ha1[33], resp[33], cnonce[40];
7694 snprintf(cnonce,
sizeof(cnonce),
"%lx", (
unsigned long)
mg_time());
7695 cs_md5(ha1, user, (
size_t) strlen(user), colon, one, auth_domain,
7696 (
size_t) strlen(auth_domain), colon, one, passwd,
7697 (
size_t) strlen(passwd), NULL);
7698 mg_mkmd5resp(method, strlen(method), uri, strlen(uri), ha1,
sizeof(ha1) - 1,
7699 nonce, strlen(nonce),
"1", one, cnonce, strlen(cnonce), qop,
7700 sizeof(qop) - 1, resp);
7701 return snprintf(buf, buf_len,
7702 "Authorization: Digest username=\"%s\","
7703 "realm=\"%s\",uri=\"%s\",qop=%s,nc=1,cnonce=%s,"
7704 "nonce=%s,response=%s\r\n",
7705 user, auth_domain, uri, qop, cnonce, nonce, resp);
7715 unsigned long now = (
unsigned long)
mg_time();
7716 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
7717 return (now >= val) && (now - val < 60 * 60);
7724 char username_buf[50], cnonce_buf[64], response_buf[40], uri_buf[200],
7725 qop_buf[20], nc_buf[20], nonce_buf[16];
7727 char *username = username_buf, *cnonce = cnonce_buf, *
response = response_buf,
7728 *uri = uri_buf, *qop = qop_buf, *nc = nc_buf, *nonce = nonce_buf;
7731 if (hm == NULL ||
fp == NULL ||
7759 if (username != username_buf)
MG_FREE(username);
7760 if (cnonce != cnonce_buf)
MG_FREE(cnonce);
7762 if (uri != uri_buf)
MG_FREE(uri);
7763 if (qop != qop_buf)
MG_FREE(qop);
7764 if (nc != nc_buf)
MG_FREE(nc);
7765 if (nonce != nonce_buf)
MG_FREE(nonce);
7774 struct mg_str auth_domain, FILE *
fp) {
7775 char buf[128], f_user[
sizeof(buf)], f_ha1[
sizeof(buf)], f_domain[
sizeof(buf)];
7783 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
7784 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3 &&
7785 mg_vcmp(&username, f_user) == 0 &&
7786 mg_vcmp(&auth_domain, f_domain) == 0) {
7789 nonce.
p, nonce.
len, nc.
p, nc.
len, cnonce.
p, cnonce.
len,
7790 qop.
p, qop.
len, exp_resp);
7802 const char *domain,
const char *passwords_file,
7809 if (domain != NULL && passwords_file != NULL) {
7813 snprintf(buf,
sizeof(buf),
"%.*s%c%s", (
int) path.
len, path.
p, DIRSEP,
7817 p = strrchr(path.
p, DIRSEP);
7818 if (
p == NULL)
p = path.
p;
7819 snprintf(buf,
sizeof(buf),
"%.*s%c%s", (
int) (
p - path.
p), path.
p, DIRSEP,
7833 passwords_file ? passwords_file :
"", flags, authorized));
7838 const char *domain,
const char *passwords_file,
7843 (void) passwords_file;
7849#if MG_ENABLE_DIRECTORY_LISTING
7850static void mg_escape(
const char *src,
char *dst,
size_t dst_len) {
7852 while (*src !=
'\0' &&
n + 5 < dst_len) {
7853 unsigned char ch = *(
unsigned char *) src++;
7855 n += snprintf(dst +
n, dst_len -
n,
"%s",
"<");
7866 int64_t fsize = stp->st_size;
7867 int is_dir = S_ISDIR(stp->st_mode);
7868 const char *slash = is_dir ?
"/" :
"";
7872 snprintf(size,
sizeof(size),
"%s",
"[DIRECTORY]");
7879 snprintf(size,
sizeof(size),
"%d", (
int) fsize);
7880 }
else if (fsize < 0x100000) {
7881 snprintf(size,
sizeof(size),
"%.1fk", (
double) fsize / 1024.0);
7882 }
else if (fsize < 0x40000000) {
7883 snprintf(size,
sizeof(size),
"%.1fM", (
double) fsize / 1048576);
7885 snprintf(size,
sizeof(size),
"%.1fG", (
double) fsize / 1073741824);
7888 strftime(mod,
sizeof(mod),
"%d-%b-%Y %H:%M",
localtime(&stp->st_mtime));
7892 "<tr><td><a href=\"%s%s\">%s%s</a></td>"
7893 "<td>%s</td><td name=%" INT64_FMT ">%s</td></tr>\n",
7894 href.p, slash, path, slash, mod, is_dir ? -1 : fsize,
7896 free((
void *) href.p);
7909 if ((dirp = (opendir(dir))) != NULL) {
7910 while ((dp = readdir(dirp)) != NULL) {
7915 snprintf(path,
sizeof(path),
"%s/%s", dir, dp->d_name);
7916 if (
mg_stat(path, &st) == 0) {
7917 func(nc, (
const char *) dp->d_name, &st);
7929 static const char *sort_js_code =
7930 "<script>function srt(tb, sc, so, d) {"
7931 "var tr = Array.prototype.slice.call(tb.rows, 0),"
7932 "tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
7933 "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
7934 "t1 = a.cells[2].getAttribute('name'), "
7935 "t2 = b.cells[2].getAttribute('name'); "
7936 "return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
7937 "n1 ? parseInt(n2) - parseInt(n1) : "
7938 "c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
7939 static const char *sort_js_code2 =
7940 "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
7941 "if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
7943 "window.onload = function() {"
7944 "var tb = document.getElementById('tb');"
7945 "var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
7946 "var sc = m[1], so = m[2]; document.onclick = function(ev) { "
7947 "var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
7948 "sc = c; ev.preventDefault();}};"
7949 "srt(tb, sc, so, true);"
7954 mg_printf(nc,
"%s: %s\r\n%s: %s\r\n\r\n",
"Transfer-Encoding",
"chunked",
7955 "Content-Type",
"text/html; charset=utf-8");
7959 "<html><head><title>Index of %.*s</title>%s%s"
7960 "<style>th,td {text-align: left; padding-right: 1em; "
7961 "font-family: monospace; }</style></head>\n"
7962 "<body><h1>Index of %.*s</h1>\n<table cellpadding=0><thead>"
7963 "<tr><th><a href=# rel=0>Name</a></th><th>"
7964 "<a href=# rel=1>Modified</a</th>"
7965 "<th><a href=# rel=2>Size</a></th></tr>"
7966 "<tr><td colspan=3><hr></td></tr>\n"
7969 (
int) hm->
uri.
len, hm->
uri.
p, sort_js_code, sort_js_code2,
7973 "</tbody><tr><td colspan=3><hr></td></tr>\n"
7975 "<address>%s</address>\n"
7992 char **index_file, cs_stat_t *stp) {
7994 size_t path_len = strlen(path);
8002 size_t len = path_len + 1 +
vec.
len + 1;
8004 if (*index_file == NULL)
break;
8005 snprintf(*index_file,
len,
"%s%c%.*s", path, DIRSEP, (
int)
vec.
len,
vec.p);
8008 if (
mg_stat(*index_file, &st) == 0 && S_ISREG(st.st_mode)) {
8019 LOG(
LL_DEBUG, (
"[%s] [%s]", path, (*index_file ? *index_file :
"")));
8022#if MG_ENABLE_HTTP_URL_REWRITES
8028 char local_port[20] = {
'%'};
8034 if (
mg_vcmp(&a, local_port) == 0) {
8036 mg_printf(
c,
"Content-Length: 0\r\nLocation: %.*s%.*s\r\n\r\n",
8037 (
int) b.len, b.p, (
int) (hm->
proto.
p - hm->
uri.
p - 1),
8046static void mg_reverse_proxy_handler(
struct mg_connection *nc,
int ev,
8047 void *ev_data
MG_UD_ARG(
void *user_data)) {
8051 if (pd == NULL || pd->reverse_proxy_data.linked_conn == NULL) {
8052 DBG((
"%p: upstream closed", nc));
8058 if (*(
int *) ev_data != 0) {
8074#if MG_ENABLE_CALLBACK_USERDATA
8081 struct mg_str upstream) {
8083 char burl[256], *purl = burl;
8088 memset(&opts, 0,
sizeof(opts));
8089 opts.error_string = &error;
8091 mg_asprintf(&purl,
sizeof(burl),
"%.*s%.*s", (
int) upstream.
len, upstream.
p,
8095 opts,
"http", NULL,
"https", NULL, purl, &path,
8098 hm->
uri.
p, purl, (
int) mount.
len, mount.
p));
8101 LOG(
LL_ERROR, (
"Error connecting to %s: %s", purl, error));
8112 (
int) path.
len, path.
p);
8114 mg_printf(be,
"Host: %.*s\r\n", (
int) host.len, host.p);
8143 if (purl != burl)
MG_FREE(purl);
8146static int mg_http_handle_forwarding(
struct mg_connection *nc,
8156 mg_http_reverse_proxy(nc, hm, a, b);
8169 struct mg_str *remainder) {
8172 struct mg_str root = {NULL, 0};
8173 const char *file_uri_start = cp;
8175 remainder->
p = NULL;
8180#if MG_ENABLE_HTTP_URL_REWRITES
8183 const char *rewrites =
"";
8189 if (a.len > 1 && a.p[0] ==
'@') {
8191 if (hh != NULL && hh->
len == a.len - 1 &&
8199 if (match_len > 0) {
8200 file_uri_start = hm->
uri.
p + match_len;
8201 if (*file_uri_start ==
'/' || file_uri_start == cp_end) {
8203 }
else if (*(file_uri_start - 1) ==
'/') {
8216 if (root.
p == NULL) {
8217#if MG_ENABLE_HTTP_WEBDAV
8228 assert(root.
p != NULL && root.
len > 0);
8232 const char *u = file_uri_start + 1;
8234 char *lp_end = lp + root.
len + hm->
uri.
len + 1;
8241 memcpy(
p, root.
p, root.
len);
8243 if (*(
p - 1) == DIRSEP)
p--;
8248 while (u <= cp_end) {
8249 const char *next = u;
8253 exists = (
mg_stat(lp, &st) == 0);
8254 if (exists && S_ISREG(st.st_mode)) {
8257 if (*(u - 1) ==
'/') u--;
8261 if (u >= cp_end)
break;
8263 if (component.len > 0) {
8265 memmove(
p + 1, component.p, component.len);
8271 component.p =
p + 1;
8272 component.len =
len;
8273 if (
mg_vcmp(&component,
".") == 0) {
8275 }
else if (
mg_vcmp(&component,
"..") == 0) {
8276 while (
p > ps && *
p != DIRSEP)
p--;
8283 if (to_wchar(component.p, buf,
MG_MAX_PATH) == 0) {
8284 DBG((
"[%.*s] smells funny", (
int) component.len, component.p));
8291 for (
i = 0;
i < component.len;
i++,
p++) {
8292 if (*
p ==
'\0' || *
p == DIRSEP
8309 if (u > cp_end) u = cp_end;
8311 remainder->
len = cp_end - u;
8319 (
"'%.*s' -> '%s' + '%.*s'", (
int) hm->
uri.
len, hm->
uri.
p,
8320 *local_path ? *local_path :
"", (int) remainder->
len, remainder->
p));
8325 static const char *
month_names[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
8326 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
8336 return year / 4 - year / 100 + year / 400;
8341 static const unsigned short days_before_month[] = {
8342 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
8344 int second, minute, hour, day, month, year, leap_days, days;
8345 time_t result = (time_t) 0;
8347 if (((sscanf(datetime,
"%d/%3s/%d %d:%d:%d", &day, month_str, &year, &hour,
8348 &minute, &second) == 6) ||
8349 (sscanf(datetime,
"%d %3s %d %d:%d:%d", &day, month_str, &year, &hour,
8350 &minute, &second) == 6) ||
8351 (sscanf(datetime,
"%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year,
8352 &hour, &minute, &second) == 6) ||
8353 (sscanf(datetime,
"%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour,
8354 &minute, &second) == 6)) &&
8358 days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
8359 result = days * 24 * 3600 + hour * 3600 + minute * 60 + second;
8379 const char *domain) {
8381 "HTTP/1.1 401 Unauthorized\r\n"
8382 "WWW-Authenticate: Digest qop=\"auth\", "
8383 "realm=\"%s\", nonce=\"%lx\"\r\n"
8384 "Content-Length: 0\r\n\r\n",
8385 domain, (
unsigned long)
mg_time());
8392 "Allow: GET, POST, HEAD, CONNECT, OPTIONS"
8394 ", MKCOL, PUT, DELETE, PROPFIND, MOVE\r\nDAV: 1,2"
8405 const struct mg_str *path_info,
8408 int exists, is_directory, is_cgi;
8409#if MG_ENABLE_HTTP_WEBDAV
8414 char *index_file = NULL;
8417 exists = (
mg_stat(path, &st) == 0);
8418 is_directory = exists && S_ISDIR(st.st_mode);
8425 index_file ? index_file : path) > 0);
8428 (
"%p %.*s [%s] exists=%d is_dir=%d is_dav=%d is_cgi=%d index=%s", nc,
8430 is_cgi, index_file ? index_file :
""));
8432 if (is_directory && hm->
uri.
p[hm->
uri.
len - 1] !=
'/' && !is_dav) {
8434 "HTTP/1.1 301 Moved\r\nLocation: %.*s/\r\n"
8435 "Content-Length: 0\r\n\r\n",
8442 if (path_info->
len > 0 && !is_cgi) {
8457 opts->per_directory_auth_file,
8461 }
else if (is_cgi) {
8462#if MG_ENABLE_HTTP_CGI
8463 mg_handle_cgi(nc, index_file ? index_file : path, path_info, hm, opts);
8467 }
else if ((!exists ||
8471#if MG_ENABLE_HTTP_WEBDAV
8474#if !MG_DISABLE_DAV_AUTH
8475 }
else if (is_dav &&
8493#if MG_ENABLE_FAKE_DAVLOCK
8495 mg_handle_lock(nc, path);
8500 }
else if (is_directory && index_file == NULL) {
8501#if MG_ENABLE_DIRECTORY_LISTING
8513 mg_http_serve_file2(nc, index_file ? index_file : path, hm, opts);
8521 struct mg_str *hdr, path_info;
8522 uint32_t remote_ip = ntohl(*(uint32_t *) &nc->
sa.
sin.sin_addr);
8531#if MG_ENABLE_HTTP_URL_REWRITES
8532 if (mg_http_handle_forwarding(nc, hm, &opts)) {
8557 opts.
index_files =
"index.html,index.htm,index.shtml,index.cgi,index.php";
8576 mg_vcmp(hdr,
"keep-alive") != 0)) {
8583#if MG_ENABLE_HTTP_STREAMING_MULTIPART
8584void mg_file_upload_handler(
struct mg_connection *nc,
int ev,
void *ev_data,
8585 mg_fu_fname_fn local_name_fn
8588 case MG_EV_HTTP_PART_BEGIN: {
8591 struct file_upload_state *fus;
8594 if (lfn.
p == NULL || lfn.
len == 0) {
8597 "HTTP/1.1 403 Not Allowed\r\n"
8598 "Content-Type: text/plain\r\n"
8599 "Connection: close\r\n\r\n"
8600 "Not allowed to upload %s\r\n",
8605 fus = (
struct file_upload_state *)
MG_CALLOC(1,
sizeof(*fus));
8611 memcpy(fus->lfn, lfn.
p, lfn.
len);
8612 fus->lfn[lfn.
len] =
'\0';
8615 (
"%p Receiving file %s -> %s", nc, mp->
file_name, fus->lfn));
8616 fus->fp =
mg_fopen(fus->lfn,
"wb");
8617 if (fus->fp == NULL) {
8619 "HTTP/1.1 500 Internal Server Error\r\n"
8620 "Content-Type: text/plain\r\n"
8621 "Connection: close\r\n\r\n");
8631 case MG_EV_HTTP_PART_DATA: {
8634 struct file_upload_state *fus =
8635 (
struct file_upload_state *) mp->
user_data;
8636 if (fus == NULL || fus->fp == NULL)
break;
8638 LOG(
LL_ERROR, (
"Failed to write to %s: %d, wrote %d", fus->lfn,
8641#ifdef SPIFFS_ERR_FULL
8646 "HTTP/1.1 413 Payload Too Large\r\n"
8647 "Content-Type: text/plain\r\n"
8648 "Connection: close\r\n\r\n");
8649 mg_printf(nc,
"Failed to write to %s: no space left; wrote %d\r\n",
8650 fus->lfn, (
int) fus->num_recd);
8653 "HTTP/1.1 500 Internal Server Error\r\n"
8654 "Content-Type: text/plain\r\n"
8655 "Connection: close\r\n\r\n");
8667 fus->num_recd += mp->
data.
len;
8669 (
int) fus->num_recd));
8672 case MG_EV_HTTP_PART_END: {
8675 struct file_upload_state *fus =
8676 (
struct file_upload_state *) mp->
user_data;
8677 if (fus == NULL)
break;
8678 if (mp->
status >= 0 && fus->fp != NULL) {
8680 fus->lfn, (
int) fus->num_recd));
8688 if (fus->fp != NULL) fclose(fus->fp);
8695 case MG_EV_HTTP_MULTIPART_REQUEST_END: {
8697 "HTTP/1.1 200 OK\r\n"
8698 "Content-Type: text/plain\r\n"
8699 "Connection: close\r\n\r\n"
8706#if MG_ENABLE_CALLBACK_USERDATA
8716 struct mg_connect_opts opts,
const char *scheme1,
const char *scheme2,
8717 const char *scheme_ssl1,
const char *scheme_ssl2,
const char *url,
8720 unsigned int port_i = 0;
8722 struct mg_str scheme, query, fragment;
8723 char conn_addr_buf[2];
8724 char *conn_addr = conn_addr_buf;
8727 &query, &fragment) != 0) {
8733 if (query.len > 0) path->
len += query.len + 1;
8735 if (scheme.len == 0 ||
mg_vcmp(&scheme, scheme1) == 0 ||
8736 (scheme2 != NULL &&
mg_vcmp(&scheme, scheme2) == 0)) {
8738 if (port_i == 0) port_i = 80;
8739 }
else if (
mg_vcmp(&scheme, scheme_ssl1) == 0 ||
8740 (scheme2 != NULL &&
mg_vcmp(&scheme, scheme_ssl2) == 0)) {
8742 if (port_i == 0) port_i = 443;
8747 mg_asprintf(&conn_addr,
sizeof(conn_addr_buf),
"tcp://%.*s:%u",
8748 (
int) host->
len, host->
p, port_i);
8749 if (conn_addr == NULL)
goto out;
8751 LOG(
LL_DEBUG, (
"%s use_ssl? %d %s", url, use_ssl, conn_addr));
8759 if (opts.ssl_ca_cert == NULL) {
8760 opts.ssl_ca_cert =
"*";
8774 if (conn_addr != NULL && conn_addr != conn_addr_buf)
MG_FREE(conn_addr);
8780 struct mg_connect_opts opts,
const char *url,
const char *extra_headers,
8781 const char *post_data) {
8787 NULL,
"https", NULL, url, &path, &user, &host);
8798 if (post_data == NULL) post_data =
"";
8799 if (extra_headers == NULL) extra_headers =
"";
8800 if (path.len == 0) path =
mg_mk_str(
"/");
8803 mg_printf(nc,
"%s %.*s HTTP/1.1\r\nHost: %.*s\r\nContent-Length: %" SIZE_T_FMT
8805 (post_data[0] ==
'\0' ?
"GET" :
"POST"), (int) path.len, path.p,
8806 (int) (path.p - host.p), host.p, strlen(post_data), (int) auth.len,
8807 (auth.
buf == NULL ?
"" : auth.
buf), extra_headers, post_data);
8815 const char *url,
const char *extra_headers,
const char *post_data) {
8817 memset(&opts, 0,
sizeof(opts));
8819 extra_headers, post_data);
8824 size_t file_name_len,
const char **
data,
8826 static const char cd[] =
"Content-Disposition: ";
8827 size_t hl,
bl,
n, ll, pos, cdl =
sizeof(cd) - 1;
8830 if (buf == NULL || buf_len <= 0)
return 0;
8833 if (buf[0] !=
'-' || buf[1] !=
'-' || buf[2] ==
'\n')
return 0;
8843 header.
p = buf +
n + cdl;
8844 header.
len = ll - (cdl + 2);
8867 for (pos = hl; pos + (
bl - 2) < buf_len; pos++) {
8868 if (buf[pos] ==
'-' && !strncmp(buf, &buf[pos],
bl - 2)) {
8869 if (data_len != NULL) *data_len = (pos - 2) - hl;
8870 if (
data != NULL) *
data = buf + hl;
8879 const char *uri_path,
8885 if (nc == NULL)
return;
8887 if (new_ep == NULL)
return;
8893 new_ep->auth_file = strdup(opts.
auth_file);
8896#if MG_ENABLE_CALLBACK_USERDATA
8910 || ev == MG_EV_HTTP_MULTIPART_REQUEST
8916#if MG_ENABLE_FILESYSTEM && !MG_DISABLE_HTTP_DIGEST_AUTH
8924#if MG_ENABLE_CALLBACK_USERDATA
8925 user_data = ep->user_data;
8937 memset(&opts, 0,
sizeof(opts));
8938#if MG_ENABLE_CALLBACK_USERDATA
8945#ifdef MG_MODULE_LINES
8946#line 1 "mongoose/src/mg_http_cgi.c"
8957#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_CGI
8959#ifndef MG_MAX_CGI_ENVIR_VARS
8960#define MG_MAX_CGI_ENVIR_VARS 64
8963#ifndef MG_ENV_EXPORT_TO_CGI
8964#define MG_ENV_EXPORT_TO_CGI "MONGOOSE_CGI"
8967#define MG_F_HTTP_CGI_PARSE_HEADERS MG_F_USER_1
8988struct mg_threadparam {
8993static int mg_wait_until_ready(sock_t sock,
int for_read) {
8997 return select(sock + 1, for_read ? &
set : 0, for_read ? 0 : &
set, 0, 0) == 1;
9000static void *mg_push_to_stdin(
void *arg) {
9001 struct mg_threadparam *tp = (
struct mg_threadparam *) arg;
9002 int n, sent, stop = 0;
9006 while (!stop && mg_wait_until_ready(tp->s, 1) &&
9007 (
n = recv(tp->s, buf,
sizeof(buf), 0)) > 0) {
9008 if (
n == -1 && GetLastError() == WSAEWOULDBLOCK)
continue;
9009 for (sent = 0; !stop && sent <
n; sent +=
k) {
9010 if (!WriteFile(tp->hPipe, buf + sent,
n - sent, &
k, 0)) stop = 1;
9013 DBG((
"%s",
"FORWARED EVERYTHING TO CGI"));
9014 CloseHandle(tp->hPipe);
9019static void *mg_pull_from_stdout(
void *arg) {
9020 struct mg_threadparam *tp = (
struct mg_threadparam *) arg;
9021 int k = 0, stop = 0;
9025 while (!stop && ReadFile(tp->hPipe, buf,
sizeof(buf), &
n, NULL)) {
9026 for (sent = 0; !stop && sent <
n; sent +=
k) {
9027 if (mg_wait_until_ready(tp->s, 0) &&
9028 (
k = send(tp->s, buf + sent,
n - sent, 0)) <= 0)
9032 DBG((
"%s",
"EOF FROM CGI"));
9033 CloseHandle(tp->hPipe);
9040static void mg_spawn_stdio_thread(sock_t sock, HANDLE hPipe,
9041 void *(*func)(
void *)) {
9042 struct mg_threadparam *tp = (
struct mg_threadparam *)
MG_MALLOC(
sizeof(*tp));
9050static void mg_abs_path(
const char *utf8_path,
char *abs_path,
size_t len) {
9053 GetFullPathNameW(buf,
ARRAY_SIZE(buf2), buf2, NULL);
9054 WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0);
9058 const char *env,
const char *envp[],
9059 const char *dir, sock_t sock) {
9061 PROCESS_INFORMATION
pi;
9062 HANDLE a[2], b[2], me = GetCurrentProcess();
9066 DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;
9069 memset(&si, 0,
sizeof(si));
9070 memset(&
pi, 0,
sizeof(
pi));
9073 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
9074 si.wShowWindow = SW_HIDE;
9075 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
9077 CreatePipe(&a[0], &a[1], NULL, 0);
9078 CreatePipe(&b[0], &b[1], NULL, 0);
9079 DuplicateHandle(me, a[0], me, &si.hStdInput, 0,
TRUE, flags);
9080 DuplicateHandle(me, b[1], me, &si.hStdOutput, 0,
TRUE, flags);
9082 if (interp == NULL && (
fp =
mg_fopen(cmd,
"r")) != NULL) {
9083 buf[0] = buf[1] =
'\0';
9084 fgets(buf,
sizeof(buf),
fp);
9085 buf[
sizeof(buf) - 1] =
'\0';
9086 if (buf[0] ==
'#' && buf[1] ==
'!') {
9089 while (*interp !=
'\0' && isspace(*(
unsigned char *) interp)) {
9096 snprintf(buf,
sizeof(buf),
"%s/%s", dir, cmd);
9100 to_wchar(dir, full_dir,
ARRAY_SIZE(full_dir));
9102 if (interp != NULL) {
9104 snprintf(cmdline,
sizeof(cmdline),
"%s \"%s\"", buf4, buf2);
9106 snprintf(cmdline,
sizeof(cmdline),
"\"%s\"", buf2);
9110 if (CreateProcessW(NULL, wcmd, NULL, NULL,
TRUE, CREATE_NEW_PROCESS_GROUP,
9111 (
void *) env, full_dir, &si, &
pi) != 0) {
9112 mg_spawn_stdio_thread(sock, a[1], mg_push_to_stdin);
9113 mg_spawn_stdio_thread(sock, b[0], mg_pull_from_stdout);
9115 CloseHandle(si.hStdOutput);
9116 CloseHandle(si.hStdInput);
9118 CloseHandle(
pi.hThread);
9119 CloseHandle(
pi.hProcess);
9125 DBG((
"CGI command: [%ls] -> %p", wcmd,
pi.hProcess));
9129 return (
pi.hProcess != NULL);
9133 const char *env,
const char *envp[],
9134 const char *dir, sock_t sock) {
9144 int tmp = chdir(dir);
9146 (void) dup2(sock, 0);
9147 (void) dup2(sock, 1);
9156 signal(SIGCHLD, SIG_DFL);
9158 if (interp == NULL) {
9159 execle(cmd, cmd, (
char *) 0, envp);
9161 execle(interp, interp, cmd, (
char *) 0, envp);
9163 snprintf(buf,
sizeof(buf),
9164 "Status: 500\r\n\r\n"
9165 "500 Server Error: %s%s%s: %s",
9166 interp == NULL ?
"" : interp, interp == NULL ?
"" :
" ", cmd,
9168 send(1, buf, strlen(buf), 0);
9169 _exit(EXIT_FAILURE);
9182 char *added = block->
buf + block->
len;
9186 space =
sizeof(block->
buf) - (block->
len + 2);
9190 n = vsnprintf(added, (
size_t) space, fmt, ap);
9194 if (
n > 0 &&
n + 1 < space &&
9199 block->
len +=
n + 1;
9213 const struct mg_str *path_info,
9222 size_t path_info_len = path_info != NULL ? path_info->
len : 0;
9224 blk->len =
blk->nvars = 0;
9227 if ((s = getenv(
"SERVER_NAME")) != NULL) {
9246 hm->query_string.
p);
9254 s = hm->
uri.
p + hm->
uri.
len - path_info_len - 1;
9256 const char *base_name = strrchr(prog, DIRSEP);
9258 (base_name != NULL ? base_name + 1 : prog));
9264 if (path_info != NULL && path_info->
len > 0) {
9267 mg_addenv(
blk,
"PATH_TRANSLATED=%.*s", (
int) path_info->
len, path_info->
p);
9316 for (; *
p !=
'=' && *
p !=
'\0';
p++) {
9317 if (*
p ==
'-') *
p =
'_';
9318 *
p = (char) toupper(*(
unsigned char *)
p);
9322 blk->vars[
blk->nvars++] = NULL;
9323 blk->buf[
blk->len++] =
'\0';
9327 void *ev_data
MG_UD_ARG(
void *user_data)) {
9328#if !MG_ENABLE_CALLBACK_USERDATA
9355 if (nc->
flags & MG_F_HTTP_CGI_PARSE_HEADERS) {
9359 if (
len == 0)
break;
9368 mg_printf(nc,
"%s",
"HTTP/1.1 302 Moved\r\n");
9372 mg_printf(nc,
"%s",
"HTTP/1.1 200 OK\r\n");
9375 nc->
flags &= ~MG_F_HTTP_CGI_PARSE_HEADERS;
9377 if (!(nc->
flags & MG_F_HTTP_CGI_PARSE_HEADERS)) {
9382 DBG((
"%p CLOSE", cgi_nc));
9390 const struct mg_str *path_info,
9398 DBG((
"%p [%s]",
nc, prog));
9405 if ((p = strrchr(prog, DIRSEP)) == NULL) {
9406 snprintf(dir,
sizeof(dir),
"%s",
".");
9408 snprintf(dir,
sizeof(dir),
"%.*s", (
int) (p - prog), prog);
9418 struct sigaction sa;
9420 sigemptyset(&sa.sa_mask);
9421 sa.sa_handler = SIG_IGN;
9423 sigaction(SIGCHLD, &sa, NULL);
9432#if !MG_ENABLE_CALLBACK_USERDATA
9435 nc->
flags |= MG_F_HTTP_CGI_PARSE_HEADERS;
9452 if (
d == NULL)
return;
9453 if (
d->cgi_nc != NULL) {
9455 d->cgi_nc->user_data = NULL;
9457 memset(
d, 0,
sizeof(*
d));
9461#ifdef MG_MODULE_LINES
9462#line 1 "mongoose/src/mg_http_ssi.c"
9469#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_SSI && MG_ENABLE_FILESYSTEM
9472 const char *path, FILE *
fp,
int include_level,
9478 while ((
n = mg_fread(buf, 1,
sizeof(buf),
fp)) > 0) {
9484 const char *ssi,
char *tag,
int include_level,
9493 if (sscanf(tag,
" virtual=\"%[^\"]\"",
file_name) == 1) {
9496 }
else if (sscanf(tag,
" abspath=\"%[^\"]\"",
file_name) == 1) {
9501 snprintf(path,
sizeof(path),
"%s",
file_name);
9502 }
else if (sscanf(tag,
" file=\"%[^\"]\"",
file_name) == 1 ||
9503 sscanf(tag,
" \"%[^\"]\"",
file_name) == 1) {
9505 snprintf(path,
sizeof(path),
"%s", ssi);
9506 if ((p = strrchr(path, DIRSEP)) != NULL) {
9509 snprintf(path + strlen(path),
sizeof(path) - strlen(path),
"%s",
file_name);
9511 mg_printf(nc,
"Bad SSI #include: [%s]", tag);
9516 mg_printf(nc,
"SSI include error: mg_fopen(%s): %s", path,
9530#if MG_ENABLE_HTTP_SSI_EXEC
9535 if (sscanf(tag,
" \"%[^\"]\"", cmd) != 1) {
9536 mg_printf(nc,
"Bad SSI #exec: [%s]", tag);
9537 }
else if ((
fp = popen(cmd,
"r")) == NULL) {
9551 const char *path, FILE *
fp,
int include_level,
9556#if MG_ENABLE_HTTP_SSI_EXEC
9559 char buf[BUFSIZ], *
p = buf + btag.
len;
9560 int ch,
len, in_ssi_tag;
9562 if (include_level > 10) {
9563 mg_printf(nc,
"SSI #include level is too deep (%s)", path);
9567 in_ssi_tag =
len = 0;
9568 while ((ch = fgetc(
fp)) != EOF) {
9569 if (in_ssi_tag && ch ==
'>' && buf[
len - 1] ==
'-' && buf[
len - 2] ==
'-') {
9575 while (
i > 0 && buf[
i] ==
' ') {
9580 if (strncmp(
p, d_include.
p, d_include.
len) == 0) {
9581 mg_do_ssi_include(nc, hm, path,
p + d_include.
len + 1, include_level,
9583 }
else if (strncmp(
p, d_call.
p, d_call.
len) == 0) {
9585 memset(&cctx, 0,
sizeof(cctx));
9590 (
void *) cctx.arg.p);
9592#if MG_ENABLE_HTTP_SSI_EXEC
9593 }
else if (strncmp(p, d_exec.
p, d_exec.
len) == 0) {
9600 }
else if (ch ==
'<') {
9603 mg_send(nc, buf, (
size_t) len);
9606 buf[len++] = ch & 0xff;
9607 }
else if (in_ssi_tag) {
9608 if (len == (
int) btag.
len && strncmp(buf, btag.
p, btag.
len) != 0) {
9611 }
else if (len == (
int)
sizeof(buf) - 2) {
9612 mg_printf(nc,
"%s: SSI tag is too large", path);
9615 buf[len++] = ch & 0xff;
9617 buf[len++] = ch & 0xff;
9618 if (len == (
int)
sizeof(buf)) {
9619 mg_send(nc, buf, (
size_t) len);
9627 mg_send(nc, buf, (
size_t) len);
9637 DBG((
"%p %s", nc, path));
9647 "Content-Type: %.*s\r\n"
9648 "Connection: close\r\n\r\n",
9657#ifdef MG_MODULE_LINES
9658#line 1 "mongoose/src/mg_http_webdav.c"
9665#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBDAV
9668 static const char *methods[] = {
9674#if MG_ENABLE_FAKE_DAVLOCK
9691static int mg_mkdir(
const char *path, uint32_t mode) {
9693 return mkdir(path, mode);
9696 return _mkdir(path);
9703 time_t t = stp->st_mtime;
9708 "<d:href>%s</d:href>"
9711 "<d:resourcetype>%s</d:resourcetype>"
9713 "</d:getcontentlength>"
9714 "<d:getlastmodified>%s</d:getlastmodified>"
9716 "<d:status>HTTP/1.1 200 OK</d:status>"
9719 name_esc.
p, S_ISDIR(stp->st_mode) ?
"<d:collection/>" :
"",
9720 (int64_t) stp->st_size, mtime);
9721 free((
void *) name_esc.
p);
9727 static const char header[] =
9728 "HTTP/1.1 207 Multi-Status\r\n"
9729 "Connection: close\r\n"
9730 "Content-Type: text/xml; charset=utf-8\r\n\r\n"
9731 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
9732 "<d:multistatus xmlns:d='DAV:'>\n";
9733 static const char footer[] =
"</d:multistatus>\n";
9737 if (S_ISDIR(stp->st_mode) &&
9739 mg_printf(nc,
"%s",
"HTTP/1.1 403 Directory Listing Denied\r\n\r\n");
9742 mg_send(nc, header,
sizeof(header) - 1);
9743 snprintf(uri,
sizeof(uri),
"%.*s", (
int) hm->
uri.
len, hm->
uri.
p);
9745 if (S_ISDIR(stp->st_mode) && (depth == NULL ||
mg_vcmp(depth,
"0") != 0)) {
9748 mg_send(nc, footer,
sizeof(footer) - 1);
9753#if MG_ENABLE_FAKE_DAVLOCK
9766 static const char *reply =
9767 "HTTP/1.1 207 Multi-Status\r\n"
9768 "Connection: close\r\n"
9769 "Content-Type: text/xml; charset=utf-8\r\n\r\n"
9770 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
9771 "<d:multistatus xmlns:d='DAV:'>\n"
9772 "<D:lockdiscovery>\n"
9776 "opaquelocktoken:%s%u"
9780 "</D:lockdiscovery>"
9781 "</d:multistatus>\n";
9789 int status_code = 500;
9792 }
else if (!
mg_mkdir(path, 0755)) {
9794 }
else if (errno == EEXIST) {
9796 }
else if (errno == EACCES) {
9798 }
else if (errno == ENOENT) {
9813 if ((dirp = opendir(dir)) == NULL)
return 0;
9815 while ((dp = readdir(dirp)) != NULL) {
9819 snprintf(path,
sizeof(path),
"%s%c%s", dir,
'/', dp->d_name);
9821 if (S_ISDIR(st.st_mode)) {
9840 const char *
p = (
char *) memchr(dest->
p,
'/', dest->
len);
9841 if (
p != NULL &&
p[1] ==
'/' &&
9842 (
p = (
char *) memchr(
p + 2,
'/', dest->
p + dest->
len -
p)) != NULL) {
9845 (
int) (dest->
p + dest->
len -
p),
p);
9846 if (rename(path, buf) == 0) {
9861 if (
mg_stat(path, &st) != 0) {
9863 }
else if (S_ISDIR(st.st_mode)) {
9866 }
else if (
remove(path) == 0) {
9878 for (s = path + 1; *s !=
'\0'; s++) {
9882 snprintf(buf,
sizeof(buf),
"%.*s", (
int) (s - path), path);
9883 buf[
sizeof(buf) - 1] =
'\0';
9898 int rc, status_code =
mg_stat(path, &st) == 0 ? 200 : 201;
9902 mg_printf(nc,
"HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code);
9903 }
else if (rc == -1) {
9905 }
else if (cl_hdr == NULL) {
9911 int64_t r1 = 0, r2 = 0;
9914 pd->
file.
cl = to64(cl_hdr->
p);
9915 if (range_hdr != NULL &&
9918 fseeko(pd->
file.
fp, r1, SEEK_SET);
9919 pd->
file.
cl = r2 > r1 ? r2 - r1 + 1 : pd->
file.
cl - r1;
9921 mg_printf(nc,
"HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n", status_code);
9929#ifdef MG_MODULE_LINES
9930#line 1 "mongoose/src/mg_http_websocket.c"
9937#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBSOCKET
9941#ifndef MG_WEBSOCKET_PING_INTERVAL_SECONDS
9942#define MG_WEBSOCKET_PING_INTERVAL_SECONDS 5
9945#define FLAGS_MASK_FIN (1 << 7)
9946#define FLAGS_MASK_OP 0x0f
9949 return (flags & FLAGS_MASK_FIN) == 0 ||
9954 return (flags & FLAGS_MASK_FIN) == 0 &&
9958static int mg_is_ws_control_frame(
unsigned char flags) {
9959 unsigned char op = (flags & FLAGS_MASK_OP);
9966 if (wsm->
flags & 0x8) {
9973static struct mg_ws_proto_data *mg_ws_get_proto_data(
struct mg_connection *nc) {
9975 return (htd != NULL ? &htd->ws_data : NULL);
9984 if ((
int) len == ~0) {
9985 len = strlen((
const char *)
data);
9993 uint64_t
i, data_len = 0, frame_len = 0, new_data_len = nc->
recv_mbuf.
len,
9994 len, mask_len = 0, header_len = 0;
9995 struct mg_ws_proto_data *wsd = mg_ws_get_proto_data(nc);
9996 unsigned char *new_data = (
unsigned char *) nc->
recv_mbuf.
buf,
10001 if (wsd->reass_len > 0) {
10012 size_t existing_len = wsd->reass_len;
10013 assert(new_data_len >= existing_len);
10015 new_data += existing_len;
10016 new_data_len -= existing_len;
10019 flags = new_data[0];
10024 if (reass && mg_is_ws_control_frame(flags)) {
10029 mg_ws_close(nc,
"fragmented control frames are illegal", ~0);
10031 }
else if (new_data_len > 0 && !reass && !mg_is_ws_control_frame(flags) &&
10032 wsd->reass_len > 0) {
10037 mg_ws_close(nc,
"non-continuation in the middle of a fragmented message",
10042 if (new_data_len >= 2) {
10043 len = new_data[1] & 0x7f;
10044 mask_len = new_data[1] & FLAGS_MASK_FIN ? 4 : 0;
10045 if (len < 126 && new_data_len >= mask_len) {
10047 header_len = 2 + mask_len;
10048 }
else if (len == 126 && new_data_len >= 4 + mask_len) {
10049 header_len = 4 + mask_len;
10050 data_len = ntohs(*(uint16_t *) &new_data[2]);
10051 }
else if (new_data_len >= 10 + mask_len) {
10052 header_len = 10 + mask_len;
10053 data_len = (((uint64_t) ntohl(*(uint32_t *) &new_data[2])) << 32) +
10054 ntohl(*(uint32_t *) &new_data[6]);
10058 frame_len = header_len + data_len;
10059 ok = (frame_len > 0 && frame_len <= new_data_len);
10062 if (frame_len < header_len || frame_len < data_len) {
10064 mg_ws_close(nc,
"overflowed message", ~0);
10068 size_t cleanup_len = 0;
10071 wsm.
size = (size_t) data_len;
10072 wsm.
data = new_data + header_len;
10076 if (mask_len > 0) {
10077 for (
i = 0;
i < data_len;
i++) {
10078 new_data[
i + header_len] ^= (new_data + header_len - mask_len)[
i % 4];
10091 wsd->reass_len = 1 ;
10095 memmove(new_data, wsm.
data,
e - wsm.
data);
10096 wsd->reass_len += wsm.
size;
10099 if (
flags & FLAGS_MASK_FIN) {
10103 wsm.
size = wsd->reass_len - 1 ;
10104 cleanup_len = wsd->reass_len;
10105 wsd->reass_len = 0;
10117 cleanup_len = (size_t) frame_len;
10120 switch (
flags & FLAGS_MASK_OP) {
10126 mg_ws_close(nc, wsm.
data, wsm.
size);
10165#if MG_DISABLE_WS_RANDOM_MASK
10168 if (
sizeof(
long) >= 4) {
10169 mask = (uint32_t) rand();
10170 }
else if (
sizeof(
long) == 2) {
10171 mask = (uint32_t) rand() << 16 | (uint32_t) rand();
10180 unsigned char header[10];
10185 header[1] = (
unsigned char) len;
10187 }
else if (len < 65535) {
10188 uint16_t tmp = htons((uint16_t) len);
10190 memcpy(&header[2], &tmp,
sizeof(tmp));
10195 tmp = htonl((uint32_t)((uint64_t) len >> 32));
10196 memcpy(&header[2], &tmp,
sizeof(tmp));
10197 tmp = htonl((uint32_t)(len & 0xffffffff));
10198 memcpy(&header[6], &tmp,
sizeof(tmp));
10204 header[1] |= 1 << 7;
10205 mg_send(nc, header, header_len);
10210 mg_send(nc, header, header_len);
10217 if (ctx->
pos == 0)
return;
10226 DBG((
"%p %d %d", nc, op, (
int) len));
10238 const struct mg_str *strv,
int strvcnt) {
10242 for (
i = 0;
i < strvcnt;
i++) {
10243 len += strv[
i].
len;
10248 for (
i = 0;
i < strvcnt;
i++) {
10260 const char *fmt, ...) {
10266 if ((len =
mg_avprintf(&buf,
sizeof(mem), fmt, ap)) > 0) {
10271 if (buf != mem && buf != NULL) {
10277 void *ev_data
MG_UD_ARG(
void *user_data)) {
10288 time_t now = *(time_t *) ev_data;
10298#if MG_ENABLE_CALLBACK_USERDATA
10305 const size_t *msg_lens, uint8_t *digest) {
10309 for (
i = 0;
i < num_msgs;
i++) {
10315extern void mg_hash_sha1_v(
size_t num_msgs,
const uint8_t *msgs[],
10316 const size_t *msg_lens, uint8_t *digest);
10322 static const char *magic =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
10323 const uint8_t *msgs[2] = {(
const uint8_t *)
key->p, (
const uint8_t *) magic};
10324 const size_t msg_lens[2] = {
key->len, 36};
10325 unsigned char sha[20];
10332 "HTTP/1.1 101 Switching Protocols\r\n"
10333 "Upgrade: websocket\r\n"
10334 "Connection: Upgrade\r\n");
10338 mg_printf(nc,
"Sec-WebSocket-Protocol: %.*s\r\n", (
int) s->
len, s->
p);
10340 mg_printf(nc,
"Sec-WebSocket-Accept: %s%s", b64_sha,
"\r\n\r\n");
10342 DBG((
"%p %.*s %s", nc, (
int)
key->len,
key->p, b64_sha));
10346 const char *host,
const char *protocol,
10347 const char *extra_headers) {
10353 const char *host,
const char *protocol,
10354 const char *extra_headers,
const char *user,
10355 const char *pass) {
10362 const struct mg_str path,
10363 const struct mg_str host,
10364 const struct mg_str protocol,
10365 const struct mg_str extra_headers,
10366 const struct mg_str user,
10367 const struct mg_str pass) {
10378 if (user.
len > 0) {
10389 "GET %.*s HTTP/1.1\r\n"
10390 "Upgrade: websocket\r\n"
10391 "Connection: Upgrade\r\n"
10393 "Sec-WebSocket-Version: 13\r\n"
10394 "Sec-WebSocket-Key: %s\r\n",
10395 (
int) path.
len, path.
p, (
int) auth.len,
10396 (auth.buf == NULL ?
"" : auth.
buf),
key);
10399 if (host.
len > 0) {
10400 int host_len = (int) (path.
p - host.
p);
10401 mg_printf(nc,
"Host: %.*s\r\n", host_len, host.
p);
10403 if (protocol.
len > 0) {
10404 mg_printf(nc,
"Sec-WebSocket-Protocol: %.*s\r\n", (
int) protocol.
len,
10407 if (extra_headers.
len > 0) {
10408 mg_printf(nc,
"%.*s", (
int) extra_headers.
len, extra_headers.
p);
10418 const char *extra_headers) {
10421 nc,
mg_mk_str(path), null_str , null_str ,
10422 mg_mk_str(extra_headers), null_str , null_str );
10428 const char *extra_headers) {
10433 "ws",
"https",
"wss", url, &path, &user_info, &host);
10444 const char *url,
const char *protocol,
const char *extra_headers) {
10446 memset(&opts, 0,
sizeof(opts));
10448 protocol, extra_headers);
10451#ifdef MG_MODULE_LINES
10452#line 1 "mongoose/src/mg_util.c"
10465#define MAX(a, b) ((a) > (b) ? (a) : (b))
10468const char *
mg_skip(
const char *s,
const char *
end,
const char *delims,
10471 while (s <
end && strchr(delims, *(
unsigned char *) s) == NULL) s++;
10473 while (s <
end && strchr(delims, *(
unsigned char *) s) != NULL) s++;
10477#if MG_ENABLE_FILESYSTEM && !defined(MG_USER_FILE_FUNCTIONS)
10478int mg_stat(
const char *path, cs_stat_t *st) {
10482 DBG((
"[%ls] -> %d", wpath, _wstati64(wpath, st)));
10483 return _wstati64(wpath, st);
10485 return stat(path, st);
10489FILE *
mg_fopen(
const char *path,
const char *mode) {
10494 return _wfopen(wpath, wmode);
10496 return fopen(path, mode);
10500int mg_open(
const char *path,
int flag,
int mode) {
10501#if defined(_WIN32) && !defined(WINCE)
10504 return _wopen(wpath, flag, mode);
10506 return open(path, flag, mode);
10510size_t mg_fread(
void *ptr,
size_t size,
size_t count, FILE *f) {
10511 return fread(ptr, size,
count, f);
10514size_t mg_fwrite(
const void *ptr,
size_t size,
size_t count, FILE *f) {
10515 return fwrite(ptr, size,
count, f);
10527#if MG_ENABLE_THREADS
10530 return (
void *) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) f, p, 0, NULL);
10531#elif defined(_WIN32)
10532 return (
void *) _beginthread((
void(__cdecl *) (
void *) ) f, 0, p);
10534 pthread_t thread_id = (pthread_t) 0;
10535 pthread_attr_t attr;
10537 (void) pthread_attr_init(&attr);
10538 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10540#if defined(MG_STACK_SIZE) && MG_STACK_SIZE > 1
10541 (void) pthread_attr_setstacksize(&attr, MG_STACK_SIZE);
10544 pthread_create(&thread_id, &attr, f, p);
10545 pthread_attr_destroy(&attr);
10547 return (
void *) thread_id;
10554#if defined(_WIN32) && !defined(WINCE)
10555 (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
10556#elif defined(__unix__)
10557 fcntl(sock, F_SETFD, FD_CLOEXEC);
10566 if (buf == NULL || len <= 0)
return 0;
10567 memset(buf, 0, len);
10569 is_v6 = sa->
sa.sa_family == AF_INET6;
10575 const void *
addr = NULL;
10577 socklen_t capacity = len;
10581 addr = (
void *) &sa->
sin6.sin6_addr;
10591#elif defined(_WIN32) || MG_LWIP || (MG_NET_IF == MG_NET_IF_PIC32)
10594 if (addr_str != NULL) {
10600 if (
inet_ntop(AF_INET, (
void *) &sa->
sin.sin_addr, buf, len) == NULL) {
10606 int port = ntohs(sa->
sin.sin_port);
10608 int buf_len = strlen(buf);
10609 snprintf(buf + buf_len, len - (buf_len + 1),
"%s:%d", (is_v6 ?
"]" :
""),
10612 snprintf(buf, len,
"%d", port);
10616 return strlen(buf);
10626 memset(&
sa, 0,
sizeof(
sa));
10631#if MG_ENABLE_HEXDUMP
10632static int mg_hexdump_n(
const void *buf,
int len,
char *dst,
int dst_len,
10634 const unsigned char *p = (
const unsigned char *) buf;
10635 char ascii[17] =
"";
10638 for (
i = 0;
i < len;
i++) {
10641 if (
i > 0)
n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
" %s\n", ascii);
10642 n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
"%04x ",
i +
offset);
10644 if (dst_len -
n < 0) {
10647 n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
" %02x", p[
i]);
10648 ascii[idx] = p[
i] < 0x20 || p[
i] > 0x7e ?
'.' : p[
i];
10649 ascii[idx + 1] =
'\0';
10652 while (
i++ % 16)
n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
"%s",
" ");
10653 n += snprintf(dst +
n,
MAX(dst_len -
n, 0),
" %s\n", ascii);
10658int mg_hexdump(
const void *buf,
int len,
char *dst,
int dst_len) {
10659 return mg_hexdump_n(buf, len, dst, dst_len, 0);
10662void mg_hexdumpf(FILE *
fp,
const void *buf,
int len) {
10666 n = (len < 16 ? len : 16);
10667 mg_hexdump_n(((
const char *) buf) +
offset,
n, tmp,
sizeof(tmp),
offset);
10675 const void *buf,
int num_bytes,
int ev) {
10677 char src[60], dst[60];
10678 const char *tag = NULL;
10696 if (tag == NULL)
return;
10698 if (strcmp(path,
"-") == 0) {
10700 }
else if (strcmp(path,
"--") == 0) {
10702#if MG_ENABLE_FILESYSTEM
10707 if (
fp == NULL)
return;
10714 fprintf(
fp,
"%lu %p %s %s %s %d\n", (
unsigned long)
mg_time(), (
void *) nc,
10715 src, tag, dst, (
int) num_bytes);
10716 if (num_bytes > 0) {
10717 mg_hexdumpf(
fp, buf, num_bytes);
10719 if (
fp != stdout &&
fp != stderr) fclose(
fp);
10724 static const int n = 1;
10726 return ((
char *) &
n)[0] == 0;
10734 return GetLastError();
10751 struct mbuf *buf) {
10752 const char *header_prefix =
"Authorization: Basic ";
10753 const char *header_suffix =
"\r\n";
10758 mbuf_append(buf, header_prefix, strlen(header_prefix));
10761 if (pass.
len > 0) {
10766 mbuf_append(buf, header_suffix, strlen(header_suffix));
10770 const struct
mg_str safe, unsigned int flags) {
10773 :
"0123456789abcdef");
10778 for (
i = 0;
i < src.len;
i++) {
10779 const unsigned char c = *((
const unsigned char *) src.p +
i);
10798#ifdef MG_MODULE_LINES
10799#line 1 "mongoose/src/mg_mqtt.c"
10813static uint16_t getu16(
const char *p) {
10814 const uint8_t *up = (
const uint8_t *) p;
10815 return (up[0] << 8) + up[1];
10818static const char *scanto(
const char *p,
struct mg_str *s) {
10819 s->
len = getu16(p);
10821 return s->
p + s->
len;
10826 size_t len = 0, len_len = 0;
10827 const char *p, *
end;
10828 unsigned char lc = 0;
10831 if (io->
len < 2)
return MG_MQTT_ERROR_INCOMPLETE_MSG;
10832 header = io->
buf[0];
10838 while ((
size_t)(p - io->
buf) < io->
len) {
10839 lc = *((
const unsigned char *) p++);
10840 len += (lc & 0x7f) << 7 * len_len;
10842 if (!(lc & 0x80))
break;
10843 if (len_len > 4)
return MG_MQTT_ERROR_MALFORMED_MSG;
10847 if (lc & 0x80 || len > (io->
len - (p - io->
buf))) {
10848 return MG_MQTT_ERROR_INCOMPLETE_MSG;
10857 if (p >
end - 4)
return MG_MQTT_ERROR_MALFORMED_MSG;
10862 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10864 if (p >
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10866 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10870 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10874 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10878 if (p >=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10881 if (p !=
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10884 (
"%d %2x %d proto [%.*s] client_id [%.*s] will_topic [%.*s] "
10885 "will_msg [%.*s] user_name [%.*s] password [%.*s]",
10895 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
10906 p = scanto(p, &mm->
topic);
10907 if (p >
end)
return MG_MQTT_ERROR_MALFORMED_MSG;
10909 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
10918 if (
end - p < 2)
return MG_MQTT_ERROR_MALFORMED_MSG;
10938 void *ev_data
MG_UD_ARG(
void *user_data)) {
10941 memset(&mm, 0,
sizeof(mm));
10954 if (
len == MG_MQTT_ERROR_MALFORMED_MSG) {
10957 }
else if (
len == MG_MQTT_ERROR_INCOMPLETE_MSG) {
10962 LOG(
LL_ERROR, (
"%p recv buffer (%lu bytes) exceeds the limit "
10963 "%lu bytes, and not drained, closing",
10985 if (pd->keep_alive > 0 && pd->last_control_time > 0 &&
10986 (now - pd->last_control_time) > pd->keep_alive) {
10995static void mg_mqtt_proto_data_destructor(
void *proto_data) {
10999static struct mg_str mg_mqtt_next_topic_component(struct
mg_str *topic) {
11000 struct mg_str res = *topic;
11003 res.
len = (
c - topic->p);
11004 topic->len -= (res.
len + 1);
11005 topic->p += (res.
len + 1);
11015 if (exp.
len == 0)
return 0;
11017 ec = mg_mqtt_next_topic_component(&exp);
11018 tc = mg_mqtt_next_topic_component(&topic);
11020 if (tc.len != 0)
return 0;
11021 if (exp.
len == 0)
break;
11024 if (
mg_vcmp(&ec,
"+") == 0) {
11025 if (tc.len == 0 && topic.
len == 0)
return 0;
11028 if (
mg_vcmp(&ec,
"#") == 0) {
11030 return (exp.
len == 0);
11036 return (tc.len == 0 && topic.
len == 0);
11049static void mg_send_mqtt_header(
struct mg_connection *nc, uint8_t cmd,
11050 uint8_t flags,
size_t len) {
11052 uint8_t buf[1 +
sizeof(size_t)];
11053 uint8_t *vlen = &buf[1];
11055 buf[0] = (cmd << 4) | flags;
11059 *vlen = len % 0x80;
11061 if (len > 0) *vlen |= 0x80;
11065 mg_send(nc, buf, vlen - buf);
11066 pd->last_control_time =
mg_time();
11077 uint16_t id_len = 0, wt_len = 0, wm_len = 0, user_len = 0, pw_len = 0;
11081 if (client_id != NULL) {
11082 id_len = strlen(client_id);
11085 total_len = 7 + 1 + 2 + 2 + id_len;
11087 if (opts.user_name != NULL) {
11090 if (opts.password != NULL) {
11093 if (opts.will_topic != NULL && opts.will_message != NULL) {
11094 wt_len = strlen(opts.will_topic);
11095 wm_len = strlen(opts.will_message);
11098 if (opts.keep_alive == 0) {
11099 opts.keep_alive = 60;
11103 total_len += 2 + wt_len + 2 + wm_len;
11106 user_len = strlen(opts.user_name);
11107 total_len += 2 + user_len;
11110 pw_len = strlen(opts.password);
11111 total_len += 2 + pw_len;
11115 mg_send(nc,
"\00\04MQTT\04", 7);
11118 netbytes = htons(opts.keep_alive);
11121 netbytes = htons(id_len);
11123 mg_send(nc, client_id, id_len);
11126 netbytes = htons(wt_len);
11128 mg_send(nc, opts.will_topic, wt_len);
11130 netbytes = htons(wm_len);
11132 mg_send(nc, opts.will_message, wm_len);
11136 netbytes = htons(user_len);
11138 mg_send(nc, opts.user_name, user_len);
11141 netbytes = htons(pw_len);
11143 mg_send(nc, opts.password, pw_len);
11147 pd->keep_alive = opts.keep_alive;
11152 uint16_t message_id,
int flags,
const void *
data,
11155 uint16_t topic_len = strlen(topic);
11157 size_t total_len = 2 + topic_len + len;
11164 netbytes = htons(topic_len);
11166 mg_send(nc, topic, topic_len);
11169 netbytes = htons(message_id);
11178 size_t topics_len, uint16_t message_id) {
11181 uint16_t topic_len;
11182 size_t total_len = 2;
11184 for (
i = 0;
i < topics_len;
i++) {
11185 total_len += 2 + strlen(topics[
i].topic) + 1;
11190 netbytes = htons(message_id);
11191 mg_send(nc, (
char *) &netbytes, 2);
11193 for (
i = 0;
i < topics_len;
i++) {
11194 topic_len = strlen(topics[
i].topic);
11195 netbytes = htons(topic_len);
11197 mg_send(nc, topics[
i].topic, topic_len);
11203 struct mg_str *topic, uint8_t *qos,
int pos) {
11204 unsigned char *buf = (
unsigned char *) msg->
payload.
p + pos;
11207 if ((
size_t) pos >= msg->payload.len)
return -1;
11209 topic->len = buf[0] << 8 | buf[1];
11210 topic->p = (
char *) buf + 2;
11211 new_pos = pos + 2 + topic->len + 1;
11212 if ((
size_t) new_pos > msg->payload.len)
return -1;
11213 *qos = buf[2 + topic->len];
11218 size_t topics_len, uint16_t message_id) {
11221 uint16_t topic_len;
11222 size_t total_len = 2;
11224 for (
i = 0;
i < topics_len;
i++) {
11225 total_len += 2 + strlen(topics[
i]);
11230 netbytes = htons(message_id);
11231 mg_send(nc, (
char *) &netbytes, 2);
11233 for (
i = 0;
i < topics_len;
i++) {
11234 topic_len = strlen(topics[
i]);
11235 netbytes = htons(topic_len);
11237 mg_send(nc, topics[
i], topic_len);
11242 uint8_t unused = 0;
11245 mg_send(nc, &return_code, 1);
11254 uint16_t message_id) {
11258 mg_send_mqtt_header(nc, cmd, flags, 2 );
11260 netbytes = htons(message_id);
11281 uint16_t message_id) {
11287 netbytes = htons(message_id);
11290 for (
i = 0;
i < qoss_len;
i++) {
11312#ifdef MG_MODULE_LINES
11313#line 1 "mongoose/src/mg_mqtt_server.c"
11323#if MG_ENABLE_MQTT_BROKER
11325static void mg_mqtt_session_init(
struct mg_mqtt_broker *brk,
11326 struct mg_mqtt_session *s,
11329 s->subscriptions = NULL;
11330 s->num_subscriptions = 0;
11334static void mg_mqtt_add_session(
struct mg_mqtt_session *s) {
11338static void mg_mqtt_remove_session(
struct mg_mqtt_session *s) {
11342static void mg_mqtt_destroy_session(
struct mg_mqtt_session *s) {
11344 for (
i = 0;
i < s->num_subscriptions;
i++) {
11345 MG_FREE((
void *) s->subscriptions[
i].topic);
11351static void mg_mqtt_close_session(
struct mg_mqtt_session *s) {
11352 mg_mqtt_remove_session(s);
11353 mg_mqtt_destroy_session(s);
11356void mg_mqtt_broker_init(
struct mg_mqtt_broker *brk,
void *user_data) {
11358 brk->user_data = user_data;
11361static void mg_mqtt_broker_handle_connect(
struct mg_mqtt_broker *brk,
11363 struct mg_mqtt_session *s =
11364 (
struct mg_mqtt_session *)
MG_CALLOC(1,
sizeof *s);
11374 mg_mqtt_session_init(brk, s, nc);
11376 mg_mqtt_add_session(s);
11381static void mg_mqtt_broker_handle_subscribe(
struct mg_connection *nc,
11383 struct mg_mqtt_session *ss = (
struct mg_mqtt_session *) nc->
priv_2;
11384 uint8_t qoss[MG_MQTT_MAX_SESSION_SUBSCRIPTIONS];
11385 size_t num_subs = 0;
11393 if (num_subs >=
sizeof(MG_MQTT_MAX_SESSION_SUBSCRIPTIONS) ||
11394 (ss->num_subscriptions + num_subs >=
11395 MG_MQTT_MAX_SESSION_SUBSCRIPTIONS)) {
11399 qoss[num_subs++] =
qos;
11402 if (num_subs > 0) {
11405 sizeof(*ss->subscriptions) * (ss->num_subscriptions + num_subs));
11410 ss->subscriptions = te;
11412 pos < (int) msg->payload.len &&
11414 ss->num_subscriptions++) {
11415 te = &ss->subscriptions[ss->num_subscriptions];
11423 if (pos == (
int) msg->payload.len) {
11431static void mg_mqtt_broker_handle_publish(
struct mg_mqtt_broker *brk,
11433 struct mg_mqtt_session *s;
11436 for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
11437 for (
i = 0;
i < s->num_subscriptions;
i++) {
11440 char buf[100], *p = buf;
11458 struct mg_mqtt_broker *brk;
11463 brk = (
struct mg_mqtt_broker *) nc->
priv_2;
11472 if (nc->
priv_2 == NULL) {
11473 mg_mqtt_broker_handle_connect(brk, nc);
11480 if (nc->
priv_2 != NULL) {
11481 mg_mqtt_broker_handle_subscribe(nc, msg);
11488 if (nc->
priv_2 != NULL) {
11489 mg_mqtt_broker_handle_publish(brk, msg);
11497 mg_mqtt_close_session((
struct mg_mqtt_session *) nc->
priv_2);
11503struct mg_mqtt_session *mg_mqtt_next(
struct mg_mqtt_broker *brk,
11504 struct mg_mqtt_session *s) {
11509#ifdef MG_MODULE_LINES
11510#line 1 "mongoose/src/mg_dns.c"
11538 for (rr = (prev == NULL ? msg->
answers : prev + 1);
11540 if (rr->
rtype == query) {
11550 switch (rr->
rtype) {
11552 if (data_len <
sizeof(
struct in_addr)) {
11562 if (data_len <
sizeof(
struct in6_addr)) {
11580 memset(&header, 0,
sizeof(header));
11582 header.flags = htons(msg->
flags);
11586 return mbuf_insert(io, pos, &header,
sizeof(header));
11602 size_t pos = io->
len;
11605 if ((s = strchr(
name,
'.')) == NULL) {
11609 if (s -
name > 127) {
11622 }
while (*s !=
'\0');
11625 return io->
len - pos;
11629 const char *
name,
size_t nlen,
const void *
rdata,
11631 size_t pos = io->
len;
11643 u16 = htons(rr->
rtype);
11645 u16 = htons(rr->
rclass);
11649 u32 = htonl(rr->
ttl);
11655 size_t off = io->
len;
11661 io->
buf[off] = u16 >> 8;
11662 io->
buf[off + 1] = u16 & 0xff;
11664 u16 = htons((uint16_t) rlen);
11670 return io->
len - pos;
11680 DBG((
"%s %d",
name, query_type));
11685 msg->
flags = 0x100;
11690 rr->
rtype = query_type;
11701 uint16_t len = htons((uint16_t) pkt.len);
11705 mg_send(nc, pkt.buf, pkt.len);
11716 int chunk_len, data_len;
11719 if (((
unsigned char *)
data)[0] & 0xc0) {
11723 data += chunk_len + 1;
11746 rr->
ttl = (uint32_t)
data[0] << 24 | (uint32_t)
data[1] << 16 |
11750 data_len = *
data << 8 | *(
data + 1);
11762 unsigned char *
data = (
unsigned char *) buf +
sizeof(*header);
11763 unsigned char *
end = (
unsigned char *) buf + len;
11766 memset(msg, 0,
sizeof(*msg));
11770 if (len < (
int)
sizeof(*header))
return -1;
11785 if (
data == NULL)
return -1;
11790 if (
data == NULL)
return -1;
11797 char *dst,
int dst_len) {
11798 int chunk_len, num_ptrs = 0;
11799 char *old_dst = dst;
11800 const unsigned char *
data = (
unsigned char *)
name->p;
11801 const unsigned char *
end = (
unsigned char *) msg->
pkt.
p + msg->
pkt.
len;
11807 while ((chunk_len = *
data++)) {
11808 int leeway = dst_len - (dst - old_dst);
11813 if ((chunk_len & 0xc0) == 0xc0) {
11814 uint16_t off = (
data[-1] & (~0xc0)) << 8 |
data[0];
11815 if (off >= msg->
pkt.
len) {
11819 if (++num_ptrs > 15) {
11822 data = (
unsigned char *) msg->
pkt.
p + off;
11825 if (chunk_len > 63) {
11828 if (chunk_len > leeway) {
11829 chunk_len = leeway;
11832 if (
data + chunk_len >=
end) {
11836 memcpy(dst,
data, chunk_len);
11839 leeway -= chunk_len;
11841 return dst - old_dst;
11846 if (dst != old_dst) {
11849 return dst - old_dst;
11853 void *ev_data
MG_UD_ARG(
void *user_data)) {
11867 memset(&msg, 0,
sizeof(msg));
11868 msg.
flags = 0x8081;
11871 uint16_t len = htons((uint16_t) io->
len);
11889#ifdef MG_MODULE_LINES
11890#line 1 "mongoose/src/mg_dns_server.c"
11897#if MG_ENABLE_DNS_SERVER
11902struct mg_dns_reply mg_dns_create_reply(struct
mbuf *io,
11904 struct mg_dns_reply rep;
11907 rep.start = io->len;
11910 msg->
flags |= 0x8080;
11917void mg_dns_send_reply(
struct mg_connection *nc,
struct mg_dns_reply *r) {
11918 size_t sent = r->io->len - r->start;
11921 uint16_t len = htons((uint16_t) sent);
11926 mg_send(nc, r->io->buf + r->start, r->io->len - r->start);
11927 r->io->len = r->start;
11931int mg_dns_reply_record(
struct mg_dns_reply *reply,
11933 const char *
name,
int rtype,
int ttl,
const void *rdata,
11934 size_t rdata_len) {
11942 if (
name == NULL) {
11954 rdata_len) == -1) {
11963#ifdef MG_MODULE_LINES
11964#line 1 "mongoose/src/mg_resolv.c"
11971#if MG_ENABLE_ASYNC_RESOLVER
11976#ifndef MG_DEFAULT_NAMESERVER
11977#define MG_DEFAULT_NAMESERVER "8.8.8.8"
12006 wchar_t subkey[512],
value[128],
12007 *
key = L
"SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces";
12009 if ((err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
key, 0, KEY_READ, &
hKey)) !=
12011 fprintf(stderr,
"cannot open reg key %S: %ld\n",
key, err);
12014 for (ret = -1,
i = 0; 1;
i++) {
12016 if (RegEnumKeyExW(
hKey,
i, subkey, &subkey_size, NULL, NULL, NULL,
12017 NULL) != ERROR_SUCCESS) {
12020 if (RegOpenKeyExW(
hKey, subkey, 0, KEY_READ, &hSub) == ERROR_SUCCESS &&
12021 ((RegQueryValueExW(hSub, L
"NameServer", 0, &
type, (
void *)
value,
12022 &len) == ERROR_SUCCESS &&
12023 value[0] !=
'\0') ||
12024 (RegQueryValueExW(hSub, L
"DhcpNameServer", 0, &
type, (
void *)
value,
12025 &len) == ERROR_SUCCESS &&
12026 value[0] !=
'\0'))) {
12035 if (
comma != NULL) {
12047#elif MG_ENABLE_FILESYSTEM && defined(MG_RESOLV_CONF_FILE_NAME)
12051 if ((
fp =
mg_fopen(MG_RESOLV_CONF_FILE_NAME,
"r")) == NULL) {
12055 for (ret = -1; fgets(line,
sizeof(line),
fp) != NULL;) {
12056 unsigned int a, b,
c,
d;
12057 if (sscanf(line,
"nameserver %u.%u.%u.%u", &a, &b, &
c, &
d) == 4) {
12058 snprintf(
name, name_len,
"%u.%u.%u.%u", a, b,
c,
d);
12073#if MG_ENABLE_FILESYSTEM && defined(MG_HOSTS_FILE_NAME)
12079 unsigned int a, b,
c,
d;
12082 if ((
fp =
mg_fopen(MG_HOSTS_FILE_NAME,
"r")) == NULL) {
12086 for (; fgets(line,
sizeof(line),
fp) != NULL;) {
12087 if (line[0] ==
'#')
continue;
12089 if (sscanf(line,
"%u.%u.%u.%u%n", &a, &b, &
c, &
d, &len) == 0) {
12093 for (p = line + len; sscanf(p,
"%s%n", alias, &len) == 1; p += len) {
12094 if (strcmp(alias,
name) == 0) {
12095 usa->
sin.sin_addr.s_addr = htonl(a << 24 | b << 16 |
c << 8 |
d);
12113 time_t now = (time_t)
mg_time();
12116#if !MG_ENABLE_CALLBACK_USERDATA
12121 DBG((
"ev=%d user_data=%p", ev, user_data));
12164 nc->
flags &= ~MG_F_CLOSE_IMMEDIATELY;
12176#ifdef MG_LOG_DNS_FAILURES
12190 memset(&opts, 0,
sizeof(opts));
12200 char dns_server_buff[17], nameserver_url[26];
12202 if (nameserver == NULL) {
12215 req->
name[
sizeof(req->
name) - 1] =
'\0';
12225 if (nameserver == NULL) {
12227 sizeof(dns_server_buff)) != -1) {
12228 nameserver = dns_server_buff;
12234 snprintf(nameserver_url,
sizeof(nameserver_url),
"udp://%s:53", nameserver);
12237 if (dns_nc == NULL) {
12252 if (nameserver != NULL) {
12258#ifdef MG_MODULE_LINES
12259#line 1 "mongoose/src/mg_coap.c"
12283void mg_coap_free_options(
struct mg_coap_message *cm) {
12284 while (cm->options != NULL) {
12285 struct mg_coap_option *next = cm->options->next;
12287 cm->options = next;
12291struct mg_coap_option *mg_coap_add_option(
struct mg_coap_message *cm,
12292 uint32_t number,
char *
value,
12294 struct mg_coap_option *new_option =
12295 (
struct mg_coap_option *)
MG_CALLOC(1,
sizeof(*new_option));
12297 new_option->number = number;
12298 new_option->value.p =
value;
12299 new_option->value.len = len;
12301 if (cm->options == NULL) {
12302 cm->options = cm->optiomg_tail = new_option;
12309 if (cm->optiomg_tail->number <= new_option->number) {
12311 cm->optiomg_tail = cm->optiomg_tail->next = new_option;
12314 struct mg_coap_option *current_opt = cm->options;
12315 struct mg_coap_option *prev_opt = 0;
12317 while (current_opt != NULL) {
12318 if (current_opt->number > new_option->number) {
12321 prev_opt = current_opt;
12322 current_opt = current_opt->next;
12325 if (prev_opt != NULL) {
12326 prev_opt->next = new_option;
12327 new_option->next = current_opt;
12330 new_option->next = cm->options;
12331 cm->options = new_option;
12344static char *coap_parse_header(
char *ptr,
struct mbuf *io,
12345 struct mg_coap_message *cm) {
12346 if (io->
len <
sizeof(uint32_t)) {
12347 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12357 if (((uint8_t) *ptr >> 6) != 1) {
12358 cm->flags |= MG_COAP_IGNORE;
12367 cm->msg_type = ((uint8_t) *ptr & 0x30) >> 4;
12368 cm->flags |= MG_COAP_MSG_TYPE_FIELD;
12376 cm->token.len = *ptr & 0x0F;
12377 if (cm->token.len > 8) {
12378 cm->flags |= MG_COAP_FORMAT_ERROR;
12388 cm->code_class = (uint8_t) *ptr >> 5;
12389 cm->code_detail = *ptr & 0x1F;
12390 cm->flags |= (MG_COAP_CODE_CLASS_FIELD | MG_COAP_CODE_DETAIL_FIELD);
12395 cm->msg_id = (uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1);
12396 cm->flags |= MG_COAP_MSG_ID_FIELD;
12408static char *coap_get_token(
char *ptr,
struct mbuf *io,
12409 struct mg_coap_message *cm) {
12410 if (cm->token.len != 0) {
12411 if (ptr + cm->token.len > io->
buf + io->
len) {
12412 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12416 ptr += cm->token.len;
12417 cm->flags |= MG_COAP_TOKEN_FIELD;
12429static int coap_get_ext_opt(
char *ptr,
struct mbuf *io, uint16_t *opt_info) {
12432 if (*opt_info == 13) {
12437 if (ptr < io->buf + io->
len) {
12438 *opt_info = (uint8_t) *ptr + 13;
12439 ret =
sizeof(uint8_t);
12443 }
else if (*opt_info == 14) {
12448 if (ptr +
sizeof(uint8_t) < io->
buf + io->
len) {
12449 *opt_info = ((uint8_t) *ptr << 8 | (uint8_t) * (ptr + 1)) + 269;
12450 ret =
sizeof(uint16_t);
12475static char *coap_get_options(
char *ptr,
struct mbuf *io,
12476 struct mg_coap_message *cm) {
12477 uint16_t prev_opt = 0;
12479 if (ptr == io->
buf + io->
len) {
12485 while (ptr < io->buf + io->
len && (uint8_t) *ptr != 0xFF) {
12486 uint16_t option_delta, option_lenght;
12490 option_delta = ((uint8_t) *ptr & 0xF0) >> 4;
12492 option_lenght = *ptr & 0x0F;
12494 if (option_delta == 15 || option_lenght == 15) {
12499 cm->flags |= MG_COAP_FORMAT_ERROR;
12506 optinfo_len = coap_get_ext_opt(ptr, io, &option_delta);
12507 if (optinfo_len == -1) {
12508 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12512 ptr += optinfo_len;
12515 optinfo_len = coap_get_ext_opt(ptr, io, &option_lenght);
12516 if (optinfo_len == -1) {
12517 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12521 ptr += optinfo_len;
12528 option_delta += prev_opt;
12530 mg_coap_add_option(cm, option_delta, ptr, option_lenght);
12532 prev_opt = option_delta;
12534 if (ptr + option_lenght > io->
buf + io->
len) {
12535 cm->flags |= MG_COAP_NOT_ENOUGH_DATA;
12539 ptr += option_lenght;
12542 if ((cm->flags & MG_COAP_ERROR) != 0) {
12543 mg_coap_free_options(cm);
12547 cm->flags |= MG_COAP_OPTIOMG_FIELD;
12549 if (ptr == io->
buf + io->
len) {
12559uint32_t mg_coap_parse(
struct mbuf *io,
struct mg_coap_message *cm) {
12562 memset(cm, 0,
sizeof(*cm));
12564 if ((ptr = coap_parse_header(io->
buf, io, cm)) == NULL) {
12568 if ((ptr = coap_get_token(ptr, io, cm)) == NULL) {
12572 if ((ptr = coap_get_options(ptr, io, cm)) == NULL) {
12577 cm->payload.len = io->
len - (ptr - io->
buf);
12578 if (cm->payload.len != 0) {
12579 cm->payload.p = ptr;
12580 cm->flags |= MG_COAP_PAYLOAD_FIELD;
12591static size_t coap_get_ext_opt_size(uint32_t
value) {
12595 ret =
sizeof(uint8_t);
12596 }
else if (
value > 0xFF + 13 &&
value <= 0xFFFF + 269) {
12597 ret =
sizeof(uint16_t);
12608static int coap_split_opt(uint32_t
value, uint8_t *
base, uint16_t *ext) {
12613 }
else if (
value >= 13 &&
value <= 0xFF + 13) {
12616 ret =
sizeof(uint8_t);
12617 }
else if (
value > 0xFF + 13 &&
value <= 0xFFFF + 269) {
12619 *ext =
value - 269;
12620 ret =
sizeof(uint16_t);
12631static char *coap_add_uint16(
char *ptr, uint16_t val) {
12634 *ptr = val & 0x00FF;
12644static char *coap_add_opt_info(
char *ptr, uint16_t val,
size_t len) {
12645 if (len ==
sizeof(uint8_t)) {
12648 }
else if (len ==
sizeof(uint16_t)) {
12649 ptr = coap_add_uint16(ptr, val);
12660static uint32_t coap_calculate_packet_size(
struct mg_coap_message *cm,
12662 struct mg_coap_option *opt;
12663 uint32_t prev_opt_number;
12666 if (cm->msg_type > MG_COAP_MSG_MAX) {
12667 return MG_COAP_ERROR | MG_COAP_MSG_TYPE_FIELD;
12669 if (cm->token.len > 8) {
12670 return MG_COAP_ERROR | MG_COAP_TOKEN_FIELD;
12672 if (cm->code_class > 7) {
12673 return MG_COAP_ERROR | MG_COAP_CODE_CLASS_FIELD;
12675 if (cm->code_detail > 31) {
12676 return MG_COAP_ERROR | MG_COAP_CODE_DETAIL_FIELD;
12679 *len += cm->token.len;
12680 if (cm->payload.len != 0) {
12681 *len += cm->payload.len + 1;
12685 prev_opt_number = 0;
12686 while (opt != NULL) {
12688 *len += coap_get_ext_opt_size(opt->number - prev_opt_number);
12689 *len += coap_get_ext_opt_size((uint32_t) opt->value.len);
12696 if ((opt->next != NULL && opt->number > opt->next->number) ||
12697 opt->value.len > 0xFFFF + 269 ||
12698 opt->number - prev_opt_number > 0xFFFF + 269) {
12699 return MG_COAP_ERROR | MG_COAP_OPTIOMG_FIELD;
12701 *len += opt->value.len;
12702 prev_opt_number = opt->number;
12709uint32_t mg_coap_compose(
struct mg_coap_message *cm,
struct mbuf *io) {
12710 struct mg_coap_option *opt;
12711 uint32_t res, prev_opt_number;
12712 size_t prev_io_len, packet_size;
12715 res = coap_calculate_packet_size(cm, &packet_size);
12721 prev_io_len = io->
len;
12722 if (
mbuf_append(io, NULL, packet_size) == 0)
return MG_COAP_ERROR;
12723 ptr = io->
buf + prev_io_len;
12731 *ptr = (1 << 6) | (cm->msg_type << 4) | (uint8_t)(cm->token.len);
12735 *ptr = (cm->code_class << 5) | (cm->code_detail);
12738 ptr = coap_add_uint16(ptr, cm->msg_id);
12740 if (cm->token.len != 0) {
12741 memcpy(ptr, cm->token.p, cm->token.len);
12742 ptr += cm->token.len;
12746 prev_opt_number = 0;
12747 while (opt != NULL) {
12748 uint8_t delta_base = 0, length_base = 0;
12749 uint16_t delta_ext = 0, length_ext = 0;
12751 size_t opt_delta_len =
12752 coap_split_opt(opt->number - prev_opt_number, &delta_base, &delta_ext);
12753 size_t opt_lenght_len =
12754 coap_split_opt((uint32_t) opt->value.len, &length_base, &length_ext);
12756 *ptr = (delta_base << 4) | length_base;
12759 ptr = coap_add_opt_info(ptr, delta_ext, opt_delta_len);
12760 ptr = coap_add_opt_info(ptr, length_ext, opt_lenght_len);
12762 if (opt->value.len != 0) {
12763 memcpy(ptr, opt->value.p, opt->value.len);
12764 ptr += opt->value.len;
12767 prev_opt_number = opt->number;
12771 if (cm->payload.len != 0) {
12774 memcpy(ptr, cm->payload.p, cm->payload.len);
12781 struct mg_coap_message *cm) {
12782 struct mbuf packet_out;
12783 uint32_t compose_res;
12786 compose_res = mg_coap_compose(cm, &packet_out);
12787 if (compose_res != 0) {
12788 return compose_res;
12791 mg_send(nc, packet_out.buf, (
int) packet_out.len);
12797uint32_t mg_coap_send_ack(
struct mg_connection *nc, uint16_t msg_id) {
12798 struct mg_coap_message cm;
12799 memset(&cm, 0,
sizeof(cm));
12800 cm.msg_type = MG_COAP_MSG_ACK;
12801 cm.msg_id = msg_id;
12803 return mg_coap_send_message(nc, &cm);
12807 void *ev_data
MG_UD_ARG(
void *user_data)) {
12809 struct mg_coap_message cm;
12810 uint32_t parse_res;
12812 memset(&cm, 0,
sizeof(cm));
12818 parse_res = mg_coap_parse(io, &cm);
12819 if ((parse_res & MG_COAP_IGNORE) == 0) {
12820 if ((cm.flags & MG_COAP_NOT_ENOUGH_DATA) != 0) {
12825 cm.flags |= MG_COAP_FORMAT_ERROR;
12827 nc->
handler(nc, MG_COAP_EVENT_BASE + cm.msg_type,
12831 mg_coap_free_options(&cm);
12858#ifdef MG_MODULE_LINES
12859#line 1 "mongoose/src/mg_sntp.c"
12872#define SNTP_TIME_OFFSET 2208988800
12874#ifndef SNTP_TIMEOUT
12875#define SNTP_TIMEOUT 10
12878#ifndef SNTP_ATTEMPTS
12879#define SNTP_ATTEMPTS 3
12882static uint64_t mg_get_sec(uint64_t val) {
12883 return (val & 0xFFFFFFFF00000000) >> 32;
12886static uint64_t mg_get_usec(uint64_t val) {
12887 uint64_t tmp = (val & 0x00000000FFFFFFFF);
12893static void mg_ntp_to_tv(uint64_t val,
struct timeval *
tv) {
12895 tmp = mg_get_sec(val);
12896 tmp -= SNTP_TIME_OFFSET;
12898 tv->tv_usec = mg_get_usec(val);
12901static void mg_get_ntp_ts(
const char *ntp, uint64_t *val) {
12903 memcpy(&tmp, ntp,
sizeof(tmp));
12905 *val = (uint64_t) tmp << 32;
12906 memcpy(&tmp, ntp + 4,
sizeof(tmp));
12912 uint8_t buf[48] = {0};
12918 buf[0] = (3 << 6) | (4 << 3) | 3;
12940#ifndef MG_SNTP_NO_DELAY_CORRECTION
12942 sec = htonl((uint32_t)(
mg_time() + SNTP_TIME_OFFSET));
12943 memcpy(&buf[40], &sec,
sizeof(sec));
12949#ifndef MG_SNTP_NO_DELAY_CORRECTION
12950static uint64_t mg_calculate_delay(uint64_t t1, uint64_t t2, uint64_t t3) {
12952 uint64_t d1 = ((
mg_time() + SNTP_TIME_OFFSET) * 1000000) -
12953 (mg_get_sec(t1) * 1000000 + mg_get_usec(t1));
12954 uint64_t d2 = (mg_get_sec(t3) * 1000000 + mg_get_usec(t3)) -
12955 (mg_get_sec(t2) * 1000000 + mg_get_usec(t2));
12957 return (d1 > d2) ? d1 - d2 : 0;
12961MG_INTERNAL int mg_sntp_parse_reply(
const char *buf,
int len,
12962 struct mg_sntp_message *msg) {
12964 uint64_t trsm_ts_T3, delay = 0;
12974 if ((hdr & 0x38) >> 3 != 4) {
12980 if (mode != 4 && mode != 5) {
12985 memset(msg, 0,
sizeof(*msg));
12987 msg->kiss_of_death = (buf[1] == 0);
12989 mg_get_ntp_ts(&buf[40], &trsm_ts_T3);
12991#ifndef MG_SNTP_NO_DELAY_CORRECTION
12993 uint64_t orig_ts_T1, recv_ts_T2;
12994 mg_get_ntp_ts(&buf[24], &orig_ts_T1);
12995 mg_get_ntp_ts(&buf[32], &recv_ts_T2);
12996 delay = mg_calculate_delay(orig_ts_T1, recv_ts_T2, trsm_ts_T3);
13000 mg_ntp_to_tv(trsm_ts_T3, &
tv);
13002 msg->time = (double)
tv.tv_sec + (((
double)
tv.tv_usec + delay) / 1000000.0);
13008 void *ev_data
MG_UD_ARG(
void *user_data)) {
13009 struct mbuf *io = &
c->recv_mbuf;
13010 struct mg_sntp_message msg;
13016 if (mg_sntp_parse_reply(io->
buf, io->
len, &msg) < 0) {
13017 DBG((
"Invalid SNTP packet received (%d)", (
int) io->
len));
13018 c->handler(
c, MG_SNTP_MALFORMED_REPLY, NULL
MG_UD_ARG(user_data));
13020 c->handler(
c, MG_SNTP_REPLY, (
void *) &msg
MG_UD_ARG(user_data));
13034 c->proto_handler = mg_sntp_handler;
13042 const char *sntp_server_name) {
13044 char url[100], *p_url = url;
13045 const char *proto =
"", *port =
"", *tmp;
13048 tmp = strchr(sntp_server_name,
':');
13049 if (tmp != NULL && *(tmp + 1) ==
'/') {
13050 tmp = strchr(tmp + 1,
':');
13058 if (strncmp(sntp_server_name,
"udp://", 6) != 0) {
13062 mg_asprintf(&p_url,
sizeof(url),
"%s%s%s", proto, sntp_server_name, port);
13070 mg_set_protocol_sntp(
c);
13073 if (p_url != url) {
13085static void mg_sntp_util_ev_handler(
struct mg_connection *
c,
int ev,
13086 void *ev_data
MG_UD_ARG(
void *user_data)) {
13087#if !MG_ENABLE_CALLBACK_USERDATA
13088 void *user_data =
c->user_data;
13090 struct sntp_data *sd = (
struct sntp_data *) user_data;
13094 if (*(
int *) ev_data != 0) {
13095 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_FAILED, NULL);
13100 if (sd->count <= SNTP_ATTEMPTS) {
13101 mg_sntp_send_request(
c);
13105 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_FAILED, NULL);
13109 case MG_SNTP_MALFORMED_REPLY:
13110 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_FAILED, NULL);
13113 case MG_SNTP_REPLY:
13114 mg_call(
c, sd->hander,
c->user_data, MG_SNTP_REPLY, ev_data);
13119 c->user_data = NULL;
13126 const char *sntp_server_name) {
13128 struct sntp_data *sd = (
struct sntp_data *)
MG_CALLOC(1,
sizeof(*sd));
13133 c = mg_sntp_connect(mgr,
MG_CB(mg_sntp_util_ev_handler, sd),
13140 sd->hander = event_handler;
13141#if !MG_ENABLE_CALLBACK_USERDATA
13149#ifdef MG_MODULE_LINES
13150#line 1 "mongoose/src/mg_socks.c"
13172 struct mbuf *r = &
c->recv_mbuf;
13173 if (r->
buf[0] != MG_SOCKS_VERSION) {
13175 }
else if (r->
len > 2 && (
size_t) r->
buf[1] + 2 <= r->
len) {
13177 unsigned char reply[2] = {MG_SOCKS_VERSION, MG_SOCKS_HANDSHAKE_FAILURE};
13179 for (
i = 2;
i < r->
buf[1] + 2;
i++) {
13181 if (r->
buf[
i] == MG_SOCKS_HANDSHAKE_NOAUTH) reply[1] = r->
buf[
i];
13185 c->flags |= MG_SOCKS_HANDSHAKE_DONE;
13193 c2->user_data = NULL;
13196 c->user_data = NULL;
13202 mg_send(c2,
c->recv_mbuf.buf,
c->recv_mbuf.len);
13209static void serv_ev_handler(
struct mg_connection *
c,
int ev,
void *ev_data) {
13215 int res = *(
int *) ev_data;
13216 if (res != 0)
LOG(
LL_ERROR, (
"connect error: %d", res));
13223 c->user_data = serv;
13236 struct mbuf *r = &
c->recv_mbuf;
13237 unsigned char *p = (
unsigned char *) r->
buf;
13238 unsigned char addr_len = 4, reply = MG_SOCKS_SUCCESS;
13239 int ver, cmd, atyp;
13242 if (r->
len < 8)
return;
13248 if (ver != MG_SOCKS_VERSION || cmd != MG_SOCKS_CMD_CONNECT) {
13249 reply = MG_SOCKS_CMD_NOT_SUPPORTED;
13250 }
else if (atyp == MG_SOCKS_ADDR_IPV4) {
13252 if (r->
len < (
size_t) addr_len + 6)
return;
13253 snprintf(
addr,
sizeof(
addr),
"%d.%d.%d.%d:%d", p[4], p[5], p[6], p[7],
13255 mg_socks5_connect(
c,
addr);
13256 }
else if (atyp == MG_SOCKS_ADDR_IPV6) {
13258 if (r->
len < (
size_t) addr_len + 6)
return;
13259 snprintf(
addr,
sizeof(
addr),
"[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
13260 p[4] << 8 | p[5], p[6] << 8 | p[7], p[8] << 8 | p[9],
13261 p[10] << 8 | p[11], p[12] << 8 | p[13], p[14] << 8 | p[15],
13262 p[16] << 8 | p[17], p[18] << 8 | p[19], p[20] << 8 | p[21]);
13263 mg_socks5_connect(
c,
addr);
13264 }
else if (atyp == MG_SOCKS_ADDR_DOMAIN) {
13265 addr_len = p[4] + 1;
13266 if (r->
len < (
size_t) addr_len + 6)
return;
13267 snprintf(
addr,
sizeof(
addr),
"%.*s:%d", p[4], p + 5,
13268 p[4 + addr_len] << 8 | p[4 + addr_len + 1]);
13269 mg_socks5_connect(
c,
addr);
13271 reply = MG_SOCKS_ADDR_NOT_SUPPORTED;
13284 unsigned char buf[] = {MG_SOCKS_VERSION, reply, 0};
13290 c->flags |= MG_SOCKS_CONNECT_DONE;
13293static void socks_handler(
struct mg_connection *
c,
int ev,
void *ev_data) {
13295 if (!(
c->flags & MG_SOCKS_HANDSHAKE_DONE)) mg_socks5_handshake(
c);
13296 if (
c->flags & MG_SOCKS_HANDSHAKE_DONE &&
13297 !(
c->flags & MG_SOCKS_CONNECT_DONE)) {
13298 mg_socks5_handle_request(
c);
13300 if (
c->flags & MG_SOCKS_CONNECT_DONE) relay_data(
c);
13308 c->proto_handler = socks_handler;
13311#ifdef MG_MODULE_LINES
13312#line 1 "common/platforms/cc3200/cc3200_libc.c"
13331#if CS_PLATFORM == CS_P_CC3200
13337#ifndef __TI_COMPILER_VERSION__
13339#include <sys/stat.h>
13340#include <sys/time.h>
13344#include <inc/hw_types.h>
13345#include <inc/hw_memmap.h>
13346#include <driverlib/prcm.h>
13347#include <driverlib/rom.h>
13348#include <driverlib/rom_map.h>
13349#include <driverlib/uart.h>
13350#include <driverlib/utils.h>
13352#define CONSOLE_UART UARTA0_BASE
13354#ifdef __TI_COMPILER_VERSION__
13355int asprintf(
char **strp,
const char *fmt, ...) {
13360 if (*strp == NULL)
return -1;
13363 len = vsnprintf(*strp, BUFSIZ, fmt, ap);
13368 if (*strp == NULL)
return -1;
13371 if (
len >= BUFSIZ) {
13373 len = vsnprintf(*strp,
len + 1, fmt, ap);
13380#if MG_TI_NO_HOST_INTERFACE
13391 while (*
str !=
'\0') {
13407 fprint_str(stderr,
" is not implemented\n");
13419 fprint_str(stderr,
"_getpid is not implemented\n");
13429#ifdef MG_MODULE_LINES
13430#line 1 "common/platforms/msp432/msp432_libc.c"
13449#if CS_PLATFORM == CS_P_MSP432
13451#include <ti/sysbios/BIOS.h>
13452#include <ti/sysbios/knl/Clock.h>
13455 uint32_t ticks = Clock_getTicks();
13456 tp->tv_sec = ticks / 1000;
13457 tp->tv_usec = (ticks % 1000) * 1000;
13462#ifdef MG_MODULE_LINES
13463#line 1 "common/platforms/nrf5/nrf5_libc.c"
13482#if (CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52) && \
13483 defined(__ARMCC_VERSION)
13491#ifdef MG_MODULE_LINES
13492#line 1 "common/platforms/simplelink/sl_fs_slfs.h"
13511#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
13512#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_FS_SLFS_H_
13514#if defined(MG_FS_SLFS)
13517#ifndef __TI_COMPILER_VERSION__
13519#include <sys/stat.h>
13522#define MAX_OPEN_SLFS_FILES 8
13525int fs_slfs_open(
const char *pathname,
int flags, mode_t mode);
13526int fs_slfs_close(
int fd);
13527ssize_t fs_slfs_read(
int fd,
void *buf,
size_t count);
13528ssize_t fs_slfs_write(
int fd,
const void *buf,
size_t count);
13529int fs_slfs_stat(
const char *pathname,
struct stat *s);
13530int fs_slfs_fstat(
int fd,
struct stat *s);
13531off_t fs_slfs_lseek(
int fd, off_t
offset,
int whence);
13532int fs_slfs_unlink(
const char *filename);
13533int fs_slfs_rename(
const char *from,
const char *to);
13535void fs_slfs_set_file_size(
const char *
name,
size_t size);
13536void fs_slfs_set_file_flags(
const char *
name, uint32_t flags, uint32_t *token);
13537void fs_slfs_unset_file_flags(
const char *
name);
13542#ifdef MG_MODULE_LINES
13543#line 1 "common/platforms/simplelink/sl_fs_slfs.c"
13564#if defined(MG_FS_SLFS) || defined(CC3200_FS_SLFS)
13570#if CS_PLATFORM == CS_P_CC3200
13571#include <inc/hw_types.h>
13577#if SL_MAJOR_VERSION_NUM < 2
13578int slfs_open(
const unsigned char *fname, uint32_t flags, uint32_t *token) {
13580 _i32 r = sl_FsOpen(fname, flags, (
unsigned long *) token, &fh);
13581 return (r < 0 ? r : fh);
13584int slfs_open(
const unsigned char *fname, uint32_t flags, uint32_t *token) {
13585 return sl_FsOpen(fname, flags, (
unsigned long *) token);
13590int set_errno(
int e);
13591const char *drop_dir(
const char *fname,
bool *is_slfs);
13597#ifndef FS_SLFS_MAX_FILE_SIZE
13598#define FS_SLFS_MAX_FILE_SIZE (64 * 1024)
13601struct sl_file_open_info {
13614static struct sl_fd_info s_sl_fds[MAX_OPEN_SLFS_FILES];
13615static struct sl_file_open_info s_sl_file_open_infos[MAX_OPEN_SLFS_FILES];
13617static struct sl_file_open_info *fs_slfs_find_foi(
const char *
name,
13620static int sl_fs_to_errno(_i32 r) {
13621 DBG((
"SL error: %d", (
int) r));
13625 case SL_ERROR_FS_FILE_NAME_EXIST:
13627 case SL_ERROR_FS_WRONG_FILE_NAME:
13629 case SL_ERROR_FS_NO_AVAILABLE_NV_INDEX:
13630 case SL_ERROR_FS_NOT_ENOUGH_STORAGE_SPACE:
13632 case SL_ERROR_FS_FAILED_TO_ALLOCATE_MEM:
13634 case SL_ERROR_FS_FILE_NOT_EXISTS:
13636 case SL_ERROR_FS_NOT_SUPPORTED:
13642int fs_slfs_open(
const char *pathname,
int flags, mode_t mode) {
13644 for (fd = 0; fd < MAX_OPEN_SLFS_FILES; fd++) {
13645 if (s_sl_fds[fd].fh <= 0)
break;
13647 if (fd >= MAX_OPEN_SLFS_FILES)
return set_errno(ENOMEM);
13648 struct sl_fd_info *fi = &s_sl_fds[fd];
13654 pathname = drop_dir(pathname, NULL);
13657 fi->size = (size_t) -1;
13658 int rw = (flags & 3);
13659 size_t new_size = 0;
13660 struct sl_file_open_info *foi =
13661 fs_slfs_find_foi(pathname,
false );
13663 LOG(
LL_DEBUG, (
"FOI for %s: %d 0x%x %p", pathname, (
int) foi->size,
13664 (
unsigned int) foi->flags, foi->token));
13666 if (rw == O_RDONLY) {
13667 SlFsFileInfo_t sl_fi;
13668 _i32 r = sl_FsGetInfo((
const _u8 *) pathname, 0, &sl_fi);
13669 if (r == SL_FS_OK) {
13670 fi->size = SL_FI_FILE_SIZE(sl_fi);
13674 if (!(flags & O_TRUNC) || (flags & O_APPEND)) {
13677 return set_errno(ENOTSUP);
13679 if (flags & O_CREAT) {
13680 if (foi->size > 0) {
13681 new_size = foi->size;
13683 new_size = FS_SLFS_MAX_FILE_SIZE;
13685 am = FS_MODE_OPEN_CREATE(new_size, 0);
13689#if SL_MAJOR_VERSION_NUM >= 2
13690 am |= SL_FS_OVERWRITE;
13693 uint32_t *token = NULL;
13696 token = foi->token;
13698 fi->fh = slfs_open((_u8 *) pathname, am, token);
13699 LOG(
LL_DEBUG, (
"sl_FsOpen(%s, 0x%x, %p) sz %u = %d", pathname, (
int) am,
13700 token, (
unsigned int) new_size, (
int) fi->fh));
13706 r = set_errno(sl_fs_to_errno(fi->fh));
13711int fs_slfs_close(
int fd) {
13712 struct sl_fd_info *fi = &s_sl_fds[fd];
13713 if (fi->fh <= 0)
return set_errno(EBADF);
13714 _i32 r = sl_FsClose(fi->fh, NULL, NULL, 0);
13715 LOG(
LL_DEBUG, (
"sl_FsClose(%d) = %d", (
int) fi->fh, (
int) r));
13716 s_sl_fds[fd].fh = -1;
13717 return set_errno(sl_fs_to_errno(r));
13720ssize_t fs_slfs_read(
int fd,
void *buf,
size_t count) {
13721 struct sl_fd_info *fi = &s_sl_fds[fd];
13722 if (fi->fh <= 0)
return set_errno(EBADF);
13725 if (fi->pos == fi->size)
return 0;
13726 _i32 r = sl_FsRead(fi->fh, fi->pos, buf,
count);
13727 DBG((
"sl_FsRead(%d, %d, %d) = %d", (
int) fi->fh, (
int) fi->pos, (
int)
count,
13733 return set_errno(sl_fs_to_errno(r));
13736ssize_t fs_slfs_write(
int fd,
const void *buf,
size_t count) {
13737 struct sl_fd_info *fi = &s_sl_fds[fd];
13738 if (fi->fh <= 0)
return set_errno(EBADF);
13739 _i32 r = sl_FsWrite(fi->fh, fi->pos, (_u8 *) buf,
count);
13740 DBG((
"sl_FsWrite(%d, %d, %d) = %d", (
int) fi->fh, (
int) fi->pos, (
int)
count,
13746 return set_errno(sl_fs_to_errno(r));
13749int fs_slfs_stat(
const char *pathname,
struct stat *s) {
13750 SlFsFileInfo_t sl_fi;
13755 pathname = drop_dir(pathname, NULL);
13756 _i32 r = sl_FsGetInfo((
const _u8 *) pathname, 0, &sl_fi);
13757 if (r == SL_FS_OK) {
13758 s->st_mode = S_IFREG | 0666;
13760 s->st_size = SL_FI_FILE_SIZE(sl_fi);
13763 return set_errno(sl_fs_to_errno(r));
13766int fs_slfs_fstat(
int fd,
struct stat *s) {
13767 struct sl_fd_info *fi = &s_sl_fds[fd];
13768 if (fi->fh <= 0)
return set_errno(EBADF);
13770 s->st_mode = S_IFREG | 0666;
13772 s->st_size = fi->size;
13776off_t fs_slfs_lseek(
int fd, off_t
offset,
int whence) {
13777 if (s_sl_fds[fd].fh <= 0)
return set_errno(EBADF);
13780 s_sl_fds[fd].pos =
offset;
13783 s_sl_fds[fd].pos +=
offset;
13786 return set_errno(ENOTSUP);
13791int fs_slfs_unlink(
const char *pathname) {
13796 pathname = drop_dir(pathname, NULL);
13797 return set_errno(sl_fs_to_errno(sl_FsDel((
const _u8 *) pathname, 0)));
13800int fs_slfs_rename(
const char *from,
const char *to) {
13801 return set_errno(ENOTSUP);
13804static struct sl_file_open_info *fs_slfs_find_foi(
const char *
name,
13807 for (
i = 0;
i < MAX_OPEN_SLFS_FILES;
i++) {
13808 if (s_sl_file_open_infos[
i].
name != NULL &&
13809 strcmp(drop_dir(s_sl_file_open_infos[
i].
name, NULL),
name) == 0) {
13813 if (
i != MAX_OPEN_SLFS_FILES)
return &s_sl_file_open_infos[
i];
13814 if (!
create)
return NULL;
13815 for (
i = 0;
i < MAX_OPEN_SLFS_FILES;
i++) {
13816 if (s_sl_file_open_infos[
i].
name == NULL)
break;
13818 if (
i == MAX_OPEN_SLFS_FILES) {
13821 if (s_sl_file_open_infos[
i].
name != NULL) {
13822 free(s_sl_file_open_infos[
i].
name);
13824 s_sl_file_open_infos[
i].name = strdup(
name);
13825 return &s_sl_file_open_infos[
i];
13828void fs_slfs_set_file_size(
const char *
name,
size_t size) {
13829 struct sl_file_open_info *foi = fs_slfs_find_foi(
name,
true );
13833void fs_slfs_set_file_flags(
const char *
name, uint32_t flags, uint32_t *token) {
13834 struct sl_file_open_info *foi = fs_slfs_find_foi(
name,
true );
13835 foi->flags = flags;
13836 foi->token = token;
13839void fs_slfs_unset_file_flags(
const char *
name) {
13840 struct sl_file_open_info *foi = fs_slfs_find_foi(
name,
false );
13841 if (foi == NULL)
return;
13843 memset(foi, 0,
sizeof(*foi));
13847#ifdef MG_MODULE_LINES
13848#line 1 "common/platforms/simplelink/sl_fs.c"
13867#if MG_NET_IF == MG_NET_IF_SIMPLELINK && \
13868 (defined(MG_FS_SLFS) || defined(MG_FS_SPIFFS))
13870int set_errno(
int e) {
13872 return (
e == 0 ? 0 : -1);
13875const char *drop_dir(
const char *fname,
bool *is_slfs) {
13876 if (is_slfs != NULL) {
13877 *is_slfs = (strncmp(fname,
"SL:", 3) == 0);
13878 if (*is_slfs) fname += 3;
13881 if (fname[0] ==
'.' && fname[1] ==
'/') {
13888 if (fname[0] ==
'/' && strchr(fname + 1,
'/') == NULL) {
13894#if !defined(MG_FS_NO_VFS)
13897#include <stdbool.h>
13901#ifdef __TI_COMPILER_VERSION__
13908#ifdef CC3200_FS_SPIFFS
13916#define NUM_SYS_FDS 3
13917#define SPIFFS_FD_BASE 10
13918#define SLFS_FD_BASE 100
13920#if !defined(MG_UART_CHAR_PUT) && !defined(MG_UART_WRITE)
13921#if CS_PLATFORM == CS_P_CC3200
13922#include <inc/hw_types.h>
13923#include <inc/hw_memmap.h>
13924#include <driverlib/rom.h>
13925#include <driverlib/rom_map.h>
13926#include <driverlib/uart.h>
13927#define MG_UART_CHAR_PUT(fd, c) MAP_UARTCharPut(UARTA0_BASE, c);
13929#define MG_UART_WRITE(fd, buf, len)
13936#ifdef CC3200_FS_SPIFFS
13943static int fd_type(
int fd) {
13944 if (fd >= 0 && fd < NUM_SYS_FDS)
return FD_SYS;
13945#ifdef CC3200_FS_SPIFFS
13946 if (fd >= SPIFFS_FD_BASE && fd < SPIFFS_FD_BASE + MAX_OPEN_SPIFFS_FILES) {
13951 if (fd >= SLFS_FD_BASE && fd < SLFS_FD_BASE + MAX_OPEN_SLFS_FILES) {
13958#if MG_TI_NO_HOST_INTERFACE
13959int open(
const char *pathname,
unsigned flags,
int mode) {
13961int _open(
const char *pathname,
int flags, mode_t mode) {
13965 const char *fname = drop_dir(pathname, &is_sl);
13968 fd = fs_slfs_open(fname, flags, mode);
13969 if (fd >= 0) fd += SLFS_FD_BASE;
13972#ifdef CC3200_FS_SPIFFS
13973 fd = fs_spiffs_open(fname, flags, mode);
13974 if (fd >= 0) fd += SPIFFS_FD_BASE;
13978 (
"open(%s, 0x%x) = %d, fname = %s", pathname, flags, fd, fname));
13982int _stat(
const char *pathname,
struct stat *st) {
13985 const char *fname = drop_dir(pathname, &is_sl);
13986 memset(st, 0,
sizeof(*st));
13988 if (fname[0] ==
'\0' || strcmp(fname,
".") == 0) {
13990 st->st_mode = S_IFDIR | 0777;
13997 res = fs_slfs_stat(fname, st);
14000#ifdef CC3200_FS_SPIFFS
14001 res = fs_spiffs_stat(fname, st);
14004 LOG(
LL_DEBUG, (
"stat(%s) = %d; fname = %s", pathname, res, fname));
14008#if MG_TI_NO_HOST_INTERFACE
14011int _close(
int fd) {
14014 switch (fd_type(fd)) {
14016 r = set_errno(EBADF);
14019 r = set_errno(EACCES);
14021#ifdef CC3200_FS_SPIFFS
14023 r = fs_spiffs_close(fd - SPIFFS_FD_BASE);
14028 r = fs_slfs_close(fd - SLFS_FD_BASE);
14032 DBG((
"close(%d) = %d", fd, r));
14036#if MG_TI_NO_HOST_INTERFACE
14037off_t lseek(
int fd, off_t
offset,
int whence) {
14039off_t _lseek(
int fd, off_t
offset,
int whence) {
14042 switch (fd_type(fd)) {
14044 r = set_errno(EBADF);
14047 r = set_errno(ESPIPE);
14049#ifdef CC3200_FS_SPIFFS
14051 r = fs_spiffs_lseek(fd - SPIFFS_FD_BASE,
offset, whence);
14056 r = fs_slfs_lseek(fd - SLFS_FD_BASE,
offset, whence);
14060 DBG((
"lseek(%d, %d, %d) = %d", fd, (
int)
offset, whence, r));
14064int _fstat(
int fd,
struct stat *s) {
14066 memset(s, 0,
sizeof(*s));
14067 switch (fd_type(fd)) {
14069 r = set_errno(EBADF);
14073 memset(s, 0,
sizeof(*s));
14075 s->st_mode = S_IFCHR | 0666;
14079#ifdef CC3200_FS_SPIFFS
14081 r = fs_spiffs_fstat(fd - SPIFFS_FD_BASE, s);
14086 r = fs_slfs_fstat(fd - SLFS_FD_BASE, s);
14090 DBG((
"fstat(%d) = %d", fd, r));
14094#if MG_TI_NO_HOST_INTERFACE
14095int read(
int fd,
char *buf,
unsigned count) {
14097ssize_t _read(
int fd,
void *buf,
size_t count) {
14100 switch (fd_type(fd)) {
14102 r = set_errno(EBADF);
14106 r = set_errno(EACCES);
14110 r = set_errno(ENOTSUP);
14113#ifdef CC3200_FS_SPIFFS
14115 r = fs_spiffs_read(fd - SPIFFS_FD_BASE, buf,
count);
14120 r = fs_slfs_read(fd - SLFS_FD_BASE, buf,
count);
14124 DBG((
"read(%d, %u) = %d", fd,
count, r));
14128#if MG_TI_NO_HOST_INTERFACE
14129int write(
int fd,
const char *buf,
unsigned count) {
14131ssize_t _write(
int fd,
const void *buf,
size_t count) {
14134 switch (fd_type(fd)) {
14136 r = set_errno(EBADF);
14140 r = set_errno(EACCES);
14143#ifdef MG_UART_WRITE
14144 MG_UART_WRITE(fd, buf,
count);
14145#elif defined(MG_UART_CHAR_PUT)
14149 const char c = ((
const char *) buf)[
i];
14150 if (
c ==
'\n') MG_UART_CHAR_PUT(fd,
'\r');
14151 MG_UART_CHAR_PUT(fd,
c);
14158#ifdef CC3200_FS_SPIFFS
14160 r = fs_spiffs_write(fd - SPIFFS_FD_BASE, buf,
count);
14165 r = fs_slfs_write(fd - SLFS_FD_BASE, buf,
count);
14176#if MG_TI_NO_HOST_INTERFACE || defined(_NEWLIB_VERSION)
14177int rename(
const char *frompath,
const char *topath) {
14179 bool is_sl_from, is_sl_to;
14180 const char *from = drop_dir(frompath, &is_sl_from);
14181 const char *to = drop_dir(topath, &is_sl_to);
14182 if (is_sl_from || is_sl_to) {
14183 set_errno(ENOTSUP);
14185#ifdef CC3200_FS_SPIFFS
14186 r = fs_spiffs_rename(from, to);
14189 DBG((
"rename(%s, %s) = %d", from, to, r));
14194#if MG_TI_NO_HOST_INTERFACE
14195int unlink(
const char *pathname) {
14197int _unlink(
const char *pathname) {
14201 const char *fname = drop_dir(pathname, &is_sl);
14204 r = fs_slfs_unlink(fname);
14207#ifdef CC3200_FS_SPIFFS
14208 r = fs_spiffs_unlink(fname);
14211 DBG((
"unlink(%s) = %d, fname = %s", pathname, r, fname));
14215#ifdef CC3200_FS_SPIFFS
14216DIR *opendir(
const char *dir_name) {
14219 drop_dir(dir_name, &is_sl);
14222 set_errno(ENOTSUP);
14224 r = fs_spiffs_opendir(dir_name);
14226 DBG((
"opendir(%s) = %p", dir_name, r));
14230struct dirent *readdir(
DIR *dir) {
14231 struct dirent *res = fs_spiffs_readdir(dir);
14232 DBG((
"readdir(%p) = %p", dir, res));
14236int closedir(
DIR *dir) {
14237 int res = fs_spiffs_closedir(dir);
14238 DBG((
"closedir(%p) = %d", dir, res));
14242int rmdir(
const char *path) {
14243 return fs_spiffs_rmdir(path);
14246int mkdir(
const char *path, mode_t mode) {
14250 return (strlen(path) == 1 && *path ==
'.') ? 0 : ENOTDIR;
14254int sl_fs_init(
void) {
14256#ifdef __TI_COMPILER_VERSION__
14259#pragma diag_suppress 169
14261 ret = (add_device(
"SL", _MSA, fs_slfs_open, fs_slfs_close, fs_slfs_read,
14262 fs_slfs_write, fs_slfs_lseek, fs_slfs_unlink,
14263 fs_slfs_rename) == 0);
14273#ifdef MG_MODULE_LINES
14274#line 1 "common/platforms/simplelink/sl_socket.c"
14293#if MG_NET_IF == MG_NET_IF_SIMPLELINK
14300const char *
inet_ntop(
int af,
const void *src,
char *dst, socklen_t size) {
14302 struct in_addr *in = (
struct in_addr *) src;
14303 if (af != AF_INET) {
14307 res = snprintf(dst, size,
"%lu.%lu.%lu.%lu", SL_IPV4_BYTE(in->s_addr, 0),
14308 SL_IPV4_BYTE(in->s_addr, 1), SL_IPV4_BYTE(in->s_addr, 2),
14309 SL_IPV4_BYTE(in->s_addr, 3));
14310 return res > 0 ? dst : NULL;
14315 return (
char *)
inet_ntop(AF_INET, &
n, a,
sizeof(a));
14319 uint32_t a0, a1, a2, a3;
14320 uint8_t *db = (uint8_t *) dst;
14321 if (af != AF_INET) {
14325 if (sscanf(src,
"%lu.%lu.%lu.%lu", &a0, &a1, &a2, &a3) != 4) {
14336#ifdef MG_MODULE_LINES
14337#line 1 "common/platforms/simplelink/sl_mg_task.c"
14339#if MG_NET_IF == MG_NET_IF_SIMPLELINK && !defined(MG_SIMPLELINK_NO_OSI)
14343#include <oslib/osi.h>
14354static void mg_task(
void *arg);
14357 if (osi_MsgQCreate(&
s_mg_q,
"MG",
sizeof(
struct mg_q_msg), 16) != OSI_OK) {
14360 if (osi_TaskCreate(
mg_task, (
const signed char *)
"MG", stack_size,
14361 (
void *) mg_init, priority, NULL) != OSI_OK) {
14369 mg_init_cb mg_init = (mg_init_cb) arg;
14375 if (osi_MsgQRead(&
s_mg_q, &msg, 1) != OSI_OK)
continue;
14376 switch (msg.
type) {
14378 msg.
cb(&mgr, msg.
arg);
14386 osi_MsgQWrite(&
s_mg_q, &msg, OSI_NO_WAIT);
14391#ifdef MG_MODULE_LINES
14392#line 1 "common/platforms/simplelink/sl_net_if.h"
14411#ifndef CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_
14412#define CS_COMMON_PLATFORMS_SIMPLELINK_SL_NET_IF_H_
14420#ifndef MG_ENABLE_NET_IF_SIMPLELINK
14421#define MG_ENABLE_NET_IF_SIMPLELINK MG_NET_IF == MG_NET_IF_SIMPLELINK
14431#ifdef MG_MODULE_LINES
14432#line 1 "common/platforms/simplelink/sl_net_if.c"
14453#if MG_ENABLE_NET_IF_SIMPLELINK
14458#define MG_TCP_RECV_BUFFER_SIZE 1024
14459#define MG_UDP_RECV_BUFFER_SIZE 1500
14466 SlSockNonblocking_t opt;
14467#if SL_MAJOR_VERSION_NUM < 2
14468 opt.NonblockingEnabled = 1;
14470 opt.NonBlockingEnabled = 1;
14472 sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &opt,
sizeof(opt));
14476 return (
n < 0 &&
n != SL_ERROR_BSD_EALREADY &&
n != SL_ERROR_BSD_EAGAIN);
14482#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14485 sock_t sock = sl_Socket(AF_INET, SOCK_STREAM, proto);
14491#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14492 nc->
err = sl_set_ssl_opts(sock, nc);
14493 if (nc->
err != 0)
goto out;
14495 nc->
err = sl_Connect(sock, &sa->
sa,
sizeof(sa->
sin));
14497 DBG((
"%p to %s:%d sock %d %d err %d", nc,
inet_ntoa(sa->
sin.sin_addr),
14498 ntohs(sa->
sin.sin_port), nc->
sock, proto, nc->
err));
14502 sock_t sock = sl_Socket(AF_INET, SOCK_DGRAM, 0);
14516 if (sock < 0)
return sock;
14531 int n = (int) sl_Send(nc->
sock, buf, len, 0);
14538 int n = sl_SendTo(nc->
sock, buf, len, 0, &nc->
sa.
sa,
sizeof(nc->
sa.
sin));
14544 int n = sl_Recv(nc->
sock, buf, len, 0);
14556 SlSocklen_t sa_len_t = *sa_len;
14558 (SlSockAddr_t *) sa, &sa_len_t);
14559 *sa_len = sa_len_t;
14573 sl_Close(nc->
sock);
14581 socklen_t sa_len =
sizeof(
sa);
14582 sock_t sock = sl_Accept(lc->
sock, &
sa.sa, &sa_len);
14584 DBG((
"%p: failed to accept: %d", lc, sock));
14593 ntohs(
sa.sin.sin_port)));
14605 (
sa->sa.sa_family == AF_INET) ?
sizeof(
sa->sin) :
sizeof(
sa->sin6);
14606 sock_t sock = sl_Socket(
sa->sa.sa_family,
type, proto);
14607 if (sock < 0)
return sock;
14608#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14609 if ((r = sl_set_ssl_opts(sock, nc)) < 0)
goto clean;
14611 if ((r = sl_Bind(sock, &
sa->sa, sa_len)) < 0)
goto clean;
14612 if (
type != SOCK_DGRAM) {
14613 if ((r = sl_Listen(sock,
SOMAXCONN)) < 0)
goto clean;
14624#define _MG_F_FD_CAN_READ 1
14625#define _MG_F_FD_CAN_WRITE 1 << 1
14626#define _MG_F_FD_ERROR 1 << 2
14629 DBG((
"%p fd=%d fd_flags=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock,
14643 DBG((
"%p conn res=%d", nc, nc->
err));
14644 if (nc->
err == SL_ERROR_BSD_ESECSNOVERIFY ||
14646 nc->
err == SL_ERROR_BSD_ESECDATEERROR
14647#
if SL_MAJOR_VERSION_NUM >= 2
14652 nc->
err == SL_ERROR_BSD_ESECUNKNOWNROOTCA
14680 DBG((
"%p after fd=%d nc_flags=0x%lx rmbl=%d smbl=%d", nc, nc->
sock, nc->
flags,
14688 DBG((
"%p %d", nc, sock));
14693 DBG((
"%p using sl_Select()", iface->
mgr));
14713 struct SlTimeval_t
tv;
14714 SlFdSet_t read_set, write_set, err_set;
14716 int num_fds, num_ev = 0, num_timers = 0;
14718 SL_SOCKET_FD_ZERO(&read_set);
14719 SL_SOCKET_FD_ZERO(&write_set);
14720 SL_SOCKET_FD_ZERO(&err_set);
14736 SL_SOCKET_FD_SET(nc->
sock, &read_set);
14742 SL_SOCKET_FD_SET(nc->
sock, &write_set);
14743 SL_SOCKET_FD_SET(nc->
sock, &err_set);
14760 if (num_timers > 0) {
14761 double timer_timeout_ms = (min_timer -
mg_time()) * 1000 + 1 ;
14762 if (timer_timeout_ms < timeout_ms) {
14763 timeout_ms = timer_timeout_ms;
14766 if (timeout_ms < 0) timeout_ms = 0;
14768 tv.tv_sec = timeout_ms / 1000;
14769 tv.tv_usec = (timeout_ms % 1000) * 1000;
14772 num_ev = sl_Select((
int) max_fd + 1, &read_set, &write_set, &err_set, &
tv);
14776 DBG((
"sl_Select @ %ld num_ev=%d of %d, timeout=%d", (
long) now, num_ev,
14777 num_fds, timeout_ms));
14784 (SL_SOCKET_FD_ISSET(nc->
sock, &read_set) &&
14809 if (remote) memcpy(sa, &nc->
sa,
sizeof(*sa));
14823 ntohs(nc->
sa.
sin.sin_port)));
14826 if (res == 0)
continue;
14831 ntohs(nc->
sa.
sin.sin_port)));
14838#define MG_SL_IFACE_VTABLE \
14842 mg_sl_if_add_conn, \
14843 mg_sl_if_remove_conn, \
14845 mg_sl_if_listen_tcp, \
14846 mg_sl_if_listen_udp, \
14847 mg_sl_if_connect_tcp, \
14848 mg_sl_if_connect_udp, \
14849 mg_sl_if_tcp_send, \
14850 mg_sl_if_udp_send, \
14851 mg_sl_if_tcp_recv, \
14852 mg_sl_if_udp_recv, \
14853 mg_sl_if_create_conn, \
14854 mg_sl_if_destroy_conn, \
14855 mg_sl_if_sock_set, \
14856 mg_sl_if_get_conn_addr, \
14861#if MG_NET_IF == MG_NET_IF_SIMPLELINK
14866#ifdef MG_MODULE_LINES
14867#line 1 "common/platforms/simplelink/sl_ssl_if.c"
14886#if MG_ENABLE_SSL && MG_SSL_IF == MG_SSL_IF_SIMPLELINK
14890#ifndef MG_SSL_IF_SIMPLELINK_SLFS_PREFIX
14891#define MG_SSL_IF_SIMPLELINK_SLFS_PREFIX "SL:"
14894#define MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN \
14895 (sizeof(MG_SSL_IF_SIMPLELINK_SLFS_PREFIX) - 1)
14897struct mg_ssl_if_ctx {
14901 char *ssl_server_name;
14904void mg_ssl_if_init() {
14907enum mg_ssl_if_result mg_ssl_if_conn_init(
14908 struct mg_connection *nc,
const struct mg_ssl_if_conn_params *params,
14909 const char **err_msg) {
14910 struct mg_ssl_if_ctx *ctx =
14911 (
struct mg_ssl_if_ctx *)
MG_CALLOC(1,
sizeof(*ctx));
14914 return MG_SSL_ERROR;
14916 nc->ssl_if_data = ctx;
14918 if (params->cert != NULL || params->key != NULL) {
14919 if (params->cert != NULL && params->key != NULL) {
14920 ctx->ssl_cert = strdup(params->cert);
14921 ctx->ssl_key = strdup(params->key);
14924 return MG_SSL_ERROR;
14927 if (params->ca_cert != NULL && strcmp(params->ca_cert,
"*") != 0) {
14928 ctx->ssl_ca_cert = strdup(params->ca_cert);
14931 if (params->server_name != NULL) {
14932 ctx->ssl_server_name = strdup(params->server_name);
14937enum mg_ssl_if_result mg_ssl_if_conn_accept(
struct mg_connection *nc,
14945enum mg_ssl_if_result mg_ssl_if_handshake(
struct mg_connection *nc) {
14950int mg_ssl_if_read(
struct mg_connection *nc,
void *buf,
size_t len) {
14957int mg_ssl_if_write(
struct mg_connection *nc,
const void *buf,
size_t len) {
14962void mg_ssl_if_conn_close_notify(
struct mg_connection *nc) {
14968 struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
14969 if (ctx == NULL)
return;
14970 nc->ssl_if_data = NULL;
14974 MG_FREE(ctx->ssl_server_name);
14975 memset(ctx, 0,
sizeof(*ctx));
14979bool pem_to_der(
const char *pem_file,
const char *der_file) {
14981 FILE *pf = NULL, *df = NULL;
14982 bool writing =
false;
14983 pf = fopen(pem_file,
"r");
14984 if (pf == NULL)
goto clean;
14986 fs_slfs_set_file_size(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN, 2048);
14987 df = fopen(der_file,
"w");
14988 fs_slfs_unset_file_flags(der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN);
14989 if (df == NULL)
goto clean;
14993 if (!fgets(pem_buf,
sizeof(pem_buf), pf))
break;
14995 if (strstr(pem_buf,
"-----END ") != NULL) {
15000 while (!isspace((
unsigned int) pem_buf[l])) l++;
15003 der_buf, &der_len);
15004 if (der_len <= 0)
break;
15005 if (fwrite(der_buf, 1, der_len, df) != der_len)
break;
15006 }
else if (strstr(pem_buf,
"-----BEGIN ") != NULL) {
15012 if (pf != NULL) fclose(pf);
15015 if (!ret)
remove(der_file);
15020#if MG_ENABLE_FILESYSTEM && defined(MG_FS_SLFS)
15022static char *sl_pem2der(
const char *pem_file) {
15023 const char *pem_ext = strstr(pem_file,
".pem");
15024 if (pem_ext == NULL || *(pem_ext + 4) !=
'\0') {
15025 return strdup(pem_file);
15027 char *der_file = NULL;
15029 int l =
mg_asprintf(&der_file, 0, MG_SSL_IF_SIMPLELINK_SLFS_PREFIX
"%.*s.der",
15030 (
int) (pem_ext - pem_file), pem_file);
15031 if (der_file == NULL)
return NULL;
15032 bool result =
false;
15034 if (
mg_stat(der_file, &st) != 0) {
15035 result = pem_to_der(pem_file, der_file);
15036 LOG(
LL_DEBUG, (
"%s -> %s = %d", pem_file, der_file, result));
15043 memmove(der_file, der_file + MG_SSL_IF_SIMPLELINK_SLFS_PREFIX_LEN,
15052static char *sl_pem2der(
const char *pem_file) {
15053 return strdup(pem_file);
15059 const struct mg_ssl_if_ctx *ctx = (
struct mg_ssl_if_ctx *) nc->ssl_if_data;
15060 DBG((
"%p ssl ctx: %p", nc, ctx));
15062 if (ctx == NULL)
return 0;
15063 DBG((
"%p %s,%s,%s,%s", nc, (ctx->ssl_cert ? ctx->ssl_cert :
"-"),
15064 (ctx->ssl_key ? ctx->ssl_cert :
"-"),
15065 (ctx->ssl_ca_cert ? ctx->ssl_ca_cert :
"-"),
15066 (ctx->ssl_server_name ? ctx->ssl_server_name :
"-")));
15067 if (ctx->ssl_cert != NULL && ctx->ssl_key != NULL) {
15068 char *ssl_cert = sl_pem2der(ctx->ssl_cert), *ssl_key = NULL;
15069 if (ssl_cert != NULL) {
15070 err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
15071 SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
15074 LOG(
LL_DEBUG, (
"CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
15075 ssl_key = sl_pem2der(ctx->ssl_key);
15076 if (ssl_key != NULL) {
15077 err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
15078 SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key,
15081 LOG(
LL_DEBUG, (
"PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
15088 if (err != 0)
return err;
15090 if (ctx->ssl_ca_cert != NULL) {
15091 if (ctx->ssl_ca_cert[0] !=
'\0') {
15092 char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
15093 if (ssl_ca_cert != NULL) {
15095 sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME,
15096 ssl_ca_cert, strlen(ssl_ca_cert));
15097 LOG(
LL_DEBUG, (
"CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
15102 if (err != 0)
return err;
15105 if (ctx->ssl_server_name != NULL) {
15106 err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
15107 SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
15108 ctx->ssl_server_name, strlen(ctx->ssl_server_name));
15109 DBG((
"DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
15114 if (err != 0 && err != SL_ERROR_BSD_ENOPROTOOPT)
return err;
15120#ifdef MG_MODULE_LINES
15121#line 1 "common/platforms/lwip/mg_lwip_net_if.h"
15140#ifndef CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_
15141#define CS_COMMON_PLATFORMS_LWIP_MG_NET_IF_LWIP_H_
15143#ifndef MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
15144#define MG_ENABLE_NET_IF_LWIP_LOW_LEVEL MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
15147#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
15188#ifdef MG_MODULE_LINES
15189#line 1 "common/platforms/lwip/mg_lwip_net_if.c"
15208#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
15212#include <lwip/init.h>
15213#include <lwip/pbuf.h>
15214#include <lwip/tcp.h>
15215#include <lwip/tcpip.h>
15216#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
15217#include <lwip/priv/tcp_priv.h>
15219#include <lwip/tcp_impl.h>
15221#include <lwip/udp.h>
15231#define ip_2_ip4(addr) ipX_2_ip(addr)
15233#define ip_2_ip4(addr) (addr)
15242#define TCP_NEW tcp_new_ip6
15243#define TCP_BIND tcp_bind_ip6
15244#define UDP_BIND udp_bind_ip6
15245#define IPADDR_NTOA(x) ip6addr_ntoa((const ip6_addr_t *)(x))
15246#define SET_ADDR(dst, src) \
15247 memcpy((dst)->sin6.sin6_addr.s6_addr, (src)->ip6.addr, \
15248 sizeof((dst)->sin6.sin6_addr.s6_addr))
15250#define TCP_NEW tcp_new
15251#define TCP_BIND tcp_bind
15252#define UDP_BIND udp_bind
15253#define IPADDR_NTOA ipaddr_ntoa
15254#define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr
15258#define tcpip_callback(fn, arg) (fn)(arg)
15259typedef void (*tcpip_callback_fn)(
void *arg);
15268#if defined(RTOS_SDK) || defined(ESP_PLATFORM)
15273#define mgos_unlock()
15278#if LWIP_TCP_KEEPALIVE
15279void mg_lwip_set_keepalive_params(
struct mg_connection *nc,
int idle,
15280 int interval,
int count) {
15285 struct tcp_pcb *tpcb = cs->pcb.tcp;
15286 if (idle > 0 && interval > 0 &&
count > 0) {
15287 tpcb->keep_idle = idle * 1000;
15288 tpcb->keep_intvl = interval * 1000;
15289 tpcb->keep_cnt =
count;
15290 tpcb->so_options |= SOF_KEEPALIVE;
15292 tpcb->so_options &= ~SOF_KEEPALIVE;
15295#elif !defined(MG_NO_LWIP_TCP_KEEPALIVE)
15296#warning LWIP TCP keepalive is disabled. Please consider enabling it.
15301 DBG((
"%p connect to %s:%u = %d", nc,
IPADDR_NTOA(ipX_2_ip(&tpcb->remote_ip)),
15302 tpcb->remote_port,
err));
15309#if LWIP_TCP_KEEPALIVE
15310 if (
err == 0) mg_lwip_set_keepalive_params(
nc, 60, 10, 6);
15318 DBG((
"%p conn error %d", nc,
err));
15331 struct pbuf *p, err_t
err) {
15335 DBG((
"%p %p %p %p %u %d",
nc, cs, tpcb, p, (p != NULL ? p->tot_len : 0),
15352 }
else if (
nc == NULL) {
15360 if (p->next != NULL) {
15361 struct pbuf *
q = p->next;
15362 for (;
q != NULL;
q =
q->next) pbuf_ref(
q);
15367 }
else if (pbuf_clen(cs->
rx_chain) >= 4) {
15371 struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
15387 DBG((
"%p %p %u %p %p", nc, tpcb, num_sent, tpcb->unsent, tpcb->unacked));
15388 if (nc == NULL)
return ERR_OK;
15390 nc->
send_mbuf.
len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
15412 struct tcp_pcb *tpcb =
TCP_NEW();
15414 ip_addr_t *ip = (ip_addr_t *) &sa->
sin.sin_addr.s_addr;
15415 u16_t port = ntohs(sa->
sin.sin_port);
15421 DBG((
"%p tcp_bind = %d", nc, cs->
err));
15422 if (cs->
err != ERR_OK) {
15427 DBG((
"%p tcp_connect %p = %d", nc, tpcb, cs->
err));
15428 if (cs->
err != ERR_OK) {
15444#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
15446 const ip_addr_t *
addr, u16_t port)
15449 ip_addr_t *
addr, u16_t port)
15462#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
15465 sa->sin.sin_addr.s_addr =
addr->addr;
15467 sa->sin.sin_port = htons(port);
15469 p = pbuf_coalesce(p, PBUF_RAW);
15470 pbuf_chain(sap, p);
15502 struct pbuf *dp = ap->next;
15504 res =
MIN(dp->len, len);
15505 pbuf_copy_partial(dp, buf, res, 0);
15507 pbuf_copy_partial(ap, sa,
MIN(*sa_len, ap->len), 0);
15517 struct udp_pcb *upcb = udp_new();
15519 DBG((
"%p udp_bind %p = %d", nc, upcb, cs->
err));
15520 if (cs->
err == ERR_OK) {
15534 tcp_close((
struct tcp_pcb *) arg);
15539 if (cs->
pcb.
tcp == NULL)
return;
15541 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15543 sa.
sin.sin_port = htons(tpcb->remote_port);
15550 struct tcp_pcb_listen *lpcb;
15552 (
"%p conn %p from %s:%u", lc, newtpcb,
15553 IPADDR_NTOA(ipX_2_ip(&newtpcb->remote_ip)), newtpcb->remote_port));
15555 tcp_abort(newtpcb);
15559 lpcb = (
struct tcp_pcb_listen *) lcs->
pcb.
tcp;
15560#if TCP_LISTEN_BACKLOG
15561 tcp_accepted(lpcb);
15565 tcp_abort(newtpcb);
15573 tcp_arg(newtpcb,
nc);
15577#if LWIP_TCP_KEEPALIVE
15578 mg_lwip_set_keepalive_params(
nc, 60, 10, 6);
15597 struct tcp_pcb *tpcb =
TCP_NEW();
15598 ip_addr_t *ip = (ip_addr_t *) &sa->
sin.sin_addr.s_addr;
15599 u16_t port = ntohs(sa->
sin.sin_port);
15602 if (cs->
err != ERR_OK) {
15608 tpcb = tcp_listen(tpcb);
15625 struct udp_pcb *upcb = udp_new();
15626 ip_addr_t *ip = (ip_addr_t *) &sa->
sin.sin_addr.s_addr;
15627 u16_t port = ntohs(sa->
sin.sin_port);
15630 if (cs->
err != ERR_OK) {
15654 tcp_output((
struct tcp_pcb *) arg);
15661 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15662 size_t len =
MIN(tpcb->mss,
MIN(ctx->
len, tpcb->snd_buf));
15663 size_t unsent, unacked;
15665 DBG((
"%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen,
15666 tpcb->unsent, tpcb->unacked));
15671 unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
15672 unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
15679#if CS_PLATFORM == CS_P_ESP8266
15684 len =
MIN(len, (TCP_MSS - unsent));
15686 cs->
err = tcp_write(tpcb, ctx->
data, len, TCP_WRITE_FLAG_COPY);
15687 unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
15688 unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
15689 DBG((
"%p tcp_write %u = %d, %u %u", tpcb, len, cs->
err, unsent, unacked));
15690 if (cs->
err != ERR_OK) {
15695 ctx->
ret = (cs->
err == ERR_MEM ? 0 : -1);
15707 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15708 if (tpcb == NULL)
return -1;
15709 if (tpcb->snd_buf <= 0)
return 0;
15731 struct udp_pcb *upcb = cs->
pcb.
udp;
15732 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
15733#if defined(LWIP_IPV4) && LWIP_IPV4 && defined(LWIP_IPV6) && LWIP_IPV6
15734 ip_addr_t ip = {.u_addr.ip4.addr = nc->
sa.
sin.sin_addr.s_addr, .type = 0};
15736 ip_addr_t ip = {.addr = nc->
sa.
sin.sin_addr.s_addr};
15738 u16_t port = ntohs(nc->
sa.
sin.sin_port);
15739 if (p == NULL)
return 0;
15740 memcpy(p->payload,
data, len);
15745 return (cs->
err == ERR_OK ? (
int) len : -2);
15755 can_send = (cs->
pcb.
udp != NULL);
15757 can_send = (cs->
pcb.
tcp != NULL && cs->
pcb.
tcp->snd_buf > 0);
15759#if CS_PLATFORM == CS_P_ESP8266
15760 if (cs->
pcb.
tcp->unacked != NULL) can_send = 0;
15774 if (ctx->
tpcb != NULL) tcp_recved(ctx->
tpcb, ctx->
len);
15784 while (cs->
rx_chain != NULL && len > 0) {
15786 size_t seg_len = (seg->len - cs->
rx_offset);
15787 size_t copy_len =
MIN(len, seg_len);
15789 pbuf_copy_partial(seg, bufp, copy_len, cs->
rx_offset);
15811 if (cs == NULL)
return 0;
15818 udp_remove((
struct udp_pcb *) arg);
15825 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15826 if (tpcb != NULL) {
15827 tcp_arg(tpcb, NULL);
15828 DBG((
"%p tcp_close %p", nc, tpcb));
15829 tcp_arg(tpcb, NULL);
15837 memset(cs, 0,
sizeof(*cs));
15839 }
else if (nc->
listener == NULL) {
15841 struct udp_pcb *upcb = cs->
pcb.
udp;
15842 if (upcb != NULL) {
15843 DBG((
"%p udp_remove %p", nc, upcb));
15846 memset(cs, 0,
sizeof(*cs));
15854 memset(sa, 0,
sizeof(*sa));
15858 struct udp_pcb *upcb = cs->
pcb.
udp;
15860 memcpy(sa, &nc->
sa,
sizeof(*sa));
15861 }
else if (upcb != NULL) {
15862 sa->
sin.sin_port = htons(upcb->local_port);
15866 struct tcp_pcb *tpcb = cs->
pcb.
tcp;
15868 memcpy(sa, &nc->
sa,
sizeof(*sa));
15869 }
else if (tpcb != NULL) {
15870 sa->
sin.sin_port = htons(tpcb->local_port);
15881#define MG_LWIP_IFACE_VTABLE \
15885 mg_lwip_if_add_conn, \
15886 mg_lwip_if_remove_conn, \
15888 mg_lwip_if_listen_tcp, \
15889 mg_lwip_if_listen_udp, \
15890 mg_lwip_if_connect_tcp, \
15891 mg_lwip_if_connect_udp, \
15892 mg_lwip_if_tcp_send, \
15893 mg_lwip_if_udp_send, \
15894 mg_lwip_if_tcp_recv, \
15895 mg_lwip_if_udp_recv, \
15896 mg_lwip_if_create_conn, \
15897 mg_lwip_if_destroy_conn, \
15898 mg_lwip_if_sock_set, \
15899 mg_lwip_if_get_conn_addr, \
15904#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
15909#ifdef MG_MODULE_LINES
15910#line 1 "common/platforms/lwip/mg_lwip_ev_mgr.c"
15929#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
15931#ifndef MG_SIG_QUEUE_LEN
15932#define MG_SIG_QUEUE_LEN 32
16003 LWIP_VERSION_MINOR, LWIP_VERSION_REVISION));
16009 iface->
data = NULL;
16032 double min_timer = 0;
16033 int num_timers = 0;
16035 DBG((
"begin poll @%u", (
unsigned int) (now * 1000)));
16045 cs->
pcb.
tcp->unsent != NULL) {
16072 DBG((
"end poll @%u, %d conns, %d timers (min %u), next in %d ms",
16073 (
unsigned int) (now * 1000),
n, num_timers,
16074 (
unsigned int) (min_timer * 1000), timeout_ms));
16081#ifdef MG_MODULE_LINES
16082#line 1 "common/platforms/wince/wince_libc.c"
16103const char *strerror(
int err) {
16108 static char buf[10];
16109 snprintf(buf,
sizeof(buf),
"%d",
err);
16113int open(
const char *filename,
int oflag,
int pmode) {
16123int _wstati64(
const wchar_t *path, cs_stat_t *st) {
16124 DWORD fa = GetFileAttributesW(path);
16125 if (fa == INVALID_FILE_ATTRIBUTES) {
16128 memset(st, 0,
sizeof(*st));
16129 if ((fa & FILE_ATTRIBUTE_DIRECTORY) == 0) {
16132 st->st_mode |= _S_IFREG;
16133 h = CreateFileW(path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
16134 FILE_ATTRIBUTE_NORMAL, NULL);
16135 if (h == INVALID_HANDLE_VALUE) {
16138 st->st_size = GetFileSize(h, NULL);
16139 GetFileTime(h, NULL, NULL, &ftime);
16140 st->st_mtime = (uint32_t)((((uint64_t) ftime.dwLowDateTime +
16141 ((uint64_t) ftime.dwHighDateTime << 32)) /
16146 st->st_mode |= _S_IFDIR;
16154 SYSTEMTIME systime;
16156 uint64_t filetime = (*t + 11644473600) * 10000000;
16157 ft.dwLowDateTime = filetime & 0xFFFFFFFF;
16158 ft.dwHighDateTime = (filetime & 0xFFFFFFFF00000000) >> 32;
16159 FileTimeToSystemTime(&ft, &systime);
16161 GetSystemTime(&systime);
16164 snprintf(buf, buf_len,
"%d.%d.%d %d:%d:%d GMT", (
int) systime.wYear,
16165 (
int) systime.wMonth, (
int) systime.wDay, (
int) systime.wHour,
16166 (
int) systime.wMinute, (
int) systime.wSecond);
16170#ifdef MG_MODULE_LINES
16171#line 1 "common/platforms/pic32/pic32_net_if.h"
16190#ifndef CS_COMMON_PLATFORMS_PIC32_NET_IF_H_
16191#define CS_COMMON_PLATFORMS_PIC32_NET_IF_H_
16199#ifndef MG_ENABLE_NET_IF_PIC32
16200#define MG_ENABLE_NET_IF_PIC32 MG_NET_IF == MG_NET_IF_PIC32
16210#ifdef MG_MODULE_LINES
16211#line 1 "common/platforms/pic32/pic32_net_if.c"
16230#if MG_ENABLE_NET_IF_PIC32
16264 TCPIP_TCP_Close((TCP_SOCKET) nc->
sock);
16265 }
else if (nc->
listener == NULL) {
16267 TCPIP_UDP_Close((UDP_SOCKET) nc->
sock);
16274 nc->
sock = TCPIP_UDP_ServerOpen(
16275 sa->
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16276 : IP_ADDRESS_TYPE_IPV6,
16277 ntohs(sa->
sin.sin_port),
16278 sa->
sin.sin_addr.s_addr == 0 ? 0 : (IP_MULTI_ADDRESS *) &sa->
sin);
16296 nc->
sock = TCPIP_TCP_ServerOpen(
16297 sa->
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16298 : IP_ADDRESS_TYPE_IPV6,
16299 ntohs(sa->
sin.sin_port),
16300 sa->
sin.sin_addr.s_addr == 0 ? 0 : (IP_MULTI_ADDRESS *) &sa->
sin);
16301 memcpy(&nc->
sa, sa,
sizeof(*sa));
16310 TCP_SOCKET_INFO si;
16320 nc->
flags &= ~MG_F_LISTENING;
16322 if (!TCPIP_TCP_SocketInfoGet((TCP_SOCKET) nc->
sock, &si)) {
16326 if (si.addressType == IP_ADDRESS_TYPE_IPV4) {
16327 sa.sin.sin_family = AF_INET;
16328 sa.sin.sin_port = htons(si.remotePort);
16329 sa.sin.sin_addr.s_addr = si.remoteIPaddress.v4Add.Val;
16332 memset(&
sa, 0,
sizeof(
sa));
16341 static char addr[17];
16342 snprintf(
addr,
sizeof(
addr),
"%d.%d.%d.%d", (
int) in.S_un.S_un_b.s_b1,
16343 (
int) in.S_un.S_un_b.s_b2, (
int) in.S_un.S_un_b.s_b3,
16344 (
int) in.S_un.S_un_b.s_b4);
16349 uint16_t bytes_written = 0;
16351 if (!TCPIP_UDP_RemoteBind(
16352 (UDP_SOCKET) nc->
sock,
16353 nc->
sa.
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16354 : IP_ADDRESS_TYPE_IPV6,
16355 ntohs(nc->
sa.
sin.sin_port), (IP_MULTI_ADDRESS *) &nc->
sa.
sin)) {
16359 bytes_written = TCPIP_UDP_TxPutIsReady((UDP_SOCKET) nc->
sock, 0);
16361 if (TCPIP_UDP_ArrayPut((UDP_SOCKET) nc->
sock,
16369 bytes_written = TCPIP_TCP_FifoTxFreeGet((TCP_SOCKET) nc->
sock);
16370 if (bytes_written != 0) {
16374 if (TCPIP_TCP_ArrayPut((TCP_SOCKET) nc->
sock,
16376 bytes_written) != bytes_written) {
16387 uint16_t bytes_read = 0;
16388 uint8_t *buf = NULL;
16390 bytes_read = TCPIP_UDP_GetIsReady((UDP_SOCKET) nc->
sock);
16391 if (bytes_read != 0 &&
16393 nc->
recv_mbuf.
len + bytes_read < nc->recv_mbuf_limit)) {
16394 buf = (uint8_t *)
MG_MALLOC(bytes_read);
16395 if (TCPIP_UDP_ArrayGet((UDP_SOCKET) nc->
sock, buf, bytes_read) !=
16403 bytes_read = TCPIP_TCP_GetIsReady((TCP_SOCKET) nc->
sock);
16404 if (bytes_read != 0) {
16409 buf = (uint8_t *)
MG_MALLOC(bytes_read);
16410 if (TCPIP_TCP_ArrayGet((TCP_SOCKET) nc->
sock, buf, bytes_read) !=
16419 if (bytes_read != 0) {
16435 TCPIP_TCP_IsConnected((TCP_SOCKET) nc->
sock)) {
16439 if (TCPIP_TCP_IsConnected((TCP_SOCKET) nc->
sock)) {
16477 nc->
sock = TCPIP_TCP_ClientOpen(
16478 sa->
sin.sin_family == AF_INET ? IP_ADDRESS_TYPE_IPV4
16479 : IP_ADDRESS_TYPE_IPV6,
16480 ntohs(
sa->
sin.sin_port), (IP_MULTI_ADDRESS *) &
sa->
sin);
16485 nc->
sock = TCPIP_UDP_ClientOpen(IP_ADDRESS_TYPE_ANY, 0, NULL);
16490#define MG_PIC32_IFACE_VTABLE \
16492 mg_pic32_if_init, \
16493 mg_pic32_if_free, \
16494 mg_pic32_if_add_conn, \
16495 mg_pic32_if_remove_conn, \
16496 mg_pic32_if_poll, \
16497 mg_pic32_if_listen_tcp, \
16498 mg_pic32_if_listen_udp, \
16499 mg_pic32_if_connect_tcp, \
16500 mg_pic32_if_connect_udp, \
16501 mg_pic32_if_tcp_send, \
16502 mg_pic32_if_udp_send, \
16503 mg_pic32_if_recved, \
16504 mg_pic32_if_create_conn, \
16505 mg_pic32_if_destroy_conn, \
16506 mg_pic32_if_sock_set, \
16507 mg_pic32_if_get_conn_addr, \
16512#if MG_NET_IF == MG_NET_IF_PIC32
16517#ifdef MG_MODULE_LINES
16518#line 1 "common/platforms/windows/windows_direct.c"
16539int rmdir(
const char *dirname) {
16540 return _rmdir(dirname);
16543unsigned int sleep(
unsigned int seconds) {
16544 Sleep(seconds * 1000);
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)
int mg_mgr_poll(struct mg_mgr *m, int timeout_ms)
void mg_mqtt_ping(struct mg_connection *nc)
void mg_set_protocol_mqtt(struct mg_connection *nc)
void mg_mgr_free(struct mg_mgr *m)
const char * hexdump_file
int mg_resolve_from_hosts_file(const char *host, 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) WEAK
#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],...)
void mg_mqtt_disconnect(struct mg_connection *nc)
#define MG_MQTT_HAS_USER_NAME
#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) WEAK
#define MG_MAX_HTTP_HEADERS
int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) WEAK
#define MG_MAX_HTTP_SEND_MBUF
#define MG_MAX_DNS_ANSWERS
#define MG_EV_WEBSOCKET_FRAME
int mg_stat(const char *path, cs_stat_t *st)
struct mg_connection * mg_connect_http(struct mg_mgr *mgr, mg_event_handler_t event_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
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) WEAK
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 **chunk, size_t *chunk_len)
#define MG_SOCK_STRINGIFY_PORT
void mbuf_remove(struct mbuf *mb, size_t n) WEAK
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 *n, int status_code, int64_t content_length, const char *extra_headers)
void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id)
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_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) WEAK
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 *, mg_event_handler_t func, void *, size_t)
#define MG_DNS_AAAA_RECORD
void mg_send_response_line(struct mg_connection *c, 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 mbuf_free(struct mbuf *mbuf) WEAK
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
int mg_open(const char *path, int flag, int mode)
double mg_set_timer(struct mg_connection *c, double timestamp)
int mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len, int flags)
#define MG_MQTT_GET_QOS(flags)
int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req)
size_t mg_match_prefix_n(const struct mg_str, const struct mg_str) WEAK
#define MG_SEND_FUNC(s, b, l, f)
void mbuf_resize(struct mbuf *a, size_t new_size) WEAK
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) WEAK
void mg_send(struct mg_connection *nc, const void *buf, int len)
int mg_socketpair(sock_t[2], int sock_type)
#define WEBSOCKET_OP_PONG
#define MG_MQTT_CMD_PUBREL
struct mg_connection * next
void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len)
#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)
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)
#define MG_EV_MQTT_CONNECT
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 cs_base64_finish(struct cs_base64_ctx *ctx)
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_and_flags, 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)
#define MG_SOCK_STRINGIFY_IP
const char * enable_directory_listing
size_t c_strnlen(const char *s, size_t maxlen) WEAK
size_t mg_match_prefix(const char *, int, const char *) WEAK
#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_and_flags, const struct mg_str *strings, int num_strings)
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) WEAK
#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 event_handler, const char *url, const char *protocol, const char *extra_headers)
struct mg_connection * listener
struct mg_connection * prev
#define MG_MQTT_HAS_PASSWORD
void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id)
void mg_set_close_on_exec(sock_t sock)
double cs_time(void) WEAK
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 *domain_name, char *ip_addr_buf, size_t buf_len)
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)
void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len, uint16_t message_id)
#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,...) WEAK
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) WEAK
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)
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) WEAK
#define MG_F_SSL_HANDSHAKE_DONE
int 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)
void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags, const void *data, size_t data_len)
#define MG_EV_MQTT_PUBLISH
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)
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)
struct mg_str mg_mk_str(const char *s) WEAK
const char ** error_string
void cs_base64_encode(const unsigned char *src, int src_len, char *dst)
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 *uri, const char *extra_headers)
void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt,...)
#define MG_EV_MQTT_SUBSCRIBE
const char * mg_next_comma_list_entry(const char *, struct mg_str *, struct mg_str *) WEAK
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)
void mbuf_trim(struct mbuf *mbuf) WEAK
#define MG_MQTT_CMD_DISCONNECT
FILE * mg_fopen(const char *path, const char *mode)
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
int mg_vcmp(const struct mg_str *str1, const char *str2) WEAK
int mg_parse_uri(const 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]
mg_event_handler_t proto_handler
const char * dav_document_root
MG_INTERNAL 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) WEAK
int mg_dns_parse_record_data(struct mg_dns_message *msg, struct mg_dns_resource_record *rr, void *data, size_t data_len)
#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
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)
void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id)
void cs_log_set_file(FILE *file)
#define WEBSOCKET_OP_CONTINUE
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
static std::string q(const char *s)
#define message(type, str)
#define write(n, a, f, d)
static std::string remove(const std::string s, char c)
static void do_ssi_exec(struct mg_connection *conn, char *tag)
static const char * month_names[]
#define MG_COPY_COMMON_CONNECTION_OPTIONS(dst, src)
int mg_pic32_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
void mg_pic32_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
void mg_socket_if_sock_set(struct mg_connection *nc, sock_t sock)
#define MD5STEP(f, w, x, y, z, data, s)
int _kill(int pid, int sig)
void cs_md5_final(unsigned char digest[16], cs_md5_ctx *ctx)
void mg_lwip_if_connect_udp(struct mg_connection *nc)
struct mg_connection * mg_bind(struct mg_mgr *srv, const char *address, MG_CB(mg_event_handler_t event_handler, void *user_data))
int mg_pic32_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
static int mg_accept_conn(struct mg_connection *lc)
static int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
void mg_socket_if_connect_udp(struct mg_connection *nc)
void mg_sl_if_sock_set(struct mg_connection *nc, sock_t sock)
static sock_t mg_open_listening_socket(union socket_address *sa, int type, int proto)
struct mg_str mg_strdup_nul(const struct mg_str s) WEAK
void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64])
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) WEAK
MG_INTERNAL void mg_remove_conn(struct mg_connection *c)
void sl_restart_cb(struct mg_mgr *mgr)
void cs_md5_init(cs_md5_ctx *ctx)
struct mg_connection * mg_add_sock_opt(struct mg_mgr *s, sock_t sock, MG_CB(mg_event_handler_t callback, void *user_data), struct mg_add_sock_opts opts)
static int mg_sl_if_udp_recv(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
const struct mg_iface_vtable * mg_ifaces[]
double cs_timegm(const struct tm *tm)
static void mg_lwip_if_connect_tcp_tcpip(void *arg)
MG_INTERNAL struct mg_connection * mg_create_connection_base(struct mg_mgr *mgr, mg_event_handler_t callback, struct mg_add_sock_opts opts)
static int mg_socket_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
#define MG_LWIP_IFACE_VTABLE
#define R1(v, w, x, y, z, i)
static int mg_do_recv(struct mg_connection *nc)
MG_INTERNAL struct mg_connection * mg_create_connection(struct mg_mgr *mgr, mg_event_handler_t callback, struct mg_add_sock_opts opts)
void mg_lwip_if_destroy_conn(struct mg_connection *nc)
static int mg_socket_if_udp_recv(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
void mg_pic32_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
time_t mg_pic32_if_poll(struct mg_iface *iface, int timeout_ms)
static void mg_null_if_add_conn(struct mg_connection *c)
int mg_null_if_tcp_recv(struct mg_connection *c, void *buf, size_t len)
void mg_lwip_if_add_conn(struct mg_connection *nc)
static void mg_lwip_tcp_error_cb(void *arg, err_t err)
void mg_mbuf_append_base64_putc(char ch, void *user_data)
#define _MG_CALLBACK_MODIFIABLE_FLAGS_MASK
void mg_basic_auth_header(const struct mg_str user, const struct mg_str pass, struct mbuf *buf)
static unsigned char from_b64(unsigned char ch)
static void tcp_output_tcpip(void *arg)
bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init)
double mg_mgr_min_timer(const struct mg_mgr *mgr)
static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags, int field_width)
static void mg_lwip_if_connect_udp_tcpip(void *arg)
static void mg_null_if_get_conn_addr(struct mg_connection *c, int remote, union socket_address *sa)
int mg_str_starts_with(struct mg_str s, struct mg_str prefix) WEAK
#define MG_UDP_RECV_BUFFER_SIZE
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
struct mg_str mg_next_comma_list_entry_n(struct mg_str list, struct mg_str *val, struct mg_str *eq_val) WEAK
int mg_lwip_if_create_conn(struct mg_connection *nc)
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms)
void mg_pic32_if_recved(struct mg_connection *nc, size_t len)
static void mg_null_if_free(struct mg_iface *iface)
void mg_pic32_if_add_conn(struct mg_connection *nc)
void mg_lwip_handle_accept(struct mg_connection *nc)
struct mg_str mg_url_encode(const struct mg_str src)
static int mg_sl_if_create_conn(struct mg_connection *nc)
int mg_asprintf(char **buf, size_t size, const char *fmt,...) WEAK
MG_INTERNAL size_t recv_avail_size(struct mg_connection *conn, size_t max)
static void mg_sl_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
void mg_lwip_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
void _not_implemented(const char *what)
size_t mbuf_append_and_free(struct mbuf *a, void *buf, size_t len) WEAK
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t num_sent)
void mg_lwip_if_free(struct mg_iface *iface)
struct mg_str mg_url_encode_opt(const struct mg_str src, const struct mg_str safe, unsigned int flags)
int mg_strncmp(const struct mg_str, const struct mg_str, size_t n) WEAK
int mg_if_poll(struct mg_connection *nc, double now)
static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err)
static int mg_lwip_if_can_send(struct mg_connection *nc, struct mg_lwip_conn_state *cs)
void mg_socket_if_add_conn(struct mg_connection *nc)
void mg_sl_if_add_conn(struct mg_connection *nc)
void mg_sl_if_remove_conn(struct mg_connection *nc)
static void mg_handle_recv(struct mg_connection *nc)
static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err)
static int mg_lwip_if_udp_send(struct mg_connection *nc, const void *data, size_t len)
void mg_lwip_if_remove_conn(struct mg_connection *nc)
void mg_socket_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
static time_t mg_null_if_poll(struct mg_iface *iface, int timeout_ms)
void mg_mgr_init_opt(struct mg_mgr *m, void *user_data, struct mg_mgr_init_opts opts)
static void cs_md5_transform(uint32_t buf[4], uint32_t const in[16])
static void udp_sendto_tcpip(void *arg)
void mg_socket_if_init(struct mg_iface *iface)
struct mg_connection * mg_connect(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data))
static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx)
#define MG_PIC32_IFACE_VTABLE
#define _MG_ALLOWED_CONNECT_FLAGS_MASK
static int mg_recv_tcp(struct mg_connection *nc, char *buf, size_t len)
enum cs_log_level cs_log_level WEAK
void mg_pic32_if_init(struct mg_iface *iface)
static void mg_null_if_init(struct mg_iface *iface)
static void mg_null_if_destroy_conn(struct mg_connection *c)
struct mg_str mg_strdup(const struct mg_str s) WEAK
static int mg_null_if_create_conn(struct mg_connection *c)
void mg_set_non_blocking_mode(sock_t sock)
void mbuf_clear(struct mbuf *mb) WEAK
static void mg_null_if_sock_set(struct mg_connection *c, sock_t sock)
void mg_socket_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
void mg_socket_if_remove_conn(struct mg_connection *nc)
#define R2(v, w, x, y, z, i)
void mg_pic32_if_connect_udp(struct mg_connection *nc)
void mg_lwip_if_init(struct mg_iface *iface)
const struct mg_iface_vtable mg_default_iface_vtable
void mg_pic32_if_free(struct mg_iface *iface)
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p)
void mg_if_can_recv_cb(struct mg_connection *nc)
#define CS_LOG_PREFIX_LEN
static int mg_lwip_if_udp_recv(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
static int mg_socket_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
static void mg_sock_get_addr(sock_t sock, int remote, union socket_address *sa)
MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, int *proto, char *host, size_t host_len)
static int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr)
void mg_mbuf_append_base64(struct mbuf *mbuf, const void *data, size_t len)
#define _MG_F_FD_CAN_READ
static void byteReverse(unsigned char *buf, unsigned longs)
#define MG_SL_IFACE_VTABLE
static void mg_null_if_connect_udp(struct mg_connection *c)
#define R0(v, w, x, y, z, i)
static void mg_sl_if_connect_udp(struct mg_connection *nc)
MG_INTERNAL int mg_get_errno(void)
static int mg_sl_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len)
static void parse_uri_component(const char **p, const char *end, const char *seps, struct mg_str *res)
#define MG_SET_PTRPTR(_ptr, _v)
int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len)
static void tcp_close_tcpip(void *arg)
const struct mg_iface_vtable mg_simplelink_iface_vtable
static int mg_null_if_listen_tcp(struct mg_connection *c, union socket_address *sa)
int mg_assemble_uri(const struct mg_str *scheme, const struct mg_str *user_info, const struct mg_str *host, unsigned int port, const struct mg_str *path, const struct mg_str *query, const struct mg_str *fragment, int normalize_path, struct mg_str *uri)
void mg_pic32_if_destroy_conn(struct mg_connection *nc)
void mg_lwip_if_sock_set(struct mg_connection *nc, sock_t sock)
struct mg_iface * mg_if_create_iface(const struct mg_iface_vtable *vtable, struct mg_mgr *mgr)
static int mg_socket_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
struct mg_connection * mg_bind_opt(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data), struct mg_bind_opts opts)
const char * mg_strstr(const struct mg_str haystack, const struct mg_str needle) WEAK
void mg_lwip_post_signal(enum mg_sig_type sig, struct mg_connection *nc)
static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v)
const struct mg_iface_vtable mg_pic32_iface_vtable
static int mg_socket_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len)
static void mg_lwip_tcp_write_tcpip(void *arg)
char * inet_ntoa(struct in_addr n)
void mg_forward(struct mg_connection *from, struct mg_connection *to)
void cs_from_hex(char *to, const char *p, size_t len) WEAK
const struct mg_iface_vtable mg_null_iface_vtable
struct mg_str mg_strstrip(struct mg_str s) WEAK
static int mg_null_if_tcp_send(struct mg_connection *c, const void *buf, size_t len)
static int str_util_lowercase(const char *s)
static int mg_lwip_if_tcp_recv(struct mg_connection *nc, void *buf, size_t len)
static int mg_null_if_udp_send(struct mg_connection *c, const void *buf, size_t len)
static void mg_task(void *arg)
void mg_sl_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
void mg_sl_if_destroy_conn(struct mg_connection *nc)
const char * mg_strchr(const struct mg_str s, int c) WEAK
static void mg_lwip_if_listen_tcp_tcpip(void *arg)
void mbuf_move(struct mbuf *from, struct mbuf *to) WEAK
int mg_null_if_udp_recv(struct mg_connection *c, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
int mg_pic32_if_create_conn(struct mg_connection *nc)
void mg_pic32_if_get_conn_addr(struct mg_connection *nc, int remote, union socket_address *sa)
static int fourbit(int ch)
#define C_SNPRINTF_FLAG_ZERO
struct mg_str mg_mk_str_n(const char *s, size_t len) WEAK
#define BASE64_ENCODE_BODY
void mg_pic32_if_sock_set(struct mg_connection *nc, sock_t sock)
#define R3(v, w, x, y, z, i)
int mg_lwip_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
#define MG_SOCKET_IFACE_VTABLE
int mg_socket_if_listen_tcp(struct mg_connection *nc, union socket_address *sa)
void mg_sl_if_init(struct mg_iface *iface)
static void mg_null_if_remove_conn(struct mg_connection *c)
const struct mg_iface_vtable mg_socket_iface_vtable
const char * inet_ntop(int af, const void *src, char *dst, socklen_t size)
int gettimeofday(struct timeval *tp, void *tzp)
void cs_md5_update(cs_md5_ctx *ctx, const unsigned char *buf, size_t len)
struct mg_iface * mg_find_iface(struct mg_mgr *mgr, const struct mg_iface_vtable *vtable, struct mg_iface *from)
static void mg_handle_send(struct mg_connection *nc)
void cs_log_set_file_level(const char *file_level)
#define SET_ADDR(dst, src)
static void udp_remove_tcpip(void *arg)
static void mg_lwip_if_listen_udp_tcpip(void *arg)
void mg_sl_if_free(struct mg_iface *iface)
MG_INTERNAL void mg_add_conn(struct mg_mgr *mgr, struct mg_connection *c)
int inet_pton(int af, const char *src, void *dst)
int mg_lwip_if_listen_udp(struct mg_connection *nc, union socket_address *sa)
#define _MG_F_FD_CAN_WRITE
static int mg_sl_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
MG_INTERNAL struct mg_connection * mg_do_connect(struct mg_connection *nc, int proto, union socket_address *sa)
void mg_socket_if_free(struct mg_iface *iface)
void mg_if_can_send_cb(struct mg_connection *nc)
static int mg_sl_if_udp_send(struct mg_connection *nc, const void *buf, size_t len)
static void mg_null_if_connect_tcp(struct mg_connection *c, const union socket_address *sa)
void mg_pic32_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
static struct mg_str mg_strdup_common(const struct mg_str s, int nul_terminate)
void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr)
void mg_strfree(struct mg_str *s) WEAK
static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
void mg_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd)
const struct mg_iface_vtable mg_lwip_iface_vtable
void fprint_str(FILE *fp, const char *str)
struct mg_connection * mg_connect_opt(struct mg_mgr *mgr, const char *address, MG_CB(mg_event_handler_t callback, void *user_data), struct mg_connect_opts opts)
int mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len)
void mg_destroy_conn(struct mg_connection *conn, int destroy_if)
void mg_lwip_if_connect_tcp(struct mg_connection *nc, const union socket_address *sa)
time_t mg_sl_if_poll(struct mg_iface *iface, int timeout_ms)
int mg_socket_if_create_conn(struct mg_connection *nc)
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line)
static int mg_is_error(void)
static uint32_t blk0(union char64long16 *block, int i)
MG_INTERNAL void mg_call(struct mg_connection *nc, mg_event_handler_t ev_handler, void *user_data, int ev, void *ev_data)
static int mg_recv_udp(struct mg_connection *nc, char *buf, size_t len)
#define C_SNPRINTF_APPEND_CHAR(ch)
void mg_socket_if_destroy_conn(struct mg_connection *nc)
void mg_run_in_task(void(*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg)
static int mg_null_if_listen_udp(struct mg_connection *c, union socket_address *sa)
void mg_pic32_if_remove_conn(struct mg_connection *nc)
#define R4(v, w, x, y, z, i)
#define MG_NULL_IFACE_VTABLE
void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now)
time_t mg_socket_if_poll(struct mg_iface *iface, int timeout_ms)
struct mg_connection * mg_add_sock(struct mg_mgr *s, sock_t sock, MG_CB(mg_event_handler_t callback, void *user_data))
MG_INTERNAL void mg_timer(struct mg_connection *c, double now)
void tcp_recved_tcpip(void *arg)
void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver)
#define MBUF_SIZE_MAX_HEADROOM
#define MG_AUTH_FLAG_IS_GLOBAL_PASS_FILE
#define DO_NOT_WARN_UNUSED
void mg_http_send_error(struct mg_connection *nc, int code, const char *reason)
int mg_get_http_basic_auth(struct http_message *hm, char *user, size_t user_len, char *pass, size_t pass_len)
int mg_parse_http_basic_auth(struct mg_str *hdr, char *user, size_t user_len, char *pass, size_t pass_len)
#define MG_AUTH_FLAG_IS_DIRECTORY
void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[], const size_t *msg_lens, uint8_t *digest)
void mg_send_websocket_handshake3v(struct mg_connection *nc, const struct mg_str path, const struct mg_str host, const struct mg_str protocol, const struct mg_str extra_headers, const struct mg_str user, const struct mg_str pass)
#define MG_ENABLE_HTTP_WEBDAV
#define MG_MK_STR_N(str_literal, len)
#define LIST_REMOVE(elm, field)
#define MG_EV_SSI_CALL_CTX
void mg_http_send_digest_auth_request(struct mg_connection *c, const char *domain)
#define PRINTF_LIKE(f, a)
#define MG_AUTH_FLAG_ALLOW_MISSING_FILE
#define MG_F_RECV_AND_CLOSE
void mg_http_send_redirect(struct mg_connection *nc, int status_code, const struct mg_str location, const struct mg_str extra_headers)
int mg_check_digest_auth(struct mg_str method, struct mg_str uri, struct mg_str username, struct mg_str cnonce, struct mg_str response, struct mg_str qop, struct mg_str nc, struct mg_str nonce, struct mg_str auth_domain, FILE *fp)
int mg_mqtt_match_topic_expression(struct mg_str exp, struct mg_str topic)
int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain, FILE *fp)
int mg_http_parse_header2(struct mg_str *hdr, const char *var_name, char **buf, size_t buf_size)
void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[], const size_t *msg_lens, uint8_t *digest)
int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len)
#define MG_ENABLE_HTTP_STREAMING_MULTIPART
int mg_mqtt_vmatch_topic_expression(const char *exp, struct mg_str topic)
#define LIST_NEXT(elm, field)
void mg_send_websocket_handshake3(struct mg_connection *nc, const char *path, const char *host, const char *protocol, const char *extra_headers, const char *user, const char *pass)
#define LIST_INSERT_HEAD(head, elm, field)
int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg)
#define MG_F_ENABLE_BROADCAST
int mg_http_is_authorized(struct http_message *hm, struct mg_str path, const char *domain, const char *passwords_file, int flags)
void mg_register_http_endpoint_opt(struct mg_connection *nc, const char *uri_path, mg_event_handler_t handler, struct mg_http_endpoint_opts opts)
#define MG_CTL_MSG_MESSAGE_SIZE
struct mg_str mg_url_encode_opt(const struct mg_str src, const struct mg_str safe, unsigned int flags)
const char * mg_strchr(const struct mg_str s, int c)
struct mg_str mg_mk_str_n(const char *s, size_t len)
#define MG_URL_ENCODE_F_UPPERCASE_HEX
#define MG_URL_ENCODE_F_SPACE_AS_PLUS
static size_t mg_http_parse_chunk(char *buf, size_t len, char **chunk_data, size_t *chunk_len)
mg_http_multipart_stream_state
@ MPS_WAITING_FOR_BOUNDARY
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)
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 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 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)
static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data)
static const struct @23 mg_static_builtin_mime_types[]
#define MIME_ENTRY(_ext, _type)
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_http_construct_etag(char *buf, size_t buf_len, const cs_stat_t *st)
static void mg_http_conn_destructor(void *proto_data)
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 mg_event_handler_t mg_http_get_endpoint_handler(struct mg_connection *nc, struct mg_str *uri_path)
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_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_print_dir_entry(struct mg_connection *nc, const char *file_name, cs_stat_t *stp)
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 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 void mg_escape(const char *src, char *dst, size_t dst_len)
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 mg_get_month_index(const char *s)
static uint32_t mg_ws_random_mask(void)
static void mg_http_free_proto_data_file(struct mg_http_proto_data_file *d)
static int mg_get_ip_address_of_nameserver(char *name, size_t name_len)
static int mg_is_dav_request(const struct mg_str *s)
static unsigned char * mg_parse_dns_resource_record(unsigned char *data, unsigned char *end, struct mg_dns_resource_record *rr, int reply)
static void mg_mgr_handle_ctl_sock(struct mg_mgr *mgr)
static char * mg_addenv(struct mg_cgi_env_block *block, const char *fmt,...)
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)
static void mg_handle_incoming_websocket_frame(struct mg_connection *nc, struct websocket_message *wsm)
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)
static void mg_addenv2(struct mg_cgi_env_block *blk, const char *name)
static void mg_send_ws_header(struct mg_connection *nc, int op, size_t len, struct ws_mask_ctx *ctx)
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)
static pid_t mg_start_process(const char *interp, const char *cmd, const char *env, const char *envp[], const char *dir, sock_t sock)
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)
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)
static size_t mg_get_line_len(const char *buf, size_t buf_len)
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)
void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data)
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)
static void mg_handle_move(struct mg_connection *c, const struct mg_serve_http_opts *opts, const char *path, struct http_message *hm)
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)
static void mg_gmt_time_string(char *buf, size_t buf_len, time_t *t)
static void mg_http_send_options(struct mg_connection *nc)
#define MG_DEFAULT_NAMESERVER
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)
static int mg_num_leap_years(int year)
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
const char * vars[MG_MAX_CGI_ENVIR_VARS]
struct mg_connection * nc
char buf[MG_CGI_ENVIRONMENT_SIZE]
struct mg_ev_mgr_lwip_signal sig_queue[MG_SIG_QUEUE_LEN]
struct mg_connection * nc
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
time_t(* poll)(struct mg_iface *iface, int timeout_ms)
void(* destroy_conn)(struct mg_connection *nc)
int(* listen_tcp)(struct mg_connection *nc, union socket_address *sa)
void(* remove_conn)(struct mg_connection *nc)
void(* connect_tcp)(struct mg_connection *nc, const union socket_address *sa)
void(* free)(struct mg_iface *iface)
void(* init)(struct mg_iface *iface)
void(* get_conn_addr)(struct mg_connection *nc, int remote, union socket_address *sa)
void(* connect_udp)(struct mg_connection *nc)
int(* udp_send)(struct mg_connection *nc, const void *buf, size_t len)
int(* create_conn)(struct mg_connection *nc)
int(* listen_udp)(struct mg_connection *nc, union socket_address *sa)
void(* sock_set)(struct mg_connection *nc, sock_t sock)
int(* udp_recv)(struct mg_connection *nc, void *buf, size_t len, union socket_address *sa, size_t *sa_len)
int(* tcp_send)(struct mg_connection *nc, const void *buf, size_t len)
int(* tcp_recv)(struct mg_connection *nc, void *buf, size_t len)
void(* add_conn)(struct mg_connection *nc)
const struct mg_iface_vtable * vtable
struct mg_connection * lc
union mg_lwip_conn_state::@24 pcb
struct mg_connection * nc
const union socket_address * sa
struct mg_connection * nc
struct mg_connection * nc
union socket_address * sa
struct mg_connection * nc
const struct mg_iface_vtable ** ifaces
const struct mg_iface_vtable * main_iface
struct mg_iface ** ifaces
uint16_t keep_alive_timer
struct mg_str will_message
struct mg_str protocol_name
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)